From: Mikko Rasa Date: Wed, 31 Mar 2021 18:07:07 +0000 (+0300) Subject: Rename compatibility.* to finalize.* X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=commitdiff_plain;h=c8de66203565f07f10898a74dbd55072432790fc Rename compatibility.* to finalize.* This seems more appropriate for some SPIR-V stuff I'm going to add. --- diff --git a/source/glsl/compatibility.cpp b/source/glsl/compatibility.cpp deleted file mode 100644 index 280a38c9..00000000 --- a/source/glsl/compatibility.cpp +++ /dev/null @@ -1,361 +0,0 @@ -#include -#include -#include -#include "compatibility.h" -#include "glsl_error.h" - -using namespace std; - -namespace Msp { -namespace GL { -namespace SL { - -DefaultPrecisionGenerator::DefaultPrecisionGenerator(): - stage(0) -{ } - -void DefaultPrecisionGenerator::apply(Stage &s) -{ - stage = &s; - s.content.visit(*this); -} - -void DefaultPrecisionGenerator::visit(Block &block) -{ - for(NodeList::iterator i=block.body.begin(); i!=block.body.end(); ++i) - { - if(&block==&stage->content) - insert_point = i; - (*i)->visit(*this); - } -} - -void DefaultPrecisionGenerator::visit(Precision &prec) -{ - have_default.insert(prec.type); -} - -void DefaultPrecisionGenerator::visit(VariableDeclaration &var) -{ - if(var.type_declaration) - return; - - string type = var.type; - if(!type.compare(0, 3, "vec") || !type.compare(0, 3, "mat")) - type = "float"; - else if(!type.compare(0, 3, "ivec") || type=="uint") - type = "int"; - - if(!have_default.count(type)) - { - Precision *prec = new Precision; - if(!type.compare(0, 7, "sampler")) - prec->precision = "lowp"; - else if(stage->type==Stage::FRAGMENT) - prec->precision = "mediump"; - else - prec->precision = "highp"; - prec->type = type; - stage->content.body.insert(insert_point, prec); - - have_default.insert(type); - } -} - - -void PrecisionRemover::apply(Stage &stage) -{ - stage.content.visit(*this); - NodeRemover().apply(stage, nodes_to_remove); -} - -void PrecisionRemover::visit(Precision &prec) -{ - nodes_to_remove.insert(&prec); -} - -void PrecisionRemover::visit(VariableDeclaration &var) -{ - var.precision.clear(); -} - - -LegacyConverter::LegacyConverter(): - frag_out(0) -{ } - -void LegacyConverter::apply(Stage &s, const Features &feat) -{ - stage = &s; - features = feat; - if(supports_stage(s.type)) - s.content.visit(*this); - else - unsupported(format("Stage %s is not supported", Stage::get_stage_name(s.type))); -} - -void LegacyConverter::unsupported(const string &reason) -{ - Diagnostic diagnostic; - diagnostic.severity = Diagnostic::ERR; - diagnostic.source = GENERATED_SOURCE; - diagnostic.line = 0; - diagnostic.message = reason; - stage->diagnostics.push_back(diagnostic); -} - -void LegacyConverter::visit(Block &block) -{ - for(NodeList::iterator i=block.body.begin(); i!=block.body.end(); ++i) - { - if(&block==&stage->content) - uniform_insert_point = i; - (*i)->visit(*this); - } -} - -bool LegacyConverter::check_version(const Version &feature_version) const -{ - if(features.glsl_versionrequired_features.glsl_versionrequired_features.glsl_version = feature_version; - - return true; -} - -bool LegacyConverter::check_extension(bool Features::*extension) const -{ - if(!(features.*extension)) - return false; - - stage->required_features.*extension = true; - - return true; -} - -bool LegacyConverter::supports_stage(Stage::Type st) const -{ - if(st==Stage::GEOMETRY) - { - if(features.gl_api==OPENGL_ES2) - return check_version(Version(3, 20)); - else - return check_version(Version(1, 50)); - } - else - return true; -} - -bool LegacyConverter::supports_unified_interface_syntax() const -{ - if(features.gl_api==OPENGL_ES2) - return check_version(Version(3, 0)); - else - return check_version(Version(1, 30)); -} - -void LegacyConverter::visit(VariableReference &var) -{ - if(var.declaration==frag_out && !supports_unified_interface_syntax()) - { - var.name = "gl_FragColor"; - var.declaration = 0; - r_type = "vec4"; - } - else if(var.declaration) - r_type = var.declaration->type; - else - r_type.clear(); -} - -void LegacyConverter::visit(Assignment &assign) -{ - TraversingVisitor::visit(assign); - if(assign.target.declaration==frag_out && !supports_unified_interface_syntax()) - assign.target.declaration = 0; -} - -bool LegacyConverter::supports_unified_sampling_functions() const -{ - if(features.gl_api==OPENGL_ES2) - return check_version(Version(3, 0)); - else - return check_version(Version(1, 30)); -} - -void LegacyConverter::visit(FunctionCall &call) -{ - if(call.name=="texture") - { - string sampler_type; - r_type.clear(); - NodeArray::iterator i = call.arguments.begin(); - if(i!=call.arguments.end()) - { - (*i)->visit(*this); - sampler_type = r_type; - - for(; i!=call.arguments.end(); ++i) - (*i)->visit(*this); - } - - if(!supports_unified_sampling_functions()) - { - if(sampler_type=="sampler1D") - call.name = "texture1D"; - else if(sampler_type=="sampler2D") - call.name = "texture2D"; - else if(sampler_type=="sampler3D") - call.name = "texture3D"; - else if(sampler_type=="samplerCube") - call.name = "textureCube"; - else if(sampler_type=="sampler1DShadow") - call.name = "shadow1D"; - else if(sampler_type=="sampler2DShadow") - call.name = "shadow2D"; - else if(sampler_type=="sampler1DArray") - { - check_extension(&Features::ext_texture_array); - call.name = "texture1DArray"; - } - else if(sampler_type=="sampler2DArray") - { - check_extension(&Features::ext_texture_array); - call.name = "texture2DArray"; - } - else if(sampler_type=="sampler1DArrayShadow") - { - check_extension(&Features::ext_texture_array); - call.name = "shadow1DArray"; - } - else if(sampler_type=="sampler2DArrayShadow") - { - check_extension(&Features::ext_texture_array); - call.name = "shadow2DArray"; - } - } - } - else - TraversingVisitor::visit(call); -} - -bool LegacyConverter::supports_interface_layouts() const -{ - if(features.gl_api==OPENGL_ES2) - return check_version(Version(3, 0)); - else if(check_version(Version(3, 30))) - return true; - else - return check_extension(&Features::arb_explicit_attrib_location); -} - -bool LegacyConverter::supports_centroid_sampling() const -{ - if(features.gl_api==OPENGL_ES2) - return check_version(Version(3, 0)); - else if(check_version(Version(1, 20))) - return true; - else - return check_extension(&Features::ext_gpu_shader4); -} - -bool LegacyConverter::supports_sample_sampling() const -{ - if(features.gl_api==OPENGL_ES2) - return check_version(Version(3, 20)); - else if(check_version(Version(4, 0))) - return true; - else - return check_extension(&Features::arb_gpu_shader5); -} - -void LegacyConverter::visit(VariableDeclaration &var) -{ - if(var.layout && !supports_interface_layouts()) - { - vector::iterator i; - for(i=var.layout->qualifiers.begin(); (i!=var.layout->qualifiers.end() && i->name!="location"); ++i) ; - if(i!=var.layout->qualifiers.end()) - { - if(stage->type==Stage::VERTEX && var.interface=="in") - { - stage->locations[var.name] = i->value; - var.layout->qualifiers.erase(i); - } - else if(stage->type==Stage::FRAGMENT && var.interface=="out") - { - 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"); - var.layout->qualifiers.erase(i); - } - - if(var.layout->qualifiers.empty()) - var.layout = 0; - } - } - - if(var.sampling=="centroid") - { - if(!supports_centroid_sampling()) - var.sampling = string(); - } - else if(var.sampling=="sample") - { - if(!supports_sample_sampling()) - 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); - } - } - - TraversingVisitor::visit(var); -} - -bool LegacyConverter::supports_interface_blocks(const string &iface) const -{ - if(features.gl_api==OPENGL_ES2) - { - 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 LegacyConverter::visit(InterfaceBlock &iface) -{ - if(!supports_interface_blocks(iface.interface) && iface.type_declaration) - { - if(!iface.instance_name.empty()) - unsupported("ARB_uniform_buffer_object required for interface block instances"); - else if(iface.struct_declaration) - { - 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 -} // namespace GL -} // namespace Msp diff --git a/source/glsl/compatibility.h b/source/glsl/compatibility.h deleted file mode 100644 index 21200713..00000000 --- a/source/glsl/compatibility.h +++ /dev/null @@ -1,87 +0,0 @@ -#ifndef MSP_GL_SL_COMPATIBILITY_H_ -#define MSP_GL_SL_COMPATIBILITY_H_ - -#include -#include "visitor.h" - -namespace Msp { -namespace GL { -namespace SL { - -/** Generates default precision declarations if they are missing, to satisfy -GLSL ES requirements. */ -class DefaultPrecisionGenerator: private TraversingVisitor -{ -private: - Stage *stage; - std::set have_default; - NodeList::iterator insert_point; - -public: - DefaultPrecisionGenerator(); - - void apply(Stage &); - -private: - virtual void visit(Block &); - virtual void visit(Precision &); - virtual void visit(VariableDeclaration &); -}; - -/** Removes precision qualifiers from variable declarations, as well as -default precision declarations. */ -class PrecisionRemover: private TraversingVisitor -{ -private: - std::set nodes_to_remove; - -public: - void apply(Stage &); - -private: - virtual void visit(Precision &); - virtual void visit(VariableDeclaration &); -}; - -/** Converts structures of the syntax tree to match a particular set of -features. */ -class LegacyConverter: private TraversingVisitor -{ -private: - Stage *stage; - Features features; - std::string r_type; - VariableDeclaration *frag_out; - NodeList::iterator uniform_insert_point; - std::set nodes_to_remove; - -public: - LegacyConverter(); - - virtual void apply(Stage &, const Features &); - -private: - void unsupported(const std::string &); - - virtual void visit(Block &); - 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 &); - virtual void visit(Assignment &); - bool supports_unified_sampling_functions() const; - virtual void visit(FunctionCall &); - bool supports_interface_layouts() const; - bool supports_centroid_sampling() const; - bool supports_sample_sampling() const; - virtual void visit(VariableDeclaration &); - bool supports_interface_blocks(const std::string &) const; - virtual void visit(InterfaceBlock &); -}; - -} // namespace SL -} // namespace GL -} // namespace Msp - -#endif diff --git a/source/glsl/compiler.cpp b/source/glsl/compiler.cpp index 03bde487..e8b06c86 100644 --- a/source/glsl/compiler.cpp +++ b/source/glsl/compiler.cpp @@ -2,10 +2,10 @@ #include #include #include "builtin.h" -#include "compatibility.h" #include "compiler.h" #include "debug.h" #include "error.h" +#include "finalize.h" #include "generate.h" #include "glsl_error.h" #include "optimize.h" diff --git a/source/glsl/finalize.cpp b/source/glsl/finalize.cpp new file mode 100644 index 00000000..fb76ab6d --- /dev/null +++ b/source/glsl/finalize.cpp @@ -0,0 +1,361 @@ +#include +#include +#include +#include "finalize.h" +#include "glsl_error.h" + +using namespace std; + +namespace Msp { +namespace GL { +namespace SL { + +DefaultPrecisionGenerator::DefaultPrecisionGenerator(): + stage(0) +{ } + +void DefaultPrecisionGenerator::apply(Stage &s) +{ + stage = &s; + s.content.visit(*this); +} + +void DefaultPrecisionGenerator::visit(Block &block) +{ + for(NodeList::iterator i=block.body.begin(); i!=block.body.end(); ++i) + { + if(&block==&stage->content) + insert_point = i; + (*i)->visit(*this); + } +} + +void DefaultPrecisionGenerator::visit(Precision &prec) +{ + have_default.insert(prec.type); +} + +void DefaultPrecisionGenerator::visit(VariableDeclaration &var) +{ + if(var.type_declaration) + return; + + string type = var.type; + if(!type.compare(0, 3, "vec") || !type.compare(0, 3, "mat")) + type = "float"; + else if(!type.compare(0, 3, "ivec") || type=="uint") + type = "int"; + + if(!have_default.count(type)) + { + Precision *prec = new Precision; + if(!type.compare(0, 7, "sampler")) + prec->precision = "lowp"; + else if(stage->type==Stage::FRAGMENT) + prec->precision = "mediump"; + else + prec->precision = "highp"; + prec->type = type; + stage->content.body.insert(insert_point, prec); + + have_default.insert(type); + } +} + + +void PrecisionRemover::apply(Stage &stage) +{ + stage.content.visit(*this); + NodeRemover().apply(stage, nodes_to_remove); +} + +void PrecisionRemover::visit(Precision &prec) +{ + nodes_to_remove.insert(&prec); +} + +void PrecisionRemover::visit(VariableDeclaration &var) +{ + var.precision.clear(); +} + + +LegacyConverter::LegacyConverter(): + frag_out(0) +{ } + +void LegacyConverter::apply(Stage &s, const Features &feat) +{ + stage = &s; + features = feat; + if(supports_stage(s.type)) + s.content.visit(*this); + else + unsupported(format("Stage %s is not supported", Stage::get_stage_name(s.type))); +} + +void LegacyConverter::unsupported(const string &reason) +{ + Diagnostic diagnostic; + diagnostic.severity = Diagnostic::ERR; + diagnostic.source = GENERATED_SOURCE; + diagnostic.line = 0; + diagnostic.message = reason; + stage->diagnostics.push_back(diagnostic); +} + +void LegacyConverter::visit(Block &block) +{ + for(NodeList::iterator i=block.body.begin(); i!=block.body.end(); ++i) + { + if(&block==&stage->content) + uniform_insert_point = i; + (*i)->visit(*this); + } +} + +bool LegacyConverter::check_version(const Version &feature_version) const +{ + if(features.glsl_versionrequired_features.glsl_versionrequired_features.glsl_version = feature_version; + + return true; +} + +bool LegacyConverter::check_extension(bool Features::*extension) const +{ + if(!(features.*extension)) + return false; + + stage->required_features.*extension = true; + + return true; +} + +bool LegacyConverter::supports_stage(Stage::Type st) const +{ + if(st==Stage::GEOMETRY) + { + if(features.gl_api==OPENGL_ES2) + return check_version(Version(3, 20)); + else + return check_version(Version(1, 50)); + } + else + return true; +} + +bool LegacyConverter::supports_unified_interface_syntax() const +{ + if(features.gl_api==OPENGL_ES2) + return check_version(Version(3, 0)); + else + return check_version(Version(1, 30)); +} + +void LegacyConverter::visit(VariableReference &var) +{ + if(var.declaration==frag_out && !supports_unified_interface_syntax()) + { + var.name = "gl_FragColor"; + var.declaration = 0; + r_type = "vec4"; + } + else if(var.declaration) + r_type = var.declaration->type; + else + r_type.clear(); +} + +void LegacyConverter::visit(Assignment &assign) +{ + TraversingVisitor::visit(assign); + if(assign.target.declaration==frag_out && !supports_unified_interface_syntax()) + assign.target.declaration = 0; +} + +bool LegacyConverter::supports_unified_sampling_functions() const +{ + if(features.gl_api==OPENGL_ES2) + return check_version(Version(3, 0)); + else + return check_version(Version(1, 30)); +} + +void LegacyConverter::visit(FunctionCall &call) +{ + if(call.name=="texture") + { + string sampler_type; + r_type.clear(); + NodeArray::iterator i = call.arguments.begin(); + if(i!=call.arguments.end()) + { + (*i)->visit(*this); + sampler_type = r_type; + + for(; i!=call.arguments.end(); ++i) + (*i)->visit(*this); + } + + if(!supports_unified_sampling_functions()) + { + if(sampler_type=="sampler1D") + call.name = "texture1D"; + else if(sampler_type=="sampler2D") + call.name = "texture2D"; + else if(sampler_type=="sampler3D") + call.name = "texture3D"; + else if(sampler_type=="samplerCube") + call.name = "textureCube"; + else if(sampler_type=="sampler1DShadow") + call.name = "shadow1D"; + else if(sampler_type=="sampler2DShadow") + call.name = "shadow2D"; + else if(sampler_type=="sampler1DArray") + { + check_extension(&Features::ext_texture_array); + call.name = "texture1DArray"; + } + else if(sampler_type=="sampler2DArray") + { + check_extension(&Features::ext_texture_array); + call.name = "texture2DArray"; + } + else if(sampler_type=="sampler1DArrayShadow") + { + check_extension(&Features::ext_texture_array); + call.name = "shadow1DArray"; + } + else if(sampler_type=="sampler2DArrayShadow") + { + check_extension(&Features::ext_texture_array); + call.name = "shadow2DArray"; + } + } + } + else + TraversingVisitor::visit(call); +} + +bool LegacyConverter::supports_interface_layouts() const +{ + if(features.gl_api==OPENGL_ES2) + return check_version(Version(3, 0)); + else if(check_version(Version(3, 30))) + return true; + else + return check_extension(&Features::arb_explicit_attrib_location); +} + +bool LegacyConverter::supports_centroid_sampling() const +{ + if(features.gl_api==OPENGL_ES2) + return check_version(Version(3, 0)); + else if(check_version(Version(1, 20))) + return true; + else + return check_extension(&Features::ext_gpu_shader4); +} + +bool LegacyConverter::supports_sample_sampling() const +{ + if(features.gl_api==OPENGL_ES2) + return check_version(Version(3, 20)); + else if(check_version(Version(4, 0))) + return true; + else + return check_extension(&Features::arb_gpu_shader5); +} + +void LegacyConverter::visit(VariableDeclaration &var) +{ + if(var.layout && !supports_interface_layouts()) + { + vector::iterator i; + for(i=var.layout->qualifiers.begin(); (i!=var.layout->qualifiers.end() && i->name!="location"); ++i) ; + if(i!=var.layout->qualifiers.end()) + { + if(stage->type==Stage::VERTEX && var.interface=="in") + { + stage->locations[var.name] = i->value; + var.layout->qualifiers.erase(i); + } + else if(stage->type==Stage::FRAGMENT && var.interface=="out") + { + 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"); + var.layout->qualifiers.erase(i); + } + + if(var.layout->qualifiers.empty()) + var.layout = 0; + } + } + + if(var.sampling=="centroid") + { + if(!supports_centroid_sampling()) + var.sampling = string(); + } + else if(var.sampling=="sample") + { + if(!supports_sample_sampling()) + 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); + } + } + + TraversingVisitor::visit(var); +} + +bool LegacyConverter::supports_interface_blocks(const string &iface) const +{ + if(features.gl_api==OPENGL_ES2) + { + 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 LegacyConverter::visit(InterfaceBlock &iface) +{ + if(!supports_interface_blocks(iface.interface) && iface.type_declaration) + { + if(!iface.instance_name.empty()) + unsupported("ARB_uniform_buffer_object required for interface block instances"); + else if(iface.struct_declaration) + { + 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 +} // namespace GL +} // namespace Msp diff --git a/source/glsl/finalize.h b/source/glsl/finalize.h new file mode 100644 index 00000000..21200713 --- /dev/null +++ b/source/glsl/finalize.h @@ -0,0 +1,87 @@ +#ifndef MSP_GL_SL_COMPATIBILITY_H_ +#define MSP_GL_SL_COMPATIBILITY_H_ + +#include +#include "visitor.h" + +namespace Msp { +namespace GL { +namespace SL { + +/** Generates default precision declarations if they are missing, to satisfy +GLSL ES requirements. */ +class DefaultPrecisionGenerator: private TraversingVisitor +{ +private: + Stage *stage; + std::set have_default; + NodeList::iterator insert_point; + +public: + DefaultPrecisionGenerator(); + + void apply(Stage &); + +private: + virtual void visit(Block &); + virtual void visit(Precision &); + virtual void visit(VariableDeclaration &); +}; + +/** Removes precision qualifiers from variable declarations, as well as +default precision declarations. */ +class PrecisionRemover: private TraversingVisitor +{ +private: + std::set nodes_to_remove; + +public: + void apply(Stage &); + +private: + virtual void visit(Precision &); + virtual void visit(VariableDeclaration &); +}; + +/** Converts structures of the syntax tree to match a particular set of +features. */ +class LegacyConverter: private TraversingVisitor +{ +private: + Stage *stage; + Features features; + std::string r_type; + VariableDeclaration *frag_out; + NodeList::iterator uniform_insert_point; + std::set nodes_to_remove; + +public: + LegacyConverter(); + + virtual void apply(Stage &, const Features &); + +private: + void unsupported(const std::string &); + + virtual void visit(Block &); + 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 &); + virtual void visit(Assignment &); + bool supports_unified_sampling_functions() const; + virtual void visit(FunctionCall &); + bool supports_interface_layouts() const; + bool supports_centroid_sampling() const; + bool supports_sample_sampling() const; + virtual void visit(VariableDeclaration &); + bool supports_interface_blocks(const std::string &) const; + virtual void visit(InterfaceBlock &); +}; + +} // namespace SL +} // namespace GL +} // namespace Msp + +#endif