X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fglsl%2Ffinalize.cpp;h=60312be8adf8fc09cdb6a55ed76de342b9f3da46;hp=27760afeabb4770d9d79028c52019ace496e9d82;hb=76cc18518fc8b0b4fa11fda153e7d9b3899ed112;hpb=37e2139a0c5721ea7e0104b5afc4cd97ad2dcb6c diff --git a/source/glsl/finalize.cpp b/source/glsl/finalize.cpp index 27760afe..60312be8 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,11 +62,15 @@ 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); - allocate_locations("uniform"); + + if(features.target_api!=VULKAN) + allocate_locations("uniform"); for(InterfaceBlock *b: unbound_blocks) bind_uniform(b->layout, b->block_name, features.uniform_binding_range); @@ -109,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); @@ -128,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; @@ -143,28 +145,52 @@ 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; 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 = 0; + int bind_point = get_layout_value(layout.get(), "binding"); - layout->qualifiers.push_back(Layout::Qualifier(name, value)); + if(features.target_api==VULKAN) + { + desc_set = get_layout_value(layout.get(), "set"); + 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; + } + + if(bind_point>=0) + { + used_bindings[desc_set].insert(bind_point); + uniforms[name].bind_point = bind_point; + } + + return bind_point>=0; } void LocationAllocator::visit(VariableDeclaration &var) @@ -174,13 +200,13 @@ void LocationAllocator::visit(VariableDeclaration &var) if(!var.interface.empty()) { - 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) @@ -197,20 +223,9 @@ void LocationAllocator::visit(VariableDeclaration &var) if(var.interface=="uniform") { - const TypeDeclaration *type = var.type_declaration; - while(const BasicTypeDeclaration *basic = dynamic_cast(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); - } + 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); } } @@ -221,25 +236,9 @@ void LocationAllocator::visit(InterfaceBlock &iface) if(iface.interface=="uniform") { - 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()); - } - - if(!push_constant) - { - 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); - } + bool push_constant = has_layout_qualifier(iface.layout.get(), "push_constant"); + if(!push_constant && !visit_uniform(iface.block_name, iface.layout)) + unbound_blocks.push_back(&iface); } } @@ -314,16 +313,11 @@ void FeatureConverter::apply(Stage &s, const Features &feat) { stage = &s; features = feat; - if(supports_stage(s.type)) - { - s.content.visit(*this); - NodeRemover().apply(s, nodes_to_remove); - if(!stage->required_features.glsl_version) - stage->required_features.glsl_version = Version(1, (stage->required_features.target_api==OPENGL_ES ? 0 : 10)); - } - else - unsupported(format("Stage %s is not supported", Stage::get_stage_name(s.type))); + if(!stage->required_features.glsl_version) + stage->required_features.glsl_version = Version(1, (stage->required_features.target_api==OPENGL_ES ? 0 : 10)); + + apply(); } void FeatureConverter::unsupported(const string &reason) @@ -336,25 +330,6 @@ void FeatureConverter::unsupported(const string &reason) stage->diagnostics.push_back(diagnostic); } -void FeatureConverter::visit(Block &block) -{ - for(auto i=block.body.begin(); i!=block.body.end(); ++i) - { - if(&block==&stage->content) - uniform_insert_point = i; - (*i)->visit(*this); - } -} - -void FeatureConverter::visit(RefPtr &expr) -{ - r_replaced_reference = 0; - expr->visit(*this); - if(r_replaced_reference) - expr = r_replaced_reference; - r_replaced_reference = 0; -} - bool FeatureConverter::check_version(const Version &feature_version) const { if(features.glsl_versiontype)) + { + stage->content.visit(*this); + NodeRemover().apply(*stage, nodes_to_remove); + } + else + unsupported(format("Stage %s is not supported", Stage::get_stage_name(stage->type))); +} + +void StructuralFeatureConverter::visit(Block &block) +{ + for(auto i=block.body.begin(); i!=block.body.end(); ++i) + { + if(&block==&stage->content) + uniform_insert_point = i; + (*i)->visit(*this); + } +} + +void StructuralFeatureConverter::visit(RefPtr &expr) +{ + r_replaced_reference = 0; + expr->visit(*this); + if(r_replaced_reference) + expr = r_replaced_reference; + r_replaced_reference = 0; +} + +bool StructuralFeatureConverter::supports_stage(Stage::Type st) const { if(st==Stage::GEOMETRY) { - if(features.target_api==OPENGL_ES) + if(features.target_api==VULKAN) + return true; + else if(features.target_api==OPENGL_ES) return check_version(Version(3, 20)); else return check_version(Version(1, 50)); @@ -388,15 +396,17 @@ bool FeatureConverter::supports_stage(Stage::Type st) const return true; } -bool FeatureConverter::supports_unified_interface_syntax() const +bool StructuralFeatureConverter::supports_unified_interface_syntax() const { - if(features.target_api==OPENGL_ES) + if(features.target_api==VULKAN) + return true; + else if(features.target_api==OPENGL_ES) return check_version(Version(3, 0)); else return check_version(Version(1, 30)); } -void FeatureConverter::visit(VariableReference &var) +void StructuralFeatureConverter::visit(VariableReference &var) { if(var.declaration==frag_out && !supports_unified_interface_syntax()) { @@ -405,12 +415,12 @@ void FeatureConverter::visit(VariableReference &var) } } -void FeatureConverter::visit(InterfaceBlockReference &iface) +void StructuralFeatureConverter::visit(InterfaceBlockReference &iface) { r_flattened_interface = nodes_to_remove.count(iface.declaration); } -void FeatureConverter::visit(MemberAccess &memacc) +void StructuralFeatureConverter::visit(MemberAccess &memacc) { r_flattened_interface = false; visit(memacc.left); @@ -422,22 +432,24 @@ void FeatureConverter::visit(MemberAccess &memacc) } } -void FeatureConverter::visit(Assignment &assign) +void StructuralFeatureConverter::visit(Assignment &assign) { TraversingVisitor::visit(assign); if(assign.target.declaration==frag_out && !supports_unified_interface_syntax()) assign.target.declaration = 0; } -bool FeatureConverter::supports_unified_sampling_functions() const +bool StructuralFeatureConverter::supports_unified_sampling_functions() const { - if(features.target_api==OPENGL_ES) + if(features.target_api==VULKAN) + return true; + else if(features.target_api==OPENGL_ES) return check_version(Version(3, 0)); else return check_version(Version(1, 30)); } -void FeatureConverter::visit(FunctionCall &call) +void StructuralFeatureConverter::visit(FunctionCall &call) { if(call.declaration && call.declaration->source==BUILTIN_SOURCE) { @@ -474,9 +486,71 @@ void FeatureConverter::visit(FunctionCall &call) TraversingVisitor::visit(call); } -bool FeatureConverter::supports_interface_layouts() const +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(iface=="uniform") + return check_version(Version(3, 0)); + else + return check_version(Version(3, 20)); + } + else if(check_version(Version(1, 50))) + return true; + else if(iface=="uniform") + return check_extension(&Features::arb_uniform_buffer_object); + else + return false; +} + +void StructuralFeatureConverter::visit(InterfaceBlock &iface) +{ + bool push_constant = has_layout_qualifier(iface.layout.get(), "push_constant"); + 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) + { + 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); + } + 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"); + } +} + + +void QualifierConverter::apply() { - if(features.target_api==OPENGL_ES) + stage->content.visit(*this); +} + +bool QualifierConverter::supports_interface_layouts() const +{ + if(features.target_api==VULKAN) + return true; + else if(features.target_api==OPENGL_ES) return check_version(Version(3, 0)); else if(check_version(Version(3, 30))) return true; @@ -486,9 +560,11 @@ bool FeatureConverter::supports_interface_layouts() const return false; } -bool FeatureConverter::supports_stage_interface_layouts() const +bool QualifierConverter::supports_stage_interface_layouts() const { - if(features.target_api==OPENGL_ES) + if(features.target_api==VULKAN) + return true; + else if(features.target_api==OPENGL_ES) return check_version(Version(3, 10)); else if(check_version(Version(4, 10))) return true; @@ -496,9 +572,11 @@ bool FeatureConverter::supports_stage_interface_layouts() const return check_extension(&Features::arb_separate_shader_objects); } -bool FeatureConverter::supports_centroid_sampling() const +bool QualifierConverter::supports_centroid_sampling() const { - if(features.target_api==OPENGL_ES) + if(features.target_api==VULKAN) + return true; + else if(features.target_api==OPENGL_ES) return check_version(Version(3, 0)); else if(check_version(Version(1, 20))) return true; @@ -506,9 +584,11 @@ bool FeatureConverter::supports_centroid_sampling() const return check_extension(&Features::ext_gpu_shader4); } -bool FeatureConverter::supports_sample_sampling() const +bool QualifierConverter::supports_sample_sampling() const { - if(features.target_api==OPENGL_ES) + 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, 0))) return true; @@ -516,9 +596,11 @@ bool FeatureConverter::supports_sample_sampling() const return check_extension(&Features::arb_gpu_shader5); } -bool FeatureConverter::supports_uniform_location() const +bool QualifierConverter::supports_uniform_location() const { - if(features.target_api==OPENGL_ES) + if(features.target_api==VULKAN) + return true; + else if(features.target_api==OPENGL_ES) return check_version(Version(3, 10)); else if(check_version(Version(4, 30))) return true; @@ -526,15 +608,17 @@ bool FeatureConverter::supports_uniform_location() const return check_extension(&Features::arb_explicit_uniform_location); } -bool FeatureConverter::supports_binding() const +bool QualifierConverter::supports_binding() const { - if(features.target_api==OPENGL_ES) + if(features.target_api==VULKAN) + return true; + else if(features.target_api==OPENGL_ES) return check_version(Version(3, 10)); else return check_version(Version(4, 20)); } -void FeatureConverter::visit(VariableDeclaration &var) +void QualifierConverter::visit(VariableDeclaration &var) { if(var.layout) { @@ -574,10 +658,7 @@ void FeatureConverter::visit(VariableDeclaration &var) } 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)) + if(dynamic_cast(get_ultimate_base_type(var.type_declaration))) stage->texture_bindings[var.name] = i->value; i = var.layout->qualifiers.erase(i); @@ -601,15 +682,6 @@ void FeatureConverter::visit(VariableDeclaration &var) var.sampling = string(); } - 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); - } - } - if(var.name=="gl_ClipDistance") if(const Literal *literal_size = dynamic_cast(var.array_size.get())) stage->n_clip_distances = literal_size->value.value(); @@ -617,26 +689,11 @@ void FeatureConverter::visit(VariableDeclaration &var) TraversingVisitor::visit(var); } -bool FeatureConverter::supports_interface_blocks(const string &iface) const +bool QualifierConverter::supports_interface_block_location() const { - if(features.target_api==OPENGL_ES) - { - if(iface=="uniform") - return check_version(Version(3, 0)); - else - return check_version(Version(3, 20)); - } - else if(check_version(Version(1, 50))) + if(features.target_api==VULKAN) return true; - else if(iface=="uniform") - return check_extension(&Features::arb_uniform_buffer_object); - else - return false; -} - -bool FeatureConverter::supports_interface_block_location() const -{ - if(features.target_api==OPENGL_ES) + else if(features.target_api==OPENGL_ES) return check_version(Version(3, 20)); else if(check_version(Version(4, 40))) return true; @@ -644,9 +701,8 @@ bool FeatureConverter::supports_interface_block_location() const return check_extension(&Features::arb_enhanced_layouts); } -void FeatureConverter::visit(InterfaceBlock &iface) +void QualifierConverter::visit(InterfaceBlock &iface) { - bool push_constant = false; if(iface.layout) { for(auto i=iface.layout->qualifiers.begin(); i!=iface.layout->qualifiers.end(); ) @@ -659,35 +715,12 @@ void FeatureConverter::visit(InterfaceBlock &iface) i = iface.layout->qualifiers.erase(i); } else - { - if(i->name=="push_constant") - push_constant = true; ++i; - } } if(iface.layout->qualifiers.empty()) iface.layout = 0; } - - if((!supports_interface_blocks(iface.interface) || push_constant) && iface.type_declaration) - { - if(!iface.instance_name.empty()) - unsupported("ARB_uniform_buffer_object required for interface block instances"); - else if(iface.struct_declaration) - { - 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); - } - 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"); - } } } // namespace SL