prev_in_buffer->next_in_buffer = this;
}
- update_buffer_offsets();
+ update_buffer_offset();
}
void Bufferable::unlink_from_buffer()
if(next_in_buffer)
{
next_in_buffer->prev_in_buffer = prev_in_buffer;
- next_in_buffer->update_buffer_offsets();
+ next_in_buffer->update_buffer_offset();
}
prev_in_buffer = 0;
next_in_buffer = 0;
}
-void Bufferable::update_buffer_offsets()
+void Bufferable::update_buffer_offset()
{
unsigned offset = 0;
if(prev_in_buffer)
{
buffer_offset = offset;
dirty = true;
+ offset_changed();
}
if(next_in_buffer)
- next_in_buffer->update_buffer_offsets();
+ next_in_buffer->update_buffer_offset();
+
+ /* Do not resize the buffer here, as the offsets may change multiple times
+ before the buffer is actually used */
}
void Bufferable::update_buffer_data() const
for(const Bufferable *b=first; b; b=b->next_in_buffer)
total_size += b->get_data_size();
- buffer->data(total_size, 0);
- for(const Bufferable *b=first; b; b=b->next_in_buffer)
+ if(total_size!=buffer->get_size())
{
- buffer->sub_data(b->buffer_offset, b->get_data_size(), b->get_data());
- b->dirty = false;
+ buffer->data(total_size, 0);
+ // Resizing the buffer invalidates its contents.
+ for(const Bufferable *b=first; b; b=b->next_in_buffer)
+ b->dirty = true;
}
+
+ upload_data();
+ dirty = false;
}
} // namespace GL
protected:
virtual unsigned get_data_size() const = 0;
- virtual const void *get_data() const = 0;
- void update_buffer_offsets();
+ void update_buffer_offset();
+ virtual void offset_changed() { }
+
void update_buffer_data() const;
+ virtual void upload_data() const = 0;
};
} // namespace GL
buf_range(0)
{ }
+UniformBlock::~UniformBlock()
+{
+ delete buf_range;
+}
+
+void UniformBlock::offset_changed()
+{
+ delete buf_range;
+ buf_range = 0;
+}
+
+void UniformBlock::upload_data() const
+{
+ if(!buf_range)
+ buf_range = new BufferRange(*buffer, buffer_offset, size);
+ buf_range->data(&data[0]);
+}
+
void UniformBlock::attach(int index, const Uniform &uni)
{
uniforms[index] = &uni;
if(buffer)
{
if(dirty)
- {
update_buffer_data();
- if(!buf_range)
- buf_range = new BufferRange(*buffer, buffer_offset, size);
- }
buf_range->bind_to(UNIFORM_BUFFER, index);
}
else
public:
UniformBlock();
UniformBlock(unsigned);
+ ~UniformBlock();
private:
- virtual const void *get_data() const { return &data[0]; }
virtual unsigned get_data_size() const { return size; }
+ virtual void offset_changed();
+ virtual void upload_data() const;
public:
void attach(int, const Uniform &);