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);
     }