1 #include <msp/core/algorithm.h>
2 #include <msp/core/raii.h>
3 #include <msp/strings/lexicalcast.h>
4 #include "compatibility.h"
12 DefaultPrecisionGenerator::DefaultPrecisionGenerator():
16 void DefaultPrecisionGenerator::apply(Stage &s)
22 void DefaultPrecisionGenerator::visit(Block &block)
24 for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); ++i)
26 if(&block==&stage->content)
32 void DefaultPrecisionGenerator::visit(Precision &prec)
34 have_default.insert(prec.type);
37 void DefaultPrecisionGenerator::visit(VariableDeclaration &var)
39 if(var.type_declaration)
42 string type = var.type;
43 if(!type.compare(0, 3, "vec") || !type.compare(0, 3, "mat"))
45 else if(!type.compare(0, 3, "ivec") || type=="uint")
48 if(!have_default.count(type))
50 Precision *prec = new Precision;
51 if(!type.compare(0, 7, "sampler"))
52 prec->precision = "lowp";
53 else if(stage->type==Stage::FRAGMENT)
54 prec->precision = "mediump";
56 prec->precision = "highp";
58 stage->content.body.insert(insert_point, prec);
60 have_default.insert(type);
65 void PrecisionRemover::apply(Stage &stage)
68 NodeRemover().apply(stage, nodes_to_remove);
71 void PrecisionRemover::visit(Precision &prec)
73 nodes_to_remove.insert(&prec);
76 void PrecisionRemover::visit(VariableDeclaration &var)
78 var.precision.clear();
82 LegacyConverter::LegacyConverter():
86 void LegacyConverter::apply(Stage &s, const Features &feat)
93 void LegacyConverter::visit(Block &block)
95 for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); ++i)
97 if(&block==&stage->content)
98 uniform_insert_point = i;
103 bool LegacyConverter::check_version(const Version &feature_version) const
105 if(features.glsl_version<feature_version)
107 else if(stage->required_features.glsl_version<feature_version)
108 stage->required_features.glsl_version = feature_version;
113 bool LegacyConverter::check_extension(bool Features::*extension) const
115 if(!(features.*extension))
118 stage->required_features.*extension = true;
123 bool LegacyConverter::supports_unified_interface_syntax() const
125 if(features.gl_api==OPENGL_ES2)
126 return check_version(Version(3, 0));
128 return check_version(Version(1, 30));
131 void LegacyConverter::visit(VariableReference &var)
133 if(var.declaration==frag_out && !supports_unified_interface_syntax())
135 var.name = "gl_FragColor";
139 else if(var.declaration)
140 type = var.declaration->type;
145 void LegacyConverter::visit(Assignment &assign)
147 TraversingVisitor::visit(assign);
148 if(assign.target_declaration==frag_out && !supports_unified_interface_syntax())
149 assign.target_declaration = 0;
152 bool LegacyConverter::supports_unified_sampling_functions() const
154 if(features.gl_api==OPENGL_ES2)
155 return check_version(Version(3, 0));
157 return check_version(Version(1, 30));
160 void LegacyConverter::visit(FunctionCall &call)
162 if(call.name=="texture")
166 NodeArray<Expression>::iterator i = call.arguments.begin();
167 if(i!=call.arguments.end())
172 for(; i!=call.arguments.end(); ++i)
176 if(!supports_unified_sampling_functions())
178 if(sampler_type=="sampler1D")
179 call.name = "texture1D";
180 else if(sampler_type=="sampler2D")
181 call.name = "texture2D";
182 else if(sampler_type=="sampler3D")
183 call.name = "texture3D";
184 else if(sampler_type=="samplerCube")
185 call.name = "textureCube";
186 else if(sampler_type=="sampler1DShadow")
187 call.name = "shadow1D";
188 else if(sampler_type=="sampler2DShadow")
189 call.name = "shadow2D";
190 else if(sampler_type=="sampler1DArray")
192 check_extension(&Features::ext_texture_array);
193 call.name = "texture1DArray";
195 else if(sampler_type=="sampler2DArray")
197 check_extension(&Features::ext_texture_array);
198 call.name = "texture2DArray";
200 else if(sampler_type=="sampler1DArrayShadow")
202 check_extension(&Features::ext_texture_array);
203 call.name = "shadow1DArray";
205 else if(sampler_type=="sampler2DArrayShadow")
207 check_extension(&Features::ext_texture_array);
208 call.name = "shadow2DArray";
213 TraversingVisitor::visit(call);
216 bool LegacyConverter::supports_interface_layouts() const
218 if(features.gl_api==OPENGL_ES2)
219 return check_version(Version(3, 0));
220 else if(check_version(Version(3, 30)))
223 return check_extension(&Features::arb_explicit_attrib_location);
226 bool LegacyConverter::supports_centroid_sampling() const
228 if(features.gl_api==OPENGL_ES2)
229 return check_version(Version(3, 0));
230 else if(check_version(Version(1, 20)))
233 return check_extension(&Features::ext_gpu_shader4);
236 bool LegacyConverter::supports_sample_sampling() const
238 if(features.gl_api==OPENGL_ES2)
239 return check_version(Version(3, 20));
240 else if(check_version(Version(4, 0)))
243 return check_extension(&Features::arb_gpu_shader5);
246 void LegacyConverter::visit(VariableDeclaration &var)
248 if(var.layout && !supports_interface_layouts())
250 vector<Layout::Qualifier>::iterator i;
251 for(i=var.layout->qualifiers.begin(); (i!=var.layout->qualifiers.end() && i->identifier!="location"); ++i) ;
252 if(i!=var.layout->qualifiers.end())
254 unsigned location = lexical_cast<unsigned>(i->value);
255 if(stage->type==Stage::VERTEX && var.interface=="in")
257 stage->locations[var.name] = location;
258 var.layout->qualifiers.erase(i);
260 else if(stage->type==Stage::FRAGMENT && var.interface=="out")
263 check_extension(&Features::ext_gpu_shader4);
264 stage->locations[var.name] = location;
265 var.layout->qualifiers.erase(i);
268 if(var.layout->qualifiers.empty())
273 if(var.sampling=="centroid")
275 if(!supports_centroid_sampling())
276 var.sampling = string();
278 else if(var.sampling=="sample")
280 if(!supports_sample_sampling())
281 var.sampling = string();
284 if((var.interface=="in" || var.interface=="out") && !supports_unified_interface_syntax())
286 if(stage->type==Stage::FRAGMENT && var.interface=="out")
289 nodes_to_remove.insert(&var);
293 TraversingVisitor::visit(var);
296 bool LegacyConverter::supports_interface_blocks(const string &iface) const
298 if(features.gl_api==OPENGL_ES2)
301 return check_version(Version(3, 0));
303 return check_version(Version(3, 20));
305 else if(check_version(Version(1, 50)))
307 else if(iface=="uniform")
308 return check_extension(&Features::arb_uniform_buffer_object);
313 void LegacyConverter::visit(InterfaceBlock &iface)
315 if(!supports_interface_blocks(iface.interface))
317 stage->content.body.splice(uniform_insert_point, iface.members.body);
318 nodes_to_remove.insert(&iface);