From 5f3c4b743f400b637aecff120ae6b939cbde371f Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Sun, 22 Mar 2015 19:04:33 -0700 Subject: [PATCH 01/21] drafting a simple skybox --- libraries/model/src/model/Stage.cpp | 11 +++++++++++ libraries/model/src/model/Stage.h | 20 ++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/libraries/model/src/model/Stage.cpp b/libraries/model/src/model/Stage.cpp index 1c171eee76..225ec8d138 100644 --- a/libraries/model/src/model/Stage.cpp +++ b/libraries/model/src/model/Stage.cpp @@ -184,6 +184,14 @@ void Atmosphere::setInnerOuterRadiuses(float inner, float outer) { data._scales.z = data._scales.x / data._scales.y; } +Skybox::Skybox() { +} + +void Skybox::setCubemap(const gpu::TexturePointer& cubemap) { + _cubemap = cubemap; +} + + const int NUM_DAYS_PER_YEAR = 365; const float NUM_HOURS_PER_DAY = 24.0f; @@ -273,3 +281,6 @@ void SunSkyStage::updateGraphicsObject() const { } +void SunSkyStage::setSkybox(const Vec3& color) { + _skybox ; +} \ No newline at end of file diff --git a/libraries/model/src/model/Stage.h b/libraries/model/src/model/Stage.h index 3cc8b4a6e9..30c96259ca 100644 --- a/libraries/model/src/model/Stage.h +++ b/libraries/model/src/model/Stage.h @@ -160,6 +160,21 @@ protected: }; typedef QSharedPointer< Atmosphere > AtmospherePointer; + +class Skybox { +public: + Skybox(); + Skybox& operator= (const Atmosphere& Skybox); + virtual ~Skybox() {}; + + void setCubemap(const gpu::TexturePointer& cubemap); + const gpu::TexturePointer& getCubemap() const { return _cubemap; } + +protected: + gpu::TexturePointer _cubemap; +}; +typedef QSharedPointer< Skybox > SkyboxPointer; + // Sun sky stage generates the rendering primitives to display a scene realistically // at the specified location and time around earth class SunSkyStage { @@ -197,9 +212,14 @@ public: LightPointer getSunLight() const { valid(); return _sunLight; } AtmospherePointer getAtmosphere() const { valid(); return _atmosphere; } + // Skybox + void setSkybox(const SkyboxPointer& skybox); + const SkyboxPointer& getSkybox() const { valid(); return _skybox; } + protected: LightPointer _sunLight; AtmospherePointer _atmosphere; + SkyboxPointer _skybox; gpu::PipelinePointer _skyPipeline; From 69667fb5cacc43ac27b88ee735877e5d7edc5cae Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 23 Mar 2015 10:21:35 -0700 Subject: [PATCH 02/21] making the state work --- libraries/gpu/src/gpu/GLBackend.h | 21 ++ libraries/gpu/src/gpu/State.cpp | 28 ++ libraries/gpu/src/gpu/State.h | 240 ++++++++++++++++-- libraries/model/src/model/Stage.cpp | 5 +- .../src/DeferredLightingEffect.cpp | 4 + .../render-utils/src/DeferredLightingEffect.h | 2 + 6 files changed, 282 insertions(+), 18 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 2fd27862f9..b2ec284843 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -75,6 +75,27 @@ public: static GLShader* syncGPUObject(const Shader& shader); static GLuint getShaderID(const ShaderPointer& shader); + class GLState : public GPUObject { + public: + class Command { + public: + typedef void *GlFunction(GLenum); + + GlFunction _glFunction; + GLenum _enum; + + void run() { _glFunction(_enum); } + }; + + typedef std::vector< Command > Commands; + + Commands _commands; + + + GLState(); + ~GLState(); + }; + static GLState* syncGPUObject(const State& state); class GLPipeline : public GPUObject { public: diff --git a/libraries/gpu/src/gpu/State.cpp b/libraries/gpu/src/gpu/State.cpp index 0b8edb7cd2..0d3f04959b 100755 --- a/libraries/gpu/src/gpu/State.cpp +++ b/libraries/gpu/src/gpu/State.cpp @@ -18,3 +18,31 @@ using namespace gpu; State::~State() { } + +void State::set(Field field, bool value) { + auto found = _fields.at(field); + found._integer = value; +} + +void State::set(Field field, uint32 value) { + auto found = _fields.at(field); + found._unsigned_integer = value; +} + +void State::set(Field field, int32 value) { + auto found = _fields.at(field); + found._integer = value; +} + +void State::set(Field field, float value) { + auto found = _fields.at(field); + found._float = value; +} + +State::Value State::get(Field field) const { + auto found = _fields.find(field); + if (found != _fields.end()) { + return (*found).second; + } + return Value(); +} \ No newline at end of file diff --git a/libraries/gpu/src/gpu/State.h b/libraries/gpu/src/gpu/State.h index 92ef4c1c8d..3528a14214 100755 --- a/libraries/gpu/src/gpu/State.h +++ b/libraries/gpu/src/gpu/State.h @@ -12,8 +12,9 @@ #define hifi_gpu_State_h #include "Format.h" -#include -#include + +#include +#include namespace gpu { @@ -25,32 +26,49 @@ public: State() {} virtual ~State(); - // Work in progress, not used - /* + // All the possible fields enum Field { FILL_MODE, CULL_MODE, DEPTH_BIAS, DEPTH_BIAS_CLAMP, - DEPTH_BIASSLOPE_SCALE, + DEPTH_BIAS_SLOPE_SCALE, FRONT_CLOCKWISE, DEPTH_CLIP_ENABLE, - SCISSR_ENABLE, + SCISSOR_ENABLE, MULTISAMPLE_ENABLE, ANTIALISED_LINE_ENABLE, DEPTH_ENABLE, DEPTH_WRITE_MASK, - DEPTH_FUNCTION, + DEPTH_FUNC, STENCIL_ENABLE, STENCIL_READ_MASK, STENCIL_WRITE_MASK, - STENCIL_FUNCTION_FRONT, - STENCIL_FUNCTION_BACK, + + 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_REFERENCE, + SAMPLE_MASK, + ALPHA_TO_COVERAGE_ENABLE, + BLEND_FACTOR_X, + BLEND_FACTOR_Y, + BLEND_FACTOR_Z, + BLEND_FACTOR_W, + BLEND_INDEPENDANT_ENABLE, BLEND_ENABLE, BLEND_SOURCE, @@ -60,18 +78,208 @@ public: BLEND_DESTINATION_ALPHA, BLEND_OPERATION_ALPHA, BLEND_WRITE_MASK, - BLEND_FACTOR, - - SAMPLE_MASK, - - ALPHA_TO_COVERAGE_ENABLE, + + NUM_FIELDS, // not a valid field, just the count }; - */ + + enum ComparisonFunction { + NEVER = 0, + LESS, + EQUAL, + LESS_EQUAL, + GREATER, + NOT_EQUAL, + GREATER_EQUAL, + ALWAYS, + + NUM_COMPARISON_FUNCS, + }; + + enum FillMode { + FILL_POINT = 0, + FILL_LINE, + FILL_FACE, + + NUM_FILL_MODES, + }; + + enum CullMode { + CULL_NONE = 0, + CULL_FRONT, + CULL_BACK, + + NUM_CULL_MODES, + }; + + enum StencilOp { + STENCIL_OP_KEEP = 0, + STENCIL_OP_ZERO, + STENCIL_OP_REPLACE, + STENCIL_OP_INCR_SAT, + STENCIL_OP_DECR_SAT, + STENCIL_OP_INVERT, + STENCIL_OP_INCR, + STENCIL_OP_DECR, + + NUM_STENCIL_OPS, + }; + + enum BlendArg { + ZERO = 0, + ONE, + SRC_COLOR, + INV_SRC_COLOR, + SRC_ALPHA, + INV_SRC_ALPHA, + DEST_ALPHA, + INV_DEST_ALPHA, + DEST_COLOR, + INV_DEST_COLOR, + SRC_ALPHA_SAT, + BLEND_FACTOR, + INV_BLEND_FACTOR, + SRC1_COLOR, + INV_SRC1_COLOR, + SRC1_ALPHA, + INV_SRC1_ALPHA, + + NUM_BLEND_ARGS, + }; + + enum BlendOp { + BLEND_OP_ADD = 0, + BLEND_OP_SUBTRACT, + BLEND_OP_REV_SUBTRACT, + BLEND_OP_MIN, + BLEND_OP_MAX, + + NUM_BLEND_OPS, + }; + + enum ColorMask + { + WRITE_NONE = 0, + WRITE_RED = 1, + WRITE_GREEN = 2, + WRITE_BLUE = 4, + WRITE_ALPHA = 8, + WRITE_ALL = (WRITE_RED | WRITE_GREEN | WRITE_BLUE | WRITE_ALPHA ), + }; + + + class Value { + public: + union { + uint32 _unsigned_integer; + int32 _integer; + float _float; + }; + }; + typedef std::unordered_map FieldMap; + + void set(Field field, bool value); + void set(Field field, uint32 value); + void set(Field field, int32 value); + void set(Field field, float value); + + Value get(Field field) const; + + void setFillMode(FillMode fill) { set(FILL_MODE, uint32(fill)); } + void setCullMode(CullMode cull) { set(FILL_MODE, uint32(cull)); } + 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 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 getDepthBiasSlopeScale() const { return get(DEPTH_BIAS_SLOPE_SCALE)._float; } + + void setFrontClockwise(bool enable) { set(FRONT_CLOCKWISE, enable); } + void setDepthClipEnable(bool enable) { set(DEPTH_CLIP_ENABLE, enable); } + void setScissorEnable(bool enable) { set(SCISSOR_ENABLE, enable); } + void setMultisampleEnable(bool enable) { set(MULTISAMPLE_ENABLE, enable); } + void setAntialiasedLineEnable(bool enable) { set(ANTIALISED_LINE_ENABLE, enable); } + bool getFrontClockwise() const { return get(FRONT_CLOCKWISE)._integer; } + bool getDepthClipEnable() const { return get(DEPTH_CLIP_ENABLE)._integer; } + bool getScissorEnable() const { return get(SCISSOR_ENABLE)._integer; } + bool getMultisampleEnable() const { return get(MULTISAMPLE_ENABLE)._integer; } + bool getAntialiasedLineEnable() const { return get(ANTIALISED_LINE_ENABLE)._integer; } + + void setDepthEnable(bool enable) { set(DEPTH_ENABLE, enable); } + void setDepthWriteMask(bool enable) { set(DEPTH_WRITE_MASK, enable); } + void setDepthFunc(ComparisonFunction func) { set(DEPTH_FUNC, func); } + bool getDepthEnable() const { return get(DEPTH_ENABLE)._integer; } + bool getDepthWriteMask() const { return get(DEPTH_WRITE_MASK)._integer; } + ComparisonFunction getDepthFunc() const { return ComparisonFunction(get(DEPTH_FUNC)._integer); } + + void setStencilEnable(bool enable) { set(STENCIL_ENABLE, enable); } + void setStencilReadMask(uint8 mask) { set(STENCIL_READ_MASK, mask); } + void setStencilWriteMask(uint8 mask) { set(STENCIL_WRITE_MASK, mask); } + bool getStencilEnable() const { return get(STENCIL_ENABLE)._integer; } + 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 setStencilReference(uint32 ref) { set(STENCIL_REFERENCE, ref); } + uint32 getStencilReference() const { return get(STENCIL_REFERENCE)._unsigned_integer; } + + void setAlphaToCoverageEnable(bool enable) { set(ALPHA_TO_COVERAGE_ENABLE, enable); } + bool getAlphaToCoverageEnable() const { return get(ALPHA_TO_COVERAGE_ENABLE)._integer; } + + 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 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); } protected: State(const State& state); State& operator=(const State& state); + FieldMap _fields; + // 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; } @@ -79,7 +287,7 @@ protected: friend class Backend; }; -typedef QSharedPointer< State > StatePointer; +typedef std::shared_ptr< State > StatePointer; typedef std::vector< StatePointer > States; }; diff --git a/libraries/model/src/model/Stage.cpp b/libraries/model/src/model/Stage.cpp index 225ec8d138..cc4d4abee3 100644 --- a/libraries/model/src/model/Stage.cpp +++ b/libraries/model/src/model/Stage.cpp @@ -281,6 +281,7 @@ void SunSkyStage::updateGraphicsObject() const { } -void SunSkyStage::setSkybox(const Vec3& color) { - _skybox ; +void SunSkyStage::setSkybox(const SkyboxPointer& skybox) { + _skybox = skybox; + invalidate(); } \ No newline at end of file diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 13bf947d71..694ffa4fdc 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -548,3 +548,7 @@ void DeferredLightingEffect::setGlobalLight(const glm::vec3& direction, const gl light->setColor(diffuse); light->setIntensity(intensity); } + +void DeferredLightingEffect::setGlobalSkybox(const model::SkyboxPointer& skybox) { + _skybox = skybox; +} \ No newline at end of file diff --git a/libraries/render-utils/src/DeferredLightingEffect.h b/libraries/render-utils/src/DeferredLightingEffect.h index 900c5243cb..6d0d131029 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.h +++ b/libraries/render-utils/src/DeferredLightingEffect.h @@ -76,6 +76,7 @@ public: void setGlobalLight(const glm::vec3& direction, const glm::vec3& diffuse, float intensity); void setGlobalAtmosphere(const model::AtmospherePointer& atmosphere) { _atmosphere = atmosphere; } + void setGlobalSkybox(const model::SkyboxPointer& skybox); private: DeferredLightingEffect() {} virtual ~DeferredLightingEffect() { } @@ -150,6 +151,7 @@ private: int _ambientLightMode = 0; model::AtmospherePointer _atmosphere; + model::SkyboxPointer _skybox; }; /// Simple interface for objects that require something to be rendered after deferred lighting. From 19a96c4815deb6008a5516c718a596cb48925b6d Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 23 Mar 2015 22:33:25 -0700 Subject: [PATCH 03/21] Adding the State to gpu and wiring the pipeline in glBackend to potentially make it work soon :) --- libraries/gpu/src/gpu/Context.h | 9 + libraries/gpu/src/gpu/Format.h | 4 + libraries/gpu/src/gpu/GLBackend.h | 67 +++- libraries/gpu/src/gpu/GLBackendPipeline.cpp | 48 ++- libraries/gpu/src/gpu/GLBackendState.cpp | 356 ++++++++++++++++++++ libraries/gpu/src/gpu/Pipeline.cpp | 6 +- libraries/gpu/src/gpu/Pipeline.h | 6 +- libraries/gpu/src/gpu/Resource.h | 4 - libraries/gpu/src/gpu/State.cpp | 4 + libraries/gpu/src/gpu/State.h | 126 ++++--- libraries/model/src/model/Stage.cpp | 8 +- libraries/render-utils/src/Model.h | 34 ++ 12 files changed, 578 insertions(+), 94 deletions(-) create mode 100644 libraries/gpu/src/gpu/GLBackendState.cpp 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) From 62841598920b36358aec2a6e182adf85c12670e7 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 24 Mar 2015 14:58:41 -0700 Subject: [PATCH 04/21] Revisiting the rendering pipeline pick and trying to use our brand new gpu::Pipeline --- libraries/gpu/src/gpu/GLBackendState.cpp | 37 +-- libraries/gpu/src/gpu/State.cpp | 8 +- libraries/gpu/src/gpu/State.h | 29 +- libraries/model/src/model/Stage.cpp | 1 - libraries/render-utils/src/Model.cpp | 328 ++++++++++------------- libraries/render-utils/src/Model.h | 165 ++++++------ 6 files changed, 254 insertions(+), 314 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackendState.cpp b/libraries/gpu/src/gpu/GLBackendState.cpp index 73ed649e83..6a93e2c842 100644 --- a/libraries/gpu/src/gpu/GLBackendState.cpp +++ b/libraries/gpu/src/gpu/GLBackendState.cpp @@ -102,16 +102,14 @@ void generateAntialiasedLineEnable(GLBackend::GLState::Commands& commands, bool 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 generateDepthTest(GLBackend::GLState::Commands& commands, State::DepthTest& test) { + if (!test._enabled) { + commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDisable, GLenum(GL_DEPTH_TEST)))); + } else { + commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glEnable, GLenum(GL_DEPTH_TEST)))); + commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDepthMask, test._writeMask))); + commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDepthFunc, GL_COMPARISON_FUNCTIONS[test._function]))); + } } void generateStencilEnable(GLBackend::GLState::Commands& commands, bool enable) { @@ -228,9 +226,6 @@ GLBackend::GLState* GLBackend::syncGPUObject(const State& state) { bool depthBias = false; - bool depthEnabled = false; - bool depthState = false; - bool stencilEnabled = false; bool stencilState = false; @@ -275,16 +270,11 @@ GLBackend::GLState* GLBackend::syncGPUObject(const State& state) { 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; + case State::DEPTH_TEST: { + generateDepthTest(object->_commands, State::DepthTest(field.second._integer)); break; } + case State::STENCIL_ENABLE: { stencilEnabled = bool(field.second._integer); generateStencilEnable(object->_commands, stencilEnabled); @@ -337,11 +327,6 @@ GLBackend::GLState* GLBackend::syncGPUObject(const State& state) { 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()); diff --git a/libraries/gpu/src/gpu/State.cpp b/libraries/gpu/src/gpu/State.cpp index 59ecdc6766..13dd24fbcc 100755 --- a/libraries/gpu/src/gpu/State.cpp +++ b/libraries/gpu/src/gpu/State.cpp @@ -20,25 +20,25 @@ State::~State() } void State::set(Field field, bool value) { - auto found = _fields.at(field); + auto found = _fields[field]; found._integer = value; _stamp++; } void State::set(Field field, uint32 value) { - auto found = _fields.at(field); + auto found = _fields[field]; found._unsigned_integer = value; _stamp++; } void State::set(Field field, int32 value) { - auto found = _fields.at(field); + auto found = _fields[field]; found._integer = value; _stamp++; } void State::set(Field field, float value) { - auto found = _fields.at(field); + auto found = _fields[field]; found._float = value; _stamp++; } diff --git a/libraries/gpu/src/gpu/State.h b/libraries/gpu/src/gpu/State.h index d92cd7c603..c3c73cefa4 100755 --- a/libraries/gpu/src/gpu/State.h +++ b/libraries/gpu/src/gpu/State.h @@ -42,9 +42,7 @@ public: MULTISAMPLE_ENABLE, ANTIALISED_LINE_ENABLE, - DEPTH_ENABLE, - DEPTH_WRITE_MASK, - DEPTH_FUNC, + DEPTH_TEST, STENCIL_ENABLE, STENCIL_READ_MASK, @@ -149,6 +147,18 @@ public: WRITE_ALL = (WRITE_RED | WRITE_GREEN | WRITE_BLUE | WRITE_ALPHA ), }; + class DepthTest { + public: + DepthTest(bool enable, bool writeMask, ComparisonFunction func) : + _function(func), _writeMask(writeMask), _enabled(enable) {} + uint8 _function = ALWAYS; + bool _writeMask = false; + bool _enabled = false; + + int32 getRaw() const { return *(reinterpret_cast(this)); } + DepthTest(int32 raw) { *(reinterpret_cast(this)) = raw; } + }; + class StencilTest { public: int8 _failOp = STENCIL_OP_KEEP; @@ -217,13 +227,12 @@ public: bool getMultisampleEnable() const { return get(MULTISAMPLE_ENABLE)._integer; } bool getAntialiasedLineEnable() const { return get(ANTIALISED_LINE_ENABLE)._integer; } - void setDepthEnable(bool enable) { set(DEPTH_ENABLE, enable); } - void setDepthWriteMask(bool enable) { set(DEPTH_WRITE_MASK, enable); } - void setDepthFunc(ComparisonFunction func) { set(DEPTH_FUNC, func); } - bool getDepthEnable() const { return get(DEPTH_ENABLE)._integer; } - bool getDepthWriteMask() const { return get(DEPTH_WRITE_MASK)._integer; } - ComparisonFunction getDepthFunc() const { return ComparisonFunction(get(DEPTH_FUNC)._integer); } - + void setDepthTest(bool enable, bool writeMask, ComparisonFunction func) { set(DEPTH_TEST, DepthTest(enable, writeMask, func).getRaw()); } + DepthTest getDepthTest() const { return DepthTest(get(DEPTH_TEST)._integer); } + bool getDepthTestEnabled() const { return getDepthTest()._enabled; } + bool getDepthTestWriteMask() const { return getDepthTest()._writeMask; } + ComparisonFunction getDepthTestFunc() const { return ComparisonFunction(getDepthTest()._function); } + void setStencilEnable(bool enable) { set(STENCIL_ENABLE, enable); } void setStencilReadMask(uint8 mask) { set(STENCIL_READ_MASK, mask); } void setStencilWriteMask(uint8 mask) { set(STENCIL_WRITE_MASK, mask); } diff --git a/libraries/model/src/model/Stage.cpp b/libraries/model/src/model/Stage.cpp index 30828da094..a1a673a80b 100644 --- a/libraries/model/src/model/Stage.cpp +++ b/libraries/model/src/model/Stage.cpp @@ -217,7 +217,6 @@ SunSkyStage::SunSkyStage() : auto skyShader = gpu::ShaderPointer(gpu::Shader::createProgram(skyFromAtmosphereVertex, skyFromAtmosphereFragment)); auto skyState = gpu::StatePointer(new gpu::State()); - skyState->setDepthEnable(false); skyState->setStencilEnable(false); skyState->setBlendEnable(false); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index d640876086..7a40b2feed 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -94,48 +94,81 @@ Model::~Model() { deleteGeometry(); } -gpu::ShaderPointer Model::_program; -gpu::ShaderPointer Model::_normalMapProgram; -gpu::ShaderPointer Model::_specularMapProgram; -gpu::ShaderPointer Model::_normalSpecularMapProgram; -gpu::ShaderPointer Model::_translucentProgram; +Model::RenderPipelineLib Model::_renderPipelineLib; +const GLint MATERIAL_GPU_SLOT = 3; -gpu::ShaderPointer Model::_lightmapProgram; -gpu::ShaderPointer Model::_lightmapNormalMapProgram; -gpu::ShaderPointer Model::_lightmapSpecularMapProgram; -gpu::ShaderPointer Model::_lightmapNormalSpecularMapProgram; +void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey& key, + gpu::ShaderPointer& vertexShader, + gpu::ShaderPointer& pixelShader ) { -gpu::ShaderPointer Model::_shadowProgram; + gpu::Shader::BindingSet slotBindings; + slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), MATERIAL_GPU_SLOT)); + slotBindings.insert(gpu::Shader::Binding(std::string("diffuseMap"), 0)); + slotBindings.insert(gpu::Shader::Binding(std::string("normalMap"), 1)); + slotBindings.insert(gpu::Shader::Binding(std::string("specularMap"), 2)); + slotBindings.insert(gpu::Shader::Binding(std::string("emissiveMap"), 3)); -gpu::ShaderPointer Model::_skinProgram; -gpu::ShaderPointer Model::_skinNormalMapProgram; -gpu::ShaderPointer Model::_skinSpecularMapProgram; -gpu::ShaderPointer Model::_skinNormalSpecularMapProgram; -gpu::ShaderPointer Model::_skinTranslucentProgram; + gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vertexShader, pixelShader)); + bool makeResult = gpu::Shader::makeProgram(*program, slotBindings); + + + Locations* locations = new Locations(); + initLocations(program, *locations); -gpu::ShaderPointer Model::_skinShadowProgram; + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + if (key.isShadow()) { + state->setCullMode(gpu::State::CULL_FRONT); + } else { + state->setCullMode(gpu::State::CULL_BACK); + } -Model::Locations Model::_locations; -Model::Locations Model::_normalMapLocations; -Model::Locations Model::_specularMapLocations; -Model::Locations Model::_normalSpecularMapLocations; -Model::Locations Model::_translucentLocations; + if (key.isTranslucent()) { + } else { + state->setBlendEnable(false); + } -Model::Locations Model::_lightmapLocations; -Model::Locations Model::_lightmapNormalMapLocations; -Model::Locations Model::_lightmapSpecularMapLocations; -Model::Locations Model::_lightmapNormalSpecularMapLocations; + /* + GLBATCH(glDisable)(GL_BLEND); + GLBATCH(glEnable)(GL_ALPHA_TEST); + + if (mode == SHADOW_RENDER_MODE) { + GLBATCH(glAlphaFunc)(GL_EQUAL, 0.0f); + } + */ -Model::SkinLocations Model::_skinLocations; -Model::SkinLocations Model::_skinNormalMapLocations; -Model::SkinLocations Model::_skinSpecularMapLocations; -Model::SkinLocations Model::_skinNormalSpecularMapLocations; -Model::SkinLocations Model::_skinShadowLocations; -Model::SkinLocations Model::_skinTranslucentLocations; + + auto it = insert(value_type(key.getRaw(), + RenderPipeline( + gpu::PipelinePointer( gpu::Pipeline::create(program, state) ), + std::shared_ptr(locations) + ))); + +} + + +void Model::RenderPipelineLib::initLocations(gpu::ShaderPointer& program, Model::Locations& locations) { + locations.alphaThreshold = program->getUniforms().findLocation("alphaThreshold"); + locations.texcoordMatrices = program->getUniforms().findLocation("texcoordMatrices"); + locations.emissiveParams = program->getUniforms().findLocation("emissiveParams"); + locations.glowIntensity = program->getUniforms().findLocation("glowIntensity"); + + locations.specularTextureUnit = program->getTextures().findLocation("specularMap"); + locations.emissiveTextureUnit = program->getTextures().findLocation("emissiveMap"); + +#if (GPU_FEATURE_PROFILE == GPU_CORE) + locations.materialBufferUnit = program->getBuffers().findLocation("materialBuffer"); +#else + locations.materialBufferUnit = program->getUniforms().findLocation("materialBuffer"); +#endif + locations.clusterMatrices = program->getUniforms().findLocation("clusterMatrices"); + + locations.clusterIndices = program->getInputs().findLocation("clusterIndices");; + locations.clusterWeights = program->getInputs().findLocation("clusterWeights");; + +} AbstractViewStateInterface* Model::_viewState = NULL; -const GLint MATERIAL_GPU_SLOT = 3; void Model::setScale(const glm::vec3& scale) { setScaleInternal(scale); @@ -167,33 +200,6 @@ void Model::setOffset(const glm::vec3& offset) { _snappedToRegistrationPoint = false; } -void Model::initProgram(gpu::ShaderPointer& program, Model::Locations& locations) { - locations.alphaThreshold = program->getUniforms().findLocation("alphaThreshold"); - locations.texcoordMatrices = program->getUniforms().findLocation("texcoordMatrices"); - locations.emissiveParams = program->getUniforms().findLocation("emissiveParams"); - locations.glowIntensity = program->getUniforms().findLocation("glowIntensity"); - - locations.specularTextureUnit = program->getTextures().findLocation("specularMap"); - locations.emissiveTextureUnit = program->getTextures().findLocation("emissiveMap"); - -#if (GPU_FEATURE_PROFILE == GPU_CORE) - locations.materialBufferUnit = program->getBuffers().findLocation("materialBuffer"); -#else - locations.materialBufferUnit = program->getUniforms().findLocation("materialBuffer"); -#endif - -} - -void Model::initSkinProgram(gpu::ShaderPointer& program, Model::SkinLocations& locations) { - - initProgram(program, locations); - - locations.clusterMatrices = program->getUniforms().findLocation("clusterMatrices"); - - locations.clusterIndices = program->getInputs().findLocation("clusterIndices");; - locations.clusterWeights = program->getInputs().findLocation("clusterWeights");; -} - QVector Model::createJointStates(const FBXGeometry& geometry) { QVector jointStates; for (int i = 0; i < geometry.joints.size(); ++i) { @@ -227,7 +233,7 @@ void Model::initJointTransforms() { } void Model::init() { - if (_program.isNull()) { + if (_renderPipelineLib.empty()) { gpu::Shader::BindingSet slotBindings; slotBindings.insert(gpu::Shader::Binding(std::string("materialBuffer"), MATERIAL_GPU_SLOT)); slotBindings.insert(gpu::Shader::Binding(std::string("diffuseMap"), 0)); @@ -257,74 +263,69 @@ void Model::init() { auto modelLightmapSpecularMapPixel = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_lightmap_specular_map_frag))); auto modelLightmapNormalSpecularMapPixel = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_lightmap_normal_specular_map_frag))); + // Fill the renderPipelineLib + _renderPipelineLib.addRenderPipeline( + RenderKey(0), + modelVertex, modelPixel); - bool makeResult = false; + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::HAS_TANGENTS), + modelNormalMapVertex, modelNormalMapPixel); - // Programs - _program = gpu::ShaderPointer(gpu::Shader::createProgram(modelVertex, modelPixel)); - makeResult = gpu::Shader::makeProgram(*_program, slotBindings); - initProgram(_program, _locations); + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::HAS_SPECULAR), + modelVertex, modelSpecularMapPixel); - _normalMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelNormalMapVertex, modelNormalMapPixel)); - makeResult = gpu::Shader::makeProgram(*_normalMapProgram, slotBindings); - initProgram(_normalMapProgram, _normalMapLocations); + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR), + modelNormalMapVertex, modelNormalSpecularMapPixel); - _specularMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelVertex, modelSpecularMapPixel)); - makeResult = gpu::Shader::makeProgram(*_specularMapProgram, slotBindings); - initProgram(_specularMapProgram, _specularMapLocations); + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::IS_TRANSLUCENT), + modelVertex, modelTranslucentPixel); + + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::IS_DEPTH_ONLY), + modelShadowVertex, modelShadowPixel); + + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::HAS_LIGHTMAP), + modelLightmapVertex, modelLightmapPixel); + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::HAS_LIGHTMAP | RenderKey::HAS_TANGENTS), + modelLightmapNormalMapVertex, modelLightmapNormalMapPixel); - _normalSpecularMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelNormalMapVertex, modelNormalSpecularMapPixel)); - makeResult = gpu::Shader::makeProgram(*_normalSpecularMapProgram, slotBindings); - initProgram(_normalSpecularMapProgram, _normalSpecularMapLocations); + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::HAS_LIGHTMAP | RenderKey::HAS_SPECULAR), + modelLightmapVertex, modelLightmapSpecularMapPixel); - _translucentProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelVertex, modelTranslucentPixel)); - makeResult = gpu::Shader::makeProgram(*_translucentProgram, slotBindings); - initProgram(_translucentProgram, _translucentLocations); - - _shadowProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelShadowVertex, modelShadowPixel)); - makeResult = gpu::Shader::makeProgram(*_shadowProgram, slotBindings); - Model::Locations tempShadowLoc; - initProgram(_shadowProgram, tempShadowLoc); + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::HAS_LIGHTMAP | RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR), + modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel); - _lightmapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelLightmapVertex, modelLightmapPixel)); - makeResult = gpu::Shader::makeProgram(*_lightmapProgram, slotBindings); - initProgram(_lightmapProgram, _lightmapLocations); + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::IS_SKINNED), + skinModelVertex, modelPixel); - _lightmapNormalMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelLightmapNormalMapVertex, modelLightmapNormalMapPixel)); - makeResult = gpu::Shader::makeProgram(*_lightmapNormalMapProgram, slotBindings); - initProgram(_lightmapNormalMapProgram, _lightmapNormalMapLocations); + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_TANGENTS), + skinModelNormalMapVertex, modelNormalMapPixel); - _lightmapSpecularMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelLightmapVertex, modelLightmapSpecularMapPixel)); - makeResult = gpu::Shader::makeProgram(*_lightmapSpecularMapProgram, slotBindings); - initProgram(_lightmapSpecularMapProgram, _lightmapSpecularMapLocations); + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_SPECULAR), + skinModelVertex, modelSpecularMapPixel); - _lightmapNormalSpecularMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(modelLightmapNormalMapVertex, modelLightmapNormalSpecularMapPixel)); - makeResult = gpu::Shader::makeProgram(*_lightmapNormalSpecularMapProgram, slotBindings); - initProgram(_lightmapNormalSpecularMapProgram, _lightmapNormalSpecularMapLocations); + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR), + skinModelNormalMapVertex, modelNormalSpecularMapPixel); - _skinProgram = gpu::ShaderPointer(gpu::Shader::createProgram(skinModelVertex, modelPixel)); - makeResult = gpu::Shader::makeProgram(*_skinProgram, slotBindings); - initSkinProgram(_skinProgram, _skinLocations); + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::IS_SKINNED | RenderKey::IS_DEPTH_ONLY), + skinModelShadowVertex, modelShadowPixel); - _skinNormalMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(skinModelNormalMapVertex, modelNormalMapPixel)); - makeResult = gpu::Shader::makeProgram(*_skinNormalMapProgram, slotBindings); - initSkinProgram(_skinNormalMapProgram, _skinNormalMapLocations); - - _skinSpecularMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(skinModelVertex, modelSpecularMapPixel)); - makeResult = gpu::Shader::makeProgram(*_skinSpecularMapProgram, slotBindings); - initSkinProgram(_skinSpecularMapProgram, _skinSpecularMapLocations); - - _skinNormalSpecularMapProgram = gpu::ShaderPointer(gpu::Shader::createProgram(skinModelNormalMapVertex, modelNormalSpecularMapPixel)); - makeResult = gpu::Shader::makeProgram(*_skinNormalSpecularMapProgram, slotBindings); - initSkinProgram(_skinNormalSpecularMapProgram, _skinNormalSpecularMapLocations); - - _skinShadowProgram = gpu::ShaderPointer(gpu::Shader::createProgram(skinModelShadowVertex, modelShadowPixel)); - makeResult = gpu::Shader::makeProgram(*_skinShadowProgram, slotBindings); - initSkinProgram(_skinShadowProgram, _skinShadowLocations); - - _skinTranslucentProgram = gpu::ShaderPointer(gpu::Shader::createProgram(skinModelVertex, modelTranslucentPixel)); - makeResult = gpu::Shader::makeProgram(*_skinTranslucentProgram, slotBindings); - initSkinProgram(_skinTranslucentProgram, _skinTranslucentLocations); + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::IS_SKINNED | RenderKey::IS_TRANSLUCENT), + skinModelVertex, modelTranslucentPixel); } } @@ -2249,81 +2250,24 @@ QVector* Model::pickMeshList(bool translucent, float alphaThreshold, bool h void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, - Locations*& locations, SkinLocations*& skinLocations) { - gpu::ShaderPointer program = _program; - locations = &_locations; - gpu::ShaderPointer skinProgram = _skinProgram; - skinLocations = &_skinLocations; - if (mode == SHADOW_RENDER_MODE) { - program = _shadowProgram; - skinProgram = _skinShadowProgram; - skinLocations = &_skinShadowLocations; - } else if (translucent && alphaThreshold == 0.0f) { - program = _translucentProgram; - locations = &_translucentLocations; - skinProgram = _skinTranslucentProgram; - skinLocations = &_skinTranslucentLocations; - - } else if (hasLightmap) { - if (hasTangents) { - if (hasSpecular) { - program = _lightmapNormalSpecularMapProgram; - locations = &_lightmapNormalSpecularMapLocations; - skinProgram.reset(); - skinLocations = NULL; - } else { - program = _lightmapNormalMapProgram; - locations = &_lightmapNormalMapLocations; - skinProgram.reset(); - skinLocations = NULL; - } - } else if (hasSpecular) { - program = _lightmapSpecularMapProgram; - locations = &_lightmapSpecularMapLocations; - skinProgram.reset(); - skinLocations = NULL; - } else { - program = _lightmapProgram; - locations = &_lightmapLocations; - skinProgram.reset(); - skinLocations = NULL; - } - } else { - if (hasTangents) { - if (hasSpecular) { - program = _normalSpecularMapProgram; - locations = &_normalSpecularMapLocations; - skinProgram = _skinNormalSpecularMapProgram; - skinLocations = &_skinNormalSpecularMapLocations; - } else { - program = _normalMapProgram; - locations = &_normalMapLocations; - skinProgram = _skinNormalMapProgram; - skinLocations = &_skinNormalMapLocations; - } - } else if (hasSpecular) { - program = _specularMapProgram; - locations = &_specularMapLocations; - skinProgram = _skinSpecularMapProgram; - skinLocations = &_skinSpecularMapLocations; - } - } + Locations*& locations) { - gpu::ShaderPointer activeProgram = program; - Locations* activeLocations = locations; - - if (isSkinned) { - activeProgram = skinProgram; - activeLocations = skinLocations; - locations = skinLocations; + RenderKey key(mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned); + auto pipeline = _renderPipelineLib.find(key.getRaw()); + if (pipeline == _renderPipelineLib.end()) { + qDebug() << "No good, couldn;t find a pipeline from the key ?" << key.getRaw(); + return; } - GLuint glprogram = gpu::GLBackend::getShaderID(activeProgram); + gpu::ShaderPointer program = (*pipeline).second._pipeline->getProgram(); + locations = (*pipeline).second._locations.get(); + + GLuint glprogram = gpu::GLBackend::getShaderID(program); GLBATCH(glUseProgram)(glprogram); - if ((activeLocations->alphaThreshold > -1) && (mode != SHADOW_RENDER_MODE)) { - GLBATCH(glUniform1f)(activeLocations->alphaThreshold, alphaThreshold); + if ((locations->alphaThreshold > -1) && (mode != SHADOW_RENDER_MODE)) { + GLBATCH(glUniform1f)(locations->alphaThreshold, alphaThreshold); } } @@ -2335,7 +2279,6 @@ int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool bool pickProgramsNeeded = true; Locations* locations; - SkinLocations* skinLocations; foreach(Model* model, _modelsInScene) { QVector* whichList = model->pickMeshList(translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned); @@ -2343,11 +2286,11 @@ int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool QVector& list = *whichList; if (list.size() > 0) { if (pickProgramsNeeded) { - pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, args, locations, skinLocations); + pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, args, locations); pickProgramsNeeded = false; } model->setupBatchTransform(batch); - meshPartsRendered += model->renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, locations, skinLocations); + meshPartsRendered += model->renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, locations); } } } @@ -2379,11 +2322,10 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl } Locations* locations; - SkinLocations* skinLocations; pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, - args, locations, skinLocations); + args, locations); meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, - args, locations, skinLocations, forceRenderSomeMeshes); + args, locations, forceRenderSomeMeshes); GLBATCH(glUseProgram)(0); return meshPartsRendered; @@ -2391,7 +2333,7 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, RenderArgs* args, - Locations* locations, SkinLocations* skinLocations, bool forceRenderSomeMeshes) { + Locations* locations, bool forceRenderSomeMeshes) { PROFILE_RANGE(__FUNCTION__); auto textureCache = DependencyManager::get(); @@ -2462,7 +2404,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod const MeshState& state = _meshStates.at(i); if (state.clusterMatrices.size() > 1) { - GLBATCH(glUniformMatrix4fv)(skinLocations->clusterMatrices, state.clusterMatrices.size(), false, + GLBATCH(glUniformMatrix4fv)(locations->clusterMatrices, state.clusterMatrices.size(), false, (const float*)state.clusterMatrices.constData()); batch.setModelTransform(Transform()); } else { diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 2e3f358635..bce534416c 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -18,12 +18,16 @@ #include #include +#include +#include + #include #include #include #include #include #include +#include #include "PhysicsEntity.h" #include @@ -318,50 +322,6 @@ 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; - static gpu::ShaderPointer _normalSpecularMapProgram; - static gpu::ShaderPointer _translucentProgram; - - static gpu::ShaderPointer _lightmapProgram; - static gpu::ShaderPointer _lightmapNormalMapProgram; - static gpu::ShaderPointer _lightmapSpecularMapProgram; - static gpu::ShaderPointer _lightmapNormalSpecularMapProgram; - - static gpu::ShaderPointer _shadowProgram; - - static gpu::ShaderPointer _skinProgram; - static gpu::ShaderPointer _skinNormalMapProgram; - static gpu::ShaderPointer _skinSpecularMapProgram; - static gpu::ShaderPointer _skinNormalSpecularMapProgram; - static gpu::ShaderPointer _skinTranslucentProgram; - - static gpu::ShaderPointer _skinShadowProgram; - class Locations { public: int tangent; @@ -372,38 +332,10 @@ private: int emissiveParams; int glowIntensity; int materialBufferUnit; - }; - - static Locations _locations; - static Locations _normalMapLocations; - static Locations _specularMapLocations; - static Locations _normalSpecularMapLocations; - static Locations _translucentLocations; - - static Locations _lightmapLocations; - static Locations _lightmapNormalMapLocations; - static Locations _lightmapSpecularMapLocations; - static Locations _lightmapNormalSpecularMapLocations; - - static void initProgram(ProgramObject& program, Locations& locations, bool link = true); - static void initProgram(gpu::ShaderPointer& program, Locations& locations); - - class SkinLocations : public Locations { - public: int clusterMatrices; int clusterIndices; int clusterWeights; }; - - static SkinLocations _skinLocations; - static SkinLocations _skinNormalMapLocations; - static SkinLocations _skinSpecularMapLocations; - static SkinLocations _skinNormalSpecularMapLocations; - static SkinLocations _skinShadowLocations; - static SkinLocations _skinTranslucentLocations; - - static void initSkinProgram(ProgramObject& program, SkinLocations& locations); - static void initSkinProgram(gpu::ShaderPointer& program, SkinLocations& locations); QVector _calculatedMeshBoxes; // world coordinate AABoxes for all sub mesh boxes bool _calculatedMeshBoxesValid; @@ -489,12 +421,12 @@ private: QVector* pickMeshList(bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned); int renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, - RenderArgs* args, Locations* locations, SkinLocations* skinLocations, + RenderArgs* args, Locations* locations, bool forceRenderSomeMeshes = false); static void pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, - Locations*& locations, SkinLocations*& skinLocations); + Locations*& locations); static int renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args); @@ -502,17 +434,90 @@ private: static AbstractViewStateInterface* _viewState; - /* class RenderKey { + class RenderKey { public: - enum Flag { - TRANSLUCENT = 0, - HAS_LIGHTMAP, + enum FlagBit { + IS_TRANSLUCENT_FLAG = 0, + HAS_LIGHTMAP_FLAG, + HAS_TANGENTS_FLAG, + HAS_SPECULAR_FLAG, + HAS_EMISSIVE_FLAG, + IS_SKINNED_FLAG, + IS_STEREO_FLAG, + IS_DEPTH_ONLY_FLAG, + IS_SHADOW_FLAG, + + NUM_FLAGS, }; + + enum Flag { + IS_TRANSLUCENT = (1 << IS_TRANSLUCENT_FLAG), + HAS_LIGHTMAP = (1 << HAS_LIGHTMAP_FLAG), + HAS_TANGENTS = (1 << HAS_TANGENTS_FLAG), + HAS_SPECULAR = (1 << HAS_SPECULAR_FLAG), + HAS_EMISSIVE = (1 << HAS_EMISSIVE_FLAG), + IS_SKINNED = (1 << IS_SKINNED_FLAG), + IS_STEREO = (1 << IS_STEREO_FLAG), + IS_DEPTH_ONLY = (1 << IS_DEPTH_ONLY_FLAG), + IS_SHADOW = (1 << IS_SHADOW_FLAG), - RenderMode mode; + }; + typedef unsigned short Flags; + + + bool isFlag(short flagNum) const { return bool((_flags & flagNum) != 0); } + + bool isTranslucent() const { return isFlag(IS_TRANSLUCENT); } + bool hasLightmap() const { return isFlag(HAS_LIGHTMAP); } + bool hasTangents() const { return isFlag(HAS_TANGENTS); } + bool HasSpecular() const { return isFlag(HAS_SPECULAR); } + bool HasEmissive() const { return isFlag(HAS_EMISSIVE); } + bool isSkinned() const { return isFlag(IS_SKINNED); } + bool isStereo() const { return isFlag(IS_STEREO); } + bool isDepthOnly() const { return isFlag(IS_DEPTH_ONLY); } + bool isShadow() const { return isFlag(IS_SHADOW); } // = depth only but with back facing + + Flags _flags = 0; + short _spare = 0; + + int getRaw() { return *reinterpret_cast(this); } + + RenderKey(RenderMode mode, + bool translucent, float alphaThreshold, bool hasLightmap, + bool hasTangents, bool hasSpecular, bool isSkinned) : + RenderKey( ((translucent && (alphaThreshold == 0.0f)) ? IS_TRANSLUCENT : 0) + | (hasLightmap && (mode != SHADOW_RENDER_MODE) ? HAS_LIGHTMAP : 0) // Lightmap, tangents and specular don't matter for depthOnly + | (hasTangents && (mode != SHADOW_RENDER_MODE) ? HAS_TANGENTS : 0) + | (hasSpecular && (mode != SHADOW_RENDER_MODE) ? HAS_SPECULAR : 0) + | (isSkinned ? IS_SKINNED : 0) + | ((mode == SHADOW_RENDER_MODE) ? IS_DEPTH_ONLY : 0) + | ((mode == SHADOW_RENDER_MODE) ? IS_SHADOW : 0)) {} + + RenderKey(int bitmask) : _flags(bitmask) {} }; -*/ + + + class RenderPipeline { + public: + gpu::PipelinePointer _pipeline; + std::shared_ptr _locations; + RenderPipeline(gpu::PipelinePointer& pipeline, std::shared_ptr& locations) : + _pipeline(pipeline), _locations(locations) {} + }; + + typedef std::unordered_map BaseRenderPipelineMap; + class RenderPipelineLib : public BaseRenderPipelineMap { + public: + typedef RenderKey Key; + + + void addRenderPipeline(Key& key, gpu::ShaderPointer& vertexShader, gpu::ShaderPointer& pixelShader); + + void initLocations(gpu::ShaderPointer& program, Locations& locations); + }; + static RenderPipelineLib _renderPipelineLib; + }; Q_DECLARE_METATYPE(QPointer) From c9377d0811744fa424f654d9e60c0af545939854 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 25 Mar 2015 10:16:18 -0700 Subject: [PATCH 05/21] the model renderer now uses the map of renderPIpeline and the pipeline object of gpu, yeah. fixed the state to do the basics glState stuff correctly --- libraries/gpu/src/gpu/GLBackend.h | 28 +++- libraries/gpu/src/gpu/GLBackendPipeline.cpp | 10 +- libraries/gpu/src/gpu/GLBackendState.cpp | 164 ++++++++++++++------ libraries/gpu/src/gpu/Pipeline.h | 2 +- libraries/gpu/src/gpu/State.cpp | 14 +- libraries/gpu/src/gpu/State.h | 21 ++- libraries/render-utils/src/Model.cpp | 51 +++--- libraries/render-utils/src/Model.h | 5 +- 8 files changed, 198 insertions(+), 97 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index bbb2b5a1d2..8a65263df0 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -80,7 +80,7 @@ public: class Command { public: - virtual void run() = 0; + virtual void run(GLBackend* backend) = 0; Command() {} virtual ~Command() {}; @@ -88,9 +88,9 @@ public: template class Command1 : public Command { public: - typedef void (*GLFunction)(typename T); + typedef void (GLBackend::*GLFunction)(typename T); - void run() { (_func)(_param); } + void run(GLBackend* backend) { (backend->*(_func))(_param); } Command1(GLFunction func, T param) : _func(func), _param(param) {}; @@ -101,7 +101,7 @@ public: public: typedef void (*GLFunction)(typename T, typename U); - void run() { (_func)(_param0, _param1); } + void run(GLBackend* backend) { (_func)(_param0, _param1); } Command2(GLFunction func, T param0, U param1) : _func(func), _param0(param0), _param1(param1) {}; @@ -114,7 +114,7 @@ public: public: typedef void (*GLFunction)(typename T, typename U, typename V, typename W); - void run() { (_func)(_param0, _param1, _param2, _param3); } + void run(GLBackend* backend) { (_func)(_param0, _param1, _param2, _param3); } Command4(GLFunction func, T param0, U param1, V param2, W param3) : _func(func), @@ -155,6 +155,24 @@ public: uint32 getNumInputBuffers() const { return _input._buffersState.size(); } + + + 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_setStateDepthTest(State::DepthTest test); + + void do_setStateStencilEnable(int32 enable); + + void do_setStateAlphaToCoverageEnable(int32 enable); + + void do_setStateBlendEnable(int32 enable); + protected: // Draw Stage diff --git a/libraries/gpu/src/gpu/GLBackendPipeline.cpp b/libraries/gpu/src/gpu/GLBackendPipeline.cpp index 77ec721276..30bebb3049 100755 --- a/libraries/gpu/src/gpu/GLBackendPipeline.cpp +++ b/libraries/gpu/src/gpu/GLBackendPipeline.cpp @@ -79,6 +79,13 @@ void GLBackend::do_setPipeline(Batch& batch, uint32 paramOffset) { _pipeline._stateCommands = pipelineObject->_state->_commands; _pipeline._invalidState = true; + + // THis should be done on Pipeline::update... + if (_pipeline._invalidProgram) { + glUseProgram(_pipeline._program); + CHECK_GL_ERROR(); + _pipeline._invalidProgram = false; + } } void GLBackend::do_setUniformBuffer(Batch& batch, uint32 paramOffset) { @@ -115,6 +122,7 @@ void GLBackend::do_setUniformTexture(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; @@ -122,7 +130,7 @@ void GLBackend::updatePipeline() { if (_pipeline._invalidState) { for (auto command: _pipeline._stateCommands) { - command->run(); + command->run(this); } CHECK_GL_ERROR(); _pipeline._invalidState = false; diff --git a/libraries/gpu/src/gpu/GLBackendState.cpp b/libraries/gpu/src/gpu/GLBackendState.cpp index 6a93e2c842..9fa515b2c4 100644 --- a/libraries/gpu/src/gpu/GLBackendState.cpp +++ b/libraries/gpu/src/gpu/GLBackendState.cpp @@ -23,6 +23,8 @@ GLBackend::GLState::~GLState() { typedef GLBackend::GLState::Command Command; typedef GLBackend::GLState::CommandPointer CommandPointer; +typedef GLBackend::GLState::Command1 Command1I; +typedef GLBackend::GLState::Command1 Command1DT; typedef GLBackend::GLState::Command1 Command1E; typedef GLBackend::GLState::Command2 Command2E; typedef GLBackend::GLState::Command2 Command2F; @@ -40,27 +42,16 @@ static GLenum GL_COMPARISON_FUNCTIONS[] = { 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 generateFillMode(GLBackend::GLState::Commands& commands, State::FillMode fillMode) { + commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateFillMode, int32(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]))); - } + 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)) { + /* 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)))); @@ -71,53 +62,39 @@ void generateDepthBias(GLBackend::GLState::Commands& commands, const State& stat 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]))); + commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateFrontClockwise, int32(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); + commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateDepthClipEnable, int32(enable)))); } void generateScissorEnable(GLBackend::GLState::Commands& commands, bool enable) { - ADD_ENABLE_DISABLE_COMMAND(GL_SCISSOR_TEST); + commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateScissorEnable, int32(enable)))); } void generateMultisampleEnable(GLBackend::GLState::Commands& commands, bool enable) { - ADD_ENABLE_DISABLE_COMMAND(GL_MULTISAMPLE); + commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateMultisampleEnable, int32(enable)))); } void generateAntialiasedLineEnable(GLBackend::GLState::Commands& commands, bool enable) { - ADD_ENABLE_DISABLE_COMMAND(GL_POINT_SMOOTH); - ADD_ENABLE_DISABLE_COMMAND(GL_LINE_SMOOTH); + commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateAntialiasedLineEnable, int32(enable)))); } void generateDepthTest(GLBackend::GLState::Commands& commands, State::DepthTest& test) { - if (!test._enabled) { - commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDisable, GLenum(GL_DEPTH_TEST)))); - } else { - commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glEnable, GLenum(GL_DEPTH_TEST)))); - commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDepthMask, test._writeMask))); - commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDepthFunc, GL_COMPARISON_FUNCTIONS[test._function]))); - } + commands.push_back(CommandPointer(new Command1DT(&GLBackend::do_setStateDepthTest, int32(test.getRaw())))); } void generateStencilEnable(GLBackend::GLState::Commands& commands, bool enable) { - ADD_ENABLE_DISABLE_COMMAND(GL_STENCIL_TEST); + commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateStencilEnable, int32(enable)))); } void generateStencilWriteMask(GLBackend::GLState::Commands& commands, uint32 mask) { - commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glStencilMask, mask))); +// commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glStencilMask, mask))); } void generateStencilState(GLBackend::GLState::Commands& commands, const State& state) { @@ -146,11 +123,11 @@ void generateStencilState(GLBackend::GLState::Commands& commands, const State& s } void generateAlphaToCoverageEnable(GLBackend::GLState::Commands& commands, bool enable) { - ADD_ENABLE_DISABLE_COMMAND(GL_SAMPLE_ALPHA_TO_COVERAGE); + commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateAlphaToCoverageEnable, int32(enable)))); } void generateBlendEnable(GLBackend::GLState::Commands& commands, bool enable) { - ADD_ENABLE_DISABLE_COMMAND(GL_BLEND); + commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateBlendEnable, int32(enable)))); } void generateBlendFunction(GLBackend::GLState::Commands& commands, const State& state) { @@ -209,9 +186,7 @@ GLBackend::GLState* GLBackend::syncGPUObject(const State& state) { // If GPU object already created then good if (object) { - if (object->_stamp == state.getStamp()) { - return object; - } + return object; } // Else allocate and create the GLState @@ -269,7 +244,6 @@ GLBackend::GLState* GLBackend::syncGPUObject(const State& state) { generateAntialiasedLineEnable(object->_commands, bool(field.second._integer)); break; } - case State::DEPTH_TEST: { generateDepthTest(object->_commands, State::DepthTest(field.second._integer)); break; @@ -337,5 +311,105 @@ GLBackend::GLState* GLBackend::syncGPUObject(const State& state) { generateBlendFactor(object->_commands, state.getBlendFactor()); } - return nullptr; + return object; +} + + +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(); +} + +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]); + } +} + +void GLBackend::do_setStateFrontClockwise(int32 isFrontClockwise) { + static GLenum GL_FRONT_FACES[] = { GL_CCW, GL_CW }; + glFrontFace(GL_FRONT_FACES[isFrontClockwise]); +} + +void GLBackend::do_setStateDepthClipEnable(int32 enable) { + if (enable) { + glEnable(GL_DEPTH_CLAMP); + } else { + glDisable(GL_DEPTH_CLAMP); + } + CHECK_GL_ERROR(); +} + +void GLBackend::do_setStateScissorEnable(int32 enable) { + if (enable) { + glEnable(GL_SCISSOR_TEST); + } else { + glDisable(GL_SCISSOR_TEST); + } + CHECK_GL_ERROR(); +} + +void GLBackend::do_setStateMultisampleEnable(int32 enable) { + if (enable) { + glEnable(GL_MULTISAMPLE); + } else { + glDisable(GL_MULTISAMPLE); + } + 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); + } + CHECK_GL_ERROR(); +} + +void GLBackend::do_setStateDepthTest(State::DepthTest test) { + if (test._enabled) { + glEnable(GL_DEPTH_TEST); + glDepthMask(test._writeMask); + glDepthFunc(GL_COMPARISON_FUNCTIONS[test._function]); + } else { + glDisable(GL_DEPTH_TEST); + } + CHECK_GL_ERROR(); +} + +void GLBackend::do_setStateStencilEnable(int32 enable) { + if (enable) { + glEnable(GL_STENCIL_TEST); + } else { + glDisable(GL_STENCIL_TEST); + } + CHECK_GL_ERROR(); +} + +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_setStateBlendEnable(int32 enable) { + if (enable) { + glEnable(GL_BLEND); + } else { + glDisable(GL_BLEND); + } + CHECK_GL_ERROR(); } diff --git a/libraries/gpu/src/gpu/Pipeline.h b/libraries/gpu/src/gpu/Pipeline.h index 189bdc4f00..73e9a29913 100755 --- a/libraries/gpu/src/gpu/Pipeline.h +++ b/libraries/gpu/src/gpu/Pipeline.h @@ -38,7 +38,7 @@ protected: Pipeline& operator=(const Pipeline& pipeline); // deep copy of the sysmem texture // This shouldn't be used by anything else than the Backend class with the proper casting. - mutable GPUObject* _gpuObject = NULL; + mutable GPUObject* _gpuObject = nullptr; void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; } GPUObject* getGPUObject() const { return _gpuObject; } friend class Backend; diff --git a/libraries/gpu/src/gpu/State.cpp b/libraries/gpu/src/gpu/State.cpp index 13dd24fbcc..1a0dad3a8c 100755 --- a/libraries/gpu/src/gpu/State.cpp +++ b/libraries/gpu/src/gpu/State.cpp @@ -20,26 +20,22 @@ State::~State() } void State::set(Field field, bool value) { - auto found = _fields[field]; - found._integer = value; + _fields[field]._integer = value; _stamp++; } void State::set(Field field, uint32 value) { - auto found = _fields[field]; - found._unsigned_integer = value; + _fields[field]._unsigned_integer = value; _stamp++; } void State::set(Field field, int32 value) { - auto found = _fields[field]; - found._integer = value; + _fields[field]._integer = value; _stamp++; } void State::set(Field field, float value) { - auto found = _fields[field]; - found._float = value; + _fields[field]._float = value; _stamp++; } @@ -49,4 +45,4 @@ State::Value State::get(Field field) const { return (*found).second; } return Value(); -} \ No newline at end of file +} diff --git a/libraries/gpu/src/gpu/State.h b/libraries/gpu/src/gpu/State.h index c3c73cefa4..deaf8c8271 100755 --- a/libraries/gpu/src/gpu/State.h +++ b/libraries/gpu/src/gpu/State.h @@ -149,11 +149,13 @@ public: class DepthTest { public: + uint8 _function = LESS; + bool _writeMask = true; + bool _enabled = false; + DepthTest(bool enable, bool writeMask, ComparisonFunction func) : _function(func), _writeMask(writeMask), _enabled(enable) {} - uint8 _function = ALWAYS; - bool _writeMask = false; - bool _enabled = false; + int32 getRaw() const { return *(reinterpret_cast(this)); } DepthTest(int32 raw) { *(reinterpret_cast(this)) = raw; } @@ -190,7 +192,7 @@ public: class Value { public: union { - uint32 _unsigned_integer; + uint32 _unsigned_integer = 0; int32 _integer; float _float; }; @@ -207,17 +209,20 @@ public: Value get(Field field) const; void setFillMode(FillMode fill) { set(FILL_MODE, uint32(fill)); } - void setCullMode(CullMode cull) { set(FILL_MODE, uint32(cull)); } FillMode getFillMode() const { return FillMode(get(FILL_MODE)._integer); } + + void setCullMode(CullMode cull) { set(CULL_MODE, uint32(cull)); } CullMode getCullMode() const { return CullMode(get(CULL_MODE)._integer); } + void setFrontClockwise(bool enable) { set(FRONT_CLOCKWISE, enable); } + void setDepthClipEnable(bool enable) { set(DEPTH_CLIP_ENABLE, enable); } + 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)._integer; } float getDepthBiasSlopeScale() const { return get(DEPTH_BIAS_SLOPE_SCALE)._float; } - void setFrontClockwise(bool enable) { set(FRONT_CLOCKWISE, enable); } - void setDepthClipEnable(bool enable) { set(DEPTH_CLIP_ENABLE, enable); } + void setScissorEnable(bool enable) { set(SCISSOR_ENABLE, enable); } void setMultisampleEnable(bool enable) { set(MULTISAMPLE_ENABLE, enable); } void setAntialiasedLineEnable(bool enable) { set(ANTIALISED_LINE_ENABLE, enable); } @@ -278,7 +283,7 @@ protected: Stamp _stamp; // This shouldn't be used by anything else than the Backend class with the proper casting. - mutable GPUObject* _gpuObject = NULL; + mutable GPUObject* _gpuObject = nullptr; void setGPUObject(GPUObject* gpuObject) const { _gpuObject = gpuObject; } GPUObject* getGPUObject() const { return _gpuObject; } friend class Backend; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 7a40b2feed..8bd48c16f8 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -116,26 +116,19 @@ void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey& key, initLocations(program, *locations); gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + + // Backface on shadow if (key.isShadow()) { state->setCullMode(gpu::State::CULL_FRONT); } else { state->setCullMode(gpu::State::CULL_BACK); } - if (key.isTranslucent()) { - } else { - state->setBlendEnable(false); - } - - /* - GLBATCH(glDisable)(GL_BLEND); - GLBATCH(glEnable)(GL_ALPHA_TEST); - - if (mode == SHADOW_RENDER_MODE) { - GLBATCH(glAlphaFunc)(GL_EQUAL, 0.0f); - } - */ + // Z test depends if transparent or not + state->setDepthTest(true, !key.isTranslucent(), gpu::State::LESS_EQUAL); + // Blend on transparent + state->setBlendEnable(key.isTranslucent()); auto it = insert(value_type(key.getRaw(), RenderPipeline( @@ -285,7 +278,7 @@ void Model::init() { modelVertex, modelTranslucentPixel); _renderPipelineLib.addRenderPipeline( - RenderKey(RenderKey::IS_DEPTH_ONLY), + RenderKey(RenderKey::IS_DEPTH_ONLY | RenderKey::IS_SHADOW), modelShadowVertex, modelShadowPixel); _renderPipelineLib.addRenderPipeline( @@ -320,7 +313,7 @@ void Model::init() { skinModelNormalMapVertex, modelNormalSpecularMapPixel); _renderPipelineLib.addRenderPipeline( - RenderKey(RenderKey::IS_SKINNED | RenderKey::IS_DEPTH_ONLY), + RenderKey(RenderKey::IS_SKINNED | RenderKey::IS_DEPTH_ONLY | RenderKey::IS_SHADOW), skinModelShadowVertex, modelShadowPixel); _renderPipelineLib.addRenderPipeline( @@ -684,7 +677,8 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { GLBATCH(glDisable)(GL_COLOR_MATERIAL); - if (mode == DIFFUSE_RENDER_MODE || mode == NORMAL_RENDER_MODE) { + // taking care of by the state? + /* if (mode == DIFFUSE_RENDER_MODE || mode == NORMAL_RENDER_MODE) { GLBATCH(glDisable)(GL_CULL_FACE); } else { GLBATCH(glEnable)(GL_CULL_FACE); @@ -692,10 +686,11 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { GLBATCH(glCullFace)(GL_FRONT); } } - + */ + // render opaque meshes with alpha testing - GLBATCH(glDisable)(GL_BLEND); +// GLBATCH(glDisable)(GL_BLEND); GLBATCH(glEnable)(GL_ALPHA_TEST); if (mode == SHADOW_RENDER_MODE) { @@ -764,10 +759,10 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, true, args); GLBATCH(glDisable)(GL_ALPHA_TEST); - GLBATCH(glEnable)(GL_BLEND); + /* GLBATCH(glEnable)(GL_BLEND); GLBATCH(glDepthMask)(false); GLBATCH(glDepthFunc)(GL_LEQUAL); - + */ //DependencyManager::get()->setPrimaryDrawBuffers(true); { GLenum buffers[1]; @@ -1740,18 +1735,18 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { GLBATCH(glDisable)(GL_COLOR_MATERIAL); - if (mode == DIFFUSE_RENDER_MODE || mode == NORMAL_RENDER_MODE) { + /* if (mode == DIFFUSE_RENDER_MODE || mode == NORMAL_RENDER_MODE) { GLBATCH(glDisable)(GL_CULL_FACE); } else { GLBATCH(glEnable)(GL_CULL_FACE); if (mode == SHADOW_RENDER_MODE) { GLBATCH(glCullFace)(GL_FRONT); } - } + }*/ // render opaque meshes with alpha testing - GLBATCH(glDisable)(GL_BLEND); + // GLBATCH(glDisable)(GL_BLEND); GLBATCH(glEnable)(GL_ALPHA_TEST); if (mode == SHADOW_RENDER_MODE) { @@ -1820,10 +1815,10 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, true, args); GLBATCH(glDisable)(GL_ALPHA_TEST); - GLBATCH(glEnable)(GL_BLEND); + /* GLBATCH(glEnable)(GL_BLEND); GLBATCH(glDepthMask)(false); GLBATCH(glDepthFunc)(GL_LEQUAL); - + */ //DependencyManager::get()->setPrimaryDrawBuffers(true); { GLenum buffers[1]; @@ -2262,9 +2257,11 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f gpu::ShaderPointer program = (*pipeline).second._pipeline->getProgram(); locations = (*pipeline).second._locations.get(); - GLuint glprogram = gpu::GLBackend::getShaderID(program); - GLBATCH(glUseProgram)(glprogram); + //GLuint glprogram = gpu::GLBackend::getShaderID(program); + //GLBATCH(glUseProgram)(glprogram); + // dare! + batch.setPipeline((*pipeline).second._pipeline); if ((locations->alphaThreshold > -1) && (mode != SHADOW_RENDER_MODE)) { GLBATCH(glUniform1f)(locations->alphaThreshold, alphaThreshold); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index bce534416c..f771bffbd8 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -373,6 +373,9 @@ private: QMap _unsortedMeshesOpaqueLightmapTangents; QMap _unsortedMeshesOpaqueLightmapTangentsSpecular; QMap _unsortedMeshesOpaqueLightmapSpecular; + + typedef std::unordered_map> MeshListMap; + MeshListMap _sortedMeshes; QVector _meshesTranslucent; QVector _meshesTranslucentTangents; @@ -486,7 +489,7 @@ private: RenderKey(RenderMode mode, bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned) : - RenderKey( ((translucent && (alphaThreshold == 0.0f)) ? IS_TRANSLUCENT : 0) + RenderKey( ((translucent && (alphaThreshold == 0.0f) && (mode != SHADOW_RENDER_MODE)) ? IS_TRANSLUCENT : 0) | (hasLightmap && (mode != SHADOW_RENDER_MODE) ? HAS_LIGHTMAP : 0) // Lightmap, tangents and specular don't matter for depthOnly | (hasTangents && (mode != SHADOW_RENDER_MODE) ? HAS_TANGENTS : 0) | (hasSpecular && (mode != SHADOW_RENDER_MODE) ? HAS_SPECULAR : 0) From c9e03603944107b44c1519a19e19e04f7af885f4 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 26 Mar 2015 13:48:49 -0700 Subject: [PATCH 06/21] using gpu::Pipeline it s mostly working but still glUniforms to get rid of --- libraries/gpu/src/gpu/GLBackend.cpp | 3 +- libraries/gpu/src/gpu/GLBackend.h | 39 ++-- libraries/gpu/src/gpu/GLBackendState.cpp | 230 +++++++++-------------- libraries/gpu/src/gpu/State.h | 162 +++++++++------- libraries/model/src/model/Stage.cpp | 4 +- libraries/render-utils/src/Model.cpp | 4 +- 6 files changed, 203 insertions(+), 239 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 4831ecdd4c..d05ba74b57 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -370,8 +370,9 @@ void GLBackend::do_glUseProgram(Batch& batch, uint32 paramOffset) { } void Batch::_glUniform1f(GLint location, GLfloat v0) { + if (location < 0) + return; ADD_COMMAND_GL(glUniform1f); - _params.push_back(v0); _params.push_back(location); diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 8a65263df0..0ef407df8a 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -79,9 +79,7 @@ public: public: class Command { public: - virtual void run(GLBackend* backend) = 0; - Command() {} virtual ~Command() {}; }; @@ -89,46 +87,32 @@ public: template class Command1 : public Command { public: typedef void (GLBackend::*GLFunction)(typename T); - void run(GLBackend* backend) { (backend->*(_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(GLBackend* backend) { (_func)(_param0, _param1); } - + typedef void (GLBackend::*GLFunction)(typename T, typename U); + void run(GLBackend* backend) { (backend->*(_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 { + template class Command3 : public Command { public: - typedef void (*GLFunction)(typename T, typename U, typename V, typename W); - - void run(GLBackend* backend) { (_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) {}; - + typedef void (GLBackend::*GLFunction)(typename T, typename U, typename 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; T _param0; U _param1; V _param2; - W _param3; }; + typedef std::shared_ptr< Command > CommandPointer; typedef std::vector< CommandPointer > Commands; @@ -137,6 +121,8 @@ public: GLState(); ~GLState(); + + friend class GLBackend; }; static GLState* syncGPUObject(const State& state); @@ -156,7 +142,7 @@ public: uint32 getNumInputBuffers() const { return _input._buffersState.size(); } - + // 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); @@ -167,11 +153,12 @@ public: void do_setStateDepthTest(State::DepthTest test); - void do_setStateStencilEnable(int32 enable); + void do_setStateStencil(State::StencilActivation activation, State::StencilTest frontTest, State::StencilTest backTest); void do_setStateAlphaToCoverageEnable(int32 enable); - void do_setStateBlendEnable(int32 enable); + void do_setStateBlend(State::BlendFunction blendFunction, Vec4 blendFactor); + void do_setStateColorWriteMask(int32 mask); protected: diff --git a/libraries/gpu/src/gpu/GLBackendState.cpp b/libraries/gpu/src/gpu/GLBackendState.cpp index 9fa515b2c4..94304080c5 100644 --- a/libraries/gpu/src/gpu/GLBackendState.cpp +++ b/libraries/gpu/src/gpu/GLBackendState.cpp @@ -24,23 +24,10 @@ GLBackend::GLState::~GLState() { typedef GLBackend::GLState::Command Command; typedef GLBackend::GLState::CommandPointer CommandPointer; typedef GLBackend::GLState::Command1 Command1I; -typedef GLBackend::GLState::Command1 Command1DT; -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 }; +typedef GLBackend::GLState::Command1 CommandDepthTest; +typedef GLBackend::GLState::Command3 CommandStencil; +typedef GLBackend::GLState::Command2 CommandBlend; + void generateFillMode(GLBackend::GLState::Commands& commands, State::FillMode fillMode) { commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateFillMode, int32(fillMode)))); @@ -86,99 +73,23 @@ void generateAntialiasedLineEnable(GLBackend::GLState::Commands& commands, bool } void generateDepthTest(GLBackend::GLState::Commands& commands, State::DepthTest& test) { - commands.push_back(CommandPointer(new Command1DT(&GLBackend::do_setStateDepthTest, int32(test.getRaw())))); + commands.push_back(CommandPointer(new CommandDepthTest(&GLBackend::do_setStateDepthTest, int32(test.getRaw())))); } -void generateStencilEnable(GLBackend::GLState::Commands& commands, bool enable) { - commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateStencilEnable, int32(enable)))); -} - -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 generateStencil(GLBackend::GLState::Commands& commands, const State& state) { + commands.push_back(CommandPointer(new CommandStencil(&GLBackend::do_setStateStencil, state.getStencilActivation(), state.getStencilTestFront(), state.getStencilTestBack()))); } void generateAlphaToCoverageEnable(GLBackend::GLState::Commands& commands, bool enable) { commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateAlphaToCoverageEnable, int32(enable)))); } -void generateBlendEnable(GLBackend::GLState::Commands& commands, bool enable) { - commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateBlendEnable, int32(enable)))); +void generateBlend(GLBackend::GLState::Commands& commands, const State& state) { + commands.push_back(CommandPointer(new CommandBlend(&GLBackend::do_setStateBlend, state.getBlendFunction(), state.getBlendFactor()))); } -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 ))); +void generateColorWriteMask(GLBackend::GLState::Commands& commands, int32 mask) { + commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateColorWriteMask, int32(mask)))); } GLBackend::GLState* GLBackend::syncGPUObject(const State& state) { @@ -200,13 +111,8 @@ GLBackend::GLState* GLBackend::syncGPUObject(const State& state) { object->_stamp = state.getStamp(); bool depthBias = false; - - bool stencilEnabled = false; bool stencilState = false; - - bool blendEnabled = false; - bool blendFunction = false; - bool blendFactor = false; + bool blendState = false; // go thorugh the list of state fields in the State and record the corresponding gl command for (auto field: state.getFields()) { @@ -224,7 +130,7 @@ GLBackend::GLState* GLBackend::syncGPUObject(const State& state) { depthBias = true; break; } - case State::FRONT_CLOCKWISE: { + case State::FRONT_FACE: { generateFrontClockwise(object->_commands, bool(field.second._integer)); break; } @@ -249,14 +155,7 @@ GLBackend::GLState* GLBackend::syncGPUObject(const State& state) { 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_ACTIVATION: case State::STENCIL_TEST_FRONT: case State::STENCIL_TEST_BACK: { stencilState = true; @@ -271,26 +170,17 @@ GLBackend::GLState* GLBackend::syncGPUObject(const State& state) { 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_FUNCTION: case State::BLEND_FACTOR_X: case State::BLEND_FACTOR_Y: case State::BLEND_FACTOR_Z: case State::BLEND_FACTOR_W: { - blendFactor = true; + blendState = true; break; } case State::COLOR_WRITE_MASK: { - generateColorWriteMask(object->_commands, State::ColorMask(field.second._integer)); + generateColorWriteMask(object->_commands, field.second._integer); break; } @@ -301,19 +191,27 @@ GLBackend::GLState* GLBackend::syncGPUObject(const State& state) { generateDepthBias(object->_commands, state); } - if (stencilEnabled) { - generateStencilState(object->_commands, state); - generateStencilWriteMask(object->_commands, state.getStencilWriteMask()); + if (stencilState) { + generateStencil(object->_commands, state); } - if (blendEnabled) { - generateBlendFunction(object->_commands, state); - generateBlendFactor(object->_commands, state.getBlendFactor()); + if (blendState) { + generateBlend(object->_commands, state); } return object; } + +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) { static GLenum GL_FILL_MODES[] = { GL_POINT, GL_LINE, GL_FILL }; @@ -386,9 +284,27 @@ void GLBackend::do_setStateDepthTest(State::DepthTest test) { CHECK_GL_ERROR(); } -void GLBackend::do_setStateStencilEnable(int32 enable) { - if (enable) { +void GLBackend::do_setStateStencil(State::StencilActivation activation, State::StencilTest frontTest, State::StencilTest backTest) { + if (activation._enabled) { glEnable(GL_STENCIL_TEST); + glStencilMaskSeparate(GL_FRONT, activation._frontWriteMask); + glStencilMaskSeparate(GL_BACK, activation._backWriteMask); + + 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._failOp], STENCIL_OPS[frontTest._passOp], STENCIL_OPS[frontTest._depthFailOp]); + glStencilFuncSeparate(GL_FRONT, GL_COMPARISON_FUNCTIONS[frontTest._function], frontTest._reference, frontTest._readMask); + + glStencilFuncSeparate(GL_BACK, STENCIL_OPS[backTest._failOp], STENCIL_OPS[backTest._passOp], STENCIL_OPS[backTest._depthFailOp]); + glStencilFuncSeparate(GL_BACK, GL_COMPARISON_FUNCTIONS[backTest._function], backTest._reference, backTest._readMask); } else { glDisable(GL_STENCIL_TEST); } @@ -404,12 +320,50 @@ void GLBackend::do_setStateAlphaToCoverageEnable(int32 enable) { CHECK_GL_ERROR(); } - -void GLBackend::do_setStateBlendEnable(int32 enable) { - if (enable) { +void GLBackend::do_setStateBlend(State::BlendFunction function, Vec4 factor ) { + if (function._enabled) { 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._operationColor], GL_BLEND_OPS[function._operationAlpha]); + + 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._sourceColor], BLEND_ARGS[function._destinationColor], + BLEND_ARGS[function._sourceAlpha], BLEND_ARGS[function._destinationAlpha]); + + glBlendColor(factor.x, factor.y, factor.z, factor.w); } else { glDisable(GL_BLEND); } CHECK_GL_ERROR(); } + +void GLBackend::do_setStateColorWriteMask(int32 mask) { + glColorMask(mask & State::ColorMask::WRITE_RED, + mask & State::ColorMask::WRITE_GREEN, + mask & State::ColorMask::WRITE_BLUE, + mask & State::ColorMask::WRITE_ALPHA ); +} \ No newline at end of file diff --git a/libraries/gpu/src/gpu/State.h b/libraries/gpu/src/gpu/State.h index deaf8c8271..97990ccfb5 100755 --- a/libraries/gpu/src/gpu/State.h +++ b/libraries/gpu/src/gpu/State.h @@ -32,31 +32,25 @@ public: enum Field { FILL_MODE, CULL_MODE, - - DEPTH_BIAS, - DEPTH_BIAS_SLOPE_SCALE, - - FRONT_CLOCKWISE, + FRONT_FACE, DEPTH_CLIP_ENABLE, SCISSOR_ENABLE, MULTISAMPLE_ENABLE, ANTIALISED_LINE_ENABLE, + DEPTH_BIAS, + DEPTH_BIAS_SLOPE_SCALE, + DEPTH_TEST, - STENCIL_ENABLE, - STENCIL_READ_MASK, - STENCIL_WRITE_MASK, + STENCIL_ACTIVATION, STENCIL_TEST_FRONT, STENCIL_TEST_BACK, - STENCIL_REFERENCE, SAMPLE_MASK, ALPHA_TO_COVERAGE_ENABLE, - BLEND_ENABLE, - BLEND_FUNCTION_COLOR, - BLEND_FUNCTION_ALPHA, + BLEND_FUNCTION, BLEND_FACTOR_X, BLEND_FACTOR_Y, BLEND_FACTOR_Z, @@ -121,9 +115,11 @@ public: DEST_COLOR, INV_DEST_COLOR, SRC_ALPHA_SAT, - BLEND_FACTOR, - INV_BLEND_FACTOR, - + FACTOR_COLOR, + INV_FACTOR_COLOR, + FACTOR_ALPHA, + INV_FACTOR_ALPHA, + NUM_BLEND_ARGS, }; @@ -153,37 +149,65 @@ public: bool _writeMask = true; bool _enabled = false; - DepthTest(bool enable, bool writeMask, ComparisonFunction func) : - _function(func), _writeMask(writeMask), _enabled(enable) {} + DepthTest(bool enabled, bool writeMask, ComparisonFunction func) : + _function(func), _writeMask(writeMask), _enabled(enabled) {} int32 getRaw() const { return *(reinterpret_cast(this)); } DepthTest(int32 raw) { *(reinterpret_cast(this)) = raw; } }; - 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)); } + class StencilTest { + public: + uint8 _reference; + uint8 _readMask; + int8 _function : 4; + int8 _failOp : 4; + int8 _depthFailOp : 4; + int8 _passOp : 4; + + 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), _function(func), _failOp(failOp), _depthFailOp(depthFailOp), _passOp(passOp) {} + + int32 getRaw() const { return *(reinterpret_cast(this)); } StencilTest(int32 raw) { *(reinterpret_cast(this)) = raw; } + }; + + class StencilActivation { + public: + uint8 _frontWriteMask; + uint8 _backWriteMask; + int16 _enabled; + + StencilActivation(bool enabled, uint8 frontWriteMask = 0xFF, uint8 backWriteMask = 0xFF) : + _frontWriteMask(frontWriteMask), _backWriteMask(backWriteMask), _enabled(enabled) {} + + int32 getRaw() const { return *(reinterpret_cast(this)); } + StencilActivation(int32 raw) { *(reinterpret_cast(this)) = raw; } }; + class BlendFunction { public: - int8 _source = ONE; - int8 _operation = BLEND_OP_ADD; - int8 _destination = ZERO; - int8 _spare = 0; + int8 _enabled; + int8 _sourceColor : 4; + int8 _sourceAlpha : 4; + int8 _destinationColor : 4; + int8 _destinationAlpha : 4; + int8 _operationColor : 4; + int8 _operationAlpha : 4; - BlendFunction(BlendArg source, BlendOp operation, BlendArg destination) : - _source(source), _operation(operation), _destination(destination) {} + BlendFunction(bool enabled, + BlendArg sourceColor, BlendOp operationColor, BlendArg destinationColor, + BlendArg sourceAlpha, BlendOp operationAlpha, BlendArg destinationAlpha) : + _enabled(enabled), + _sourceColor(sourceColor), _operationColor(operationColor), _destinationColor(destinationColor), + _sourceAlpha(sourceAlpha), _operationAlpha(operationAlpha), _destinationAlpha(destinationAlpha) {} + + BlendFunction(bool enabled, BlendArg source, BlendOp operation, BlendArg destination) : + _enabled(enabled), + _sourceColor(source), _operationColor(operation), _destinationColor(destination), + _sourceAlpha(source), _operationAlpha(operation), _destinationAlpha(destination) {} int32 raw() const { return *(reinterpret_cast(this)); } BlendFunction(int32 raw) { *(reinterpret_cast(this)) = raw; } @@ -214,65 +238,61 @@ public: void setCullMode(CullMode cull) { set(CULL_MODE, uint32(cull)); } CullMode getCullMode() const { return CullMode(get(CULL_MODE)._integer); } - void setFrontClockwise(bool enable) { set(FRONT_CLOCKWISE, enable); } + void setFrontFace(bool isClockwise) { set(FRONT_FACE, isClockwise); } void setDepthClipEnable(bool enable) { set(DEPTH_CLIP_ENABLE, enable); } - + void setScissorEnable(bool enable) { set(SCISSOR_ENABLE, enable); } + void setMultisampleEnable(bool enable) { set(MULTISAMPLE_ENABLE, enable); } + void setAntialiasedLineEnable(bool enable) { set(ANTIALISED_LINE_ENABLE, enable); } + + bool isFrontFaceClockwise() const { return get(FRONT_FACE)._integer; } + bool isDepthClipEnable() const { return get(DEPTH_CLIP_ENABLE)._integer; } + bool isScissorEnable() const { return get(SCISSOR_ENABLE)._integer; } + bool isMultisampleEnable() const { return get(MULTISAMPLE_ENABLE)._integer; } + bool isAntialiasedLineEnable() const { return get(ANTIALISED_LINE_ENABLE)._integer; } + 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)._integer; } float getDepthBiasSlopeScale() const { return get(DEPTH_BIAS_SLOPE_SCALE)._float; } - - - void setScissorEnable(bool enable) { set(SCISSOR_ENABLE, enable); } - void setMultisampleEnable(bool enable) { set(MULTISAMPLE_ENABLE, enable); } - void setAntialiasedLineEnable(bool enable) { set(ANTIALISED_LINE_ENABLE, enable); } - bool getFrontClockwise() const { return get(FRONT_CLOCKWISE)._integer; } - bool getDepthClipEnable() const { return get(DEPTH_CLIP_ENABLE)._integer; } - bool getScissorEnable() const { return get(SCISSOR_ENABLE)._integer; } - bool getMultisampleEnable() const { return get(MULTISAMPLE_ENABLE)._integer; } - bool getAntialiasedLineEnable() const { return get(ANTIALISED_LINE_ENABLE)._integer; } void setDepthTest(bool enable, bool writeMask, ComparisonFunction func) { set(DEPTH_TEST, DepthTest(enable, writeMask, func).getRaw()); } DepthTest getDepthTest() const { return DepthTest(get(DEPTH_TEST)._integer); } - bool getDepthTestEnabled() const { return getDepthTest()._enabled; } + bool isDepthTestEnabled() const { return getDepthTest()._enabled; } bool getDepthTestWriteMask() const { return getDepthTest()._writeMask; } ComparisonFunction getDepthTestFunc() const { return ComparisonFunction(getDepthTest()._function); } - void setStencilEnable(bool enable) { set(STENCIL_ENABLE, enable); } - void setStencilReadMask(uint8 mask) { set(STENCIL_READ_MASK, mask); } - void setStencilWriteMask(uint8 mask) { set(STENCIL_WRITE_MASK, mask); } - bool getStencilEnable() const { return get(STENCIL_ENABLE)._integer; } - uint8 getStencilReadMask() const { return get(STENCIL_READ_MASK)._unsigned_integer; } - uint8 getStencilWriteMask() const { return get(STENCIL_WRITE_MASK)._unsigned_integer; } + void setStencilTest(bool enabled, uint8 frontWriteMask, StencilTest frontTest, uint8 backWriteMask, StencilTest backTest) { + set(STENCIL_ACTIVATION, StencilActivation(enabled, frontWriteMask, backWriteMask).getRaw()); + set(STENCIL_TEST_FRONT, frontTest.getRaw()); set(STENCIL_TEST_BACK, backTest.getRaw()); + } + void setStencilTest(bool enabled, uint8 frontWriteMask, StencilTest frontTest) { setStencilTest(enabled, frontWriteMask, frontTest, frontWriteMask, frontTest); } - void setStencilTestFront(StencilTest test) { set(STENCIL_TEST_FRONT, test.raw()); } - void setStencilTestBack(StencilTest test) { set(STENCIL_TEST_BACK, test.raw()); } + StencilActivation getStencilActivation() const { return StencilActivation(get(STENCIL_ACTIVATION)._integer); } + bool isStencilEnabled() const { return getStencilActivation()._enabled != 0; } + uint8 getStencilWriteMaskFront() const { return getStencilActivation()._frontWriteMask; } + uint8 getStencilWriteMaskBack() const { return getStencilActivation()._backWriteMask; } 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; } - void setAlphaToCoverageEnable(bool enable) { set(ALPHA_TO_COVERAGE_ENABLE, enable); } - bool getAlphaToCoverageEnable() const { return get(ALPHA_TO_COVERAGE_ENABLE)._integer; } + bool isAlphaToCoverageEnabled() const { return get(ALPHA_TO_COVERAGE_ENABLE)._integer; } void setSampleMask(uint32 mask) { set(SAMPLE_MASK, mask); } uint32 getSampleMask() const { return get(SAMPLE_MASK)._unsigned_integer; } - void setBlendEnable(bool enable) { set(BLEND_ENABLE, enable); } - bool getBlendEnable() const { return get(BLEND_ENABLE)._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 setBlendFunction(BlendFunction function) { set(BLEND_FUNCTION, function.raw()); } + 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 BlendFunction(get(BLEND_FUNCTION)._integer)._enabled; } + BlendFunction getBlendFunction() const { return BlendFunction(get(BLEND_FUNCTION)._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); } + void setColorWriteMask(int32 mask) { set(COLOR_WRITE_MASK, mask); } + int32 getColorWriteMask() const { return ColorMask(get(COLOR_WRITE_MASK)._integer); } protected: State(const State& state); @@ -280,7 +300,7 @@ protected: FieldMap _fields; - Stamp _stamp; + Stamp _stamp = 0; // This shouldn't be used by anything else than the Backend class with the proper casting. mutable GPUObject* _gpuObject = nullptr; diff --git a/libraries/model/src/model/Stage.cpp b/libraries/model/src/model/Stage.cpp index a1a673a80b..b274973ee7 100644 --- a/libraries/model/src/model/Stage.cpp +++ b/libraries/model/src/model/Stage.cpp @@ -217,8 +217,8 @@ SunSkyStage::SunSkyStage() : auto skyShader = gpu::ShaderPointer(gpu::Shader::createProgram(skyFromAtmosphereVertex, skyFromAtmosphereFragment)); auto skyState = gpu::StatePointer(new gpu::State()); - skyState->setStencilEnable(false); - skyState->setBlendEnable(false); + // skyState->setStencilEnable(false); + // skyState->setBlendEnable(false); _skyPipeline = gpu::PipelinePointer(gpu::Pipeline::create(skyShader, skyState)); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 711c850c5e..22202801d3 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -128,7 +128,9 @@ void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey& key, state->setDepthTest(true, !key.isTranslucent(), gpu::State::LESS_EQUAL); // Blend on transparent - state->setBlendEnable(key.isTranslucent()); + 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( From 9c44100bb82fdaa59ddd62d8bfe6853f7fab843a Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 27 Mar 2015 10:33:29 -0700 Subject: [PATCH 07/21] cleaning the State class code --- libraries/gpu/src/gpu/GLBackend.cpp | 2 + libraries/gpu/src/gpu/GLBackendPipeline.cpp | 1 + libraries/gpu/src/gpu/GLBackendState.cpp | 36 +-- libraries/gpu/src/gpu/State.cpp | 33 +-- libraries/gpu/src/gpu/State.h | 235 +++++++++++++------- libraries/render-utils/src/Model.cpp | 11 +- 6 files changed, 192 insertions(+), 126 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index d05ba74b57..533261d2a6 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -379,6 +379,8 @@ void Batch::_glUniform1f(GLint location, GLfloat v0) { DO_IT_NOW(_glUniform1f, 1); } void GLBackend::do_glUniform1f(Batch& batch, uint32 paramOffset) { + if (_pipeline._program == 0) + return; glUniform1f( batch._params[paramOffset + 1]._int, batch._params[paramOffset + 0]._float); diff --git a/libraries/gpu/src/gpu/GLBackendPipeline.cpp b/libraries/gpu/src/gpu/GLBackendPipeline.cpp index 30bebb3049..5079cd1ff9 100755 --- a/libraries/gpu/src/gpu/GLBackendPipeline.cpp +++ b/libraries/gpu/src/gpu/GLBackendPipeline.cpp @@ -71,6 +71,7 @@ void GLBackend::do_setPipeline(Batch& batch, uint32 paramOffset) { _pipeline._pipeline = pipeline; + if (_pipeline._program != pipelineObject->_program->_program) { _pipeline._program = pipelineObject->_program->_program; _pipeline._invalidProgram = true; diff --git a/libraries/gpu/src/gpu/GLBackendState.cpp b/libraries/gpu/src/gpu/GLBackendState.cpp index 94304080c5..4485b18e6d 100644 --- a/libraries/gpu/src/gpu/GLBackendState.cpp +++ b/libraries/gpu/src/gpu/GLBackendState.cpp @@ -228,11 +228,13 @@ void GLBackend::do_setStateCullMode(int32 mode) { glEnable(GL_CULL_FACE); glCullFace(GL_CULL_MODES[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_setStateDepthClipEnable(int32 enable) { @@ -274,10 +276,10 @@ void GLBackend::do_setStateAntialiasedLineEnable(int32 enable) { } void GLBackend::do_setStateDepthTest(State::DepthTest test) { - if (test._enabled) { + if (test.isEnabled()) { glEnable(GL_DEPTH_TEST); - glDepthMask(test._writeMask); - glDepthFunc(GL_COMPARISON_FUNCTIONS[test._function]); + glDepthMask(test.getWriteMask()); + glDepthFunc(GL_COMPARISON_FUNCTIONS[test.getFunction()]); } else { glDisable(GL_DEPTH_TEST); } @@ -285,12 +287,12 @@ void GLBackend::do_setStateDepthTest(State::DepthTest test) { } void GLBackend::do_setStateStencil(State::StencilActivation activation, State::StencilTest frontTest, State::StencilTest backTest) { - if (activation._enabled) { + if (activation.isEnabled()) { glEnable(GL_STENCIL_TEST); - glStencilMaskSeparate(GL_FRONT, activation._frontWriteMask); - glStencilMaskSeparate(GL_BACK, activation._backWriteMask); + glStencilMaskSeparate(GL_FRONT, activation.getWriteMaskFront()); + glStencilMaskSeparate(GL_BACK, activation.getWriteMaskBack()); - static GLenum STENCIL_OPS[] = { + static GLenum STENCIL_OPS[] = { GL_KEEP, GL_ZERO, GL_REPLACE, @@ -300,11 +302,11 @@ void GLBackend::do_setStateStencil(State::StencilActivation activation, State::S GL_INCR, GL_DECR }; - glStencilFuncSeparate(GL_FRONT, STENCIL_OPS[frontTest._failOp], STENCIL_OPS[frontTest._passOp], STENCIL_OPS[frontTest._depthFailOp]); - glStencilFuncSeparate(GL_FRONT, GL_COMPARISON_FUNCTIONS[frontTest._function], frontTest._reference, frontTest._readMask); + 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()); - glStencilFuncSeparate(GL_BACK, STENCIL_OPS[backTest._failOp], STENCIL_OPS[backTest._passOp], STENCIL_OPS[backTest._depthFailOp]); - glStencilFuncSeparate(GL_BACK, GL_COMPARISON_FUNCTIONS[backTest._function], backTest._reference, backTest._readMask); + 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); } @@ -321,7 +323,7 @@ void GLBackend::do_setStateAlphaToCoverageEnable(int32 enable) { } void GLBackend::do_setStateBlend(State::BlendFunction function, Vec4 factor ) { - if (function._enabled) { + if (function.isEnabled()) { glEnable(GL_BLEND); static GLenum GL_BLEND_OPS[] = { @@ -331,7 +333,8 @@ void GLBackend::do_setStateBlend(State::BlendFunction function, Vec4 factor ) { GL_MIN, GL_MAX }; - glBlendEquationSeparate(GL_BLEND_OPS[function._operationColor], GL_BLEND_OPS[function._operationAlpha]); + glBlendEquationSeparate(GL_BLEND_OPS[function.getOperationColor()], GL_BLEND_OPS[function.getOperationAlpha()]); + CHECK_GL_ERROR(); static GLenum BLEND_ARGS[] = { GL_ZERO, @@ -351,14 +354,15 @@ void GLBackend::do_setStateBlend(State::BlendFunction function, Vec4 factor ) { GL_ONE_MINUS_CONSTANT_ALPHA, }; - glBlendFuncSeparate(BLEND_ARGS[function._sourceColor], BLEND_ARGS[function._destinationColor], - BLEND_ARGS[function._sourceAlpha], BLEND_ARGS[function._destinationAlpha]); + 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); } - CHECK_GL_ERROR(); } void GLBackend::do_setStateColorWriteMask(int32 mask) { diff --git a/libraries/gpu/src/gpu/State.cpp b/libraries/gpu/src/gpu/State.cpp index 1a0dad3a8c..0260190327 100755 --- a/libraries/gpu/src/gpu/State.cpp +++ b/libraries/gpu/src/gpu/State.cpp @@ -14,35 +14,8 @@ using namespace gpu; - -State::~State() -{ +State::State() { } -void State::set(Field field, bool value) { - _fields[field]._integer = value; - _stamp++; -} - -void State::set(Field field, uint32 value) { - _fields[field]._unsigned_integer = value; - _stamp++; -} - -void State::set(Field field, int32 value) { - _fields[field]._integer = value; - _stamp++; -} - -void State::set(Field field, float value) { - _fields[field]._float = value; - _stamp++; -} - -State::Value State::get(Field field) const { - auto found = _fields.find(field); - if (found != _fields.end()) { - return (*found).second; - } - return Value(); -} +State::~State() { +} diff --git a/libraries/gpu/src/gpu/State.h b/libraries/gpu/src/gpu/State.h index 97990ccfb5..839768bbc7 100755 --- a/libraries/gpu/src/gpu/State.h +++ b/libraries/gpu/src/gpu/State.h @@ -23,7 +23,7 @@ class GPUObject; class State { public: - State() {} + State(); virtual ~State(); const Stamp getStamp() const { return _stamp; } @@ -144,72 +144,105 @@ public: }; class DepthTest { - public: 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(this)); } DepthTest(int32 raw) { *(reinterpret_cast(this)) = raw; } }; - class StencilTest { + 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_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: - uint8 _reference; - uint8 _readMask; - int8 _function : 4; - int8 _failOp : 4; - int8 _depthFailOp : 4; - int8 _passOp : 4; - + 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), _function(func), _failOp(failOp), _depthFailOp(depthFailOp), _passOp(passOp) {} - + _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(this)); } StencilTest(int32 raw) { *(reinterpret_cast(this)) = raw; } }; class StencilActivation { + uint8 _frontWriteMask = 0xFF; + uint8 _backWriteMask = 0xFF; + uint16 _enabled = 0; public: - uint8 _frontWriteMask; - uint8 _backWriteMask; - int16 _enabled; - + 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(this)); } StencilActivation(int32 raw) { *(reinterpret_cast(this)) = raw; } }; class BlendFunction { + static const int COLOR_MASK = 0x0f; + static const int ALPHA_MASK = 0xf0; + static const int ALPHA_OFFSET = 4; + + uint8 _enabled; + uint8 _source; + uint8 _destination; + uint8 _operation; public: - int8 _enabled; - int8 _sourceColor : 4; - int8 _sourceAlpha : 4; - int8 _destinationColor : 4; - int8 _destinationAlpha : 4; - int8 _operationColor : 4; - int8 _operationAlpha : 4; BlendFunction(bool enabled, BlendArg sourceColor, BlendOp operationColor, BlendArg destinationColor, BlendArg sourceAlpha, BlendOp operationAlpha, BlendArg destinationAlpha) : _enabled(enabled), - _sourceColor(sourceColor), _operationColor(operationColor), _destinationColor(destinationColor), - _sourceAlpha(sourceAlpha), _operationAlpha(operationAlpha), _destinationAlpha(destinationAlpha) {} + _source(sourceColor | (sourceAlpha << ALPHA_OFFSET)), + _destination(destinationColor | (destinationAlpha << ALPHA_OFFSET)), + _operation(operationColor | (operationAlpha << ALPHA_OFFSET)) {} - BlendFunction(bool enabled, BlendArg source, BlendOp operation, BlendArg destination) : + BlendFunction(bool enabled, BlendArg source = ONE, BlendOp operation = BLEND_OP_ADD, BlendArg destination = ZERO) : _enabled(enabled), - _sourceColor(source), _operationColor(operation), _destinationColor(destination), - _sourceAlpha(source), _operationAlpha(operation), _destinationAlpha(destination) {} + _source(source | (source << ALPHA_OFFSET)), + _destination(destination | (destination << ALPHA_OFFSET)), + _operation(operation | (operation << ALPHA_OFFSET)) {} - int32 raw() const { return *(reinterpret_cast(this)); } + 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(this)); } BlendFunction(int32 raw) { *(reinterpret_cast(this)) = raw; } }; @@ -220,79 +253,124 @@ public: int32 _integer; float _float; }; + + template void uncast(T v) { _integer = v; } + template <> void State::Value::uncast(int v) { _integer = v; } + template <> void State::Value::uncast(float v) { _float = v; } + template <> void State::Value::uncast(unsigned int v) { _unsigned_integer = v; } + template <> void State::Value::uncast(DepthTest v) { _integer = v.getRaw(); } + template <> void State::Value::uncast(StencilActivation v) { _integer = v.getRaw(); } + template <> void State::Value::uncast(StencilTest v) { _integer = v.getRaw(); } + template <> void State::Value::uncast(BlendFunction v) { _integer = v.getRaw(); } + + template T cast() const; + template <> int State::Value::cast() const { return _integer; } + template <> float State::Value::cast() const { return _float; } + template <> unsigned int State::Value::cast() const { return _unsigned_integer; } + template <> DepthTest State::Value::cast() const { return DepthTest(_integer); } + template <> StencilActivation State::Value::cast() const { return StencilActivation(_integer); } + template <> StencilTest State::Value::cast() const { return StencilTest(_integer); } + template <> BlendFunction State::Value::cast() const { return BlendFunction(_integer); } }; 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); - void set(Field field, float value); + template void set(Field field, T value) { + _fields[field].uncast(value); + _stamp++; + } - Value get(Field field) const; + template T get(Field field, T defaultValue) const { + auto found = _fields.find(field); + if (found != _fields.end()) { + return (*found).second.cast(); + } + return defaultValue; + } - void setFillMode(FillMode fill) { set(FILL_MODE, uint32(fill)); } - FillMode getFillMode() const { return FillMode(get(FILL_MODE)._integer); } + void setFillMode(FillMode fill) { set(FILL_MODE, fill); } + FillMode getFillMode() const { return get(FILL_MODE, FILL_FACE); } - void setCullMode(CullMode cull) { set(CULL_MODE, uint32(cull)); } - CullMode getCullMode() const { return CullMode(get(CULL_MODE)._integer); } + 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); } - void setDepthClipEnable(bool enable) { set(DEPTH_CLIP_ENABLE, enable); } - void setScissorEnable(bool enable) { set(SCISSOR_ENABLE, enable); } - void setMultisampleEnable(bool enable) { set(MULTISAMPLE_ENABLE, enable); } - void setAntialiasedLineEnable(bool enable) { set(ANTIALISED_LINE_ENABLE, enable); } + bool isFrontFaceClockwise() const { return get(FRONT_FACE, true); } - bool isFrontFaceClockwise() const { return get(FRONT_FACE)._integer; } - bool isDepthClipEnable() const { return get(DEPTH_CLIP_ENABLE)._integer; } - bool isScissorEnable() const { return get(SCISSOR_ENABLE)._integer; } - bool isMultisampleEnable() const { return get(MULTISAMPLE_ENABLE)._integer; } - bool isAntialiasedLineEnable() const { return get(ANTIALISED_LINE_ENABLE)._integer; } + 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)._integer; } - float getDepthBiasSlopeScale() const { return get(DEPTH_BIAS_SLOPE_SCALE)._float; } + float getDepthBias() const { return get(DEPTH_BIAS, 0.0f); } + float getDepthBiasSlopeScale() const { return get(DEPTH_BIAS_SLOPE_SCALE, 1.0f); } - void setDepthTest(bool enable, bool writeMask, ComparisonFunction func) { set(DEPTH_TEST, DepthTest(enable, writeMask, func).getRaw()); } - DepthTest getDepthTest() const { return DepthTest(get(DEPTH_TEST)._integer); } - bool isDepthTestEnabled() const { return getDepthTest()._enabled; } - bool getDepthTestWriteMask() const { return getDepthTest()._writeMask; } - ComparisonFunction getDepthTestFunc() const { return ComparisonFunction(getDepthTest()._function); } + // 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).getRaw()); - set(STENCIL_TEST_FRONT, frontTest.getRaw()); set(STENCIL_TEST_BACK, backTest.getRaw()); - } - void setStencilTest(bool enabled, uint8 frontWriteMask, StencilTest frontTest) { setStencilTest(enabled, frontWriteMask, frontTest, frontWriteMask, frontTest); } + 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 StencilActivation(get(STENCIL_ACTIVATION)._integer); } - bool isStencilEnabled() const { return getStencilActivation()._enabled != 0; } - uint8 getStencilWriteMaskFront() const { return getStencilActivation()._frontWriteMask; } - uint8 getStencilWriteMaskBack() const { return getStencilActivation()._backWriteMask; } - StencilTest getStencilTestFront() const { return StencilTest(get(STENCIL_TEST_FRONT)._integer); } - StencilTest getStencilTestBack() const { return StencilTest(get(STENCIL_TEST_BACK)._integer); } + 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)._integer; } + bool isAlphaToCoverageEnabled() const { return get(ALPHA_TO_COVERAGE_ENABLE, false); } + // Sample mask void setSampleMask(uint32 mask) { set(SAMPLE_MASK, mask); } - uint32 getSampleMask() const { return get(SAMPLE_MASK)._unsigned_integer; } + uint32 getSampleMask() const { return get(SAMPLE_MASK, 0xFFFFFFFF); } - void setBlendFunction(BlendFunction function) { set(BLEND_FUNCTION, function.raw()); } - 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) { + // 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)); } - bool isBlendEnabled() const { return BlendFunction(get(BLEND_FUNCTION)._integer)._enabled; } - BlendFunction getBlendFunction() const { return BlendFunction(get(BLEND_FUNCTION)._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); } + 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); } - int32 getColorWriteMask() const { return ColorMask(get(COLOR_WRITE_MASK)._integer); } + uint32 getColorWriteMask() const { return get(COLOR_WRITE_MASK, WRITE_ALL); } protected: State(const State& state); @@ -309,8 +387,9 @@ protected: friend class Backend; }; + typedef std::shared_ptr< State > StatePointer; -typedef std::vector< StatePointer > States; +typedef std::vector< StatePointer > States; }; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 22202801d3..130d6b7f5c 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -816,6 +816,9 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { GLBATCH(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, 0); GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); + // Back to no program + GLBATCH(glUseProgram)(0); + // Render! { PROFILE_RANGE("render Batch"); @@ -1873,6 +1876,10 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { GLBATCH(glBindBuffer)(GL_ARRAY_BUFFER, 0); GLBATCH(glBindBuffer)(GL_ELEMENT_ARRAY_BUFFER, 0); GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); + + // Back to no program + GLBATCH(glUseProgram)(0); + if (args) { args->_translucentMeshPartsRendered = translucentParts; args->_opaqueMeshPartsRendered = opaqueMeshPartsRendered; @@ -2295,7 +2302,7 @@ int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool } // if we selected a program, then unselect it if (!pickProgramsNeeded) { - GLBATCH(glUseProgram)(0); + // GLBATCH(glUseProgram)(0); } return meshPartsRendered; } @@ -2325,7 +2332,7 @@ int Model::renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, fl args, locations); meshPartsRendered = renderMeshesFromList(list, batch, mode, translucent, alphaThreshold, args, locations, forceRenderSomeMeshes); - GLBATCH(glUseProgram)(0); + // GLBATCH(glUseProgram)(0); return meshPartsRendered; } From 21b5d6f40475aec58f2e3bbacc029d0d6cfa4686 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Sat, 28 Mar 2015 11:26:06 -0700 Subject: [PATCH 08/21] refining the state interface and the GLBackend for it with a true cache --- libraries/gpu/src/gpu/Batch.cpp | 26 +- libraries/gpu/src/gpu/Batch.h | 61 +-- libraries/gpu/src/gpu/GLBackend.cpp | 155 +------ libraries/gpu/src/gpu/GLBackend.h | 48 ++- libraries/gpu/src/gpu/GLBackendPipeline.cpp | 89 ++-- libraries/gpu/src/gpu/GLBackendState.cpp | 436 +++++++++++++------- libraries/gpu/src/gpu/State.cpp | 2 + libraries/gpu/src/gpu/State.h | 299 ++++++++------ libraries/render-utils/src/Model.cpp | 5 +- 9 files changed, 568 insertions(+), 553 deletions(-) diff --git a/libraries/gpu/src/gpu/Batch.cpp b/libraries/gpu/src/gpu/Batch.cpp index 9ca0eeaebf..9eb9648478 100644 --- a/libraries/gpu/src/gpu/Batch.cpp +++ b/libraries/gpu/src/gpu/Batch.cpp @@ -20,7 +20,6 @@ Batch::Batch() : _commands(), _commandOffsets(), _params(), - _resources(), _data(), _buffers(), _textures(), @@ -37,7 +36,6 @@ void Batch::clear() { _commands.clear(); _commandOffsets.clear(); _params.clear(); - _resources.clear(); _data.clear(); _buffers.clear(); _textures.clear(); @@ -46,20 +44,6 @@ void Batch::clear() { _pipelines.clear(); } -uint32 Batch::cacheResource(Resource* res) { - uint32 offset = _resources.size(); - _resources.push_back(ResourceCache(res)); - - return offset; -} - -uint32 Batch::cacheResource(const void* pointer) { - uint32 offset = _resources.size(); - _resources.push_back(ResourceCache(pointer)); - - return offset; -} - uint32 Batch::cacheData(uint32 size, const void* data) { uint32 offset = _data.size(); uint32 nbBytes = size; @@ -167,6 +151,16 @@ void Batch::setPipeline(const PipelinePointer& pipeline) { _params.push_back(_pipelines.cache(pipeline)); } +void Batch::setStateBlendFactor(const Vec4& factor) { + ADD_COMMAND(setStateBlendFactor); + + _params.push_back(factor.x); + _params.push_back(factor.y); + _params.push_back(factor.z); + _params.push_back(factor.w); +} + + void Batch::setUniformBuffer(uint32 slot, const BufferPointer& buffer, Offset offset, Offset size) { ADD_COMMAND(setUniformBuffer); diff --git a/libraries/gpu/src/gpu/Batch.h b/libraries/gpu/src/gpu/Batch.h index 3468e75738..6e8a2d1da6 100644 --- a/libraries/gpu/src/gpu/Batch.h +++ b/libraries/gpu/src/gpu/Batch.h @@ -104,6 +104,8 @@ public: // Pipeline Stage void setPipeline(const PipelinePointer& pipeline); + void setStateBlendFactor(const Vec4& factor); + void setUniformBuffer(uint32 slot, const BufferPointer& buffer, Offset offset, Offset size); void setUniformBuffer(uint32 slot, const BufferView& view); // not a command, just a shortcut from a BufferView @@ -128,7 +130,7 @@ public: void _glDepthFunc(GLenum func); void _glDepthMask(GLboolean flag); - void _glDepthRange(GLclampd zNear, GLclampd zFar); + void _glDepthRange(GLfloat zNear, GLfloat zFar); void _glBindBuffer(GLenum target, GLuint buffer); @@ -143,15 +145,6 @@ public: void _glUniform4fv(GLint location, GLsizei count, const GLfloat* value); void _glUniformMatrix4fv(GLint location, GLsizei count, GLboolean transpose, const GLfloat* value); - void _glDrawArrays(GLenum mode, GLint first, GLsizei count); - void _glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices); - - void _glColorPointer(GLint size, GLenum type, GLsizei stride, const void *pointer); - void _glNormalPointer(GLenum type, GLsizei stride, const void *pointer); - void _glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const void *pointer); - void _glVertexPointer(GLint size, GLenum type, GLsizei stride, const void *pointer); - - void _glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer); void _glEnableVertexAttribArray(GLint location); void _glDisableVertexAttribArray(GLint location); @@ -172,6 +165,8 @@ public: COMMAND_setProjectionTransform, COMMAND_setPipeline, + COMMAND_setStateBlendFactor, + COMMAND_setUniformBuffer, COMMAND_setUniformTexture, @@ -204,15 +199,6 @@ public: COMMAND_glUniform4fv, COMMAND_glUniformMatrix4fv, - COMMAND_glDrawArrays, - COMMAND_glDrawRangeElements, - - COMMAND_glColorPointer, - COMMAND_glNormalPointer, - COMMAND_glTexCoordPointer, - COMMAND_glVertexPointer, - - COMMAND_glVertexAttribPointer, COMMAND_glEnableVertexAttribArray, COMMAND_glDisableVertexAttribArray, @@ -233,28 +219,18 @@ public: uint32 _uint; float _float; char _chars[4]; - double _double; }; Param(int32 val) : _int(val) {} Param(uint32 val) : _uint(val) {} Param(float val) : _float(val) {} - Param(double val) : _double(val) {} }; typedef std::vector Params; const Params& getParams() const { return _params; } - class ResourceCache { - public: - union { - Resource* _resource; - const void* _pointer; - }; - ResourceCache(Resource* res) : _resource(res) {} - ResourceCache(const void* pointer) : _pointer(pointer) {} - }; - typedef std::vector Resources; - + // The template cache mechanism for the gpu::Object passed to the gpu::Batch + // this allow us to have one cache container for each different types and eventually + // be smarter how we manage them template class Cache { public: @@ -291,26 +267,10 @@ public: typedef Cache::Vector TransformCaches; typedef Cache::Vector PipelineCaches; + // Cache Data in a byte array if too big to fit in Param + // FOr example Mat4s are going there typedef unsigned char Byte; typedef std::vector Bytes; - - uint32 cacheResource(Resource* res); - uint32 cacheResource(const void* pointer); - ResourceCache* editResource(uint32 offset) { - if (offset >= _resources.size()) { - return 0; - } - return (_resources.data() + offset); - } - - template - T* editResourcePointer(uint32 offset) { - if (offset >= _resources.size()) { - return 0; - } - return reinterpret_cast((_resources.data() + offset)->_pointer); - } - uint32 cacheData(uint32 size, const void* data); Byte* editData(uint32 offset) { if (offset >= _data.size()) { @@ -322,7 +282,6 @@ public: Commands _commands; CommandOffsets _commandOffsets; Params _params; - Resources _resources; Bytes _data; BufferCaches _buffers; diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 533261d2a6..0bf13636f1 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -26,6 +26,8 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_setProjectionTransform), (&::gpu::GLBackend::do_setPipeline), + (&::gpu::GLBackend::do_setStateBlendFactor), + (&::gpu::GLBackend::do_setUniformBuffer), (&::gpu::GLBackend::do_setUniformTexture), @@ -55,15 +57,6 @@ GLBackend::CommandCall GLBackend::_commandCalls[Batch::NUM_COMMANDS] = (&::gpu::GLBackend::do_glUniform4fv), (&::gpu::GLBackend::do_glUniformMatrix4fv), - (&::gpu::GLBackend::do_glDrawArrays), - (&::gpu::GLBackend::do_glDrawRangeElements), - - (&::gpu::GLBackend::do_glColorPointer), - (&::gpu::GLBackend::do_glNormalPointer), - (&::gpu::GLBackend::do_glTexCoordPointer), - (&::gpu::GLBackend::do_glVertexPointer), - - (&::gpu::GLBackend::do_glVertexAttribPointer), (&::gpu::GLBackend::do_glEnableVertexAttribArray), (&::gpu::GLBackend::do_glDisableVertexAttribArray), @@ -280,7 +273,7 @@ void GLBackend::do_glDepthMask(Batch& batch, uint32 paramOffset) { CHECK_GL_ERROR(); } -void Batch::_glDepthRange(GLclampd zNear, GLclampd zFar) { +void Batch::_glDepthRange(GLfloat zNear, GLfloat zFar) { ADD_COMMAND_GL(glDepthRange); _params.push_back(zFar); @@ -290,8 +283,8 @@ void Batch::_glDepthRange(GLclampd zNear, GLclampd zFar) { } void GLBackend::do_glDepthRange(Batch& batch, uint32 paramOffset) { glDepthRange( - batch._params[paramOffset + 1]._double, - batch._params[paramOffset + 0]._double); + batch._params[paramOffset + 1]._float, + batch._params[paramOffset + 0]._float); CHECK_GL_ERROR(); } @@ -443,144 +436,6 @@ void GLBackend::do_glUniformMatrix4fv(Batch& batch, uint32 paramOffset) { CHECK_GL_ERROR(); } -void Batch::_glDrawArrays(GLenum mode, GLint first, GLsizei count) { - ADD_COMMAND_GL(glDrawArrays); - - _params.push_back(count); - _params.push_back(first); - _params.push_back(mode); - - DO_IT_NOW(_glDrawArrays, 3); -} -void GLBackend::do_glDrawArrays(Batch& batch, uint32 paramOffset) { - glDrawArrays( - batch._params[paramOffset + 2]._uint, - batch._params[paramOffset + 1]._int, - batch._params[paramOffset + 0]._int); - CHECK_GL_ERROR(); -} - -void Batch::_glDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const void *indices) { - ADD_COMMAND_GL(glDrawRangeElements); - - _params.push_back(cacheResource(indices)); - _params.push_back(type); - _params.push_back(count); - _params.push_back(end); - _params.push_back(start); - _params.push_back(mode); - - DO_IT_NOW(_glDrawRangeElements, 6); -} -void GLBackend::do_glDrawRangeElements(Batch& batch, uint32 paramOffset) { - glDrawRangeElements( - batch._params[paramOffset + 5]._uint, - batch._params[paramOffset + 4]._uint, - batch._params[paramOffset + 3]._uint, - batch._params[paramOffset + 2]._int, - batch._params[paramOffset + 1]._uint, - batch.editResource(batch._params[paramOffset + 0]._uint)->_pointer); - CHECK_GL_ERROR(); -} - -void Batch::_glColorPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) { - ADD_COMMAND_GL(glColorPointer); - - _params.push_back(cacheResource(pointer)); - _params.push_back(stride); - _params.push_back(type); - _params.push_back(size); - - DO_IT_NOW(_glColorPointer, 4); -} -void GLBackend::do_glColorPointer(Batch& batch, uint32 paramOffset) { - glColorPointer( - batch._params[paramOffset + 3]._int, - batch._params[paramOffset + 2]._uint, - batch._params[paramOffset + 1]._int, - batch.editResource(batch._params[paramOffset + 0]._uint)->_pointer); - CHECK_GL_ERROR(); -} - -void Batch::_glNormalPointer(GLenum type, GLsizei stride, const void *pointer) { - ADD_COMMAND_GL(glNormalPointer); - - _params.push_back(cacheResource(pointer)); - _params.push_back(stride); - _params.push_back(type); - - DO_IT_NOW(_glNormalPointer, 3); -} -void GLBackend::do_glNormalPointer(Batch& batch, uint32 paramOffset) { - glNormalPointer( - batch._params[paramOffset + 2]._uint, - batch._params[paramOffset + 1]._int, - batch.editResource(batch._params[paramOffset + 0]._uint)->_pointer); - CHECK_GL_ERROR(); -} - -void Batch::_glTexCoordPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) { - ADD_COMMAND_GL(glTexCoordPointer); - - _params.push_back(cacheResource(pointer)); - _params.push_back(stride); - _params.push_back(type); - _params.push_back(size); - - DO_IT_NOW(_glTexCoordPointer, 4); -} -void GLBackend::do_glTexCoordPointer(Batch& batch, uint32 paramOffset) { - glTexCoordPointer( - batch._params[paramOffset + 3]._int, - batch._params[paramOffset + 2]._uint, - batch._params[paramOffset + 1]._int, - batch.editResource(batch._params[paramOffset + 0]._uint)->_pointer); - CHECK_GL_ERROR(); -} - -void Batch::_glVertexPointer(GLint size, GLenum type, GLsizei stride, const void *pointer) { - ADD_COMMAND_GL(glVertexPointer); - - _params.push_back(cacheResource(pointer)); - _params.push_back(stride); - _params.push_back(type); - _params.push_back(size); - - DO_IT_NOW(_glVertexPointer, 4); -} -void GLBackend::do_glVertexPointer(Batch& batch, uint32 paramOffset) { - glVertexPointer( - batch._params[paramOffset + 3]._int, - batch._params[paramOffset + 2]._uint, - batch._params[paramOffset + 1]._int, - batch.editResource(batch._params[paramOffset + 0]._uint)->_pointer); - CHECK_GL_ERROR(); -} - - -void Batch::_glVertexAttribPointer(GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void *pointer) { - ADD_COMMAND_GL(glVertexAttribPointer); - - _params.push_back(cacheResource(pointer)); - _params.push_back(stride); - _params.push_back(normalized); - _params.push_back(type); - _params.push_back(size); - _params.push_back(index); - - DO_IT_NOW(_glVertexAttribPointer, 6); -} -void GLBackend::do_glVertexAttribPointer(Batch& batch, uint32 paramOffset) { - glVertexAttribPointer( - batch._params[paramOffset + 5]._uint, - batch._params[paramOffset + 4]._int, - batch._params[paramOffset + 3]._uint, - batch._params[paramOffset + 2]._uint, - batch._params[paramOffset + 1]._int, - batch.editResource(batch._params[paramOffset + 0]._uint)->_pointer); - CHECK_GL_ERROR(); -} - void Batch::_glEnableVertexAttribArray(GLint location) { ADD_COMMAND_GL(glEnableVertexAttribArray); diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 0ef407df8a..3ca65d45eb 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -118,10 +118,15 @@ public: Commands _commands; Stamp _stamp; + State::Signature _signature; GLState(); ~GLState(); + // The state commands to reset to default, + // WARNING depending on the order of the State::Field enum + static const Commands _resetStateCommands; + friend class GLBackend; }; static GLState* syncGPUObject(const State& state); @@ -145,20 +150,23 @@ public: // The State setters called by the GLState::Commands when a new state is assigned void do_setStateFillMode(int32 mode); void do_setStateCullMode(int32 mode); - void do_setStateFrontClockwise(int32 isFrontClockwise); - void do_setStateDepthClipEnable(int32 enable); - void do_setStateScissorEnable(int32 enable); - void do_setStateMultisampleEnable(int32 enable); - void do_setStateAntialiasedLineEnable(int32 enable); + void do_setStateFrontFaceClockwise(bool isClockwise); + void do_setStateDepthClipEnable(bool enable); + void do_setStateScissorEnable(bool enable); + void do_setStateMultisampleEnable(bool enable); + void do_setStateAntialiasedLineEnable(bool enable); + void do_setStateDepthBias(Vec2 bias); void do_setStateDepthTest(State::DepthTest test); void do_setStateStencil(State::StencilActivation activation, State::StencilTest frontTest, State::StencilTest backTest); - void do_setStateAlphaToCoverageEnable(int32 enable); + void do_setStateAlphaToCoverageEnable(bool enable); + void do_setStateSampleMask(uint32 mask); - void do_setStateBlend(State::BlendFunction blendFunction, Vec4 blendFactor); - void do_setStateColorWriteMask(int32 mask); + void do_setStateBlend(State::BlendFunction blendFunction); + + void do_setStateColorWriteMask(uint32 mask); protected: @@ -242,25 +250,34 @@ protected: // Pipeline Stage void do_setPipeline(Batch& batch, uint32 paramOffset); + + void do_setStateBlendFactor(Batch& batch, uint32 paramOffset); + void do_setUniformBuffer(Batch& batch, uint32 paramOffset); void do_setUniformTexture(Batch& batch, uint32 paramOffset); void updatePipeline(); + void resetPipelineState(State::Signature toBeReset); struct PipelineStageState { PipelinePointer _pipeline; + GLuint _program; bool _invalidProgram; - State _state; - GLState::Commands _stateCommands; + State::Cache _stateCache; + State::Signature _stateSignatureCache; + + GLState* _state; bool _invalidState; PipelineStageState() : _pipeline(), _program(0), _invalidProgram(false), - _state(), + _stateSignatureCache(0), + _stateCache(State::DEFAULT), + _state(nullptr), _invalidState(false) {} } _pipeline; @@ -294,15 +311,6 @@ protected: void do_glUniform4fv(Batch& batch, uint32 paramOffset); void do_glUniformMatrix4fv(Batch& batch, uint32 paramOffset); - void do_glDrawArrays(Batch& batch, uint32 paramOffset); - void do_glDrawRangeElements(Batch& batch, uint32 paramOffset); - - void do_glColorPointer(Batch& batch, uint32 paramOffset); - void do_glNormalPointer(Batch& batch, uint32 paramOffset); - void do_glTexCoordPointer(Batch& batch, uint32 paramOffset); - void do_glVertexPointer(Batch& batch, uint32 paramOffset); - - void do_glVertexAttribPointer(Batch& batch, uint32 paramOffset); void do_glEnableVertexAttribArray(Batch& batch, uint32 paramOffset); void do_glDisableVertexAttribArray(Batch& batch, uint32 paramOffset); diff --git a/libraries/gpu/src/gpu/GLBackendPipeline.cpp b/libraries/gpu/src/gpu/GLBackendPipeline.cpp index 5079cd1ff9..d0ef01c4a4 100755 --- a/libraries/gpu/src/gpu/GLBackendPipeline.cpp +++ b/libraries/gpu/src/gpu/GLBackendPipeline.cpp @@ -60,27 +60,41 @@ GLBackend::GLPipeline* GLBackend::syncGPUObject(const Pipeline& pipeline) { void GLBackend::do_setPipeline(Batch& batch, uint32 paramOffset) { PipelinePointer pipeline = batch._pipelines.get(batch._params[paramOffset + 0]._uint); - if (pipeline == _pipeline._pipeline) { + if (_pipeline._pipeline == pipeline) { return; } - auto pipelineObject = syncGPUObject((*pipeline)); - if (!pipelineObject) { - return; - } - - _pipeline._pipeline = pipeline; + // null pipeline == reset + if (!pipeline) { + _pipeline._pipeline.reset(); - - if (_pipeline._program != pipelineObject->_program->_program) { - _pipeline._program = pipelineObject->_program->_program; + _pipeline._program = 0; _pipeline._invalidProgram = true; + + _pipeline._state = nullptr; + _pipeline._invalidState = true; + } else { + auto pipelineObject = syncGPUObject((*pipeline)); + if (!pipelineObject) { + return; + } + + // check the program cache + if (_pipeline._program != pipelineObject->_program->_program) { + _pipeline._program = pipelineObject->_program->_program; + _pipeline._invalidProgram = true; + } + + // Now for the state + if (_pipeline._state != pipelineObject->_state) { + _pipeline._state = pipelineObject->_state; + _pipeline._invalidState = true; + } + + // Remember the new pipeline + _pipeline._pipeline = pipeline; } - _pipeline._stateCommands = pipelineObject->_state->_commands; - _pipeline._invalidState = true; - - // THis should be done on Pipeline::update... if (_pipeline._invalidProgram) { glUseProgram(_pipeline._program); @@ -89,6 +103,35 @@ void GLBackend::do_setPipeline(Batch& batch, uint32 paramOffset) { } } +void GLBackend::updatePipeline() { + if (_pipeline._invalidProgram) { + // doing it here is aproblem for calls to glUniform.... so will do it on assing... + glUseProgram(_pipeline._program); + CHECK_GL_ERROR(); + _pipeline._invalidProgram = false; + } + + if (_pipeline._invalidState) { + if (_pipeline._state) { + // first reset to default what should be + // the fields which were not to default and are default now + resetPipelineState(_pipeline._state->_signature); + + // Update the signature cache with what's going to be touched + _pipeline._stateSignatureCache |= _pipeline._state->_signature; + + // And perform + for (auto command: _pipeline._state->_commands) { + command->run(this); + } + } else { + // No state ? anyway just reset everything + resetPipelineState(0); + } + _pipeline._invalidState = false; + } +} + void GLBackend::do_setUniformBuffer(Batch& batch, uint32 paramOffset) { GLuint slot = batch._params[paramOffset + 3]._uint; BufferPointer uniformBuffer = batch._buffers.get(batch._params[paramOffset + 2]._uint); @@ -120,21 +163,3 @@ void GLBackend::do_setUniformTexture(Batch& batch, uint32 paramOffset) { CHECK_GL_ERROR(); } - -void GLBackend::updatePipeline() { - if (_pipeline._invalidProgram) { - // doing it here is aproblem for calls to glUniform.... so will do it on assing... - glUseProgram(_pipeline._program); - CHECK_GL_ERROR(); - _pipeline._invalidProgram = false; - } - - if (_pipeline._invalidState) { - for (auto command: _pipeline._stateCommands) { - command->run(this); - } - CHECK_GL_ERROR(); - _pipeline._invalidState = false; - } -} - diff --git a/libraries/gpu/src/gpu/GLBackendState.cpp b/libraries/gpu/src/gpu/GLBackendState.cpp index 4485b18e6d..2397af7cec 100644 --- a/libraries/gpu/src/gpu/GLBackendState.cpp +++ b/libraries/gpu/src/gpu/GLBackendState.cpp @@ -23,11 +23,44 @@ GLBackend::GLState::~GLState() { typedef GLBackend::GLState::Command Command; typedef GLBackend::GLState::CommandPointer CommandPointer; +typedef GLBackend::GLState::Command1 Command1U; typedef GLBackend::GLState::Command1 Command1I; +typedef GLBackend::GLState::Command1 Command1B; +typedef GLBackend::GLState::Command1 CommandDepthBias; typedef GLBackend::GLState::Command1 CommandDepthTest; typedef GLBackend::GLState::Command3 CommandStencil; -typedef GLBackend::GLState::Command2 CommandBlend; +typedef GLBackend::GLState::Command1 CommandBlend; +// The state commands to reset to default, +// WARNING depending on the order of the State::Field enum +const GLBackend::GLState::Commands GLBackend::GLState::_resetStateCommands = { + CommandPointer(new Command1I(&GLBackend::do_setStateFillMode, State::DEFAULT.fillMode)), + CommandPointer(new Command1I(&GLBackend::do_setStateCullMode, State::DEFAULT.cullMode)), + CommandPointer(new Command1B(&GLBackend::do_setStateFrontFaceClockwise, State::DEFAULT.frontFaceClockwise)), + CommandPointer(new Command1B(&GLBackend::do_setStateDepthClipEnable, State::DEFAULT.depthClipEnable)), + CommandPointer(new Command1B(&GLBackend::do_setStateScissorEnable, State::DEFAULT.scissorEnable)), + CommandPointer(new Command1B(&GLBackend::do_setStateMultisampleEnable, State::DEFAULT.multisampleEnable)), + CommandPointer(new Command1B(&GLBackend::do_setStateAntialiasedLineEnable, State::DEFAULT.antialisedLineEnable)), + + // Depth bias has 2 fields in State but really one call in GLBackend + CommandPointer(new CommandDepthBias(&GLBackend::do_setStateDepthBias, Vec2(State::DEFAULT.depthBias, State::DEFAULT.depthBiasSlopeScale))), + CommandPointer(new CommandDepthBias(&GLBackend::do_setStateDepthBias, Vec2(State::DEFAULT.depthBias, State::DEFAULT.depthBiasSlopeScale))), + + CommandPointer(new CommandDepthTest(&GLBackend::do_setStateDepthTest, State::DEFAULT.depthTest)), + + // Depth bias has 3 fields in State but really one call in GLBackend + CommandPointer(new CommandStencil(&GLBackend::do_setStateStencil, State::DEFAULT.stencilActivation, State::DEFAULT.stencilTestFront, State::DEFAULT.stencilTestBack)), + CommandPointer(new CommandStencil(&GLBackend::do_setStateStencil, State::DEFAULT.stencilActivation, State::DEFAULT.stencilTestFront, State::DEFAULT.stencilTestBack)), + CommandPointer(new CommandStencil(&GLBackend::do_setStateStencil, State::DEFAULT.stencilActivation, State::DEFAULT.stencilTestFront, State::DEFAULT.stencilTestBack)), + + CommandPointer(new Command1B(&GLBackend::do_setStateAlphaToCoverageEnable, State::DEFAULT.alphaToCoverageEnable)), + + CommandPointer(new Command1U(&GLBackend::do_setStateSampleMask, State::DEFAULT.sampleMask)), + + CommandPointer(new CommandBlend(&GLBackend::do_setStateBlend, State::DEFAULT.blendFunction)), + + CommandPointer(new Command1U(&GLBackend::do_setStateColorWriteMask, State::DEFAULT.colorWriteMask)) +}; void generateFillMode(GLBackend::GLState::Commands& commands, State::FillMode fillMode) { commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateFillMode, int32(fillMode)))); @@ -37,39 +70,28 @@ void generateCullMode(GLBackend::GLState::Commands& commands, State::CullMode cu commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateCullMode, int32(cullMode)))); } -void generateDepthBias(GLBackend::GLState::Commands& commands, const State& state) { - /* if ((state.getDepthBias() == 0) && (state.getDepthBiasSlopeScale() == 0.0f)) { - commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDisable, GLenum(GL_POLYGON_OFFSET_FILL)))); - commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDisable, GLenum(GL_POLYGON_OFFSET_LINE)))); - commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glDisable, GLenum(GL_POLYGON_OFFSET_POINT)))); - } else { - commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glEnable, GLenum(GL_POLYGON_OFFSET_FILL)))); - commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glEnable, GLenum(GL_POLYGON_OFFSET_LINE)))); - commands.push_back(CommandPointer(new Command1E((Command1E::GLFunction)glEnable, GLenum(GL_POLYGON_OFFSET_POINT)))); - commands.push_back(CommandPointer(new Command2F((Command2F::GLFunction)glPolygonOffset, - state.getDepthBiasSlopeScale(), - state.getDepthBias()))); - }*/ -} - -void generateFrontClockwise(GLBackend::GLState::Commands& commands, bool frontClockwise) { - commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateFrontClockwise, int32(frontClockwise)))); +void generateFrontFaceClockwise(GLBackend::GLState::Commands& commands, bool isClockwise) { + commands.push_back(CommandPointer(new Command1B(&GLBackend::do_setStateFrontFaceClockwise, isClockwise))); } void generateDepthClipEnable(GLBackend::GLState::Commands& commands, bool enable) { - commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateDepthClipEnable, int32(enable)))); + commands.push_back(CommandPointer(new Command1B(&GLBackend::do_setStateDepthClipEnable, enable))); } void generateScissorEnable(GLBackend::GLState::Commands& commands, bool enable) { - commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateScissorEnable, int32(enable)))); + commands.push_back(CommandPointer(new Command1B(&GLBackend::do_setStateScissorEnable, enable))); } void generateMultisampleEnable(GLBackend::GLState::Commands& commands, bool enable) { - commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateMultisampleEnable, int32(enable)))); + commands.push_back(CommandPointer(new Command1B(&GLBackend::do_setStateMultisampleEnable, enable))); } void generateAntialiasedLineEnable(GLBackend::GLState::Commands& commands, bool enable) { - commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateAntialiasedLineEnable, int32(enable)))); + commands.push_back(CommandPointer(new Command1B(&GLBackend::do_setStateAntialiasedLineEnable, enable))); +} + +void generateDepthBias(GLBackend::GLState::Commands& commands, const State& state) { + commands.push_back(CommandPointer(new CommandDepthBias(&GLBackend::do_setStateDepthBias, Vec2(state.getDepthBias(), state.getDepthBiasSlopeScale())))); } void generateDepthTest(GLBackend::GLState::Commands& commands, State::DepthTest& test) { @@ -81,15 +103,19 @@ void generateStencil(GLBackend::GLState::Commands& commands, const State& state) } void generateAlphaToCoverageEnable(GLBackend::GLState::Commands& commands, bool enable) { - commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateAlphaToCoverageEnable, int32(enable)))); + commands.push_back(CommandPointer(new Command1B(&GLBackend::do_setStateAlphaToCoverageEnable, enable))); +} + +void generateSampleMask(GLBackend::GLState::Commands& commands, uint32 mask) { + commands.push_back(CommandPointer(new Command1U(&GLBackend::do_setStateSampleMask, mask))); } void generateBlend(GLBackend::GLState::Commands& commands, const State& state) { - commands.push_back(CommandPointer(new CommandBlend(&GLBackend::do_setStateBlend, state.getBlendFunction(), state.getBlendFactor()))); + commands.push_back(CommandPointer(new CommandBlend(&GLBackend::do_setStateBlend, state.getBlendFunction()))); } -void generateColorWriteMask(GLBackend::GLState::Commands& commands, int32 mask) { - commands.push_back(CommandPointer(new Command1I(&GLBackend::do_setStateColorWriteMask, int32(mask)))); +void generateColorWriteMask(GLBackend::GLState::Commands& commands, uint32 mask) { + commands.push_back(CommandPointer(new Command1U(&GLBackend::do_setStateColorWriteMask, mask))); } GLBackend::GLState* GLBackend::syncGPUObject(const State& state) { @@ -109,6 +135,7 @@ GLBackend::GLState* GLBackend::syncGPUObject(const State& state) { // here, we need to regenerate something so let's do it all object->_commands.clear(); object->_stamp = state.getStamp(); + object->_signature = state.getSignature(); bool depthBias = false; bool stencilState = false; @@ -130,8 +157,8 @@ GLBackend::GLState* GLBackend::syncGPUObject(const State& state) { depthBias = true; break; } - case State::FRONT_FACE: { - generateFrontClockwise(object->_commands, bool(field.second._integer)); + case State::FRONT_FACE_CLOCKWISE: { + generateFrontFaceClockwise(object->_commands, bool(field.second._integer)); break; } case State::DEPTH_CLIP_ENABLE: { @@ -163,6 +190,7 @@ GLBackend::GLState* GLBackend::syncGPUObject(const State& state) { } case State::SAMPLE_MASK: { + generateSampleMask(object->_commands, (field.second._unsigned_integer)); break; } case State::ALPHA_TO_COVERAGE_ENABLE: { @@ -170,12 +198,8 @@ GLBackend::GLState* GLBackend::syncGPUObject(const State& state) { break; } - case State::BLEND_FUNCTION: - case State::BLEND_FACTOR_X: - case State::BLEND_FACTOR_Y: - case State::BLEND_FACTOR_Z: - case State::BLEND_FACTOR_W: { - blendState = true; + case State::BLEND_FUNCTION: { + generateBlend(object->_commands, state); break; } @@ -195,14 +219,26 @@ GLBackend::GLState* GLBackend::syncGPUObject(const State& state) { generateStencil(object->_commands, state); } - if (blendState) { - generateBlend(object->_commands, state); - } - return object; } + + +void GLBackend::resetPipelineState(State::Signature nextSignature) { + auto currentNotSignature = ~_pipeline._stateSignatureCache; + auto nextNotSignature = ~nextSignature; + auto fieldsToBeReset = currentNotSignature ^ (currentNotSignature | nextNotSignature); + if (fieldsToBeReset.any()) { + for (auto i = 0; i < State::NUM_FIELDS; i++) { + if (fieldsToBeReset[i]) { + GLState::_resetStateCommands[i]->run(this); + _pipeline._stateSignatureCache.reset(i); + } + } + } +} + static GLenum GL_COMPARISON_FUNCTIONS[] = { GL_NEVER, GL_LESS, @@ -214,160 +250,246 @@ static GLenum GL_COMPARISON_FUNCTIONS[] = { GL_ALWAYS }; void GLBackend::do_setStateFillMode(int32 mode) { - static GLenum GL_FILL_MODES[] = { GL_POINT, GL_LINE, GL_FILL }; - glPolygonMode(GL_FRONT_AND_BACK, GL_FILL_MODES[mode]); - CHECK_GL_ERROR(); + if (_pipeline._stateCache.fillMode != mode) { + static GLenum GL_FILL_MODES[] = { GL_POINT, GL_LINE, GL_FILL }; + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL_MODES[mode]); + CHECK_GL_ERROR(); + + _pipeline._stateCache.fillMode = State::FillMode(mode); + } } void GLBackend::do_setStateCullMode(int32 mode) { - static GLenum GL_CULL_MODES[] = { GL_FRONT_AND_BACK, GL_FRONT, GL_BACK }; - if (mode == State::CULL_NONE) { - glDisable(GL_CULL_FACE); - glCullFace(GL_FRONT_AND_BACK); - } else { - glEnable(GL_CULL_FACE); - glCullFace(GL_CULL_MODES[mode]); + if (_pipeline._stateCache.cullMode != mode) { + static GLenum GL_CULL_MODES[] = { GL_FRONT_AND_BACK, GL_FRONT, GL_BACK }; + if (mode == State::CULL_NONE) { + glDisable(GL_CULL_FACE); + glCullFace(GL_FRONT_AND_BACK); + } else { + glEnable(GL_CULL_FACE); + glCullFace(GL_CULL_MODES[mode]); + } + CHECK_GL_ERROR(); + + _pipeline._stateCache.cullMode = State::CullMode(mode); } - CHECK_GL_ERROR(); } -void GLBackend::do_setStateFrontClockwise(int32 isFrontClockwise) { - static GLenum GL_FRONT_FACES[] = { GL_CCW, GL_CW }; - glFrontFace(GL_FRONT_FACES[isFrontClockwise]); - CHECK_GL_ERROR(); +void GLBackend::do_setStateFrontFaceClockwise(bool isClockwise) { + if (_pipeline._stateCache.frontFaceClockwise != isClockwise) { + static GLenum GL_FRONT_FACES[] = { GL_CCW, GL_CW }; + glFrontFace(GL_FRONT_FACES[isClockwise]); + CHECK_GL_ERROR(); + + _pipeline._stateCache.frontFaceClockwise = isClockwise; + } } -void GLBackend::do_setStateDepthClipEnable(int32 enable) { - if (enable) { - glEnable(GL_DEPTH_CLAMP); - } else { - glDisable(GL_DEPTH_CLAMP); +void GLBackend::do_setStateDepthClipEnable(bool enable) { + if (_pipeline._stateCache.depthClipEnable != enable) { + if (enable) { + glEnable(GL_DEPTH_CLAMP); + } else { + glDisable(GL_DEPTH_CLAMP); + } + CHECK_GL_ERROR(); + + _pipeline._stateCache.depthClipEnable = enable; } - CHECK_GL_ERROR(); } -void GLBackend::do_setStateScissorEnable(int32 enable) { - if (enable) { - glEnable(GL_SCISSOR_TEST); - } else { - glDisable(GL_SCISSOR_TEST); +void GLBackend::do_setStateScissorEnable(bool enable) { + if (_pipeline._stateCache.scissorEnable != enable) { + if (enable) { + glEnable(GL_SCISSOR_TEST); + } else { + glDisable(GL_SCISSOR_TEST); + } + CHECK_GL_ERROR(); + + _pipeline._stateCache.scissorEnable = enable; } - CHECK_GL_ERROR(); } -void GLBackend::do_setStateMultisampleEnable(int32 enable) { - if (enable) { - glEnable(GL_MULTISAMPLE); - } else { - glDisable(GL_MULTISAMPLE); +void GLBackend::do_setStateMultisampleEnable(bool enable) { + if (_pipeline._stateCache.multisampleEnable != enable) { + if (enable) { + glEnable(GL_MULTISAMPLE); + } else { + glDisable(GL_MULTISAMPLE); + } + CHECK_GL_ERROR(); + + _pipeline._stateCache.multisampleEnable = enable; } - CHECK_GL_ERROR(); } -void GLBackend::do_setStateAntialiasedLineEnable(int32 enable) { - if (enable) { - glEnable(GL_POINT_SMOOTH); - glEnable(GL_LINE_SMOOTH); - } else { - glDisable(GL_POINT_SMOOTH); - glDisable(GL_LINE_SMOOTH); +void GLBackend::do_setStateAntialiasedLineEnable(bool enable) { + if (_pipeline._stateCache.antialisedLineEnable != enable) { + if (enable) { + glEnable(GL_POINT_SMOOTH); + glEnable(GL_LINE_SMOOTH); + } else { + glDisable(GL_POINT_SMOOTH); + glDisable(GL_LINE_SMOOTH); + } + CHECK_GL_ERROR(); + + _pipeline._stateCache.antialisedLineEnable = enable; + } +} + +void GLBackend::do_setStateDepthBias(Vec2 bias) { + if ( (bias.x != _pipeline._stateCache.depthBias) || (bias.y != _pipeline._stateCache.depthBiasSlopeScale)) { + if ((bias.x != 0.f) || (bias.y != 0.f)) { + glEnable(GL_POLYGON_OFFSET_FILL); + glEnable(GL_POLYGON_OFFSET_LINE); + glEnable(GL_POLYGON_OFFSET_POINT); + glPolygonOffset(bias.x, bias.y); + } else { + glDisable(GL_POLYGON_OFFSET_FILL); + glDisable(GL_POLYGON_OFFSET_LINE); + glDisable(GL_POLYGON_OFFSET_POINT); + } + _pipeline._stateCache.depthBias = bias.x; + _pipeline._stateCache.depthBiasSlopeScale = bias.y; } - CHECK_GL_ERROR(); } void GLBackend::do_setStateDepthTest(State::DepthTest test) { - if (test.isEnabled()) { - glEnable(GL_DEPTH_TEST); - glDepthMask(test.getWriteMask()); - glDepthFunc(GL_COMPARISON_FUNCTIONS[test.getFunction()]); - } else { - glDisable(GL_DEPTH_TEST); + if (_pipeline._stateCache.depthTest != test) { + if (test.isEnabled()) { + glEnable(GL_DEPTH_TEST); + glDepthMask(test.getWriteMask()); + glDepthFunc(GL_COMPARISON_FUNCTIONS[test.getFunction()]); + } else { + glDisable(GL_DEPTH_TEST); + } + CHECK_GL_ERROR(); + + _pipeline._stateCache.depthTest = test; } - CHECK_GL_ERROR(); } void GLBackend::do_setStateStencil(State::StencilActivation activation, State::StencilTest frontTest, State::StencilTest backTest) { - if (activation.isEnabled()) { - glEnable(GL_STENCIL_TEST); - glStencilMaskSeparate(GL_FRONT, activation.getWriteMaskFront()); - glStencilMaskSeparate(GL_BACK, activation.getWriteMaskBack()); + + if ((_pipeline._stateCache.stencilActivation != activation) + || (_pipeline._stateCache.stencilTestFront != frontTest) + || (_pipeline._stateCache.stencilTestBack != backTest)) { - static GLenum STENCIL_OPS[] = { - GL_KEEP, - GL_ZERO, - GL_REPLACE, - GL_INCR_WRAP, - GL_DECR_WRAP, - GL_INVERT, - GL_INCR, - GL_DECR }; + if (activation.isEnabled()) { + glEnable(GL_STENCIL_TEST); + glStencilMaskSeparate(GL_FRONT, activation.getWriteMaskFront()); + glStencilMaskSeparate(GL_BACK, activation.getWriteMaskBack()); - glStencilFuncSeparate(GL_FRONT, STENCIL_OPS[frontTest.getFailOp()], STENCIL_OPS[frontTest.getPassOp()], STENCIL_OPS[frontTest.getDepthFailOp()]); - glStencilFuncSeparate(GL_FRONT, GL_COMPARISON_FUNCTIONS[frontTest.getFunction()], frontTest.getReference(), frontTest.getReadMask()); + static GLenum STENCIL_OPS[] = { + GL_KEEP, + GL_ZERO, + GL_REPLACE, + GL_INCR_WRAP, + GL_DECR_WRAP, + GL_INVERT, + GL_INCR, + GL_DECR }; - glStencilFuncSeparate(GL_BACK, STENCIL_OPS[backTest.getFailOp()], STENCIL_OPS[backTest.getPassOp()], STENCIL_OPS[backTest.getDepthFailOp()]); - glStencilFuncSeparate(GL_BACK, GL_COMPARISON_FUNCTIONS[backTest.getFunction()], backTest.getReference(), backTest.getReadMask()); - } else { - glDisable(GL_STENCIL_TEST); - } - CHECK_GL_ERROR(); -} + glStencilFuncSeparate(GL_FRONT, STENCIL_OPS[frontTest.getFailOp()], STENCIL_OPS[frontTest.getPassOp()], STENCIL_OPS[frontTest.getDepthFailOp()]); + glStencilFuncSeparate(GL_FRONT, GL_COMPARISON_FUNCTIONS[frontTest.getFunction()], frontTest.getReference(), frontTest.getReadMask()); -void GLBackend::do_setStateAlphaToCoverageEnable(int32 enable) { - if (enable) { - glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE); - } else { - glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); - } - CHECK_GL_ERROR(); -} - -void GLBackend::do_setStateBlend(State::BlendFunction function, Vec4 factor ) { - if (function.isEnabled()) { - glEnable(GL_BLEND); - - static GLenum GL_BLEND_OPS[] = { - GL_FUNC_ADD, - GL_FUNC_SUBTRACT, - GL_FUNC_REVERSE_SUBTRACT, - GL_MIN, - GL_MAX }; - - glBlendEquationSeparate(GL_BLEND_OPS[function.getOperationColor()], GL_BLEND_OPS[function.getOperationAlpha()]); + glStencilFuncSeparate(GL_BACK, STENCIL_OPS[backTest.getFailOp()], STENCIL_OPS[backTest.getPassOp()], STENCIL_OPS[backTest.getDepthFailOp()]); + glStencilFuncSeparate(GL_BACK, GL_COMPARISON_FUNCTIONS[backTest.getFunction()], backTest.getReference(), backTest.getReadMask()); + } else { + glDisable(GL_STENCIL_TEST); + } CHECK_GL_ERROR(); - static GLenum BLEND_ARGS[] = { - GL_ZERO, - GL_ONE, - GL_SRC_COLOR, - GL_ONE_MINUS_SRC_COLOR, - GL_SRC_ALPHA, - GL_ONE_MINUS_SRC_ALPHA, - GL_DST_ALPHA, - GL_ONE_MINUS_DST_ALPHA, - GL_DST_COLOR, - GL_ONE_MINUS_DST_COLOR, - GL_SRC_ALPHA_SATURATE, - GL_CONSTANT_COLOR, - GL_ONE_MINUS_CONSTANT_COLOR, - GL_CONSTANT_ALPHA, - GL_ONE_MINUS_CONSTANT_ALPHA, - }; - - glBlendFuncSeparate(BLEND_ARGS[function.getSourceColor()], BLEND_ARGS[function.getDestinationColor()], - BLEND_ARGS[function.getSourceAlpha()], BLEND_ARGS[function.getDestinationAlpha()]); - CHECK_GL_ERROR(); - - glBlendColor(factor.x, factor.y, factor.z, factor.w); - CHECK_GL_ERROR(); - } else { - glDisable(GL_BLEND); + _pipeline._stateCache.stencilActivation = activation; + _pipeline._stateCache.stencilTestFront = frontTest; + _pipeline._stateCache.stencilTestBack = backTest; } } -void GLBackend::do_setStateColorWriteMask(int32 mask) { - glColorMask(mask & State::ColorMask::WRITE_RED, +void GLBackend::do_setStateAlphaToCoverageEnable(bool enable) { + if (_pipeline._stateCache.alphaToCoverageEnable != enable) { + if (enable) { + glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE); + } else { + glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE); + } + CHECK_GL_ERROR(); + _pipeline._stateCache.alphaToCoverageEnable = enable; + } +} + +void GLBackend::do_setStateSampleMask(uint32 mask) { + if (_pipeline._stateCache.sampleMask != mask) { + // TODO + _pipeline._stateCache.sampleMask = mask; + } +} + +void GLBackend::do_setStateBlend(State::BlendFunction function) { + if (_pipeline._stateCache.blendFunction != function) { + if (function.isEnabled()) { + glEnable(GL_BLEND); + + static GLenum GL_BLEND_OPS[] = { + GL_FUNC_ADD, + GL_FUNC_SUBTRACT, + GL_FUNC_REVERSE_SUBTRACT, + GL_MIN, + GL_MAX }; + + glBlendEquationSeparate(GL_BLEND_OPS[function.getOperationColor()], GL_BLEND_OPS[function.getOperationAlpha()]); + CHECK_GL_ERROR(); + + static GLenum BLEND_ARGS[] = { + GL_ZERO, + GL_ONE, + GL_SRC_COLOR, + GL_ONE_MINUS_SRC_COLOR, + GL_SRC_ALPHA, + GL_ONE_MINUS_SRC_ALPHA, + GL_DST_ALPHA, + GL_ONE_MINUS_DST_ALPHA, + GL_DST_COLOR, + GL_ONE_MINUS_DST_COLOR, + GL_SRC_ALPHA_SATURATE, + GL_CONSTANT_COLOR, + GL_ONE_MINUS_CONSTANT_COLOR, + GL_CONSTANT_ALPHA, + GL_ONE_MINUS_CONSTANT_ALPHA, + }; + + glBlendFuncSeparate(BLEND_ARGS[function.getSourceColor()], BLEND_ARGS[function.getDestinationColor()], + BLEND_ARGS[function.getSourceAlpha()], BLEND_ARGS[function.getDestinationAlpha()]); + CHECK_GL_ERROR(); + } else { + glDisable(GL_BLEND); + } + + _pipeline._stateCache.blendFunction = function; + } +} + +void GLBackend::do_setStateColorWriteMask(uint32 mask) { + if (_pipeline._stateCache.colorWriteMask = mask) { + glColorMask(mask & State::ColorMask::WRITE_RED, mask & State::ColorMask::WRITE_GREEN, mask & State::ColorMask::WRITE_BLUE, mask & State::ColorMask::WRITE_ALPHA ); + + _pipeline._stateCache.colorWriteMask = mask; + } +} + + +void GLBackend::do_setStateBlendFactor(Batch& batch, uint32 paramOffset) { + + Vec4 factor(batch._params[paramOffset + 0]._float, + batch._params[paramOffset + 1]._float, + batch._params[paramOffset + 2]._float, + batch._params[paramOffset + 3]._float); + + glBlendColor(factor.x, factor.y, factor.z, factor.w); + CHECK_GL_ERROR(); } \ No newline at end of file diff --git a/libraries/gpu/src/gpu/State.cpp b/libraries/gpu/src/gpu/State.cpp index 0260190327..4276e19dbb 100755 --- a/libraries/gpu/src/gpu/State.cpp +++ b/libraries/gpu/src/gpu/State.cpp @@ -19,3 +19,5 @@ State::State() { State::~State() { } + +const State::Cache State::DEFAULT = State::Cache(); diff --git a/libraries/gpu/src/gpu/State.h b/libraries/gpu/src/gpu/State.h index 839768bbc7..c4ac2d0a5d 100755 --- a/libraries/gpu/src/gpu/State.h +++ b/libraries/gpu/src/gpu/State.h @@ -15,6 +15,7 @@ #include #include +#include namespace gpu { @@ -27,40 +28,7 @@ public: virtual ~State(); const Stamp getStamp() const { return _stamp; } - - // All the possible fields - enum Field { - FILL_MODE, - CULL_MODE, - FRONT_FACE, - DEPTH_CLIP_ENABLE, - SCISSOR_ENABLE, - MULTISAMPLE_ENABLE, - ANTIALISED_LINE_ENABLE, - - DEPTH_BIAS, - DEPTH_BIAS_SLOPE_SCALE, - - DEPTH_TEST, - - STENCIL_ACTIVATION, - STENCIL_TEST_FRONT, - STENCIL_TEST_BACK, - - SAMPLE_MASK, - ALPHA_TO_COVERAGE_ENABLE, - - BLEND_FUNCTION, - BLEND_FACTOR_X, - BLEND_FACTOR_Y, - BLEND_FACTOR_Z, - BLEND_FACTOR_W, - - COLOR_WRITE_MASK, - - NUM_FIELDS, // not a valid field, just the count - }; - + enum ComparisonFunction { NEVER = 0, LESS, @@ -157,6 +125,8 @@ public: int32 getRaw() const { return *(reinterpret_cast(this)); } DepthTest(int32 raw) { *(reinterpret_cast(this)) = raw; } + bool operator== (const DepthTest& right) { return getRaw() == right.getRaw(); } + bool operator!= (const DepthTest& right) { return getRaw() != right.getRaw(); } }; class StencilTest { @@ -187,6 +157,8 @@ public: int32 getRaw() const { return *(reinterpret_cast(this)); } StencilTest(int32 raw) { *(reinterpret_cast(this)) = raw; } + bool operator== (const StencilTest& right) { return getRaw() == right.getRaw(); } + bool operator!= (const StencilTest& right) { return getRaw() != right.getRaw(); } }; class StencilActivation { @@ -204,9 +176,10 @@ public: int32 getRaw() const { return *(reinterpret_cast(this)); } StencilActivation(int32 raw) { *(reinterpret_cast(this)) = raw; } + bool operator== (const StencilActivation& right) { return getRaw() == right.getRaw(); } + bool operator!= (const StencilActivation& right) { return getRaw() != right.getRaw(); } }; - class BlendFunction { static const int COLOR_MASK = 0x0f; static const int ALPHA_MASK = 0xf0; @@ -244,8 +217,151 @@ public: int32 getRaw() const { return *(reinterpret_cast(this)); } BlendFunction(int32 raw) { *(reinterpret_cast(this)) = raw; } + bool operator== (const BlendFunction& right) { return getRaw() == right.getRaw(); } + bool operator!= (const BlendFunction& right) { return getRaw() != right.getRaw(); } }; + // The Cache class is the full explicit description of the State class fields value. + // Useful for having one const static called Default for reference or for the gpu::Backend to keep track of the current value + class Cache { + public: + FillMode fillMode = FILL_FACE; + CullMode cullMode = CULL_NONE; + bool frontFaceClockwise = true; + bool depthClipEnable = false; + bool scissorEnable = false; + bool multisampleEnable = false; + bool antialisedLineEnable = false; + + float depthBias = 0.0f; + float depthBiasSlopeScale = 0.0f; + + DepthTest depthTest = DepthTest(false, true, LESS); + + StencilActivation stencilActivation = StencilActivation(false); + StencilTest stencilTestFront = StencilTest(0, 0xff, ALWAYS, STENCIL_OP_KEEP, STENCIL_OP_KEEP, STENCIL_OP_KEEP); + StencilTest stencilTestBack = StencilTest(0, 0xff, ALWAYS, STENCIL_OP_KEEP, STENCIL_OP_KEEP, STENCIL_OP_KEEP); + + uint32 sampleMask = 0xFFFFFFFF; + bool alphaToCoverageEnable = false; + + BlendFunction blendFunction = BlendFunction(false); + + uint32 colorWriteMask = WRITE_ALL; + }; + + // The unique default values for all the fields + static const Cache DEFAULT; + + void setFillMode(FillMode fill) { set(FILL_MODE, DEFAULT.fillMode, fill); } + FillMode getFillMode() const { return get(FILL_MODE, DEFAULT.fillMode); } + + void setCullMode(CullMode cull) { set(CULL_MODE, DEFAULT.cullMode, cull); } + CullMode getCullMode() const { return get(CULL_MODE, DEFAULT.cullMode); } + + void setFrontFaceClockwise(bool isClockwise) { set(FRONT_FACE_CLOCKWISE, DEFAULT.frontFaceClockwise, isClockwise); } + bool isFrontFaceClockwise() const { return get(FRONT_FACE_CLOCKWISE, DEFAULT.frontFaceClockwise); } + + void setDepthClipEnable(bool enable) { set(DEPTH_CLIP_ENABLE, DEFAULT.depthClipEnable, enable); } + bool isDepthClipEnable() const { return get(DEPTH_CLIP_ENABLE, DEFAULT.depthClipEnable); } + + void setScissorEnable(bool enable) { set(SCISSOR_ENABLE, DEFAULT.scissorEnable, enable); } + bool isScissorEnable() const { return get(SCISSOR_ENABLE, DEFAULT.scissorEnable); } + + void setMultisampleEnable(bool enable) { set(MULTISAMPLE_ENABLE, DEFAULT.multisampleEnable, enable); } + bool isMultisampleEnable() const { return get(MULTISAMPLE_ENABLE, DEFAULT.multisampleEnable); } + + void setAntialiasedLineEnable(bool enable) { set(ANTIALISED_LINE_ENABLE, DEFAULT.antialisedLineEnable, enable); } + bool isAntialiasedLineEnable() const { return get(ANTIALISED_LINE_ENABLE, DEFAULT.antialisedLineEnable); } + + // Depth Bias + void setDepthBias(float bias) { set(DEPTH_BIAS, DEFAULT.depthBias, bias); } + float getDepthBias() const { return get(DEPTH_BIAS, DEFAULT.depthBias); } + + void setDepthBiasSlopeScale(float scale) { set(DEPTH_BIAS_SLOPE_SCALE, DEFAULT.depthBiasSlopeScale, scale); } + float getDepthBiasSlopeScale() const { return get(DEPTH_BIAS_SLOPE_SCALE, DEFAULT.depthBiasSlopeScale); } + + // Depth Test + void setDepthTest(DepthTest depthTest) { set(DEPTH_TEST, DEFAULT.depthTest, depthTest); } + void setDepthTest(bool enable, bool writeMask, ComparisonFunction func) { setDepthTest(DepthTest(enable, writeMask, func)); } + DepthTest getDepthTest() const { return get(DEPTH_TEST, DEFAULT.depthTest); } + + bool isDepthTestEnabled() const { return getDepthTest().isEnabled(); } + bool getDepthTestWriteMask() const { return getDepthTest().getWriteMask(); } + ComparisonFunction getDepthTestFunc() const { return getDepthTest().getFunction(); } + + // Stencil test + void setStencilTest(bool enabled, uint8 frontWriteMask, StencilTest frontTest, uint8 backWriteMask, StencilTest backTest) { + set(STENCIL_ACTIVATION, DEFAULT.stencilActivation, StencilActivation(enabled, frontWriteMask, backWriteMask)); + set(STENCIL_TEST_FRONT, DEFAULT.stencilTestFront, frontTest); + set(STENCIL_TEST_BACK, DEFAULT.stencilTestBack, backTest); } + void setStencilTest(bool enabled, uint8 frontWriteMask, StencilTest frontTest) { + setStencilTest(enabled, frontWriteMask, frontTest, frontWriteMask, frontTest); } + + StencilActivation getStencilActivation() const { return get(STENCIL_ACTIVATION, DEFAULT.stencilActivation); } + StencilTest getStencilTestFront() const { return get(STENCIL_TEST_FRONT, DEFAULT.stencilTestFront); } + StencilTest getStencilTestBack() const { return get(STENCIL_TEST_BACK, DEFAULT.stencilTestBack); } + + bool isStencilEnabled() const { return getStencilActivation().isEnabled(); } + uint8 getStencilWriteMaskFront() const { return getStencilActivation().getWriteMaskFront(); } + uint8 getStencilWriteMaskBack() const { return getStencilActivation().getWriteMaskBack(); } + + // Alpha to coverage + void setAlphaToCoverageEnable(bool enable) { set(ALPHA_TO_COVERAGE_ENABLE, DEFAULT.alphaToCoverageEnable, enable); } + bool isAlphaToCoverageEnabled() const { return get(ALPHA_TO_COVERAGE_ENABLE, DEFAULT.alphaToCoverageEnable); } + + // Sample mask + void setSampleMask(uint32 mask) { set(SAMPLE_MASK, DEFAULT.sampleMask, mask); } + uint32 getSampleMask() const { return get(SAMPLE_MASK, DEFAULT.sampleMask); } + + // Blend Function + void setBlendFunction(BlendFunction function) { set(BLEND_FUNCTION, DEFAULT.blendFunction, function); } + BlendFunction getBlendFunction() const { return get(BLEND_FUNCTION, DEFAULT.blendFunction); } + + void setBlendFunction(bool enabled, BlendArg sourceColor, BlendOp operationColor, BlendArg destinationColor, BlendArg sourceAlpha, BlendOp operationAlpha, BlendArg destinationAlpha) { + setBlendFunction(BlendFunction(enabled, sourceColor, operationColor, destinationColor, sourceAlpha, operationAlpha, destinationAlpha)); } + void setBlendFunction(bool enabled, BlendArg source, BlendOp operation, BlendArg destination) { + setBlendFunction(BlendFunction(enabled, source, operation, destination)); } + + bool isBlendEnabled() const { return getBlendFunction().isEnabled(); } + + // Color write mask + void setColorWriteMask(int32 mask) { set(COLOR_WRITE_MASK, DEFAULT.colorWriteMask, mask); } + uint32 getColorWriteMask() const { return get(COLOR_WRITE_MASK, DEFAULT.colorWriteMask); } + + // The state values are stored in a Map called FieldMap + // only the fields with non default value are saved + + // All the possible fields + enum Field { + FILL_MODE, + CULL_MODE, + FRONT_FACE_CLOCKWISE, + DEPTH_CLIP_ENABLE, + SCISSOR_ENABLE, + MULTISAMPLE_ENABLE, + ANTIALISED_LINE_ENABLE, + + DEPTH_BIAS, + DEPTH_BIAS_SLOPE_SCALE, + + DEPTH_TEST, + + STENCIL_ACTIVATION, + STENCIL_TEST_FRONT, + STENCIL_TEST_BACK, + + SAMPLE_MASK, + ALPHA_TO_COVERAGE_ENABLE, + + BLEND_FUNCTION, + + COLOR_WRITE_MASK, + + NUM_FIELDS, // not a valid field, just the count + }; + + // the value of a field class Value { public: union { @@ -272,12 +388,30 @@ public: template <> StencilTest State::Value::cast() const { return StencilTest(_integer); } template <> BlendFunction State::Value::cast() const { return BlendFunction(_integer); } }; + + // The field map type typedef std::unordered_map FieldMap; const FieldMap& getFields() const { return _fields; } - template void set(Field field, T value) { - _fields[field].uncast(value); + // The signature of the state tells which fields of the state are not default + // this way during rendering the Backend can compare it's current state and try to minimize the job to do + typedef std::bitset Signature; + + Signature getSignature() const { return _signature; } + +protected: + State(const State& state); + State& operator=(const State& state); + + template void set(Field field, T defaultValue, T value) { + if (value == defaultValue) { + _fields.erase(field); + _signature.reset(field); + } else { + _fields[field].uncast(value); + _signature.set(field); + } _stamp++; } @@ -289,96 +423,9 @@ public: return defaultValue; } - void setFillMode(FillMode fill) { set(FILL_MODE, fill); } - FillMode getFillMode() const { return get(FILL_MODE, FILL_FACE); } - - void setCullMode(CullMode cull) { set(CULL_MODE, cull); } - CullMode getCullMode() const { return get(CULL_MODE, CULL_NONE); } - - void setFrontFace(bool isClockwise) { set(FRONT_FACE, isClockwise); } - bool isFrontFaceClockwise() const { return get(FRONT_FACE, true); } - - void setDepthClipEnable(bool enable) { set(DEPTH_CLIP_ENABLE, enable); } - bool isDepthClipEnable() const { return get(DEPTH_CLIP_ENABLE, false); } - - void setScissorEnable(bool enable) { set(SCISSOR_ENABLE, enable); } - bool isScissorEnable() const { return get(SCISSOR_ENABLE, false); } - - void setMultisampleEnable(bool enable) { set(MULTISAMPLE_ENABLE, enable); } - bool isMultisampleEnable() const { return get(MULTISAMPLE_ENABLE, false); } - - void setAntialiasedLineEnable(bool enable) { set(ANTIALISED_LINE_ENABLE, enable); } - bool isAntialiasedLineEnable() const { return get(ANTIALISED_LINE_ENABLE, true); } - - // Depth Bias - void setDepthBias(float bias) { set(DEPTH_BIAS, bias); } - void setDepthBiasSlopeScale(float scale) { set(DEPTH_BIAS_SLOPE_SCALE, scale); } - float getDepthBias() const { return get(DEPTH_BIAS, 0.0f); } - float getDepthBiasSlopeScale() const { return get(DEPTH_BIAS_SLOPE_SCALE, 1.0f); } - - // Depth Test - void setDepthTest(DepthTest depthTest) { set(DEPTH_TEST, depthTest); } - void setDepthTest(bool enable, bool writeMask, ComparisonFunction func) { setDepthTest(DepthTest(enable, writeMask, func)); } - DepthTest getDepthTest() const { return get(DEPTH_TEST, DepthTest(false, true, LESS)); } - - bool isDepthTestEnabled() const { return getDepthTest().isEnabled(); } - bool getDepthTestWriteMask() const { return getDepthTest().getWriteMask(); } - ComparisonFunction getDepthTestFunc() const { return getDepthTest().getFunction(); } - - // Stencil test - void setStencilTest(bool enabled, uint8 frontWriteMask, StencilTest frontTest, uint8 backWriteMask, StencilTest backTest) { - set(STENCIL_ACTIVATION, StencilActivation(enabled, frontWriteMask, backWriteMask)); - set(STENCIL_TEST_FRONT, frontTest); - set(STENCIL_TEST_BACK, backTest); } - void setStencilTest(bool enabled, uint8 frontWriteMask, StencilTest frontTest) { - setStencilTest(enabled, frontWriteMask, frontTest, frontWriteMask, frontTest); } - - StencilActivation getStencilActivation() const { return get(STENCIL_ACTIVATION, StencilActivation(false)); } - bool isStencilEnabled() const { return getStencilActivation().isEnabled(); } - uint8 getStencilWriteMaskFront() const { return getStencilActivation().getWriteMaskFront(); } - uint8 getStencilWriteMaskBack() const { return getStencilActivation().getWriteMaskBack(); } - - StencilTest getStencilTestFront() const { return get(STENCIL_TEST_FRONT, StencilTest()); } - StencilTest getStencilTestBack() const { return get(STENCIL_TEST_BACK, StencilTest()); } - - // Alpha to coverage - void setAlphaToCoverageEnable(bool enable) { set(ALPHA_TO_COVERAGE_ENABLE, enable); } - bool isAlphaToCoverageEnabled() const { return get(ALPHA_TO_COVERAGE_ENABLE, false); } - - // Sample mask - void setSampleMask(uint32 mask) { set(SAMPLE_MASK, mask); } - uint32 getSampleMask() const { return get(SAMPLE_MASK, 0xFFFFFFFF); } - - // Blend - void setBlendFunction(BlendFunction function) { set(BLEND_FUNCTION, function); } - void setBlendFunction(bool enabled, BlendArg sourceColor, BlendOp operationColor, BlendArg destinationColor, BlendArg sourceAlpha, BlendOp operationAlpha, BlendArg destinationAlpha) { - setBlendFunction(BlendFunction(enabled, sourceColor, operationColor, destinationColor, sourceAlpha, operationAlpha, destinationAlpha)); } - void setBlendFunction(bool enabled, BlendArg source, BlendOp operation, BlendArg destination) { - setBlendFunction(BlendFunction(enabled, source, operation, destination)); } - BlendFunction getBlendFunction() const { return get(BLEND_FUNCTION, BlendFunction(false)); } - - bool isBlendEnabled() const { return getBlendFunction().isEnabled(); } - - void setBlendFactor(const Vec4& factor) { - set(BLEND_FACTOR_X, factor.x); - set(BLEND_FACTOR_Y, factor.y); - set(BLEND_FACTOR_Z, factor.z); - set(BLEND_FACTOR_W, factor.w); } - Vec4 State::getBlendFactor() const { - return Vec4(get(BLEND_FACTOR_X, 0.0f), get(BLEND_FACTOR_Y, 0.0f), get(BLEND_FACTOR_Z, 0.0f), get(BLEND_FACTOR_W, 0.0f)); - } - - // Color write mask - void setColorWriteMask(int32 mask) { set(COLOR_WRITE_MASK, mask); } - uint32 getColorWriteMask() const { return get(COLOR_WRITE_MASK, WRITE_ALL); } - -protected: - State(const State& state); - State& operator=(const State& state); - FieldMap _fields; - - Stamp _stamp = 0; + Signature _signature{0}; + Stamp _stamp{0}; // This shouldn't be used by anything else than the Backend class with the proper casting. mutable GPUObject* _gpuObject = nullptr; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 130d6b7f5c..3f304fc630 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -785,6 +785,9 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, true, true, true, args, true); } + // try that + batch.setPipeline(gpu::PipelinePointer()); + GLBATCH(glDepthMask)(true); GLBATCH(glDepthFunc)(GL_LESS); GLBATCH(glDisable)(GL_CULL_FACE); @@ -2428,7 +2431,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod } if (mesh.colors.isEmpty()) { - GLBATCH(glColor4f)(1.0f, 1.0f, 1.0f, 1.0f); + GLBATCH(glColor4f)(0.0f, 1.0f, 0.0f, 1.0f); } qint64 offset = 0; From ce659e6307e5869233a481eb078824739a2861b5 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Sun, 29 Mar 2015 10:15:18 -0700 Subject: [PATCH 09/21] Introducing the gl state capture in order to resync the gpu::state with the true gl state --- libraries/gpu/src/gpu/GLBackend.h | 11 +- libraries/gpu/src/gpu/GLBackendPipeline.cpp | 5 + libraries/gpu/src/gpu/GLBackendState.cpp | 227 +++++++++++++++++++- libraries/gpu/src/gpu/State.cpp | 58 +++++ libraries/gpu/src/gpu/State.h | 18 +- 5 files changed, 307 insertions(+), 12 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 3ca65d45eb..7e5c6c775f 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -256,8 +256,13 @@ protected: 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(); - void resetPipelineState(State::Signature toBeReset); + // 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(); + struct PipelineStageState { PipelinePointer _pipeline; @@ -270,6 +275,7 @@ protected: GLState* _state; bool _invalidState; + bool _needStateSync; PipelineStageState() : _pipeline(), @@ -278,7 +284,8 @@ protected: _stateSignatureCache(0), _stateCache(State::DEFAULT), _state(nullptr), - _invalidState(false) + _invalidState(false), + _needStateSync(true) {} } _pipeline; diff --git a/libraries/gpu/src/gpu/GLBackendPipeline.cpp b/libraries/gpu/src/gpu/GLBackendPipeline.cpp index d0ef01c4a4..409cf5594c 100755 --- a/libraries/gpu/src/gpu/GLBackendPipeline.cpp +++ b/libraries/gpu/src/gpu/GLBackendPipeline.cpp @@ -64,6 +64,11 @@ void GLBackend::do_setPipeline(Batch& batch, uint32 paramOffset) { return; } + if (_pipeline._needStateSync) { + syncPipelineStateCache(); + _pipeline._needStateSync = false; + } + // null pipeline == reset if (!pipeline) { _pipeline._pipeline.reset(); diff --git a/libraries/gpu/src/gpu/GLBackendState.cpp b/libraries/gpu/src/gpu/GLBackendState.cpp index 2397af7cec..809f4177c8 100644 --- a/libraries/gpu/src/gpu/GLBackendState.cpp +++ b/libraries/gpu/src/gpu/GLBackendState.cpp @@ -223,8 +223,6 @@ GLBackend::GLState* GLBackend::syncGPUObject(const State& state) { } - - void GLBackend::resetPipelineState(State::Signature nextSignature) { auto currentNotSignature = ~_pipeline._stateSignatureCache; auto nextNotSignature = ~nextSignature; @@ -237,6 +235,231 @@ 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; + } + + 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; +} + +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; + } + + 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) { + return State::SRC_ALPHA; + } else if (blendArg == GL_ONE_MINUS_SRC_ALPHA) { + return State::INV_SRC_ALPHA; + } else if (blendArg == GL_DST_ALPHA) { + return State::DEST_ALPHA; + } else if (blendArg == GL_ONE_MINUS_DST_ALPHA) { + return State::INV_DEST_ALPHA; + } else if (blendArg == GL_CONSTANT_COLOR) { + return State::FACTOR_COLOR; + } else if (blendArg == GL_ONE_MINUS_CONSTANT_COLOR) { + return State::INV_FACTOR_COLOR; + } else if (blendArg == GL_CONSTANT_ALPHA) { + return State::FACTOR_ALPHA; + } else if (blendArg == GL_ONE_MINUS_CONSTANT_ALPHA) { + return State::INV_FACTOR_ALPHA; + } + + return State::ONE; +} + + +void GLBackend::syncPipelineStateCache() { + 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; + glGetIntegerv(GL_SAMPLE_COVERAGE, &mask); + state.sampleMask = mask; + } + { + state.alphaToCoverageEnable = glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE); + } + { + GLboolean isEnabled = glIsEnabled(GL_BLEND); + GLint srcRGB; + GLint srcA; + GLint dstRGB; + GLint dstA; + glGetIntegerv(GL_BLEND_SRC_RGB, &srcRGB); + glGetIntegerv(GL_BLEND_SRC_ALPHA, &srcA); + glGetIntegerv(GL_BLEND_DST_RGB, &dstRGB); + glGetIntegerv(GL_BLEND_DST_ALPHA, &dstA); + + GLint opRGB; + GLint opA; + glGetIntegerv(GL_BLEND_EQUATION_RGB, &opRGB); + glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &opA); + + state.blendFunction = State::BlendFunction(false, + blendArgFromGL(srcRGB), blendOpFromGL(opRGB), blendArgFromGL(dstRGB), + blendArgFromGL(srcA), blendOpFromGL(opA), blendArgFromGL(dstA)); + } + { + 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) + | (mask[3] ? State::WRITE_ALPHA : 0); + } + + CHECK_GL_ERROR(); + + State::Signature signature = State::evalSignature(state); + + _pipeline._stateCache = state; + _pipeline._stateSignatureCache = signature; } static GLenum GL_COMPARISON_FUNCTIONS[] = { diff --git a/libraries/gpu/src/gpu/State.cpp b/libraries/gpu/src/gpu/State.cpp index 4276e19dbb..d2488aac17 100755 --- a/libraries/gpu/src/gpu/State.cpp +++ b/libraries/gpu/src/gpu/State.cpp @@ -21,3 +21,61 @@ State::~State() { } const State::Cache State::DEFAULT = State::Cache(); + +State::Signature State::evalSignature(const Cache& state) { + Signature signature(0); + + if (state.fillMode != State::DEFAULT.fillMode) { + signature.set(State::FILL_MODE); + } + if (state.cullMode != State::DEFAULT.cullMode) { + signature.set(State::CULL_MODE); + } + if (state.frontFaceClockwise != State::DEFAULT.frontFaceClockwise) { + signature.set(State::FRONT_FACE_CLOCKWISE); + } + if (state.depthClipEnable != State::DEFAULT.depthClipEnable) { + signature.set(State::DEPTH_CLIP_ENABLE); + } + if (state.scissorEnable != State::DEFAULT.scissorEnable) { + signature.set(State::SCISSOR_ENABLE); + } + if (state.multisampleEnable != State::DEFAULT.multisampleEnable) { + signature.set(State::MULTISAMPLE_ENABLE); + } + if (state.antialisedLineEnable != State::DEFAULT.antialisedLineEnable) { + signature.set(State::ANTIALISED_LINE_ENABLE); + } + if (state.depthBias != State::DEFAULT.depthBias) { + signature.set(State::DEPTH_BIAS); + } + if (state.depthBiasSlopeScale != State::DEFAULT.depthBiasSlopeScale) { + signature.set(State::DEPTH_BIAS_SLOPE_SCALE); + } + if (state.depthTest != State::DEFAULT.depthTest) { + signature.set(State::DEPTH_TEST); + } + if (state.stencilActivation != State::DEFAULT.stencilActivation) { + signature.set(State::STENCIL_ACTIVATION); + } + if (state.stencilTestFront != State::DEFAULT.stencilTestFront) { + signature.set(State::STENCIL_TEST_FRONT); + } + if (state.stencilTestBack != State::DEFAULT.stencilTestBack) { + signature.set(State::STENCIL_TEST_BACK); + } + if (state.sampleMask != State::DEFAULT.sampleMask) { + signature.set(State::SAMPLE_MASK); + } + if (state.alphaToCoverageEnable != State::DEFAULT.alphaToCoverageEnable) { + signature.set(State::ALPHA_TO_COVERAGE_ENABLE); + } + if (state.blendFunction != State::DEFAULT.blendFunction) { + signature.set(State::BLEND_FUNCTION); + } + if (state.colorWriteMask != State::DEFAULT.colorWriteMask) { + signature.set(State::COLOR_WRITE_MASK); + } + + return signature; +} diff --git a/libraries/gpu/src/gpu/State.h b/libraries/gpu/src/gpu/State.h index c4ac2d0a5d..32b91c544c 100755 --- a/libraries/gpu/src/gpu/State.h +++ b/libraries/gpu/src/gpu/State.h @@ -125,8 +125,8 @@ public: int32 getRaw() const { return *(reinterpret_cast(this)); } DepthTest(int32 raw) { *(reinterpret_cast(this)) = raw; } - bool operator== (const DepthTest& right) { return getRaw() == right.getRaw(); } - bool operator!= (const DepthTest& right) { return getRaw() != right.getRaw(); } + bool operator== (const DepthTest& right) const { return getRaw() == right.getRaw(); } + bool operator!= (const DepthTest& right) const { return getRaw() != right.getRaw(); } }; class StencilTest { @@ -157,8 +157,8 @@ public: int32 getRaw() const { return *(reinterpret_cast(this)); } StencilTest(int32 raw) { *(reinterpret_cast(this)) = raw; } - bool operator== (const StencilTest& right) { return getRaw() == right.getRaw(); } - bool operator!= (const StencilTest& right) { return getRaw() != right.getRaw(); } + bool operator== (const StencilTest& right) const { return getRaw() == right.getRaw(); } + bool operator!= (const StencilTest& right) const { return getRaw() != right.getRaw(); } }; class StencilActivation { @@ -176,8 +176,8 @@ public: int32 getRaw() const { return *(reinterpret_cast(this)); } StencilActivation(int32 raw) { *(reinterpret_cast(this)) = raw; } - bool operator== (const StencilActivation& right) { return getRaw() == right.getRaw(); } - bool operator!= (const StencilActivation& right) { return getRaw() != right.getRaw(); } + bool operator== (const StencilActivation& right) const { return getRaw() == right.getRaw(); } + bool operator!= (const StencilActivation& right) const { return getRaw() != right.getRaw(); } }; class BlendFunction { @@ -217,8 +217,8 @@ public: int32 getRaw() const { return *(reinterpret_cast(this)); } BlendFunction(int32 raw) { *(reinterpret_cast(this)) = raw; } - bool operator== (const BlendFunction& right) { return getRaw() == right.getRaw(); } - bool operator!= (const BlendFunction& right) { return getRaw() != right.getRaw(); } + 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. @@ -400,6 +400,8 @@ public: Signature getSignature() const { return _signature; } + static Signature evalSignature(const Cache& state); + protected: State(const State& state); State& operator=(const State& state); From 2a58a65a8fe4f4c18e16249a47414182d0eefc60 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 30 Mar 2015 10:10:39 -0700 Subject: [PATCH 10/21] back to the office monday morning, State almost working in the full piupeline --- interface/src/Environment.cpp | 4 +++- libraries/gpu/src/gpu/GLBackendPipeline.cpp | 2 +- libraries/gpu/src/gpu/State.h | 2 +- libraries/render-utils/src/Model.cpp | 2 ++ 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/interface/src/Environment.cpp b/interface/src/Environment.cpp index 5cc132bb7f..5389c81137 100644 --- a/interface/src/Environment.cpp +++ b/interface/src/Environment.cpp @@ -262,9 +262,11 @@ void Environment::renderAtmosphere(Camera& camera, const EnvironmentData& data) program->setUniformValue(locations[G2_LOCATION], -0.990f * -0.990f); glDepthMask(GL_FALSE); - glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); + // glDisable(GL_DEPTH_TEST); DependencyManager::get()->renderSphere(1.0f, 100, 50, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)); //Draw a unit sphere glDepthMask(GL_TRUE); +// glEnable(GL_CULL_FACE); program->release(); diff --git a/libraries/gpu/src/gpu/GLBackendPipeline.cpp b/libraries/gpu/src/gpu/GLBackendPipeline.cpp index 409cf5594c..13051b68cb 100755 --- a/libraries/gpu/src/gpu/GLBackendPipeline.cpp +++ b/libraries/gpu/src/gpu/GLBackendPipeline.cpp @@ -65,7 +65,7 @@ void GLBackend::do_setPipeline(Batch& batch, uint32 paramOffset) { } if (_pipeline._needStateSync) { - syncPipelineStateCache(); + // syncPipelineStateCache(); _pipeline._needStateSync = false; } diff --git a/libraries/gpu/src/gpu/State.h b/libraries/gpu/src/gpu/State.h index 32b91c544c..f3529da01e 100755 --- a/libraries/gpu/src/gpu/State.h +++ b/libraries/gpu/src/gpu/State.h @@ -227,7 +227,7 @@ public: public: FillMode fillMode = FILL_FACE; CullMode cullMode = CULL_NONE; - bool frontFaceClockwise = true; + bool frontFaceClockwise = false; bool depthClipEnable = false; bool scissorEnable = false; bool multisampleEnable = false; diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 3f304fc630..9a94716637 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -120,6 +120,8 @@ void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey& key, // Backface on shadow if (key.isShadow()) { state->setCullMode(gpu::State::CULL_FRONT); + state->setDepthBias(1.1f); + state->setDepthBiasSlopeScale(4.0f); } else { state->setCullMode(gpu::State::CULL_BACK); } From ee3ec3fe1ac4570d78e2ddd63d43030033c8579c Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 30 Mar 2015 17:28:58 -0700 Subject: [PATCH 11/21] found the issue brekaing the render, i didn't do the Blend enable sync properly --- interface/src/Environment.cpp | 4 +-- libraries/gpu/src/gpu/GLBackend.h | 4 ++- libraries/gpu/src/gpu/GLBackendPipeline.cpp | 10 +++++++- libraries/gpu/src/gpu/GLBackendState.cpp | 27 +++++++++++++++------ 4 files changed, 33 insertions(+), 12 deletions(-) diff --git a/interface/src/Environment.cpp b/interface/src/Environment.cpp index 5389c81137..4547cacf83 100644 --- a/interface/src/Environment.cpp +++ b/interface/src/Environment.cpp @@ -261,12 +261,12 @@ void Environment::renderAtmosphere(Camera& camera, const EnvironmentData& data) program->setUniformValue(locations[G_LOCATION], -0.990f); program->setUniformValue(locations[G2_LOCATION], -0.990f * -0.990f); + glFrontFace(GL_CCW); glDepthMask(GL_FALSE); + glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); - // glDisable(GL_DEPTH_TEST); DependencyManager::get()->renderSphere(1.0f, 100, 50, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)); //Draw a unit sphere glDepthMask(GL_TRUE); -// glEnable(GL_CULL_FACE); program->release(); diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 7e5c6c775f..5f6ae3957d 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -260,8 +260,10 @@ protected: 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 + // 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 { diff --git a/libraries/gpu/src/gpu/GLBackendPipeline.cpp b/libraries/gpu/src/gpu/GLBackendPipeline.cpp index 13051b68cb..6a66f9aa99 100755 --- a/libraries/gpu/src/gpu/GLBackendPipeline.cpp +++ b/libraries/gpu/src/gpu/GLBackendPipeline.cpp @@ -65,7 +65,7 @@ void GLBackend::do_setPipeline(Batch& batch, uint32 paramOffset) { } if (_pipeline._needStateSync) { - // syncPipelineStateCache(); + syncPipelineStateCache(); _pipeline._needStateSync = false; } @@ -109,6 +109,14 @@ void GLBackend::do_setPipeline(Batch& batch, uint32 paramOffset) { } void GLBackend::updatePipeline() { +#ifdef DEBUG_GLSTATE + if (_pipeline._needStateSync) { + State::Cache state; + getCurrentGLState(state); + State::Signature signature = State::evalSignature(state); + } +#endif + if (_pipeline._invalidProgram) { // doing it here is aproblem for calls to glUniform.... so will do it on assing... glUseProgram(_pipeline._program); diff --git a/libraries/gpu/src/gpu/GLBackendState.cpp b/libraries/gpu/src/gpu/GLBackendState.cpp index 809f4177c8..d06ba06d63 100644 --- a/libraries/gpu/src/gpu/GLBackendState.cpp +++ b/libraries/gpu/src/gpu/GLBackendState.cpp @@ -331,9 +331,7 @@ State::BlendArg blendArgFromGL(GLenum blendArg) { return State::ONE; } - -void GLBackend::syncPipelineStateCache() { - State::Cache state; +void GLBackend::getCurrentGLState(State::Cache& state) { { GLint modes[2]; glGetIntegerv(GL_POLYGON_MODE, modes); @@ -418,8 +416,11 @@ void GLBackend::syncPipelineStateCache() { state.stencilTestBack = State::StencilTest(backRef, backReadMask, comparisonFuncFromGL(backFunc), stencilOpFromGL(backFail), stencilOpFromGL(backDepthFail), stencilOpFromGL(backPass)); } { - GLint mask; - glGetIntegerv(GL_SAMPLE_COVERAGE, &mask); + GLint mask = 0xFFFFFFFF; + if (glIsEnabled(GL_SAMPLE_MASK)) { + glGetIntegerv(GL_SAMPLE_MASK, &mask); + state.sampleMask = mask; + } state.sampleMask = mask; } { @@ -441,7 +442,7 @@ void GLBackend::syncPipelineStateCache() { glGetIntegerv(GL_BLEND_EQUATION_RGB, &opRGB); glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &opA); - state.blendFunction = State::BlendFunction(false, + state.blendFunction = State::BlendFunction(isEnabled, blendArgFromGL(srcRGB), blendOpFromGL(opRGB), blendArgFromGL(dstRGB), blendArgFromGL(srcA), blendOpFromGL(opA), blendArgFromGL(dstA)); } @@ -454,8 +455,13 @@ void GLBackend::syncPipelineStateCache() { | (mask[3] ? State::WRITE_ALPHA : 0); } - CHECK_GL_ERROR(); + CHECK_GL_ERROR(); +} +void GLBackend::syncPipelineStateCache() { + State::Cache state; + + getCurrentGLState(state); State::Signature signature = State::evalSignature(state); _pipeline._stateCache = state; @@ -645,7 +651,12 @@ void GLBackend::do_setStateAlphaToCoverageEnable(bool enable) { void GLBackend::do_setStateSampleMask(uint32 mask) { if (_pipeline._stateCache.sampleMask != mask) { - // TODO + if (mask == 0xFFFFFFFF) { + glDisable(GL_SAMPLE_MASK); + } else { + glEnable(GL_SAMPLE_MASK); + glSampleMaski(0, mask); + } _pipeline._stateCache.sampleMask = mask; } } From ee4b9a483bafb8b39c61cc2eaf06ccdc819d6df9 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 30 Mar 2015 18:04:44 -0700 Subject: [PATCH 12/21] found the issue brekaing the render, i didn't do the Blend enable sync properly --- interface/src/Environment.cpp | 4 ++-- libraries/gpu/src/gpu/GLBackendPipeline.cpp | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/interface/src/Environment.cpp b/interface/src/Environment.cpp index 4547cacf83..e6fc0184cf 100644 --- a/interface/src/Environment.cpp +++ b/interface/src/Environment.cpp @@ -260,11 +260,11 @@ void Environment::renderAtmosphere(Camera& camera, const EnvironmentData& data) (1.0f / (data.getAtmosphereOuterRadius() - data.getAtmosphereInnerRadius())) / 0.25f); program->setUniformValue(locations[G_LOCATION], -0.990f); program->setUniformValue(locations[G2_LOCATION], -0.990f * -0.990f); - - glFrontFace(GL_CCW); + glDepthMask(GL_FALSE); glDisable(GL_DEPTH_TEST); glDisable(GL_CULL_FACE); + glEnable(GL_BLEND); DependencyManager::get()->renderSphere(1.0f, 100, 50, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)); //Draw a unit sphere glDepthMask(GL_TRUE); diff --git a/libraries/gpu/src/gpu/GLBackendPipeline.cpp b/libraries/gpu/src/gpu/GLBackendPipeline.cpp index 6a66f9aa99..8922d53a6f 100755 --- a/libraries/gpu/src/gpu/GLBackendPipeline.cpp +++ b/libraries/gpu/src/gpu/GLBackendPipeline.cpp @@ -108,6 +108,7 @@ void GLBackend::do_setPipeline(Batch& batch, uint32 paramOffset) { } } +#define DEBUG_GLSTATE void GLBackend::updatePipeline() { #ifdef DEBUG_GLSTATE if (_pipeline._needStateSync) { From 1a18719031a4f88725e71fd8114bd35670e8df8b Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 30 Mar 2015 21:53:59 -0700 Subject: [PATCH 13/21] and make it compile on mac... remove the field map from state just because it's unecessary --- libraries/gpu/src/gpu/GLBackend.h | 54 +- libraries/gpu/src/gpu/GLBackendState.cpp | 549 +++++++++++-------- libraries/gpu/src/gpu/State.h | 669 +++++++++++++---------- libraries/render-utils/src/Model.cpp | 10 +- libraries/render-utils/src/Model.h | 4 +- 5 files changed, 724 insertions(+), 562 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 5f6ae3957d..842b92efda 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -86,7 +86,7 @@ public: template 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 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 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); diff --git a/libraries/gpu/src/gpu/GLBackendState.cpp b/libraries/gpu/src/gpu/GLBackendState.cpp index d06ba06d63..acc64de8b4 100644 --- a/libraries/gpu/src/gpu/GLBackendState.cpp +++ b/libraries/gpu/src/gpu/GLBackendState.cpp @@ -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 { diff --git a/libraries/gpu/src/gpu/State.h b/libraries/gpu/src/gpu/State.h index f3529da01e..61d5e0250c 100755 --- a/libraries/gpu/src/gpu/State.h +++ b/libraries/gpu/src/gpu/State.h @@ -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 -#include -#include - - -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 +#include +#include +#include + + +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(this)); } - DepthTest(int32 raw) { *(reinterpret_cast(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(this)); } + DepthTest(int32 raw) { *(reinterpret_cast(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(this)); } - StencilTest(int32 raw) { *(reinterpret_cast(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(this)); } - StencilActivation(int32 raw) { *(reinterpret_cast(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(this)); } + StencilTest(int32 raw) { *(reinterpret_cast(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(this)); } + StencilActivation(int32 raw) { *(reinterpret_cast(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(this)); } - BlendFunction(int32 raw) { *(reinterpret_cast(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(this)); } + BlendFunction(int32 raw) { *(reinterpret_cast(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(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(COLOR_WRITE_MASK, DEFAULT.colorWriteMask, mask); } - uint32 getColorWriteMask() const { return get(COLOR_WRITE_MASK, DEFAULT.colorWriteMask); } - - // The state values are stored in a Map called FieldMap - // only the fields with non default value are saved - - // All the possible fields - enum Field { - FILL_MODE, - CULL_MODE, - FRONT_FACE_CLOCKWISE, - DEPTH_CLIP_ENABLE, - SCISSOR_ENABLE, - MULTISAMPLE_ENABLE, - ANTIALISED_LINE_ENABLE, - - DEPTH_BIAS, - DEPTH_BIAS_SLOPE_SCALE, - - DEPTH_TEST, - - STENCIL_ACTIVATION, - STENCIL_TEST_FRONT, - STENCIL_TEST_BACK, - - SAMPLE_MASK, - ALPHA_TO_COVERAGE_ENABLE, - - BLEND_FUNCTION, - - COLOR_WRITE_MASK, - - NUM_FIELDS, // not a valid field, just the count - }; - - // the value of a field - class Value { - public: - union { - uint32 _unsigned_integer = 0; - int32 _integer; - float _float; - }; - - template void uncast(T v) { _integer = v; } - template <> void State::Value::uncast(int v) { _integer = v; } - template <> void State::Value::uncast(float v) { _float = v; } - template <> void State::Value::uncast(unsigned int v) { _unsigned_integer = v; } - template <> void State::Value::uncast(DepthTest v) { _integer = v.getRaw(); } - template <> void State::Value::uncast(StencilActivation v) { _integer = v.getRaw(); } - template <> void State::Value::uncast(StencilTest v) { _integer = v.getRaw(); } - template <> void State::Value::uncast(BlendFunction v) { _integer = v.getRaw(); } - - template T cast() const; - template <> int State::Value::cast() const { return _integer; } - template <> float State::Value::cast() const { return _float; } - template <> unsigned int State::Value::cast() const { return _unsigned_integer; } - template <> DepthTest State::Value::cast() const { return DepthTest(_integer); } - template <> StencilActivation State::Value::cast() const { return StencilActivation(_integer); } - template <> StencilTest State::Value::cast() const { return StencilTest(_integer); } - template <> BlendFunction State::Value::cast() const { return BlendFunction(_integer); } - }; - - // The field map type - typedef std::unordered_map FieldMap; - - const FieldMap& getFields() const { return _fields; } - - // The signature of the state tells which fields of the state are not default - // this way during rendering the Backend can compare it's current state and try to minimize the job to do - typedef std::bitset Signature; - - Signature getSignature() const { return _signature; } - - static Signature evalSignature(const Cache& state); - -protected: - State(const State& state); - State& operator=(const State& state); - - template void set(Field field, T defaultValue, T value) { - if (value == defaultValue) { - _fields.erase(field); - _signature.reset(field); - } else { - _fields[field].uncast(value); - _signature.set(field); - } - _stamp++; - } - - template T get(Field field, T defaultValue) const { - auto found = _fields.find(field); - if (found != _fields.end()) { - return (*found).second.cast(); - } - 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(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 void uncast(T v) { _integer = v; } + + template T cast() const { return T(_integer); } + }; + + // The field map type + typedef std::unordered_map 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 Signature; + + Signature getSignature() const { return _signature; } + + static Signature evalSignature(const Cache& state); + +protected: + State(const State& state); + State& operator=(const State& state); + + template 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 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 T get(Field field, T defaultValue) const { + auto found = _fields.find(field); + if (found != _fields.end()) { + return (*found).second.cast(); + } + 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 v) { _integer = v; } + template <> void State::Value::uncast(float v) { _float = v; } + template <> void State::Value::uncast(unsigned int v) { _unsigned_integer = v; } + template <> void State::Value::uncast(State::DepthTest v) { _integer = v.getRaw(); } + template <> void State::Value::uncast(State::StencilActivation v) { _integer = v.getRaw(); } + template <> void State::Value::uncast(State::StencilTest v) { _integer = v.getRaw(); } + template <> void State::Value::uncast(State::BlendFunction v) { _integer = v.getRaw(); } + + template <> int State::Value::cast() const { return _integer; } + template <> float State::Value::cast() const { return _float; } + template <> unsigned int State::Value::cast() const { return _unsigned_integer; } + template <> State::DepthTest State::Value::cast() const { return DepthTest(_integer); } + template <> State::StencilActivation State::Value::cast() const { return StencilActivation(_integer); } + template <> State::StencilTest State::Value::cast() const { return StencilTest(_integer); } + template <> State::BlendFunction State::Value::cast() const { return BlendFunction(_integer); } + +typedef std::shared_ptr< State > StatePointer; typedef std::vector< StatePointer > States; - -}; - - -#endif + +}; + + +#endif diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 9a94716637..4c5f0ba4cf 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -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) - ))); + auto pipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, state)); + auto it = insert(value_type(key.getRaw(), RenderPipeline(pipeline, std::shared_ptr(locations)))); } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index f771bffbd8..07c5890aa3 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -505,7 +505,7 @@ private: public: gpu::PipelinePointer _pipeline; std::shared_ptr _locations; - RenderPipeline(gpu::PipelinePointer& pipeline, std::shared_ptr& locations) : + RenderPipeline(gpu::PipelinePointer pipeline, std::shared_ptr 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); }; From d4dac0477b6cc72ed4ed487a30090cf2e2988bb2 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 31 Mar 2015 09:47:56 -0700 Subject: [PATCH 14/21] changed again the state field storage for hopefully the better by using the Cache class and compressing it --- libraries/gpu/src/gpu/State.h | 230 ++++++++-------------------------- 1 file changed, 52 insertions(+), 178 deletions(-) diff --git a/libraries/gpu/src/gpu/State.h b/libraries/gpu/src/gpu/State.h index 61d5e0250c..3e9324d482 100755 --- a/libraries/gpu/src/gpu/State.h +++ b/libraries/gpu/src/gpu/State.h @@ -17,7 +17,17 @@ #include #include #include - + +#define SET_FIELD(field, defaultValue, value, dest) {\ + dest = value;\ + if (value == defaultValue) {\ + _signature.reset(field);\ + } else {\ + _signature.set(field);\ + }\ + _stamp++;\ +}\ + namespace gpu { @@ -227,14 +237,6 @@ public: // 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; @@ -245,45 +247,63 @@ public: 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; + uint8 fillMode = FILL_FACE; + uint8 cullMode = CULL_NONE; + + uint8 colorWriteMask = WRITE_ALL; + + bool frontFaceClockwise : 1; + bool depthClipEnable : 1; + bool scissorEnable : 1; + bool multisampleEnable : 1; + bool antialisedLineEnable : 1; + bool alphaToCoverageEnable : 1; + + Cache() : + frontFaceClockwise(false), + depthClipEnable(false), + scissorEnable(false), + multisampleEnable(false), + antialisedLineEnable(false), + alphaToCoverageEnable(false) + {} }; // 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 setFillMode(FillMode fill) { SET_FIELD(FILL_MODE, DEFAULT.fillMode, fill, _values.fillMode); } + FillMode getFillMode() const { return FillMode(_values.fillMode); } - void setCullMode(CullMode cull) { set(CULL_MODE, DEFAULT.cullMode, cull, _values.cullMode); } - CullMode getCullMode() const { return _values.cullMode; } + void setCullMode(CullMode cull) { SET_FIELD(CULL_MODE, DEFAULT.cullMode, cull, _values.cullMode); } + CullMode getCullMode() const { return CullMode(_values.cullMode); } - void setFrontFaceClockwise(bool isClockwise) { set(FRONT_FACE_CLOCKWISE, DEFAULT.frontFaceClockwise, isClockwise, _values.frontFaceClockwise); } + void setFrontFaceClockwise(bool isClockwise) { SET_FIELD(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); } + void setDepthClipEnable(bool enable) { SET_FIELD(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); } + void setScissorEnable(bool enable) { SET_FIELD(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); } + void setMultisampleEnable(bool enable) { SET_FIELD(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); } + void setAntialiasedLineEnable(bool enable) { SET_FIELD(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); } + void setDepthBias(float bias) { SET_FIELD(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); } + void setDepthBiasSlopeScale(float scale) { SET_FIELD(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(DepthTest depthTest) { SET_FIELD(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; } @@ -293,9 +313,9 @@ public: // 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); } + SET_FIELD(STENCIL_ACTIVATION, DEFAULT.stencilActivation, StencilActivation(enabled, frontWriteMask, backWriteMask), _values.stencilActivation); + SET_FIELD(STENCIL_TEST_FRONT, DEFAULT.stencilTestFront, frontTest, _values.stencilTestFront); + SET_FIELD(STENCIL_TEST_BACK, DEFAULT.stencilTestBack, backTest, _values.stencilTestBack); } void setStencilTest(bool enabled, uint8 frontWriteMask, StencilTest frontTest) { setStencilTest(enabled, frontWriteMask, frontTest, frontWriteMask, frontTest); } @@ -308,15 +328,15 @@ public: uint8 getStencilWriteMaskBack() const { return getStencilActivation().getWriteMaskBack(); } // Alpha to coverage - void setAlphaToCoverageEnable(bool enable) { set(ALPHA_TO_COVERAGE_ENABLE, DEFAULT.alphaToCoverageEnable, enable, _values.alphaToCoverageEnable); } + void setAlphaToCoverageEnable(bool enable) { SET_FIELD(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); } + void setSampleMask(uint32 mask) { SET_FIELD(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); } + void setBlendFunction(BlendFunction function) { SET_FIELD(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) { @@ -327,87 +347,8 @@ public: bool isBlendEnabled() const { return getBlendFunction().isEnabled(); } // Color write mask - void setColorWriteMask(int32 mask) { set(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); } - - void setFrontFaceClockwise(bool isClockwise) { set(FRONT_FACE_CLOCKWISE, DEFAULT.frontFaceClockwise, isClockwise); } - bool isFrontFaceClockwise() const { return get(FRONT_FACE_CLOCKWISE, DEFAULT.frontFaceClockwise); } - - void setDepthClipEnable(bool enable) { set(DEPTH_CLIP_ENABLE, DEFAULT.depthClipEnable, enable); } - bool isDepthClipEnable() const { return get(DEPTH_CLIP_ENABLE, DEFAULT.depthClipEnable); } - - void setScissorEnable(bool enable) { set(SCISSOR_ENABLE, DEFAULT.scissorEnable, enable); } - bool isScissorEnable() const { return get(SCISSOR_ENABLE, DEFAULT.scissorEnable); } - - void setMultisampleEnable(bool enable) { set(MULTISAMPLE_ENABLE, DEFAULT.multisampleEnable, enable); } - bool isMultisampleEnable() const { return get(MULTISAMPLE_ENABLE, DEFAULT.multisampleEnable); } - - void setAntialiasedLineEnable(bool enable) { set(ANTIALISED_LINE_ENABLE, DEFAULT.antialisedLineEnable, enable); } - bool isAntialiasedLineEnable() const { return get(ANTIALISED_LINE_ENABLE, DEFAULT.antialisedLineEnable); } - - // Depth Bias - void setDepthBias(float bias) { set(DEPTH_BIAS, DEFAULT.depthBias, bias); } - float getDepthBias() const { return get(DEPTH_BIAS, DEFAULT.depthBias); } - - void setDepthBiasSlopeScale(float scale) { set(DEPTH_BIAS_SLOPE_SCALE, DEFAULT.depthBiasSlopeScale, scale); } - float getDepthBiasSlopeScale() const { return get(DEPTH_BIAS_SLOPE_SCALE, DEFAULT.depthBiasSlopeScale); } - - // Depth Test - void setDepthTest(DepthTest depthTest) { set(DEPTH_TEST, DEFAULT.depthTest, depthTest); } - void setDepthTest(bool enable, bool writeMask, ComparisonFunction func) { setDepthTest(DepthTest(enable, writeMask, func)); } - DepthTest getDepthTest() const { return get(DEPTH_TEST, DEFAULT.depthTest); } - - bool isDepthTestEnabled() const { return getDepthTest().isEnabled(); } - bool getDepthTestWriteMask() const { return getDepthTest().getWriteMask(); } - ComparisonFunction getDepthTestFunc() const { return getDepthTest().getFunction(); } - - // Stencil test - void setStencilTest(bool enabled, uint8 frontWriteMask, StencilTest frontTest, uint8 backWriteMask, StencilTest backTest) { - set(STENCIL_ACTIVATION, DEFAULT.stencilActivation, StencilActivation(enabled, frontWriteMask, backWriteMask)); - set(STENCIL_TEST_FRONT, DEFAULT.stencilTestFront, frontTest); - set(STENCIL_TEST_BACK, DEFAULT.stencilTestBack, backTest); } - void setStencilTest(bool enabled, uint8 frontWriteMask, StencilTest frontTest) { - setStencilTest(enabled, frontWriteMask, frontTest, frontWriteMask, frontTest); } - - StencilActivation getStencilActivation() const { return get(STENCIL_ACTIVATION, DEFAULT.stencilActivation); } - StencilTest getStencilTestFront() const { return get(STENCIL_TEST_FRONT, DEFAULT.stencilTestFront); } - StencilTest getStencilTestBack() const { return get(STENCIL_TEST_BACK, DEFAULT.stencilTestBack); } - - bool isStencilEnabled() const { return getStencilActivation().isEnabled(); } - uint8 getStencilWriteMaskFront() const { return getStencilActivation().getWriteMaskFront(); } - uint8 getStencilWriteMaskBack() const { return getStencilActivation().getWriteMaskBack(); } - - // Alpha to coverage - void setAlphaToCoverageEnable(bool enable) { set(ALPHA_TO_COVERAGE_ENABLE, DEFAULT.alphaToCoverageEnable, enable); } - bool isAlphaToCoverageEnabled() const { return get(ALPHA_TO_COVERAGE_ENABLE, DEFAULT.alphaToCoverageEnable); } - - // Sample mask - void setSampleMask(uint32 mask) { set(SAMPLE_MASK, DEFAULT.sampleMask, mask); } - uint32 getSampleMask() const { return get(SAMPLE_MASK, DEFAULT.sampleMask); } - - // Blend Function - void setBlendFunction(BlendFunction function) { set(BLEND_FUNCTION, DEFAULT.blendFunction, function); } - BlendFunction getBlendFunction() const { return get(BLEND_FUNCTION, DEFAULT.blendFunction); } - - void setBlendFunction(bool enabled, BlendArg sourceColor, BlendOp operationColor, BlendArg destinationColor, BlendArg sourceAlpha, BlendOp operationAlpha, BlendArg destinationAlpha) { - setBlendFunction(BlendFunction(enabled, sourceColor, operationColor, destinationColor, sourceAlpha, operationAlpha, destinationAlpha)); } - void setBlendFunction(bool enabled, BlendArg source, BlendOp operation, BlendArg destination) { - setBlendFunction(BlendFunction(enabled, source, operation, destination)); } - - bool isBlendEnabled() const { return getBlendFunction().isEnabled(); } - - // Color write mask - void setColorWriteMask(int32 mask) { set(COLOR_WRITE_MASK, DEFAULT.colorWriteMask, mask); } - uint32 getColorWriteMask() const { return get(COLOR_WRITE_MASK, DEFAULT.colorWriteMask); } -*/ - // The state values are stored in a Map called FieldMap - // only the fields with non default value are saved + void setColorWriteMask(uint8 mask) { SET_FIELD(COLOR_WRITE_MASK, DEFAULT.colorWriteMask, mask, _values.colorWriteMask); } + uint8 getColorWriteMask() const { return _values.colorWriteMask; } // All the possible fields enum Field { @@ -438,25 +379,6 @@ public: 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 void uncast(T v) { _integer = v; } - - template T cast() const { return T(_integer); } - }; - - // The field map type - typedef std::unordered_map 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 Signature; @@ -468,39 +390,7 @@ public: protected: State(const State& state); State& operator=(const State& state); - - template 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 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 T get(Field field, T defaultValue) const { - auto found = _fields.find(field); - if (found != _fields.end()) { - return (*found).second.cast(); - } - return defaultValue; - } - - FieldMap _fields; + Cache _values; Signature _signature{0}; Stamp _stamp{0}; @@ -512,22 +402,6 @@ protected: friend class Backend; }; - template <> void State::Value::uncast(int v) { _integer = v; } - template <> void State::Value::uncast(float v) { _float = v; } - template <> void State::Value::uncast(unsigned int v) { _unsigned_integer = v; } - template <> void State::Value::uncast(State::DepthTest v) { _integer = v.getRaw(); } - template <> void State::Value::uncast(State::StencilActivation v) { _integer = v.getRaw(); } - template <> void State::Value::uncast(State::StencilTest v) { _integer = v.getRaw(); } - template <> void State::Value::uncast(State::BlendFunction v) { _integer = v.getRaw(); } - - template <> int State::Value::cast() const { return _integer; } - template <> float State::Value::cast() const { return _float; } - template <> unsigned int State::Value::cast() const { return _unsigned_integer; } - template <> State::DepthTest State::Value::cast() const { return DepthTest(_integer); } - template <> State::StencilActivation State::Value::cast() const { return StencilActivation(_integer); } - template <> State::StencilTest State::Value::cast() const { return StencilTest(_integer); } - template <> State::BlendFunction State::Value::cast() const { return BlendFunction(_integer); } - typedef std::shared_ptr< State > StatePointer; typedef std::vector< StatePointer > States; From 9b63739a721cd01c5e8b11eac7dfad4b01ed51ca Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 31 Mar 2015 17:35:34 -0700 Subject: [PATCH 15/21] Trying to clen up the REnderMode usage in connection with the needed gpu::State for all the different variations --- interface/src/Application.cpp | 6 +- interface/src/avatar/Avatar.cpp | 29 ++-- interface/src/avatar/Avatar.h | 12 +- interface/src/avatar/AvatarManager.cpp | 6 +- interface/src/avatar/AvatarManager.h | 4 +- interface/src/avatar/Hand.cpp | 4 +- interface/src/avatar/Hand.h | 2 +- interface/src/avatar/MyAvatar.cpp | 19 ++- interface/src/avatar/MyAvatar.h | 8 +- interface/src/ui/overlays/ModelOverlay.cpp | 2 +- .../src/EntityTreeRenderer.cpp | 2 +- libraries/gpu/src/gpu/GLBackend.h | 4 +- libraries/gpu/src/gpu/GLBackendPipeline.cpp | 2 +- libraries/gpu/src/gpu/GLBackendState.cpp | 4 +- libraries/gpu/src/gpu/State.cpp | 9 +- libraries/gpu/src/gpu/State.h | 21 ++- .../render-utils/src/DeferredBufferWrite.slh | 11 ++ libraries/render-utils/src/Model.cpp | 129 +++++++++++------- libraries/render-utils/src/Model.h | 43 +++--- libraries/shared/src/RenderArgs.h | 2 +- 20 files changed, 190 insertions(+), 129 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 97d132508a..effc395ed2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2705,7 +2705,7 @@ void Application::updateShadowMap() { { PerformanceTimer perfTimer("avatarManager"); - DependencyManager::get()->renderAvatars(Avatar::SHADOW_RENDER_MODE); + DependencyManager::get()->renderAvatars(RenderArgs::SHADOW_RENDER_MODE); } { @@ -2975,7 +2975,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs bool mirrorMode = (theCamera.getMode() == CAMERA_MODE_MIRROR); { PerformanceTimer perfTimer("avatars"); - DependencyManager::get()->renderAvatars(mirrorMode ? Avatar::MIRROR_RENDER_MODE : Avatar::NORMAL_RENDER_MODE, + DependencyManager::get()->renderAvatars(mirrorMode ? RenderArgs::MIRROR_RENDER_MODE : RenderArgs::NORMAL_RENDER_MODE, false, selfAvatarOnly); } @@ -2993,7 +2993,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs { PerformanceTimer perfTimer("avatarsPostLighting"); - DependencyManager::get()->renderAvatars(mirrorMode ? Avatar::MIRROR_RENDER_MODE : Avatar::NORMAL_RENDER_MODE, + DependencyManager::get()->renderAvatars(mirrorMode ? RenderArgs::MIRROR_RENDER_MODE : RenderArgs::NORMAL_RENDER_MODE, true, selfAvatarOnly); } diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 431b6e0d37..4882316157 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -267,7 +267,7 @@ static TextRenderer* textRenderer(TextRendererType type) { return displayNameRenderer; } -void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode, bool postLighting) { +void Avatar::render(const glm::vec3& cameraPosition, RenderArgs::RenderMode renderMode, bool postLighting) { if (_referential) { _referential->update(); } @@ -337,7 +337,7 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode, bool // simple frustum check float boundingRadius = getBillboardSize(); - ViewFrustum* frustum = (renderMode == Avatar::SHADOW_RENDER_MODE) ? + ViewFrustum* frustum = (renderMode == RenderArgs::SHADOW_RENDER_MODE) ? Application::getInstance()->getShadowViewFrustum() : Application::getInstance()->getDisplayViewFrustum(); if (frustum->sphereInFrustum(getPosition(), boundingRadius) == ViewFrustum::OUTSIDE) { return; @@ -359,7 +359,7 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode, bool GLOW_FROM_AVERAGE_LOUDNESS = 0.0f; } - float glowLevel = _moving && distanceToTarget > GLOW_DISTANCE && renderMode == NORMAL_RENDER_MODE + float glowLevel = _moving && distanceToTarget > GLOW_DISTANCE && renderMode == RenderArgs::NORMAL_RENDER_MODE ? 1.0f : GLOW_FROM_AVERAGE_LOUDNESS; @@ -368,7 +368,7 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode, bool renderBody(frustum, renderMode, postLighting, glowLevel); } - if (!postLighting && renderMode != SHADOW_RENDER_MODE) { + if (!postLighting && renderMode != RenderArgs::SHADOW_RENDER_MODE) { // add local lights const float BASE_LIGHT_DISTANCE = 2.0f; const float LIGHT_EXPONENT = 1.0f; @@ -432,7 +432,7 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode, bool float angle = abs(angleBetween(toTarget + delta, toTarget - delta)); float sphereRadius = getHead()->getAverageLoudness() * SPHERE_LOUDNESS_SCALING; - if (renderMode == NORMAL_RENDER_MODE && (sphereRadius > MIN_SPHERE_SIZE) && + if (renderMode == RenderArgs::NORMAL_RENDER_MODE && (sphereRadius > MIN_SPHERE_SIZE) && (angle < MAX_SPHERE_ANGLE) && (angle > MIN_SPHERE_ANGLE)) { glPushMatrix(); glTranslatef(_position.x, _position.y, _position.z); @@ -451,8 +451,8 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode, bool } const float DISPLAYNAME_DISTANCE = 20.0f; - setShowDisplayName(renderMode == NORMAL_RENDER_MODE && distanceToTarget < DISPLAYNAME_DISTANCE); - if (!postLighting || renderMode != NORMAL_RENDER_MODE || (isMyAvatar() && + setShowDisplayName(renderMode == RenderArgs::NORMAL_RENDER_MODE && distanceToTarget < DISPLAYNAME_DISTANCE); + if (!postLighting || renderMode != RenderArgs::NORMAL_RENDER_MODE || (isMyAvatar() && Application::getInstance()->getCamera()->getMode() == CAMERA_MODE_FIRST_PERSON)) { return; } @@ -475,14 +475,13 @@ glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const { return glm::angleAxis(angle * proportion, axis); } -void Avatar::renderBody(ViewFrustum* renderFrustum, RenderMode renderMode, bool postLighting, float glowLevel) { - Model::RenderMode modelRenderMode = (renderMode == SHADOW_RENDER_MODE) ? - Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE; +void Avatar::renderBody(ViewFrustum* renderFrustum, RenderArgs::RenderMode renderMode, bool postLighting, float glowLevel) { + Model::RenderMode modelRenderMode = renderMode; { Glower glower(glowLevel); if (_shouldRenderBillboard || !(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) { - if (postLighting || renderMode == SHADOW_RENDER_MODE) { + if (postLighting || renderMode == RenderArgs::SHADOW_RENDER_MODE) { // render the billboard until both models are loaded renderBillboard(); } @@ -501,7 +500,7 @@ void Avatar::renderBody(ViewFrustum* renderFrustum, RenderMode renderMode, bool getHead()->render(1.0f, renderFrustum, modelRenderMode, postLighting); } -bool Avatar::shouldRenderHead(const glm::vec3& cameraPosition, RenderMode renderMode) const { +bool Avatar::shouldRenderHead(const glm::vec3& cameraPosition, RenderArgs::RenderMode renderMode) const { return true; } @@ -525,9 +524,9 @@ void Avatar::simulateAttachments(float deltaTime) { } } -void Avatar::renderAttachments(RenderMode renderMode, RenderArgs* args) { - Model::RenderMode modelRenderMode = (renderMode == SHADOW_RENDER_MODE) ? - Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE; +void Avatar::renderAttachments(RenderArgs::RenderMode renderMode, RenderArgs* args) { + RenderArgs::RenderMode modelRenderMode = (renderMode == RenderArgs::SHADOW_RENDER_MODE) ? + RenderArgs::SHADOW_RENDER_MODE : RenderArgs::DEFAULT_RENDER_MODE; foreach (Model* model, _attachmentModels) { model->render(1.0f, modelRenderMode, args); } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 0cde800be0..032fe25c7d 100644 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -67,10 +67,8 @@ public: void init(); void simulate(float deltaTime); - - enum RenderMode { NORMAL_RENDER_MODE, SHADOW_RENDER_MODE, MIRROR_RENDER_MODE }; - - virtual void render(const glm::vec3& cameraPosition, RenderMode renderMode = NORMAL_RENDER_MODE, + + virtual void render(const glm::vec3& cameraPosition, RenderArgs::RenderMode renderMode = RenderArgs::NORMAL_RENDER_MODE, bool postLighting = false); //setters @@ -208,11 +206,11 @@ protected: float calculateDisplayNameScaleFactor(const glm::vec3& textPosition, bool inHMD); void renderDisplayName(); - virtual void renderBody(ViewFrustum* renderFrustum, RenderMode renderMode, bool postLighting, float glowLevel = 0.0f); - virtual bool shouldRenderHead(const glm::vec3& cameraPosition, RenderMode renderMode) const; + virtual void renderBody(ViewFrustum* renderFrustum, RenderArgs::RenderMode renderMode, bool postLighting, float glowLevel = 0.0f); + virtual bool shouldRenderHead(const glm::vec3& cameraPosition, RenderArgs::RenderMode renderMode) const; void simulateAttachments(float deltaTime); - virtual void renderAttachments(RenderMode renderMode, RenderArgs* args); + virtual void renderAttachments(RenderArgs::RenderMode renderMode, RenderArgs* args); virtual void updateJointMappings(); diff --git a/interface/src/avatar/AvatarManager.cpp b/interface/src/avatar/AvatarManager.cpp index 0ffcf19bf9..1764183807 100644 --- a/interface/src/avatar/AvatarManager.cpp +++ b/interface/src/avatar/AvatarManager.cpp @@ -114,7 +114,7 @@ void AvatarManager::updateOtherAvatars(float deltaTime) { simulateAvatarFades(deltaTime); } -void AvatarManager::renderAvatars(Avatar::RenderMode renderMode, bool postLighting, bool selfAvatarOnly) { +void AvatarManager::renderAvatars(RenderArgs::RenderMode renderMode, bool postLighting, bool selfAvatarOnly) { PerformanceWarning warn(Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings), "Application::renderAvatars()"); bool renderLookAtVectors = Menu::getInstance()->isOptionChecked(MenuOption::RenderLookAtVectors); @@ -156,9 +156,9 @@ void AvatarManager::simulateAvatarFades(float deltaTime) { } } -void AvatarManager::renderAvatarFades(const glm::vec3& cameraPosition, Avatar::RenderMode renderMode) { +void AvatarManager::renderAvatarFades(const glm::vec3& cameraPosition, RenderArgs::RenderMode renderMode) { // render avatar fades - Glower glower(renderMode == Avatar::NORMAL_RENDER_MODE ? 1.0f : 0.0f); + Glower glower(renderMode == RenderArgs::NORMAL_RENDER_MODE ? 1.0f : 0.0f); foreach(const AvatarSharedPointer& fadingAvatar, _avatarFades) { Avatar* avatar = static_cast(fadingAvatar.data()); diff --git a/interface/src/avatar/AvatarManager.h b/interface/src/avatar/AvatarManager.h index ae6fbe5fc2..4912fabd33 100644 --- a/interface/src/avatar/AvatarManager.h +++ b/interface/src/avatar/AvatarManager.h @@ -37,7 +37,7 @@ public: void updateMyAvatar(float deltaTime); void updateOtherAvatars(float deltaTime); - void renderAvatars(Avatar::RenderMode renderMode, bool postLighting = false, bool selfAvatarOnly = false); + void renderAvatars(RenderArgs::RenderMode renderMode, bool postLighting = false, bool selfAvatarOnly = false); void clearOtherAvatars(); @@ -55,7 +55,7 @@ private: AvatarManager(const AvatarManager& other); void simulateAvatarFades(float deltaTime); - void renderAvatarFades(const glm::vec3& cameraPosition, Avatar::RenderMode renderMode); + void renderAvatarFades(const glm::vec3& cameraPosition, RenderArgs::RenderMode renderMode); AvatarSharedPointer newSharedAvatar(); diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index b51264b955..e67ed15b67 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -103,7 +103,7 @@ void Hand::resolvePenetrations() { } void Hand::render(bool isMine, Model::RenderMode renderMode) { - if (renderMode != Model::SHADOW_RENDER_MODE && + if (renderMode != RenderArgs::SHADOW_RENDER_MODE && Menu::getInstance()->isOptionChecked(MenuOption::RenderSkeletonCollisionShapes)) { // draw a green sphere at hand joint location, which is actually near the wrist) for (size_t i = 0; i < getNumPalms(); i++) { @@ -119,7 +119,7 @@ void Hand::render(bool isMine, Model::RenderMode renderMode) { } } - if (renderMode != Model::SHADOW_RENDER_MODE && Menu::getInstance()->isOptionChecked(MenuOption::DisplayHands)) { + if (renderMode != RenderArgs::SHADOW_RENDER_MODE && Menu::getInstance()->isOptionChecked(MenuOption::DisplayHands)) { renderHandTargets(isMine); } diff --git a/interface/src/avatar/Hand.h b/interface/src/avatar/Hand.h index 688af151b4..e19f5674b4 100644 --- a/interface/src/avatar/Hand.h +++ b/interface/src/avatar/Hand.h @@ -52,7 +52,7 @@ public: }; void simulate(float deltaTime, bool isMine); - void render(bool isMine, Model::RenderMode renderMode = Model::DEFAULT_RENDER_MODE); + void render(bool isMine, Model::RenderMode renderMode = RenderArgs::DEFAULT_RENDER_MODE); void collideAgainstAvatar(Avatar* avatar, bool isMyHand); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 26b777b35b..9f542da19a 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -326,7 +326,7 @@ void MyAvatar::renderDebugBodyPoints() { } // virtual -void MyAvatar::render(const glm::vec3& cameraPosition, RenderMode renderMode, bool postLighting) { +void MyAvatar::render(const glm::vec3& cameraPosition, RenderArgs::RenderMode renderMode, bool postLighting) { // don't render if we've been asked to disable local rendering if (!_shouldRender) { return; // exit early @@ -997,7 +997,7 @@ void MyAvatar::attach(const QString& modelURL, const QString& jointName, const g Avatar::attach(modelURL, jointName, translation, rotation, scale, allowDuplicates, useSaved); } -void MyAvatar::renderBody(ViewFrustum* renderFrustum, RenderMode renderMode, bool postLighting, float glowLevel) { +void MyAvatar::renderBody(ViewFrustum* renderFrustum, RenderArgs::RenderMode renderMode, bool postLighting, float glowLevel) { if (!(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) { return; // wait until both models are loaded } @@ -1024,8 +1024,7 @@ void MyAvatar::renderBody(ViewFrustum* renderFrustum, RenderMode renderMode, boo } // Render the body's voxels and head - Model::RenderMode modelRenderMode = (renderMode == SHADOW_RENDER_MODE) ? - Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE; + RenderArgs::RenderMode modelRenderMode = renderMode; if (!postLighting) { RenderArgs args; args._viewFrustum = renderFrustum; @@ -1044,9 +1043,9 @@ void MyAvatar::renderBody(ViewFrustum* renderFrustum, RenderMode renderMode, boo const float RENDER_HEAD_CUTOFF_DISTANCE = 0.50f; -bool MyAvatar::shouldRenderHead(const glm::vec3& cameraPosition, RenderMode renderMode) const { +bool MyAvatar::shouldRenderHead(const glm::vec3& cameraPosition, RenderArgs::RenderMode renderMode) const { const Head* head = getHead(); - return (renderMode != NORMAL_RENDER_MODE) || (Application::getInstance()->getCamera()->getMode() != CAMERA_MODE_FIRST_PERSON) || + return (renderMode != RenderArgs::NORMAL_RENDER_MODE) || (Application::getInstance()->getCamera()->getMode() != CAMERA_MODE_FIRST_PERSON) || (glm::length(cameraPosition - head->getEyePosition()) > RENDER_HEAD_CUTOFF_DISTANCE * _scale); } @@ -1392,15 +1391,15 @@ void MyAvatar::updateMotionBehavior() { _feetTouchFloor = menu->isOptionChecked(MenuOption::ShiftHipsForIdleAnimations); } -void MyAvatar::renderAttachments(RenderMode renderMode, RenderArgs* args) { - if (Application::getInstance()->getCamera()->getMode() != CAMERA_MODE_FIRST_PERSON || renderMode == MIRROR_RENDER_MODE) { +void MyAvatar::renderAttachments(RenderArgs::RenderMode renderMode, RenderArgs* args) { + if (Application::getInstance()->getCamera()->getMode() != CAMERA_MODE_FIRST_PERSON || renderMode == RenderArgs::MIRROR_RENDER_MODE) { Avatar::renderAttachments(renderMode, args); return; } const FBXGeometry& geometry = _skeletonModel.getGeometry()->getFBXGeometry(); QString headJointName = (geometry.headJointIndex == -1) ? QString() : geometry.joints.at(geometry.headJointIndex).name; - Model::RenderMode modelRenderMode = (renderMode == SHADOW_RENDER_MODE) ? - Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE; + RenderArgs::RenderMode modelRenderMode = (renderMode == RenderArgs::SHADOW_RENDER_MODE) ? + RenderArgs::SHADOW_RENDER_MODE : RenderArgs::DEFAULT_RENDER_MODE; for (int i = 0; i < _attachmentData.size(); i++) { const QString& jointName = _attachmentData.at(i).jointName; if (jointName != headJointName && jointName != "Head") { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 99c0bdb5df..17471d5827 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -37,9 +37,9 @@ public: void simulate(float deltaTime); void updateFromTrackers(float deltaTime); - void render(const glm::vec3& cameraPosition, RenderMode renderMode = NORMAL_RENDER_MODE, bool postLighting = false); - void renderBody(ViewFrustum* renderFrustum, RenderMode renderMode, bool postLighting, float glowLevel = 0.0f); - bool shouldRenderHead(const glm::vec3& cameraPosition, RenderMode renderMode) const; + void render(const glm::vec3& cameraPosition, RenderArgs::RenderMode renderMode = RenderArgs::NORMAL_RENDER_MODE, bool postLighting = false); + void renderBody(ViewFrustum* renderFrustum, RenderArgs::RenderMode renderMode, bool postLighting, float glowLevel = 0.0f); + bool shouldRenderHead(const glm::vec3& cameraPosition, RenderArgs::RenderMode renderMode) const; void renderDebugBodyPoints(); // setters @@ -181,7 +181,7 @@ signals: void transformChanged(); protected: - virtual void renderAttachments(RenderMode renderMode, RenderArgs* args); + virtual void renderAttachments(RenderArgs::RenderMode renderMode, RenderArgs* args); private: float _turningKeyPressTime; diff --git a/interface/src/ui/overlays/ModelOverlay.cpp b/interface/src/ui/overlays/ModelOverlay.cpp index 58d42598f2..29d7c20f09 100644 --- a/interface/src/ui/overlays/ModelOverlay.cpp +++ b/interface/src/ui/overlays/ModelOverlay.cpp @@ -68,7 +68,7 @@ void ModelOverlay::render(RenderArgs* args) { if (glowLevel > 0.0f) { glower = new Glower(glowLevel); } - _model.render(getAlpha(), Model::DEFAULT_RENDER_MODE, args); + _model.render(getAlpha(), RenderArgs::DEFAULT_RENDER_MODE, args); if (glower) { delete glower; } diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 3faa06fc53..a4a5572670 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -364,7 +364,7 @@ void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode, RenderArgs::R _tree->recurseTreeWithOperation(renderOperation, &args); Model::RenderMode modelRenderMode = renderMode == RenderArgs::SHADOW_RENDER_MODE - ? Model::SHADOW_RENDER_MODE : Model::DEFAULT_RENDER_MODE; + ? RenderArgs::SHADOW_RENDER_MODE : RenderArgs::DEFAULT_RENDER_MODE; // we must call endScene while we still have the tree locked so that no one deletes a model // on us while rendering the scene diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index 842b92efda..71e44ddfda 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -263,7 +263,7 @@ protected: // 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); + void getCurrentGLState(State::Data& state); struct PipelineStageState { @@ -272,7 +272,7 @@ protected: GLuint _program; bool _invalidProgram; - State::Cache _stateCache; + State::Data _stateCache; State::Signature _stateSignatureCache; GLState* _state; diff --git a/libraries/gpu/src/gpu/GLBackendPipeline.cpp b/libraries/gpu/src/gpu/GLBackendPipeline.cpp index 8922d53a6f..0f7d3d6db8 100755 --- a/libraries/gpu/src/gpu/GLBackendPipeline.cpp +++ b/libraries/gpu/src/gpu/GLBackendPipeline.cpp @@ -112,7 +112,7 @@ void GLBackend::do_setPipeline(Batch& batch, uint32 paramOffset) { void GLBackend::updatePipeline() { #ifdef DEBUG_GLSTATE if (_pipeline._needStateSync) { - State::Cache state; + State::Data state; getCurrentGLState(state); State::Signature signature = State::evalSignature(state); } diff --git a/libraries/gpu/src/gpu/GLBackendState.cpp b/libraries/gpu/src/gpu/GLBackendState.cpp index acc64de8b4..1e2d842597 100644 --- a/libraries/gpu/src/gpu/GLBackendState.cpp +++ b/libraries/gpu/src/gpu/GLBackendState.cpp @@ -401,7 +401,7 @@ State::BlendArg blendArgFromGL(GLenum blendArg) { return State::ONE; } -void GLBackend::getCurrentGLState(State::Cache& state) { +void GLBackend::getCurrentGLState(State::Data& state) { { GLint modes[2]; glGetIntegerv(GL_POLYGON_MODE, modes); @@ -532,7 +532,7 @@ void GLBackend::getCurrentGLState(State::Cache& state) { } void GLBackend::syncPipelineStateCache() { - State::Cache state; + State::Data state; getCurrentGLState(state); State::Signature signature = State::evalSignature(state); diff --git a/libraries/gpu/src/gpu/State.cpp b/libraries/gpu/src/gpu/State.cpp index d2488aac17..76a444a2e6 100755 --- a/libraries/gpu/src/gpu/State.cpp +++ b/libraries/gpu/src/gpu/State.cpp @@ -20,9 +20,9 @@ State::State() { State::~State() { } -const State::Cache State::DEFAULT = State::Cache(); +const State::Data State::DEFAULT = State::Data(); -State::Signature State::evalSignature(const Cache& state) { +State::Signature State::evalSignature(const Data& state) { Signature signature(0); if (state.fillMode != State::DEFAULT.fillMode) { @@ -79,3 +79,8 @@ State::Signature State::evalSignature(const Cache& state) { return signature; } + +State::State(const Data& values) : + _values(values) { + _signature = evalSignature(_values); +} diff --git a/libraries/gpu/src/gpu/State.h b/libraries/gpu/src/gpu/State.h index 3e9324d482..56bc472cac 100755 --- a/libraries/gpu/src/gpu/State.h +++ b/libraries/gpu/src/gpu/State.h @@ -18,6 +18,9 @@ #include #include +// Why a macro and not a fancy template you will ask me ? +// Because some of the fields are bool packed tightly in the State::Cache class +// and it s just not good anymore for template T& variable manipulation... #define SET_FIELD(field, defaultValue, value, dest) {\ dest = value;\ if (value == defaultValue) {\ @@ -39,7 +42,7 @@ public: virtual ~State(); const Stamp getStamp() const { return _stamp; } - + enum ComparisonFunction { NEVER = 0, LESS, @@ -233,9 +236,9 @@ public: bool operator!= (const BlendFunction& right) const { return getRaw() != right.getRaw(); } }; - // The Cache class is the full explicit description of the State class fields value. + // The Data 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 { + class Data { public: float depthBias = 0.0f; float depthBiasSlopeScale = 0.0f; @@ -262,7 +265,7 @@ public: bool antialisedLineEnable : 1; bool alphaToCoverageEnable : 1; - Cache() : + Data() : frontFaceClockwise(false), depthClipEnable(false), scissorEnable(false), @@ -273,7 +276,7 @@ public: }; // The unique default values for all the fields - static const Cache DEFAULT; + static const Data DEFAULT; void setFillMode(FillMode fill) { SET_FIELD(FILL_MODE, DEFAULT.fillMode, fill, _values.fillMode); } FillMode getFillMode() const { return FillMode(_values.fillMode); } @@ -385,13 +388,17 @@ public: Signature getSignature() const { return _signature; } - static Signature evalSignature(const Cache& state); + static Signature evalSignature(const Data& state); + // For convenience, create a State from the values directly + State(const Data& values); + const Data& getValues() const { return _values; } + protected: State(const State& state); State& operator=(const State& state); - Cache _values; + Data _values; Signature _signature{0}; Stamp _stamp{0}; diff --git a/libraries/render-utils/src/DeferredBufferWrite.slh b/libraries/render-utils/src/DeferredBufferWrite.slh index 066e0198b1..a7f4055bba 100755 --- a/libraries/render-utils/src/DeferredBufferWrite.slh +++ b/libraries/render-utils/src/DeferredBufferWrite.slh @@ -22,12 +22,19 @@ float evalOpaqueFinalAlpha(float alpha, float mapAlpha) { } void packDeferredFragment(vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess) { + if (alpha != glowIntensity) { + discard; + } gl_FragData[0] = vec4(diffuse.rgb, alpha); gl_FragData[1] = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[2] = vec4(specular, shininess / 128.0); } void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess, vec3 emissive) { + if (alpha != glowIntensity) { + discard; + } + gl_FragData[0] = vec4(diffuse.rgb, alpha); //gl_FragData[1] = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); gl_FragData[1] = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 0.5); @@ -35,6 +42,10 @@ void packDeferredFragmentLightmap(vec3 normal, float alpha, vec3 diffuse, vec3 s } void packDeferredFragmentTranslucent(vec3 normal, float alpha, vec3 diffuse, vec3 specular, float shininess) { + if (alpha <= alphaThreshold) { + discard; + } + gl_FragData[0] = vec4(diffuse.rgb, alpha); // gl_FragData[1] = vec4(normal, 0.0) * 0.5 + vec4(0.5, 0.5, 0.5, 1.0); // gl_FragData[2] = vec4(specular, shininess / 128.0); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 4c5f0ba4cf..961a4c90a9 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -115,8 +115,9 @@ void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key, Locations* locations = new Locations(); initLocations(program, *locations); - gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + gpu::StatePointer state = gpu::StatePointer(new gpu::State()); + // Backface on shadow if (key.isShadow()) { state->setCullMode(gpu::State::CULL_FRONT); @@ -133,9 +134,23 @@ 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); + + // Good to go add the brand new pipeline auto pipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, state)); auto it = insert(value_type(key.getRaw(), RenderPipeline(pipeline, std::shared_ptr(locations)))); + // If not a shadow pass, create the mirror version from the same state, just change the FrontFace + if (!key.isShadow()) { + + RenderKey mirrorKey(key.getRaw() | RenderKey::IS_MIRROR); + gpu::StatePointer mirrorState = gpu::StatePointer(new gpu::State(state->getValues())); + + // mirrorState->setFrontFaceClockwise(true); + + // create a new RenderPipeline with the same shader side and the mirrorState + auto mirrorPipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, mirrorState)); + auto it = insert(value_type(mirrorKey.getRaw(), RenderPipeline(mirrorPipeline, std::shared_ptr(locations)))); + } } @@ -257,6 +272,7 @@ void Model::init() { auto modelLightmapNormalSpecularMapPixel = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(model_lightmap_normal_specular_map_frag))); // Fill the renderPipelineLib + _renderPipelineLib.addRenderPipeline( RenderKey(0), modelVertex, modelPixel); @@ -265,7 +281,7 @@ void Model::init() { RenderKey(RenderKey::HAS_TANGENTS), modelNormalMapVertex, modelNormalMapPixel); - _renderPipelineLib.addRenderPipeline( + _renderPipelineLib.addRenderPipeline( RenderKey(RenderKey::HAS_SPECULAR), modelVertex, modelSpecularMapPixel); @@ -276,15 +292,11 @@ void Model::init() { _renderPipelineLib.addRenderPipeline( RenderKey(RenderKey::IS_TRANSLUCENT), modelVertex, modelTranslucentPixel); - - _renderPipelineLib.addRenderPipeline( - RenderKey(RenderKey::IS_DEPTH_ONLY | RenderKey::IS_SHADOW), - modelShadowVertex, modelShadowPixel); _renderPipelineLib.addRenderPipeline( RenderKey(RenderKey::HAS_LIGHTMAP), modelLightmapVertex, modelLightmapPixel); - _renderPipelineLib.addRenderPipeline( + _renderPipelineLib.addRenderPipeline( RenderKey(RenderKey::HAS_LIGHTMAP | RenderKey::HAS_TANGENTS), modelLightmapNormalMapVertex, modelLightmapNormalMapPixel); @@ -312,13 +324,18 @@ void Model::init() { RenderKey(RenderKey::IS_SKINNED | RenderKey::HAS_TANGENTS | RenderKey::HAS_SPECULAR), skinModelNormalMapVertex, modelNormalSpecularMapPixel); - _renderPipelineLib.addRenderPipeline( - RenderKey(RenderKey::IS_SKINNED | RenderKey::IS_DEPTH_ONLY | RenderKey::IS_SHADOW), - skinModelShadowVertex, modelShadowPixel); - _renderPipelineLib.addRenderPipeline( RenderKey(RenderKey::IS_SKINNED | RenderKey::IS_TRANSLUCENT), skinModelVertex, modelTranslucentPixel); + + + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::IS_DEPTH_ONLY | RenderKey::IS_SHADOW), + modelShadowVertex, modelShadowPixel); + + _renderPipelineLib.addRenderPipeline( + RenderKey(RenderKey::IS_SKINNED | RenderKey::IS_DEPTH_ONLY | RenderKey::IS_SHADOW), + skinModelShadowVertex, modelShadowPixel); } } @@ -654,6 +671,8 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { return false; } + // auto glowEffectIntensity = DependencyManager::get()->getIntensity(); + // Let's introduce a gpu::Batch to capture all the calls to the graphics api _renderBatch.clear(); gpu::Batch& batch = _renderBatch; @@ -675,14 +694,14 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { batch.setViewTransform(_transforms[0]); - GLBATCH(glDisable)(GL_COLOR_MATERIAL); + // GLBATCH(glDisable)(GL_COLOR_MATERIAL); // taking care of by the state? - /* if (mode == DIFFUSE_RENDER_MODE || mode == NORMAL_RENDER_MODE) { + /* if (mode == RenderArgs::DIFFUSE_RENDER_MODE || mode == RenderArgs::NORMAL_RENDER_MODE) { GLBATCH(glDisable)(GL_CULL_FACE); } else { GLBATCH(glEnable)(GL_CULL_FACE); - if (mode == SHADOW_RENDER_MODE) { + if (mode == RenderArgs::SHADOW_RENDER_MODE) { GLBATCH(glCullFace)(GL_FRONT); } } @@ -691,28 +710,31 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { // render opaque meshes with alpha testing // GLBATCH(glDisable)(GL_BLEND); - GLBATCH(glEnable)(GL_ALPHA_TEST); +// GLBATCH(glEnable)(GL_ALPHA_TEST); - if (mode == SHADOW_RENDER_MODE) { + /* if (mode == RenderArgs::SHADOW_RENDER_MODE) { GLBATCH(glAlphaFunc)(GL_EQUAL, 0.0f); } - + */ /*DependencyManager::get()->setPrimaryDrawBuffers( - mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE, - mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE, - mode == DEFAULT_RENDER_MODE); + mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE, + mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::NORMAL_RENDER_MODE, + mode == RenderArgs::DEFAULT_RENDER_MODE); */ { GLenum buffers[3]; int bufferCount = 0; - if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) { + // if (mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE) { + if (mode != RenderArgs::SHADOW_RENDER_MODE) { buffers[bufferCount++] = GL_COLOR_ATTACHMENT0; } - if (mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE) { + // if (mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::NORMAL_RENDER_MODE) { + if (mode != RenderArgs::SHADOW_RENDER_MODE) { buffers[bufferCount++] = GL_COLOR_ATTACHMENT1; } - if (mode == DEFAULT_RENDER_MODE) { + // if (mode == RenderArgs::DEFAULT_RENDER_MODE) { + if (mode != RenderArgs::SHADOW_RENDER_MODE) { buffers[bufferCount++] = GL_COLOR_ATTACHMENT2; } GLBATCH(glDrawBuffers)(bufferCount, buffers); @@ -758,7 +780,7 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, false, args, true); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, true, args, true); - GLBATCH(glDisable)(GL_ALPHA_TEST); + // GLBATCH(glDisable)(GL_ALPHA_TEST); /* GLBATCH(glEnable)(GL_BLEND); GLBATCH(glDepthMask)(false); GLBATCH(glDepthFunc)(GL_LEQUAL); @@ -771,7 +793,8 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { GLBATCH(glDrawBuffers)(bufferCount, buffers); } - if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) { + // if (mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE) { + if (mode != RenderArgs::SHADOW_RENDER_MODE) { const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f; translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, false, args, true); translucentMeshPartsRendered += renderMeshes(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, true, args, true); @@ -790,7 +813,7 @@ bool Model::renderCore(float alpha, RenderMode mode, RenderArgs* args) { GLBATCH(glDepthFunc)(GL_LESS); GLBATCH(glDisable)(GL_CULL_FACE); - if (mode == SHADOW_RENDER_MODE) { + if (mode == RenderArgs::SHADOW_RENDER_MODE) { GLBATCH(glCullFace)(GL_BACK); } @@ -1713,6 +1736,9 @@ void Model::setupBatchTransform(gpu::Batch& batch) { void Model::endScene(RenderMode mode, RenderArgs* args) { PROFILE_RANGE(__FUNCTION__); + // auto glowEffectIntensity = DependencyManager::get()->getIntensity(); + + #if defined(ANDROID) #else glPushMatrix(); @@ -1739,13 +1765,13 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { _sceneRenderBatch.clear(); gpu::Batch& batch = _sceneRenderBatch; - GLBATCH(glDisable)(GL_COLOR_MATERIAL); + // GLBATCH(glDisable)(GL_COLOR_MATERIAL); - /* if (mode == DIFFUSE_RENDER_MODE || mode == NORMAL_RENDER_MODE) { + /* if (mode == RenderArgs::DIFFUSE_RENDER_MODE || mode == RenderArgs::NORMAL_RENDER_MODE) { GLBATCH(glDisable)(GL_CULL_FACE); } else { GLBATCH(glEnable)(GL_CULL_FACE); - if (mode == SHADOW_RENDER_MODE) { + if (mode == RenderArgs::SHADOW_RENDER_MODE) { GLBATCH(glCullFace)(GL_FRONT); } }*/ @@ -1753,28 +1779,31 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { // render opaque meshes with alpha testing // GLBATCH(glDisable)(GL_BLEND); - GLBATCH(glEnable)(GL_ALPHA_TEST); + // GLBATCH(glEnable)(GL_ALPHA_TEST); - if (mode == SHADOW_RENDER_MODE) { + /* if (mode == RenderArgs::SHADOW_RENDER_MODE) { GLBATCH(glAlphaFunc)(GL_EQUAL, 0.0f); } - +*/ /*DependencyManager::get()->setPrimaryDrawBuffers( - mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE, - mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE, - mode == DEFAULT_RENDER_MODE); + mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE, + mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::NORMAL_RENDER_MODE, + mode == RenderArgs::DEFAULT_RENDER_MODE); */ { GLenum buffers[3]; int bufferCount = 0; - if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) { + // if (mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE) { + if (mode != RenderArgs::SHADOW_RENDER_MODE) { buffers[bufferCount++] = GL_COLOR_ATTACHMENT0; } - if (mode == DEFAULT_RENDER_MODE || mode == NORMAL_RENDER_MODE) { + //if (mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::NORMAL_RENDER_MODE) { + if (mode != RenderArgs::SHADOW_RENDER_MODE) { buffers[bufferCount++] = GL_COLOR_ATTACHMENT1; } - if (mode == DEFAULT_RENDER_MODE) { + // if (mode == RenderArgs::DEFAULT_RENDER_MODE) { + if (mode != RenderArgs::SHADOW_RENDER_MODE) { buffers[bufferCount++] = GL_COLOR_ATTACHMENT2; } GLBATCH(glDrawBuffers)(bufferCount, buffers); @@ -1820,7 +1849,7 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, false, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_OPAQUE_THRESHOLD, false, true, true, true, args); - GLBATCH(glDisable)(GL_ALPHA_TEST); + // GLBATCH(glDisable)(GL_ALPHA_TEST); /* GLBATCH(glEnable)(GL_BLEND); GLBATCH(glDepthMask)(false); GLBATCH(glDepthFunc)(GL_LEQUAL); @@ -1833,7 +1862,8 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { GLBATCH(glDrawBuffers)(bufferCount, buffers); } - if (mode == DEFAULT_RENDER_MODE || mode == DIFFUSE_RENDER_MODE) { + // if (mode == RenderArgs::DEFAULT_RENDER_MODE || mode == RenderArgs::DIFFUSE_RENDER_MODE) { + if (mode != RenderArgs::SHADOW_RENDER_MODE) { const float MOSTLY_TRANSPARENT_THRESHOLD = 0.0f; translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, false, args); translucentParts += renderMeshesForModelsInScene(batch, mode, true, MOSTLY_TRANSPARENT_THRESHOLD, false, false, false, true, args); @@ -1849,7 +1879,7 @@ void Model::endScene(RenderMode mode, RenderArgs* args) { GLBATCH(glDepthFunc)(GL_LESS); GLBATCH(glDisable)(GL_CULL_FACE); - if (mode == SHADOW_RENDER_MODE) { + if (mode == RenderArgs::SHADOW_RENDER_MODE) { GLBATCH(glCullFace)(GL_BACK); } @@ -2273,9 +2303,16 @@ void Model::pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, f // dare! batch.setPipeline((*pipeline).second._pipeline); - if ((locations->alphaThreshold > -1) && (mode != SHADOW_RENDER_MODE)) { + if ((locations->alphaThreshold > -1) && (mode != RenderArgs::SHADOW_RENDER_MODE)) { GLBATCH(glUniform1f)(locations->alphaThreshold, alphaThreshold); } + + if ((locations->glowIntensity > -1) && (mode != RenderArgs::SHADOW_RENDER_MODE)) { + GLBATCH(glUniform1f)(locations->glowIntensity, DependencyManager::get()->getIntensity()); + } + // if (!(translucent && alphaThreshold == 0.0f) && (mode != RenderArgs::SHADOW_RENDER_MODE)) { + // GLBATCH(glAlphaFunc)(GL_EQUAL, DependencyManager::get()->getIntensity()); + // } } int Model::renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, @@ -2344,7 +2381,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod PROFILE_RANGE(__FUNCTION__); auto textureCache = DependencyManager::get(); - auto glowEffect = DependencyManager::get(); + // auto glowEffect = DependencyManager::get(); QString lastMaterialID; int meshPartsRendered = 0; updateVisibleJointStates(); @@ -2443,7 +2480,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod } // apply material properties - if (mode == SHADOW_RENDER_MODE) { + if (mode == RenderArgs::SHADOW_RENDER_MODE) { /// GLBATCH(glBindTexture)(GL_TEXTURE_2D, 0); } else { @@ -2455,13 +2492,13 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod qDebug() << "NEW part.materialID:" << part.materialID; } - if (locations->glowIntensity >= 0) { +/* if (locations->glowIntensity >= 0) { GLBATCH(glUniform1f)(locations->glowIntensity, glowEffect->getIntensity()); } if (!(translucent && alphaThreshold == 0.0f)) { GLBATCH(glAlphaFunc)(GL_EQUAL, glowEffect->getIntensity()); } - +*/ if (locations->materialBufferUnit >= 0) { batch.setUniformBuffer(locations->materialBufferUnit, material->getSchemaBuffer()); } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 07c5890aa3..ae0c66af9b 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -51,6 +51,8 @@ class Model : public QObject, public PhysicsEntity { public: + typedef RenderArgs::RenderMode RenderMode; + static void setAbstractViewStateInterface(AbstractViewStateInterface* viewState) { _viewState = viewState; } Model(QObject* parent = NULL); @@ -94,15 +96,13 @@ public: void init(); void reset(); virtual void simulate(float deltaTime, bool fullUpdate = true); - - enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE }; - - bool render(float alpha = 1.0f, RenderMode mode = DEFAULT_RENDER_MODE, RenderArgs* args = NULL); + + bool render(float alpha = 1.0f, RenderArgs::RenderMode mode = RenderArgs::DEFAULT_RENDER_MODE, RenderArgs* args = NULL); // Scene rendering support static void startScene(RenderArgs::RenderSide renderSide); bool renderInScene(float alpha = 1.0f, RenderArgs* args = NULL); - static void endScene(RenderMode mode = DEFAULT_RENDER_MODE, RenderArgs* args = NULL); + static void endScene(RenderArgs::RenderMode mode = RenderArgs::DEFAULT_RENDER_MODE, RenderArgs* args = NULL); /// Sets the URL of the model to render. /// \param fallback the URL of a fallback model to render if the requested model fails to load @@ -410,28 +410,28 @@ private: static QVector _modelsInScene; static gpu::Batch _sceneRenderBatch; - static void endSceneSimple(RenderMode mode = DEFAULT_RENDER_MODE, RenderArgs* args = NULL); - static void endSceneSplitPass(RenderMode mode = DEFAULT_RENDER_MODE, RenderArgs* args = NULL); + static void endSceneSimple(RenderArgs::RenderMode mode = RenderArgs::DEFAULT_RENDER_MODE, RenderArgs* args = NULL); + static void endSceneSplitPass(RenderArgs::RenderMode mode = RenderArgs::DEFAULT_RENDER_MODE, RenderArgs* args = NULL); // helper functions used by render() or renderInScene() void renderSetup(RenderArgs* args); - bool renderCore(float alpha, RenderMode mode, RenderArgs* args); - int renderMeshes(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, + bool renderCore(float alpha, RenderArgs::RenderMode mode, RenderArgs* args); + int renderMeshes(gpu::Batch& batch, RenderArgs::RenderMode mode, bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args = NULL, bool forceRenderSomeMeshes = false); void setupBatchTransform(gpu::Batch& batch); QVector* pickMeshList(bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned); - int renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, + int renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderArgs::RenderMode mode, bool translucent, float alphaThreshold, RenderArgs* args, Locations* locations, bool forceRenderSomeMeshes = false); - static void pickPrograms(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, + static void pickPrograms(gpu::Batch& batch, RenderArgs::RenderMode mode, bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args, Locations*& locations); - static int renderMeshesForModelsInScene(gpu::Batch& batch, RenderMode mode, bool translucent, float alphaThreshold, + static int renderMeshesForModelsInScene(gpu::Batch& batch, RenderArgs::RenderMode mode, bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned, RenderArgs* args); @@ -449,6 +449,7 @@ private: IS_STEREO_FLAG, IS_DEPTH_ONLY_FLAG, IS_SHADOW_FLAG, + IS_MIRROR_FLAG, //THis means that the mesh is rendered mirrored, not the same as "Rear view mirror" NUM_FLAGS, }; @@ -463,6 +464,7 @@ private: IS_STEREO = (1 << IS_STEREO_FLAG), IS_DEPTH_ONLY = (1 << IS_DEPTH_ONLY_FLAG), IS_SHADOW = (1 << IS_SHADOW_FLAG), + IS_MIRROR = (1 << IS_MIRROR_FLAG), }; typedef unsigned short Flags; @@ -480,22 +482,25 @@ private: bool isStereo() const { return isFlag(IS_STEREO); } bool isDepthOnly() const { return isFlag(IS_DEPTH_ONLY); } bool isShadow() const { return isFlag(IS_SHADOW); } // = depth only but with back facing + bool isMirror() const { return isFlag(IS_MIRROR); } Flags _flags = 0; short _spare = 0; int getRaw() { return *reinterpret_cast(this); } - RenderKey(RenderMode mode, + RenderKey(RenderArgs::RenderMode mode, bool translucent, float alphaThreshold, bool hasLightmap, bool hasTangents, bool hasSpecular, bool isSkinned) : - RenderKey( ((translucent && (alphaThreshold == 0.0f) && (mode != SHADOW_RENDER_MODE)) ? IS_TRANSLUCENT : 0) - | (hasLightmap && (mode != SHADOW_RENDER_MODE) ? HAS_LIGHTMAP : 0) // Lightmap, tangents and specular don't matter for depthOnly - | (hasTangents && (mode != SHADOW_RENDER_MODE) ? HAS_TANGENTS : 0) - | (hasSpecular && (mode != SHADOW_RENDER_MODE) ? HAS_SPECULAR : 0) + RenderKey( ((translucent && (alphaThreshold == 0.0f) && (mode != RenderArgs::SHADOW_RENDER_MODE)) ? IS_TRANSLUCENT : 0) + | (hasLightmap && (mode != RenderArgs::SHADOW_RENDER_MODE) ? HAS_LIGHTMAP : 0) // Lightmap, tangents and specular don't matter for depthOnly + | (hasTangents && (mode != RenderArgs::SHADOW_RENDER_MODE) ? HAS_TANGENTS : 0) + | (hasSpecular && (mode != RenderArgs::SHADOW_RENDER_MODE) ? HAS_SPECULAR : 0) | (isSkinned ? IS_SKINNED : 0) - | ((mode == SHADOW_RENDER_MODE) ? IS_DEPTH_ONLY : 0) - | ((mode == SHADOW_RENDER_MODE) ? IS_SHADOW : 0)) {} + | ((mode == RenderArgs::SHADOW_RENDER_MODE) ? IS_DEPTH_ONLY : 0) + | ((mode == RenderArgs::SHADOW_RENDER_MODE) ? IS_SHADOW : 0) + | ((mode == RenderArgs::MIRROR_RENDER_MODE) ? IS_MIRROR :0) + ) {} RenderKey(int bitmask) : _flags(bitmask) {} }; diff --git a/libraries/shared/src/RenderArgs.h b/libraries/shared/src/RenderArgs.h index e447472fee..cedad769b3 100644 --- a/libraries/shared/src/RenderArgs.h +++ b/libraries/shared/src/RenderArgs.h @@ -17,7 +17,7 @@ class OctreeRenderer; class RenderArgs { public: - enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE }; + enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE, MIRROR_RENDER_MODE }; enum RenderSide { MONO, STEREO_LEFT, STEREO_RIGHT }; OctreeRenderer* _renderer; From 3f581d03d2aa8de52c1d2033f055f56c224306a9 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Fri, 3 Apr 2015 10:45:30 -0700 Subject: [PATCH 16/21] mirror means we render the Closkwise side --- libraries/render-utils/src/Model.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 405795c3c7..cdb754c5d6 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -145,7 +145,7 @@ void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key, RenderKey mirrorKey(key.getRaw() | RenderKey::IS_MIRROR); gpu::StatePointer mirrorState = gpu::StatePointer(new gpu::State(state->getValues())); - // mirrorState->setFrontFaceClockwise(true); + mirrorState->setFrontFaceClockwise(true); // create a new RenderPipeline with the same shader side and the mirrorState auto mirrorPipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, mirrorState)); From ecdffadcb7a0e92607e6211903d8029ffbd712e5 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 6 Apr 2015 10:17:31 -0700 Subject: [PATCH 17/21] trying to debug the indirect sh lighting going wrong, the noraml on avatar is not correct --- interface/src/Application.cpp | 2 ++ interface/src/avatar/Avatar.cpp | 6 +++--- interface/src/avatar/MyAvatar.cpp | 6 +++--- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 6 +++--- libraries/render-utils/src/DeferredGlobalLight.slh | 9 +++++---- libraries/render-utils/src/Model.cpp | 3 --- 6 files changed, 16 insertions(+), 16 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 35f21cee61..303892d072 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2996,6 +2996,8 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs "Application::displaySide() ... entities..."); if (renderCollisionHulls) { _entities.render(RenderArgs::DEBUG_RENDER_MODE, renderSide); + } else if (theCamera.getMode() == CAMERA_MODE_MIRROR) { + _entities.render(RenderArgs::MIRROR_RENDER_MODE, renderSide); } else { _entities.render(RenderArgs::DEFAULT_RENDER_MODE, renderSide); } diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index c346a69df1..cfce0bd80e 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -528,10 +528,10 @@ void Avatar::simulateAttachments(float deltaTime) { } void Avatar::renderAttachments(RenderArgs::RenderMode renderMode, RenderArgs* args) { - RenderArgs::RenderMode modelRenderMode = (renderMode == RenderArgs::SHADOW_RENDER_MODE) ? - RenderArgs::SHADOW_RENDER_MODE : RenderArgs::DEFAULT_RENDER_MODE; + // RenderArgs::RenderMode modelRenderMode = (renderMode == RenderArgs::SHADOW_RENDER_MODE) ? + // RenderArgs::SHADOW_RENDER_MODE : RenderArgs::DEFAULT_RENDER_MODE; foreach (Model* model, _attachmentModels) { - model->render(1.0f, modelRenderMode, args); + model->render(1.0f, renderMode, args); } } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 30b64ccbb2..95aa42284a 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -1401,12 +1401,12 @@ void MyAvatar::renderAttachments(RenderArgs::RenderMode renderMode, RenderArgs* } const FBXGeometry& geometry = _skeletonModel.getGeometry()->getFBXGeometry(); QString headJointName = (geometry.headJointIndex == -1) ? QString() : geometry.joints.at(geometry.headJointIndex).name; - RenderArgs::RenderMode modelRenderMode = (renderMode == RenderArgs::SHADOW_RENDER_MODE) ? - RenderArgs::SHADOW_RENDER_MODE : RenderArgs::DEFAULT_RENDER_MODE; + // RenderArgs::RenderMode modelRenderMode = (renderMode == RenderArgs::SHADOW_RENDER_MODE) ? + // RenderArgs::SHADOW_RENDER_MODE : RenderArgs::DEFAULT_RENDER_MODE; for (int i = 0; i < _attachmentData.size(); i++) { const QString& jointName = _attachmentData.at(i).jointName; if (jointName != headJointName && jointName != "Head") { - _attachmentModels.at(i)->render(1.0f, modelRenderMode, args); + _attachmentModels.at(i)->render(1.0f, renderMode, args); } } } diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index d773a5add6..606825bb5d 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -394,12 +394,12 @@ void EntityTreeRenderer::render(RenderArgs::RenderMode renderMode, RenderArgs::R _tree->lockForRead(); _tree->recurseTreeWithOperation(renderOperation, &args); - Model::RenderMode modelRenderMode = renderMode == RenderArgs::SHADOW_RENDER_MODE - ? RenderArgs::SHADOW_RENDER_MODE : RenderArgs::DEFAULT_RENDER_MODE; +// Model::RenderMode modelRenderMode = renderMode == RenderArgs::SHADOW_RENDER_MODE + // ? RenderArgs::SHADOW_RENDER_MODE : RenderArgs::DEFAULT_RENDER_MODE; // we must call endScene while we still have the tree locked so that no one deletes a model // on us while rendering the scene - Model::endScene(modelRenderMode, &args); + Model::endScene(renderMode, &args); _tree->unlock(); // stats... diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index 556e7421af..cb74a0e218 100755 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -82,15 +82,16 @@ vec3 evalAmbienSphereGlobalColor(float shadowAttenuation, vec3 position, vec3 no // TODO: The world space normal doesn;t seem to work properly with the current SH definitions // FoOr now, we use the normal in view space - vec3 ambientNormal = normal; + vec3 ambientNormal = fragNormal.xzy; - vec3 color = diffuse.rgb * 0.5 * evalSphericalLight(ambientSphere, ambientNormal).xyz; + vec3 color = /* diffuse.rgb * 0.5 */ evalSphericalLight(ambientSphere, ambientNormal).xyz; vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss); - color += vec3(diffuse + shading.rgb) * shading.w * shadowAttenuation * getLightColor(light) * getLightIntensity(light); + // color += vec3(diffuse + shading.rgb) * shading.w * shadowAttenuation * getLightColor(light) * getLightIntensity(light); - return color; + //return color; + return fragNormal; } vec3 evalLightmappedColor(float shadowAttenuation, vec3 normal, vec3 diffuse, vec3 lightmap) { diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index e250e1278f..c76ccaad17 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -814,9 +814,6 @@ 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); From 4aa695d5f3e15d7ee76e892ded3a0e0b0e5997c0 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 6 Apr 2015 12:24:01 -0700 Subject: [PATCH 18/21] fixed an issue with skinned normaled map models not doing the correct transformation --- .../render-utils/src/DeferredGlobalLight.slh | 36 +++++++++---------- .../render-utils/src/model_normal_map.slf | 2 +- .../src/model_normal_specular_map.slf | 2 +- .../src/skin_model_normal_map.slv | 7 ++-- 4 files changed, 24 insertions(+), 23 deletions(-) diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index cb74a0e218..ecb1f503c7 100755 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -28,21 +28,23 @@ struct SphericalHarmonics { vec4 evalSphericalLight(SphericalHarmonics sh, vec3 direction ) { + vec3 dir = direction.xzy; // we don;t understand why yet but we need to use z as vertical axis? + const float C1 = 0.429043; const float C2 = 0.511664; const float C3 = 0.743125; const float C4 = 0.886227; const float C5 = 0.247708; - vec4 value = C1 * sh.L22 * (direction.x * direction.x - direction.y * direction.y) + - C3 * sh.L20 * direction.z * direction.z + + vec4 value = C1 * sh.L22 * (dir.x * dir.x - dir.y * dir.y) + + C3 * sh.L20 * dir.z * dir.z + C4 * sh.L00 - C5 * sh.L20 + - 2.0 * C1 * ( sh.L2m2 * direction.x * direction.y + - sh.L21 * direction.x * direction.z + - sh.L2m1 * direction.y * direction.z ) + - 2.0 * C2 * ( sh.L11 * direction.x + - sh.L1m1 * direction.y + - sh.L10 * direction.z ) ; + 2.0 * C1 * ( sh.L2m2 * dir.x * dir.y + + sh.L21 * dir.x * dir.z + + sh.L2m1 * dir.y * dir.z ) + + 2.0 * C2 * ( sh.L11 * dir.x + + sh.L1m1 * dir.y + + sh.L10 * dir.z ) ; return value; } @@ -75,23 +77,19 @@ vec3 evalAmbienGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 evalAmbienSphereGlobalColor(float shadowAttenuation, vec3 position, vec3 normal, vec3 diffuse, vec3 specular, float gloss) { // Need the light now Light light = getLight(); - - vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); + + vec3 fragNormal = normalize(vec3(invViewMat * vec4(normal, 0.0))); vec4 fragEyeVector = invViewMat * vec4(-position, 0.0); vec3 fragEyeDir = normalize(fragEyeVector.xyz); - - // TODO: The world space normal doesn;t seem to work properly with the current SH definitions - // FoOr now, we use the normal in view space - vec3 ambientNormal = fragNormal.xzy; - - vec3 color = /* diffuse.rgb * 0.5 */ evalSphericalLight(ambientSphere, ambientNormal).xyz; + + vec3 ambientNormal = fragNormal.xyz; + vec3 color = diffuse.rgb * 0.5 * evalSphericalLight(ambientSphere, ambientNormal).xyz; vec4 shading = evalFragShading(fragNormal, -getLightDirection(light), fragEyeDir, specular, gloss); - // color += vec3(diffuse + shading.rgb) * shading.w * shadowAttenuation * getLightColor(light) * getLightIntensity(light); + color += vec3(diffuse + shading.rgb) * shading.w * shadowAttenuation * getLightColor(light) * getLightIntensity(light); - //return color; - return fragNormal; + return color; } vec3 evalLightmappedColor(float shadowAttenuation, vec3 normal, vec3 diffuse, vec3 lightmap) { diff --git a/libraries/render-utils/src/model_normal_map.slf b/libraries/render-utils/src/model_normal_map.slf index 5ad0bfb50d..6a74ddaca0 100755 --- a/libraries/render-utils/src/model_normal_map.slf +++ b/libraries/render-utils/src/model_normal_map.slf @@ -33,7 +33,7 @@ void main(void) { vec3 normalizedNormal = normalize(vec3(interpolatedNormal)); vec3 normalizedTangent = normalize(vec3(interpolatedTangent)); vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent)); - vec3 localNormal = vec3(texture2D(normalMap, gl_TexCoord[0].st)) - vec3(0.5, 0.5, 0.5); + vec3 localNormal = normalize(vec3(texture2D(normalMap, gl_TexCoord[0].st)) - vec3(0.5, 0.5, 0.5)); vec4 viewNormal = vec4(normalizedTangent * localNormal.x + normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0); diff --git a/libraries/render-utils/src/model_normal_specular_map.slf b/libraries/render-utils/src/model_normal_specular_map.slf index 5c272d0c6b..4d70e659e6 100755 --- a/libraries/render-utils/src/model_normal_specular_map.slf +++ b/libraries/render-utils/src/model_normal_specular_map.slf @@ -36,7 +36,7 @@ void main(void) { vec3 normalizedNormal = normalize(vec3(interpolatedNormal)); vec3 normalizedTangent = normalize(vec3(interpolatedTangent)); vec3 normalizedBitangent = normalize(cross(normalizedNormal, normalizedTangent)); - vec3 localNormal = vec3(texture2D(normalMap, gl_TexCoord[0].st)) - vec3(0.5, 0.5, 0.5); + vec3 localNormal = normalize(vec3(texture2D(normalMap, gl_TexCoord[0].st)) - vec3(0.5, 0.5, 0.5)); vec4 viewNormal = vec4(normalizedTangent * localNormal.x + normalizedBitangent * localNormal.y + normalizedNormal * localNormal.z, 0.0); diff --git a/libraries/render-utils/src/skin_model_normal_map.slv b/libraries/render-utils/src/skin_model_normal_map.slv index 6a4170152d..19e0c041f0 100755 --- a/libraries/render-utils/src/skin_model_normal_map.slv +++ b/libraries/render-utils/src/skin_model_normal_map.slv @@ -52,12 +52,15 @@ void main(void) { // and the texture coordinates gl_TexCoord[0] = texcoordMatrices[0] * vec4(gl_MultiTexCoord0.xy, 0.0, 1.0); + interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0); + interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0); + // standard transform TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); <$transformModelToClipPos(cam, obj, interpolatedPosition, gl_Position)$> - <$transformModelToEyeDir(cam, obj, gl_Normal, interpolatedNormal.xyz)$> - <$transformModelToEyeDir(cam, obj, tangent, interpolatedTangent.xyz)$> + <$transformModelToEyeDir(cam, obj, interpolatedNormal.xyz, interpolatedNormal.xyz)$> + <$transformModelToEyeDir(cam, obj, interpolatedTangent.xyz, interpolatedTangent.xyz)$> interpolatedNormal = vec4(normalize(interpolatedNormal.xyz), 0.0); interpolatedTangent = vec4(normalize(interpolatedTangent.xyz), 0.0); From 07e7f6ea1d9f547c8524d95aa90ea44878a985b2 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 6 Apr 2015 15:40:29 -0700 Subject: [PATCH 19/21] FIx review comments --- libraries/gpu/src/gpu/GLBackend.cpp | 6 ++++-- libraries/render-utils/src/Model.h | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackend.cpp b/libraries/gpu/src/gpu/GLBackend.cpp index 0bf13636f1..1199251669 100644 --- a/libraries/gpu/src/gpu/GLBackend.cpp +++ b/libraries/gpu/src/gpu/GLBackend.cpp @@ -363,8 +363,9 @@ void GLBackend::do_glUseProgram(Batch& batch, uint32 paramOffset) { } void Batch::_glUniform1f(GLint location, GLfloat v0) { - if (location < 0) + if (location < 0) { return; + } ADD_COMMAND_GL(glUniform1f); _params.push_back(v0); _params.push_back(location); @@ -372,8 +373,9 @@ void Batch::_glUniform1f(GLint location, GLfloat v0) { DO_IT_NOW(_glUniform1f, 1); } void GLBackend::do_glUniform1f(Batch& batch, uint32 paramOffset) { - if (_pipeline._program == 0) + if (_pipeline._program == 0) { return; + } glUniform1f( batch._params[paramOffset + 1]._int, batch._params[paramOffset + 0]._float); diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 354dcae4bc..fce5629b8d 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -477,8 +477,8 @@ private: bool isTranslucent() const { return isFlag(IS_TRANSLUCENT); } bool hasLightmap() const { return isFlag(HAS_LIGHTMAP); } bool hasTangents() const { return isFlag(HAS_TANGENTS); } - bool HasSpecular() const { return isFlag(HAS_SPECULAR); } - bool HasEmissive() const { return isFlag(HAS_EMISSIVE); } + bool hasSpecular() const { return isFlag(HAS_SPECULAR); } + bool hasEmissive() const { return isFlag(HAS_EMISSIVE); } bool isSkinned() const { return isFlag(IS_SKINNED); } bool isStereo() const { return isFlag(IS_STEREO); } bool isDepthOnly() const { return isFlag(IS_DEPTH_ONLY); } From 7f46736bb4d966aa1de016aeec4cf7c03a884c7f Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Mon, 6 Apr 2015 17:17:25 -0700 Subject: [PATCH 20/21] playing with the shadwos --- libraries/gpu/src/gpu/GLBackendState.cpp | 69 ------------------------ libraries/render-utils/src/Model.cpp | 2 +- 2 files changed, 1 insertion(+), 70 deletions(-) diff --git a/libraries/gpu/src/gpu/GLBackendState.cpp b/libraries/gpu/src/gpu/GLBackendState.cpp index 1e2d842597..fba40ca77f 100644 --- a/libraries/gpu/src/gpu/GLBackendState.cpp +++ b/libraries/gpu/src/gpu/GLBackendState.cpp @@ -211,76 +211,7 @@ GLBackend::GLState* GLBackend::syncGPUObject(const State& state) { } } } -/* - 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_FACE_CLOCKWISE: { - generateFrontFaceClockwise(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_TEST: { - generateDepthTest(object->_commands, State::DepthTest(field.second._integer)); - 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, (field.second._unsigned_integer)); - break; - } - case State::ALPHA_TO_COVERAGE_ENABLE: { - generateAlphaToCoverageEnable(object->_commands, bool(field.second._integer)); - break; - } - - case State::BLEND_FUNCTION: { - generateBlend(object->_commands, state); - break; - } - - case State::COLOR_WRITE_MASK: { - generateColorWriteMask(object->_commands, field.second._integer); - break; - } - - } - } -*/ if (depthBias) { generateDepthBias(object->_commands, state); } diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 6a51de2a36..7c8bc3b35c 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -122,7 +122,7 @@ void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key, // Backface on shadow if (key.isShadow()) { state->setCullMode(gpu::State::CULL_FRONT); - state->setDepthBias(1.1f); + state->setDepthBias(1.0f); state->setDepthBiasSlopeScale(4.0f); } else { state->setCullMode(gpu::State::CULL_BACK); From 25643479c9a7fc18b4b586959ba277857806d9bc Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Tue, 7 Apr 2015 11:20:55 -0700 Subject: [PATCH 21/21] Fixed the memory leak, due to the location pointer in the Model::RenderPipelineLib which was not smart pointed correctly --- libraries/render-utils/src/Model.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 7c8bc3b35c..e2e09af27b 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -113,7 +113,7 @@ void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key, bool makeResult = gpu::Shader::makeProgram(*program, slotBindings); - Locations* locations = new Locations(); + auto locations = std::shared_ptr(new Locations()); initLocations(program, *locations); @@ -138,7 +138,7 @@ void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key, // Good to go add the brand new pipeline auto pipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, state)); - auto it = insert(value_type(key.getRaw(), RenderPipeline(pipeline, std::shared_ptr(locations)))); + auto it = insert(value_type(key.getRaw(), RenderPipeline(pipeline, locations))); // If not a shadow pass, create the mirror version from the same state, just change the FrontFace if (!key.isShadow()) { @@ -150,7 +150,7 @@ void Model::RenderPipelineLib::addRenderPipeline(Model::RenderKey key, // create a new RenderPipeline with the same shader side and the mirrorState auto mirrorPipeline = gpu::PipelinePointer(gpu::Pipeline::create(program, mirrorState)); - auto it = insert(value_type(mirrorKey.getRaw(), RenderPipeline(mirrorPipeline, std::shared_ptr(locations)))); + auto it = insert(value_type(mirrorKey.getRaw(), RenderPipeline(mirrorPipeline, locations))); } }