diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index 1e239f0c56..8276ff5f95 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -82,6 +82,15 @@ public: return reinterpret_cast(pipeline.getGPUObject()); } + template< typename T > + static void setGPUObject(const State& state, T* so) { + state.setGPUObject(so); + } + template< typename T > + static T* getGPUObject(const State& state) { + return reinterpret_cast(state.getGPUObject()); + } + protected: }; diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index 8a754bb564..7f36797374 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -16,6 +16,10 @@ namespace gpu { +class GPUObject; + +typedef int Stamp; + typedef unsigned int uint32; typedef int int32; typedef unsigned short uint16; diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index b2ec284843..bbb2b5a1d2 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -79,18 +79,61 @@ public: public: class Command { public: - typedef void *GlFunction(GLenum); - - GlFunction _glFunction; - GLenum _enum; - void run() { _glFunction(_enum); } + virtual void run() = 0; + + Command() {} + virtual ~Command() {}; }; - typedef std::vector< Command > Commands; + template class Command1 : public Command { + public: + typedef void (*GLFunction)(typename T); + + void run() { (_func)(_param); } + + Command1(GLFunction func, T param) : _func(func), _param(param) {}; + + GLFunction _func; + T _param; + }; + template class Command2 : public Command { + public: + typedef void (*GLFunction)(typename T, typename U); + + void run() { (_func)(_param0, _param1); } + + Command2(GLFunction func, T param0, U param1) : _func(func), _param0(param0), _param1(param1) {}; + + GLFunction _func; + T _param0; + U _param1; + }; + + template class Command4 : public Command { + public: + typedef void (*GLFunction)(typename T, typename U, typename V, typename W); + + void run() { (_func)(_param0, _param1, _param2, _param3); } + + Command4(GLFunction func, T param0, U param1, V param2, W param3) : + _func(func), + _param0(param0), + _param1(param1), + _param2(param2), + _param3(param3) {}; + + GLFunction _func; + T _param0; + U _param1; + V _param2; + W _param3; + }; + typedef std::shared_ptr< Command > CommandPointer; + typedef std::vector< CommandPointer > Commands; Commands _commands; - + Stamp _stamp; GLState(); ~GLState(); @@ -100,6 +143,7 @@ public: class GLPipeline : public GPUObject { public: GLShader* _program; + GLState* _state; GLPipeline(); ~GLPipeline(); @@ -203,14 +247,19 @@ protected: GLuint _program; bool _invalidProgram; + State _state; + GLState::Commands _stateCommands; + bool _invalidState; + PipelineStageState() : _pipeline(), _program(0), - _invalidProgram(false) + _invalidProgram(false), + _state(), + _invalidState(false) {} } _pipeline; - // 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 diff --git a/libraries/gpu/src/gpu/GLBackendPipeline.cpp b/libraries/gpu/src/gpu/GLBackendPipeline.cpp index aee3f009d1..77ec721276 100755 --- a/libraries/gpu/src/gpu/GLBackendPipeline.cpp +++ b/libraries/gpu/src/gpu/GLBackendPipeline.cpp @@ -15,11 +15,13 @@ using namespace gpu; GLBackend::GLPipeline::GLPipeline() : - _program(nullptr) + _program(nullptr), + _state(nullptr) {} GLBackend::GLPipeline::~GLPipeline() { _program = nullptr; + _state = nullptr; } GLBackend::GLPipeline* GLBackend::syncGPUObject(const Pipeline& pipeline) { @@ -30,7 +32,29 @@ GLBackend::GLPipeline* GLBackend::syncGPUObject(const Pipeline& pipeline) { return object; } - return nullptr; + // No object allocated yet, let's see if it's worth it... + ShaderPointer shader = pipeline.getProgram(); + GLShader* programObject = GLBackend::syncGPUObject((*shader)); + if (programObject == nullptr) { + return nullptr; + } + + StatePointer state = pipeline.getState(); + GLState* stateObject = GLBackend::syncGPUObject((*state)); + if (stateObject == nullptr) { + return nullptr; + } + + // Program and state are valid, we can create the pipeline object + if (!object) { + object = new GLPipeline(); + Backend::setGPUObject(pipeline, object); + } + + object->_program = programObject; + object->_state = stateObject; + + return object; } void GLBackend::do_setPipeline(Batch& batch, uint32 paramOffset) { @@ -46,8 +70,15 @@ void GLBackend::do_setPipeline(Batch& batch, uint32 paramOffset) { } _pipeline._pipeline = pipeline; - _pipeline._program = pipelineObject->_program->_program; - _pipeline._invalidProgram = true; + + if (_pipeline._program != pipelineObject->_program->_program) { + _pipeline._program = pipelineObject->_program->_program; + _pipeline._invalidProgram = true; + } + + _pipeline._stateCommands = pipelineObject->_state->_commands; + _pipeline._invalidState = true; + } void GLBackend::do_setUniformBuffer(Batch& batch, uint32 paramOffset) { @@ -86,8 +117,15 @@ void GLBackend::updatePipeline() { if (_pipeline._invalidProgram) { glUseProgram(_pipeline._program); CHECK_GL_ERROR(); + _pipeline._invalidProgram = false; + } - _pipeline._invalidProgram = true; + if (_pipeline._invalidState) { + for (auto command: _pipeline._stateCommands) { + command->run(); + } + CHECK_GL_ERROR(); + _pipeline._invalidState = false; } } diff --git a/libraries/gpu/src/gpu/GLBackendState.cpp b/libraries/gpu/src/gpu/GLBackendState.cpp new file mode 100644 index 0000000000..73ed649e83 --- /dev/null +++ b/libraries/gpu/src/gpu/GLBackendState.cpp @@ -0,0 +1,356 @@ +// +// GLBackendState.cpp +// libraries/gpu/src/gpu +// +// Created by Sam Gateau on 3/22/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 +// +#include "GLBackendShared.h" + +#include "Format.h" + +using namespace gpu; + +GLBackend::GLState::GLState() +{} + +GLBackend::GLState::~GLState() { +} + + +typedef GLBackend::GLState::Command Command; +typedef GLBackend::GLState::CommandPointer CommandPointer; +typedef GLBackend::GLState::Command1 Command1E; +typedef GLBackend::GLState::Command2 Command2E; +typedef GLBackend::GLState::Command2 Command2F; +typedef GLBackend::GLState::Command4 Command4E; +typedef GLBackend::GLState::Command4 Command4F; +typedef GLBackend::GLState::Command4 Command4B; + +static GLenum GL_COMPARISON_FUNCTIONS[] = { + GL_NEVER, + GL_LESS, + GL_EQUAL, + GL_LEQUAL, + GL_GREATER, + GL_NOTEQUAL, + GL_GEQUAL, + GL_ALWAYS }; + +void glBackend_glPolygonMode(GLenum fillMode) { + glPolygonMode(GL_FRONT_AND_BACK, fillMode); +} + +void generateFillMode(GLBackend::GLState::Commands& commands, State::FillMode fillMode) { + static GLenum GL_FILL_MODES[] = { GL_POINT, GL_LINE, GL_FILL }; + commands.push_back(CommandPointer(new Command1E(glBackend_glPolygonMode, GL_FILL_MODES[fillMode]))); +} + +void generateCullMode(GLBackend::GLState::Commands& commands, State::CullMode cullMode) { + static GLenum CULL_MODES[] = { GL_FRONT_AND_BACK, GL_FRONT, GL_BACK }; + if (cullMode == State::CULL_NONE) { + commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDisable, GLenum(GL_CULL_FACE)))); + } else { + commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glEnable, GLenum(GL_CULL_FACE)))); + commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glCullFace, CULL_MODES[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) { + static GLenum GL_FRONT_FACES[] = { GL_CCW, GL_CW }; + commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glFrontFace, GL_FRONT_FACES[frontClockwise]))); +} + +#define ADD_ENABLE_DISABLE_COMMAND( NAME ) if (enable) {\ + commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glEnable, NAME)));\ + } else {\ + commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDisable, NAME)));\ + } + +void generateDepthClipEnable(GLBackend::GLState::Commands& commands, bool enable) { + ADD_ENABLE_DISABLE_COMMAND(GL_DEPTH_CLAMP); +} + +void generateScissorEnable(GLBackend::GLState::Commands& commands, bool enable) { + ADD_ENABLE_DISABLE_COMMAND(GL_SCISSOR_TEST); +} + +void generateMultisampleEnable(GLBackend::GLState::Commands& commands, bool enable) { + ADD_ENABLE_DISABLE_COMMAND(GL_MULTISAMPLE); +} + +void generateAntialiasedLineEnable(GLBackend::GLState::Commands& commands, bool enable) { + ADD_ENABLE_DISABLE_COMMAND(GL_POINT_SMOOTH); + ADD_ENABLE_DISABLE_COMMAND(GL_LINE_SMOOTH); +} + +void generateDepthEnable(GLBackend::GLState::Commands& commands, bool enable) { + ADD_ENABLE_DISABLE_COMMAND(GL_DEPTH_TEST); +} + +void generateDepthWriteMask(GLBackend::GLState::Commands& commands, bool write) { + commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDepthMask, write))); +} + +void generateDepthFunc(GLBackend::GLState::Commands& commands, State::ComparisonFunction function) { + commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDepthFunc, GL_COMPARISON_FUNCTIONS[function]))); +} + +void generateStencilEnable(GLBackend::GLState::Commands& commands, bool enable) { + ADD_ENABLE_DISABLE_COMMAND(GL_STENCIL_TEST); +} + +void generateStencilWriteMask(GLBackend::GLState::Commands& commands, uint32 mask) { + commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glStencilMask, mask))); +} + +void generateStencilState(GLBackend::GLState::Commands& commands, const State& state) { + auto frontTest(state.getStencilTestFront()); + auto backTest(state.getStencilTestBack()); + + commands.push_back(CommandPointer(new Command4E((Command4E::GLFunction)glBlendEquationSeparate, + GL_FRONT, GL_COMPARISON_FUNCTIONS[frontTest._function], state.getStencilReference(), state.getStencilReadMask()))); + commands.push_back(CommandPointer(new Command4E((Command4E::GLFunction)glBlendEquationSeparate, + GL_BACK, GL_COMPARISON_FUNCTIONS[backTest._function], state.getStencilReference(), state.getStencilReadMask()))); + + static GLenum STENCIL_OPS[] = { + GL_KEEP, + GL_ZERO, + GL_REPLACE, + GL_INCR_WRAP, + GL_DECR_WRAP, + GL_INVERT, + GL_INCR, + GL_DECR }; + + commands.push_back(CommandPointer(new Command4E((Command4E::GLFunction)glStencilOpSeparate, + GL_FRONT, STENCIL_OPS[frontTest._failOp], STENCIL_OPS[frontTest._passOp], STENCIL_OPS[frontTest._depthFailOp]))); + commands.push_back(CommandPointer(new Command4E((Command4E::GLFunction)glStencilOpSeparate, + GL_BACK, STENCIL_OPS[backTest._failOp], STENCIL_OPS[backTest._passOp], STENCIL_OPS[backTest._depthFailOp]))); +} + +void generateAlphaToCoverageEnable(GLBackend::GLState::Commands& commands, bool enable) { + ADD_ENABLE_DISABLE_COMMAND(GL_SAMPLE_ALPHA_TO_COVERAGE); +} + +void generateBlendEnable(GLBackend::GLState::Commands& commands, bool enable) { + ADD_ENABLE_DISABLE_COMMAND(GL_BLEND); +} + +void generateBlendFunction(GLBackend::GLState::Commands& commands, const State& state) { + static GLenum GL_BLEND_OPS[] = { + GL_FUNC_ADD, + GL_FUNC_SUBTRACT, + GL_FUNC_REVERSE_SUBTRACT, + GL_MIN, + GL_MAX }; + + auto colorFunction = state.getBlendFunctionColor(); + auto alphaFunction = state.getBlendFunctionColor(); + + commands.push_back(CommandPointer(new Command2E((Command2E::GLFunction)glBlendEquationSeparate, + GL_BLEND_OPS[colorFunction._operation], + GL_BLEND_OPS[alphaFunction._operation]))); + + 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 + }; + + commands.push_back(CommandPointer(new Command4E((Command4E::GLFunction)glBlendFuncSeparate, + BLEND_ARGS[colorFunction._source], + BLEND_ARGS[colorFunction._destination], + BLEND_ARGS[alphaFunction._source], + BLEND_ARGS[alphaFunction._destination]))); +} + +void generateBlendFactor(GLBackend::GLState::Commands& commands, const Vec4& factor) { + commands.push_back(CommandPointer(new Command4F((Command4F::GLFunction)glBlendColor, + factor.x, factor.y, factor.z, factor.w))); +} + +void generateColorWriteMask(GLBackend::GLState::Commands& commands, State::ColorMask mask) { + commands.push_back(CommandPointer(new Command4B((Command4B::GLFunction)glColorMask, + mask & State::ColorMask::WRITE_RED, + mask & State::ColorMask::WRITE_GREEN, + mask & State::ColorMask::WRITE_BLUE, + mask & State::ColorMask::WRITE_ALPHA ))); +} + +GLBackend::GLState* GLBackend::syncGPUObject(const State& state) { + GLState* object = Backend::getGPUObject(state); + + // If GPU object already created then good + if (object) { + if (object->_stamp == state.getStamp()) { + return object; + } + } + + // Else allocate and create the GLState + if (!object) { + object = new GLState(); + Backend::setGPUObject(state, object); + } + + // here, we need to regenerate something so let's do it all + object->_commands.clear(); + object->_stamp = state.getStamp(); + + bool depthBias = false; + + bool depthEnabled = false; + bool depthState = false; + + bool stencilEnabled = false; + bool stencilState = false; + + bool blendEnabled = false; + bool blendFunction = false; + bool blendFactor = false; + + // go thorugh the list of state fields in the State and record the corresponding gl command + for (auto field: state.getFields()) { + switch(field.first) { + case State::FILL_MODE: { + generateFillMode(object->_commands, State::FillMode(field.second._integer)); + break; + } + case State::CULL_MODE: { + generateCullMode(object->_commands, State::CullMode(field.second._integer)); + break; + } + case State::DEPTH_BIAS: + case State::DEPTH_BIAS_SLOPE_SCALE: { + depthBias = true; + break; + } + case State::FRONT_CLOCKWISE: { + generateFrontClockwise(object->_commands, bool(field.second._integer)); + break; + } + case State::DEPTH_CLIP_ENABLE: { + generateDepthClipEnable(object->_commands, bool(field.second._integer)); + break; + } + case State::SCISSOR_ENABLE: { + generateScissorEnable(object->_commands, bool(field.second._integer)); + break; + } + case State::MULTISAMPLE_ENABLE: { + generateMultisampleEnable(object->_commands, bool(field.second._integer)); + break; + } + case State::ANTIALISED_LINE_ENABLE: { + generateAntialiasedLineEnable(object->_commands, bool(field.second._integer)); + break; + } + + case State::DEPTH_ENABLE: { + depthEnabled = bool(field.second._integer); + generateDepthEnable(object->_commands, depthEnabled); + break; + } + case State::DEPTH_WRITE_MASK: + case State::DEPTH_FUNC: { + depthState = true; + break; + } + case State::STENCIL_ENABLE: { + stencilEnabled = bool(field.second._integer); + generateStencilEnable(object->_commands, stencilEnabled); + break; + } + case State::STENCIL_WRITE_MASK: + case State::STENCIL_READ_MASK: + case State::STENCIL_REFERENCE: + case State::STENCIL_TEST_FRONT: + case State::STENCIL_TEST_BACK: { + stencilState = true; + break; + } + + case State::SAMPLE_MASK: { + break; + } + case State::ALPHA_TO_COVERAGE_ENABLE: { + generateAlphaToCoverageEnable(object->_commands, bool(field.second._integer)); + break; + } + + case State::BLEND_ENABLE: { + blendEnabled = field.second._integer; + generateBlendEnable(object->_commands, blendEnabled); + break; + } + case State::BLEND_FUNCTION_COLOR: + case State::BLEND_FUNCTION_ALPHA: { + blendFunction = true; + break; + } + case State::BLEND_FACTOR_X: + case State::BLEND_FACTOR_Y: + case State::BLEND_FACTOR_Z: + case State::BLEND_FACTOR_W: { + blendFactor = true; + break; + } + + case State::COLOR_WRITE_MASK: { + generateColorWriteMask(object->_commands, State::ColorMask(field.second._integer)); + break; + } + + } + } + + if (depthBias) { + generateDepthBias(object->_commands, state); + } + + if (depthEnabled) { + generateDepthWriteMask(object->_commands, state.getDepthWriteMask()); + generateDepthFunc(object->_commands, state.getDepthFunc()); + } + + if (stencilEnabled) { + generateStencilState(object->_commands, state); + generateStencilWriteMask(object->_commands, state.getStencilWriteMask()); + } + + if (blendEnabled) { + generateBlendFunction(object->_commands, state); + generateBlendFactor(object->_commands, state.getBlendFactor()); + } + + return nullptr; +} diff --git a/libraries/gpu/src/gpu/Pipeline.cpp b/libraries/gpu/src/gpu/Pipeline.cpp index 931d330c2b..237932b07d 100755 --- a/libraries/gpu/src/gpu/Pipeline.cpp +++ b/libraries/gpu/src/gpu/Pipeline.cpp @@ -17,7 +17,7 @@ using namespace gpu; Pipeline::Pipeline(): _program(), - _states() + _state() { } @@ -25,10 +25,10 @@ Pipeline::~Pipeline() { } -Pipeline* Pipeline::create(const ShaderPointer& program, const States& states) { +Pipeline* Pipeline::create(const ShaderPointer& program, const StatePointer& state) { Pipeline* pipeline = new Pipeline(); pipeline->_program = program; - pipeline->_states = states; + pipeline->_state = state; return pipeline; } diff --git a/libraries/gpu/src/gpu/Pipeline.h b/libraries/gpu/src/gpu/Pipeline.h index faa671c30f..189bdc4f00 100755 --- a/libraries/gpu/src/gpu/Pipeline.h +++ b/libraries/gpu/src/gpu/Pipeline.h @@ -22,16 +22,16 @@ namespace gpu { class Pipeline { public: - static Pipeline* create(const ShaderPointer& program, const States& states); + static Pipeline* create(const ShaderPointer& program, const StatePointer& state); ~Pipeline(); const ShaderPointer& getProgram() const { return _program; } - const States& getStates() const { return _states; } + const StatePointer& getState() const { return _state; } protected: ShaderPointer _program; - States _states; + StatePointer _state; Pipeline(); Pipeline(const Pipeline& pipeline); // deep copy of the sysmem shader diff --git a/libraries/gpu/src/gpu/Resource.h b/libraries/gpu/src/gpu/Resource.h index 3da25ae78f..96b961ffd7 100644 --- a/libraries/gpu/src/gpu/Resource.h +++ b/libraries/gpu/src/gpu/Resource.h @@ -24,10 +24,6 @@ namespace gpu { -class GPUObject; - -typedef int Stamp; - class Resource { public: typedef unsigned char Byte; diff --git a/libraries/gpu/src/gpu/State.cpp b/libraries/gpu/src/gpu/State.cpp index 0d3f04959b..59ecdc6766 100755 --- a/libraries/gpu/src/gpu/State.cpp +++ b/libraries/gpu/src/gpu/State.cpp @@ -22,21 +22,25 @@ State::~State() void State::set(Field field, bool value) { auto found = _fields.at(field); found._integer = value; + _stamp++; } void State::set(Field field, uint32 value) { auto found = _fields.at(field); found._unsigned_integer = value; + _stamp++; } void State::set(Field field, int32 value) { auto found = _fields.at(field); found._integer = value; + _stamp++; } void State::set(Field field, float value) { auto found = _fields.at(field); found._float = value; + _stamp++; } State::Value State::get(Field field) const { diff --git a/libraries/gpu/src/gpu/State.h b/libraries/gpu/src/gpu/State.h index 3528a14214..d92cd7c603 100755 --- a/libraries/gpu/src/gpu/State.h +++ b/libraries/gpu/src/gpu/State.h @@ -26,12 +26,14 @@ public: State() {} virtual ~State(); + const Stamp getStamp() const { return _stamp; } + // All the possible fields enum Field { FILL_MODE, CULL_MODE, + DEPTH_BIAS, - DEPTH_BIAS_CLAMP, DEPTH_BIAS_SLOPE_SCALE, FRONT_CLOCKWISE, @@ -47,37 +49,22 @@ public: STENCIL_ENABLE, STENCIL_READ_MASK, STENCIL_WRITE_MASK, - - STENCIL_FUNC_FRONT, - STENCIL_FRONT_FUNC, - STENCIL_FRONT_FAIL_OP, - STENCIL_FRONT_DEPTH_FAIL_OP, - STENCIL_FRONT_PASS_OP, - - STENCIL_BACK_FUNC, - STENCIL_BACK_FAIL_OP, - STENCIL_BACK_DEPTH_FAIL_OP, - STENCIL_BACK_PASS_OP, - STENCIL_FUNC_BACK, - + STENCIL_TEST_FRONT, + STENCIL_TEST_BACK, STENCIL_REFERENCE, SAMPLE_MASK, ALPHA_TO_COVERAGE_ENABLE, + + BLEND_ENABLE, + BLEND_FUNCTION_COLOR, + BLEND_FUNCTION_ALPHA, BLEND_FACTOR_X, BLEND_FACTOR_Y, BLEND_FACTOR_Z, BLEND_FACTOR_W, - - BLEND_INDEPENDANT_ENABLE, - BLEND_ENABLE, - BLEND_SOURCE, - BLEND_DESTINATION, - BLEND_OPERATION, - BLEND_SOURCE_ALPHA, - BLEND_DESTINATION_ALPHA, - BLEND_OPERATION_ALPHA, - BLEND_WRITE_MASK, + + COLOR_WRITE_MASK, NUM_FIELDS, // not a valid field, just the count }; @@ -138,10 +125,6 @@ public: SRC_ALPHA_SAT, BLEND_FACTOR, INV_BLEND_FACTOR, - SRC1_COLOR, - INV_SRC1_COLOR, - SRC1_ALPHA, - INV_SRC1_ALPHA, NUM_BLEND_ARGS, }; @@ -166,6 +149,33 @@ public: WRITE_ALL = (WRITE_RED | WRITE_GREEN | WRITE_BLUE | WRITE_ALPHA ), }; + class StencilTest { + public: + int8 _failOp = STENCIL_OP_KEEP; + int8 _depthFailOp = STENCIL_OP_KEEP; + int8 _passOp = STENCIL_OP_KEEP; + int8 _function = ALWAYS; + + StencilTest(StencilOp failOp, StencilOp depthFailOp, StencilOp passOp, ComparisonFunction func) : + _failOp(failOp), _depthFailOp(depthFailOp), _passOp(passOp), _function(func) {} + + int32 raw() const { return *(reinterpret_cast(this)); } + StencilTest(int32 raw) { *(reinterpret_cast(this)) = raw; } + }; + + class BlendFunction { + public: + int8 _source = ONE; + int8 _operation = BLEND_OP_ADD; + int8 _destination = ZERO; + int8 _spare = 0; + + BlendFunction(BlendArg source, BlendOp operation, BlendArg destination) : + _source(source), _operation(operation), _destination(destination) {} + + int32 raw() const { return *(reinterpret_cast(this)); } + BlendFunction(int32 raw) { *(reinterpret_cast(this)) = raw; } + }; class Value { public: @@ -177,6 +187,8 @@ public: }; typedef std::unordered_map FieldMap; + const FieldMap& getFields() const { return _fields; } + void set(Field field, bool value); void set(Field field, uint32 value); void set(Field field, int32 value); @@ -189,11 +201,9 @@ public: FillMode getFillMode() const { return FillMode(get(FILL_MODE)._integer); } CullMode getCullMode() const { return CullMode(get(CULL_MODE)._integer); } - void setDepthBias(int32 bias) { set(DEPTH_BIAS, bias); } - void setDepthBiasClamp(float clamp) { set(DEPTH_BIAS_CLAMP, clamp); } + void setDepthBias(float bias) { set(DEPTH_BIAS, bias); } void setDepthBiasSlopeScale(float scale) { set(DEPTH_BIAS_SLOPE_SCALE, scale); } - int32 getDepthBias() const { return get(DEPTH_BIAS)._integer; } - float getDepthBiasClamp() const { return get(DEPTH_BIAS_CLAMP)._float; } + float getDepthBias() const { return get(DEPTH_BIAS)._integer; } float getDepthBiasSlopeScale() const { return get(DEPTH_BIAS_SLOPE_SCALE)._float; } void setFrontClockwise(bool enable) { set(FRONT_CLOCKWISE, enable); } @@ -221,23 +231,10 @@ public: uint8 getStencilReadMask() const { return get(STENCIL_READ_MASK)._unsigned_integer; } uint8 getStencilWriteMask() const { return get(STENCIL_WRITE_MASK)._unsigned_integer; } - void setStencilFrontFailOp(StencilOp op) { set(STENCIL_FRONT_FAIL_OP, op); } - void setStencilFrontDepthFailOp(StencilOp op) { set(STENCIL_FRONT_DEPTH_FAIL_OP, op); } - void setStencilFrontPassOp(StencilOp op) { set(STENCIL_FRONT_PASS_OP, op); } - void setStencilFrontFunc(ComparisonFunction func) { set(STENCIL_FRONT_FUNC, func); } - StencilOp getStencilFrontFailOp() const { return StencilOp(get(STENCIL_FRONT_FAIL_OP)._integer); } - StencilOp getStencilFrontDepthFailOp() const { return StencilOp(get(STENCIL_FRONT_DEPTH_FAIL_OP)._integer); } - StencilOp getStencilFrontPassOp() const { return StencilOp(get(STENCIL_FRONT_PASS_OP)._integer); } - ComparisonFunction getStencilFrontFunc() const { return ComparisonFunction(get(STENCIL_FRONT_FUNC)._integer); } - - void setStencilBackFailOp(StencilOp op) { set(STENCIL_BACK_FAIL_OP, op); } - void setStencilBackDepthFailOp(StencilOp op) { set(STENCIL_BACK_DEPTH_FAIL_OP, op); } - void setStencilBackPassOp(StencilOp op) { set(STENCIL_BACK_PASS_OP, op); } - void setStencilBackFunc(ComparisonFunction func) { set(STENCIL_BACK_FUNC, func); } - StencilOp getStencilBackFailOp() const { return StencilOp(get(STENCIL_BACK_FAIL_OP)._integer); } - StencilOp getStencilBackDepthFailOp() const { return StencilOp(get(STENCIL_BACK_DEPTH_FAIL_OP)._integer); } - StencilOp getStencilBackPassOp() const { return StencilOp(get(STENCIL_BACK_PASS_OP)._integer); } - ComparisonFunction getStencilBackFunc() const { return ComparisonFunction(get(STENCIL_BACK_FUNC)._integer); } + void setStencilTestFront(StencilTest test) { set(STENCIL_TEST_FRONT, test.raw()); } + void setStencilTestBack(StencilTest test) { set(STENCIL_TEST_BACK, test.raw()); } + StencilTest getStencilTestFront() const { return StencilTest(get(STENCIL_TEST_FRONT)._integer); } + StencilTest getStencilTestBack() const { return StencilTest(get(STENCIL_TEST_BACK)._integer); } void setStencilReference(uint32 ref) { set(STENCIL_REFERENCE, ref); } uint32 getStencilReference() const { return get(STENCIL_REFERENCE)._unsigned_integer; } @@ -247,39 +244,30 @@ public: void setSampleMask(uint32 mask) { set(SAMPLE_MASK, mask); } uint32 getSampleMask() const { return get(SAMPLE_MASK)._unsigned_integer; } - - // void setBlendIndependantEnable(bool enable) { set(BLEND_INDEPENDANT_ENABLE, enable); } - // bool getBlendIndependantEnable() const { return get(BLEND_INDEPENDANT_ENABLE)._integer; } void setBlendEnable(bool enable) { set(BLEND_ENABLE, enable); } bool getBlendEnable() const { return get(BLEND_ENABLE)._integer; } - void setBlendSource(BlendArg source) { set(BLEND_SOURCE, source); } - void setBlendDestination(BlendArg destination) { set(BLEND_DESTINATION, destination); } - void setBlendOperation(BlendOp operation) { set(BLEND_OPERATION, operation); } - BlendArg getBlendSource() const { return BlendArg(get(BLEND_SOURCE)._integer); } - BlendArg getBlendDestination() const { return BlendArg(get(BLEND_DESTINATION)._integer); } - BlendOp getBlendOperation() const { return BlendOp(get(BLEND_OPERATION)._integer); } - - void setBlendSourceAlpha(BlendArg source) { set(BLEND_SOURCE_ALPHA, source); } - void setBlendDestinationAlpha(BlendArg destination) { set(BLEND_DESTINATION_ALPHA, destination); } - void setBlendOperationAlpha(BlendOp operation) { set(BLEND_OPERATION_ALPHA, operation); } - BlendArg getBlendSourceAlpha() const { return BlendArg(get(BLEND_SOURCE_ALPHA)._integer); } - BlendArg getBlendDestinationAlpha() const { return BlendArg(get(BLEND_DESTINATION_ALPHA)._integer); } - BlendOp getBlendOperationAlpha() const { return BlendOp(get(BLEND_OPERATION_ALPHA)._integer); } - - void setBlendWriteMask(ColorMask mask) { set(BLEND_WRITE_MASK, mask); } - ColorMask getBlendWriteMask() const { return ColorMask(get(BLEND_WRITE_MASK)._integer); } - + void setBlendFunctionColor(BlendFunction function) { set(BLEND_FUNCTION_COLOR, function.raw()); } + BlendFunction getBlendFunctionColor() const { return BlendFunction(get(BLEND_FUNCTION_COLOR)._integer); } + void setBlendFunctionAlpha(BlendFunction function) { set(BLEND_FUNCTION_ALPHA, function.raw()); } + BlendFunction getBlendFunctionAlpha() const { return BlendFunction(get(BLEND_FUNCTION_ALPHA)._integer); } + 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 getBlendFactor() const { return Vec4(get(BLEND_FACTOR_X)._float, get(BLEND_FACTOR_Y)._float, get(BLEND_FACTOR_Z)._float, get(BLEND_FACTOR_W)._float); } + + void setColorWriteMask(ColorMask mask) { set(COLOR_WRITE_MASK, mask); } + ColorMask getColorWriteMask() const { return ColorMask(get(COLOR_WRITE_MASK)._integer); } + protected: State(const State& state); State& operator=(const State& state); FieldMap _fields; + Stamp _stamp; + // This shouldn't be used by anything else than the Backend class with the proper casting. mutable GPUObject* _gpuObject = NULL; void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; } diff --git a/libraries/model/src/model/Stage.cpp b/libraries/model/src/model/Stage.cpp index cc4d4abee3..30828da094 100644 --- a/libraries/model/src/model/Stage.cpp +++ b/libraries/model/src/model/Stage.cpp @@ -215,7 +215,13 @@ SunSkyStage::SunSkyStage() : auto skyFromAtmosphereVertex = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(SkyFromAtmosphere_vert))); auto skyFromAtmosphereFragment = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(SkyFromAtmosphere_frag))); auto skyShader = gpu::ShaderPointer(gpu::Shader::createProgram(skyFromAtmosphereVertex, skyFromAtmosphereFragment)); - _skyPipeline = gpu::PipelinePointer(gpu::Pipeline::create(skyShader, gpu::States())); + + auto skyState = gpu::StatePointer(new gpu::State()); + skyState->setDepthEnable(false); + skyState->setStencilEnable(false); + skyState->setBlendEnable(false); + + _skyPipeline = gpu::PipelinePointer(gpu::Pipeline::create(skyShader, skyState)); } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 5114ef1c9f..7468ddb288 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -318,6 +318,29 @@ private: int _blendNumber; int _appliedBlendNumber; +/* + static gpu::PipelinePointer _program; + static gpu::PipelinePointer _normalMapProgram; + static gpu::PipelinePointer _specularMapProgram; + static gpu::PipelinePointer _normalSpecularMapProgram; + static gpu::PipelinePointer _translucentProgram; + + static gpu::PipelinePointer _lightmapProgram; + static gpu::PipelinePointer _lightmapNormalMapProgram; + static gpu::PipelinePointer _lightmapSpecularMapProgram; + static gpu::PipelinePointer _lightmapNormalSpecularMapProgram; + + static gpu::PipelinePointer _shadowProgram; + + static gpu::PipelinePointer _skinProgram; + static gpu::PipelinePointer _skinNormalMapProgram; + static gpu::PipelinePointer _skinSpecularMapProgram; + static gpu::PipelinePointer _skinNormalSpecularMapProgram; + static gpu::PipelinePointer _skinTranslucentProgram; + + static gpu::PipelinePointer _skinShadowProgram; +*/ + static gpu::ShaderPointer _program; static gpu::ShaderPointer _normalMapProgram; static gpu::ShaderPointer _specularMapProgram; @@ -473,6 +496,17 @@ private: static AbstractViewStateInterface* _viewState; + /* class RenderKey { + public: + enum Flag { + TRANSLUCENT = 0, + HAS_LIGHTMAP, + }; + + RenderMode mode; + + }; +*/ }; Q_DECLARE_METATYPE(QPointer)