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/TranslatorESSL.h"
8
9 #include "compiler/translator/BuiltInFunctionEmulatorGLSL.h"
10 #include "compiler/translator/EmulatePrecision.h"
11 #include "compiler/translator/RecordConstantPrecision.h"
12 #include "compiler/translator/OutputESSL.h"
13 #include "angle_gl.h"
14
15 namespace sh
16 {
17
TranslatorESSL(sh::GLenum type,ShShaderSpec spec)18 TranslatorESSL::TranslatorESSL(sh::GLenum type, ShShaderSpec spec)
19 : TCompiler(type, spec, SH_ESSL_OUTPUT)
20 {
21 }
22
initBuiltInFunctionEmulator(BuiltInFunctionEmulator * emu,ShCompileOptions compileOptions)23 void TranslatorESSL::initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu,
24 ShCompileOptions compileOptions)
25 {
26 if (compileOptions & SH_EMULATE_ATAN2_FLOAT_FUNCTION)
27 {
28 InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(emu);
29 }
30 }
31
translate(TIntermBlock * root,ShCompileOptions compileOptions,PerformanceDiagnostics *)32 void TranslatorESSL::translate(TIntermBlock *root,
33 ShCompileOptions compileOptions,
34 PerformanceDiagnostics * /*perfDiagnostics*/)
35 {
36 TInfoSinkBase &sink = getInfoSink().obj;
37
38 int shaderVer = getShaderVersion();
39 if (shaderVer > 100)
40 {
41 sink << "#version " << shaderVer << " es\n";
42 }
43
44 // Write built-in extension behaviors.
45 writeExtensionBehavior(compileOptions);
46
47 // Write pragmas after extensions because some drivers consider pragmas
48 // like non-preprocessor tokens.
49 writePragma(compileOptions);
50
51 bool precisionEmulation =
52 getResources().WEBGL_debug_shader_precision && getPragma().debugShaderPrecision;
53
54 if (precisionEmulation)
55 {
56 EmulatePrecision emulatePrecision(&getSymbolTable(), shaderVer);
57 root->traverse(&emulatePrecision);
58 emulatePrecision.updateTree();
59 emulatePrecision.writeEmulationHelpers(sink, shaderVer, SH_ESSL_OUTPUT);
60 }
61
62 RecordConstantPrecision(root, &getSymbolTable());
63
64 // Write emulated built-in functions if needed.
65 if (!getBuiltInFunctionEmulator().isOutputEmpty())
66 {
67 sink << "// BEGIN: Generated code for built-in function emulation\n\n";
68 if (getShaderType() == GL_FRAGMENT_SHADER)
69 {
70 sink << "#if defined(GL_FRAGMENT_PRECISION_HIGH)\n"
71 << "#define emu_precision highp\n"
72 << "#else\n"
73 << "#define emu_precision mediump\n"
74 << "#endif\n\n";
75 }
76 else
77 {
78 sink << "#define emu_precision highp\n";
79 }
80
81 getBuiltInFunctionEmulator().outputEmulatedFunctions(sink);
82 sink << "// END: Generated code for built-in function emulation\n\n";
83 }
84
85 // Write array bounds clamping emulation if needed.
86 getArrayBoundsClamper().OutputClampingFunctionDefinition(sink);
87
88 if (getShaderType() == GL_COMPUTE_SHADER && isComputeShaderLocalSizeDeclared())
89 {
90 const sh::WorkGroupSize &localSize = getComputeShaderLocalSize();
91 sink << "layout (local_size_x=" << localSize[0] << ", local_size_y=" << localSize[1]
92 << ", local_size_z=" << localSize[2] << ") in;\n";
93 }
94
95 if (getShaderType() == GL_GEOMETRY_SHADER_OES)
96 {
97 WriteGeometryShaderLayoutQualifiers(
98 sink, getGeometryShaderInputPrimitiveType(), getGeometryShaderInvocations(),
99 getGeometryShaderOutputPrimitiveType(), getGeometryShaderMaxVertices());
100 }
101
102 // Write translated shader.
103 TOutputESSL outputESSL(sink, getArrayIndexClampingStrategy(), getHashFunction(), getNameMap(),
104 &getSymbolTable(), getShaderType(), shaderVer, precisionEmulation,
105 compileOptions);
106
107 if (compileOptions & SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM)
108 {
109 TName uniformName(TString("ViewID_OVR"));
110 uniformName.setInternal(true);
111 sink << "highp uniform int " << outputESSL.hashName(uniformName) << ";\n";
112 }
113
114 root->traverse(&outputESSL);
115 }
116
shouldFlattenPragmaStdglInvariantAll()117 bool TranslatorESSL::shouldFlattenPragmaStdglInvariantAll()
118 {
119 // Not necessary when translating to ESSL.
120 return false;
121 }
122
writeExtensionBehavior(ShCompileOptions compileOptions)123 void TranslatorESSL::writeExtensionBehavior(ShCompileOptions compileOptions)
124 {
125 TInfoSinkBase &sink = getInfoSink().obj;
126 const TExtensionBehavior &extBehavior = getExtensionBehavior();
127 const bool isMultiviewExtEmulated =
128 (compileOptions &
129 (SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM | SH_INITIALIZE_BUILTINS_FOR_INSTANCED_MULTIVIEW |
130 SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER)) != 0u;
131 for (TExtensionBehavior::const_iterator iter = extBehavior.begin(); iter != extBehavior.end();
132 ++iter)
133 {
134 if (iter->second != EBhUndefined)
135 {
136 const bool isMultiview = (iter->first == TExtension::OVR_multiview);
137 if (getResources().NV_shader_framebuffer_fetch &&
138 iter->first == TExtension::EXT_shader_framebuffer_fetch)
139 {
140 sink << "#extension GL_NV_shader_framebuffer_fetch : "
141 << GetBehaviorString(iter->second) << "\n";
142 }
143 else if (getResources().NV_draw_buffers && iter->first == TExtension::EXT_draw_buffers)
144 {
145 sink << "#extension GL_NV_draw_buffers : " << GetBehaviorString(iter->second)
146 << "\n";
147 }
148 else if (isMultiview && isMultiviewExtEmulated)
149 {
150 if (getShaderType() == GL_VERTEX_SHADER &&
151 (compileOptions & SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER) != 0u)
152 {
153 // Emit the NV_viewport_array2 extension in a vertex shader if the
154 // SH_SELECT_VIEW_IN_NV_GLSL_VERTEX_SHADER option is set and the
155 // OVR_multiview(2) extension is requested.
156 sink << "#extension GL_NV_viewport_array2 : require\n";
157 }
158 }
159 else if (iter->first == TExtension::OES_geometry_shader)
160 {
161 sink << "#ifdef GL_OES_geometry_shader\n"
162 << "#extension GL_OES_geometry_shader : " << GetBehaviorString(iter->second)
163 << "\n"
164 << "#elif defined GL_EXT_geometry_shader\n"
165 << "#extension GL_EXT_geometry_shader : " << GetBehaviorString(iter->second)
166 << "\n";
167 if (iter->second == EBhRequire)
168 {
169 sink << "#else\n"
170 << "#error \"No geometry shader extensions available.\" // Only generate "
171 "this if the extension is \"required\"\n";
172 }
173 sink << "#endif\n";
174 }
175 else
176 {
177 sink << "#extension " << GetExtensionNameString(iter->first) << " : "
178 << GetBehaviorString(iter->second) << "\n";
179 }
180 }
181 }
182 }
183
184 } // namespace sh
185