X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fglsl%2Ffinalize.cpp;h=192baec550e111313c76a5cde659e37c6604fba8;hb=ece3438c6a1630ada39cc01ae3d54b27aacdd663;hp=0805a29e830eb45d626970a80faa1d10ae072c3b;hpb=7b03ca83ca6c48b9f8c3f77c13760e7f87e9632d;p=libs%2Fgl.git diff --git a/source/glsl/finalize.cpp b/source/glsl/finalize.cpp index 0805a29e..192baec5 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,76 @@ 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; + + var.layout->qualifiers.push_back(Layout::Qualifier("offset", offset)); + } + + 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) + var.layout->qualifiers.push_back(Layout::Qualifier("column_major")); + } + + 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 +111,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 +133,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.has_value = true; - qual.value = location; - layout->qualifiers.push_back(qual); + layout->qualifiers.push_back(Layout::Qualifier(name, value)); } 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 +185,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 +194,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); + } } @@ -382,6 +503,14 @@ bool LegacyConverter::supports_uniform_location() const return check_extension(&Features::arb_explicit_uniform_location); } +bool LegacyConverter::supports_binding() const +{ + if(features.gl_api==OPENGL_ES2) + return check_version(Version(3, 10)); + else + return check_version(Version(4, 20)); +} + void LegacyConverter::visit(VariableDeclaration &var) { if(var.layout) @@ -420,6 +549,16 @@ void LegacyConverter::visit(VariableDeclaration &var) else ++i; } + else if(i->name=="binding" && !supports_binding()) + { + const TypeDeclaration *type = var.type_declaration; + while(const BasicTypeDeclaration *basic = dynamic_cast(type)) + type = basic->base_type; + if(dynamic_cast(type)) + stage->texture_bindings[var.name] = i->value; + + i = var.layout->qualifiers.erase(i); + } else ++i; } @@ -486,6 +625,11 @@ void LegacyConverter::visit(InterfaceBlock &iface) { if(i->name=="location" && !supports_interface_block_location()) i = iface.layout->qualifiers.erase(i); + else if(i->name=="binding" && !supports_binding()) + { + stage->uniform_block_bindings[iface.block_name] = i->value; + i = iface.layout->qualifiers.erase(i); + } else ++i; }