]> git.tdb.fi Git - libs/gl.git/commitdiff
Store default-block uniform data in a memory block
authorMikko Rasa <tdb@tdb.fi>
Tue, 28 Sep 2021 09:29:47 +0000 (12:29 +0300)
committerMikko Rasa <tdb@tdb.fi>
Tue, 28 Sep 2021 09:46:00 +0000 (12:46 +0300)
This is more cache-friendly than using individually allocated polymorphic
objects.  It also makes it easier to use push constants in Vulkan.

source/core/pipelinestate.cpp
source/core/pipelinestate.h
source/core/program.cpp
source/core/program.h
source/core/uniform.cpp [deleted file]
source/core/uniform.h
source/core/uniformblock.cpp
source/core/uniformblock.h
source/render/programdata.cpp
source/render/programdata.h

index 1c65cda4434782623bc5e281865d800c080970bb..871336bb76b25b43b6928aa41b7384e7f0410f5b 100644 (file)
@@ -123,17 +123,7 @@ void PipelineState::set_texture(unsigned binding, const Texture *tex, const Samp
        }
 }
 
-void PipelineState::set_uniforms(const DefaultUniformBlock *block)
-{
-       set_uniform_block_(-1, block);
-}
-
-void PipelineState::set_uniform_block(unsigned binding, const BufferBackedUniformBlock *block)
-{
-       set_uniform_block_(binding, block);
-}
-
-void PipelineState::set_uniform_block_(int binding, const UniformBlock *block)
+void PipelineState::set_uniform_block(int binding, const UniformBlock *block)
 {
        auto i = lower_bound_member(uniform_blocks, binding, &BoundUniformBlock::binding);
        if(i==uniform_blocks.end() || i->binding!=binding)
@@ -283,12 +273,15 @@ void PipelineState::apply(unsigned mask) const
                                {
                                        if(u.binding>=0)
                                        {
-                                               const BufferBackedUniformBlock *block = static_cast<const BufferBackedUniformBlock *>(u.block);
-                                               glBindBufferRange(GL_UNIFORM_BUFFER, u.binding, block->get_buffer()->id, block->get_offset(), block->get_data_size());
+                                               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;
                                        }
-                                       else
-                                               static_cast<const DefaultUniformBlock *>(u.block)->apply();
+                                       else if(shprog)
+                                       {
+                                               const char *data = static_cast<const char *>(u.block->get_data_pointer());
+                                               for(const Program::UniformCall &call: shprog->uniform_calls)
+                                                       call.func(call.location, call.size, data+call.location*16);
+                                       }
                                }
 
                                u.changed = false;
index b9fac143c7b9784773970b5710de7f9bdb9e80d8..9573f9fede7eecc28a61bd7651728bb828c740cf 100644 (file)
@@ -96,11 +96,7 @@ public:
        void set_face_cull(CullMode);
        void set_enabled_clip_planes(unsigned);
        void set_texture(unsigned, const Texture *, const Sampler *);
-       void set_uniforms(const DefaultUniformBlock *);
-       void set_uniform_block(unsigned, const BufferBackedUniformBlock *);
-private:
-       void set_uniform_block_(int, const UniformBlock *);
-public:
+       void set_uniform_block(int, const UniformBlock *);
        void set_depth_test(const DepthTest *);
        void set_stencil_test(const StencilTest *);
        void set_blend(const Blend *);
index 919fceebe68eee80081116b1ab65397250056303..35304554ea33b9d0911d299522ae847755223534 100644 (file)
 
 using namespace std;
 
+namespace {
+
+template<typename T, void (*&func)(GLint, GLsizei, const T *)>
+void uniform_wrapper(unsigned index, unsigned count, const void *data)
+{
+       func(index, count, static_cast<const T *>(data));
+}
+
+template<typename T, void (*&func)(GLint, GLsizei, GLboolean, const T *)>
+void uniform_matrix_wrapper(unsigned index, unsigned count, const void *data)
+{
+       func(index, count, false, static_cast<const T *>(data));
+}
+
+}
+
 namespace Msp {
 namespace GL {
 
@@ -349,10 +365,57 @@ void Program::query_uniforms()
                                u.matrix_stride = get_type_size(get_matrix_column_type(u.type));
                        default_block.uniforms.push_back(&u);
 
-                       if(is_image(u.type) && u.location>=0)
-                               glGetUniformiv(id, u.location, &u.binding);
+                       if(u.location>=0)
+                       {
+                               UniformCall::FuncPtr func = 0;
+                               if(u.type==FLOAT)
+                                       func = &uniform_wrapper<float, glUniform1fv>;
+                               else if(u.type==FLOAT_VEC2)
+                                       func = &uniform_wrapper<float, glUniform2fv>;
+                               else if(u.type==FLOAT_VEC3)
+                                       func = &uniform_wrapper<float, glUniform3fv>;
+                               else if(u.type==FLOAT_VEC4)
+                                       func = &uniform_wrapper<float, glUniform4fv>;
+                               else if(u.type==INT)
+                                       func = &uniform_wrapper<int, glUniform1iv>;
+                               else if(u.type==INT_VEC2)
+                                       func = &uniform_wrapper<int, glUniform2iv>;
+                               else if(u.type==INT_VEC3)
+                                       func = &uniform_wrapper<int, glUniform3iv>;
+                               else if(u.type==INT_VEC4)
+                                       func = &uniform_wrapper<int, glUniform4iv>;
+                               else if(u.type==FLOAT_MAT2)
+                                       func = &uniform_matrix_wrapper<float, glUniformMatrix2fv>;
+                               else if(u.type==FLOAT_MAT3)
+                                       func = &uniform_matrix_wrapper<float, glUniformMatrix3fv>;
+                               else if(u.type==FLOAT_MAT4)
+                                       func = &uniform_matrix_wrapper<float, glUniformMatrix4fv>;
+                               else if(u.type==FLOAT_MAT2x3)
+                                       func = &uniform_matrix_wrapper<float, glUniformMatrix2x3fv>;
+                               else if(u.type==FLOAT_MAT3x2)
+                                       func = &uniform_matrix_wrapper<float, glUniformMatrix3x2fv>;
+                               else if(u.type==FLOAT_MAT2x4)
+                                       func = &uniform_matrix_wrapper<float, glUniformMatrix2x4fv>;
+                               else if(u.type==FLOAT_MAT4x2)
+                                       func = &uniform_matrix_wrapper<float, glUniformMatrix4x2fv>;
+                               else if(u.type==FLOAT_MAT3x4)
+                                       func = &uniform_matrix_wrapper<float, glUniformMatrix3x4fv>;
+                               else if(u.type==FLOAT_MAT4x3)
+                                       func = &uniform_matrix_wrapper<float, glUniformMatrix4x3fv>;
+                               else if(is_image(u.type))
+                                       glGetUniformiv(id, u.location, &u.binding);
+
+                               if(func)
+                                       uniform_calls.push_back(UniformCall(u.location, u.array_size, func));
+                       }
                }
 
+       default_block.sort_uniforms();
+       if(!default_block.uniforms.empty())
+       {
+               const ReflectData::UniformInfo &uni = *default_block.uniforms.back();
+               default_block.data_size = uni.location*16+uni.array_size*get_type_size(uni.type);
+       }
        default_block.update_layout_hash();
        reflect_data.update_layout_hash();
 }
index 6301edbe2c6e23ded094519e38f30db842ebbb55..b384defe90fa0d7904133a37bd3f66429c1f88fa 100644 (file)
@@ -63,10 +63,22 @@ private:
                std::map<unsigned, int> spec_values;
        };
 
+       struct UniformCall
+       {
+               using FuncPtr = void (*)(unsigned, unsigned, const void *);
+
+               unsigned location;
+               unsigned size;
+               FuncPtr func;
+
+               UniformCall(unsigned l, unsigned s, FuncPtr f): location(l), size(s), func(f) { }
+       };
+
        unsigned id;
        unsigned stage_ids[MAX_STAGES];
        bool linked;
        ReflectData reflect_data;
+       std::vector<UniformCall> uniform_calls;
        std::string debug_name;
 
 public:
diff --git a/source/core/uniform.cpp b/source/core/uniform.cpp
deleted file mode 100644 (file)
index c18fc36..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-#include <msp/gl/extensions/arb_shader_objects.h>
-#include <msp/gl/extensions/nv_non_square_matrices.h>
-#include "uniform.h"
-
-namespace Msp {
-namespace GL {
-
-template<>
-void UniformScalar<int>::apply(int index, unsigned size, const int *value)
-{
-       glUniform1iv(index, size, value);
-}
-
-template<>
-void UniformScalar<float>::apply(int index, unsigned size, const float *value)
-{
-       glUniform1fv(index, size, value);
-}
-
-
-template<>
-void UniformVector<int, 2>::apply(int index, unsigned size, const int *value)
-{
-       glUniform2iv(index, size, value);
-}
-
-template<>
-void UniformVector<float, 2>::apply(int index, unsigned size, const float *value)
-{
-       glUniform2fv(index, size, value);
-}
-
-template<>
-void UniformVector<int, 3>::apply(int index, unsigned size, const int *value)
-{
-       glUniform3iv(index, size, value);
-}
-
-template<>
-void UniformVector<float, 3>::apply(int index, unsigned size, const float *value)
-{
-       glUniform3fv(index, size, value);
-}
-
-template<>
-void UniformVector<int, 4>::apply(int index, unsigned size, const int *value)
-{
-       glUniform4iv(index, size, value);
-}
-
-template<>
-void UniformVector<float, 4>::apply(int index, unsigned size, const float *value)
-{
-       glUniform4fv(index, size, value);
-}
-
-
-template<>
-void UniformMatrix<float, 2, 2>::apply(int index, unsigned size, const float *value)
-{
-       glUniformMatrix2fv(index, size, false, value);
-}
-
-template<>
-void UniformMatrix<float, 2, 3>::apply(int index, unsigned size, const float *value)
-{
-       glUniformMatrix3x2fv(index, size, false, value);
-}
-
-template<>
-void UniformMatrix<float, 2, 4>::apply(int index, unsigned size, const float *value)
-{
-       glUniformMatrix4x2fv(index, size, false, value);
-}
-
-template<>
-void UniformMatrix<float, 3, 2>::apply(int index, unsigned size, const float *value)
-{
-       glUniformMatrix2x3fv(index, size, false, value);
-}
-
-template<>
-void UniformMatrix<float, 3, 3>::apply(int index, unsigned size, const float *value)
-{
-       glUniformMatrix3fv(index, size, false, value);
-}
-
-template<>
-void UniformMatrix<float, 3, 4>::apply(int index, unsigned size, const float *value)
-{
-       glUniformMatrix4x3fv(index, size, false, value);
-}
-
-template<>
-void UniformMatrix<float, 4, 2>::apply(int index, unsigned size, const float *value)
-{
-       glUniformMatrix2x4fv(index, size, false, value);
-}
-
-template<>
-void UniformMatrix<float, 4, 3>::apply(int index, unsigned size, const float *value)
-{
-       glUniformMatrix3x4fv(index, size, false, value);
-}
-
-template<>
-void UniformMatrix<float, 4, 4>::apply(int index, unsigned size, const float *value)
-{
-       glUniformMatrix4fv(index, size, false, value);
-}
-
-} // namespace GL
-} // namespace Msp
index e12f65216c82b0bf572930c7cc33e4626d4a40ea..8cdcdfda5aefea0a255533b189294e8496f7f745 100644 (file)
@@ -17,7 +17,6 @@ private:
 public:
        virtual ~Uniform() { }
 
-       virtual void apply(int) const = 0;
        virtual void store(const ReflectData::UniformInfo &, void *) const = 0;
        virtual Uniform *clone() const = 0;
 };
@@ -40,11 +39,6 @@ public:
 
        Type get() const { return value; }
 
-       virtual void apply(int index) const
-       { apply(index, 1, &value); }
-
-       static void apply(int, unsigned, const T *);
-
        virtual void store(const ReflectData::UniformInfo &info, void *buffer) const
        { store(info, buffer, &value); }
 
@@ -77,11 +71,6 @@ public:
 
        BaseType get(unsigned i) const { return value[i]; }
 
-       virtual void apply(int index) const
-       { apply(index, 1, value); }
-
-       static void apply(int index, unsigned size, const T *value);
-
        virtual void store(const ReflectData::UniformInfo &info, void *buffer) const
        { store(info, buffer, value); }
 
@@ -116,11 +105,6 @@ public:
        void set(const T *vp)
        { std::copy(vp, vp+rows*cols, value); }
 
-       virtual void apply(int index) const
-       { apply(index, 1, value); }
-
-       static void apply(int index, unsigned size, const T *value);
-
        virtual void store(const ReflectData::UniformInfo &info, void *buffer) const
        { store(info, buffer, value); }
 
@@ -174,9 +158,6 @@ public:
        void set(const BaseType *vp)
        { std::copy(vp, vp+elemsize*size_, values); }
 
-       virtual void apply(int index) const
-       { T::apply(index, size_, values); }
-
        virtual void store(const ReflectData::UniformInfo &info, void *buffer) const
        {
                for(unsigned i=0; i<size_; ++i)
index 4b07241fab3943d14f35932ea498024bdc5ad2d2..f713bd2af5d320541b27f114b9a4cad719528231 100644 (file)
@@ -1,4 +1,3 @@
-#include <stdexcept>
 #include <msp/gl/extensions/arb_shader_objects.h>
 #include <msp/gl/extensions/arb_uniform_buffer_object.h>
 #include "buffer.h"
 #include "uniformblock.h"
 #include "vector.h"
 
-using namespace std;
-
 namespace Msp {
 namespace GL {
 
-DefaultUniformBlock::DefaultUniformBlock()
+UniformBlock::UniformBlock(const ReflectData::UniformBlockInfo &info):
+       data(info.data_size)
 {
        static Require _req(ARB_shader_objects);
+       if(info.bind_point>=0)
+               static Require _req2(ARB_uniform_buffer_object);
 }
 
-void DefaultUniformBlock::attach(const ReflectData::UniformInfo &info, const Uniform &uni)
-{
-       if(info.block->bind_point>=0)
-               throw invalid_argument("DefaultUniformBlock::attach");
-
-       attach(info.location, uni);
-}
-
-void DefaultUniformBlock::attach(int index, const Uniform &uni)
-{
-       if(index<0)
-               return;
-
-       if(static_cast<unsigned>(index)>=uniforms.size())
-               uniforms.resize(index+1, 0);
-       uniforms[index] = &uni;
-}
-
-void DefaultUniformBlock::apply() const
-{
-       for(unsigned i=0; i<uniforms.size(); ++i)
-               if(uniforms[i])
-                       uniforms[i]->apply(i);
-}
-
-
-BufferBackedUniformBlock::BufferBackedUniformBlock(unsigned s):
-       size(s),
-       data(size)
-{
-       static Require _req(ARB_shader_objects);
-       static Require _req2(ARB_uniform_buffer_object);
-
-       if(!size)
-               throw invalid_argument("BufferBackedUniformBlock::BufferBackedUniformBlock");
-}
-
-unsigned BufferBackedUniformBlock::get_alignment() const
+unsigned UniformBlock::get_alignment() const
 {
        return Limits::get_global().uniform_buffer_alignment;
 }
 
-void BufferBackedUniformBlock::attach(const ReflectData::UniformInfo &info, const Uniform &uni)
+void UniformBlock::store(const ReflectData::UniformInfo &info, const Uniform &uni)
 {
        if(info.block->bind_point<0)
-               throw invalid_argument("BufferBackedUniformBlock::attach");
-
-       uni.store(info, &data[info.offset]);
+       {
+               if(info.location<0)
+                       return;
+               uni.store(info, &data[info.location*16]);
+       }
+       else
+               uni.store(info, &data[info.offset]);
        dirty = true;
 }
 
index 08eaa9b857e3dcbc1c8de08e7a129433dbc6b0ee..9f2a0849e9cca10795c759456dc12fcf6405a386 100644 (file)
@@ -20,50 +20,21 @@ struct Color;
 Stores uniforms with a specific layout.  Both named and default uniform blocks
 are supported.
 */
-class UniformBlock: public NonCopyable
-{
-protected:
-       UniformBlock() { }
-public:
-       virtual ~UniformBlock() { }
-
-       virtual void attach(const ReflectData::UniformInfo &, const Uniform &) = 0;
-};
-
-/** Stores uniforms for the default uniform block.  Uniforms are associated
-with locations, as returned by Program::get_uniform_location. */
-class DefaultUniformBlock: public UniformBlock
-{
-private:
-       std::vector<const Uniform *> uniforms;
-
-public:
-       DefaultUniformBlock();
-
-       virtual void attach(const ReflectData::UniformInfo &, const Uniform &);
-       void attach(int, const Uniform &);
-       void apply() const;
-};
-
-/** Stores uniforms for a buffer-backed uniform block.  Uniform values are
-stored in a memory block which can be uploaded into a buffer and bound for use
-by a Program. */
-class BufferBackedUniformBlock: public UniformBlock, public Bufferable
+class UniformBlock: public NonCopyable, public Bufferable
 {
 private:
-       unsigned size;
        std::vector<char> data;
 
 public:
-       BufferBackedUniformBlock(unsigned);
+       UniformBlock(const ReflectData::UniformBlockInfo &);
 
-       virtual unsigned get_data_size() const { return size; }
-private:
+       virtual unsigned get_data_size() const { return data.size(); }
        virtual const void *get_data_pointer() const { return &data[0]; }
+private:
        virtual unsigned get_alignment() const;
 
 public:
-       void attach(const ReflectData::UniformInfo &, const Uniform &);
+       void store(const ReflectData::UniformInfo &, const Uniform &);
 };
 
 } // namespace GL
index 65934d382ae29fad792c0b67031a406658b7b3fb..377b5ace09eb9632eadac8410bfa675bd5f9a13f 100644 (file)
@@ -564,6 +564,7 @@ void ProgramData::update_block_uniform_indices(SharedBlock &block, const Reflect
 
        if(block.used && !block.block)
        {
+               block.block = new UniformBlock(info);
                if(info.bind_point>=0)
                {
                        if(!buffer)
@@ -576,13 +577,9 @@ void ProgramData::update_block_uniform_indices(SharedBlock &block, const Reflect
 #endif
                        }
 
-                       BufferBackedUniformBlock *bb_block = new BufferBackedUniformBlock(info.data_size);
-                       block.block = bb_block;
-                       bb_block->use_buffer(buffer, last_buffer_block);
-                       last_buffer_block = bb_block;
+                       block.block->use_buffer(buffer, last_buffer_block);
+                       last_buffer_block = block.block;
                }
-               else
-                       block.block = new DefaultUniformBlock;
        }
 }
 
@@ -594,13 +591,13 @@ void ProgramData::update_block(SharedBlock &block, const ReflectData::UniformBlo
                if(is_image(info.uniforms[i]->type))
                        ;  // Temporarily ignore deprecated use of sampler uniforms in ProgramData
                else if(indices[i]!=0xFF)
-                       block.block->attach(*info.uniforms[i], *uniforms[indices[i]].value);
+                       block.block->store(*info.uniforms[i], *uniforms[indices[i]].value);
        }
 }
 
 vector<ProgramData::ProgramBlock>::const_iterator ProgramData::prepare_program(const Program &prog) const
 {
-       BufferBackedUniformBlock *old_last_block = last_buffer_block;
+       UniformBlock *old_last_block = last_buffer_block;
        auto prog_begin = get_program(prog);
 
        Mask force_dirty = (dirty==ALL_ONES ? ALL_ONES : 0U);
@@ -688,14 +685,9 @@ void ProgramData::apply(const Program &prog, PipelineState &state) const
        for(auto i=prog_begin+1; (i!=programs.end() && i->prog_hash==prog_hash); ++i)
                if(i->block)
                {
-                       if(i->bind_point<0)
-                               state.set_uniforms(static_cast<const DefaultUniformBlock *>(i->block));
-                       else
-                       {
-                               const BufferBackedUniformBlock *block = static_cast<const BufferBackedUniformBlock *>(i->block);
-                               block->refresh();
-                               state.set_uniform_block(i->bind_point, block);
-                       }
+                       state.set_uniform_block(i->bind_point, i->block);
+                       if(i->bind_point>=0)
+                               i->block->refresh();
                }
 }
 
index 380f352a66376b6b168805bea5f6c46f4ee0cae5..05e1bedc199eb78e7f29f9a4d6b75df9377505e3 100644 (file)
@@ -157,7 +157,7 @@ private:
        unsigned generation;
        mutable std::vector<SharedBlock> blocks;
        mutable std::vector<ProgramBlock> programs;
-       mutable BufferBackedUniformBlock *last_buffer_block;
+       mutable UniformBlock *last_buffer_block;
        mutable Buffer *buffer;
        mutable Mask dirty;
        std::string debug_name;