From: Mikko Rasa Date: Fri, 24 Aug 2012 16:05:43 +0000 (+0300) Subject: Query information about uniform blocks when linking a Program X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=commitdiff_plain;h=02dc3bda81eb0d421670b744c1c56aaf1104d5bf Query information about uniform blocks when linking a Program --- diff --git a/source/program.cpp b/source/program.cpp index 8ca8e336..40a38819 100644 --- a/source/program.cpp +++ b/source/program.cpp @@ -1,8 +1,12 @@ #include +#include #include +#include #include #include "arb_shader_objects.h" +#include "arb_uniform_buffer_object.h" #include "arb_vertex_shader.h" +#include "buffer.h" #include "error.h" #include "extension.h" #include "program.h" @@ -235,29 +239,112 @@ void Program::link() throw compile_error(get_info_log()); glGetObjectParameterivARB(id, GL_OBJECT_ACTIVE_UNIFORMS_ARB, &value); - for(int i=0; i uniforms_by_index(count); + for(unsigned i=0; i::const_iterator i = uniforms.begin(); i!=uniforms.end(); ++i) - if(i->second.location>=0) + vector blockless_uniforms; + + if(is_supported("GL_ARB_uniform_buffer_object")) + { + glGetObjectParameterivARB(id, GL_ACTIVE_UNIFORM_BLOCKS, &value); + count = value; + vector uniforms_in_blocks(uniforms_by_index.size()); + for(unsigned i=0; isecond.location, i->second.name, i->second.type); + char name[128]; + int len; + glGetActiveUniformBlockName(id, i, 128, &len, name); + UniformBlockInfo &info = uniform_blocks[name]; + info.name = name; + + glGetActiveUniformBlockiv(id, i, GL_UNIFORM_BLOCK_DATA_SIZE, &value); + info.data_size = value; + + glGetActiveUniformBlockiv(id, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &value); + vector indices(value); + glGetActiveUniformBlockiv(id, i, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, &indices[0]); + for(vector::iterator j=indices.begin(); j!=indices.end(); ++j) + { + if(!uniforms_by_index[*j]) + throw logic_error("Program::link"); + info.uniforms.push_back(uniforms_by_index[*j]); + uniforms_in_blocks[*j] = true; + } + + vector indices2(indices.begin(), indices.end()); + vector values(indices.size()); + glGetActiveUniformsiv(id, indices.size(), &indices2[0], GL_UNIFORM_OFFSET, &values[0]); + for(unsigned j=0; jlocation = values[j]; + + indices2.clear(); + for(vector::iterator j=indices.begin(); j!=indices.end(); ++j) + if(uniforms_by_index[*j]->size>1) + indices2.push_back(*j); + glGetActiveUniformsiv(id, indices2.size(), &indices2[0], GL_UNIFORM_ARRAY_STRIDE, &values[0]); + for(unsigned j=0; jarray_stride = values[j]; + + indices2.clear(); + for(vector::iterator j=indices.begin(); j!=indices.end(); ++j) + { + GLenum t = uniforms_by_index[*j]->type; + if(t==GL_FLOAT_MAT4 || t==GL_FLOAT_MAT3 || t==GL_FLOAT_MAT2 || + t==GL_FLOAT_MAT2x3 || t==GL_FLOAT_MAT2x4 || t==GL_FLOAT_MAT3x2 || + t==GL_FLOAT_MAT3x4 || t==GL_FLOAT_MAT4x2 || t==GL_FLOAT_MAT4x3) + indices2.push_back(*j); + } + glGetActiveUniformsiv(id, indices2.size(), &indices2[0], GL_UNIFORM_MATRIX_STRIDE, &values[0]); + for(unsigned j=0; jmatrix_stride = values[j]; + + info.layout_hash = compute_layout_hash(info.uniforms); + info.bind_point = info.layout_hash%BufferRange::get_n_uniform_buffer_bindings(); + glUniformBlockBinding(id, i, info.bind_point); } - uniform_layout_hash = hash32(layout_descriptor); + + for(unsigned i=0; ilocation = glGetUniformLocationARB(id, info->name.c_str()); + blockless_uniforms.push_back(info); + } + } + else + { + for(UniformMap::iterator i=uniforms.begin(); i!=uniforms.end(); ++i) + { + i->second.location = glGetUniformLocationARB(id, i->second.name.c_str()); + blockless_uniforms.push_back(&i->second); + } + } + + uniform_layout_hash = compute_layout_hash(blockless_uniforms); +} + +unsigned Program::compute_layout_hash(const vector &uniforms) +{ + string layout_descriptor; + for(vector::const_iterator i = uniforms.begin(); i!=uniforms.end(); ++i) + layout_descriptor += format("%d:%s:%x:%d\n", (*i)->location, (*i)->name, (*i)->type, (*i)->size); + return hash32(layout_descriptor); } string Program::get_info_log() const @@ -271,6 +358,16 @@ string Program::get_info_log() const return log; } +const Program::UniformBlockInfo &Program::get_uniform_block_info(const string &name) const +{ + return get_item(uniform_blocks, name); +} + +const Program::UniformInfo &Program::get_uniform_info(const string &name) const +{ + return get_item(uniforms, name); +} + int Program::get_uniform_location(const string &n) const { UniformMap::const_iterator i = uniforms.find(n); @@ -284,7 +381,7 @@ int Program::get_uniform_location(const string &n) const /* The requested name looks like an array. glGetActiveUniform only gives us the first element of the array, so try to look that up and add an offset. */ - int offset = lexical_cast(n.substr(open_bracket+1, n.size()-2-open_bracket)); + unsigned offset = lexical_cast(n.substr(open_bracket+1, n.size()-2-open_bracket)); i = uniforms.find(n.substr(0, open_bracket)+"[0]"); if(i!=uniforms.end() && offsetsecond.size) return i->second.location+offset; diff --git a/source/program.h b/source/program.h index 7e9676d3..40a7a33b 100644 --- a/source/program.h +++ b/source/program.h @@ -54,19 +54,32 @@ public: struct UniformInfo { std::string name; - int location; - int size; + unsigned location; + unsigned size; + unsigned array_stride; + unsigned matrix_stride; GLenum type; }; + struct UniformBlockInfo + { + std::string name; + unsigned data_size; + unsigned bind_point; + std::vector uniforms; + unsigned layout_hash; + }; + typedef std::list ShaderList; typedef std::map UniformMap; + typedef std::map UniformBlockMap; private: unsigned id; ShaderList shaders; ShaderList owned_data; bool linked; + UniformBlockMap uniform_blocks; UniformMap uniforms; unsigned uniform_layout_hash; @@ -91,10 +104,17 @@ public: void bind_attribute(unsigned, const std::string &); void link(); +private: + static unsigned compute_layout_hash(const std::vector &); +public: bool is_linked() const { return linked; } std::string get_info_log() const; unsigned get_uniform_layout_hash() const { return uniform_layout_hash; } + const UniformBlockMap &get_uniform_blocks() const { return uniform_blocks; } + const UniformBlockInfo &get_uniform_block_info(const std::string &) const; + const UniformMap &get_uniforms() const { return uniforms; } + const UniformInfo &get_uniform_info(const std::string &) const; int get_uniform_location(const std::string &) const; void bind() const;