and make it compile on mac... remove the field map from state just because it's unecessary

This commit is contained in:
samcake 2015-03-30 21:53:59 -07:00
parent ee4b9a483b
commit 1a18719031
5 changed files with 724 additions and 562 deletions

View file

@ -86,7 +86,7 @@ public:
template <class T> class Command1 : public Command {
public:
typedef void (GLBackend::*GLFunction)(typename T);
typedef void (GLBackend::*GLFunction)(T);
void run(GLBackend* backend) { (backend->*(_func))(_param); }
Command1(GLFunction func, T param) : _func(func), _param(param) {};
GLFunction _func;
@ -94,7 +94,7 @@ public:
};
template <class T, class U> class Command2 : public Command {
public:
typedef void (GLBackend::*GLFunction)(typename T, typename U);
typedef void (GLBackend::*GLFunction)(T, U);
void run(GLBackend* backend) { (backend->*(_func))(_param0, _param1); }
Command2(GLFunction func, T param0, U param1) : _func(func), _param0(param0), _param1(param1) {};
GLFunction _func;
@ -104,7 +104,7 @@ public:
template <class T, class U, class V> class Command3 : public Command {
public:
typedef void (GLBackend::*GLFunction)(typename T, typename U, typename V);
typedef void (GLBackend::*GLFunction)(T, U, V);
void run(GLBackend* backend) { (backend->*(_func))(_param0, _param1, _param2); }
Command3(GLFunction func, T param0, U param1, V param2) : _func(func), _param0(param0), _param1(param1), _param2(param2) {};
GLFunction _func;
@ -171,18 +171,18 @@ public:
protected:
// Draw Stage
void do_draw(Batch& batch, uint32 paramOffset);
void do_draw(Batch& batch, uint32 paramOffset);
void do_drawIndexed(Batch& batch, uint32 paramOffset);
void do_drawInstanced(Batch& batch, uint32 paramOffset);
void do_drawInstanced(Batch& batch, uint32 paramOffset);
void do_drawIndexedInstanced(Batch& batch, uint32 paramOffset);
// Input Stage
void do_setInputFormat(Batch& batch, uint32 paramOffset);
void do_setInputBuffer(Batch& batch, uint32 paramOffset);
void do_setInputFormat(Batch& batch, uint32 paramOffset);
void do_setInputBuffer(Batch& batch, uint32 paramOffset);
void do_setIndexBuffer(Batch& batch, uint32 paramOffset);
void updateInput();
struct InputStageState {
struct InputStageState {
bool _invalidFormat;
Stream::FormatPointer _format;
@ -215,18 +215,18 @@ protected:
} _input;
// Transform Stage
void do_setModelTransform(Batch& batch, uint32 paramOffset);
void do_setViewTransform(Batch& batch, uint32 paramOffset);
void do_setModelTransform(Batch& batch, uint32 paramOffset);
void do_setViewTransform(Batch& batch, uint32 paramOffset);
void do_setProjectionTransform(Batch& batch, uint32 paramOffset);
void initTransform();
void killTransform();
void updateTransform();
struct TransformStageState {
TransformObject _transformObject;
TransformCamera _transformCamera;
GLuint _transformObjectBuffer;
GLuint _transformCameraBuffer;
void updateTransform();
struct TransformStageState {
TransformObject _transformObject;
TransformCamera _transformCamera;
GLuint _transformObjectBuffer;
GLuint _transformCameraBuffer;
Transform _model;
Transform _view;
Mat4 _projection;
@ -253,18 +253,18 @@ protected:
void do_setStateBlendFactor(Batch& batch, uint32 paramOffset);
void do_setUniformBuffer(Batch& batch, uint32 paramOffset);
void do_setUniformTexture(Batch& batch, uint32 paramOffset);
void do_setUniformBuffer(Batch& batch, uint32 paramOffset);
void do_setUniformTexture(Batch& batch, uint32 paramOffset);
// Standard update pipeline check that the current Program and current State or good to go for a
void updatePipeline();
// Force to reset all the state fields indicated by the 'toBeReset" signature
void updatePipeline();
// Force to reset all the state fields indicated by the 'toBeReset" signature
void resetPipelineState(State::Signature toBeReset);
// Synchronize the state cache of this Backend with the actual real state of the GL Context
void syncPipelineStateCache();
// Grab the actual gl state into it's gpu::State equivalent. THis is used by the above call syncPipleineStateCache()
void getCurrentGLState(State::Cache& state);
struct PipelineStageState {
PipelinePointer _pipeline;
@ -283,8 +283,8 @@ protected:
_pipeline(),
_program(0),
_invalidProgram(false),
_stateSignatureCache(0),
_stateCache(State::DEFAULT),
_stateSignatureCache(0),
_state(nullptr),
_invalidState(false),
_needStateSync(true)
@ -294,17 +294,17 @@ protected:
// TODO: As long as we have gl calls explicitely issued from interface
// code, we need to be able to record and batch these calls. THe long
// term strategy is to get rid of any GL calls in favor of the HIFI GPU API
void do_glEnable(Batch& batch, uint32 paramOffset);
void do_glEnable(Batch& batch, uint32 paramOffset);
void do_glDisable(Batch& batch, uint32 paramOffset);
void do_glEnableClientState(Batch& batch, uint32 paramOffset);
void do_glDisableClientState(Batch& batch, uint32 paramOffset);
void do_glCullFace(Batch& batch, uint32 paramOffset);
void do_glAlphaFunc(Batch& batch, uint32 paramOffset);
void do_glDepthFunc(Batch& batch, uint32 paramOffset);
void do_glDepthMask(Batch& batch, uint32 paramOffset);
void do_glDepthFunc(Batch& batch, uint32 paramOffset);
void do_glDepthMask(Batch& batch, uint32 paramOffset);
void do_glDepthRange(Batch& batch, uint32 paramOffset);
void do_glBindBuffer(Batch& batch, uint32 paramOffset);
@ -318,7 +318,7 @@ protected:
void do_glUniform1f(Batch& batch, uint32 paramOffset);
void do_glUniform2f(Batch& batch, uint32 paramOffset);
void do_glUniform4fv(Batch& batch, uint32 paramOffset);
void do_glUniformMatrix4fv(Batch& batch, uint32 paramOffset);
void do_glUniformMatrix4fv(Batch& batch, uint32 paramOffset);
void do_glEnableVertexAttribArray(Batch& batch, uint32 paramOffset);
void do_glDisableVertexAttribArray(Batch& batch, uint32 paramOffset);

View file

@ -19,7 +19,7 @@ GLBackend::GLState::GLState()
GLBackend::GLState::~GLState() {
}
typedef GLBackend::GLState::Command Command;
typedef GLBackend::GLState::CommandPointer CommandPointer;
@ -62,7 +62,7 @@ const GLBackend::GLState::Commands GLBackend::GLState::_resetStateCommands = {
CommandPointer(new Command1U(&GLBackend::do_setStateColorWriteMask, State::DEFAULT.colorWriteMask))
};
void generateFillMode(GLBackend::GLState::Commands& commands, State::FillMode fillMode) {
void generateFillMode(GLBackend::GLState::Commands& commands, State::FillMode fillMode) {
commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateFillMode, int32(fillMode))));
}
@ -94,7 +94,7 @@ void generateDepthBias(GLBackend::GLState::Commands& commands, const State& stat
commands.push_back(CommandPointer(new CommandDepthBias(&GLBackend::do_setStateDepthBias, Vec2(state.getDepthBias(), state.getDepthBiasSlopeScale()))));
}
void generateDepthTest(GLBackend::GLState::Commands& commands, State::DepthTest& test) {
void generateDepthTest(GLBackend::GLState::Commands& commands, const State::DepthTest& test) {
commands.push_back(CommandPointer(new CommandDepthTest(&GLBackend::do_setStateDepthTest, int32(test.getRaw()))));
}
@ -142,6 +142,76 @@ GLBackend::GLState* GLBackend::syncGPUObject(const State& state) {
bool blendState = false;
// go thorugh the list of state fields in the State and record the corresponding gl command
for (int i = 0; i < State::NUM_FIELDS; i++) {
if (state.getSignature()[i]) {
switch(i) {
case State::FILL_MODE: {
generateFillMode(object->_commands, state.getFillMode());
break;
}
case State::CULL_MODE: {
generateCullMode(object->_commands, state.getCullMode());
break;
}
case State::DEPTH_BIAS:
case State::DEPTH_BIAS_SLOPE_SCALE: {
depthBias = true;
break;
}
case State::FRONT_FACE_CLOCKWISE: {
generateFrontFaceClockwise(object->_commands, state.isFrontFaceClockwise());
break;
}
case State::DEPTH_CLIP_ENABLE: {
generateDepthClipEnable(object->_commands, state.isDepthClipEnable());
break;
}
case State::SCISSOR_ENABLE: {
generateScissorEnable(object->_commands, state.isScissorEnable());
break;
}
case State::MULTISAMPLE_ENABLE: {
generateMultisampleEnable(object->_commands, state.isMultisampleEnable());
break;
}
case State::ANTIALISED_LINE_ENABLE: {
generateAntialiasedLineEnable(object->_commands, state.isAntialiasedLineEnable());
break;
}
case State::DEPTH_TEST: {
generateDepthTest(object->_commands, state.getDepthTest());
break;
}
case State::STENCIL_ACTIVATION:
case State::STENCIL_TEST_FRONT:
case State::STENCIL_TEST_BACK: {
stencilState = true;
break;
}
case State::SAMPLE_MASK: {
generateSampleMask(object->_commands, state.getSampleMask());
break;
}
case State::ALPHA_TO_COVERAGE_ENABLE: {
generateAlphaToCoverageEnable(object->_commands, state.isAlphaToCoverageEnabled());
break;
}
case State::BLEND_FUNCTION: {
generateBlend(object->_commands, state);
break;
}
case State::COLOR_WRITE_MASK: {
generateColorWriteMask(object->_commands, state.getColorWriteMask());
break;
}
}
}
}
/*
for (auto field: state.getFields()) {
switch(field.first) {
case State::FILL_MODE: {
@ -210,7 +280,7 @@ GLBackend::GLState* GLBackend::syncGPUObject(const State& state) {
}
}
*/
if (depthBias) {
generateDepthBias(object->_commands, state);
}
@ -222,7 +292,7 @@ GLBackend::GLState* GLBackend::syncGPUObject(const State& state) {
return object;
}
void GLBackend::resetPipelineState(State::Signature nextSignature) {
auto currentNotSignature = ~_pipeline._stateSignatureCache;
auto nextNotSignature = ~nextSignature;
@ -238,196 +308,199 @@ void GLBackend::resetPipelineState(State::Signature nextSignature) {
}
State::ComparisonFunction comparisonFuncFromGL(GLenum func) {
if (func == GL_NEVER) {
return State::NEVER;
} else if (func == GL_LESS) {
return State::LESS;
} else if (func == GL_EQUAL) {
return State::EQUAL;
} else if (func == GL_LEQUAL) {
return State::LESS_EQUAL;
} else if (func == GL_GREATER) {
return State::GREATER;
} else if (func == GL_NOTEQUAL) {
return State::NOT_EQUAL;
} else if (func == GL_GEQUAL) {
return State::GREATER_EQUAL;
} else if (func == GL_ALWAYS) {
return State::ALWAYS;
}
if (func == GL_NEVER) {
return State::NEVER;
} else if (func == GL_LESS) {
return State::LESS;
} else if (func == GL_EQUAL) {
return State::EQUAL;
} else if (func == GL_LEQUAL) {
return State::LESS_EQUAL;
} else if (func == GL_GREATER) {
return State::GREATER;
} else if (func == GL_NOTEQUAL) {
return State::NOT_EQUAL;
} else if (func == GL_GEQUAL) {
return State::GREATER_EQUAL;
} else if (func == GL_ALWAYS) {
return State::ALWAYS;
}
return State::ALWAYS;
}
State::StencilOp stencilOpFromGL(GLenum stencilOp) {
if (stencilOp == GL_KEEP) {
return State::STENCIL_OP_KEEP;
} else if (stencilOp == GL_ZERO) {
return State::STENCIL_OP_ZERO;
} else if (stencilOp == GL_REPLACE) {
return State::STENCIL_OP_REPLACE;
} else if (stencilOp == GL_INCR_WRAP) {
return State::STENCIL_OP_INCR_SAT;
} else if (stencilOp == GL_DECR_WRAP) {
return State::STENCIL_OP_DECR_SAT;
} else if (stencilOp == GL_INVERT) {
return State::STENCIL_OP_INVERT;
} else if (stencilOp == GL_INCR) {
return State::STENCIL_OP_INCR;
} else if (stencilOp == GL_DECR) {
return State::STENCIL_OP_DECR;
}
return State::STENCIL_OP_KEEP;
}
if (stencilOp == GL_KEEP) {
return State::STENCIL_OP_KEEP;
} else if (stencilOp == GL_ZERO) {
return State::STENCIL_OP_ZERO;
} else if (stencilOp == GL_REPLACE) {
return State::STENCIL_OP_REPLACE;
} else if (stencilOp == GL_INCR_WRAP) {
return State::STENCIL_OP_INCR_SAT;
} else if (stencilOp == GL_DECR_WRAP) {
return State::STENCIL_OP_DECR_SAT;
} else if (stencilOp == GL_INVERT) {
return State::STENCIL_OP_INVERT;
} else if (stencilOp == GL_INCR) {
return State::STENCIL_OP_INCR;
} else if (stencilOp == GL_DECR) {
return State::STENCIL_OP_DECR;
}
return State::STENCIL_OP_KEEP;
}
State::BlendOp blendOpFromGL(GLenum blendOp) {
if (blendOp == GL_FUNC_ADD) {
return State::BLEND_OP_ADD;
} else if (blendOp == GL_FUNC_SUBTRACT) {
return State::BLEND_OP_SUBTRACT;
} else if (blendOp == GL_FUNC_REVERSE_SUBTRACT) {
return State::BLEND_OP_REV_SUBTRACT;
} else if (blendOp == GL_MIN) {
return State::BLEND_OP_MIN;
} else if (blendOp == GL_MAX) {
return State::BLEND_OP_MAX;
}
if (blendOp == GL_FUNC_ADD) {
return State::BLEND_OP_ADD;
} else if (blendOp == GL_FUNC_SUBTRACT) {
return State::BLEND_OP_SUBTRACT;
} else if (blendOp == GL_FUNC_REVERSE_SUBTRACT) {
return State::BLEND_OP_REV_SUBTRACT;
} else if (blendOp == GL_MIN) {
return State::BLEND_OP_MIN;
} else if (blendOp == GL_MAX) {
return State::BLEND_OP_MAX;
}
return State::BLEND_OP_ADD;
}
State::BlendArg blendArgFromGL(GLenum blendArg) {
if (blendArg == GL_ZERO) {
return State::ZERO;
} else if (blendArg == GL_ONE) {
return State::ONE;
} else if (blendArg == GL_SRC_COLOR) {
return State::SRC_COLOR;
} else if (blendArg == GL_ONE_MINUS_SRC_COLOR) {
return State::INV_SRC_COLOR;
} else if (blendArg == GL_DST_COLOR) {
return State::DEST_COLOR;
} else if (blendArg == GL_ONE_MINUS_DST_COLOR) {
return State::INV_DEST_COLOR;
} else if (blendArg == GL_SRC_ALPHA) {
if (blendArg == GL_ZERO) {
return State::ZERO;
} else if (blendArg == GL_ONE) {
return State::ONE;
} else if (blendArg == GL_SRC_COLOR) {
return State::SRC_COLOR;
} else if (blendArg == GL_ONE_MINUS_SRC_COLOR) {
return State::INV_SRC_COLOR;
} else if (blendArg == GL_DST_COLOR) {
return State::DEST_COLOR;
} else if (blendArg == GL_ONE_MINUS_DST_COLOR) {
return State::INV_DEST_COLOR;
} else if (blendArg == GL_SRC_ALPHA) {
return State::SRC_ALPHA;
} else if (blendArg == GL_ONE_MINUS_SRC_ALPHA) {
} else if (blendArg == GL_ONE_MINUS_SRC_ALPHA) {
return State::INV_SRC_ALPHA;
} else if (blendArg == GL_DST_ALPHA) {
} else if (blendArg == GL_DST_ALPHA) {
return State::DEST_ALPHA;
} else if (blendArg == GL_ONE_MINUS_DST_ALPHA) {
} else if (blendArg == GL_ONE_MINUS_DST_ALPHA) {
return State::INV_DEST_ALPHA;
} else if (blendArg == GL_CONSTANT_COLOR) {
} else if (blendArg == GL_CONSTANT_COLOR) {
return State::FACTOR_COLOR;
} else if (blendArg == GL_ONE_MINUS_CONSTANT_COLOR) {
} else if (blendArg == GL_ONE_MINUS_CONSTANT_COLOR) {
return State::INV_FACTOR_COLOR;
} else if (blendArg == GL_CONSTANT_ALPHA) {
} else if (blendArg == GL_CONSTANT_ALPHA) {
return State::FACTOR_ALPHA;
} else if (blendArg == GL_ONE_MINUS_CONSTANT_ALPHA) {
} else if (blendArg == GL_ONE_MINUS_CONSTANT_ALPHA) {
return State::INV_FACTOR_ALPHA;
}
return State::ONE;
}
void GLBackend::getCurrentGLState(State::Cache& state) {
{
GLint modes[2];
glGetIntegerv(GL_POLYGON_MODE, modes);
if (modes[0] == GL_FILL) {
state.fillMode = State::FILL_FACE;
} else {
if (modes[0] == GL_LINE) {
state.fillMode = State::FILL_LINE;
} else {
state.fillMode = State::FILL_POINT;
}
}
}
{
if (glIsEnabled(GL_CULL_FACE)) {
GLint mode;
glGetIntegerv(GL_CULL_FACE_MODE, &mode);
state.cullMode = (mode == GL_FRONT ? State::CULL_FRONT : State::CULL_BACK);
} else {
state.cullMode = State::CULL_NONE;
}
}
{
GLint winding;
glGetIntegerv(GL_FRONT_FACE, &winding);
state.frontFaceClockwise = (winding == GL_CW);
state.depthClipEnable = glIsEnabled(GL_DEPTH_CLAMP);
state.scissorEnable = glIsEnabled(GL_SCISSOR_TEST);
state.multisampleEnable = glIsEnabled(GL_MULTISAMPLE);
state.antialisedLineEnable = glIsEnabled(GL_LINE_SMOOTH);
}
{
if (glIsEnabled(GL_POLYGON_OFFSET_FILL)) {
glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &state.depthBiasSlopeScale);
glGetFloatv(GL_POLYGON_OFFSET_UNITS, &state.depthBias);
}
}
{
GLboolean isEnabled = glIsEnabled(GL_DEPTH_TEST);
GLboolean writeMask;
glGetBooleanv(GL_DEPTH_WRITEMASK, &writeMask);
GLint func;
glGetIntegerv(GL_DEPTH_FUNC, &func);
state.depthTest = State::DepthTest(isEnabled, writeMask, comparisonFuncFromGL(func));
}
{
GLboolean isEnabled = glIsEnabled(GL_STENCIL_TEST);
GLint frontWriteMask;
GLint frontReadMask;
GLint frontRef;
GLint frontFail;
GLint frontDepthFail;
GLint frontPass;
GLint frontFunc;
glGetIntegerv(GL_STENCIL_WRITEMASK, &frontWriteMask);
glGetIntegerv(GL_STENCIL_VALUE_MASK, &frontReadMask);
glGetIntegerv(GL_STENCIL_REF, &frontRef);
glGetIntegerv(GL_STENCIL_FAIL, &frontFail);
glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &frontDepthFail);
glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &frontPass);
glGetIntegerv(GL_STENCIL_FUNC, &frontFunc);
GLint backWriteMask;
GLint backReadMask;
GLint backRef;
GLint backFail;
GLint backDepthFail;
GLint backPass;
GLint backFunc;
glGetIntegerv(GL_STENCIL_BACK_WRITEMASK, &backWriteMask);
glGetIntegerv(GL_STENCIL_BACK_VALUE_MASK, &backReadMask);
glGetIntegerv(GL_STENCIL_BACK_REF, &backRef);
glGetIntegerv(GL_STENCIL_BACK_FAIL, &backFail);
glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &backDepthFail);
glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS, &backPass);
glGetIntegerv(GL_STENCIL_BACK_FUNC, &backFunc);
state.stencilActivation = State::StencilActivation(isEnabled, frontWriteMask, backWriteMask);
state.stencilTestFront = State::StencilTest(frontRef, frontReadMask, comparisonFuncFromGL(frontFunc), stencilOpFromGL(frontFail), stencilOpFromGL(frontDepthFail), stencilOpFromGL(frontPass));
state.stencilTestBack = State::StencilTest(backRef, backReadMask, comparisonFuncFromGL(backFunc), stencilOpFromGL(backFail), stencilOpFromGL(backDepthFail), stencilOpFromGL(backPass));
}
{
void GLBackend::getCurrentGLState(State::Cache& state) {
{
GLint modes[2];
glGetIntegerv(GL_POLYGON_MODE, modes);
if (modes[0] == GL_FILL) {
state.fillMode = State::FILL_FACE;
} else {
if (modes[0] == GL_LINE) {
state.fillMode = State::FILL_LINE;
} else {
state.fillMode = State::FILL_POINT;
}
}
}
{
if (glIsEnabled(GL_CULL_FACE)) {
GLint mode;
glGetIntegerv(GL_CULL_FACE_MODE, &mode);
state.cullMode = (mode == GL_FRONT ? State::CULL_FRONT : State::CULL_BACK);
} else {
state.cullMode = State::CULL_NONE;
}
}
{
GLint winding;
glGetIntegerv(GL_FRONT_FACE, &winding);
state.frontFaceClockwise = (winding == GL_CW);
state.depthClipEnable = glIsEnabled(GL_DEPTH_CLAMP);
state.scissorEnable = glIsEnabled(GL_SCISSOR_TEST);
state.multisampleEnable = glIsEnabled(GL_MULTISAMPLE);
state.antialisedLineEnable = glIsEnabled(GL_LINE_SMOOTH);
}
{
if (glIsEnabled(GL_POLYGON_OFFSET_FILL)) {
glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &state.depthBiasSlopeScale);
glGetFloatv(GL_POLYGON_OFFSET_UNITS, &state.depthBias);
}
}
{
GLboolean isEnabled = glIsEnabled(GL_DEPTH_TEST);
GLboolean writeMask;
glGetBooleanv(GL_DEPTH_WRITEMASK, &writeMask);
GLint func;
glGetIntegerv(GL_DEPTH_FUNC, &func);
state.depthTest = State::DepthTest(isEnabled, writeMask, comparisonFuncFromGL(func));
}
{
GLboolean isEnabled = glIsEnabled(GL_STENCIL_TEST);
GLint frontWriteMask;
GLint frontReadMask;
GLint frontRef;
GLint frontFail;
GLint frontDepthFail;
GLint frontPass;
GLint frontFunc;
glGetIntegerv(GL_STENCIL_WRITEMASK, &frontWriteMask);
glGetIntegerv(GL_STENCIL_VALUE_MASK, &frontReadMask);
glGetIntegerv(GL_STENCIL_REF, &frontRef);
glGetIntegerv(GL_STENCIL_FAIL, &frontFail);
glGetIntegerv(GL_STENCIL_PASS_DEPTH_FAIL, &frontDepthFail);
glGetIntegerv(GL_STENCIL_PASS_DEPTH_PASS, &frontPass);
glGetIntegerv(GL_STENCIL_FUNC, &frontFunc);
GLint backWriteMask;
GLint backReadMask;
GLint backRef;
GLint backFail;
GLint backDepthFail;
GLint backPass;
GLint backFunc;
glGetIntegerv(GL_STENCIL_BACK_WRITEMASK, &backWriteMask);
glGetIntegerv(GL_STENCIL_BACK_VALUE_MASK, &backReadMask);
glGetIntegerv(GL_STENCIL_BACK_REF, &backRef);
glGetIntegerv(GL_STENCIL_BACK_FAIL, &backFail);
glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_FAIL, &backDepthFail);
glGetIntegerv(GL_STENCIL_BACK_PASS_DEPTH_PASS, &backPass);
glGetIntegerv(GL_STENCIL_BACK_FUNC, &backFunc);
state.stencilActivation = State::StencilActivation(isEnabled, frontWriteMask, backWriteMask);
state.stencilTestFront = State::StencilTest(frontRef, frontReadMask, comparisonFuncFromGL(frontFunc), stencilOpFromGL(frontFail), stencilOpFromGL(frontDepthFail), stencilOpFromGL(frontPass));
state.stencilTestBack = State::StencilTest(backRef, backReadMask, comparisonFuncFromGL(backFunc), stencilOpFromGL(backFail), stencilOpFromGL(backDepthFail), stencilOpFromGL(backPass));
}
{
GLint mask = 0xFFFFFFFF;
if (glIsEnabled(GL_SAMPLE_MASK)) {
glGetIntegerv(GL_SAMPLE_MASK, &mask);
state.sampleMask = mask;
}
state.sampleMask = mask;
}
{
#ifdef GPU_PROFILE_CORE
if (glIsEnabled(GL_SAMPLE_MASK)) {
glGetIntegerv(GL_SAMPLE_MASK, &mask);
state.sampleMask = mask;
}
#endif
state.sampleMask = mask;
}
{
state.alphaToCoverageEnable = glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE);
}
{
GLboolean isEnabled = glIsEnabled(GL_BLEND);
GLboolean isEnabled = glIsEnabled(GL_BLEND);
GLint srcRGB;
GLint srcA;
GLint dstRGB;
@ -448,34 +521,34 @@ void GLBackend::getCurrentGLState(State::Cache& state) {
}
{
GLboolean mask[4];
glGetBooleanv(GL_COLOR_WRITEMASK, mask);
state.colorWriteMask = (mask[0] ? State::WRITE_RED : 0)
| (mask[1] ? State::WRITE_GREEN : 0)
| (mask[2] ? State::WRITE_BLUE : 0)
glGetBooleanv(GL_COLOR_WRITEMASK, mask);
state.colorWriteMask = (mask[0] ? State::WRITE_RED : 0)
| (mask[1] ? State::WRITE_GREEN : 0)
| (mask[2] ? State::WRITE_BLUE : 0)
| (mask[3] ? State::WRITE_ALPHA : 0);
}
}
CHECK_GL_ERROR();
}
void GLBackend::syncPipelineStateCache() {
State::Cache state;
CHECK_GL_ERROR();
}
getCurrentGLState(state);
State::Signature signature = State::evalSignature(state);
_pipeline._stateCache = state;
_pipeline._stateSignatureCache = signature;
}
static GLenum GL_COMPARISON_FUNCTIONS[] = {
GL_NEVER,
GL_LESS,
GL_EQUAL,
GL_LEQUAL,
GL_GREATER,
GL_NOTEQUAL,
GL_GEQUAL,
void GLBackend::syncPipelineStateCache() {
State::Cache state;
getCurrentGLState(state);
State::Signature signature = State::evalSignature(state);
_pipeline._stateCache = state;
_pipeline._stateSignatureCache = signature;
}
static GLenum GL_COMPARISON_FUNCTIONS[] = {
GL_NEVER,
GL_LESS,
GL_EQUAL,
GL_LEQUAL,
GL_GREATER,
GL_NOTEQUAL,
GL_GEQUAL,
GL_ALWAYS };
void GLBackend::do_setStateFillMode(int32 mode) {
@ -488,15 +561,15 @@ void GLBackend::do_setStateFillMode(int32 mode) {
}
}
void GLBackend::do_setStateCullMode(int32 mode) {
void GLBackend::do_setStateCullMode(int32 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]);
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();
@ -587,12 +660,12 @@ void GLBackend::do_setStateDepthBias(Vec2 bias) {
void GLBackend::do_setStateDepthTest(State::DepthTest test) {
if (_pipeline._stateCache.depthTest != test) {
if (test.isEnabled()) {
glEnable(GL_DEPTH_TEST);
if (test.isEnabled()) {
glEnable(GL_DEPTH_TEST);
glDepthMask(test.getWriteMask());
glDepthFunc(GL_COMPARISON_FUNCTIONS[test.getFunction()]);
} else {
glDisable(GL_DEPTH_TEST);
} else {
glDisable(GL_DEPTH_TEST);
}
CHECK_GL_ERROR();
@ -611,14 +684,14 @@ void GLBackend::do_setStateStencil(State::StencilActivation activation, State::S
glStencilMaskSeparate(GL_FRONT, activation.getWriteMaskFront());
glStencilMaskSeparate(GL_BACK, activation.getWriteMaskBack());
static GLenum STENCIL_OPS[] = {
GL_KEEP,
GL_ZERO,
GL_REPLACE,
GL_INCR_WRAP,
GL_DECR_WRAP,
GL_INVERT,
GL_INCR,
static GLenum STENCIL_OPS[] = {
GL_KEEP,
GL_ZERO,
GL_REPLACE,
GL_INCR_WRAP,
GL_DECR_WRAP,
GL_INVERT,
GL_INCR,
GL_DECR };
glStencilFuncSeparate(GL_FRONT, STENCIL_OPS[frontTest.getFailOp()], STENCIL_OPS[frontTest.getPassOp()], STENCIL_OPS[frontTest.getDepthFailOp()]);
@ -651,12 +724,14 @@ void GLBackend::do_setStateAlphaToCoverageEnable(bool enable) {
void GLBackend::do_setStateSampleMask(uint32 mask) {
if (_pipeline._stateCache.sampleMask != mask) {
#ifdef GPU_CORE_PROFILE
if (mask == 0xFFFFFFFF) {
glDisable(GL_SAMPLE_MASK);
} else {
glEnable(GL_SAMPLE_MASK);
glSampleMaski(0, mask);
}
#endif
_pipeline._stateCache.sampleMask = mask;
}
}
@ -666,35 +741,35 @@ void GLBackend::do_setStateBlend(State::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 };
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,
};
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()],
glBlendFuncSeparate(BLEND_ARGS[function.getSourceColor()], BLEND_ARGS[function.getDestinationColor()],
BLEND_ARGS[function.getSourceAlpha()], BLEND_ARGS[function.getDestinationAlpha()]);
CHECK_GL_ERROR();
} else {

View file

@ -1,33 +1,34 @@
//
// Pipeline.h
// libraries/gpu/src/gpu
//
// Created by Sam Gateau on 3/8/2015.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_gpu_State_h
#define hifi_gpu_State_h
#include "Format.h"
#include <memory>
#include <unordered_map>
#include <bitset>
namespace gpu {
class GPUObject;
class State {
public:
State();
virtual ~State();
const Stamp getStamp() const { return _stamp; }
//
// State
// libraries/gpu/src/gpu
//
// Created by Sam Gateau on 3/8/2015.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_gpu_State_h
#define hifi_gpu_State_h
#include "Format.h"
#include <memory>
#include <vector>
#include <unordered_map>
#include <bitset>
namespace gpu {
class GPUObject;
class State {
public:
State();
virtual ~State();
const Stamp getStamp() const { return _stamp; }
enum ComparisonFunction {
NEVER = 0,
@ -57,7 +58,7 @@ public:
NUM_CULL_MODES,
};
enum StencilOp {
STENCIL_OP_KEEP = 0,
STENCIL_OP_ZERO,
@ -69,8 +70,8 @@ public:
STENCIL_OP_DECR,
NUM_STENCIL_OPS,
};
};
enum BlendArg {
ZERO = 0,
ONE,
@ -110,152 +111,228 @@ public:
WRITE_ALPHA = 8,
WRITE_ALL = (WRITE_RED | WRITE_GREEN | WRITE_BLUE | WRITE_ALPHA ),
};
class DepthTest {
uint8 _function = LESS;
bool _writeMask = true;
bool _enabled = false;
public:
DepthTest(bool enabled, bool writeMask, ComparisonFunction func) :
_function(func), _writeMask(writeMask), _enabled(enabled) {}
bool isEnabled() const { return _enabled; }
ComparisonFunction getFunction() const { return ComparisonFunction(_function); }
bool getWriteMask() const { return _writeMask; }
int32 getRaw() const { return *(reinterpret_cast<const int32*>(this)); }
DepthTest(int32 raw) { *(reinterpret_cast<int32*>(this)) = raw; }
bool operator== (const DepthTest& right) const { return getRaw() == right.getRaw(); }
bool operator!= (const DepthTest& right) const { return getRaw() != right.getRaw(); }
};
class DepthTest {
uint8 _function = LESS;
bool _writeMask = true;
bool _enabled = false;
public:
DepthTest(bool enabled, bool writeMask, ComparisonFunction func) :
_function(func), _writeMask(writeMask), _enabled(enabled) {}
bool isEnabled() const { return _enabled; }
ComparisonFunction getFunction() const { return ComparisonFunction(_function); }
bool getWriteMask() const { return _writeMask; }
int32 getRaw() const { return *(reinterpret_cast<const int32*>(this)); }
DepthTest(int32 raw) { *(reinterpret_cast<int32*>(this)) = raw; }
bool operator== (const DepthTest& right) const { return getRaw() == right.getRaw(); }
bool operator!= (const DepthTest& right) const { return getRaw() != right.getRaw(); }
};
class StencilTest {
static const int FUNC_MASK = 0x000f;
static const int FAIL_OP_MASK = 0x00f0;
static const int DEPTH_FAIL_OP_MASK = 0x0f00;
static const int PASS_OP_MASK = 0xf000;
static const int FAIL_OP_MASK = 0x00f0;
static const int DEPTH_FAIL_OP_MASK = 0x0f00;
static const int PASS_OP_MASK = 0xf000;
static const int FAIL_OP_OFFSET = 4;
static const int DEPTH_FAIL_OP_OFFSET = 8;
static const int PASS_OP_OFFSET = 12;
uint16 _functionAndOperations;
uint8 _reference = 0;
uint8 _readMask = 0xff;
public:
StencilTest(uint8 reference = 0, uint8 readMask =0xFF, ComparisonFunction func = ALWAYS, StencilOp failOp = STENCIL_OP_KEEP, StencilOp depthFailOp = STENCIL_OP_KEEP, StencilOp passOp = STENCIL_OP_KEEP) :
_reference(reference), _readMask(readMask),
_functionAndOperations(func | (failOp << FAIL_OP_OFFSET) | (depthFailOp << DEPTH_FAIL_OP_OFFSET) | (passOp << PASS_OP_OFFSET)) {}
ComparisonFunction getFunction() const { return ComparisonFunction(_functionAndOperations & FUNC_MASK); }
StencilOp getFailOp() const { return StencilOp((_functionAndOperations & FAIL_OP_MASK) >> FAIL_OP_OFFSET); }
StencilOp getDepthFailOp() const { return StencilOp((_functionAndOperations & DEPTH_FAIL_OP_MASK) >> DEPTH_FAIL_OP_OFFSET); }
StencilOp getPassOp() const { return StencilOp((_functionAndOperations & PASS_OP_MASK) >> PASS_OP_OFFSET); }
uint8 getReference() const { return _reference; }
uint8 getReadMask() const { return _readMask; }
int32 getRaw() const { return *(reinterpret_cast<const int32*>(this)); }
StencilTest(int32 raw) { *(reinterpret_cast<int32*>(this)) = raw; }
bool operator== (const StencilTest& right) const { return getRaw() == right.getRaw(); }
bool operator!= (const StencilTest& right) const { return getRaw() != right.getRaw(); }
};
class StencilActivation {
uint8 _frontWriteMask = 0xFF;
uint8 _backWriteMask = 0xFF;
uint16 _enabled = 0;
public:
StencilActivation(bool enabled, uint8 frontWriteMask = 0xFF, uint8 backWriteMask = 0xFF) :
_frontWriteMask(frontWriteMask), _backWriteMask(backWriteMask), _enabled(enabled) {}
bool isEnabled() const { return (_enabled != 0); }
uint8 getWriteMaskFront() const { return _frontWriteMask; }
uint8 getWriteMaskBack() const { return _backWriteMask; }
int32 getRaw() const { return *(reinterpret_cast<const int32*>(this)); }
StencilActivation(int32 raw) { *(reinterpret_cast<int32*>(this)) = raw; }
bool operator== (const StencilActivation& right) const { return getRaw() == right.getRaw(); }
bool operator!= (const StencilActivation& right) const { return getRaw() != right.getRaw(); }
};
class BlendFunction {
static const int PASS_OP_OFFSET = 12;
uint16 _functionAndOperations;
uint8 _reference = 0;
uint8 _readMask = 0xff;
public:
StencilTest(uint8 reference = 0, uint8 readMask =0xFF, ComparisonFunction func = ALWAYS, StencilOp failOp = STENCIL_OP_KEEP, StencilOp depthFailOp = STENCIL_OP_KEEP, StencilOp passOp = STENCIL_OP_KEEP) :
_functionAndOperations(func | (failOp << FAIL_OP_OFFSET) | (depthFailOp << DEPTH_FAIL_OP_OFFSET) | (passOp << PASS_OP_OFFSET)),
_reference(reference), _readMask(readMask)
{}
ComparisonFunction getFunction() const { return ComparisonFunction(_functionAndOperations & FUNC_MASK); }
StencilOp getFailOp() const { return StencilOp((_functionAndOperations & FAIL_OP_MASK) >> FAIL_OP_OFFSET); }
StencilOp getDepthFailOp() const { return StencilOp((_functionAndOperations & DEPTH_FAIL_OP_MASK) >> DEPTH_FAIL_OP_OFFSET); }
StencilOp getPassOp() const { return StencilOp((_functionAndOperations & PASS_OP_MASK) >> PASS_OP_OFFSET); }
uint8 getReference() const { return _reference; }
uint8 getReadMask() const { return _readMask; }
int32 getRaw() const { return *(reinterpret_cast<const int32*>(this)); }
StencilTest(int32 raw) { *(reinterpret_cast<int32*>(this)) = raw; }
bool operator== (const StencilTest& right) const { return getRaw() == right.getRaw(); }
bool operator!= (const StencilTest& right) const { return getRaw() != right.getRaw(); }
};
class StencilActivation {
uint8 _frontWriteMask = 0xFF;
uint8 _backWriteMask = 0xFF;
uint16 _enabled = 0;
public:
StencilActivation(bool enabled, uint8 frontWriteMask = 0xFF, uint8 backWriteMask = 0xFF) :
_frontWriteMask(frontWriteMask), _backWriteMask(backWriteMask), _enabled(enabled) {}
bool isEnabled() const { return (_enabled != 0); }
uint8 getWriteMaskFront() const { return _frontWriteMask; }
uint8 getWriteMaskBack() const { return _backWriteMask; }
int32 getRaw() const { return *(reinterpret_cast<const int32*>(this)); }
StencilActivation(int32 raw) { *(reinterpret_cast<int32*>(this)) = raw; }
bool operator== (const StencilActivation& right) const { return getRaw() == right.getRaw(); }
bool operator!= (const StencilActivation& right) const { return getRaw() != right.getRaw(); }
};
class BlendFunction {
static const int COLOR_MASK = 0x0f;
static const int ALPHA_MASK = 0xf0;
static const int ALPHA_MASK = 0xf0;
static const int ALPHA_OFFSET = 4;
uint8 _enabled;
uint8 _enabled;
uint8 _source;
uint8 _destination;
uint8 _destination;
uint8 _operation;
public:
BlendFunction(bool enabled,
BlendArg sourceColor, BlendOp operationColor, BlendArg destinationColor,
BlendArg sourceAlpha, BlendOp operationAlpha, BlendArg destinationAlpha) :
_enabled(enabled),
_source(sourceColor | (sourceAlpha << ALPHA_OFFSET)),
_destination(destinationColor | (destinationAlpha << ALPHA_OFFSET)),
_operation(operationColor | (operationAlpha << ALPHA_OFFSET)) {}
BlendFunction(bool enabled, BlendArg source = ONE, BlendOp operation = BLEND_OP_ADD, BlendArg destination = ZERO) :
_enabled(enabled),
_source(source | (source << ALPHA_OFFSET)),
_destination(destination | (destination << ALPHA_OFFSET)),
_operation(operation | (operation << ALPHA_OFFSET)) {}
bool isEnabled() const { return (_enabled != 0); }
BlendArg getSourceColor() const { return BlendArg(_source & COLOR_MASK); }
BlendArg getDestinationColor() const { return BlendArg(_destination & COLOR_MASK); }
BlendOp getOperationColor() const { return BlendOp(_operation & COLOR_MASK); }
BlendArg getSourceAlpha() const { return BlendArg((_source & ALPHA_MASK) >> ALPHA_OFFSET); }
BlendArg getDestinationAlpha() const { return BlendArg((_destination & ALPHA_MASK) >> ALPHA_OFFSET); }
BlendOp getOperationAlpha() const { return BlendOp((_operation & ALPHA_MASK) >> ALPHA_OFFSET); }
int32 getRaw() const { return *(reinterpret_cast<const int32*>(this)); }
BlendFunction(int32 raw) { *(reinterpret_cast<int32*>(this)) = raw; }
bool operator== (const BlendFunction& right) const { return getRaw() == right.getRaw(); }
bool operator!= (const BlendFunction& right) const { 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 = false;
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;
BlendFunction(bool enabled,
BlendArg sourceColor, BlendOp operationColor, BlendArg destinationColor,
BlendArg sourceAlpha, BlendOp operationAlpha, BlendArg destinationAlpha) :
_enabled(enabled),
_source(sourceColor | (sourceAlpha << ALPHA_OFFSET)),
_destination(destinationColor | (destinationAlpha << ALPHA_OFFSET)),
_operation(operationColor | (operationAlpha << ALPHA_OFFSET)) {}
BlendFunction(bool enabled, BlendArg source = ONE, BlendOp operation = BLEND_OP_ADD, BlendArg destination = ZERO) :
_enabled(enabled),
_source(source | (source << ALPHA_OFFSET)),
_destination(destination | (destination << ALPHA_OFFSET)),
_operation(operation | (operation << ALPHA_OFFSET)) {}
bool isEnabled() const { return (_enabled != 0); }
BlendArg getSourceColor() const { return BlendArg(_source & COLOR_MASK); }
BlendArg getDestinationColor() const { return BlendArg(_destination & COLOR_MASK); }
BlendOp getOperationColor() const { return BlendOp(_operation & COLOR_MASK); }
BlendArg getSourceAlpha() const { return BlendArg((_source & ALPHA_MASK) >> ALPHA_OFFSET); }
BlendArg getDestinationAlpha() const { return BlendArg((_destination & ALPHA_MASK) >> ALPHA_OFFSET); }
BlendOp getOperationAlpha() const { return BlendOp((_operation & ALPHA_MASK) >> ALPHA_OFFSET); }
int32 getRaw() const { return *(reinterpret_cast<const int32*>(this)); }
BlendFunction(int32 raw) { *(reinterpret_cast<int32*>(this)) = raw; }
bool operator== (const BlendFunction& right) const { return getRaw() == right.getRaw(); }
bool operator!= (const BlendFunction& right) const { 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 = false;
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, _values.fillMode); }
FillMode getFillMode() const { return _values.fillMode; }
void setCullMode(CullMode cull) { set(CULL_MODE, DEFAULT.cullMode, cull, _values.cullMode); }
CullMode getCullMode() const { return _values.cullMode; }
void setFrontFaceClockwise(bool isClockwise) { set(FRONT_FACE_CLOCKWISE, DEFAULT.frontFaceClockwise, isClockwise, _values.frontFaceClockwise); }
bool isFrontFaceClockwise() const { return _values.frontFaceClockwise; }
void setDepthClipEnable(bool enable) { set(DEPTH_CLIP_ENABLE, DEFAULT.depthClipEnable, enable, _values.depthClipEnable); }
bool isDepthClipEnable() const { return _values.depthClipEnable; }
void setScissorEnable(bool enable) { set(SCISSOR_ENABLE, DEFAULT.scissorEnable, enable, _values.scissorEnable); }
bool isScissorEnable() const { return _values.scissorEnable; }
void setMultisampleEnable(bool enable) { set(MULTISAMPLE_ENABLE, DEFAULT.multisampleEnable, enable, _values.multisampleEnable); }
bool isMultisampleEnable() const { return _values.multisampleEnable; }
void setAntialiasedLineEnable(bool enable) { set(ANTIALISED_LINE_ENABLE, DEFAULT.antialisedLineEnable, enable, _values.antialisedLineEnable); }
bool isAntialiasedLineEnable() const { return _values.antialisedLineEnable; }
// Depth Bias
void setDepthBias(float bias) { set(DEPTH_BIAS, DEFAULT.depthBias, bias, _values.depthBias); }
float getDepthBias() const { return _values.depthBias; }
void setDepthBiasSlopeScale(float scale) { set(DEPTH_BIAS_SLOPE_SCALE, DEFAULT.depthBiasSlopeScale, scale, _values.depthBiasSlopeScale); }
float getDepthBiasSlopeScale() const { return _values.depthBiasSlopeScale; }
// Depth Test
void setDepthTest(DepthTest depthTest) { set(DEPTH_TEST, DEFAULT.depthTest, depthTest, _values.depthTest); }
void setDepthTest(bool enable, bool writeMask, ComparisonFunction func) { setDepthTest(DepthTest(enable, writeMask, func)); }
DepthTest getDepthTest() const { return _values.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), _values.stencilActivation);
set(STENCIL_TEST_FRONT, DEFAULT.stencilTestFront, frontTest, _values.stencilTestFront);
set(STENCIL_TEST_BACK, DEFAULT.stencilTestBack, backTest, _values.stencilTestBack); }
void setStencilTest(bool enabled, uint8 frontWriteMask, StencilTest frontTest) {
setStencilTest(enabled, frontWriteMask, frontTest, frontWriteMask, frontTest); }
StencilActivation getStencilActivation() const { return _values.stencilActivation; }
StencilTest getStencilTestFront() const { return _values.stencilTestFront; }
StencilTest getStencilTestBack() const { return _values.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, _values.alphaToCoverageEnable); }
bool isAlphaToCoverageEnabled() const { return _values.alphaToCoverageEnable; }
// Sample mask
void setSampleMask(uint32 mask) { set(SAMPLE_MASK, DEFAULT.sampleMask, mask, _values.sampleMask); }
uint32 getSampleMask() const { return _values.sampleMask; }
// Blend Function
void setBlendFunction(BlendFunction function) { set(BLEND_FUNCTION, DEFAULT.blendFunction, function, _values.blendFunction); }
BlendFunction getBlendFunction() const { return _values.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, _values.colorWriteMask); }
uint32 getColorWriteMask() const { return _values.colorWriteMask; }
/*
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); }
@ -273,14 +350,14 @@ public:
void setAntialiasedLineEnable(bool enable) { set(ANTIALISED_LINE_ENABLE, DEFAULT.antialisedLineEnable, enable); }
bool isAntialiasedLineEnable() const { return get(ANTIALISED_LINE_ENABLE, DEFAULT.antialisedLineEnable); }
// Depth Bias
// 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)); }
@ -307,7 +384,7 @@ public:
uint8 getStencilWriteMaskBack() const { return getStencilActivation().getWriteMaskBack(); }
// Alpha to coverage
void setAlphaToCoverageEnable(bool enable) { set(ALPHA_TO_COVERAGE_ENABLE, DEFAULT.alphaToCoverageEnable, enable); }
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
@ -323,124 +400,138 @@ public:
void setBlendFunction(bool enabled, BlendArg source, BlendOp operation, BlendArg destination) {
setBlendFunction(BlendFunction(enabled, source, operation, destination)); }
bool isBlendEnabled() const { return getBlendFunction().isEnabled(); }
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 {
uint32 _unsigned_integer = 0;
int32 _integer;
float _float;
};
template <typename T> void uncast(T v) { _integer = v; }
template <> void State::Value::uncast<int>(int v) { _integer = v; }
template <> void State::Value::uncast<float>(float v) { _float = v; }
template <> void State::Value::uncast<unsigned int>(unsigned int v) { _unsigned_integer = v; }
template <> void State::Value::uncast<DepthTest>(DepthTest v) { _integer = v.getRaw(); }
template <> void State::Value::uncast<StencilActivation>(StencilActivation v) { _integer = v.getRaw(); }
template <> void State::Value::uncast<StencilTest>(StencilTest v) { _integer = v.getRaw(); }
template <> void State::Value::uncast<BlendFunction>(BlendFunction v) { _integer = v.getRaw(); }
template <typename T> T cast() const;
template <> int State::Value::cast<int>() const { return _integer; }
template <> float State::Value::cast<float>() const { return _float; }
template <> unsigned int State::Value::cast<unsigned int>() const { return _unsigned_integer; }
template <> DepthTest State::Value::cast<DepthTest>() const { return DepthTest(_integer); }
template <> StencilActivation State::Value::cast<StencilActivation>() const { return StencilActivation(_integer); }
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; }
// 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; }
static Signature evalSignature(const Cache& state);
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++;
}
template <class T> T get(Field field, T defaultValue) const {
auto found = _fields.find(field);
if (found != _fields.end()) {
return (*found).second.cast<T>();
}
return defaultValue;
}
FieldMap _fields;
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;
void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; }
GPUObject* getGPUObject() const { return _gpuObject; }
friend class Backend;
};
typedef std::shared_ptr< State > StatePointer;
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 {
uint32 _unsigned_integer = 0;
int32 _integer;
float _float;
};
template <typename T> void uncast(T v) { _integer = v; }
template <typename T> T cast() const { return T(_integer); }
};
// The field map type
typedef std::unordered_map<int32, Value> FieldMap;
const FieldMap& getFields() const { return _fields; }
// 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; }
static Signature evalSignature(const Cache& state);
protected:
State(const State& state);
State& operator=(const State& state);
template <typename T> void set(Field field, T defaultValue, T value, T& dest) {
dest = value;
if (value == defaultValue) {
//_fields.erase(field);
_signature.reset(field);
} else {
//_fields[field].uncast(value);
_signature.set(field);
}
_stamp++;
}
template <typename 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++;
}
template <typename T> T get(Field field, T defaultValue) const {
auto found = _fields.find(field);
if (found != _fields.end()) {
return (*found).second.cast<T>();
}
return defaultValue;
}
FieldMap _fields;
Cache _values;
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;
void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; }
GPUObject* getGPUObject() const { return _gpuObject; }
friend class Backend;
};
template <> void State::Value::uncast<int>(int v) { _integer = v; }
template <> void State::Value::uncast<float>(float v) { _float = v; }
template <> void State::Value::uncast<unsigned int>(unsigned int v) { _unsigned_integer = v; }
template <> void State::Value::uncast<State::DepthTest>(State::DepthTest v) { _integer = v.getRaw(); }
template <> void State::Value::uncast<State::StencilActivation>(State::StencilActivation v) { _integer = v.getRaw(); }
template <> void State::Value::uncast<State::StencilTest>(State::StencilTest v) { _integer = v.getRaw(); }
template <> void State::Value::uncast<State::BlendFunction>(State::BlendFunction v) { _integer = v.getRaw(); }
template <> int State::Value::cast<int>() const { return _integer; }
template <> float State::Value::cast<float>() const { return _float; }
template <> unsigned int State::Value::cast<unsigned int>() const { return _unsigned_integer; }
template <> State::DepthTest State::Value::cast<State::DepthTest>() const { return DepthTest(_integer); }
template <> State::StencilActivation State::Value::cast<State::StencilActivation>() const { return StencilActivation(_integer); }
template <> State::StencilTest State::Value::cast<State::StencilTest>() const { return StencilTest(_integer); }
template <> State::BlendFunction State::Value::cast<State::BlendFunction>() const { return BlendFunction(_integer); }
typedef std::shared_ptr< State > StatePointer;
typedef std::vector< StatePointer > States;
};
#endif
};
#endif

View file

@ -97,7 +97,7 @@ Model::~Model() {
Model::RenderPipelineLib Model::_renderPipelineLib;
const GLint MATERIAL_GPU_SLOT = 3;
void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey& key,
void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key,
gpu::ShaderPointer& vertexShader,
gpu::ShaderPointer& pixelShader ) {
@ -133,12 +133,8 @@ void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey& key,
state->setBlendFunction(key.isTranslucent(),
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
auto it = insert(value_type(key.getRaw(),
RenderPipeline(
gpu::PipelinePointer( gpu::Pipeline::create(program, state) ),
std::shared_ptr<Locations>(locations)
)));
auto pipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, state));
auto it = insert(value_type(key.getRaw(), RenderPipeline(pipeline, std::shared_ptr<Locations>(locations))));
}

View file

@ -505,7 +505,7 @@ private:
public:
gpu::PipelinePointer _pipeline;
std::shared_ptr<Locations> _locations;
RenderPipeline(gpu::PipelinePointer& pipeline, std::shared_ptr<Locations>& locations) :
RenderPipeline(gpu::PipelinePointer pipeline, std::shared_ptr<Locations> locations) :
_pipeline(pipeline), _locations(locations) {}
};
@ -515,7 +515,7 @@ private:
typedef RenderKey Key;
void addRenderPipeline(Key& key, gpu::ShaderPointer& vertexShader, gpu::ShaderPointer& pixelShader);
void addRenderPipeline(Key key, gpu::ShaderPointer& vertexShader, gpu::ShaderPointer& pixelShader);
void initLocations(gpu::ShaderPointer& program, Locations& locations);
};