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