X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fglsl%2Ffinalize.cpp;h=94007b8fc3eda25f24b91deff5425549de70ce15;hb=dfcf8ebc329b79c369b88bdbeb982480aa5fc12a;hp=0adb2960b1da3784a4554d9a97b447b12163481d;hpb=9cfccf5c4e366e033cfd5eebf8955d2b13202b46;p=libs%2Fgl.git diff --git a/source/glsl/finalize.cpp b/source/glsl/finalize.cpp index 0adb2960..94007b8f 100644 --- a/source/glsl/finalize.cpp +++ b/source/glsl/finalize.cpp @@ -1,8 +1,10 @@ #include +#include #include #include #include "finalize.h" #include "glsl_error.h" +#include "reflect.h" using namespace std; @@ -10,6 +12,245 @@ namespace Msp { namespace GL { namespace SL { +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) +{ + swap(used_locations["in"], used_locations["out"]); + used_locations["out"].clear(); + + stage.content.visit(*this); + + allocate_locations("in"); + allocate_locations("out"); +} + +void LocationAllocator::allocate_locations(const string &iface) +{ + vector::iterator write = unplaced_variables.begin(); + unsigned next = 0; + for(vector::const_iterator i=unplaced_variables.begin(); i!=unplaced_variables.end(); ++i) + { + if((*i)->interface!=iface) + { + if(write!=i) + *write = *i; + ++write; + continue; + } + + if((*i)->interface=="uniform") + { + map::const_iterator j = uniforms.find((*i)->name); + if(j!=uniforms.end() && j->second.location>=0) + { + add_layout_value((*i)->layout, "location", j->second.location); + continue; + } + } + + set &used = used_locations[(*i)->interface]; + + unsigned size = LocationCounter().apply(**i); + while(1) + { + int blocking = -1; + for(unsigned j=0; jlayout, "location", next); + if((*i)->interface=="uniform") + uniforms[(*i)->name].location = next; + + for(unsigned j=0; j &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 = name; + qual.has_value = true; + qual.value = value; + layout->qualifiers.push_back(qual); +} + +void LocationAllocator::visit(VariableDeclaration &var) +{ + if(!var.name.compare(0, 3, "gl_")) + return; + + if(!var.interface.empty()) + { + int location = (var.layout ? get_layout_value(*var.layout, "location") : -1); + + if(location<0 && var.linked_declaration && var.linked_declaration->layout) + { + location = get_layout_value(*var.linked_declaration->layout, "location"); + if(location>=0) + add_layout_value(var.layout, "location", location); + } + + if(location>=0) + { + unsigned size = LocationCounter().apply(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); + } +} + + PrecisionConverter::PrecisionConverter(): stage(0) { } @@ -274,6 +515,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) @@ -312,6 +561,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; } @@ -378,6 +637,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; }