X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fglsl%2Fvalidate.cpp;h=7e5f295f165ac3eda0993a7767b2b29fa9b6bbc5;hb=d3a41542c4982d6df08b5e6f969267f9c8889f9f;hp=0096ff5e5106f5a0547b24472a2a3397968e5cad;hpb=20a86c5905e1f7527d3c9edc3f56f6b7679c268a;p=libs%2Fgl.git diff --git a/source/glsl/validate.cpp b/source/glsl/validate.cpp index 0096ff5e..7e5f295f 100644 --- a/source/glsl/validate.cpp +++ b/source/glsl/validate.cpp @@ -3,6 +3,7 @@ #include #include #include +#include "reflect.h" #include "validate.h" using namespace std; @@ -69,16 +70,26 @@ void DeclarationValidator::visit(Layout &layout) allowed = (variable && scope==GLOBAL); else if(i->name=="binding" || i->name=="set") { + if(i->name=="set") + { + error(layout, "Layout qualifier 'set' not allowed when targeting OpenGL"); + continue; + } + if(variable) { TypeDeclaration *type = variable->type_declaration; while(BasicTypeDeclaration *basic = dynamic_cast(type)) type = basic->base_type; - allowed = (scope==GLOBAL && dynamic_cast(type)); - err_descr = "variable of non-opaque type"; + bool uniform = (variable->interface=="uniform"); + allowed = (scope==GLOBAL && uniform && dynamic_cast(type)); + err_descr = (uniform ? "variable of non-opaque type" : "non-uniform variable"); } else if(iface_block) - allowed = true; + { + allowed = (iface_block->interface=="uniform"); + err_descr = "non-uniform interface block"; + } } else if(i->name=="constant_id") { @@ -103,7 +114,9 @@ void DeclarationValidator::visit(Layout &layout) } } else if(i->name=="offset") - allowed = (variable && scope==INTERFACE_BLOCK); + allowed = (variable && scope==INTERFACE_BLOCK && iface_block->interface=="uniform"); + else if(i->name=="align") + allowed = (scope==INTERFACE_BLOCK && iface_block->interface=="uniform"); else if(i->name=="points") { allowed = (stage->type==Stage::GEOMETRY && iface_layout && (iface_layout->interface=="in" || iface_layout->interface=="out")); @@ -653,12 +666,7 @@ void StageInterfaceValidator::visit(VariableDeclaration &var) { map &used = used_locations[var.interface]; - unsigned loc_count = 1; - if(var.array) - if(const Literal *literal = dynamic_cast(var.array_size.get())) - if(literal->value.check_type()) - loc_count = literal->value.value(); - + unsigned loc_count = LocationCounter().apply(var); for(unsigned i=0; i::const_iterator j = used.find(location+i); @@ -683,63 +691,109 @@ void GlobalInterfaceValidator::apply(Module &module) } } -void GlobalInterfaceValidator::get_binding(const Layout &layout, unsigned &desc_set, int &binding) +void GlobalInterfaceValidator::check_uniform(const Uniform &uni) { - for(vector::const_iterator i=layout.qualifiers.begin(); i!=layout.qualifiers.end(); ++i) + map::const_iterator i = used_names.find(uni.name); + if(i!=used_names.end()) { - if(i->name=="set") - desc_set = i->value; - else if(i->name=="binding") - binding = i->value; + if(uni.location>=0 && i->second->location>=0 && i->second->location!=uni.location) + { + error(*uni.node, format("Mismatched location %d for uniform '%s'", uni.location, uni.name)); + add_info(*i->second->node, format("Previously declared here with location %d", i->second->location)); + } + if(uni.bind_point>=0 && i->second->bind_point>=0 && i->second->bind_point!=uni.bind_point) + { + error(*uni.node, format("Mismatched binding %d for uniform '%s'", uni.bind_point, uni.name)); + add_info(*i->second->node, format("Previously declared here with binding %d", i->second->bind_point)); + } + if(uni.type && i->second->type && !is_same_type(*uni.type, *i->second->type)) + { + string type_name = (dynamic_cast(uni.type) ? + "structure" : format("type '%s'", uni.type->name)); + error(*uni.node, format("Mismatched %s for uniform '%s'", type_name, uni.name)); + + string message = "Previously declared here"; + if(!dynamic_cast(i->second->type)) + message += format(" with type '%s'", i->second->type->name); + add_info(*i->second->node, message); + } } -} - -void GlobalInterfaceValidator::check_binding(const Layout &layout, const Binding &binding) -{ - unsigned desc_set = 0; - int bind_point = -1; - get_binding(layout, desc_set, bind_point); - if(bind_point<0) - return; + else + used_names.insert(make_pair(uni.name, &uni)); - map &used = used_bindings[desc_set]; - map::const_iterator i = used.find(bind_point); - if(i!=used.end()) + if(uni.location>=0) { - if(i->second.name!=binding.name) + map::const_iterator j = used_locations.find(uni.location); + if(j!=used_locations.end()) { - error(*binding.node, format("Overlapping binding %d for '%s'", bind_point, binding.name)); - add_info(*i->second.node, format("Previously used here for '%s'", i->second.name)); + if(j->second->name!=uni.name) + { + error(*uni.node, format("Overlapping location %d for '%s'", uni.location, uni.name)); + add_info(*j->second->node, format("Previously used here for '%s'", j->second->name)); + } } - if(i->second.type && binding.type) + else { - if(!is_same_type(*i->second.type, *binding.type)) + for(unsigned k=0; k=0) + { + map &used = used_bindings[uni.desc_set]; + map::const_iterator j = used.find(uni.bind_point); + if(j!=used.end()) + { + if(j->second->name!=uni.name) { - string type_name = (dynamic_cast(binding.type) ? "struct type" : - format("type '%s'", binding.type->name)); - error(*binding.node, format("Mismatched %s for binding %d '%s'", type_name, bind_point, binding.name)); - - string message = "Previously used here"; - if(!dynamic_cast(i->second.type)) - message += format(" with type '%s'", i->second.type->name); - add_info(*i->second.node, message); + error(*uni.node, format("Overlapping binding %d for '%s'", uni.bind_point, uni.name)); + add_info(*j->second->node, format("Previously used here for '%s'", j->second->name)); } } + else + used.insert(make_pair(uni.bind_point, &uni)); } - else - used.insert(make_pair(bind_point, binding)); } void GlobalInterfaceValidator::visit(VariableDeclaration &var) { - if(var.interface=="uniform" && var.layout) - check_binding(*var.layout, var); + if(var.interface=="uniform") + { + Uniform uni; + uni.node = &var; + uni.type = var.type_declaration; + uni.name = var.name; + if(var.layout) + { + uni.location = get_layout_value(*var.layout, "location"); + uni.loc_count = LocationCounter().apply(var); + uni.desc_set = get_layout_value(*var.layout, "set", 0); + uni.bind_point = get_layout_value(*var.layout, "binding"); + } + + uniforms.push_back(uni); + check_uniform(uniforms.back()); + } } void GlobalInterfaceValidator::visit(InterfaceBlock &iface) { - if(iface.interface=="uniform" && iface.layout) - check_binding(*iface.layout, iface); + if(iface.interface=="uniform") + { + Uniform uni; + uni.node = &iface; + uni.type = iface.struct_declaration; + uni.name = iface.block_name; + if(iface.layout) + { + uni.desc_set = get_layout_value(*iface.layout, "set", 0); + uni.bind_point = get_layout_value(*iface.layout, "binding"); + } + + uniforms.push_back(uni); + check_uniform(uniforms.back()); + } } } // namespace SL