1//
2// Copyright (c) 2002-2013 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/TranslatorGLSL.h"
8
9#include "angle_gl.h"
10#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h"
11#include "compiler/translator/ExtensionGLSL.h"
12#include "compiler/translator/OutputGLSL.h"
13#include "compiler/translator/VersionGLSL.h"
14#include "compiler/translator/tree_ops/EmulatePrecision.h"
15#include "compiler/translator/tree_ops/RewriteTexelFetchOffset.h"
16#include "compiler/translator/tree_ops/RewriteUnaryMinusOperatorFloat.h"
17
18namespace sh
19{
20
21TranslatorGLSL::TranslatorGLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output)
22 : TCompiler(type, spec, output)
23{}
24
25void TranslatorGLSL::initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu,
26 ShCompileOptions compileOptions)
27{
28 if (compileOptions & SH_EMULATE_ABS_INT_FUNCTION)
29 {
30 InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(emu, getShaderType());
31 }
32
33 if (compileOptions & SH_EMULATE_ISNAN_FLOAT_FUNCTION)
34 {
35 InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(emu, getShaderVersion());
36 }
37
38 if (compileOptions & SH_EMULATE_ATAN2_FLOAT_FUNCTION)
39 {
40 InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(emu);
41 }
42
43 int targetGLSLVersion = ShaderOutputTypeToGLSLVersion(getOutputType());
44 InitBuiltInFunctionEmulatorForGLSLMissingFunctions(emu, getShaderType(), targetGLSLVersion);
45}
46
47void TranslatorGLSL::translate(TIntermBlock *root,
48 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(compileOptions);
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 & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) != 0 &&
68 getPragma().stdgl.invariantAll &&
69 !sh::RemoveInvariant(getShaderType(), getShaderVersion(), getOutputType(), compileOptions))
70 {
71 ASSERT(wereVariablesCollected());
72
73 switch (getShaderType())
74 {
75 case GL_VERTEX_SHADER:
76 sink << "invariant gl_Position;\n";
77
78 // gl_PointSize should be declared invariant in both ESSL 1.00 and 3.00 fragment
79 // shaders if it's statically referenced.
80 conditionallyOutputInvariantDeclaration("gl_PointSize");
81 break;
82 case GL_FRAGMENT_SHADER:
83 // The preprocessor will reject this pragma if it's used in ESSL 3.00 fragment
84 // shaders, so we can use simple logic to determine whether to declare these
85 // variables invariant.
86 conditionallyOutputInvariantDeclaration("gl_FragCoord");
87 conditionallyOutputInvariantDeclaration("gl_PointCoord");
88 break;
89 default:
90 // Currently not reached, but leave this in for future expansion.
91 ASSERT(false);
92 break;
93 }
94 }
95
96 if ((compileOptions & SH_REWRITE_TEXELFETCHOFFSET_TO_TEXELFETCH) != 0)
97 {
98 sh::RewriteTexelFetchOffset(root, getSymbolTable(), getShaderVersion());
99 }
100
101 if ((compileOptions & SH_REWRITE_FLOAT_UNARY_MINUS_OPERATOR) != 0)
102 {
103 sh::RewriteUnaryMinusOperatorFloat(root);
104 }
105
106 bool precisionEmulation =
107 getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision;
108
109 if (precisionEmulation)
110 {
111 EmulatePrecision emulatePrecision(&getSymbolTable());
112 root->traverse(&emulatePrecision);
113 emulatePrecision.updateTree();
114 emulatePrecision.writeEmulationHelpers(sink, getShaderVersion(), getOutputType());
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 // Write array bounds clamping emulation if needed.
127 getArrayBoundsClamper().OutputClampingFunctionDefinition(sink);
128
129 // Declare gl_FragColor and glFragData as webgl_FragColor and webgl_FragData
130 // if it's core profile shaders and they are used.
131 if (getShaderType() == GL_FRAGMENT_SHADER)
132 {
133 const bool mayHaveESSL1SecondaryOutputs =
134 IsExtensionEnabled(getExtensionBehavior(), TExtension::EXT_blend_func_extended) &&
135 getShaderVersion() == 100;
136 const bool declareGLFragmentOutputs = IsGLSL130OrNewer(getOutputType());
137
138 bool hasGLFragColor = false;
139 bool hasGLFragData = false;
140 bool hasGLSecondaryFragColor = false;
141 bool hasGLSecondaryFragData = false;
142
143 for (const auto &outputVar : mOutputVariables)
144 {
145 if (declareGLFragmentOutputs)
146 {
147 if (outputVar.name == "gl_FragColor")
148 {
149 ASSERT(!hasGLFragColor);
150 hasGLFragColor = true;
151 continue;
152 }
153 else if (outputVar.name == "gl_FragData")
154 {
155 ASSERT(!hasGLFragData);
156 hasGLFragData = true;
157 continue;
158 }
159 }
160 if (mayHaveESSL1SecondaryOutputs)
161 {
162 if (outputVar.name == "gl_SecondaryFragColorEXT")
163 {
164 ASSERT(!hasGLSecondaryFragColor);
165 hasGLSecondaryFragColor = true;
166 continue;
167 }
168 else if (outputVar.name == "gl_SecondaryFragDataEXT")
169 {
170 ASSERT(!hasGLSecondaryFragData);
171 hasGLSecondaryFragData = true;
172 continue;
173 }
174 }
175 }
176 ASSERT(!((hasGLFragColor || hasGLSecondaryFragColor) &&
177 (hasGLFragData || hasGLSecondaryFragData)));
178 if (hasGLFragColor)
179 {
180 sink << "out vec4 webgl_FragColor;\n";
181 }
182 if (hasGLFragData)
183 {
184 sink << "out vec4 webgl_FragData[gl_MaxDrawBuffers];\n";
185 }
186 if (hasGLSecondaryFragColor)
187 {
188 sink << "out vec4 angle_SecondaryFragColor;\n";
189 }
190 if (hasGLSecondaryFragData)
191 {
192 sink << "out vec4 angle_SecondaryFragData[" << getResources().MaxDualSourceDrawBuffers
193 << "];\n";
194 }
195 }
196
197 if (getShaderType() == GL_COMPUTE_SHADER && isComputeShaderLocalSizeDeclared())
198 {
199 const sh::WorkGroupSize &localSize = getComputeShaderLocalSize();
200 sink << "layout (local_size_x=" << localSize[0] << ", local_size_y=" << localSize[1]
201 << ", local_size_z=" << localSize[2] << ") in;\n";
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(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(),
213 &getSymbolTable(), getShaderType(), getShaderVersion(), getOutputType(),
214 compileOptions);
215
216 root->traverse(&outputGLSL);
217}
218
219bool 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
226bool TranslatorGLSL::shouldCollectVariables(ShCompileOptions compileOptions)
227{
228 return (compileOptions & SH_FLATTEN_PRAGMA_STDGL_INVARIANT_ALL) ||
229 TCompiler::shouldCollectVariables(compileOptions);
230}
231
232void TranslatorGLSL::writeVersion(TIntermNode *root)
233{
234 TVersionGLSL versionGLSL(getShaderType(), getPragma(), getOutputType());
235 root->traverse(&versionGLSL);
236 int version = versionGLSL.getVersion();
237 // We need to write version directive only if it is greater than 110.
238 // If there is no version directive in the shader, 110 is implied.
239 if (version > 110)
240 {
241 TInfoSinkBase &sink = getInfoSink().obj;
242 sink << "#version " << version << "\n";
243 }
244}
245
246void TranslatorGLSL::writeExtensionBehavior(TIntermNode *root, ShCompileOptions compileOptions)
247{
248 TInfoSinkBase &sink = getInfoSink().obj;
249 const TExtensionBehavior &extBehavior = getExtensionBehavior();
250 for (const auto &iter : extBehavior)
251 {
252 if (iter.second == EBhUndefined)
253 {
254 continue;
255 }
256
257 if (getOutputType() == SH_GLSL_COMPATIBILITY_OUTPUT)
258 {
259 // For GLSL output, we don't need to emit most extensions explicitly,
260 // but some we need to translate in GL compatibility profile.
261 if (iter.first == TExtension::EXT_shader_texture_lod)
262 {
263 sink << "#extension GL_ARB_shader_texture_lod : " << GetBehaviorString(iter.second)
264 << "\n";
265 }
266
267 if (iter.first == TExtension::EXT_draw_buffers)
268 {
269 sink << "#extension GL_ARB_draw_buffers : " << GetBehaviorString(iter.second)
270 << "\n";
271 }
272
273 if (iter.first == TExtension::EXT_geometry_shader)
274 {
275 sink << "#extension GL_ARB_geometry_shader4 : " << GetBehaviorString(iter.second)
276 << "\n";
277 }
278 }
279
280 const bool isMultiview = (iter.first == TExtension::OVR_multiview2);
281 if (isMultiview && getShaderType() == GL_VERTEX_SHADER &&
282 (compileOptions & SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER) != 0u)
283 {
284 // Emit the NV_viewport_array2 extension in a vertex shader if the
285 // SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER option is set and the OVR_multiview2(2)
286 // extension is requested.
287 sink << "#extension GL_NV_viewport_array2 : require\n";
288 }
289
290 // Support ANGLE_texture_multisample extension on GLSL300
291 if (getShaderVersion() >= 300 && iter.first == TExtension::ANGLE_texture_multisample &&
292 getOutputType() < SH_GLSL_330_CORE_OUTPUT)
293 {
294 sink << "#extension GL_ARB_texture_multisample : " << GetBehaviorString(iter.second)
295 << "\n";
296 }
297 }
298
299 // GLSL ES 3 explicit location qualifiers need to use an extension before GLSL 330
300 if (getShaderVersion() >= 300 && getOutputType() < SH_GLSL_330_CORE_OUTPUT &&
301 getShaderType() != GL_COMPUTE_SHADER)
302 {
303 sink << "#extension GL_ARB_explicit_attrib_location : require\n";
304 }
305
306 // Need to enable gpu_shader5 to have index constant sampler array indexing
307 if (getOutputType() != SH_ESSL_OUTPUT && getOutputType() < SH_GLSL_400_CORE_OUTPUT &&
308 getShaderVersion() == 100)
309 {
310 // Don't use "require" on to avoid breaking WebGL 1 on drivers that silently
311 // support index constant sampler array indexing, but don't have the extension or
312 // on drivers that don't have the extension at all as it would break WebGL 1 for
313 // some users.
314 sink << "#extension GL_ARB_gpu_shader5 : enable\n";
315 }
316
317 TExtensionGLSL extensionGLSL(getOutputType());
318 root->traverse(&extensionGLSL);
319
320 for (const auto &ext : extensionGLSL.getEnabledExtensions())
321 {
322 sink << "#extension " << ext << " : enable\n";
323 }
324 for (const auto &ext : extensionGLSL.getRequiredExtensions())
325 {
326 sink << "#extension " << ext << " : require\n";
327 }
328}
329
330void TranslatorGLSL::conditionallyOutputInvariantDeclaration(const char *builtinVaryingName)
331{
332 if (isVaryingDefined(builtinVaryingName))
333 {
334 TInfoSinkBase &sink = getInfoSink().obj;
335 sink << "invariant " << builtinVaryingName << ";\n";
336 }
337}
338
339} // namespace sh
340