X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fglsl%2Fcompatibility.cpp;h=280a38c9f2c829443991da07f5d6d6713db190a9;hb=a721984a85925a17ae0e43a2198fbc4762d76798;hp=a9f38a35cda42481935864b5bbd97285bbf63462;hpb=ab5f2e6f1ddd35f8f117460530d76c0ba0c9bc87;p=libs%2Fgl.git diff --git a/source/glsl/compatibility.cpp b/source/glsl/compatibility.cpp index a9f38a35..280a38c9 100644 --- a/source/glsl/compatibility.cpp +++ b/source/glsl/compatibility.cpp @@ -1,11 +1,8 @@ #include #include -#include -#include -#include -#include -#include +#include #include "compatibility.h" +#include "glsl_error.h" using namespace std; @@ -20,7 +17,7 @@ DefaultPrecisionGenerator::DefaultPrecisionGenerator(): void DefaultPrecisionGenerator::apply(Stage &s) { stage = &s; - visit(s.content); + s.content.visit(*this); } void DefaultPrecisionGenerator::visit(Block &block) @@ -68,7 +65,7 @@ void DefaultPrecisionGenerator::visit(VariableDeclaration &var) void PrecisionRemover::apply(Stage &stage) { - visit(stage.content); + stage.content.visit(*this); NodeRemover().apply(stage, nodes_to_remove); } @@ -84,15 +81,27 @@ void PrecisionRemover::visit(VariableDeclaration &var) LegacyConverter::LegacyConverter(): - target_api(get_gl_api()), - target_version(get_glsl_version()), frag_out(0) { } -void LegacyConverter::apply(Stage &s) +void LegacyConverter::apply(Stage &s, const Features &feat) { stage = &s; - visit(s.content); + 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) @@ -107,29 +116,40 @@ void LegacyConverter::visit(Block &block) bool LegacyConverter::check_version(const Version &feature_version) const { - if(target_versionrequired_versionrequired_version = feature_version; + else if(stage->required_features.glsl_versionrequired_features.glsl_version = feature_version; return true; } -bool LegacyConverter::check_extension(const Extension &extension) const +bool LegacyConverter::check_extension(bool Features::*extension) const { - if(!extension) + if(!(features.*extension)) return false; - vector::iterator i = find(stage->required_extensions, &extension); - if(i==stage->required_extensions.end()) - stage->required_extensions.push_back(&extension); + 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(target_api==OPENGL_ES2) + if(features.gl_api==OPENGL_ES2) return check_version(Version(3, 0)); else return check_version(Version(1, 30)); @@ -141,24 +161,24 @@ void LegacyConverter::visit(VariableReference &var) { var.name = "gl_FragColor"; var.declaration = 0; - type = "vec4"; + r_type = "vec4"; } else if(var.declaration) - type = var.declaration->type; + r_type = var.declaration->type; else - type = string(); + 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; + if(assign.target.declaration==frag_out && !supports_unified_interface_syntax()) + assign.target.declaration = 0; } bool LegacyConverter::supports_unified_sampling_functions() const { - if(target_api==OPENGL_ES2) + if(features.gl_api==OPENGL_ES2) return check_version(Version(3, 0)); else return check_version(Version(1, 30)); @@ -169,12 +189,12 @@ void LegacyConverter::visit(FunctionCall &call) if(call.name=="texture") { string sampler_type; - type = string(); + r_type.clear(); NodeArray::iterator i = call.arguments.begin(); if(i!=call.arguments.end()) { (*i)->visit(*this); - sampler_type = type; + sampler_type = r_type; for(; i!=call.arguments.end(); ++i) (*i)->visit(*this); @@ -196,22 +216,22 @@ void LegacyConverter::visit(FunctionCall &call) call.name = "shadow2D"; else if(sampler_type=="sampler1DArray") { - check_extension(EXT_texture_array); + check_extension(&Features::ext_texture_array); call.name = "texture1DArray"; } else if(sampler_type=="sampler2DArray") { - check_extension(EXT_texture_array); + check_extension(&Features::ext_texture_array); call.name = "texture2DArray"; } else if(sampler_type=="sampler1DArrayShadow") { - check_extension(EXT_texture_array); + check_extension(&Features::ext_texture_array); call.name = "shadow1DArray"; } else if(sampler_type=="sampler2DArrayShadow") { - check_extension(EXT_texture_array); + check_extension(&Features::ext_texture_array); call.name = "shadow2DArray"; } } @@ -222,32 +242,32 @@ void LegacyConverter::visit(FunctionCall &call) bool LegacyConverter::supports_interface_layouts() const { - if(target_api==OPENGL_ES2) + 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(ARB_explicit_attrib_location); + return check_extension(&Features::arb_explicit_attrib_location); } bool LegacyConverter::supports_centroid_sampling() const { - if(target_api==OPENGL_ES2) + 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(EXT_gpu_shader4); + return check_extension(&Features::ext_gpu_shader4); } bool LegacyConverter::supports_sample_sampling() const { - if(target_api==OPENGL_ES2) + 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(ARB_gpu_shader5); + return check_extension(&Features::arb_gpu_shader5); } void LegacyConverter::visit(VariableDeclaration &var) @@ -255,20 +275,20 @@ 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->identifier!="location"); ++i) ; + for(i=var.layout->qualifiers.begin(); (i!=var.layout->qualifiers.end() && i->name!="location"); ++i) ; if(i!=var.layout->qualifiers.end()) { - unsigned location = lexical_cast(i->value); if(stage->type==Stage::VERTEX && var.interface=="in") { - stage->locations[var.name] = location; + stage->locations[var.name] = i->value; var.layout->qualifiers.erase(i); } else if(stage->type==Stage::FRAGMENT && var.interface=="out") { - if(location!=0) - static Require _req(EXT_gpu_shader4); - stage->locations[var.name] = location; + 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); } @@ -302,7 +322,7 @@ void LegacyConverter::visit(VariableDeclaration &var) bool LegacyConverter::supports_interface_blocks(const string &iface) const { - if(target_api==OPENGL_ES2) + if(features.gl_api==OPENGL_ES2) { if(iface=="uniform") return check_version(Version(3, 0)); @@ -312,17 +332,27 @@ bool LegacyConverter::supports_interface_blocks(const string &iface) const else if(check_version(Version(1, 50))) return true; else if(iface=="uniform") - return check_extension(ARB_uniform_buffer_object); + return check_extension(&Features::arb_uniform_buffer_object); else return false; } void LegacyConverter::visit(InterfaceBlock &iface) { - if(!supports_interface_blocks(iface.interface)) + if(!supports_interface_blocks(iface.interface) && iface.type_declaration) { - stage->content.body.splice(uniform_insert_point, iface.members.body); - nodes_to_remove.insert(&iface); + 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"); } }