X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fglsl%2Ffinalize.cpp;h=2d1a46fb0862639457a1137a2de94036c6a1f7da;hb=70d9d2d28e5fe723c6b46894276e4c935f578e2d;hp=0805a29e830eb45d626970a80faa1d10ae072c3b;hpb=7b03ca83ca6c48b9f8c3f77c13760e7f87e9632d;p=libs%2Fgl.git diff --git a/source/glsl/finalize.cpp b/source/glsl/finalize.cpp index 0805a29e..2d1a46fb 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,16 @@ namespace Msp { namespace GL { namespace SL { -void LocationAllocator::apply(Module &module) +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 +51,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 +73,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 +129,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 +138,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 +447,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 +493,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 +569,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; }