xref: /aosp_15_r20/external/angle/src/compiler/translator/glsl/TranslatorGLSL.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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