X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fglsl%2Ffinalize.cpp;h=0805a29e830eb45d626970a80faa1d10ae072c3b;hb=7b03ca83ca6c48b9f8c3f77c13760e7f87e9632d;hp=030cb432a4a0c835b2485773ffa8b92fb36b705d;hpb=9c1035c136c7c78f0cbf0205ec48befc49219de7;p=libs%2Fgl.git diff --git a/source/glsl/finalize.cpp b/source/glsl/finalize.cpp index 030cb432..0805a29e 100644 --- a/source/glsl/finalize.cpp +++ b/source/glsl/finalize.cpp @@ -3,6 +3,7 @@ #include #include "finalize.h" #include "glsl_error.h" +#include "reflect.h" using namespace std; @@ -10,6 +11,113 @@ namespace Msp { namespace GL { namespace SL { +void LocationAllocator::apply(Module &module) +{ + for(list::iterator i=module.stages.begin(); i!=module.stages.end(); ++i) + apply(*i); + allocate_locations("uniform"); +} + +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 = uniform_locations.find((*i)->name); + if(j!=uniform_locations.end()) + { + add_location((*i)->layout, j->second); + continue; + } + } + + set &used = used_locations[(*i)->interface]; + + unsigned size = LocationCounter().apply(**i); + while(1) + { + int blocking = -1; + for(unsigned j=0; jlayout, next); + if((*i)->interface=="uniform") + uniform_locations[(*i)->name] = next; + + for(unsigned j=0; j &layout, unsigned location) +{ + if(!layout) + layout = new Layout; + + Layout::Qualifier qual; + qual.name = "location"; + qual.has_value = true; + qual.value = location; + layout->qualifiers.push_back(qual); +} + +void LocationAllocator::visit(VariableDeclaration &var) +{ + if(!var.interface.empty() && var.name.compare(0, 3, "gl_")) + { + 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_location(var.layout, location); + } + + if(location>=0) + { + unsigned size = LocationCounter().apply(var); + for(unsigned i=0; i::const_iterator i=var.layout->qualifiers.begin(); i!=var.layout->qualifiers.end(); ) { - if(i->name=="location" && !supports_interface_layouts()) + if(i->name=="location") { - if(stage->type==Stage::VERTEX && var.interface=="in") - stage->locations[var.name] = i->value; - else if(stage->type==Stage::FRAGMENT && var.interface=="out") + bool supported = true; + bool external = false; + if(var.interface=="in") { - if(check_extension(&Features::ext_gpu_shader4)) - stage->locations[var.name] = i->value; - else if(i->value!=0) - unsupported("EXT_gpu_shader4 required for multiple fragment shader outputs"); + external = (stage->type==Stage::VERTEX); + supported = (external ? supports_interface_layouts() : supports_stage_interface_layouts()); + } + else if(var.interface=="out") + { + external = (stage->type==Stage::FRAGMENT); + supported = (external ? supports_interface_layouts() : supports_stage_interface_layouts()); + if(external && !supported && !check_extension(&Features::ext_gpu_shader4)) + { + external = false; + if(i->value!=0) + unsupported("EXT_gpu_shader4 required for multiple fragment shader outputs"); + } } + else if(var.interface=="uniform") + supported = supports_uniform_location(); - i = var.layout->qualifiers.erase(i); + if(!supported) + { + if(external) + stage->locations[var.name] = i->value; + i = var.layout->qualifiers.erase(i); + } + else + ++i; } else ++i; @@ -322,8 +468,32 @@ bool LegacyConverter::supports_interface_blocks(const string &iface) const return false; } +bool LegacyConverter::supports_interface_block_location() const +{ + if(features.gl_api==OPENGL_ES2) + return check_version(Version(3, 20)); + else if(check_version(Version(4, 40))) + return true; + else + return check_extension(&Features::arb_enhanced_layouts); +} + void LegacyConverter::visit(InterfaceBlock &iface) { + if(iface.layout) + { + for(vector::const_iterator i=iface.layout->qualifiers.begin(); i!=iface.layout->qualifiers.end(); ) + { + if(i->name=="location" && !supports_interface_block_location()) + i = iface.layout->qualifiers.erase(i); + else + ++i; + } + + if(iface.layout->qualifiers.empty()) + iface.layout = 0; + } + if(!supports_interface_blocks(iface.interface) && iface.type_declaration) { if(!iface.instance_name.empty())