From 6fb869126e857c98afca9b540cb58d28358608ea Mon Sep 17 00:00:00 2001 From: Brad Davis <bdavis@saintandreas.org> Date: Sun, 28 Oct 2018 16:10:21 -0700 Subject: [PATCH] GPU state cleanup --- .../gpu-gl-common/src/gpu/gl/GLBackend.h | 127 +----- .../src/gpu/gl/GLBackendOutput.cpp | 4 +- .../src/gpu/gl/GLBackendState.cpp | 28 +- .../gpu-gl-common/src/gpu/gl/GLShared.cpp | 22 +- .../gpu-gl-common/src/gpu/gl/GLState.cpp | 14 +- libraries/gpu/src/gpu/Context.h | 146 +++++++ libraries/gpu/src/gpu/Format.h | 2 +- libraries/gpu/src/gpu/State.cpp | 38 +- libraries/gpu/src/gpu/State.h | 388 ++++++++++-------- .../render-utils/src/StencilMaskPass.cpp | 4 +- 10 files changed, 437 insertions(+), 336 deletions(-) diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h index 07f7df9277..ed94cbb64d 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackend.h @@ -78,129 +78,6 @@ namespace gpu { namespace gl { -#if defined(GPU_POINTER_STORAGE_SHARED) -template <typename T> -static inline bool compare(const std::shared_ptr<T>& a, const std::shared_ptr<T>& b) { - return a == b; -} - -template <typename T> -static inline T* acquire(const std::shared_ptr<T>& pointer) { - return pointer.get(); -} - -template <typename T> -static inline void reset(std::shared_ptr<T>& pointer) { - return pointer.reset(); -} - -template <typename T> -static inline bool valid(const std::shared_ptr<T>& pointer) { - return pointer.operator bool(); -} - -template <typename T> -static inline void assign(std::shared_ptr<T>& pointer, const std::shared_ptr<T>& source) { - pointer = source; -} - -using BufferReference = BufferPointer; -using TextureReference = TexturePointer; -using FramebufferReference = FramebufferPointer; -using FormatReference = Stream::FormatPointer; -using PipelineReference = PipelinePointer; - -#define GPU_REFERENCE_INIT_VALUE nullptr - -#elif defined(GPU_POINTER_STORAGE_REF) - -template <typename T> -class PointerReferenceWrapper : public std::reference_wrapper<const std::shared_ptr<T>> { - using Parent = std::reference_wrapper<const std::shared_ptr<T>>; - -public: - using Pointer = std::shared_ptr<T>; - PointerReferenceWrapper() : Parent(EMPTY()) {} - PointerReferenceWrapper(const Pointer& pointer) : Parent(pointer) {} - void clear() { *this = EMPTY(); } - -private: - static const Pointer& EMPTY() { - static const Pointer EMPTY_VALUE; - return EMPTY_VALUE; - }; -}; - -template <typename T> -static bool compare(const PointerReferenceWrapper<T>& reference, const std::shared_ptr<T>& pointer) { - return reference.get() == pointer; -} - -template <typename T> -static inline T* acquire(const PointerReferenceWrapper<T>& reference) { - return reference.get().get(); -} - -template <typename T> -static void assign(PointerReferenceWrapper<T>& reference, const std::shared_ptr<T>& pointer) { - reference = pointer; -} - -template <typename T> -static bool valid(const PointerReferenceWrapper<T>& reference) { - return reference.get().operator bool(); -} - -template <typename T> -static inline void reset(PointerReferenceWrapper<T>& reference) { - return reference.clear(); -} - -using BufferReference = PointerReferenceWrapper<Buffer>; -using TextureReference = PointerReferenceWrapper<Texture>; -using FramebufferReference = PointerReferenceWrapper<Framebuffer>; -using FormatReference = PointerReferenceWrapper<Stream::Format>; -using PipelineReference = PointerReferenceWrapper<Pipeline>; - -#define GPU_REFERENCE_INIT_VALUE - -#elif defined(GPU_POINTER_STORAGE_RAW) - -template <typename T> -static bool compare(const T* const& rawPointer, const std::shared_ptr<T>& pointer) { - return rawPointer == pointer.get(); -} - -template <typename T> -static inline T* acquire(T*& rawPointer) { - return rawPointer; -} - -template <typename T> -static inline bool valid(const T* const& rawPointer) { - return rawPointer; -} - -template <typename T> -static inline void reset(T*& rawPointer) { - rawPointer = nullptr; -} - -template <typename T> -static inline void assign(T*& rawPointer, const std::shared_ptr<T>& pointer) { - rawPointer = pointer.get(); -} - -using BufferReference = Buffer*; -using TextureReference = Texture*; -using FramebufferReference = Framebuffer*; -using FormatReference = Stream::Format*; -using PipelineReference = Pipeline*; - -#define GPU_REFERENCE_INIT_VALUE nullptr - -#endif - class GLBackend : public Backend, public std::enable_shared_from_this<GLBackend> { // Context Backend static interface required friend class gpu::Context; @@ -583,13 +460,13 @@ protected: BufferState& operator=(const BufferState& other) = delete; void reset() { - gpu::gl::reset(buffer); + gpu::reset(buffer); offset = 0; size = 0; } bool compare(const BufferPointer& buffer, GLintptr offset, GLsizeiptr size) { const auto& self = *this; - return (self.offset == offset && self.size == size && gpu::gl::compare(self.buffer, buffer)); + return (self.offset == offset && self.size == size && gpu::compare(self.buffer, buffer)); } }; diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackendOutput.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackendOutput.cpp index 411e16b18e..a10d6c96c4 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackendOutput.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackendOutput.cpp @@ -73,7 +73,7 @@ void GLBackend::do_advance(const Batch& batch, size_t paramOffset) { } void GLBackend::do_clearFramebuffer(const Batch& batch, size_t paramOffset) { - if (_stereo.isStereo() && !_pipeline._stateCache.scissorEnable) { + if (_stereo.isStereo() && !_pipeline._stateCache.flags.scissorEnable) { qWarning("Clear without scissor in stereo mode"); } @@ -140,7 +140,7 @@ void GLBackend::do_clearFramebuffer(const Batch& batch, size_t paramOffset) { } // Apply scissor if needed and if not already on - bool doEnableScissor = (useScissor && (!_pipeline._stateCache.scissorEnable)); + bool doEnableScissor = (useScissor && (!_pipeline._stateCache.flags.scissorEnable)); if (doEnableScissor) { glEnable(GL_SCISSOR_TEST); } diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLBackendState.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLBackendState.cpp index 8363af9b00..5da32f39df 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLBackendState.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLBackendState.cpp @@ -100,17 +100,17 @@ void GLBackend::do_setStateCullMode(int32 mode) { } void GLBackend::do_setStateFrontFaceClockwise(bool isClockwise) { - if (_pipeline._stateCache.frontFaceClockwise != isClockwise) { + if (_pipeline._stateCache.flags.frontFaceClockwise != isClockwise) { static GLenum GL_FRONT_FACES[] = { GL_CCW, GL_CW }; glFrontFace(GL_FRONT_FACES[isClockwise]); (void)CHECK_GL_ERROR(); - _pipeline._stateCache.frontFaceClockwise = isClockwise; + _pipeline._stateCache.flags.frontFaceClockwise = isClockwise; } } void GLBackend::do_setStateDepthClampEnable(bool enable) { - if (_pipeline._stateCache.depthClampEnable != enable) { + if (_pipeline._stateCache.flags.depthClampEnable != enable) { #if !defined(USE_GLES) if (enable) { glEnable(GL_DEPTH_CLAMP); @@ -118,13 +118,13 @@ void GLBackend::do_setStateDepthClampEnable(bool enable) { glDisable(GL_DEPTH_CLAMP); } (void)CHECK_GL_ERROR(); - _pipeline._stateCache.depthClampEnable = enable; + _pipeline._stateCache.flags.depthClampEnable = enable; #endif } } void GLBackend::do_setStateScissorEnable(bool enable) { - if (_pipeline._stateCache.scissorEnable != enable) { + if (_pipeline._stateCache.flags.scissorEnable != enable) { if (enable) { glEnable(GL_SCISSOR_TEST); } else { @@ -132,12 +132,12 @@ void GLBackend::do_setStateScissorEnable(bool enable) { } (void)CHECK_GL_ERROR(); - _pipeline._stateCache.scissorEnable = enable; + _pipeline._stateCache.flags.scissorEnable = enable; } } void GLBackend::do_setStateMultisampleEnable(bool enable) { - if (_pipeline._stateCache.multisampleEnable != enable) { + if (_pipeline._stateCache.flags.multisampleEnable != enable) { #if !defined(USE_GLES) if (enable) { glEnable(GL_MULTISAMPLE); @@ -146,13 +146,13 @@ void GLBackend::do_setStateMultisampleEnable(bool enable) { } (void)CHECK_GL_ERROR(); - _pipeline._stateCache.multisampleEnable = enable; + _pipeline._stateCache.flags.multisampleEnable = enable; #endif } } void GLBackend::do_setStateAntialiasedLineEnable(bool enable) { - if (_pipeline._stateCache.antialisedLineEnable != enable) { + if (_pipeline._stateCache.flags.antialisedLineEnable != enable) { #if !defined(USE_GLES) if (enable) { glEnable(GL_LINE_SMOOTH); @@ -161,7 +161,7 @@ void GLBackend::do_setStateAntialiasedLineEnable(bool enable) { } (void)CHECK_GL_ERROR(); - _pipeline._stateCache.antialisedLineEnable = enable; + _pipeline._stateCache.flags.antialisedLineEnable = enable; #endif } } @@ -206,7 +206,7 @@ void GLBackend::do_setStateDepthTest(State::DepthTest test) { if (CHECK_GL_ERROR()) { qCDebug(gpulogging) << "DepthTest" << (test.isEnabled() ? "Enabled" : "Disabled") << "Mask=" << (test.getWriteMask() ? "Write" : "no Write") - << "Func=" << test.getFunction() + << "Func=" << (uint16_t)test.getFunction() << "Raw=" << test.getRaw(); } _pipeline._stateCache.depthTest = test; @@ -264,7 +264,7 @@ void GLBackend::do_setStateStencil(State::StencilActivation activation, State::S } void GLBackend::do_setStateAlphaToCoverageEnable(bool enable) { - if (_pipeline._stateCache.alphaToCoverageEnable != enable) { + if (_pipeline._stateCache.flags.alphaToCoverageEnable != enable) { if (enable) { glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE); } else { @@ -272,7 +272,7 @@ void GLBackend::do_setStateAlphaToCoverageEnable(bool enable) { } (void)CHECK_GL_ERROR(); - _pipeline._stateCache.alphaToCoverageEnable = enable; + _pipeline._stateCache.flags.alphaToCoverageEnable = enable; } } @@ -317,7 +317,7 @@ void GLBackend::do_setStateColorWriteMask(uint32 mask) { mask & State::ColorMask::WRITE_ALPHA); (void)CHECK_GL_ERROR(); - _pipeline._stateCache.colorWriteMask = mask; + _pipeline._stateCache.colorWriteMask = (State::ColorMask)mask; } } diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLShared.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLShared.cpp index 9ba85b8418..995feaa7a4 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLShared.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLShared.cpp @@ -174,17 +174,17 @@ void getCurrentGLState(State::Data& state) { { GLint winding; glGetIntegerv(GL_FRONT_FACE, &winding); - state.frontFaceClockwise = (winding == GL_CW); + state.flags.frontFaceClockwise = (winding == GL_CW); #if defined(USE_GLES) - state.multisampleEnable = glIsEnabled(GL_MULTISAMPLE_EXT); - state.antialisedLineEnable = false; - state.depthClampEnable = false; + state.flags.multisampleEnable = glIsEnabled(GL_MULTISAMPLE_EXT); + state.flags.antialisedLineEnable = false; + state.flags.depthClampEnable = false; #else - state.multisampleEnable = glIsEnabled(GL_MULTISAMPLE); - state.antialisedLineEnable = glIsEnabled(GL_LINE_SMOOTH); - state.depthClampEnable = glIsEnabled(GL_DEPTH_CLAMP); + state.flags.multisampleEnable = glIsEnabled(GL_MULTISAMPLE); + state.flags.antialisedLineEnable = glIsEnabled(GL_LINE_SMOOTH); + state.flags.depthClampEnable = glIsEnabled(GL_DEPTH_CLAMP); #endif - state.scissorEnable = glIsEnabled(GL_SCISSOR_TEST); + state.flags.scissorEnable = glIsEnabled(GL_SCISSOR_TEST); } { if (glIsEnabled(GL_POLYGON_OFFSET_FILL)) { @@ -247,7 +247,7 @@ void getCurrentGLState(State::Data& state) { state.sampleMask = mask; } { - state.alphaToCoverageEnable = glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE); + state.flags.alphaToCoverageEnable = glIsEnabled(GL_SAMPLE_ALPHA_TO_COVERAGE); } { GLboolean isEnabled = glIsEnabled(GL_BLEND); @@ -272,10 +272,10 @@ void getCurrentGLState(State::Data& state) { { GLboolean mask[4]; glGetBooleanv(GL_COLOR_WRITEMASK, mask); - state.colorWriteMask = (mask[0] ? State::WRITE_RED : 0) + state.colorWriteMask = (State::ColorMask)((mask[0] ? State::WRITE_RED : 0) | (mask[1] ? State::WRITE_GREEN : 0) | (mask[2] ? State::WRITE_BLUE : 0) - | (mask[3] ? State::WRITE_ALPHA : 0); + | (mask[3] ? State::WRITE_ALPHA : 0)); } (void)CHECK_GL_ERROR(); diff --git a/libraries/gpu-gl-common/src/gpu/gl/GLState.cpp b/libraries/gpu-gl-common/src/gpu/gl/GLState.cpp index b6d917b928..4a27f1ec1f 100644 --- a/libraries/gpu-gl-common/src/gpu/gl/GLState.cpp +++ b/libraries/gpu-gl-common/src/gpu/gl/GLState.cpp @@ -44,7 +44,7 @@ const GLState::Commands makeResetStateCommands() { // and we have a 50/50 chance that State::DEFAULT is not yet initialized. // Since State::DEFAULT = State::Data() it is much easier to not use the actual State::DEFAULT // but another State::Data object with a default initialization. - const State::Data DEFAULT = State::Data(); + const State::Data& DEFAULT = State::DEFAULT; auto depthBiasCommand = std::make_shared<CommandDepthBias>(&GLBackend::do_setStateDepthBias, Vec2(DEFAULT.depthBias, DEFAULT.depthBiasSlopeScale)); @@ -56,11 +56,11 @@ const GLState::Commands makeResetStateCommands() { return { std::make_shared<Command1I>(&GLBackend::do_setStateFillMode, DEFAULT.fillMode), std::make_shared<Command1I>(&GLBackend::do_setStateCullMode, DEFAULT.cullMode), - std::make_shared<Command1B>(&GLBackend::do_setStateFrontFaceClockwise, DEFAULT.frontFaceClockwise), - std::make_shared<Command1B>(&GLBackend::do_setStateDepthClampEnable, DEFAULT.depthClampEnable), - std::make_shared<Command1B>(&GLBackend::do_setStateScissorEnable, DEFAULT.scissorEnable), - std::make_shared<Command1B>(&GLBackend::do_setStateMultisampleEnable, DEFAULT.multisampleEnable), - std::make_shared<Command1B>(&GLBackend::do_setStateAntialiasedLineEnable, DEFAULT.antialisedLineEnable), + std::make_shared<Command1B>(&GLBackend::do_setStateFrontFaceClockwise, DEFAULT.flags.frontFaceClockwise), + std::make_shared<Command1B>(&GLBackend::do_setStateDepthClampEnable, DEFAULT.flags.depthClampEnable), + std::make_shared<Command1B>(&GLBackend::do_setStateScissorEnable, DEFAULT.flags.scissorEnable), + std::make_shared<Command1B>(&GLBackend::do_setStateMultisampleEnable, DEFAULT.flags.multisampleEnable), + std::make_shared<Command1B>(&GLBackend::do_setStateAntialiasedLineEnable, DEFAULT.flags.antialisedLineEnable), // Depth bias has 2 fields in State but really one call in GLBackend CommandPointer(depthBiasCommand), @@ -75,7 +75,7 @@ const GLState::Commands makeResetStateCommands() { std::make_shared<Command1U>(&GLBackend::do_setStateSampleMask, DEFAULT.sampleMask), - std::make_shared<Command1B>(&GLBackend::do_setStateAlphaToCoverageEnable, DEFAULT.alphaToCoverageEnable), + std::make_shared<Command1B>(&GLBackend::do_setStateAlphaToCoverageEnable, DEFAULT.flags.alphaToCoverageEnable), std::make_shared<CommandBlend>(&GLBackend::do_setStateBlend, DEFAULT.blendFunction), diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index 0626ecd8f3..5fccd206d8 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -29,6 +29,152 @@ class QImage; namespace gpu { +// +// GL Backend pointer storage mechanism +// One of the following three defines must be defined. +// GPU_POINTER_STORAGE_SHARED + +// The platonic ideal, use references to smart pointers. +// However, this produces artifacts because there are too many places in the code right now that +// create temporary values (undesirable smart pointer duplications) and then those temp variables +// get passed on and have their reference taken, and then invalidated +// GPU_POINTER_STORAGE_REF + +// Raw pointer manipulation. Seems more dangerous than the reference wrappers, +// but in practice, the danger of grabbing a reference to a temporary variable +// is causing issues +// GPU_POINTER_STORAGE_RAW + +#if defined(USE_GLES) +#define GPU_POINTER_STORAGE_SHARED +#else +#define GPU_POINTER_STORAGE_RAW +#endif + +#if defined(GPU_POINTER_STORAGE_SHARED) +template <typename T> +static inline bool compare(const std::shared_ptr<T>& a, const std::shared_ptr<T>& b) { + return a == b; +} + +template <typename T> +static inline T* acquire(const std::shared_ptr<T>& pointer) { + return pointer.get(); +} + +template <typename T> +static inline void reset(std::shared_ptr<T>& pointer) { + return pointer.reset(); +} + +template <typename T> +static inline bool valid(const std::shared_ptr<T>& pointer) { + return pointer.operator bool(); +} + +template <typename T> +static inline void assign(std::shared_ptr<T>& pointer, const std::shared_ptr<T>& source) { + pointer = source; +} + +using BufferReference = BufferPointer; +using TextureReference = TexturePointer; +using FramebufferReference = FramebufferPointer; +using FormatReference = Stream::FormatPointer; +using PipelineReference = PipelinePointer; + +#define GPU_REFERENCE_INIT_VALUE nullptr + +#elif defined(GPU_POINTER_STORAGE_REF) + +template <typename T> +class PointerReferenceWrapper : public std::reference_wrapper<const std::shared_ptr<T>> { + using Parent = std::reference_wrapper<const std::shared_ptr<T>>; + +public: + using Pointer = std::shared_ptr<T>; + PointerReferenceWrapper() : Parent(EMPTY()) {} + PointerReferenceWrapper(const Pointer& pointer) : Parent(pointer) {} + void clear() { *this = EMPTY(); } + +private: + static const Pointer& EMPTY() { + static const Pointer EMPTY_VALUE; + return EMPTY_VALUE; + }; +}; + +template <typename T> +static bool compare(const PointerReferenceWrapper<T>& reference, const std::shared_ptr<T>& pointer) { + return reference.get() == pointer; +} + +template <typename T> +static inline T* acquire(const PointerReferenceWrapper<T>& reference) { + return reference.get().get(); +} + +template <typename T> +static void assign(PointerReferenceWrapper<T>& reference, const std::shared_ptr<T>& pointer) { + reference = pointer; +} + +template <typename T> +static bool valid(const PointerReferenceWrapper<T>& reference) { + return reference.get().operator bool(); +} + +template <typename T> +static inline void reset(PointerReferenceWrapper<T>& reference) { + return reference.clear(); +} + +using BufferReference = PointerReferenceWrapper<Buffer>; +using TextureReference = PointerReferenceWrapper<Texture>; +using FramebufferReference = PointerReferenceWrapper<Framebuffer>; +using FormatReference = PointerReferenceWrapper<Stream::Format>; +using PipelineReference = PointerReferenceWrapper<Pipeline>; + +#define GPU_REFERENCE_INIT_VALUE + +#elif defined(GPU_POINTER_STORAGE_RAW) + +template <typename T> +static bool compare(const T* const& rawPointer, const std::shared_ptr<T>& pointer) { + return rawPointer == pointer.get(); +} + +template <typename T> +static inline T* acquire(T* const& rawPointer) { + return rawPointer; +} + +template <typename T> +static inline bool valid(const T* const& rawPointer) { + return rawPointer; +} + +template <typename T> +static inline void reset(T*& rawPointer) { + rawPointer = nullptr; +} + +template <typename T> +static inline void assign(T*& rawPointer, const std::shared_ptr<T>& pointer) { + rawPointer = pointer.get(); +} + +using BufferReference = Buffer*; +using TextureReference = Texture*; +using FramebufferReference = Framebuffer*; +using FormatReference = Stream::Format*; +using PipelineReference = Pipeline*; + +#define GPU_REFERENCE_INIT_VALUE nullptr + +#endif + + struct ContextStats { public: int _ISNumFormatChanges = 0; diff --git a/libraries/gpu/src/gpu/Format.h b/libraries/gpu/src/gpu/Format.h index 7a3e0a2f82..5103296e6e 100644 --- a/libraries/gpu/src/gpu/Format.h +++ b/libraries/gpu/src/gpu/Format.h @@ -376,7 +376,7 @@ public: }; -enum ComparisonFunction { +enum ComparisonFunction : uint16 { NEVER = 0, LESS, EQUAL, diff --git a/libraries/gpu/src/gpu/State.cpp b/libraries/gpu/src/gpu/State.cpp index cb5ced2c15..c62d2060df 100755 --- a/libraries/gpu/src/gpu/State.cpp +++ b/libraries/gpu/src/gpu/State.cpp @@ -33,19 +33,19 @@ State::Signature State::evalSignature(const Data& state) { if (state.cullMode != State::DEFAULT.cullMode) { signature.set(State::CULL_MODE); } - if (state.frontFaceClockwise != State::DEFAULT.frontFaceClockwise) { + if (state.flags.frontFaceClockwise != State::DEFAULT.flags.frontFaceClockwise) { signature.set(State::FRONT_FACE_CLOCKWISE); } - if (state.depthClampEnable != State::DEFAULT.depthClampEnable) { + if (state.flags.depthClampEnable != State::DEFAULT.flags.depthClampEnable) { signature.set(State::DEPTH_CLAMP_ENABLE); } - if (state.scissorEnable != State::DEFAULT.scissorEnable) { + if (state.flags.scissorEnable != State::DEFAULT.flags.scissorEnable) { signature.set(State::SCISSOR_ENABLE); } - if (state.multisampleEnable != State::DEFAULT.multisampleEnable) { + if (state.flags.multisampleEnable != State::DEFAULT.flags.multisampleEnable) { signature.set(State::MULTISAMPLE_ENABLE); } - if (state.antialisedLineEnable != State::DEFAULT.antialisedLineEnable) { + if (state.flags.antialisedLineEnable != State::DEFAULT.flags.antialisedLineEnable) { signature.set(State::ANTIALISED_LINE_ENABLE); } if (state.depthBias != State::DEFAULT.depthBias) { @@ -69,7 +69,7 @@ State::Signature State::evalSignature(const Data& state) { if (state.sampleMask != State::DEFAULT.sampleMask) { signature.set(State::SAMPLE_MASK); } - if (state.alphaToCoverageEnable != State::DEFAULT.alphaToCoverageEnable) { + if (state.flags.alphaToCoverageEnable != State::DEFAULT.flags.alphaToCoverageEnable) { signature.set(State::ALPHA_TO_COVERAGE_ENABLE); } if (state.blendFunction != State::DEFAULT.blendFunction) { @@ -86,3 +86,29 @@ State::State(const Data& values) : _values(values) { _signature = evalSignature(_values); } + + +template <typename T> +static std::string hex(T t) { + std::stringstream stream; + stream << std::hex << t; + return stream.str(); +} + +std::string State::getKey() const { + std::string key; + key = hex(*(int*)&_values.depthBias); + key += ":" + hex(*(int*)&_values.depthBiasSlopeScale); + key += ":" + hex(_values.depthTest.getRaw()); + key += ":" + hex(_values.stencilActivation.getRaw()); + key += ":" + hex(_values.stencilTestFront.getRaw()); + key += ":" + hex(_values.stencilTestBack.getRaw()); + key += ":" + hex(_values.blendFunction.getRaw()); + key += ":" + hex(_values.sampleMask); + key += ":" + hex(_values.sampleMask); + // fillMode, cullMode, colorMaskWrite and the flags consume 32 bits alltogether + static_assert(0 == offsetof(State::Data, fillMode) % 4, "Validate fillMode offset"); + key += ":" + hex(*(int*)&_values.fillMode); + return key; +} + diff --git a/libraries/gpu/src/gpu/State.h b/libraries/gpu/src/gpu/State.h index e68e829fb5..e726c8c53d 100755 --- a/libraries/gpu/src/gpu/State.h +++ b/libraries/gpu/src/gpu/State.h @@ -14,6 +14,7 @@ #include "Format.h" #include <memory> +#include <sstream> #include <vector> #include <unordered_map> #include <bitset> @@ -21,16 +22,16 @@ // 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) {\ - _signature.reset(field);\ - } else {\ - _signature.set(field);\ - }\ - _stamp++;\ -}\ - +#define SET_FIELD(FIELD, PATH, value) \ + { \ + _values.PATH = value; \ + if (value == DEFAULT.PATH) { \ + _signature.reset(FIELD); \ + } else { \ + _signature.set(FIELD); \ + } \ + _stamp++; \ + } namespace gpu { @@ -45,7 +46,8 @@ public: typedef ::gpu::ComparisonFunction ComparisonFunction; - enum FillMode { + enum FillMode : uint8 + { FILL_POINT = 0, FILL_LINE, FILL_FACE, @@ -53,7 +55,8 @@ public: NUM_FILL_MODES, }; - enum CullMode { + enum CullMode : uint8 + { CULL_NONE = 0, CULL_FRONT, CULL_BACK, @@ -61,7 +64,8 @@ public: NUM_CULL_MODES, }; - enum StencilOp { + enum StencilOp : uint16 + { STENCIL_OP_KEEP = 0, STENCIL_OP_ZERO, STENCIL_OP_REPLACE, @@ -74,7 +78,8 @@ public: NUM_STENCIL_OPS, }; - enum BlendArg { + enum BlendArg : uint16 + { ZERO = 0, ONE, SRC_COLOR, @@ -94,7 +99,8 @@ public: NUM_BLEND_ARGS, }; - enum BlendOp { + enum BlendOp : uint16 + { BLEND_OP_ADD = 0, BLEND_OP_SUBTRACT, BLEND_OP_REV_SUBTRACT, @@ -104,204 +110,234 @@ public: NUM_BLEND_OPS, }; - enum ColorMask + enum ColorMask : uint8 { 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 ), + WRITE_ALL = (WRITE_RED | WRITE_GREEN | WRITE_BLUE | WRITE_ALPHA), }; class DepthTest { - uint8 _function = LESS; - uint8 _writeMask = true; - uint8 _enabled = false; -#if defined(__clang__) - __attribute__((unused)) -#endif - uint8 _spare = 0; // Padding + public: + uint8 writeMask{ true }; + uint8 enabled{ false }; + ComparisonFunction function{ LESS }; + public: DepthTest(bool enabled = false, bool writeMask = true, ComparisonFunction func = LESS) : - _function(func), _writeMask(writeMask), _enabled(enabled) { - } + function(func), writeMask(writeMask), enabled(enabled) {} - bool isEnabled() const { return _enabled != 0; } - ComparisonFunction getFunction() const { return ComparisonFunction(_function); } - uint8 getWriteMask() const { return _writeMask; } + bool isEnabled() const { return enabled != 0; } + ComparisonFunction getFunction() const { return function; } + uint8 getWriteMask() const { return writeMask; } int32 getRaw() const { return *(reinterpret_cast<const int32*>(this)); } DepthTest(int32 raw) { *(reinterpret_cast<int32*>(this)) = raw; } - bool operator== (const DepthTest& right) const { return getRaw() == right.getRaw(); } - bool operator!= (const DepthTest& right) const { return getRaw() != right.getRaw(); } - }; + 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_OFFSET = 4; - static const int DEPTH_FAIL_OP_OFFSET = 8; - static const int PASS_OP_OFFSET = 12; + static_assert(sizeof(DepthTest) == sizeof(uint32_t), "DepthTest size check"); - uint16 _functionAndOperations; - int8 _reference = 0; - uint8 _readMask = 0xff; - public: + struct StencilTest { + ComparisonFunction function : 4; + StencilOp failOp : 4; + StencilOp depthFailOp : 4; + StencilOp passOp : 4; + int8 reference{ 0 }; + uint8 readMask{ 0xff }; - StencilTest(int8 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) - {} + public: + StencilTest(int8 reference = 0, + uint8 readMask = 0xFF, + ComparisonFunction func = ALWAYS, + StencilOp failOp = STENCIL_OP_KEEP, + StencilOp depthFailOp = STENCIL_OP_KEEP, + StencilOp passOp = STENCIL_OP_KEEP) : + function(func), + failOp(failOp), depthFailOp(depthFailOp), passOp(passOp), 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); } + ComparisonFunction getFunction() const { return function; } + StencilOp getFailOp() const { return failOp; } + StencilOp getDepthFailOp() const { return depthFailOp; } + StencilOp getPassOp() const { return passOp; } - int8 getReference() const { return _reference; } - uint8 getReadMask() const { return _readMask; } + int8 getReference() const { return reference; } + uint8 getReadMask() const { return readMask; } int32 getRaw() const { return *(reinterpret_cast<const int32*>(this)); } StencilTest(int32 raw) { *(reinterpret_cast<int32*>(this)) = raw; } - bool operator== (const StencilTest& right) const { return getRaw() == right.getRaw(); } - bool operator!= (const StencilTest& right) const { return getRaw() != right.getRaw(); } - }; + bool operator==(const StencilTest& right) const { return getRaw() == right.getRaw(); } + bool operator!=(const StencilTest& right) const { return getRaw() != right.getRaw(); } + }; + static_assert(sizeof(StencilTest) == sizeof(uint32_t), "StencilTest size check"); - class StencilActivation { - uint8 _frontWriteMask = 0xFF; - uint8 _backWriteMask = 0xFF; - uint16 _enabled = 0; - public: + StencilTest stencilTestFront; - StencilActivation(bool enabled, uint8 frontWriteMask = 0xFF, uint8 backWriteMask = 0xFF) : - _frontWriteMask(frontWriteMask), _backWriteMask(backWriteMask), _enabled(enabled) {} + struct StencilActivation { + uint8 frontWriteMask = 0xFF; + uint8 backWriteMask = 0xFF; + bool enabled : 1; + uint8 _spare1 : 7; + uint8 _spare2{ 0 }; - bool isEnabled() const { return (_enabled != 0); } - uint8 getWriteMaskFront() const { return _frontWriteMask; } - uint8 getWriteMaskBack() const { return _backWriteMask; } + public: + StencilActivation(bool enabled = false, uint8 frontWriteMask = 0xFF, uint8 backWriteMask = 0xFF) : + frontWriteMask(frontWriteMask), backWriteMask(backWriteMask), enabled(enabled), _spare1{ 0 } {} + + bool isEnabled() const { return enabled; } + uint8 getWriteMaskFront() const { return frontWriteMask; } + uint8 getWriteMaskBack() const { return backWriteMask; } int32 getRaw() const { return *(reinterpret_cast<const int32*>(this)); } StencilActivation(int32 raw) { *(reinterpret_cast<int32*>(this)) = raw; } - bool operator== (const StencilActivation& right) const { return getRaw() == right.getRaw(); } - bool operator!= (const StencilActivation& right) const { return getRaw() != right.getRaw(); } + 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_OFFSET = 4; + static_assert(sizeof(StencilActivation) == sizeof(uint32_t), "StencilActivation size check"); + + struct BlendFunction { + // Using uint8 here will make the structure as a whole not align to 32 bits + uint16 enabled : 8; + BlendArg sourceColor : 4; + BlendArg sourceAlpha : 4; + BlendArg destColor : 4; + BlendArg destAlpha : 4; + BlendOp opColor : 4; + BlendOp opAlpha : 4; - uint8 _enabled; - uint8 _source; - 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)) {} + BlendArg sourceColor, + BlendOp operationColor, + BlendArg destinationColor, + BlendArg sourceAlpha, + BlendOp operationAlpha, + BlendArg destinationAlpha) : + enabled(enabled), + sourceColor(sourceColor), sourceAlpha(sourceAlpha), + destColor(destinationColor), destAlpha(destinationAlpha), + opColor(operationColor), opAlpha(operationAlpha) {} - 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)) {} + BlendFunction(bool enabled = false, BlendArg source = ONE, BlendOp operation = BLEND_OP_ADD, BlendArg destination = ZERO) : + BlendFunction(enabled, source, operation, destination, source, operation, destination) {} - bool isEnabled() const { return (_enabled != 0); } + 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 getSourceColor() const { return sourceColor; } + BlendArg getDestinationColor() const { return destColor; } + BlendOp getOperationColor() const { return opColor; } - 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); } + BlendArg getSourceAlpha() const { return sourceAlpha; } + BlendArg getDestinationAlpha() const { return destAlpha; } + BlendOp getOperationAlpha() const { return opAlpha; } int32 getRaw() const { return *(reinterpret_cast<const int32*>(this)); } BlendFunction(int32 raw) { *(reinterpret_cast<int32*>(this)) = raw; } - bool operator== (const BlendFunction& right) const { return getRaw() == right.getRaw(); } - bool operator!= (const BlendFunction& right) const { return getRaw() != right.getRaw(); } + bool operator==(const BlendFunction& right) const { return getRaw() == right.getRaw(); } + bool operator!=(const BlendFunction& right) const { return getRaw() != right.getRaw(); } }; - // 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 Data { - public: - 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; - - BlendFunction blendFunction = BlendFunction(false); - - uint8 fillMode = FILL_FACE; - uint8 cullMode = CULL_NONE; - - uint8 colorWriteMask = WRITE_ALL; + static_assert(sizeof(BlendFunction) == sizeof(uint32_t), "BlendFunction size check"); + struct Flags { + Flags() : + frontFaceClockwise(false), depthClampEnable(false), scissorEnable(false), multisampleEnable(false), + antialisedLineEnable(true), alphaToCoverageEnable(false), _spare1(0) {} bool frontFaceClockwise : 1; bool depthClampEnable : 1; bool scissorEnable : 1; bool multisampleEnable : 1; bool antialisedLineEnable : 1; bool alphaToCoverageEnable : 1; + uint8 _spare1 : 2; - Data() : - frontFaceClockwise(false), - depthClampEnable(false), - scissorEnable(false), - multisampleEnable(false), - antialisedLineEnable(true), - alphaToCoverageEnable(false) - {} + bool operator==(const Flags& right) const { return *(uint8*)this == *(uint8*)&right; } + bool operator!=(const Flags& right) const { return *(uint8*)this != *(uint8*)&right; } }; + static_assert(sizeof(Flags) == sizeof(uint8), "Flags size check"); + + // 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 Data { + public: + float depthBias = 0.0f; + float depthBiasSlopeScale = 0.0f; + + DepthTest depthTest; + StencilActivation stencilActivation; + StencilTest stencilTestFront; + StencilTest stencilTestBack; + BlendFunction blendFunction; + + uint32 sampleMask = 0xFFFFFFFF; + + FillMode fillMode = FILL_FACE; + CullMode cullMode = CULL_NONE; + ColorMask colorWriteMask = WRITE_ALL; + + Flags flags; + }; + + static_assert(offsetof(Data, depthBias) == 0, "Data offsets"); + static_assert(offsetof(Data, depthBiasSlopeScale) == 4, "Data offsets"); + static_assert(offsetof(Data, depthTest) == 8, "Data offsets"); + static_assert(offsetof(Data, stencilActivation) == 12, "Data offsets"); + static_assert(offsetof(Data, stencilTestFront) == 16, "Data offsets"); + static_assert(offsetof(Data, stencilTestBack) == 20, "Data offsets"); + static_assert(offsetof(Data, blendFunction) == 24, "Data offsets"); + static_assert(offsetof(Data, sampleMask) == 28, "Data offsets"); + static_assert(offsetof(Data, fillMode) == 32, "Data offsets"); + static_assert(offsetof(Data, cullMode) == 33, "Data offsets"); + static_assert(offsetof(Data, colorWriteMask) == 34, "Data offsets"); + static_assert(offsetof(Data, flags) == 35, "Data offsets"); + static_assert(sizeof(Data) == 36, "Data Size Check"); + + + std::string getKey() const; + // The unique default values for all the fields static const Data DEFAULT; - void setFillMode(FillMode fill) { SET_FIELD(FILL_MODE, DEFAULT.fillMode, fill, _values.fillMode); } - FillMode getFillMode() const { return FillMode(_values.fillMode); } + void setFillMode(FillMode fill) { SET_FIELD(FILL_MODE, fillMode, fill); } + FillMode getFillMode() const { return _values.fillMode; } - void setCullMode(CullMode cull) { SET_FIELD(CULL_MODE, DEFAULT.cullMode, cull, _values.cullMode); } - CullMode getCullMode() const { return CullMode(_values.cullMode); } + void setCullMode(CullMode cull) { SET_FIELD(CULL_MODE, cullMode, cull); } + CullMode getCullMode() const { return _values.cullMode; } - void setFrontFaceClockwise(bool isClockwise) { SET_FIELD(FRONT_FACE_CLOCKWISE, DEFAULT.frontFaceClockwise, isClockwise, _values.frontFaceClockwise); } - bool isFrontFaceClockwise() const { return _values.frontFaceClockwise; } + const Flags& getFlags() const { return _values.flags; } + + void setFrontFaceClockwise(bool isClockwise) { SET_FIELD(FRONT_FACE_CLOCKWISE, flags.frontFaceClockwise, isClockwise); } + bool isFrontFaceClockwise() const { return _values.flags.frontFaceClockwise; } - void setDepthClampEnable(bool enable) { SET_FIELD(DEPTH_CLAMP_ENABLE, DEFAULT.depthClampEnable, enable, _values.depthClampEnable); } - bool isDepthClampEnable() const { return _values.depthClampEnable; } + void setDepthClampEnable(bool enable) { SET_FIELD(DEPTH_CLAMP_ENABLE, flags.depthClampEnable, enable); } + bool isDepthClampEnable() const { return _values.flags.depthClampEnable; } - void setScissorEnable(bool enable) { SET_FIELD(SCISSOR_ENABLE, DEFAULT.scissorEnable, enable, _values.scissorEnable); } - bool isScissorEnable() const { return _values.scissorEnable; } + void setScissorEnable(bool enable) { SET_FIELD(SCISSOR_ENABLE, flags.scissorEnable, enable); } + bool isScissorEnable() const { return _values.flags.scissorEnable; } - void setMultisampleEnable(bool enable) { SET_FIELD(MULTISAMPLE_ENABLE, DEFAULT.multisampleEnable, enable, _values.multisampleEnable); } - bool isMultisampleEnable() const { return _values.multisampleEnable; } + void setMultisampleEnable(bool enable) { SET_FIELD(MULTISAMPLE_ENABLE, flags.multisampleEnable, enable); } + bool isMultisampleEnable() const { return _values.flags.multisampleEnable; } - void setAntialiasedLineEnable(bool enable) { SET_FIELD(ANTIALISED_LINE_ENABLE, DEFAULT.antialisedLineEnable, enable, _values.antialisedLineEnable); } - bool isAntialiasedLineEnable() const { return _values.antialisedLineEnable; } + void setAntialiasedLineEnable(bool enable) { SET_FIELD(ANTIALISED_LINE_ENABLE, flags.antialisedLineEnable, enable); } + bool isAntialiasedLineEnable() const { return _values.flags.antialisedLineEnable; } // Depth Bias - void setDepthBias(float bias) { SET_FIELD(DEPTH_BIAS, DEFAULT.depthBias, bias, _values.depthBias); } + void setDepthBias(float bias) { SET_FIELD(DEPTH_BIAS, depthBias, bias); } float getDepthBias() const { return _values.depthBias; } - void setDepthBiasSlopeScale(float scale) { SET_FIELD(DEPTH_BIAS_SLOPE_SCALE, DEFAULT.depthBiasSlopeScale, scale, _values.depthBiasSlopeScale); } + void setDepthBiasSlopeScale(float scale) { SET_FIELD(DEPTH_BIAS_SLOPE_SCALE, depthBiasSlopeScale, scale); } float getDepthBiasSlopeScale() const { return _values.depthBiasSlopeScale; } // Depth Test - 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)); } + void setDepthTest(DepthTest newDepthTest) { SET_FIELD(DEPTH_TEST, depthTest, newDepthTest); } + 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(); } @@ -310,11 +346,14 @@ public: // Stencil test void setStencilTest(bool enabled, uint8 frontWriteMask, StencilTest frontTest, uint8 backWriteMask, StencilTest backTest) { - 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); } + SET_FIELD(STENCIL_ACTIVATION, stencilActivation, StencilActivation(enabled, frontWriteMask, backWriteMask)); + SET_FIELD(STENCIL_TEST_FRONT, stencilTestFront, frontTest); + SET_FIELD(STENCIL_TEST_BACK, stencilTestBack, backTest); + } + void setStencilTest(bool enabled, uint8 frontWriteMask, StencilTest frontTest) { - setStencilTest(enabled, frontWriteMask, frontTest, frontWriteMask, frontTest); } + setStencilTest(enabled, frontWriteMask, frontTest, frontWriteMask, frontTest); + } StencilActivation getStencilActivation() const { return _values.stencilActivation; } StencilTest getStencilTestFront() const { return _values.stencilTestFront; } @@ -325,32 +364,45 @@ public: uint8 getStencilWriteMaskBack() const { return getStencilActivation().getWriteMaskBack(); } // Alpha to coverage - void setAlphaToCoverageEnable(bool enable) { SET_FIELD(ALPHA_TO_COVERAGE_ENABLE, DEFAULT.alphaToCoverageEnable, enable, _values.alphaToCoverageEnable); } - bool isAlphaToCoverageEnabled() const { return _values.alphaToCoverageEnable; } + void setAlphaToCoverageEnable(bool enable) { SET_FIELD(ALPHA_TO_COVERAGE_ENABLE, flags.alphaToCoverageEnable, enable); } + bool isAlphaToCoverageEnabled() const { return _values.flags.alphaToCoverageEnable; } // Sample mask - void setSampleMask(uint32 mask) { SET_FIELD(SAMPLE_MASK, DEFAULT.sampleMask, mask, _values.sampleMask); } + void setSampleMask(uint32 mask) { SET_FIELD(SAMPLE_MASK, sampleMask, mask); } uint32 getSampleMask() const { return _values.sampleMask; } // Blend Function - void setBlendFunction(BlendFunction function) { SET_FIELD(BLEND_FUNCTION, DEFAULT.blendFunction, function, _values.blendFunction); } - BlendFunction getBlendFunction() const { return _values.blendFunction; } + void setBlendFunction(BlendFunction function) { SET_FIELD(BLEND_FUNCTION, blendFunction, function); } + const 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 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)); } + setBlendFunction(BlendFunction(enabled, source, operation, destination)); + } bool isBlendEnabled() const { return getBlendFunction().isEnabled(); } // Color write mask - void setColorWriteMask(uint8 mask) { SET_FIELD(COLOR_WRITE_MASK, DEFAULT.colorWriteMask, mask, _values.colorWriteMask); } - void setColorWriteMask(bool red, bool green, bool blue, bool alpha) { uint32 value = ((WRITE_RED * red) | (WRITE_GREEN * green) | (WRITE_BLUE * blue) | (WRITE_ALPHA * alpha)); SET_FIELD(COLOR_WRITE_MASK, DEFAULT.colorWriteMask, value, _values.colorWriteMask); } - uint8 getColorWriteMask() const { return _values.colorWriteMask; } + void setColorWriteMask(ColorMask mask) { SET_FIELD(COLOR_WRITE_MASK, colorWriteMask, mask); } + void setColorWriteMask(bool red, bool green, bool blue, bool alpha) { + ColorMask value = (ColorMask)((WRITE_RED * red) | (WRITE_GREEN * green) | (WRITE_BLUE * blue) | (WRITE_ALPHA * alpha)); + SET_FIELD(COLOR_WRITE_MASK, colorWriteMask, value); + } + ColorMask getColorWriteMask() const { return _values.colorWriteMask; } // All the possible fields // NOTE: If you change this, you must update GLBackend::GLState::_resetStateCommands - enum Field { + enum Field + { FILL_MODE, CULL_MODE, FRONT_FACE_CLOCKWISE, @@ -376,7 +428,7 @@ public: COLOR_WRITE_MASK, - NUM_FIELDS, // not a valid field, just the count + NUM_FIELDS, // not a valid field, just the count }; // The signature of the state tells which fields of the state are not default @@ -391,20 +443,20 @@ public: State(const Data& values); const Data& getValues() const { return _values; } - const GPUObjectPointer gpuObject {}; + const GPUObjectPointer gpuObject{}; protected: State(const State& state); State& operator=(const State& state); Data _values; - Signature _signature{0}; - Stamp _stamp{0}; + Signature _signature{ 0 }; + Stamp _stamp{ 0 }; }; -typedef std::shared_ptr< State > StatePointer; -typedef std::vector< StatePointer > States; +typedef std::shared_ptr<State> StatePointer; +typedef std::vector<StatePointer> States; -}; +}; // namespace gpu #endif diff --git a/libraries/render-utils/src/StencilMaskPass.cpp b/libraries/render-utils/src/StencilMaskPass.cpp index 556e305fac..7217a3e5eb 100644 --- a/libraries/render-utils/src/StencilMaskPass.cpp +++ b/libraries/render-utils/src/StencilMaskPass.cpp @@ -42,7 +42,7 @@ gpu::PipelinePointer PrepareStencil::getMeshStencilPipeline() { auto program = gpu::Shader::createProgram(shader::gpu::program::drawNothing); auto state = std::make_shared<gpu::State>(); drawMask(*state); - state->setColorWriteMask(0); + state->setColorWriteMask(gpu::State::WRITE_NONE); _meshStencilPipeline = gpu::Pipeline::create(program, state); } @@ -54,7 +54,7 @@ gpu::PipelinePointer PrepareStencil::getPaintStencilPipeline() { auto program = gpu::Shader::createProgram(shader::render_utils::program::stencil_drawMask); auto state = std::make_shared<gpu::State>(); drawMask(*state); - state->setColorWriteMask(0); + state->setColorWriteMask(gpu::State::WRITE_NONE); _paintStencilPipeline = gpu::Pipeline::create(program, state); }