diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index 9ca0eeaebf..9eb9648478 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -20,7 +20,6 @@ Batch::Batch() : _commands(), _commandOffsets(), _params(), - _resources(), _data(), _buffers(), _textures(), @@ -37,7 +36,6 @@ void Batch::clear() { _commands.clear(); _commandOffsets.clear(); _params.clear(); - _resources.clear(); _data.clear(); _buffers.clear(); _textures.clear(); @@ -46,20 +44,6 @@ void Batch::clear() { _pipelines.clear(); } -uint32 Batch::cacheResource(Resource* res) { - uint32 offset = _resources.size(); - _resources.push_back(ResourceCache(res)); - - return offset; -} - -uint32 Batch::cacheResource(const void* pointer) { - uint32 offset = _resources.size(); - _resources.push_back(ResourceCache(pointer)); - - return offset; -} - uint32 Batch::cacheData(uint32 size, const void* data) { uint32 offset = _data.size(); uint32 nbBytes = size; @@ -167,6 +151,16 @@ void Batch::setPipeline(const PipelinePointer& pipeline) { _params.push_back(_pipelines.cache(pipeline)); } +void Batch::setStateBlendFactor(const Vec4& factor) { + ADD_COMMAND(setStateBlendFactor); + + _params.push_back(factor.x); + _params.push_back(factor.y); + _params.push_back(factor.z); + _params.push_back(factor.w); +} + + void Batch::setUniformBuffer(uint32 slot, const BufferPointer& buffer, Offset offset, Offset size) { ADD_COMMAND(setUniformBuffer); diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index 3468e75738..6e8a2d1da6 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -104,6 +104,8 @@ public: // Pipeline Stage void setPipeline(const PipelinePointer& pipeline); + void setStateBlendFactor(const Vec4& factor); + void setUniformBuffer(uint32 slot, const BufferPointer& buffer, Offset offset, Offset size); void setUniformBuffer(uint32 slot, const BufferView& view); // not a command, just a shortcut from a BufferView @@ -128,7 +130,7 @@ public: void _glDepthFunc(GLenum func); void _glDepthMask(GLboolean flag); - void _glDepthRange(GLclampd zNear, GLclampd zFar); + void _glDepthRange(GLfloat zNear, GLfloat zFar); void _glBindBuffer(GLenum target, GLuint buffer); @@ -143,15 +145,6 @@ public: void _glUniform4fv(GLint location, GLsizei count, const GLfloat* value); void _glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); - void _glDrawArrays(GLenum mode, GLint first, GLsizei count); - void _glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices); - - void _glColorPointer(GLint size, GLenum type, GLsizei stride, const void *pointer); - void _glNormalPointer(GLenum type, GLsizei stride, const void *pointer); - void _glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const void *pointer); - void _glVertexPointer(GLint size, GLenum type, GLsizei stride, const void *pointer); - - void _glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); void _glEnableVertexAttribArray(GLint location); void _glDisableVertexAttribArray(GLint location); @@ -172,6 +165,8 @@ public: COMMAND_setProjectionTransform, COMMAND_setPipeline, + COMMAND_setStateBlendFactor, + COMMAND_setUniformBuffer, COMMAND_setUniformTexture, @@ -204,15 +199,6 @@ public: COMMAND_glUniform4fv, COMMAND_glUniformMatrix4fv, - COMMAND_glDrawArrays, - COMMAND_glDrawRangeElements, - - COMMAND_glColorPointer, - COMMAND_glNormalPointer, - COMMAND_glTexCoordPointer, - COMMAND_glVertexPointer, - - COMMAND_glVertexAttribPointer, COMMAND_glEnableVertexAttribArray, COMMAND_glDisableVertexAttribArray, @@ -233,28 +219,18 @@ public: uint32 _uint; float _float; char _chars[4]; - double _double; }; Param(int32 val) : _int(val) {} Param(uint32 val) : _uint(val) {} Param(float val) : _float(val) {} - Param(double val) : _double(val) {} }; typedef std::vector Params; const Params& getParams() const { return _params; } - class ResourceCache { - public: - union { - Resource* _resource; - const void* _pointer; - }; - ResourceCache(Resource* res) : _resource(res) {} - ResourceCache(const void* pointer) : _pointer(pointer) {} - }; - typedef std::vector Resources; - + // The template cache mechanism for the gpu::Object passed to the gpu::Batch + // this allow us to have one cache container for each different types and eventually + // be smarter how we manage them template class Cache { public: @@ -291,26 +267,10 @@ public: typedef Cache::Vector TransformCaches; typedef Cache::Vector PipelineCaches; + // Cache Data in a byte array if too big to fit in Param + // FOr example Mat4s are going there typedef unsigned char Byte; typedef std::vector Bytes; - - uint32 cacheResource(Resource* res); - uint32 cacheResource(const void* pointer); - ResourceCache* editResource(uint32 offset) { - if (offset >= _resources.size()) { - return 0; - } - return (_resources.data() + offset); - } - - template - T* editResourcePointer(uint32 offset) { - if (offset >= _resources.size()) { - return 0; - } - return reinterpret_cast((_resources.data() + offset)->_pointer); - } - uint32 cacheData(uint32 size, const void* data); Byte* editData(uint32 offset) { if (offset >= _data.size()) { @@ -322,7 +282,6 @@ public: Commands _commands; CommandOffsets _commandOffsets; Params _params; - Resources _resources; Bytes _data; BufferCaches _buffers; diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 533261d2a6..0bf13636f1 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -26,6 +26,8 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_setProjectionTransform), (&::gpu::GLBackend::do_setPipeline), + (&::gpu::GLBackend::do_setStateBlendFactor), + (&::gpu::GLBackend::do_setUniformBuffer), (&::gpu::GLBackend::do_setUniformTexture), @@ -55,15 +57,6 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_glUniform4fv), (&::gpu::GLBackend::do_glUniformMatrix4fv), - (&::gpu::GLBackend::do_glDrawArrays), - (&::gpu::GLBackend::do_glDrawRangeElements), - - (&::gpu::GLBackend::do_glColorPointer), - (&::gpu::GLBackend::do_glNormalPointer), - (&::gpu::GLBackend::do_glTexCoordPointer), - (&::gpu::GLBackend::do_glVertexPointer), - - (&::gpu::GLBackend::do_glVertexAttribPointer), (&::gpu::GLBackend::do_glEnableVertexAttribArray), (&::gpu::GLBackend::do_glDisableVertexAttribArray), @@ -280,7 +273,7 @@ void GLBackend::do_glDepthMask(Batch& batch, uint32 paramOffset) { CHECK_GL_ERROR(); } -void Batch::_glDepthRange(GLclampd zNear, GLclampd zFar) { +void Batch::_glDepthRange(GLfloat zNear, GLfloat zFar) { ADD_COMMAND_GL(glDepthRange); _params.push_back(zFar); @@ -290,8 +283,8 @@ void Batch::_glDepthRange(GLclampd zNear, GLclampd zFar) { } void GLBackend::do_glDepthRange(Batch& batch, uint32 paramOffset) { glDepthRange( - batch._params[paramOffset + 1]._double, - batch._params[paramOffset + 0]._double); + batch._params[paramOffset + 1]._float, + batch._params[paramOffset + 0]._float); CHECK_GL_ERROR(); } @@ -443,144 +436,6 @@ void GLBackend::do_glUniformMatrix4fv(Batch& batch, uint32 paramOffset) { CHECK_GL_ERROR(); } -void Batch::_glDrawArrays(GLenum mode, GLint first, GLsizei count) { - ADD_COMMAND_GL(glDrawArrays); - - _params.push_back(count); - _params.push_back(first); - _params.push_back(mode); - - DO_IT_NOW(_glDrawArrays, 3); -} -void GLBackend::do_glDrawArrays(Batch& batch, uint32 paramOffset) { - glDrawArrays( - batch._params[paramOffset + 2]._uint, - batch._params[paramOffset + 1]._int, - batch._params[paramOffset + 0]._int); - CHECK_GL_ERROR(); -} - -void Batch::_glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices) { - ADD_COMMAND_GL(glDrawRangeElements); - - _params.push_back(cacheResource(indices)); - _params.push_back(type); - _params.push_back(count); - _params.push_back(end); - _params.push_back(start); - _params.push_back(mode); - - DO_IT_NOW(_glDrawRangeElements, 6); -} -void GLBackend::do_glDrawRangeElements(Batch& batch, uint32 paramOffset) { - glDrawRangeElements( - batch._params[paramOffset + 5]._uint, - batch._params[paramOffset + 4]._uint, - batch._params[paramOffset + 3]._uint, - batch._params[paramOffset + 2]._int, - batch._params[paramOffset + 1]._uint, - batch.editResource(batch._params[paramOffset + 0]._uint)->_pointer); - CHECK_GL_ERROR(); -} - -void Batch::_glColorPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) { - ADD_COMMAND_GL(glColorPointer); - - _params.push_back(cacheResource(pointer)); - _params.push_back(stride); - _params.push_back(type); - _params.push_back(size); - - DO_IT_NOW(_glColorPointer, 4); -} -void GLBackend::do_glColorPointer(Batch& batch, uint32 paramOffset) { - glColorPointer( - batch._params[paramOffset + 3]._int, - batch._params[paramOffset + 2]._uint, - batch._params[paramOffset + 1]._int, - batch.editResource(batch._params[paramOffset + 0]._uint)->_pointer); - CHECK_GL_ERROR(); -} - -void Batch::_glNormalPointer(GLenum type, GLsizei stride, const void *pointer) { - ADD_COMMAND_GL(glNormalPointer); - - _params.push_back(cacheResource(pointer)); - _params.push_back(stride); - _params.push_back(type); - - DO_IT_NOW(_glNormalPointer, 3); -} -void GLBackend::do_glNormalPointer(Batch& batch, uint32 paramOffset) { - glNormalPointer( - batch._params[paramOffset + 2]._uint, - batch._params[paramOffset + 1]._int, - batch.editResource(batch._params[paramOffset + 0]._uint)->_pointer); - CHECK_GL_ERROR(); -} - -void Batch::_glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) { - ADD_COMMAND_GL(glTexCoordPointer); - - _params.push_back(cacheResource(pointer)); - _params.push_back(stride); - _params.push_back(type); - _params.push_back(size); - - DO_IT_NOW(_glTexCoordPointer, 4); -} -void GLBackend::do_glTexCoordPointer(Batch& batch, uint32 paramOffset) { - glTexCoordPointer( - batch._params[paramOffset + 3]._int, - batch._params[paramOffset + 2]._uint, - batch._params[paramOffset + 1]._int, - batch.editResource(batch._params[paramOffset + 0]._uint)->_pointer); - CHECK_GL_ERROR(); -} - -void Batch::_glVertexPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) { - ADD_COMMAND_GL(glVertexPointer); - - _params.push_back(cacheResource(pointer)); - _params.push_back(stride); - _params.push_back(type); - _params.push_back(size); - - DO_IT_NOW(_glVertexPointer, 4); -} -void GLBackend::do_glVertexPointer(Batch& batch, uint32 paramOffset) { - glVertexPointer( - batch._params[paramOffset + 3]._int, - batch._params[paramOffset + 2]._uint, - batch._params[paramOffset + 1]._int, - batch.editResource(batch._params[paramOffset + 0]._uint)->_pointer); - CHECK_GL_ERROR(); -} - - -void Batch::_glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer) { - ADD_COMMAND_GL(glVertexAttribPointer); - - _params.push_back(cacheResource(pointer)); - _params.push_back(stride); - _params.push_back(normalized); - _params.push_back(type); - _params.push_back(size); - _params.push_back(index); - - DO_IT_NOW(_glVertexAttribPointer, 6); -} -void GLBackend::do_glVertexAttribPointer(Batch& batch, uint32 paramOffset) { - glVertexAttribPointer( - batch._params[paramOffset + 5]._uint, - batch._params[paramOffset + 4]._int, - batch._params[paramOffset + 3]._uint, - batch._params[paramOffset + 2]._uint, - batch._params[paramOffset + 1]._int, - batch.editResource(batch._params[paramOffset + 0]._uint)->_pointer); - CHECK_GL_ERROR(); -} - void Batch::_glEnableVertexAttribArray(GLint location) { ADD_COMMAND_GL(glEnableVertexAttribArray); diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 0ef407df8a..3ca65d45eb 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -118,10 +118,15 @@ public: Commands _commands; Stamp _stamp; + State::Signature _signature; GLState(); ~GLState(); + // The state commands to reset to default, + // WARNING depending on the order of the State::Field enum + static const Commands _resetStateCommands; + friend class GLBackend; }; static GLState* syncGPUObject(const State& state); @@ -145,20 +150,23 @@ public: // The State setters called by the GLState::Commands when a new state is assigned void do_setStateFillMode(int32 mode); void do_setStateCullMode(int32 mode); - void do_setStateFrontClockwise(int32 isFrontClockwise); - void do_setStateDepthClipEnable(int32 enable); - void do_setStateScissorEnable(int32 enable); - void do_setStateMultisampleEnable(int32 enable); - void do_setStateAntialiasedLineEnable(int32 enable); + void do_setStateFrontFaceClockwise(bool isClockwise); + void do_setStateDepthClipEnable(bool enable); + void do_setStateScissorEnable(bool enable); + void do_setStateMultisampleEnable(bool enable); + void do_setStateAntialiasedLineEnable(bool enable); + void do_setStateDepthBias(Vec2 bias); void do_setStateDepthTest(State::DepthTest test); void do_setStateStencil(State::StencilActivation activation, State::StencilTest frontTest, State::StencilTest backTest); - void do_setStateAlphaToCoverageEnable(int32 enable); + void do_setStateAlphaToCoverageEnable(bool enable); + void do_setStateSampleMask(uint32 mask); - void do_setStateBlend(State::BlendFunction blendFunction, Vec4 blendFactor); - void do_setStateColorWriteMask(int32 mask); + void do_setStateBlend(State::BlendFunction blendFunction); + + void do_setStateColorWriteMask(uint32 mask); protected: @@ -242,25 +250,34 @@ protected: // Pipeline Stage void do_setPipeline(Batch& batch, uint32 paramOffset); + + void do_setStateBlendFactor(Batch& batch, uint32 paramOffset); + void do_setUniformBuffer(Batch& batch, uint32 paramOffset); void do_setUniformTexture(Batch& batch, uint32 paramOffset); void updatePipeline(); + void resetPipelineState(State::Signature toBeReset); struct PipelineStageState { PipelinePointer _pipeline; + GLuint _program; bool _invalidProgram; - State _state; - GLState::Commands _stateCommands; + State::Cache _stateCache; + State::Signature _stateSignatureCache; + + GLState* _state; bool _invalidState; PipelineStageState() : _pipeline(), _program(0), _invalidProgram(false), - _state(), + _stateSignatureCache(0), + _stateCache(State::DEFAULT), + _state(nullptr), _invalidState(false) {} } _pipeline; @@ -294,15 +311,6 @@ protected: void do_glUniform4fv(Batch& batch, uint32 paramOffset); void do_glUniformMatrix4fv(Batch& batch, uint32 paramOffset); - void do_glDrawArrays(Batch& batch, uint32 paramOffset); - void do_glDrawRangeElements(Batch& batch, uint32 paramOffset); - - void do_glColorPointer(Batch& batch, uint32 paramOffset); - void do_glNormalPointer(Batch& batch, uint32 paramOffset); - void do_glTexCoordPointer(Batch& batch, uint32 paramOffset); - void do_glVertexPointer(Batch& batch, uint32 paramOffset); - - void do_glVertexAttribPointer(Batch& batch, uint32 paramOffset); void do_glEnableVertexAttribArray(Batch& batch, uint32 paramOffset); void do_glDisableVertexAttribArray(Batch& batch, uint32 paramOffset); diff --git a/libraries/gpu/src/gpu/GLBackendPipeline.cpp b/libraries/gpu/src/gpu/GLBackendPipeline.cpp index 5079cd1ff9..d0ef01c4a4 100755 --- a/libraries/gpu/src/gpu/GLBackendPipeline.cpp +++ b/libraries/gpu/src/gpu/GLBackendPipeline.cpp @@ -60,27 +60,41 @@ GLBackend::GLPipeline* GLBackend::syncGPUObject(const Pipeline& pipeline) { void GLBackend::do_setPipeline(Batch& batch, uint32 paramOffset) { PipelinePointer pipeline = batch._pipelines.get(batch._params[paramOffset + 0]._uint); - if (pipeline == _pipeline._pipeline) { + if (_pipeline._pipeline == pipeline) { return; } - auto pipelineObject = syncGPUObject((*pipeline)); - if (!pipelineObject) { - return; - } - - _pipeline._pipeline = pipeline; + // null pipeline == reset + if (!pipeline) { + _pipeline._pipeline.reset(); - - if (_pipeline._program != pipelineObject->_program->_program) { - _pipeline._program = pipelineObject->_program->_program; + _pipeline._program = 0; _pipeline._invalidProgram = true; + + _pipeline._state = nullptr; + _pipeline._invalidState = true; + } else { + auto pipelineObject = syncGPUObject((*pipeline)); + if (!pipelineObject) { + return; + } + + // check the program cache + if (_pipeline._program != pipelineObject->_program->_program) { + _pipeline._program = pipelineObject->_program->_program; + _pipeline._invalidProgram = true; + } + + // Now for the state + if (_pipeline._state != pipelineObject->_state) { + _pipeline._state = pipelineObject->_state; + _pipeline._invalidState = true; + } + + // Remember the new pipeline + _pipeline._pipeline = pipeline; } - _pipeline._stateCommands = pipelineObject->_state->_commands; - _pipeline._invalidState = true; - - // THis should be done on Pipeline::update... if (_pipeline._invalidProgram) { glUseProgram(_pipeline._program); @@ -89,6 +103,35 @@ void GLBackend::do_setPipeline(Batch& batch, uint32 paramOffset) { } } +void GLBackend::updatePipeline() { + if (_pipeline._invalidProgram) { + // doing it here is aproblem for calls to glUniform.... so will do it on assing... + glUseProgram(_pipeline._program); + CHECK_GL_ERROR(); + _pipeline._invalidProgram = false; + } + + if (_pipeline._invalidState) { + if (_pipeline._state) { + // first reset to default what should be + // the fields which were not to default and are default now + resetPipelineState(_pipeline._state->_signature); + + // Update the signature cache with what's going to be touched + _pipeline._stateSignatureCache |= _pipeline._state->_signature; + + // And perform + for (auto command: _pipeline._state->_commands) { + command->run(this); + } + } else { + // No state ? anyway just reset everything + resetPipelineState(0); + } + _pipeline._invalidState = false; + } +} + void GLBackend::do_setUniformBuffer(Batch& batch, uint32 paramOffset) { GLuint slot = batch._params[paramOffset + 3]._uint; BufferPointer uniformBuffer = batch._buffers.get(batch._params[paramOffset + 2]._uint); @@ -120,21 +163,3 @@ void GLBackend::do_setUniformTexture(Batch& batch, uint32 paramOffset) { CHECK_GL_ERROR(); } - -void GLBackend::updatePipeline() { - if (_pipeline._invalidProgram) { - // doing it here is aproblem for calls to glUniform.... so will do it on assing... - glUseProgram(_pipeline._program); - CHECK_GL_ERROR(); - _pipeline._invalidProgram = false; - } - - if (_pipeline._invalidState) { - for (auto command: _pipeline._stateCommands) { - command->run(this); - } - CHECK_GL_ERROR(); - _pipeline._invalidState = false; - } -} - diff --git a/libraries/gpu/src/gpu/GLBackendState.cpp b/libraries/gpu/src/gpu/GLBackendState.cpp index 4485b18e6d..2397af7cec 100644 --- a/libraries/gpu/src/gpu/GLBackendState.cpp +++ b/libraries/gpu/src/gpu/GLBackendState.cpp @@ -23,11 +23,44 @@ GLBackend::GLState::~GLState() { typedef GLBackend::GLState::Command Command; typedef GLBackend::GLState::CommandPointer CommandPointer; +typedef GLBackend::GLState::Command1 Command1U; typedef GLBackend::GLState::Command1 Command1I; +typedef GLBackend::GLState::Command1 Command1B; +typedef GLBackend::GLState::Command1 CommandDepthBias; typedef GLBackend::GLState::Command1 CommandDepthTest; typedef GLBackend::GLState::Command3 CommandStencil; -typedef GLBackend::GLState::Command2 CommandBlend; +typedef GLBackend::GLState::Command1 CommandBlend; +// The state commands to reset to default, +// WARNING depending on the order of the State::Field enum +const GLBackend::GLState::Commands GLBackend::GLState::_resetStateCommands = { + CommandPointer(new Command1I(&GLBackend::do_setStateFillMode, State::DEFAULT.fillMode)), + CommandPointer(new Command1I(&GLBackend::do_setStateCullMode, State::DEFAULT.cullMode)), + CommandPointer(new Command1B(&GLBackend::do_setStateFrontFaceClockwise, State::DEFAULT.frontFaceClockwise)), + CommandPointer(new Command1B(&GLBackend::do_setStateDepthClipEnable, State::DEFAULT.depthClipEnable)), + CommandPointer(new Command1B(&GLBackend::do_setStateScissorEnable, State::DEFAULT.scissorEnable)), + CommandPointer(new Command1B(&GLBackend::do_setStateMultisampleEnable, State::DEFAULT.multisampleEnable)), + CommandPointer(new Command1B(&GLBackend::do_setStateAntialiasedLineEnable, State::DEFAULT.antialisedLineEnable)), + + // Depth bias has 2 fields in State but really one call in GLBackend + CommandPointer(new CommandDepthBias(&GLBackend::do_setStateDepthBias, Vec2(State::DEFAULT.depthBias, State::DEFAULT.depthBiasSlopeScale))), + CommandPointer(new CommandDepthBias(&GLBackend::do_setStateDepthBias, Vec2(State::DEFAULT.depthBias, State::DEFAULT.depthBiasSlopeScale))), + + CommandPointer(new CommandDepthTest(&GLBackend::do_setStateDepthTest, State::DEFAULT.depthTest)), + + // Depth bias has 3 fields in State but really one call in GLBackend + CommandPointer(new CommandStencil(&GLBackend::do_setStateStencil, State::DEFAULT.stencilActivation, State::DEFAULT.stencilTestFront, State::DEFAULT.stencilTestBack)), + CommandPointer(new CommandStencil(&GLBackend::do_setStateStencil, State::DEFAULT.stencilActivation, State::DEFAULT.stencilTestFront, State::DEFAULT.stencilTestBack)), + CommandPointer(new CommandStencil(&GLBackend::do_setStateStencil, State::DEFAULT.stencilActivation, State::DEFAULT.stencilTestFront, State::DEFAULT.stencilTestBack)), + + CommandPointer(new Command1B(&GLBackend::do_setStateAlphaToCoverageEnable, State::DEFAULT.alphaToCoverageEnable)), + + CommandPointer(new Command1U(&GLBackend::do_setStateSampleMask, State::DEFAULT.sampleMask)), + + CommandPointer(new CommandBlend(&GLBackend::do_setStateBlend, State::DEFAULT.blendFunction)), + + CommandPointer(new Command1U(&GLBackend::do_setStateColorWriteMask, State::DEFAULT.colorWriteMask)) +}; void generateFillMode(GLBackend::GLState::Commands& commands, State::FillMode fillMode) { commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateFillMode, int32(fillMode)))); @@ -37,39 +70,28 @@ void generateCullMode(GLBackend::GLState::Commands& commands, State::CullMode cu commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateCullMode, int32(cullMode)))); } -void generateDepthBias(GLBackend::GLState::Commands& commands, const State& state) { - /* if ((state.getDepthBias() == 0) && (state.getDepthBiasSlopeScale() == 0.0f)) { - commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDisable, GLenum(GL_POLYGON_OFFSET_FILL)))); - commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDisable, GLenum(GL_POLYGON_OFFSET_LINE)))); - commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDisable, GLenum(GL_POLYGON_OFFSET_POINT)))); - } else { - commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glEnable, GLenum(GL_POLYGON_OFFSET_FILL)))); - commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glEnable, GLenum(GL_POLYGON_OFFSET_LINE)))); - commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glEnable, GLenum(GL_POLYGON_OFFSET_POINT)))); - commands.push_back(CommandPointer(new Command2F((Command2F::GLFunction)glPolygonOffset, - state.getDepthBiasSlopeScale(), - state.getDepthBias()))); - }*/ -} - -void generateFrontClockwise(GLBackend::GLState::Commands& commands, bool frontClockwise) { - commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateFrontClockwise, int32(frontClockwise)))); +void generateFrontFaceClockwise(GLBackend::GLState::Commands& commands, bool isClockwise) { + commands.push_back(CommandPointer(new Command1B(&GLBackend::do_setStateFrontFaceClockwise, isClockwise))); } void generateDepthClipEnable(GLBackend::GLState::Commands& commands, bool enable) { - commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateDepthClipEnable, int32(enable)))); + commands.push_back(CommandPointer(new Command1B(&GLBackend::do_setStateDepthClipEnable, enable))); } void generateScissorEnable(GLBackend::GLState::Commands& commands, bool enable) { - commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateScissorEnable, int32(enable)))); + commands.push_back(CommandPointer(new Command1B(&GLBackend::do_setStateScissorEnable, enable))); } void generateMultisampleEnable(GLBackend::GLState::Commands& commands, bool enable) { - commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateMultisampleEnable, int32(enable)))); + commands.push_back(CommandPointer(new Command1B(&GLBackend::do_setStateMultisampleEnable, enable))); } void generateAntialiasedLineEnable(GLBackend::GLState::Commands& commands, bool enable) { - commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateAntialiasedLineEnable, int32(enable)))); + commands.push_back(CommandPointer(new Command1B(&GLBackend::do_setStateAntialiasedLineEnable, enable))); +} + +void generateDepthBias(GLBackend::GLState::Commands& commands, const State& state) { + commands.push_back(CommandPointer(new CommandDepthBias(&GLBackend::do_setStateDepthBias, Vec2(state.getDepthBias(), state.getDepthBiasSlopeScale())))); } void generateDepthTest(GLBackend::GLState::Commands& commands, State::DepthTest& test) { @@ -81,15 +103,19 @@ void generateStencil(GLBackend::GLState::Commands& commands, const State& state) } void generateAlphaToCoverageEnable(GLBackend::GLState::Commands& commands, bool enable) { - commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateAlphaToCoverageEnable, int32(enable)))); + commands.push_back(CommandPointer(new Command1B(&GLBackend::do_setStateAlphaToCoverageEnable, enable))); +} + +void generateSampleMask(GLBackend::GLState::Commands& commands, uint32 mask) { + commands.push_back(CommandPointer(new Command1U(&GLBackend::do_setStateSampleMask, mask))); } void generateBlend(GLBackend::GLState::Commands& commands, const State& state) { - commands.push_back(CommandPointer(new CommandBlend(&GLBackend::do_setStateBlend, state.getBlendFunction(), state.getBlendFactor()))); + commands.push_back(CommandPointer(new CommandBlend(&GLBackend::do_setStateBlend, state.getBlendFunction()))); } -void generateColorWriteMask(GLBackend::GLState::Commands& commands, int32 mask) { - commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateColorWriteMask, int32(mask)))); +void generateColorWriteMask(GLBackend::GLState::Commands& commands, uint32 mask) { + commands.push_back(CommandPointer(new Command1U(&GLBackend::do_setStateColorWriteMask, mask))); } GLBackend::GLState* GLBackend::syncGPUObject(const State& state) { @@ -109,6 +135,7 @@ GLBackend::GLState* GLBackend::syncGPUObject(const State& state) { // here, we need to regenerate something so let's do it all object->_commands.clear(); object->_stamp = state.getStamp(); + object->_signature = state.getSignature(); bool depthBias = false; bool stencilState = false; @@ -130,8 +157,8 @@ GLBackend::GLState* GLBackend::syncGPUObject(const State& state) { depthBias = true; break; } - case State::FRONT_FACE: { - generateFrontClockwise(object->_commands, bool(field.second._integer)); + case State::FRONT_FACE_CLOCKWISE: { + generateFrontFaceClockwise(object->_commands, bool(field.second._integer)); break; } case State::DEPTH_CLIP_ENABLE: { @@ -163,6 +190,7 @@ GLBackend::GLState* GLBackend::syncGPUObject(const State& state) { } case State::SAMPLE_MASK: { + generateSampleMask(object->_commands, (field.second._unsigned_integer)); break; } case State::ALPHA_TO_COVERAGE_ENABLE: { @@ -170,12 +198,8 @@ GLBackend::GLState* GLBackend::syncGPUObject(const State& state) { break; } - case State::BLEND_FUNCTION: - case State::BLEND_FACTOR_X: - case State::BLEND_FACTOR_Y: - case State::BLEND_FACTOR_Z: - case State::BLEND_FACTOR_W: { - blendState = true; + case State::BLEND_FUNCTION: { + generateBlend(object->_commands, state); break; } @@ -195,14 +219,26 @@ GLBackend::GLState* GLBackend::syncGPUObject(const State& state) { generateStencil(object->_commands, state); } - if (blendState) { - generateBlend(object->_commands, state); - } - return object; } + + +void GLBackend::resetPipelineState(State::Signature nextSignature) { + auto currentNotSignature = ~_pipeline._stateSignatureCache; + auto nextNotSignature = ~nextSignature; + auto fieldsToBeReset = currentNotSignature ^ (currentNotSignature | nextNotSignature); + if (fieldsToBeReset.any()) { + for (auto i = 0; i < State::NUM_FIELDS; i++) { + if (fieldsToBeReset[i]) { + GLState::_resetStateCommands[i]->run(this); + _pipeline._stateSignatureCache.reset(i); + } + } + } +} + static GLenum GL_COMPARISON_FUNCTIONS[] = { GL_NEVER, GL_LESS, @@ -214,160 +250,246 @@ static GLenum GL_COMPARISON_FUNCTIONS[] = { GL_ALWAYS }; void GLBackend::do_setStateFillMode(int32 mode) { - static GLenum GL_FILL_MODES[] = { GL_POINT, GL_LINE, GL_FILL }; - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL_MODES[mode]); - CHECK_GL_ERROR(); + if (_pipeline._stateCache.fillMode != mode) { + static GLenum GL_FILL_MODES[] = { GL_POINT, GL_LINE, GL_FILL }; + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL_MODES[mode]); + CHECK_GL_ERROR(); + + _pipeline._stateCache.fillMode = State::FillMode(mode); + } } void GLBackend::do_setStateCullMode(int32 mode) { - static GLenum GL_CULL_MODES[] = { GL_FRONT_AND_BACK, GL_FRONT, GL_BACK }; - if (mode == State::CULL_NONE) { - glDisable(GL_CULL_FACE); - glCullFace(GL_FRONT_AND_BACK); - } else { - glEnable(GL_CULL_FACE); - glCullFace(GL_CULL_MODES[mode]); + if (_pipeline._stateCache.cullMode != mode) { + static GLenum GL_CULL_MODES[] = { GL_FRONT_AND_BACK, GL_FRONT, GL_BACK }; + if (mode == State::CULL_NONE) { + glDisable(GL_CULL_FACE); + glCullFace(GL_FRONT_AND_BACK); + } else { + glEnable(GL_CULL_FACE); + glCullFace(GL_CULL_MODES[mode]); + } + CHECK_GL_ERROR(); + + _pipeline._stateCache.cullMode = State::CullMode(mode); } - CHECK_GL_ERROR(); } -void GLBackend::do_setStateFrontClockwise(int32 isFrontClockwise) { - static GLenum GL_FRONT_FACES[] = { GL_CCW, GL_CW }; - glFrontFace(GL_FRONT_FACES[isFrontClockwise]); - CHECK_GL_ERROR(); +void GLBackend::do_setStateFrontFaceClockwise(bool isClockwise) { + if (_pipeline._stateCache.frontFaceClockwise != isClockwise) { + static GLenum GL_FRONT_FACES[] = { GL_CCW, GL_CW }; + glFrontFace(GL_FRONT_FACES[isClockwise]); + CHECK_GL_ERROR(); + + _pipeline._stateCache.frontFaceClockwise = isClockwise; + } } -void GLBackend::do_setStateDepthClipEnable(int32 enable) { - if (enable) { - glEnable(GL_DEPTH_CLAMP); - } else { - glDisable(GL_DEPTH_CLAMP); +void GLBackend::do_setStateDepthClipEnable(bool enable) { + if (_pipeline._stateCache.depthClipEnable != enable) { + if (enable) { + glEnable(GL_DEPTH_CLAMP); + } else { + glDisable(GL_DEPTH_CLAMP); + } + CHECK_GL_ERROR(); + + _pipeline._stateCache.depthClipEnable = enable; } - CHECK_GL_ERROR(); } -void GLBackend::do_setStateScissorEnable(int32 enable) { - if (enable) { - glEnable(GL_SCISSOR_TEST); - } else { - glDisable(GL_SCISSOR_TEST); +void GLBackend::do_setStateScissorEnable(bool enable) { + if (_pipeline._stateCache.scissorEnable != enable) { + if (enable) { + glEnable(GL_SCISSOR_TEST); + } else { + glDisable(GL_SCISSOR_TEST); + } + CHECK_GL_ERROR(); + + _pipeline._stateCache.scissorEnable = enable; } - CHECK_GL_ERROR(); } -void GLBackend::do_setStateMultisampleEnable(int32 enable) { - if (enable) { - glEnable(GL_MULTISAMPLE); - } else { - glDisable(GL_MULTISAMPLE); +void GLBackend::do_setStateMultisampleEnable(bool enable) { + if (_pipeline._stateCache.multisampleEnable != enable) { + if (enable) { + glEnable(GL_MULTISAMPLE); + } else { + glDisable(GL_MULTISAMPLE); + } + CHECK_GL_ERROR(); + + _pipeline._stateCache.multisampleEnable = enable; } - CHECK_GL_ERROR(); } -void GLBackend::do_setStateAntialiasedLineEnable(int32 enable) { - if (enable) { - glEnable(GL_POINT_SMOOTH); - glEnable(GL_LINE_SMOOTH); - } else { - glDisable(GL_POINT_SMOOTH); - glDisable(GL_LINE_SMOOTH); +void GLBackend::do_setStateAntialiasedLineEnable(bool enable) { + if (_pipeline._stateCache.antialisedLineEnable != enable) { + if (enable) { + glEnable(GL_POINT_SMOOTH); + glEnable(GL_LINE_SMOOTH); + } else { + glDisable(GL_POINT_SMOOTH); + glDisable(GL_LINE_SMOOTH); + } + CHECK_GL_ERROR(); + + _pipeline._stateCache.antialisedLineEnable = enable; + } +} + +void GLBackend::do_setStateDepthBias(Vec2 bias) { + if ( (bias.x != _pipeline._stateCache.depthBias) || (bias.y != _pipeline._stateCache.depthBiasSlopeScale)) { + if ((bias.x != 0.f) || (bias.y != 0.f)) { + glEnable(GL_POLYGON_OFFSET_FILL); + glEnable(GL_POLYGON_OFFSET_LINE); + glEnable(GL_POLYGON_OFFSET_POINT); + glPolygonOffset(bias.x, bias.y); + } else { + glDisable(GL_POLYGON_OFFSET_FILL); + glDisable(GL_POLYGON_OFFSET_LINE); + glDisable(GL_POLYGON_OFFSET_POINT); + } + _pipeline._stateCache.depthBias = bias.x; + _pipeline._stateCache.depthBiasSlopeScale = bias.y; } - CHECK_GL_ERROR(); } void GLBackend::do_setStateDepthTest(State::DepthTest test) { - if (test.isEnabled()) { - glEnable(GL_DEPTH_TEST); - glDepthMask(test.getWriteMask()); - glDepthFunc(GL_COMPARISON_FUNCTIONS[test.getFunction()]); - } else { - glDisable(GL_DEPTH_TEST); + if (_pipeline._stateCache.depthTest != test) { + if (test.isEnabled()) { + glEnable(GL_DEPTH_TEST); + glDepthMask(test.getWriteMask()); + glDepthFunc(GL_COMPARISON_FUNCTIONS[test.getFunction()]); + } else { + glDisable(GL_DEPTH_TEST); + } + CHECK_GL_ERROR(); + + _pipeline._stateCache.depthTest = test; } - CHECK_GL_ERROR(); } void GLBackend::do_setStateStencil(State::StencilActivation activation, State::StencilTest frontTest, State::StencilTest backTest) { - if (activation.isEnabled()) { - glEnable(GL_STENCIL_TEST); - glStencilMaskSeparate(GL_FRONT, activation.getWriteMaskFront()); - glStencilMaskSeparate(GL_BACK, activation.getWriteMaskBack()); + + if ((_pipeline._stateCache.stencilActivation != activation) + || (_pipeline._stateCache.stencilTestFront != frontTest) + || (_pipeline._stateCache.stencilTestBack != backTest)) { - static GLenum STENCIL_OPS[] = { - GL_KEEP, - GL_ZERO, - GL_REPLACE, - GL_INCR_WRAP, - GL_DECR_WRAP, - GL_INVERT, - GL_INCR, - GL_DECR }; + if (activation.isEnabled()) { + glEnable(GL_STENCIL_TEST); + glStencilMaskSeparate(GL_FRONT, activation.getWriteMaskFront()); + glStencilMaskSeparate(GL_BACK, activation.getWriteMaskBack()); - glStencilFuncSeparate(GL_FRONT, STENCIL_OPS[frontTest.getFailOp()], STENCIL_OPS[frontTest.getPassOp()], STENCIL_OPS[frontTest.getDepthFailOp()]); - glStencilFuncSeparate(GL_FRONT, GL_COMPARISON_FUNCTIONS[frontTest.getFunction()], frontTest.getReference(), frontTest.getReadMask()); + static GLenum STENCIL_OPS[] = { + GL_KEEP, + GL_ZERO, + GL_REPLACE, + GL_INCR_WRAP, + GL_DECR_WRAP, + GL_INVERT, + GL_INCR, + GL_DECR }; - glStencilFuncSeparate(GL_BACK, STENCIL_OPS[backTest.getFailOp()], STENCIL_OPS[backTest.getPassOp()], STENCIL_OPS[backTest.getDepthFailOp()]); - glStencilFuncSeparate(GL_BACK, GL_COMPARISON_FUNCTIONS[backTest.getFunction()], backTest.getReference(), backTest.getReadMask()); - } else { - glDisable(GL_STENCIL_TEST); - } - CHECK_GL_ERROR(); -} + glStencilFuncSeparate(GL_FRONT, STENCIL_OPS[frontTest.getFailOp()], STENCIL_OPS[frontTest.getPassOp()], STENCIL_OPS[frontTest.getDepthFailOp()]); + glStencilFuncSeparate(GL_FRONT, GL_COMPARISON_FUNCTIONS[frontTest.getFunction()], frontTest.getReference(), frontTest.getReadMask()); -void GLBackend::do_setStateAlphaToCoverageEnable(int32 enable) { - if (enable) { - glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE); - } else { - glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); - } - CHECK_GL_ERROR(); -} - -void GLBackend::do_setStateBlend(State::BlendFunction function, Vec4 factor ) { - if (function.isEnabled()) { - glEnable(GL_BLEND); - - static GLenum GL_BLEND_OPS[] = { - GL_FUNC_ADD, - GL_FUNC_SUBTRACT, - GL_FUNC_REVERSE_SUBTRACT, - GL_MIN, - GL_MAX }; - - glBlendEquationSeparate(GL_BLEND_OPS[function.getOperationColor()], GL_BLEND_OPS[function.getOperationAlpha()]); + glStencilFuncSeparate(GL_BACK, STENCIL_OPS[backTest.getFailOp()], STENCIL_OPS[backTest.getPassOp()], STENCIL_OPS[backTest.getDepthFailOp()]); + glStencilFuncSeparate(GL_BACK, GL_COMPARISON_FUNCTIONS[backTest.getFunction()], backTest.getReference(), backTest.getReadMask()); + } else { + glDisable(GL_STENCIL_TEST); + } CHECK_GL_ERROR(); - static GLenum BLEND_ARGS[] = { - GL_ZERO, - GL_ONE, - GL_SRC_COLOR, - GL_ONE_MINUS_SRC_COLOR, - GL_SRC_ALPHA, - GL_ONE_MINUS_SRC_ALPHA, - GL_DST_ALPHA, - GL_ONE_MINUS_DST_ALPHA, - GL_DST_COLOR, - GL_ONE_MINUS_DST_COLOR, - GL_SRC_ALPHA_SATURATE, - GL_CONSTANT_COLOR, - GL_ONE_MINUS_CONSTANT_COLOR, - GL_CONSTANT_ALPHA, - GL_ONE_MINUS_CONSTANT_ALPHA, - }; - - glBlendFuncSeparate(BLEND_ARGS[function.getSourceColor()], BLEND_ARGS[function.getDestinationColor()], - BLEND_ARGS[function.getSourceAlpha()], BLEND_ARGS[function.getDestinationAlpha()]); - CHECK_GL_ERROR(); - - glBlendColor(factor.x, factor.y, factor.z, factor.w); - CHECK_GL_ERROR(); - } else { - glDisable(GL_BLEND); + _pipeline._stateCache.stencilActivation = activation; + _pipeline._stateCache.stencilTestFront = frontTest; + _pipeline._stateCache.stencilTestBack = backTest; } } -void GLBackend::do_setStateColorWriteMask(int32 mask) { - glColorMask(mask & State::ColorMask::WRITE_RED, +void GLBackend::do_setStateAlphaToCoverageEnable(bool enable) { + if (_pipeline._stateCache.alphaToCoverageEnable != enable) { + if (enable) { + glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE); + } else { + glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); + } + CHECK_GL_ERROR(); + _pipeline._stateCache.alphaToCoverageEnable = enable; + } +} + +void GLBackend::do_setStateSampleMask(uint32 mask) { + if (_pipeline._stateCache.sampleMask != mask) { + // TODO + _pipeline._stateCache.sampleMask = mask; + } +} + +void GLBackend::do_setStateBlend(State::BlendFunction function) { + if (_pipeline._stateCache.blendFunction != function) { + if (function.isEnabled()) { + glEnable(GL_BLEND); + + static GLenum GL_BLEND_OPS[] = { + GL_FUNC_ADD, + GL_FUNC_SUBTRACT, + GL_FUNC_REVERSE_SUBTRACT, + GL_MIN, + GL_MAX }; + + glBlendEquationSeparate(GL_BLEND_OPS[function.getOperationColor()], GL_BLEND_OPS[function.getOperationAlpha()]); + CHECK_GL_ERROR(); + + static GLenum BLEND_ARGS[] = { + GL_ZERO, + GL_ONE, + GL_SRC_COLOR, + GL_ONE_MINUS_SRC_COLOR, + GL_SRC_ALPHA, + GL_ONE_MINUS_SRC_ALPHA, + GL_DST_ALPHA, + GL_ONE_MINUS_DST_ALPHA, + GL_DST_COLOR, + GL_ONE_MINUS_DST_COLOR, + GL_SRC_ALPHA_SATURATE, + GL_CONSTANT_COLOR, + GL_ONE_MINUS_CONSTANT_COLOR, + GL_CONSTANT_ALPHA, + GL_ONE_MINUS_CONSTANT_ALPHA, + }; + + glBlendFuncSeparate(BLEND_ARGS[function.getSourceColor()], BLEND_ARGS[function.getDestinationColor()], + BLEND_ARGS[function.getSourceAlpha()], BLEND_ARGS[function.getDestinationAlpha()]); + CHECK_GL_ERROR(); + } else { + glDisable(GL_BLEND); + } + + _pipeline._stateCache.blendFunction = function; + } +} + +void GLBackend::do_setStateColorWriteMask(uint32 mask) { + if (_pipeline._stateCache.colorWriteMask = mask) { + glColorMask(mask & State::ColorMask::WRITE_RED, mask & State::ColorMask::WRITE_GREEN, mask & State::ColorMask::WRITE_BLUE, mask & State::ColorMask::WRITE_ALPHA ); + + _pipeline._stateCache.colorWriteMask = mask; + } +} + + +void GLBackend::do_setStateBlendFactor(Batch& batch, uint32 paramOffset) { + + Vec4 factor(batch._params[paramOffset + 0]._float, + batch._params[paramOffset + 1]._float, + batch._params[paramOffset + 2]._float, + batch._params[paramOffset + 3]._float); + + glBlendColor(factor.x, factor.y, factor.z, factor.w); + CHECK_GL_ERROR(); } \ No newline at end of file diff --git a/libraries/gpu/src/gpu/State.cpp b/libraries/gpu/src/gpu/State.cpp index 0260190327..4276e19dbb 100755 --- a/libraries/gpu/src/gpu/State.cpp +++ b/libraries/gpu/src/gpu/State.cpp @@ -19,3 +19,5 @@ State::State() { State::~State() { } + +const State::Cache State::DEFAULT = State::Cache(); diff --git a/libraries/gpu/src/gpu/State.h b/libraries/gpu/src/gpu/State.h index 839768bbc7..c4ac2d0a5d 100755 --- a/libraries/gpu/src/gpu/State.h +++ b/libraries/gpu/src/gpu/State.h @@ -15,6 +15,7 @@ #include #include +#include namespace gpu { @@ -27,40 +28,7 @@ public: virtual ~State(); const Stamp getStamp() const { return _stamp; } - - // All the possible fields - enum Field { - FILL_MODE, - CULL_MODE, - FRONT_FACE, - DEPTH_CLIP_ENABLE, - SCISSOR_ENABLE, - MULTISAMPLE_ENABLE, - ANTIALISED_LINE_ENABLE, - - DEPTH_BIAS, - DEPTH_BIAS_SLOPE_SCALE, - - DEPTH_TEST, - - STENCIL_ACTIVATION, - STENCIL_TEST_FRONT, - STENCIL_TEST_BACK, - - SAMPLE_MASK, - ALPHA_TO_COVERAGE_ENABLE, - - BLEND_FUNCTION, - BLEND_FACTOR_X, - BLEND_FACTOR_Y, - BLEND_FACTOR_Z, - BLEND_FACTOR_W, - - COLOR_WRITE_MASK, - - NUM_FIELDS, // not a valid field, just the count - }; - + enum ComparisonFunction { NEVER = 0, LESS, @@ -157,6 +125,8 @@ public: int32 getRaw() const { return *(reinterpret_cast(this)); } DepthTest(int32 raw) { *(reinterpret_cast(this)) = raw; } + bool operator== (const DepthTest& right) { return getRaw() == right.getRaw(); } + bool operator!= (const DepthTest& right) { return getRaw() != right.getRaw(); } }; class StencilTest { @@ -187,6 +157,8 @@ public: int32 getRaw() const { return *(reinterpret_cast(this)); } StencilTest(int32 raw) { *(reinterpret_cast(this)) = raw; } + bool operator== (const StencilTest& right) { return getRaw() == right.getRaw(); } + bool operator!= (const StencilTest& right) { return getRaw() != right.getRaw(); } }; class StencilActivation { @@ -204,9 +176,10 @@ public: int32 getRaw() const { return *(reinterpret_cast(this)); } StencilActivation(int32 raw) { *(reinterpret_cast(this)) = raw; } + bool operator== (const StencilActivation& right) { return getRaw() == right.getRaw(); } + bool operator!= (const StencilActivation& right) { return getRaw() != right.getRaw(); } }; - class BlendFunction { static const int COLOR_MASK = 0x0f; static const int ALPHA_MASK = 0xf0; @@ -244,8 +217,151 @@ public: int32 getRaw() const { return *(reinterpret_cast(this)); } BlendFunction(int32 raw) { *(reinterpret_cast(this)) = raw; } + bool operator== (const BlendFunction& right) { return getRaw() == right.getRaw(); } + bool operator!= (const BlendFunction& right) { return getRaw() != right.getRaw(); } }; + // The Cache class is the full explicit description of the State class fields value. + // Useful for having one const static called Default for reference or for the gpu::Backend to keep track of the current value + class Cache { + public: + FillMode fillMode = FILL_FACE; + CullMode cullMode = CULL_NONE; + bool frontFaceClockwise = true; + bool depthClipEnable = false; + bool scissorEnable = false; + bool multisampleEnable = false; + bool antialisedLineEnable = false; + + float depthBias = 0.0f; + float depthBiasSlopeScale = 0.0f; + + DepthTest depthTest = DepthTest(false, true, LESS); + + StencilActivation stencilActivation = StencilActivation(false); + StencilTest stencilTestFront = StencilTest(0, 0xff, ALWAYS, STENCIL_OP_KEEP, STENCIL_OP_KEEP, STENCIL_OP_KEEP); + StencilTest stencilTestBack = StencilTest(0, 0xff, ALWAYS, STENCIL_OP_KEEP, STENCIL_OP_KEEP, STENCIL_OP_KEEP); + + uint32 sampleMask = 0xFFFFFFFF; + bool alphaToCoverageEnable = false; + + BlendFunction blendFunction = BlendFunction(false); + + uint32 colorWriteMask = WRITE_ALL; + }; + + // The unique default values for all the fields + static const Cache DEFAULT; + + void setFillMode(FillMode fill) { set(FILL_MODE, DEFAULT.fillMode, fill); } + FillMode getFillMode() const { return get(FILL_MODE, DEFAULT.fillMode); } + + void setCullMode(CullMode cull) { set(CULL_MODE, DEFAULT.cullMode, cull); } + CullMode getCullMode() const { return get(CULL_MODE, DEFAULT.cullMode); } + + void setFrontFaceClockwise(bool isClockwise) { set(FRONT_FACE_CLOCKWISE, DEFAULT.frontFaceClockwise, isClockwise); } + bool isFrontFaceClockwise() const { return get(FRONT_FACE_CLOCKWISE, DEFAULT.frontFaceClockwise); } + + void setDepthClipEnable(bool enable) { set(DEPTH_CLIP_ENABLE, DEFAULT.depthClipEnable, enable); } + bool isDepthClipEnable() const { return get(DEPTH_CLIP_ENABLE, DEFAULT.depthClipEnable); } + + void setScissorEnable(bool enable) { set(SCISSOR_ENABLE, DEFAULT.scissorEnable, enable); } + bool isScissorEnable() const { return get(SCISSOR_ENABLE, DEFAULT.scissorEnable); } + + void setMultisampleEnable(bool enable) { set(MULTISAMPLE_ENABLE, DEFAULT.multisampleEnable, enable); } + bool isMultisampleEnable() const { return get(MULTISAMPLE_ENABLE, DEFAULT.multisampleEnable); } + + void setAntialiasedLineEnable(bool enable) { set(ANTIALISED_LINE_ENABLE, DEFAULT.antialisedLineEnable, enable); } + bool isAntialiasedLineEnable() const { return get(ANTIALISED_LINE_ENABLE, DEFAULT.antialisedLineEnable); } + + // Depth Bias + void setDepthBias(float bias) { set(DEPTH_BIAS, DEFAULT.depthBias, bias); } + float getDepthBias() const { return get(DEPTH_BIAS, DEFAULT.depthBias); } + + void setDepthBiasSlopeScale(float scale) { set(DEPTH_BIAS_SLOPE_SCALE, DEFAULT.depthBiasSlopeScale, scale); } + float getDepthBiasSlopeScale() const { return get(DEPTH_BIAS_SLOPE_SCALE, DEFAULT.depthBiasSlopeScale); } + + // Depth Test + void setDepthTest(DepthTest depthTest) { set(DEPTH_TEST, DEFAULT.depthTest, depthTest); } + void setDepthTest(bool enable, bool writeMask, ComparisonFunction func) { setDepthTest(DepthTest(enable, writeMask, func)); } + DepthTest getDepthTest() const { return get(DEPTH_TEST, DEFAULT.depthTest); } + + bool isDepthTestEnabled() const { return getDepthTest().isEnabled(); } + bool getDepthTestWriteMask() const { return getDepthTest().getWriteMask(); } + ComparisonFunction getDepthTestFunc() const { return getDepthTest().getFunction(); } + + // Stencil test + void setStencilTest(bool enabled, uint8 frontWriteMask, StencilTest frontTest, uint8 backWriteMask, StencilTest backTest) { + set(STENCIL_ACTIVATION, DEFAULT.stencilActivation, StencilActivation(enabled, frontWriteMask, backWriteMask)); + set(STENCIL_TEST_FRONT, DEFAULT.stencilTestFront, frontTest); + set(STENCIL_TEST_BACK, DEFAULT.stencilTestBack, backTest); } + void setStencilTest(bool enabled, uint8 frontWriteMask, StencilTest frontTest) { + setStencilTest(enabled, frontWriteMask, frontTest, frontWriteMask, frontTest); } + + StencilActivation getStencilActivation() const { return get(STENCIL_ACTIVATION, DEFAULT.stencilActivation); } + StencilTest getStencilTestFront() const { return get(STENCIL_TEST_FRONT, DEFAULT.stencilTestFront); } + StencilTest getStencilTestBack() const { return get(STENCIL_TEST_BACK, DEFAULT.stencilTestBack); } + + bool isStencilEnabled() const { return getStencilActivation().isEnabled(); } + uint8 getStencilWriteMaskFront() const { return getStencilActivation().getWriteMaskFront(); } + uint8 getStencilWriteMaskBack() const { return getStencilActivation().getWriteMaskBack(); } + + // Alpha to coverage + void setAlphaToCoverageEnable(bool enable) { set(ALPHA_TO_COVERAGE_ENABLE, DEFAULT.alphaToCoverageEnable, enable); } + bool isAlphaToCoverageEnabled() const { return get(ALPHA_TO_COVERAGE_ENABLE, DEFAULT.alphaToCoverageEnable); } + + // Sample mask + void setSampleMask(uint32 mask) { set(SAMPLE_MASK, DEFAULT.sampleMask, mask); } + uint32 getSampleMask() const { return get(SAMPLE_MASK, DEFAULT.sampleMask); } + + // Blend Function + void setBlendFunction(BlendFunction function) { set(BLEND_FUNCTION, DEFAULT.blendFunction, function); } + BlendFunction getBlendFunction() const { return get(BLEND_FUNCTION, DEFAULT.blendFunction); } + + void setBlendFunction(bool enabled, BlendArg sourceColor, BlendOp operationColor, BlendArg destinationColor, BlendArg sourceAlpha, BlendOp operationAlpha, BlendArg destinationAlpha) { + setBlendFunction(BlendFunction(enabled, sourceColor, operationColor, destinationColor, sourceAlpha, operationAlpha, destinationAlpha)); } + void setBlendFunction(bool enabled, BlendArg source, BlendOp operation, BlendArg destination) { + setBlendFunction(BlendFunction(enabled, source, operation, destination)); } + + bool isBlendEnabled() const { return getBlendFunction().isEnabled(); } + + // Color write mask + void setColorWriteMask(int32 mask) { set(COLOR_WRITE_MASK, DEFAULT.colorWriteMask, mask); } + uint32 getColorWriteMask() const { return get(COLOR_WRITE_MASK, DEFAULT.colorWriteMask); } + + // The state values are stored in a Map called FieldMap + // only the fields with non default value are saved + + // All the possible fields + enum Field { + FILL_MODE, + CULL_MODE, + FRONT_FACE_CLOCKWISE, + DEPTH_CLIP_ENABLE, + SCISSOR_ENABLE, + MULTISAMPLE_ENABLE, + ANTIALISED_LINE_ENABLE, + + DEPTH_BIAS, + DEPTH_BIAS_SLOPE_SCALE, + + DEPTH_TEST, + + STENCIL_ACTIVATION, + STENCIL_TEST_FRONT, + STENCIL_TEST_BACK, + + SAMPLE_MASK, + ALPHA_TO_COVERAGE_ENABLE, + + BLEND_FUNCTION, + + COLOR_WRITE_MASK, + + NUM_FIELDS, // not a valid field, just the count + }; + + // the value of a field class Value { public: union { @@ -272,12 +388,30 @@ public: template <> StencilTest State::Value::cast() const { return StencilTest(_integer); } template <> BlendFunction State::Value::cast() const { return BlendFunction(_integer); } }; + + // The field map type typedef std::unordered_map FieldMap; const FieldMap& getFields() const { return _fields; } - template void set(Field field, T value) { - _fields[field].uncast(value); + // The signature of the state tells which fields of the state are not default + // this way during rendering the Backend can compare it's current state and try to minimize the job to do + typedef std::bitset Signature; + + Signature getSignature() const { return _signature; } + +protected: + State(const State& state); + State& operator=(const State& state); + + template void set(Field field, T defaultValue, T value) { + if (value == defaultValue) { + _fields.erase(field); + _signature.reset(field); + } else { + _fields[field].uncast(value); + _signature.set(field); + } _stamp++; } @@ -289,96 +423,9 @@ public: return defaultValue; } - void setFillMode(FillMode fill) { set(FILL_MODE, fill); } - FillMode getFillMode() const { return get(FILL_MODE, FILL_FACE); } - - void setCullMode(CullMode cull) { set(CULL_MODE, cull); } - CullMode getCullMode() const { return get(CULL_MODE, CULL_NONE); } - - void setFrontFace(bool isClockwise) { set(FRONT_FACE, isClockwise); } - bool isFrontFaceClockwise() const { return get(FRONT_FACE, true); } - - void setDepthClipEnable(bool enable) { set(DEPTH_CLIP_ENABLE, enable); } - bool isDepthClipEnable() const { return get(DEPTH_CLIP_ENABLE, false); } - - void setScissorEnable(bool enable) { set(SCISSOR_ENABLE, enable); } - bool isScissorEnable() const { return get(SCISSOR_ENABLE, false); } - - void setMultisampleEnable(bool enable) { set(MULTISAMPLE_ENABLE, enable); } - bool isMultisampleEnable() const { return get(MULTISAMPLE_ENABLE, false); } - - void setAntialiasedLineEnable(bool enable) { set(ANTIALISED_LINE_ENABLE, enable); } - bool isAntialiasedLineEnable() const { return get(ANTIALISED_LINE_ENABLE, true); } - - // Depth Bias - void setDepthBias(float bias) { set(DEPTH_BIAS, bias); } - void setDepthBiasSlopeScale(float scale) { set(DEPTH_BIAS_SLOPE_SCALE, scale); } - float getDepthBias() const { return get(DEPTH_BIAS, 0.0f); } - float getDepthBiasSlopeScale() const { return get(DEPTH_BIAS_SLOPE_SCALE, 1.0f); } - - // Depth Test - void setDepthTest(DepthTest depthTest) { set(DEPTH_TEST, depthTest); } - void setDepthTest(bool enable, bool writeMask, ComparisonFunction func) { setDepthTest(DepthTest(enable, writeMask, func)); } - DepthTest getDepthTest() const { return get(DEPTH_TEST, DepthTest(false, true, LESS)); } - - bool isDepthTestEnabled() const { return getDepthTest().isEnabled(); } - bool getDepthTestWriteMask() const { return getDepthTest().getWriteMask(); } - ComparisonFunction getDepthTestFunc() const { return getDepthTest().getFunction(); } - - // Stencil test - void setStencilTest(bool enabled, uint8 frontWriteMask, StencilTest frontTest, uint8 backWriteMask, StencilTest backTest) { - set(STENCIL_ACTIVATION, StencilActivation(enabled, frontWriteMask, backWriteMask)); - set(STENCIL_TEST_FRONT, frontTest); - set(STENCIL_TEST_BACK, backTest); } - void setStencilTest(bool enabled, uint8 frontWriteMask, StencilTest frontTest) { - setStencilTest(enabled, frontWriteMask, frontTest, frontWriteMask, frontTest); } - - StencilActivation getStencilActivation() const { return get(STENCIL_ACTIVATION, StencilActivation(false)); } - bool isStencilEnabled() const { return getStencilActivation().isEnabled(); } - uint8 getStencilWriteMaskFront() const { return getStencilActivation().getWriteMaskFront(); } - uint8 getStencilWriteMaskBack() const { return getStencilActivation().getWriteMaskBack(); } - - StencilTest getStencilTestFront() const { return get(STENCIL_TEST_FRONT, StencilTest()); } - StencilTest getStencilTestBack() const { return get(STENCIL_TEST_BACK, StencilTest()); } - - // Alpha to coverage - void setAlphaToCoverageEnable(bool enable) { set(ALPHA_TO_COVERAGE_ENABLE, enable); } - bool isAlphaToCoverageEnabled() const { return get(ALPHA_TO_COVERAGE_ENABLE, false); } - - // Sample mask - void setSampleMask(uint32 mask) { set(SAMPLE_MASK, mask); } - uint32 getSampleMask() const { return get(SAMPLE_MASK, 0xFFFFFFFF); } - - // Blend - void setBlendFunction(BlendFunction function) { set(BLEND_FUNCTION, function); } - void setBlendFunction(bool enabled, BlendArg sourceColor, BlendOp operationColor, BlendArg destinationColor, BlendArg sourceAlpha, BlendOp operationAlpha, BlendArg destinationAlpha) { - setBlendFunction(BlendFunction(enabled, sourceColor, operationColor, destinationColor, sourceAlpha, operationAlpha, destinationAlpha)); } - void setBlendFunction(bool enabled, BlendArg source, BlendOp operation, BlendArg destination) { - setBlendFunction(BlendFunction(enabled, source, operation, destination)); } - BlendFunction getBlendFunction() const { return get(BLEND_FUNCTION, BlendFunction(false)); } - - bool isBlendEnabled() const { return getBlendFunction().isEnabled(); } - - void setBlendFactor(const Vec4& factor) { - set(BLEND_FACTOR_X, factor.x); - set(BLEND_FACTOR_Y, factor.y); - set(BLEND_FACTOR_Z, factor.z); - set(BLEND_FACTOR_W, factor.w); } - Vec4 State::getBlendFactor() const { - return Vec4(get(BLEND_FACTOR_X, 0.0f), get(BLEND_FACTOR_Y, 0.0f), get(BLEND_FACTOR_Z, 0.0f), get(BLEND_FACTOR_W, 0.0f)); - } - - // Color write mask - void setColorWriteMask(int32 mask) { set(COLOR_WRITE_MASK, mask); } - uint32 getColorWriteMask() const { return get(COLOR_WRITE_MASK, WRITE_ALL); } - -protected: - State(const State& state); - State& operator=(const State& state); - FieldMap _fields; - - Stamp _stamp = 0; + Signature _signature{0}; + Stamp _stamp{0}; // This shouldn't be used by anything else than the Backend class with the proper casting. mutable GPUObject* _gpuObject = nullptr; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 130d6b7f5c..3f304fc630 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -785,6 +785,9 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, true, args, true); } + // try that + batch.setPipeline(gpu::PipelinePointer()); + GLBATCH(glDepthMask)(true); GLBATCH(glDepthFunc)(GL_LESS); GLBATCH(glDisable)(GL_CULL_FACE); @@ -2428,7 +2431,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod } if (mesh.colors.isEmpty()) { - GLBATCH(glColor4f)(1.0f, 1.0f, 1.0f, 1.0f); + GLBATCH(glColor4f)(0.0f, 1.0f, 0.0f, 1.0f); } qint64 offset = 0;