tied_program(p)
{ }
-// Blocks are intentionally left uncopied
-ProgramData::ProgramData(const ProgramData &other):
- tied_program(other.tied_program),
- uniforms(other.uniforms),
- uniform_data(other.uniform_data),
- generation(other.generation)
-{ }
-
-ProgramData::ProgramData(const ProgramData &other, const Program *p):
- tied_program(p)
-{
- if(tied_program)
- {
- for(const TaggedUniform &u: other.uniforms)
- validate_tag(u.tag);
- }
-
- uniforms = other.uniforms;
- uniform_data = other.uniform_data;
-}
-
-ProgramData &ProgramData::operator=(const ProgramData &other)
-{
- tied_program = other.tied_program;
-
- uniforms = other.uniforms;
- uniform_data = other.uniform_data;
-
- for(SharedBlock &b: blocks)
- delete b.block;
- blocks.clear();
- programs.clear();
-
- last_buffer_block = 0;
- buffer = 0;
- dirty = 0;
-
- return *this;
-}
-
ProgramData::ProgramData(ProgramData &&other):
tied_program(other.tied_program),
uniforms(move(other.uniforms)),
void ProgramData::mark_dirty(Mask bits)
{
if(!dirty)
+ {
+ if(generation && !streaming)
+ {
+ streaming = true;
+ if(buffer && buffer->get_size())
+ recreate_buffer();
+ }
++generation;
+ }
dirty |= bits;
}
uniform(tag, tu.type, tu.array_size, source.uniform_data.data()+tu.data_offset);
}
+void ProgramData::copy_uniforms(const ProgramData &source)
+{
+ for(const TaggedUniform &u: source.uniforms)
+ uniform(u.tag, u.type, u.array_size, source.uniform_data.data()+u.data_offset);
+}
+
int ProgramData::find_uniform_index(Tag tag) const
{
auto i = lower_bound_member(uniforms, tag, &TaggedUniform::tag);
return programs.begin()+index;
}
+void ProgramData::recreate_buffer() const
+{
+ Buffer *old_buffer = buffer;
+ // Create the new buffer first to ensure it has a different address
+ buffer = new Buffer;
+ delete old_buffer;
+ if(last_buffer_block)
+ last_buffer_block->change_buffer(buffer);
+
+#ifdef DEBUG
+ if(!debug_name.empty())
+ buffer->set_debug_name(debug_name);
+#endif
+}
+
void ProgramData::update_block_uniform_indices(SharedBlock &block, const ReflectData::UniformBlockInfo &info) const
{
uint8_t *indices = block.indices.values;
if(info.bind_point>=0)
{
if(!buffer)
- {
- buffer = new Buffer();
-
-#ifdef DEBUG
- if(!debug_name.empty())
- buffer->set_debug_name(debug_name);
-#endif
- }
+ recreate_buffer();
block.block->use_buffer(buffer, last_buffer_block);
last_buffer_block = block.block;
prog_begin->masks.dirty = 0;
- if(last_buffer_block!=old_last_block)
+ if(last_buffer_block!=old_last_block || (buffer && !buffer->get_size()))
{
- unsigned required_size = last_buffer_block->get_required_buffer_size();
+ unsigned required_size = last_buffer_block->get_required_buffer_size(streaming);
if(last_buffer_block->get_required_buffer_size()>buffer->get_size())
{
if(buffer->get_size()>0)
- {
- delete buffer;
- buffer = new Buffer();
- last_buffer_block->change_buffer(buffer);
+ recreate_buffer();
-#ifdef DEBUG
- if(!debug_name.empty())
- buffer->set_debug_name(debug_name);
-#endif
- }
-
- buffer->storage(required_size);
+ buffer->storage(required_size, (streaming ? STREAMING : STATIC));
}
}
}
return prog_begin;
}
-void ProgramData::apply(const Program &prog, PipelineState &state) const
+void ProgramData::apply(const Program &prog, PipelineState &state, unsigned frame) const
{
auto prog_begin = prepare_program(prog);
ReflectData::LayoutHash prog_hash = prog_begin->prog_hash;
+
for(auto i=prog_begin+1; (i!=programs.end() && i->prog_hash==prog_hash); ++i)
if(i->block)
{
state.set_uniform_block(i->bind_point, i->block);
if(i->bind_point>=0)
- i->block->refresh();
+ i->block->refresh(frame);
}
}