]> git.tdb.fi Git - libs/gl.git/blobdiff - source/programdata.cpp
Deprecate some Buffer features which don't translate to Vulkan
[libs/gl.git] / source / programdata.cpp
index dba6b06f2cc8a94ca25d1006020fc567f9d1619d..1589d9b0d44e00258d2457fc1f8acb0def28b23e 100644 (file)
@@ -1,5 +1,7 @@
 #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"
@@ -24,7 +26,7 @@ ProgramData::ProgramData(const Program *p):
 
 // Blocks are intentionally left uncopied
 ProgramData::ProgramData(const ProgramData &other):
-       tied_program(0),
+       tied_program(other.tied_program),
        uniforms(other.uniforms),
        last_block(0),
        buffer(0),
@@ -34,6 +36,23 @@ ProgramData::ProgramData(const ProgramData &other):
                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;
@@ -75,10 +94,15 @@ void ProgramData::uniform(const string &name, Uniform *uni)
                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);
@@ -404,6 +428,12 @@ const Uniform &ProgramData::get_uniform(const string &name) const
        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;
@@ -459,21 +489,31 @@ ProgramData::SharedBlock *ProgramData::get_shared_block(const Program::UniformBl
        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);
@@ -516,6 +556,7 @@ void ProgramData::apply() const
 
                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.
@@ -557,6 +598,13 @@ void ProgramData::apply() const
                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)