]> git.tdb.fi Git - libs/gl.git/commitdiff
Refactor low-level state management
authorMikko Rasa <tdb@tdb.fi>
Thu, 18 Nov 2021 10:09:57 +0000 (12:09 +0200)
committerMikko Rasa <tdb@tdb.fi>
Thu, 18 Nov 2021 10:27:32 +0000 (12:27 +0200)
The global context state is now held in Device.

The changes mask in PipelineState was also moved to the backend class,
because pipeline state is applied very differently in Vulkan.

source/backends/opengl/buffer_backend.cpp
source/backends/opengl/buffer_backend.h
source/backends/opengl/device_backend.cpp
source/backends/opengl/device_backend.h
source/backends/opengl/pipelinestate_backend.cpp
source/backends/opengl/pipelinestate_backend.h
source/backends/opengl/texture_backend.cpp
source/backends/opengl/texture_backend.h
source/core/pipelinestate.h

index e0f5525a9a2b211f8b2f5367ee78379aa8415146..13944a86d439231e93603b84454fceed5f781900 100644 (file)
@@ -6,14 +6,13 @@
 #include <msp/gl/extensions/oes_mapbuffer.h>
 #include "buffer.h"
 #include "buffer_backend.h"
+#include "device.h"
 
 using namespace std;
 
 namespace Msp {
 namespace GL {
 
-OpenGLBuffer *OpenGLBuffer::scratch_binding = 0;
-
 OpenGLBuffer::OpenGLBuffer()
 {
        static Require _req(ARB_vertex_buffer_object);
@@ -32,7 +31,7 @@ OpenGLBuffer::OpenGLBuffer(OpenGLBuffer &&other):
 
 OpenGLBuffer::~OpenGLBuffer()
 {
-       if(this==scratch_binding)
+       if(this==Device::get_current().get_state().scratch_buffer)
                unbind_scratch();
        if(id)
                glDeleteBuffers(1, &id);
@@ -115,6 +114,7 @@ void OpenGLBuffer::set_debug_name(const string &name)
 
 void OpenGLBuffer::bind_scratch()
 {
+       const OpenGLBuffer *&scratch_binding = Device::get_current().get_state().scratch_buffer;
        if(scratch_binding!=this)
        {
                glBindBuffer(GL_ARRAY_BUFFER, id);
@@ -124,6 +124,7 @@ void OpenGLBuffer::bind_scratch()
 
 void OpenGLBuffer::unbind_scratch()
 {
+       const OpenGLBuffer *&scratch_binding = Device::get_current().get_state().scratch_buffer;
        if(scratch_binding)
        {
                glBindBuffer(GL_ARRAY_BUFFER, 0);
index 6595ec2a65e0c63c79a2b09ca9271cf4486340be..3d76c01a0a5d4bd1de107dc99c58aa5ae66fc454 100644 (file)
@@ -15,8 +15,6 @@ class OpenGLBuffer: public NonCopyable
 protected:
        unsigned id = 0;
 
-       static OpenGLBuffer *scratch_binding;
-
        OpenGLBuffer();
        OpenGLBuffer(OpenGLBuffer &&);
        ~OpenGLBuffer();
index 35c0ca5c244d71573979171a1d2de85b2ccad55d..7819c98fe68e6d92f095a9edfc3ea2919e0cf48a 100644 (file)
@@ -87,6 +87,9 @@ void OpenGLDevice::fill_info()
        feat.ext_texture_array = EXT_texture_array;
        feat.uniform_binding_range = lim.max_uniform_bindings;
        feat.texture_binding_range = lim.max_texture_bindings;
+
+       state.bound_tex_targets.resize(lim.max_texture_bindings);
+       state.bound_uniform_blocks.resize(lim.max_uniform_bindings);
 }
 
 } // namespace GL
index dfa16653167d979d40279026fb743c57a0f75a3b..491f1b3173a3aefc3a4da3d07b0123a7c69d64e6 100644 (file)
@@ -1,16 +1,33 @@
 #ifndef MSP_GL_DEVICE_BACKEND_H_
 #define MSP_GL_DEVICE_BACKEND_H_
 
+#include <vector>
 #include <msp/core/noncopyable.h>
 #include <msp/graphics/glcontext.h>
 
 namespace Msp {
 namespace GL {
 
+class OpenGLBuffer;
+class OpenGLPipelineState;
+class OpenGLTexture;
+
+struct OpenGLDeviceState
+{
+       const OpenGLPipelineState *last_pipeline = 0;
+       std::vector<int> bound_tex_targets;
+       std::vector<char> bound_uniform_blocks;
+       unsigned restart_index = 0;
+       unsigned n_clip_distances = 0;
+       const OpenGLBuffer *scratch_buffer = 0;
+       const OpenGLTexture *scratch_texture = 0;
+};
+
 class OpenGLDevice: public NonCopyable
 {
 protected:
        Graphics::GLContext context;
+       OpenGLDeviceState state;
 
        OpenGLDevice(Graphics::Window &, const Graphics::GLOptions &);
 
@@ -19,6 +36,9 @@ protected:
        void fill_info();
 
        Graphics::GLContext &get_context() { return context; }
+
+public:
+       OpenGLDeviceState &get_state() { return state; }
 };
 
 using DeviceBackend = OpenGLDevice;
index 19ee0f58f0a1788a27b46b1a326c41eafc133ca0..9616b18be326d99cbccdfa0c30ad0f195732a60f 100644 (file)
@@ -26,37 +26,34 @@ using namespace std;
 namespace Msp {
 namespace GL {
 
-const OpenGLPipelineState *OpenGLPipelineState::last_applied = 0;
-vector<int> OpenGLPipelineState::bound_tex_targets;
-vector<char> OpenGLPipelineState::bound_uniform_blocks;
-unsigned OpenGLPipelineState::restart_index = 0;
-unsigned OpenGLPipelineState::n_clip_distances = 0;
-
-OpenGLPipelineState::OpenGLPipelineState()
-{
-       if(bound_tex_targets.empty())
-               bound_tex_targets.resize(Device::get_current().get_info().limits.max_texture_bindings);
-       if(bound_uniform_blocks.empty())
-               bound_uniform_blocks.resize(Device::get_current().get_info().limits.max_uniform_bindings);
-}
-
 OpenGLPipelineState::~OpenGLPipelineState()
 {
-       if(this==last_applied)
-               last_applied = 0;
+       if(applied_to)
+               applied_to->get_state().last_pipeline = 0;
 }
 
 void OpenGLPipelineState::apply() const
 {
-       if(!last_applied)
-               OpenGLTexture::unbind_scratch();
+       const PipelineState &self = *static_cast<const PipelineState *>(this);
+       Device &device = Device::get_current();
+       unsigned mask = changes;
 
-       apply(this==last_applied ? static_cast<const PipelineState *>(this)->changes : ~0U);
-}
+       if(applied_to && applied_to!=&device)
+       {
+               applied_to->get_state().last_pipeline = 0;
+               mask = ~0U;
+       }
 
-void OpenGLPipelineState::apply(unsigned mask) const
-{
-       const PipelineState &self = *static_cast<const PipelineState *>(this);
+       OpenGLDeviceState &dev_state = device.get_state();
+       if(!dev_state.last_pipeline)
+               OpenGLTexture::unbind_scratch();
+       
+       if(this!=dev_state.last_pipeline)
+       {
+               if(dev_state.last_pipeline)
+                       dev_state.last_pipeline->applied_to = 0;
+               mask = ~0U;
+       }
 
        if(mask&PipelineState::FRAMEBUFFER)
        {
@@ -93,16 +90,16 @@ void OpenGLPipelineState::apply(unsigned mask) const
                glUseProgram(self.shprog ? self.shprog->id : 0);
 
                unsigned ncd = (self.shprog ? self.shprog->get_n_clip_distances() : 0);
-               if(ncd!=n_clip_distances)
+               if(ncd!=dev_state.n_clip_distances)
                {
-                       for(unsigned i=0; (i<ncd || i<n_clip_distances); ++i)
+                       for(unsigned i=0; (i<ncd || i<dev_state.n_clip_distances); ++i)
                        {
                                if(i<ncd)
                                        glEnable(GL_CLIP_PLANE0+i);
                                else
                                        glDisable(GL_CLIP_PLANE0+i);
                        }
-                       n_clip_distances = ncd;
+                       dev_state.n_clip_distances = ncd;
                }
        }
 
@@ -116,7 +113,7 @@ void OpenGLPipelineState::apply(unsigned mask) const
                                        if(u.binding>=0)
                                        {
                                                glBindBufferRange(GL_UNIFORM_BUFFER, u.binding, u.block->get_buffer()->id, u.block->get_offset(), u.block->get_data_size());
-                                               bound_uniform_blocks[u.binding] = 1;
+                                               dev_state.bound_uniform_blocks[u.binding] = 1;
                                        }
                                        else if(u.binding==ReflectData::DEFAULT_BLOCK && self.shprog)
                                        {
@@ -142,12 +139,12 @@ void OpenGLPipelineState::apply(unsigned mask) const
                                        else
                                        {
                                                glActiveTexture(GL_TEXTURE0+t.binding);
-                                               if(bound_tex_targets[t.binding] && static_cast<int>(t.texture->target)!=bound_tex_targets[t.binding])
-                                                       glBindTexture(bound_tex_targets[t.binding], 0);
+                                               if(dev_state.bound_tex_targets[t.binding] && static_cast<int>(t.texture->target)!=dev_state.bound_tex_targets[t.binding])
+                                                       glBindTexture(dev_state.bound_tex_targets[t.binding], 0);
                                                glBindTexture(t.texture->target, t.texture->id);
                                        }
 
-                                       bound_tex_targets[t.binding] = t.texture->target;
+                                       dev_state.bound_tex_targets[t.binding] = t.texture->target;
 
                                        glBindSampler(t.binding, t.sampler->id);
                                        t.sampler->refresh();
@@ -167,12 +164,12 @@ void OpenGLPipelineState::apply(unsigned mask) const
 
                        vertex_setup->refresh();
                        unsigned ri = (vertex_setup->get_index_type()==UNSIGNED_INT ? 0xFFFFFFFF : 0xFFFF);
-                       if(ri!=restart_index)
+                       if(ri!=dev_state.restart_index)
                        {
-                               if(!restart_index)
+                               if(!dev_state.restart_index)
                                        glEnable(GL_PRIMITIVE_RESTART);
                                glPrimitiveRestartIndex(ri);
-                               restart_index = ri;
+                               dev_state.restart_index = ri;
                        }
                }
        }
@@ -236,39 +233,41 @@ void OpenGLPipelineState::apply(unsigned mask) const
                }
        }
 
-       last_applied = this;
-       self.changes &= ~mask;
+       applied_to = &device;
+       dev_state.last_pipeline = this;
+       changes = 0;
 }
 
 void OpenGLPipelineState::clear()
 {
-       if(last_applied)
+       OpenGLDeviceState &dev_state = Device::get_current().get_state();
+       if(dev_state.last_pipeline)
        {
                glUseProgram(0);
                glBindVertexArray(0);
 
-               for(unsigned i=0; i<n_clip_distances; ++i)
+               for(unsigned i=0; i<dev_state.n_clip_distances; ++i)
                        glDisable(GL_CLIP_PLANE0+i);
-               n_clip_distances = 0;
+               dev_state.n_clip_distances = 0;
 
-               for(unsigned i=0; i<bound_tex_targets.size(); ++i)
-                       if(bound_tex_targets[i])
+               for(unsigned i=0; i<dev_state.bound_tex_targets.size(); ++i)
+                       if(dev_state.bound_tex_targets[i])
                        {
                                if(ARB_direct_state_access)
                                        glBindTextureUnit(i, 0);
                                else
                                {
                                        glActiveTexture(GL_TEXTURE0+i);
-                                       glBindTexture(bound_tex_targets[i], 0);
+                                       glBindTexture(dev_state.bound_tex_targets[i], 0);
                                }
-                               bound_tex_targets[i] = 0;
+                               dev_state.bound_tex_targets[i] = 0;
                        }
 
-               for(unsigned i=0; i<bound_uniform_blocks.size(); ++i)
-                       if(bound_uniform_blocks[i])
+               for(unsigned i=0; i<dev_state.bound_uniform_blocks.size(); ++i)
+                       if(dev_state.bound_uniform_blocks[i])
                        {
                                glBindBufferBase(GL_UNIFORM_BUFFER, i, 0);
-                               bound_uniform_blocks[i] = 0;
+                               dev_state.bound_uniform_blocks[i] = 0;
                        }
 
                glDisable(GL_DEPTH_TEST);
@@ -276,7 +275,8 @@ void OpenGLPipelineState::clear()
                glDisable(GL_STENCIL_TEST);
                glDisable(GL_BLEND);
 
-               last_applied = 0;
+               dev_state.last_pipeline->applied_to = 0;
+               dev_state.last_pipeline = 0;
        }
 }
 
index 566b819c086cbadf120ef232dddd662cabd61a26..a8f2d306109109f440661b066410bb947973940f 100644 (file)
@@ -7,25 +7,22 @@
 namespace Msp {
 namespace GL {
 
+class Device;
+
 class OpenGLPipelineState: public NonCopyable
 {
        friend class OpenGLCommands;
 
 protected:
-       static const OpenGLPipelineState *last_applied;
-       static std::vector<int> bound_tex_targets;
-       static std::vector<char> bound_uniform_blocks;
-       static unsigned restart_index;
-       static unsigned n_clip_distances;
+       mutable Device *applied_to = 0;
+       mutable unsigned changes = 0;
 
-       OpenGLPipelineState();
+       OpenGLPipelineState() = default;
        OpenGLPipelineState(OpenGLPipelineState &&) { }
        ~OpenGLPipelineState();
 
        void apply() const;
-private:
-       void apply(unsigned) const;
-protected:
+
        static void clear();
 };
 
index ebfeb0255b2083d8a04b8b49ff0503302e361333..818defdd44c475a103b96adcf2ac20d8acb7f12e 100644 (file)
@@ -2,6 +2,7 @@
 #include <msp/gl/extensions/arb_texture_swizzle.h>
 #include <msp/gl/extensions/ext_framebuffer_object.h>
 #include <msp/gl/extensions/khr_debug.h>
+#include "device.h"
 #include "gl.h"
 #include "error.h"
 #include "texture.h"
@@ -12,8 +13,6 @@ using namespace std;
 namespace Msp {
 namespace GL {
 
-OpenGLTexture *OpenGLTexture::scratch_binding = 0;
-
 OpenGLTexture::OpenGLTexture(unsigned t):
        target(t)
 {
@@ -35,7 +34,7 @@ OpenGLTexture::OpenGLTexture(OpenGLTexture &&other):
 
 OpenGLTexture::~OpenGLTexture()
 {
-       if(this==scratch_binding)
+       if(this==Device::get_current().get_state().scratch_texture)
                unbind_scratch();
        if(id)
                glDeleteTextures(1, &id);
@@ -119,6 +118,7 @@ void OpenGLTexture::set_debug_name(const string &name)
 
 void OpenGLTexture::bind_scratch()
 {
+       const OpenGLTexture *&scratch_binding = Device::get_current().get_state().scratch_texture;
        if(!scratch_binding)
                glActiveTexture(GL_TEXTURE0);
        if(scratch_binding!=this)
@@ -132,6 +132,7 @@ void OpenGLTexture::bind_scratch()
 
 void OpenGLTexture::unbind_scratch()
 {
+       const OpenGLTexture *&scratch_binding = Device::get_current().get_state().scratch_texture;
        if(scratch_binding)
        {
                glBindTexture(scratch_binding->target, 0);
index ecb3056fd2ead2cd0f7bcf86fd568a7aa61b502a..623bd813291771ec39a10c5bdfbb501a49ee44c8 100644 (file)
@@ -16,8 +16,6 @@ protected:
        unsigned target;
        std::string debug_name;
 
-       static OpenGLTexture *scratch_binding;
-
        OpenGLTexture(unsigned);
        OpenGLTexture(OpenGLTexture &&);
        ~OpenGLTexture();
index 0973bfb5ba16a4c7d04f6f54844ea677149c6c25..5e59330953e9e29f179323a9001b7487da2d65fa 100644 (file)
@@ -79,7 +79,6 @@ private:
        const DepthTest *depth_test = 0;
        const StencilTest *stencil_test = 0;
        const Blend *blend = 0;
-       mutable unsigned changes = 0;
 
        template<typename T>
        void set(T &, T, unsigned);