X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fglsl%2Ffinalize.cpp;h=94007b8fc3eda25f24b91deff5425549de70ce15;hb=180698dbb41d312128c496721f1207c6688fe350;hp=1b300e72a872cd55aa19727cf284efba5607b26f;hpb=c6b29fbf9927467b21dca65539a1fa2c98f96e0e;p=libs%2Fgl.git diff --git a/source/glsl/finalize.cpp b/source/glsl/finalize.cpp index 1b300e72..94007b8f 100644 --- a/source/glsl/finalize.cpp +++ b/source/glsl/finalize.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include "finalize.h" @@ -11,11 +12,84 @@ namespace Msp { namespace GL { namespace SL { -void LocationAllocator::apply(Module &module) +StructOrganizer::StructOrganizer(): + offset(-1) +{ } + +void StructOrganizer::visit(StructDeclaration &strct) +{ + SetForScope set_offset(offset, 0); + TraversingVisitor::visit(strct); +} + +void StructOrganizer::visit(VariableDeclaration &var) +{ + if(offset>=0) + { + int *layout_offset = 0; + bool has_matrix_order = false; + if(var.layout) + { + vector &qualifiers = var.layout->qualifiers; + for(vector::iterator i=qualifiers.begin(); i!=qualifiers.end(); ++i) + { + if(i->name=="offset" && i->has_value) + { + layout_offset = &i->value; + if(i->value>=offset) + offset = i->value; + } + else if(i->name=="column_major" || i->name=="row_major") + has_matrix_order = true; + } + } + + MemoryRequirementsCalculator::Result mem_reqs = MemoryRequirementsCalculator().apply(var); + offset += mem_reqs.alignment-1; + offset -= offset%mem_reqs.alignment; + + if(layout_offset) + *layout_offset = offset; + else + { + if(!var.layout) + var.layout = new Layout; + + Layout::Qualifier qual; + qual.name = "offset"; + qual.has_value = true; + qual.value = offset; + var.layout->qualifiers.push_back(qual); + } + + if(!has_matrix_order) + { + const BasicTypeDeclaration *basic = dynamic_cast(var.type_declaration); + while(basic && basic->kind==BasicTypeDeclaration::ARRAY) + basic = dynamic_cast(basic->base_type); + if(basic && basic->kind==BasicTypeDeclaration::MATRIX) + { + Layout::Qualifier qual; + qual.name = "column_major"; + var.layout->qualifiers.push_back(qual); + } + } + + offset += mem_reqs.size; + } +} + + +void LocationAllocator::apply(Module &module, const Features &features) { for(list::iterator i=module.stages.begin(); i!=module.stages.end(); ++i) apply(*i); allocate_locations("uniform"); + + for(vector::const_iterator i=unbound_blocks.begin(); i!=unbound_blocks.end(); ++i) + bind_uniform((*i)->layout, (*i)->block_name, features.uniform_binding_range); + for(vector::const_iterator i=unbound_textures.begin(); i!=unbound_textures.end(); ++i) + bind_uniform((*i)->layout, (*i)->name, features.texture_binding_range); } void LocationAllocator::apply(Stage &stage) @@ -45,10 +119,10 @@ void LocationAllocator::allocate_locations(const string &iface) if((*i)->interface=="uniform") { - map::const_iterator j = uniform_locations.find((*i)->name); - if(j!=uniform_locations.end()) + map::const_iterator j = uniforms.find((*i)->name); + if(j!=uniforms.end() && j->second.location>=0) { - add_location((*i)->layout, j->second); + add_layout_value((*i)->layout, "location", j->second.location); continue; } } @@ -67,9 +141,9 @@ void LocationAllocator::allocate_locations(const string &iface) next = blocking+1; } - add_location((*i)->layout, next); + add_layout_value((*i)->layout, "location", next); if((*i)->interface=="uniform") - uniform_locations[(*i)->name] = next; + uniforms[(*i)->name].location = next; for(unsigned j=0; j &layout, unsigned location) +void LocationAllocator::bind_uniform(RefPtr &layout, const string &name, unsigned range) +{ + map::const_iterator i = uniforms.find(name); + if(i!=uniforms.end() && i->second.bind_point>=0) + add_layout_value(layout, "binding", i->second.bind_point); + else + { + set &used = used_bindings[0]; + + unsigned bind_point = fold32(hash64(name))%range; + while(used.count(bind_point)) + bind_point = (bind_point+1)%range; + + add_layout_value(layout, "binding", bind_point); + uniforms[name].bind_point = bind_point; + used.insert(bind_point); + } +} + +void LocationAllocator::add_layout_value(RefPtr &layout, const string &name, unsigned value) { if(!layout) layout = new Layout; Layout::Qualifier qual; - qual.name = "location"; + qual.name = name; qual.has_value = true; - qual.value = location; + qual.value = value; layout->qualifiers.push_back(qual); } void LocationAllocator::visit(VariableDeclaration &var) { - if(!var.interface.empty() && var.name.compare(0, 3, "gl_")) + if(!var.name.compare(0, 3, "gl_")) + return; + + if(!var.interface.empty()) { int location = (var.layout ? get_layout_value(*var.layout, "location") : -1); @@ -101,7 +197,7 @@ void LocationAllocator::visit(VariableDeclaration &var) { location = get_layout_value(*var.linked_declaration->layout, "location"); if(location>=0) - add_location(var.layout, location); + add_layout_value(var.layout, "location", location); } if(location>=0) @@ -110,11 +206,48 @@ void LocationAllocator::visit(VariableDeclaration &var) for(unsigned i=0; i(type)) + type = basic->base_type; + if(dynamic_cast(type)) + { + int bind_point = (var.layout ? get_layout_value(*var.layout, "binding") : -1); + if(bind_point>=0) + { + used_bindings[0].insert(bind_point); + uniforms[var.name].bind_point = bind_point; + } + else + unbound_textures.push_back(&var); + } + } +} + +void LocationAllocator::visit(InterfaceBlock &iface) +{ + if(!iface.instance_name.compare(0, 3, "gl_")) + return; + + if(iface.interface=="uniform") + { + int bind_point = (iface.layout ? get_layout_value(*iface.layout, "binding") : -1); + + if(bind_point>=0) + { + used_bindings[0].insert(bind_point); + uniforms[iface.block_name].bind_point = bind_point; + } + else + unbound_blocks.push_back(&iface); + } }