1 #include <msp/core/algorithm.h>
2 #include <msp/core/raii.h>
3 #include <msp/gl/extensions/arb_explicit_attrib_location.h>
4 #include <msp/gl/extensions/arb_gpu_shader5.h>
5 #include <msp/gl/extensions/arb_uniform_buffer_object.h>
6 #include <msp/gl/extensions/ext_gpu_shader4.h>
7 #include <msp/gl/extensions/ext_texture_array.h>
8 #include "compatibility.h"
16 DefaultPrecisionGenerator::DefaultPrecisionGenerator():
17 stage_type(Stage::SHARED),
21 void DefaultPrecisionGenerator::apply(Stage &stage)
23 SetForScope<Stage::Type> set_stage(stage_type, stage.type);
27 void DefaultPrecisionGenerator::visit(Block &block)
31 SetForScope<bool> set(toplevel, false);
32 BlockModifier::visit(block);
35 TraversingVisitor::visit(block);
38 void DefaultPrecisionGenerator::visit(Precision &prec)
40 have_default.insert(prec.type);
43 void DefaultPrecisionGenerator::visit(VariableDeclaration &var)
45 if(var.type_declaration)
48 string type = var.type;
49 if(!type.compare(0, 3, "vec") || !type.compare(0, 3, "mat"))
51 else if(!type.compare(0, 3, "ivec") || type=="uint")
54 if(!have_default.count(type))
56 Precision *prec = new Precision;
57 if(!type.compare(0, 7, "sampler"))
58 prec->precision = "lowp";
59 else if(stage_type==Stage::FRAGMENT)
60 prec->precision = "mediump";
62 prec->precision = "highp";
64 insert_nodes.push_back(prec);
66 have_default.insert(type);
71 void PrecisionRemover::visit(Precision &)
76 void PrecisionRemover::visit(VariableDeclaration &var)
78 var.precision.clear();
82 LegacyConverter::LegacyConverter():
83 target_api(get_gl_api()),
84 target_version(get_glsl_version()),
88 LegacyConverter::LegacyConverter(const Version &v):
89 target_api(get_gl_api()),
94 bool LegacyConverter::check_version(const Version &feature_version) const
96 if(target_version<feature_version)
98 else if(stage->required_version<feature_version)
99 stage->required_version = feature_version;
104 bool LegacyConverter::check_extension(const Extension &extension) const
109 vector<const Extension *>::iterator i = find(stage->required_extensions, &extension);
110 if(i==stage->required_extensions.end())
111 stage->required_extensions.push_back(&extension);
116 void LegacyConverter::apply(Stage &s)
118 SetForScope<Stage *> set_stage(stage, &s);
122 bool LegacyConverter::supports_unified_interface_syntax() const
124 if(target_api==OPENGL_ES2)
125 return check_version(Version(3, 0));
127 return check_version(Version(1, 30));
130 void LegacyConverter::visit(VariableReference &var)
132 if(var.declaration==frag_out && !supports_unified_interface_syntax())
134 var.name = "gl_FragColor";
138 else if(var.declaration)
139 type = var.declaration->type;
144 void LegacyConverter::visit(Assignment &assign)
146 TraversingVisitor::visit(assign);
147 if(assign.target_declaration==frag_out && !supports_unified_interface_syntax())
148 assign.target_declaration = 0;
151 bool LegacyConverter::supports_unified_sampling_functions() const
153 if(target_api==OPENGL_ES2)
154 return check_version(Version(3, 0));
156 return check_version(Version(1, 30));
159 void LegacyConverter::visit(FunctionCall &call)
161 if(call.name=="texture")
165 NodeArray<Expression>::iterator i = call.arguments.begin();
166 if(i!=call.arguments.end())
171 for(; i!=call.arguments.end(); ++i)
175 if(!supports_unified_sampling_functions())
177 if(sampler_type=="sampler1D")
178 call.name = "texture1D";
179 else if(sampler_type=="sampler2D")
180 call.name = "texture2D";
181 else if(sampler_type=="sampler3D")
182 call.name = "texture3D";
183 else if(sampler_type=="samplerCube")
184 call.name = "textureCube";
185 else if(sampler_type=="sampler1DShadow")
186 call.name = "shadow1D";
187 else if(sampler_type=="sampler2DShadow")
188 call.name = "shadow2D";
189 else if(sampler_type=="sampler1DArray")
191 check_extension(EXT_texture_array);
192 call.name = "texture1DArray";
194 else if(sampler_type=="sampler2DArray")
196 check_extension(EXT_texture_array);
197 call.name = "texture2DArray";
199 else if(sampler_type=="sampler1DArrayShadow")
201 check_extension(EXT_texture_array);
202 call.name = "shadow1DArray";
204 else if(sampler_type=="sampler2DArrayShadow")
206 check_extension(EXT_texture_array);
207 call.name = "shadow2DArray";
212 TraversingVisitor::visit(call);
215 bool LegacyConverter::supports_interface_layouts() const
217 if(target_api==OPENGL_ES2)
218 return check_version(Version(3, 0));
219 else if(check_version(Version(3, 30)))
222 return check_extension(ARB_explicit_attrib_location);
225 bool LegacyConverter::supports_centroid_sampling() const
227 if(target_api==OPENGL_ES2)
228 return check_version(Version(3, 0));
229 else if(check_version(Version(1, 20)))
232 return check_extension(EXT_gpu_shader4);
235 bool LegacyConverter::supports_sample_sampling() const
237 if(target_api==OPENGL_ES2)
238 return check_version(Version(3, 20));
239 else if(check_version(Version(4, 0)))
242 return check_extension(ARB_gpu_shader5);
245 void LegacyConverter::visit(VariableDeclaration &var)
247 if(var.layout && !supports_interface_layouts())
249 vector<Layout::Qualifier>::iterator i;
250 for(i=var.layout->qualifiers.begin(); (i!=var.layout->qualifiers.end() && i->identifier!="location"); ++i) ;
251 if(i!=var.layout->qualifiers.end())
253 unsigned location = lexical_cast<unsigned>(i->value);
254 if(stage->type==Stage::VERTEX && var.interface=="in")
256 stage->locations[var.name] = location;
257 var.layout->qualifiers.erase(i);
259 else if(stage->type==Stage::FRAGMENT && var.interface=="out")
262 static Require _req(EXT_gpu_shader4);
263 stage->locations[var.name] = location;
264 var.layout->qualifiers.erase(i);
267 if(var.layout->qualifiers.empty())
272 if(var.sampling=="centroid")
274 if(!supports_centroid_sampling())
275 var.sampling = string();
277 else if(var.sampling=="sample")
279 if(!supports_sample_sampling())
280 var.sampling = string();
283 if((var.interface=="in" || var.interface=="out") && !supports_unified_interface_syntax())
285 if(stage->type==Stage::FRAGMENT && var.interface=="out")
292 TraversingVisitor::visit(var);
295 bool LegacyConverter::supports_interface_blocks(const string &iface) const
297 if(target_api==OPENGL_ES2)
300 return check_version(Version(3, 0));
302 return check_version(Version(3, 20));
304 else if(check_version(Version(1, 50)))
306 else if(iface=="uniform")
307 return check_extension(ARB_uniform_buffer_object);
312 void LegacyConverter::visit(InterfaceBlock &iface)
314 if(!supports_interface_blocks(iface.interface))
315 flatten_block(iface.members);