X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fglsl%2Ffinalize.cpp;h=fcf48c61cd0ae1fbce706cff7744384525be7d7c;hb=1a5dafe20e47c764f2914c341fb7b8f1fba59fb8;hp=3bdca5cb7d02dcbf786e69dd60d9f0b3b394d554;hpb=ea844415db7fb7705ecbfea9cf27df2a8f00b802;p=libs%2Fgl.git diff --git a/source/glsl/finalize.cpp b/source/glsl/finalize.cpp index 3bdca5cb..fcf48c61 100644 --- a/source/glsl/finalize.cpp +++ b/source/glsl/finalize.cpp @@ -46,12 +46,7 @@ void StructOrganizer::visit(VariableDeclaration &var) if(layout_offset) *layout_offset = offset; else - { - if(!var.layout) - var.layout = new Layout; - - var.layout->qualifiers.push_back(Layout::Qualifier("offset", offset)); - } + add_layout_qualifier(var.layout, Layout::Qualifier("offset", offset)); if(!has_matrix_order) { @@ -59,7 +54,7 @@ void StructOrganizer::visit(VariableDeclaration &var) 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")); + add_layout_qualifier(var.layout, Layout::Qualifier("column_major")); } offset += mem_reqs.size; @@ -67,16 +62,18 @@ void StructOrganizer::visit(VariableDeclaration &var) } -void LocationAllocator::apply(Module &module, const Features &features) +void LocationAllocator::apply(Module &module, const Features &f, bool a) { + features = f; + alloc_new = a; for(Stage &s: module.stages) apply(s); if(features.target_api!=VULKAN) allocate_locations("uniform"); - for(InterfaceBlock *b: unbound_blocks) - bind_uniform(b->layout, b->block_name, features.uniform_binding_range); + for(VariableDeclaration *b: unbound_blocks) + bind_uniform(b->layout, b->block_declaration->block_name, features.uniform_binding_range); for(VariableDeclaration *t: unbound_textures) bind_uniform(t->layout, t->name, features.texture_binding_range); } @@ -111,11 +108,14 @@ void LocationAllocator::allocate_locations(const string &iface) auto j = uniforms.find((*i)->name); if(j!=uniforms.end() && j->second.location>=0) { - add_layout_value((*i)->layout, "location", j->second.location); + add_layout_qualifier((*i)->layout, Layout::Qualifier("location", j->second.location)); continue; } } + if(!alloc_new) + continue; + set &used = used_locations[(*i)->interface]; unsigned size = LocationCounter().apply(**i); @@ -130,7 +130,7 @@ void LocationAllocator::allocate_locations(const string &iface) next = blocking+1; } - add_layout_value((*i)->layout, "location", next); + add_layout_qualifier((*i)->layout, Layout::Qualifier("location", next)); if((*i)->interface=="uniform") uniforms[(*i)->name].location = next; @@ -145,38 +145,55 @@ void LocationAllocator::allocate_locations(const string &iface) void LocationAllocator::bind_uniform(RefPtr &layout, const string &name, unsigned range) { auto i = uniforms.find(name); + + int desc_set = (i!=uniforms.end() ? i->second.desc_set : 0); + if(features.target_api==VULKAN && get_layout_value(layout.get(), "set")<0) + add_layout_qualifier(layout, Layout::Qualifier("set", desc_set)); + if(i!=uniforms.end() && i->second.bind_point>=0) - add_layout_value(layout, "binding", i->second.bind_point); - else + add_layout_qualifier(layout, Layout::Qualifier("binding", i->second.bind_point)); + else if(alloc_new) { - set &used = used_bindings[0]; + set &used = used_bindings[desc_set]; - unsigned bind_point = fold32(hash64(name))%range; + unsigned bind_point = hash_fold<32>(hash<64>(name))%range; while(used.count(bind_point)) bind_point = (bind_point+1)%range; - add_layout_value(layout, "binding", bind_point); + add_layout_qualifier(layout, Layout::Qualifier("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) +bool LocationAllocator::visit_uniform(const string &name, RefPtr &layout) { - if(!layout) - layout = new Layout; + int desc_set = get_layout_value(layout.get(), "set"); + int bind_point = get_layout_value(layout.get(), "binding"); - layout->qualifiers.push_back(Layout::Qualifier(name, value)); -} + if(features.target_api==VULKAN) + { + if(desc_set<0 && bind_point>=0) + { + desc_set = 0; + add_layout_qualifier(layout, Layout::Qualifier("set", desc_set)); + } + + if(desc_set>=0) + uniforms[name].desc_set = desc_set; + } + else if(desc_set>=0 && bind_point<0) + { + auto i = find_member(layout->qualifiers, string("set"), &Layout::Qualifier::name); + layout->qualifiers.erase(i); + } -bool LocationAllocator::visit_uniform(const string &name, RefPtr &layout) -{ - int bind_point = (layout ? get_layout_value(*layout, "binding") : -1); if(bind_point>=0) { - used_bindings[0].insert(bind_point); + used_bindings[desc_set].insert(bind_point); uniforms[name].bind_point = bind_point; } + return bind_point>=0; } @@ -185,15 +202,15 @@ void LocationAllocator::visit(VariableDeclaration &var) if(!var.name.compare(0, 3, "gl_")) return; - if(!var.interface.empty()) + if(!var.interface.empty() && !var.block_declaration) { - int location = (var.layout ? get_layout_value(*var.layout, "location") : -1); + int location = get_layout_value(var.layout.get(), "location"); if(location<0 && var.linked_declaration && var.linked_declaration->layout) { - location = get_layout_value(*var.linked_declaration->layout, "location"); + location = get_layout_value(var.linked_declaration->layout.get(), "location"); if(location>=0) - add_layout_value(var.layout, "location", location); + add_layout_qualifier(var.layout, Layout::Qualifier("location", location)); } if(location>=0) @@ -210,28 +227,68 @@ void LocationAllocator::visit(VariableDeclaration &var) if(var.interface=="uniform") { - const TypeDeclaration *base_type = get_ultimate_base_type(var.type_declaration); - if(dynamic_cast(base_type) && !visit_uniform(var.name, var.layout)) - unbound_textures.push_back(&var); + if(var.block_declaration) + { + bool push_constant = has_layout_qualifier(var.layout.get(), "push_constant"); + if(!push_constant && !visit_uniform(var.block_declaration->block_name, var.layout)) + unbound_blocks.push_back(&var); + } + else + { + const TypeDeclaration *base_type = get_ultimate_base_type(var.type_declaration); + if(dynamic_cast(base_type) && !visit_uniform(var.name, var.layout)) + unbound_textures.push_back(&var); + } } } -void LocationAllocator::visit(InterfaceBlock &iface) + +void DepthRangeConverter::apply(Stage &stage, const Features &features) { - if(!iface.instance_name.compare(0, 3, "gl_")) + if(stage.type!=Stage::VERTEX || features.target_api==VULKAN) return; - if(iface.interface=="uniform") + stage.content.visit(*this); +} + +void DepthRangeConverter::visit(FunctionDeclaration &func) +{ + if(func.definition==&func && func.name=="main") { - bool push_constant = false; - if(iface.layout) - { - auto i = find_member(iface.layout->qualifiers, string("push_constant"), &Layout::Qualifier::name); - push_constant = (i!=iface.layout->qualifiers.end()); - } + VariableReference *position = new VariableReference; + position->name = "gl_Position"; + + MemberAccess *z = new MemberAccess; + z->left = position; + z->member = "z"; + + Literal *scale = new Literal; + scale->token = "2.0"; + scale->value = 2.0f; + + BinaryExpression *multiply = new BinaryExpression; + multiply->oper = &Operator::get_operator("*", Operator::BINARY); + multiply->left = z; + multiply->right = scale; + + MemberAccess *w = new MemberAccess; + w->left = position->clone(); + w->member = "w"; + + BinaryExpression *subtract = new BinaryExpression; + subtract->oper = &Operator::get_operator("-", Operator::BINARY); + subtract->left = multiply; + subtract->right = w; - if(!push_constant && !visit_uniform(iface.block_name, iface.layout)) - unbound_blocks.push_back(&iface); + Assignment *assign = new Assignment; + assign->oper = &Operator::get_operator("=", Operator::BINARY); + assign->left = z->clone(); + assign->right = subtract; + + ExpressionStatement *statement = new ExpressionStatement; + statement->expression = assign; + + func.body.body.push_back(statement); } } @@ -378,9 +435,7 @@ bool StructuralFeatureConverter::supports_stage(Stage::Type st) const { if(st==Stage::GEOMETRY) { - if(features.target_api==VULKAN) - return true; - else if(features.target_api==OPENGL_ES) + if(features.target_api==OPENGL_ES) return check_version(Version(3, 20)); else return check_version(Version(1, 50)); @@ -391,9 +446,7 @@ bool StructuralFeatureConverter::supports_stage(Stage::Type st) const bool StructuralFeatureConverter::supports_unified_interface_syntax() const { - if(features.target_api==VULKAN) - return true; - else if(features.target_api==OPENGL_ES) + if(features.target_api==OPENGL_ES) return check_version(Version(3, 0)); else return check_version(Version(1, 30)); @@ -406,11 +459,8 @@ void StructuralFeatureConverter::visit(VariableReference &var) var.name = "gl_FragColor"; var.declaration = 0; } -} -void StructuralFeatureConverter::visit(InterfaceBlockReference &iface) -{ - r_flattened_interface = nodes_to_remove.count(iface.declaration); + r_flattened_interface = nodes_to_remove.count(var.declaration); } void StructuralFeatureConverter::visit(MemberAccess &memacc) @@ -434,9 +484,7 @@ void StructuralFeatureConverter::visit(Assignment &assign) bool StructuralFeatureConverter::supports_unified_sampling_functions() const { - if(features.target_api==VULKAN) - return true; - else if(features.target_api==OPENGL_ES) + if(features.target_api==OPENGL_ES) return check_version(Version(3, 0)); else return check_version(Version(1, 30)); @@ -479,23 +527,9 @@ void StructuralFeatureConverter::visit(FunctionCall &call) TraversingVisitor::visit(call); } -void StructuralFeatureConverter::visit(VariableDeclaration &var) -{ - if((var.interface=="in" || var.interface=="out") && !supports_unified_interface_syntax()) - if(stage->type==Stage::FRAGMENT && var.interface=="out") - { - frag_out = &var; - nodes_to_remove.insert(&var); - } - - TraversingVisitor::visit(var); -} - bool StructuralFeatureConverter::supports_interface_blocks(const string &iface) const { - if(features.target_api==VULKAN) - return true; - else if(features.target_api==OPENGL_ES) + if(features.target_api==OPENGL_ES) { if(iface=="uniform") return check_version(Version(3, 0)); @@ -510,33 +544,35 @@ bool StructuralFeatureConverter::supports_interface_blocks(const string &iface) return false; } -void StructuralFeatureConverter::visit(InterfaceBlock &iface) +void StructuralFeatureConverter::visit(VariableDeclaration &var) { - bool push_constant = false; - if(iface.layout) + if(var.block_declaration) { - auto i = find_member(iface.layout->qualifiers, string("push_constant"), &Layout::Qualifier::name); - push_constant = (i!=iface.layout->qualifiers.end()); + bool push_constant = has_layout_qualifier(var.layout.get(), "push_constant"); + if(!supports_interface_blocks(var.interface) || (push_constant && features.target_api!=VULKAN)) + { + if(var.name.find(' ')==string::npos) + unsupported("ARB_uniform_buffer_object required for interface block instances"); + else + { + for(const RefPtr &s: var.block_declaration->members.body) + if(VariableDeclaration *mem = dynamic_cast(s.get())) + mem->interface = var.interface; + stage->content.body.splice(uniform_insert_point, var.block_declaration->members.body); + nodes_to_remove.insert(&var); + nodes_to_remove.insert(var.block_declaration); + } + } } - if((!supports_interface_blocks(iface.interface) || (push_constant && features.target_api!=VULKAN)) && iface.type_declaration) - { - if(!iface.instance_name.empty()) - unsupported("ARB_uniform_buffer_object required for interface block instances"); - else if(iface.struct_declaration) + if((var.interface=="in" || var.interface=="out") && !supports_unified_interface_syntax()) + if(stage->type==Stage::FRAGMENT && var.interface=="out") { - for(const RefPtr &s: iface.struct_declaration->members.body) - if(VariableDeclaration *var = dynamic_cast(s.get())) - var->interface = iface.interface; - stage->content.body.splice(uniform_insert_point, iface.struct_declaration->members.body); - nodes_to_remove.insert(&iface); - nodes_to_remove.insert(iface.struct_declaration); + frag_out = &var; + nodes_to_remove.insert(&var); } - else - /* If the interface block is an array, it should have an instance - name too, so this should never be reached */ - throw logic_error("Unexpected interface block configuration"); - } + + TraversingVisitor::visit(var); } @@ -547,9 +583,7 @@ void QualifierConverter::apply() bool QualifierConverter::supports_interface_layouts() const { - if(features.target_api==VULKAN) - return true; - else if(features.target_api==OPENGL_ES) + if(features.target_api==OPENGL_ES) return check_version(Version(3, 0)); else if(check_version(Version(3, 30))) return true; @@ -561,9 +595,7 @@ bool QualifierConverter::supports_interface_layouts() const bool QualifierConverter::supports_stage_interface_layouts() const { - if(features.target_api==VULKAN) - return true; - else if(features.target_api==OPENGL_ES) + if(features.target_api==OPENGL_ES) return check_version(Version(3, 10)); else if(check_version(Version(4, 10))) return true; @@ -573,9 +605,7 @@ bool QualifierConverter::supports_stage_interface_layouts() const bool QualifierConverter::supports_centroid_sampling() const { - if(features.target_api==VULKAN) - return true; - else if(features.target_api==OPENGL_ES) + if(features.target_api==OPENGL_ES) return check_version(Version(3, 0)); else if(check_version(Version(1, 20))) return true; @@ -585,9 +615,7 @@ bool QualifierConverter::supports_centroid_sampling() const bool QualifierConverter::supports_sample_sampling() const { - if(features.target_api==VULKAN) - return true; - else if(features.target_api==OPENGL_ES) + if(features.target_api==OPENGL_ES) return check_version(Version(3, 20)); else if(check_version(Version(4, 0))) return true; @@ -597,9 +625,7 @@ bool QualifierConverter::supports_sample_sampling() const bool QualifierConverter::supports_uniform_location() const { - if(features.target_api==VULKAN) - return true; - else if(features.target_api==OPENGL_ES) + if(features.target_api==OPENGL_ES) return check_version(Version(3, 10)); else if(check_version(Version(4, 30))) return true; @@ -609,14 +635,22 @@ bool QualifierConverter::supports_uniform_location() const bool QualifierConverter::supports_binding() const { - if(features.target_api==VULKAN) - return true; - else if(features.target_api==OPENGL_ES) + if(features.target_api==OPENGL_ES) return check_version(Version(3, 10)); else return check_version(Version(4, 20)); } +bool QualifierConverter::supports_interface_block_location() const +{ + if(features.target_api==OPENGL_ES) + return check_version(Version(3, 20)); + else if(check_version(Version(4, 40))) + return true; + else + return check_extension(&Features::arb_enhanced_layouts); +} + void QualifierConverter::visit(VariableDeclaration &var) { if(var.layout) @@ -627,7 +661,9 @@ void QualifierConverter::visit(VariableDeclaration &var) { bool supported = true; bool external = false; - if(var.interface=="in") + if(var.block_declaration) + supported = supports_interface_block_location(); + else if(var.interface=="in") { external = (stage->type==Stage::VERTEX); supported = (external ? supports_interface_layouts() : supports_stage_interface_layouts()); @@ -657,7 +693,9 @@ void QualifierConverter::visit(VariableDeclaration &var) } else if(i->name=="binding" && !supports_binding()) { - if(dynamic_cast(get_ultimate_base_type(var.type_declaration))) + if(var.block_declaration) + stage->uniform_block_bindings[var.block_declaration->block_name] = i->value; + else if(dynamic_cast(get_ultimate_base_type(var.type_declaration))) stage->texture_bindings[var.name] = i->value; i = var.layout->qualifiers.erase(i); @@ -688,40 +726,6 @@ void QualifierConverter::visit(VariableDeclaration &var) TraversingVisitor::visit(var); } -bool QualifierConverter::supports_interface_block_location() const -{ - if(features.target_api==VULKAN) - return true; - else if(features.target_api==OPENGL_ES) - return check_version(Version(3, 20)); - else if(check_version(Version(4, 40))) - return true; - else - return check_extension(&Features::arb_enhanced_layouts); -} - -void QualifierConverter::visit(InterfaceBlock &iface) -{ - if(iface.layout) - { - for(auto 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 if(i->name=="binding" && !supports_binding()) - { - stage->uniform_block_bindings[iface.block_name] = i->value; - i = iface.layout->qualifiers.erase(i); - } - else - ++i; - } - - if(iface.layout->qualifiers.empty()) - iface.layout = 0; - } -} - } // namespace SL } // namespace GL } // namespace Msp