mirror of
https://github.com/lubosz/overte.git
synced 2025-04-23 11:33:44 +02:00
refining the state interface and the GLBackend for it with a true cache
This commit is contained in:
parent
f1a0783347
commit
21b5d6f404
9 changed files with 568 additions and 553 deletions
|
@ -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);
|
||||
|
||||
|
|
|
@ -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<Param> 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<ResourceCache> 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 <typename T>
|
||||
class Cache {
|
||||
public:
|
||||
|
@ -291,26 +267,10 @@ public:
|
|||
typedef Cache<Transform>::Vector TransformCaches;
|
||||
typedef Cache<PipelinePointer>::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<Byte> 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 <typename T>
|
||||
T* editResourcePointer(uint32 offset) {
|
||||
if (offset >= _resources.size()) {
|
||||
return 0;
|
||||
}
|
||||
return reinterpret_cast<T*>((_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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,11 +23,44 @@ GLBackend::GLState::~GLState() {
|
|||
|
||||
typedef GLBackend::GLState::Command Command;
|
||||
typedef GLBackend::GLState::CommandPointer CommandPointer;
|
||||
typedef GLBackend::GLState::Command1<uint32> Command1U;
|
||||
typedef GLBackend::GLState::Command1<int32> Command1I;
|
||||
typedef GLBackend::GLState::Command1<bool> Command1B;
|
||||
typedef GLBackend::GLState::Command1<Vec2> CommandDepthBias;
|
||||
typedef GLBackend::GLState::Command1<State::DepthTest> CommandDepthTest;
|
||||
typedef GLBackend::GLState::Command3<State::StencilActivation, State::StencilTest, State::StencilTest> CommandStencil;
|
||||
typedef GLBackend::GLState::Command2<State::BlendFunction, Vec4> CommandBlend;
|
||||
typedef GLBackend::GLState::Command1<State::BlendFunction> 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();
|
||||
}
|
|
@ -19,3 +19,5 @@ State::State() {
|
|||
|
||||
State::~State() {
|
||||
}
|
||||
|
||||
const State::Cache State::DEFAULT = State::Cache();
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <bitset>
|
||||
|
||||
|
||||
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<const int32*>(this)); }
|
||||
DepthTest(int32 raw) { *(reinterpret_cast<int32*>(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<const int32*>(this)); }
|
||||
StencilTest(int32 raw) { *(reinterpret_cast<int32*>(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<const int32*>(this)); }
|
||||
StencilActivation(int32 raw) { *(reinterpret_cast<int32*>(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<const int32*>(this)); }
|
||||
BlendFunction(int32 raw) { *(reinterpret_cast<int32*>(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<uint32>(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<uint32>(COLOR_WRITE_MASK, DEFAULT.colorWriteMask, mask); }
|
||||
uint32 getColorWriteMask() const { return get<uint32>(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<StencilTest>() const { return StencilTest(_integer); }
|
||||
template <> BlendFunction State::Value::cast<BlendFunction>() const { return BlendFunction(_integer); }
|
||||
};
|
||||
|
||||
// The field map type
|
||||
typedef std::unordered_map<Field, Value> FieldMap;
|
||||
|
||||
const FieldMap& getFields() const { return _fields; }
|
||||
|
||||
template <class T> 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<NUM_FIELDS> Signature;
|
||||
|
||||
Signature getSignature() const { return _signature; }
|
||||
|
||||
protected:
|
||||
State(const State& state);
|
||||
State& operator=(const State& state);
|
||||
|
||||
template <class T> 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<uint32>(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<uint32>(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;
|
||||
|
|
|
@ -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<int>& 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;
|
||||
|
|
Loading…
Reference in a new issue