}
}
-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)
{
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;
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 *);
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 {
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();
}
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:
+++ /dev/null
-#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
public:
virtual ~Uniform() { }
- virtual void apply(int) const = 0;
virtual void store(const ReflectData::UniformInfo &, void *) const = 0;
virtual Uniform *clone() const = 0;
};
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); }
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); }
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); }
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)
-#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;
}
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
if(block.used && !block.block)
{
+ block.block = new UniformBlock(info);
if(info.bind_point>=0)
{
if(!buffer)
#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;
}
}
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);
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();
}
}
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;