1 #include <msp/core/algorithm.h>
2 #include <msp/core/raii.h>
3 #include <msp/strings/lexicalcast.h>
4 #include "compatibility.h"
5 #include "glsl_error.h"
13 DefaultPrecisionGenerator::DefaultPrecisionGenerator():
17 void DefaultPrecisionGenerator::apply(Stage &s)
23 void DefaultPrecisionGenerator::visit(Block &block)
25 for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); ++i)
27 if(&block==&stage->content)
33 void DefaultPrecisionGenerator::visit(Precision &prec)
35 have_default.insert(prec.type);
38 void DefaultPrecisionGenerator::visit(VariableDeclaration &var)
40 if(var.type_declaration)
43 string type = var.type;
44 if(!type.compare(0, 3, "vec") || !type.compare(0, 3, "mat"))
46 else if(!type.compare(0, 3, "ivec") || type=="uint")
49 if(!have_default.count(type))
51 Precision *prec = new Precision;
52 if(!type.compare(0, 7, "sampler"))
53 prec->precision = "lowp";
54 else if(stage->type==Stage::FRAGMENT)
55 prec->precision = "mediump";
57 prec->precision = "highp";
59 stage->content.body.insert(insert_point, prec);
61 have_default.insert(type);
66 void PrecisionRemover::apply(Stage &stage)
69 NodeRemover().apply(stage, nodes_to_remove);
72 void PrecisionRemover::visit(Precision &prec)
74 nodes_to_remove.insert(&prec);
77 void PrecisionRemover::visit(VariableDeclaration &var)
79 var.precision.clear();
83 LegacyConverter::LegacyConverter():
87 void LegacyConverter::apply(Stage &s, const Features &feat)
94 void LegacyConverter::visit(Block &block)
96 for(NodeList<Statement>::iterator i=block.body.begin(); i!=block.body.end(); ++i)
98 if(&block==&stage->content)
99 uniform_insert_point = i;
104 bool LegacyConverter::check_version(const Version &feature_version) const
106 if(features.glsl_version<feature_version)
108 else if(stage->required_features.glsl_version<feature_version)
109 stage->required_features.glsl_version = feature_version;
114 bool LegacyConverter::check_extension(bool Features::*extension) const
116 if(!(features.*extension))
119 stage->required_features.*extension = true;
124 bool LegacyConverter::supports_unified_interface_syntax() const
126 if(features.gl_api==OPENGL_ES2)
127 return check_version(Version(3, 0));
129 return check_version(Version(1, 30));
132 void LegacyConverter::visit(VariableReference &var)
134 if(var.declaration==frag_out && !supports_unified_interface_syntax())
136 var.name = "gl_FragColor";
140 else if(var.declaration)
141 type = var.declaration->type;
146 void LegacyConverter::visit(Assignment &assign)
148 TraversingVisitor::visit(assign);
149 if(assign.target_declaration==frag_out && !supports_unified_interface_syntax())
150 assign.target_declaration = 0;
153 bool LegacyConverter::supports_unified_sampling_functions() const
155 if(features.gl_api==OPENGL_ES2)
156 return check_version(Version(3, 0));
158 return check_version(Version(1, 30));
161 void LegacyConverter::visit(FunctionCall &call)
163 if(call.name=="texture")
167 NodeArray<Expression>::iterator i = call.arguments.begin();
168 if(i!=call.arguments.end())
173 for(; i!=call.arguments.end(); ++i)
177 if(!supports_unified_sampling_functions())
179 if(sampler_type=="sampler1D")
180 call.name = "texture1D";
181 else if(sampler_type=="sampler2D")
182 call.name = "texture2D";
183 else if(sampler_type=="sampler3D")
184 call.name = "texture3D";
185 else if(sampler_type=="samplerCube")
186 call.name = "textureCube";
187 else if(sampler_type=="sampler1DShadow")
188 call.name = "shadow1D";
189 else if(sampler_type=="sampler2DShadow")
190 call.name = "shadow2D";
191 else if(sampler_type=="sampler1DArray")
193 check_extension(&Features::ext_texture_array);
194 call.name = "texture1DArray";
196 else if(sampler_type=="sampler2DArray")
198 check_extension(&Features::ext_texture_array);
199 call.name = "texture2DArray";
201 else if(sampler_type=="sampler1DArrayShadow")
203 check_extension(&Features::ext_texture_array);
204 call.name = "shadow1DArray";
206 else if(sampler_type=="sampler2DArrayShadow")
208 check_extension(&Features::ext_texture_array);
209 call.name = "shadow2DArray";
214 TraversingVisitor::visit(call);
217 bool LegacyConverter::supports_interface_layouts() const
219 if(features.gl_api==OPENGL_ES2)
220 return check_version(Version(3, 0));
221 else if(check_version(Version(3, 30)))
224 return check_extension(&Features::arb_explicit_attrib_location);
227 bool LegacyConverter::supports_centroid_sampling() const
229 if(features.gl_api==OPENGL_ES2)
230 return check_version(Version(3, 0));
231 else if(check_version(Version(1, 20)))
234 return check_extension(&Features::ext_gpu_shader4);
237 bool LegacyConverter::supports_sample_sampling() const
239 if(features.gl_api==OPENGL_ES2)
240 return check_version(Version(3, 20));
241 else if(check_version(Version(4, 0)))
244 return check_extension(&Features::arb_gpu_shader5);
247 void LegacyConverter::visit(VariableDeclaration &var)
249 if(var.layout && !supports_interface_layouts())
251 vector<Layout::Qualifier>::iterator i;
252 for(i=var.layout->qualifiers.begin(); (i!=var.layout->qualifiers.end() && i->identifier!="location"); ++i) ;
253 if(i!=var.layout->qualifiers.end())
255 unsigned location = lexical_cast<unsigned>(i->value);
256 if(stage->type==Stage::VERTEX && var.interface=="in")
258 stage->locations[var.name] = location;
259 var.layout->qualifiers.erase(i);
261 else if(stage->type==Stage::FRAGMENT && var.interface=="out")
263 if(location!=0 && !check_extension(&Features::ext_gpu_shader4))
264 throw unsupported_shader("EXT_gpu_shader4 is required");
265 stage->locations[var.name] = location;
266 var.layout->qualifiers.erase(i);
269 if(var.layout->qualifiers.empty())
274 if(var.sampling=="centroid")
276 if(!supports_centroid_sampling())
277 var.sampling = string();
279 else if(var.sampling=="sample")
281 if(!supports_sample_sampling())
282 var.sampling = string();
285 if((var.interface=="in" || var.interface=="out") && !supports_unified_interface_syntax())
287 if(stage->type==Stage::FRAGMENT && var.interface=="out")
290 nodes_to_remove.insert(&var);
294 TraversingVisitor::visit(var);
297 bool LegacyConverter::supports_interface_blocks(const string &iface) const
299 if(features.gl_api==OPENGL_ES2)
302 return check_version(Version(3, 0));
304 return check_version(Version(3, 20));
306 else if(check_version(Version(1, 50)))
308 else if(iface=="uniform")
309 return check_extension(&Features::arb_uniform_buffer_object);
314 void LegacyConverter::visit(InterfaceBlock &iface)
316 if(!supports_interface_blocks(iface.interface))
318 stage->content.body.splice(uniform_insert_point, iface.members.body);
319 nodes_to_remove.insert(&iface);