1 //
2 // Copyright 2002 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6
7 #include "compiler/translator/glsl/TranslatorGLSL.h"
8
9 #include "angle_gl.h"
10 #include "compiler/translator/glsl/BuiltInFunctionEmulatorGLSL.h"
11 #include "compiler/translator/glsl/ExtensionGLSL.h"
12 #include "compiler/translator/glsl/OutputGLSL.h"
13 #include "compiler/translator/glsl/VersionGLSL.h"
14 #include "compiler/translator/tree_ops/PreTransformTextureCubeGradDerivatives.h"
15 #include "compiler/translator/tree_ops/RewriteTexelFetchOffset.h"
16 #include "compiler/translator/tree_ops/glsl/apple/RewriteRowMajorMatrices.h"
17 #include "compiler/translator/tree_ops/glsl/apple/RewriteUnaryMinusOperatorFloat.h"
18
19 namespace sh
20 {
21
TranslatorGLSL(sh::GLenum type,ShShaderSpec spec,ShShaderOutput output)22 TranslatorGLSL::TranslatorGLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
23 : TCompiler(type, spec, output)
24 {}
25
initBuiltInFunctionEmulator(BuiltInFunctionEmulator * emu,const ShCompileOptions & compileOptions)26 void TranslatorGLSL::initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu,
27 const ShCompileOptions &compileOptions)
28 {
29 if (compileOptions.emulateAbsIntFunction)
30 {
31 InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(emu, getShaderType());
32 }
33
34 if (compileOptions.emulateIsnanFloatFunction)
35 {
36 InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(emu, getShaderVersion());
37 }
38
39 if (compileOptions.emulateAtan2FloatFunction)
40 {
41 InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(emu);
42 }
43
44 int targetGLSLVersion = ShaderOutputTypeToGLSLVersion(getOutputType());
45 InitBuiltInFunctionEmulatorForGLSLMissingFunctions(emu, getShaderType(), targetGLSLVersion);
46 }
47
translate(TIntermBlock * root,const ShCompileOptions & compileOptions,PerformanceDiagnostics *)48 bool TranslatorGLSL::translate(TIntermBlock *root,
49 const ShCompileOptions &compileOptions,
50 PerformanceDiagnostics * /*perfDiagnostics*/)
51 {
52 TInfoSinkBase &sink = getInfoSink().obj;
53
54 // Write GLSL version.
55 writeVersion(root);
56
57 // Write extension behaviour as needed
58 writeExtensionBehavior(root, compileOptions);
59
60 // Write pragmas after extensions because some drivers consider pragmas
61 // like non-preprocessor tokens.
62 WritePragma(sink, compileOptions, getPragma());
63
64 // If flattening the global invariant pragma, write invariant declarations for built-in
65 // variables. It should be harmless to do this twice in the case that the shader also explicitly
66 // did this. However, it's important to emit invariant qualifiers only for those built-in
67 // variables that are actually used, to avoid affecting the behavior of the shader.
68 if (compileOptions.flattenPragmaSTDGLInvariantAll && getPragma().stdgl.invariantAll &&
69 !sh::RemoveInvariant(getShaderType(), getShaderVersion(), getOutputType(), compileOptions))
70 {
71 switch (getShaderType())
72 {
73 case GL_VERTEX_SHADER:
74 sink << "invariant gl_Position;\n";
75
76 // gl_PointSize should be declared invariant in both ESSL 1.00 and 3.00 fragment
77 // shaders if it's statically referenced.
78 conditionallyOutputInvariantDeclaration("gl_PointSize");
79 break;
80 case GL_FRAGMENT_SHADER:
81 // The preprocessor will reject this pragma if it's used in ESSL 3.00 fragment
82 // shaders, so we can use simple logic to determine whether to declare these
83 // variables invariant.
84 conditionallyOutputInvariantDeclaration("gl_FragCoord");
85 conditionallyOutputInvariantDeclaration("gl_PointCoord");
86 break;
87 default:
88 // Currently not reached, but leave this in for future expansion.
89 ASSERT(false);
90 break;
91 }
92 }
93
94 if (getShaderVersion() >= 300 ||
95 IsExtensionEnabled(getExtensionBehavior(), TExtension::EXT_shader_texture_lod))
96 {
97 if (compileOptions.preTransformTextureCubeGradDerivatives)
98 {
99 if (!sh::PreTransformTextureCubeGradDerivatives(this, root, &getSymbolTable(),
100 getShaderVersion()))
101 {
102 return false;
103 }
104 }
105 }
106
107 if (compileOptions.rewriteTexelFetchOffsetToTexelFetch)
108 {
109 if (!sh::RewriteTexelFetchOffset(this, root, getSymbolTable(), getShaderVersion()))
110 {
111 return false;
112 }
113 }
114
115 if (compileOptions.rewriteFloatUnaryMinusOperator)
116 {
117 if (!sh::RewriteUnaryMinusOperatorFloat(this, root))
118 {
119 return false;
120 }
121 }
122
123 if (compileOptions.rewriteRowMajorMatrices && getShaderVersion() >= 300)
124 {
125 if (!RewriteRowMajorMatrices(this, root, &getSymbolTable()))
126 {
127 return false;
128 }
129 }
130
131 // Write emulated built-in functions if needed.
132 if (!getBuiltInFunctionEmulator().isOutputEmpty())
133 {
134 sink << "// BEGIN: Generated code for built-in function emulation\n\n";
135 sink << "#define emu_precision\n\n";
136 getBuiltInFunctionEmulator().outputEmulatedFunctions(sink);
137 sink << "// END: Generated code for built-in function emulation\n\n";
138 }
139
140 // Declare gl_FragColor and glFragData as webgl_FragColor and webgl_FragData
141 // if it's core profile shaders and they are used.
142 if (getShaderType() == GL_FRAGMENT_SHADER)
143 {
144 const bool mayHaveESSL1SecondaryOutputs =
145 IsExtensionEnabled(getExtensionBehavior(), TExtension::EXT_blend_func_extended) &&
146 getShaderVersion() == 100;
147 const bool declareGLFragmentOutputs = IsGLSL130OrNewer(getOutputType());
148
149 bool hasGLFragColor = false;
150 bool hasGLFragData = false;
151 bool hasGLSecondaryFragColor = false;
152 bool hasGLSecondaryFragData = false;
153
154 for (const auto &outputVar : mOutputVariables)
155 {
156 if (declareGLFragmentOutputs)
157 {
158 if (outputVar.name == "gl_FragColor")
159 {
160 ASSERT(!hasGLFragColor);
161 hasGLFragColor = true;
162 continue;
163 }
164 else if (outputVar.name == "gl_FragData")
165 {
166 ASSERT(!hasGLFragData);
167 hasGLFragData = true;
168 continue;
169 }
170 }
171 if (mayHaveESSL1SecondaryOutputs)
172 {
173 if (outputVar.name == "gl_SecondaryFragColorEXT")
174 {
175 ASSERT(!hasGLSecondaryFragColor);
176 hasGLSecondaryFragColor = true;
177 continue;
178 }
179 else if (outputVar.name == "gl_SecondaryFragDataEXT")
180 {
181 ASSERT(!hasGLSecondaryFragData);
182 hasGLSecondaryFragData = true;
183 continue;
184 }
185 }
186 }
187 ASSERT(!((hasGLFragColor || hasGLSecondaryFragColor) &&
188 (hasGLFragData || hasGLSecondaryFragData)));
189 if (hasGLFragColor)
190 {
191 sink << "out vec4 webgl_FragColor;\n";
192 }
193 if (hasGLFragData)
194 {
195 sink << "out vec4 webgl_FragData["
196 << (hasGLSecondaryFragData ? getResources().MaxDualSourceDrawBuffers
197 : getResources().MaxDrawBuffers)
198 << "];\n";
199 }
200 if (hasGLSecondaryFragColor)
201 {
202 sink << "out vec4 webgl_SecondaryFragColor;\n";
203 }
204 if (hasGLSecondaryFragData)
205 {
206 sink << "out vec4 webgl_SecondaryFragData[" << getResources().MaxDualSourceDrawBuffers
207 << "];\n";
208 }
209
210 EmitEarlyFragmentTestsGLSL(*this, sink);
211 WriteFragmentShaderLayoutQualifiers(sink, getAdvancedBlendEquations());
212 }
213
214 if (getShaderType() == GL_COMPUTE_SHADER)
215 {
216 EmitWorkGroupSizeGLSL(*this, sink);
217 }
218
219 if (getShaderType() == GL_GEOMETRY_SHADER_EXT)
220 {
221 WriteGeometryShaderLayoutQualifiers(
222 sink, getGeometryShaderInputPrimitiveType(), getGeometryShaderInvocations(),
223 getGeometryShaderOutputPrimitiveType(), getGeometryShaderMaxVertices());
224 }
225
226 // Write translated shader.
227 TOutputGLSL outputGLSL(this, sink, compileOptions);
228
229 root->traverse(&outputGLSL);
230
231 return true;
232 }
233
shouldFlattenPragmaStdglInvariantAll()234 bool TranslatorGLSL::shouldFlattenPragmaStdglInvariantAll()
235 {
236 // Required when outputting to any GLSL version greater than 1.20, but since ANGLE doesn't
237 // translate to that version, return true for the next higher version.
238 return IsGLSL130OrNewer(getOutputType());
239 }
240
writeVersion(TIntermNode * root)241 void TranslatorGLSL::writeVersion(TIntermNode *root)
242 {
243 TVersionGLSL versionGLSL(getShaderType(), getPragma(), getOutputType());
244 root->traverse(&versionGLSL);
245 int version = versionGLSL.getVersion();
246 // We need to write version directive only if it is greater than 110.
247 // If there is no version directive in the shader, 110 is implied.
248 if (version > 110)
249 {
250 TInfoSinkBase &sink = getInfoSink().obj;
251 sink << "#version " << version << "\n";
252 }
253 }
254
writeExtensionBehavior(TIntermNode * root,const ShCompileOptions & compileOptions)255 void TranslatorGLSL::writeExtensionBehavior(TIntermNode *root,
256 const ShCompileOptions &compileOptions)
257 {
258 bool usesTextureCubeMapArray = false;
259 bool usesTextureBuffer = false;
260 bool usesGPUShader5 = false;
261
262 TInfoSinkBase &sink = getInfoSink().obj;
263 const TExtensionBehavior &extBehavior = getExtensionBehavior();
264 for (const auto &iter : extBehavior)
265 {
266 if (iter.second == EBhUndefined)
267 {
268 continue;
269 }
270
271 if (getOutputType() == SH_GLSL_COMPATIBILITY_OUTPUT)
272 {
273 // For GLSL output, we don't need to emit most extensions explicitly,
274 // but some we need to translate in GL compatibility profile.
275 if (iter.first == TExtension::EXT_shader_texture_lod)
276 {
277 sink << "#extension GL_ARB_shader_texture_lod : " << GetBehaviorString(iter.second)
278 << "\n";
279 }
280
281 if (iter.first == TExtension::EXT_draw_buffers)
282 {
283 sink << "#extension GL_ARB_draw_buffers : " << GetBehaviorString(iter.second)
284 << "\n";
285 }
286
287 if (iter.first == TExtension::EXT_geometry_shader ||
288 iter.first == TExtension::OES_geometry_shader)
289 {
290 sink << "#extension GL_ARB_geometry_shader4 : " << GetBehaviorString(iter.second)
291 << "\n";
292 }
293 }
294
295 const bool isMultiview =
296 (iter.first == TExtension::OVR_multiview) || (iter.first == TExtension::OVR_multiview2);
297 if (isMultiview)
298 {
299 // Only either OVR_multiview or OVR_multiview2 should be emitted.
300 if ((iter.first != TExtension::OVR_multiview) ||
301 !IsExtensionEnabled(extBehavior, TExtension::OVR_multiview2))
302 {
303 EmitMultiviewGLSL(*this, compileOptions, iter.first, iter.second, sink);
304 }
305 }
306
307 // Support ANGLE_texture_multisample extension on GLSL300
308 if (getShaderVersion() >= 300 && iter.first == TExtension::ANGLE_texture_multisample &&
309 getOutputType() < SH_GLSL_330_CORE_OUTPUT)
310 {
311 sink << "#extension GL_ARB_texture_multisample : " << GetBehaviorString(iter.second)
312 << "\n";
313 }
314
315 if (getOutputType() != SH_ESSL_OUTPUT &&
316 (iter.first == TExtension::EXT_clip_cull_distance ||
317 (iter.first == TExtension::ANGLE_clip_cull_distance &&
318 getResources().MaxCullDistances > 0)) &&
319 getOutputType() < SH_GLSL_450_CORE_OUTPUT)
320 {
321 sink << "#extension GL_ARB_cull_distance : " << GetBehaviorString(iter.second) << "\n";
322 }
323
324 if (getOutputType() != SH_ESSL_OUTPUT && iter.first == TExtension::EXT_conservative_depth &&
325 getOutputType() < SH_GLSL_420_CORE_OUTPUT)
326 {
327 sink << "#extension GL_ARB_conservative_depth : " << GetBehaviorString(iter.second)
328 << "\n";
329 }
330
331 if (iter.first == TExtension::EXT_texture_shadow_lod)
332 {
333 sink << "#extension " << GetExtensionNameString(iter.first) << " : "
334 << GetBehaviorString(iter.second) << "\n";
335 }
336
337 if (iter.first == TExtension::KHR_blend_equation_advanced)
338 {
339 sink << "#ifdef GL_KHR_blend_equation_advanced\n"
340 << "#extension GL_KHR_blend_equation_advanced : " << GetBehaviorString(iter.second)
341 << "\n"
342 << "#elif defined GL_NV_blend_equation_advanced\n"
343 << "#extension GL_NV_blend_equation_advanced : " << GetBehaviorString(iter.second)
344 << "\n";
345 if (iter.second == EBhRequire)
346 {
347 sink << "#else\n" << "#error \"No advanced blend equation extensions available.\n";
348 }
349 sink << "#endif\n";
350 }
351
352 if ((iter.first == TExtension::OES_texture_cube_map_array ||
353 iter.first == TExtension::EXT_texture_cube_map_array) &&
354 (iter.second == EBhRequire || iter.second == EBhEnable))
355 {
356 usesTextureCubeMapArray = true;
357 }
358
359 if ((iter.first == TExtension::OES_texture_buffer ||
360 iter.first == TExtension::EXT_texture_buffer) &&
361 (iter.second == EBhRequire || iter.second == EBhEnable))
362 {
363 usesTextureBuffer = true;
364 }
365
366 if ((iter.first == TExtension::OES_gpu_shader5 ||
367 iter.first == TExtension::EXT_gpu_shader5) &&
368 (iter.second == EBhRequire || iter.second == EBhEnable))
369 {
370 usesGPUShader5 = true;
371 }
372 }
373
374 // GLSL ES 3 explicit location qualifiers need to use an extension before GLSL 330
375 if (getShaderVersion() >= 300 && getOutputType() < SH_GLSL_330_CORE_OUTPUT &&
376 getShaderType() != GL_COMPUTE_SHADER)
377 {
378 sink << "#extension GL_ARB_explicit_attrib_location : require\n";
379 }
380
381 // Need to enable gpu_shader5 to have index constant sampler array indexing
382 if (usesGPUShader5)
383 {
384 if (getOutputType() >= SH_GLSL_COMPATIBILITY_OUTPUT &&
385 getOutputType() < SH_GLSL_400_CORE_OUTPUT && getShaderVersion() == 100)
386 {
387 // Don't use "require" on to avoid breaking WebGL 1 on drivers that silently
388 // support index constant sampler array indexing, but don't have the extension or
389 // on drivers that don't have the extension at all as it would break WebGL 1 for
390 // some users.
391 sink << "#extension GL_ARB_gpu_shader5 : enable\n";
392 sink << "#extension GL_OES_gpu_shader5 : enable\n";
393 sink << "#extension GL_EXT_gpu_shader5 : enable\n";
394 }
395 else if (getOutputType() == SH_ESSL_OUTPUT && getShaderVersion() < 320)
396 {
397 sink << "#extension GL_OES_gpu_shader5 : enable\n";
398 sink << "#extension GL_EXT_gpu_shader5 : enable\n";
399 }
400 }
401
402 if (usesTextureCubeMapArray)
403 {
404 if (getOutputType() >= SH_GLSL_COMPATIBILITY_OUTPUT &&
405 getOutputType() < SH_GLSL_400_CORE_OUTPUT)
406 {
407 sink << "#extension GL_ARB_texture_cube_map_array : enable\n";
408 }
409 else if (getOutputType() == SH_ESSL_OUTPUT && getShaderVersion() < 320)
410 {
411 sink << "#extension GL_OES_texture_cube_map_array : enable\n";
412 sink << "#extension GL_EXT_texture_cube_map_array : enable\n";
413 }
414 }
415
416 if (usesTextureBuffer)
417 {
418 if (getOutputType() >= SH_GLSL_COMPATIBILITY_OUTPUT &&
419 getOutputType() < SH_GLSL_400_CORE_OUTPUT)
420 {
421 sink << "#extension GL_ARB_texture_buffer_objects : enable\n";
422 }
423 else if (getOutputType() == SH_ESSL_OUTPUT && getShaderVersion() < 320)
424 {
425 sink << "#extension GL_OES_texture_buffer : enable\n";
426 sink << "#extension GL_EXT_texture_buffer : enable\n";
427 }
428 }
429
430 TExtensionGLSL extensionGLSL(getOutputType());
431 root->traverse(&extensionGLSL);
432
433 for (const auto &ext : extensionGLSL.getEnabledExtensions())
434 {
435 sink << "#extension " << ext << " : enable\n";
436 }
437 for (const auto &ext : extensionGLSL.getRequiredExtensions())
438 {
439 sink << "#extension " << ext << " : require\n";
440 }
441 }
442
conditionallyOutputInvariantDeclaration(const char * builtinVaryingName)443 void TranslatorGLSL::conditionallyOutputInvariantDeclaration(const char *builtinVaryingName)
444 {
445 if (isVaryingDefined(builtinVaryingName))
446 {
447 TInfoSinkBase &sink = getInfoSink().obj;
448 sink << "invariant " << builtinVaryingName << ";\n";
449 }
450 }
451
452 } // namespace sh
453