#include <msp/core/maputils.h>
+#include <msp/debug/demangle.h>
#include <msp/gl/extensions/arb_direct_state_access.h>
+#include <msp/io/print.h>
#include "buffer.h"
#include "color.h"
#include "error.h"
i->value = i->value->clone();
}
+ProgramData::ProgramData(const ProgramData &other, const Program *p):
+ tied_program(p),
+ last_block(0),
+ buffer(0),
+ dirty(0)
+{
+ if(tied_program)
+ {
+ for(vector<NamedUniform>::const_iterator i=other.uniforms.begin(); i!=other.uniforms.end(); ++i)
+ tied_program->get_uniform_info(i->name);
+ }
+
+ uniforms = other.uniforms;
+ for(vector<NamedUniform>::iterator i=uniforms.begin(); i!=uniforms.end(); ++i)
+ i->value = i->value->clone();
+}
+
ProgramData &ProgramData::operator=(const ProgramData &other)
{
tied_program = other.tied_program;
else if(name[name.size()-1]==']')
throw invalid_argument("ProgramData::uniform");
}
- catch(...)
+ catch(const exception &e)
{
delete uni;
+#ifdef DEBUG
+ IO::print(IO::cerr, "Error while setting uniform %s: %s: %s\n", name, Debug::demangle(typeid(e).name()), e.what());
+ return;
+#else
throw;
+#endif
}
int i = find_uniform_index(name);
return *uniforms[i].value;
}
+const Uniform *ProgramData::find_uniform(const string &name) const
+{
+ int i = find_uniform_index(name);
+ return (i>=0 ? uniforms[i].value : 0);
+}
+
bool ProgramData::uniform_name_compare(const NamedUniform &nu, const string &name)
{
return nu.name<name;
if(i==blocks.end())
{
bool any_found = false;
- for(vector<const Program::UniformInfo *>::const_iterator j=info.uniforms.begin(); (!any_found && j!=info.uniforms.end()); ++j)
- any_found = (find_uniform_index((*j)->name)>=0);
+ bool all_found = true;
+ for(vector<const Program::UniformInfo *>::const_iterator j=info.uniforms.begin(); j!=info.uniforms.end(); ++j)
+ {
+ if(find_uniform_index((*j)->name)>=0)
+ any_found = true;
+ else
+ all_found = false;
+ }
- // TODO throw if all uniforms for a buffer-backed block are not found
if(!any_found)
return 0;
+ else if(!all_found && info.bind_point>=0)
+ {
+#ifdef DEBUG
+ IO::print(IO::cerr, "Warning: not all uniforms for block %s are present\n", info.name);
+#else
+ throw incomplete_uniform_block(info.name);
+#endif
+ }
UniformBlock *block;
if(info.bind_point>=0)
{
if(!buffer)
- {
buffer = new Buffer(UNIFORM_BUFFER);
- buffer->set_usage(STREAM_DRAW);
- }
block = new UniformBlock(info.data_size);
block->use_buffer(buffer, last_block);
const Program::UniformBlockMap &prog_blocks = prog->get_uniform_blocks();
+ UniformBlock *old_last_block = last_block;
if(pu.dirty==ALL_ONES)
{
/* The set of uniforms has changed since this program was last used.
to avoid state thrashing. */
if(buffered_blocks_updated && !ARB_direct_state_access)
buffer->bind();
+
+ if(last_block!=old_last_block)
+ {
+ unsigned required_size = last_block->get_required_buffer_size();
+ if(last_block->get_required_buffer_size()>buffer->get_size())
+ buffer->data(required_size, 0);
+ }
}
for(vector<ProgramBlock>::iterator i=pu.blocks.begin(); i!=pu.blocks.end(); ++i)