namespace Msp {
namespace GL {
-UniformBlock::UniformBlock():
- size(0),
- buf_range(0)
+DefaultUniformBlock::DefaultUniformBlock()
{
static Require _req(ARB_shader_objects);
}
-UniformBlock::UniformBlock(unsigned s):
+void DefaultUniformBlock::attach(const Program::UniformInfo &info, const Uniform &uni)
+{
+ if(info.block->bind_point>=0)
+ throw invalid_argument("DefaultUniformBlock::attach");
+
+ uniforms[info.location] = &uni;
+}
+
+void DefaultUniformBlock::attach(int index, const Uniform &uni)
+{
+ uniforms[index] = &uni;
+}
+
+void DefaultUniformBlock::apply(int index) const
+{
+ if(index>=0)
+ throw invalid_argument("DefaultUniformBlock::apply");
+
+ for(map<int, const Uniform *>::const_iterator i=uniforms.begin(); i!=uniforms.end(); ++i)
+ i->second->apply(i->first);
+}
+
+
+BufferBackedUniformBlock::BufferBackedUniformBlock(unsigned s):
size(s),
+ data(size),
buf_range(0)
{
- static Require _req(ARB_uniform_buffer_object);
+ static Require _req(ARB_shader_objects);
+ static Require _req2(ARB_uniform_buffer_object);
if(!size)
- throw invalid_argument("UniformBlock::UniformBlock");
- data.resize(size);
+ throw invalid_argument("BufferBackedUniformBlock::BufferBackedUniformBlock");
}
-UniformBlock::~UniformBlock()
+BufferBackedUniformBlock::~BufferBackedUniformBlock()
{
delete buf_range;
}
-unsigned UniformBlock::get_alignment() const
+unsigned BufferBackedUniformBlock::get_alignment() const
{
return BufferRange::get_uniform_buffer_alignment();
}
-void UniformBlock::location_changed(Buffer *buf, unsigned off, unsigned) const
+void BufferBackedUniformBlock::location_changed(Buffer *buf, unsigned off, unsigned) const
{
delete buf_range;
- buf_range = new BufferRange(*buf, off, size);
+ buf_range = buf->create_range(off, size);
}
-void UniformBlock::attach(int index, const Uniform &uni)
+void BufferBackedUniformBlock::attach(const Program::UniformInfo &info, const Uniform &uni)
{
- if(size)
- throw invalid_operation("UniformBlock::attach");
+ if(info.block->bind_point<0)
+ throw invalid_argument("BufferBackedUniformBlock::attach");
- uniforms[index] = &uni;
-}
-
-void UniformBlock::attach(const Program::UniformInfo &info, const Uniform &uni)
-{
- if(size)
- {
- uni.store(info, &data[info.offset]);
- dirty = true;
- }
- else
- uniforms[info.location] = &uni;
+ uni.store(info, &data[info.offset]);
+ dirty = true;
}
-void UniformBlock::apply(int index) const
+void BufferBackedUniformBlock::apply(int index) const
{
- if((index>=0) != (size>0))
+ if(index<0)
+ throw invalid_argument("BufferBackedUniformBlock::apply");
+ if(!get_buffer())
throw invalid_operation("UniformBlock::apply");
- if(size)
- {
- if(!get_buffer())
- throw invalid_operation("UniformBlock::apply");
-
- refresh();
- buf_range->bind_to(UNIFORM_BUFFER, index);
- }
- else
- {
- for(map<int, const Uniform *>::const_iterator i=uniforms.begin(); i!=uniforms.end(); ++i)
- i->second->apply(i->first);
- }
+ refresh();
+ buf_range->bind_to(UNIFORM_BUFFER, index);
}
} // namespace GL
Stores uniforms with a specific layout. Both named and default uniform blocks
are supported.
*/
-class UniformBlock: public Bufferable
+class UniformBlock: public NonCopyable
+{
+protected:
+ UniformBlock() { }
+public:
+ virtual ~UniformBlock() { }
+
+ virtual void attach(const Program::UniformInfo &, const Uniform &) = 0;
+ virtual void apply(int) const = 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::map<int, const Uniform *> uniforms;
+
+public:
+ DefaultUniformBlock();
+
+ virtual void attach(const Program::UniformInfo &, const Uniform &);
+ void attach(int, const Uniform &);
+ virtual void apply(int) 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
+{
+private:
unsigned size;
std::vector<char> data;
mutable BufferRange *buf_range;
- UniformBlock(const UniformBlock &);
- UniformBlock &operator=(const UniformBlock &);
public:
- UniformBlock();
- UniformBlock(unsigned);
- ~UniformBlock();
+ BufferBackedUniformBlock(unsigned);
+ virtual ~BufferBackedUniformBlock();
private:
virtual unsigned get_data_size() const { return size; }
virtual void location_changed(Buffer *, unsigned, unsigned) const;
public:
- void attach(int, const Uniform &);
void attach(const Program::UniformInfo &, const Uniform &);
-
- void apply(int) const;
+ virtual void apply(int) const;
};
} // namespace GL
ProgramData::ProgramData(const Program *p):
tied_program(p),
- last_block(0),
+ last_buffer_block(0),
buffer(0),
dirty(0)
{ }
ProgramData::ProgramData(const ProgramData &other):
tied_program(other.tied_program),
uniforms(other.uniforms),
- last_block(0),
+ last_buffer_block(0),
buffer(0),
dirty(0)
{
ProgramData::ProgramData(const ProgramData &other, const Program *p):
tied_program(p),
- last_block(0),
+ last_buffer_block(0),
buffer(0),
dirty(0)
{
delete i->block;
programs.clear();
- last_block = 0;
+ last_buffer_block = 0;
buffer = 0;
dirty = 0;
if(!buffer)
buffer = new Buffer(UNIFORM_BUFFER);
- block.block = new UniformBlock(info.data_size);
- block.block->use_buffer(buffer, last_block);
- last_block = block.block;
+ 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;
}
else
- block.block = new UniformBlock;
+ block.block = new DefaultUniformBlock;
}
}
if(!prog)
throw invalid_operation("ProgramData::apply");
- UniformBlock *old_last_block = last_block;
+ BufferBackedUniformBlock *old_last_block = last_buffer_block;
vector<ProgramBlock>::iterator prog_begin = get_program(*prog);
Program::LayoutHash prog_hash = prog->get_uniform_layout_hash();
if(buffered_blocks_updated && !ARB_direct_state_access)
buffer->bind();
- if(last_block!=old_last_block)
+ if(last_buffer_block!=old_last_block)
{
- unsigned required_size = last_block->get_required_buffer_size();
- if(last_block->get_required_buffer_size()>buffer->get_size())
+ unsigned required_size = last_buffer_block->get_required_buffer_size();
+ if(last_buffer_block->get_required_buffer_size()>buffer->get_size())
{
if(buffer->get_size()>0)
{
delete buffer;
buffer = new Buffer(UNIFORM_BUFFER);
- last_block->change_buffer(buffer);
+ last_buffer_block->change_buffer(buffer);
}
buffer->storage(required_size);
};
class Buffer;
+class BufferBackedUniformBlock;
class Uniform;
class UniformBlock;
struct Color;
std::vector<TaggedUniform> uniforms;
mutable std::vector<SharedBlock> blocks;
mutable std::vector<ProgramBlock> programs;
- mutable UniformBlock *last_block;
+ mutable BufferBackedUniformBlock *last_buffer_block;
mutable Buffer *buffer;
mutable Mask dirty;