From c32051dc7e77faf0fe6bdad2a6f1025e7b43da19 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Mon, 8 Nov 2021 19:56:45 +0200 Subject: [PATCH] Split FeatureConverter into two parts --- source/glsl/compiler.cpp | 3 +- source/glsl/finalize.cpp | 211 +++++++++++++++++++++------------------ source/glsl/finalize.h | 46 +++++++-- 3 files changed, 155 insertions(+), 105 deletions(-) diff --git a/source/glsl/compiler.cpp b/source/glsl/compiler.cpp index b3ffba14..9ddafcff 100644 --- a/source/glsl/compiler.cpp +++ b/source/glsl/compiler.cpp @@ -396,7 +396,8 @@ void Compiler::finalize(Stage &stage, Mode mode) { if(mode==PROGRAM) { - FeatureConverter().apply(stage, features); + StructuralFeatureConverter().apply(stage, features); + QualifierConverter().apply(stage, features); resolve(stage, RESOLVE_VARIABLES|RESOLVE_FUNCTIONS); PrecisionConverter().apply(stage); } diff --git a/source/glsl/finalize.cpp b/source/glsl/finalize.cpp index 27760afe..1a8f7542 100644 --- a/source/glsl/finalize.cpp +++ b/source/glsl/finalize.cpp @@ -314,16 +314,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 +331,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) { @@ -388,7 +395,7 @@ 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) return check_version(Version(3, 0)); @@ -396,7 +403,7 @@ bool FeatureConverter::supports_unified_interface_syntax() const 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 +412,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,14 +429,14 @@ 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) return check_version(Version(3, 0)); @@ -437,7 +444,7 @@ bool FeatureConverter::supports_unified_sampling_functions() const 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,7 +481,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==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 = 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((!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"); + } +} + + +void QualifierConverter::apply() +{ + stage->content.visit(*this); +} + +bool QualifierConverter::supports_interface_layouts() const { if(features.target_api==OPENGL_ES) return check_version(Version(3, 0)); @@ -486,7 +557,7 @@ 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) return check_version(Version(3, 10)); @@ -496,7 +567,7 @@ 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) return check_version(Version(3, 0)); @@ -506,7 +577,7 @@ 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) return check_version(Version(3, 20)); @@ -516,7 +587,7 @@ 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) return check_version(Version(3, 10)); @@ -526,7 +597,7 @@ 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) return check_version(Version(3, 10)); @@ -534,7 +605,7 @@ bool FeatureConverter::supports_binding() const return check_version(Version(4, 20)); } -void FeatureConverter::visit(VariableDeclaration &var) +void QualifierConverter::visit(VariableDeclaration &var) { if(var.layout) { @@ -601,15 +672,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,24 +679,7 @@ void FeatureConverter::visit(VariableDeclaration &var) TraversingVisitor::visit(var); } -bool FeatureConverter::supports_interface_blocks(const string &iface) 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))) - return true; - else if(iface=="uniform") - return check_extension(&Features::arb_uniform_buffer_object); - else - return false; -} - -bool FeatureConverter::supports_interface_block_location() const +bool QualifierConverter::supports_interface_block_location() const { if(features.target_api==OPENGL_ES) return check_version(Version(3, 20)); @@ -644,9 +689,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 +703,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 diff --git a/source/glsl/finalize.h b/source/glsl/finalize.h index 6fa0b094..263be454 100644 --- a/source/glsl/finalize.h +++ b/source/glsl/finalize.h @@ -76,13 +76,31 @@ private: virtual void visit(VariableDeclaration &); }; +/** Base class for feature converters. */ +class FeatureConverter: protected TraversingVisitor +{ +protected: + Stage *stage = 0; + Features features; + + FeatureConverter() = default; + +public: + void apply(Stage &, const Features &); +protected: + virtual void apply() = 0; + + void unsupported(const std::string &); + + bool check_version(const Version &) const; + bool check_extension(bool Features::*) const; +}; + /** Converts structures of the syntax tree to match a particular set of features. */ -class FeatureConverter: private TraversingVisitor +class StructuralFeatureConverter: public FeatureConverter { private: - Stage *stage = 0; - Features features; VariableDeclaration *frag_out = 0; NodeList::iterator uniform_insert_point; std::set nodes_to_remove; @@ -90,15 +108,12 @@ private: bool r_flattened_interface = false; public: - virtual void apply(Stage &, const Features &); - + void apply(Stage &s, const Features &f) { FeatureConverter::apply(s, f); } private: - void unsupported(const std::string &); + virtual void apply(); virtual void visit(Block &); virtual void visit(RefPtr &); - bool check_version(const Version &) const; - bool check_extension(bool Features::*) const; bool supports_stage(Stage::Type) const; bool supports_unified_interface_syntax() const; virtual void visit(VariableReference &); @@ -107,6 +122,20 @@ private: virtual void visit(Assignment &); bool supports_unified_sampling_functions() const; virtual void visit(FunctionCall &); + virtual void visit(VariableDeclaration &); + bool supports_interface_blocks(const std::string &) const; + virtual void visit(InterfaceBlock &); +}; + +/** Converts qualifiers on variables and blocksto match a particular set of +features. */ +class QualifierConverter: private FeatureConverter +{ +public: + void apply(Stage &s, const Features &f) { FeatureConverter::apply(s, f); } +private: + virtual void apply(); + bool supports_interface_layouts() const; bool supports_stage_interface_layouts() const; bool supports_centroid_sampling() const; @@ -114,7 +143,6 @@ private: bool supports_uniform_location() const; bool supports_binding() const; virtual void visit(VariableDeclaration &); - bool supports_interface_blocks(const std::string &) const; bool supports_interface_block_location() const; virtual void visit(InterfaceBlock &); }; -- 2.45.2