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;