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