• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/TranslatorESSL.h"
8 
9 #include "angle_gl.h"
10 #include "compiler/translator/BuiltInFunctionEmulatorGLSL.h"
11 #include "compiler/translator/OutputESSL.h"
12 #include "compiler/translator/tree_ops/RecordConstantPrecision.h"
13 
14 namespace sh
15 {
16 
TranslatorESSL(sh::GLenum type,ShShaderSpec spec)17 TranslatorESSL::TranslatorESSL(sh::GLenum type, ShShaderSpec spec)
18     : TCompiler(type, spec, SH_ESSL_OUTPUT)
19 {}
20 
initBuiltInFunctionEmulator(BuiltInFunctionEmulator * emu,ShCompileOptions compileOptions)21 void TranslatorESSL::initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu,
22                                                  ShCompileOptions compileOptions)
23 {
24     if ((compileOptions & SH_EMULATE_ATAN2_FLOAT_FUNCTION) != 0)
25     {
26         InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(emu);
27     }
28 }
29 
translate(TIntermBlock * root,ShCompileOptions compileOptions,PerformanceDiagnostics *)30 bool TranslatorESSL::translate(TIntermBlock *root,
31                                ShCompileOptions compileOptions,
32                                PerformanceDiagnostics * /*perfDiagnostics*/)
33 {
34     TInfoSinkBase &sink = getInfoSink().obj;
35 
36     int shaderVer = getShaderVersion();
37     if (shaderVer > 100)
38     {
39         sink << "#version " << shaderVer << " es\n";
40     }
41 
42     // Write built-in extension behaviors.
43     writeExtensionBehavior(compileOptions);
44 
45     // Write pragmas after extensions because some drivers consider pragmas
46     // like non-preprocessor tokens.
47     WritePragma(sink, compileOptions, getPragma());
48 
49     if (!RecordConstantPrecision(this, root, &getSymbolTable()))
50     {
51         return false;
52     }
53 
54     // Write emulated built-in functions if needed.
55     if (!getBuiltInFunctionEmulator().isOutputEmpty())
56     {
57         sink << "// BEGIN: Generated code for built-in function emulation\n\n";
58         if (getShaderType() == GL_FRAGMENT_SHADER)
59         {
60             sink << "#if defined(GL_FRAGMENT_PRECISION_HIGH)\n"
61                  << "#define emu_precision highp\n"
62                  << "#else\n"
63                  << "#define emu_precision mediump\n"
64                  << "#endif\n\n";
65         }
66         else
67         {
68             sink << "#define emu_precision highp\n";
69         }
70 
71         getBuiltInFunctionEmulator().outputEmulatedFunctions(sink);
72         sink << "// END: Generated code for built-in function emulation\n\n";
73     }
74 
75     if (getShaderType() == GL_FRAGMENT_SHADER)
76     {
77         EmitEarlyFragmentTestsGLSL(*this, sink);
78     }
79 
80     if (getShaderType() == GL_COMPUTE_SHADER)
81     {
82         EmitWorkGroupSizeGLSL(*this, sink);
83     }
84 
85     if (getShaderType() == GL_GEOMETRY_SHADER_EXT)
86     {
87         WriteGeometryShaderLayoutQualifiers(
88             sink, getGeometryShaderInputPrimitiveType(), getGeometryShaderInvocations(),
89             getGeometryShaderOutputPrimitiveType(), getGeometryShaderMaxVertices());
90     }
91 
92     // Write translated shader.
93     TOutputESSL outputESSL(this, sink, compileOptions);
94 
95     root->traverse(&outputESSL);
96 
97     return true;
98 }
99 
shouldFlattenPragmaStdglInvariantAll()100 bool TranslatorESSL::shouldFlattenPragmaStdglInvariantAll()
101 {
102     // If following the spec to the letter, we should not flatten this pragma.
103     // However, the spec's wording means that the pragma applies only to outputs.
104     // This contradicts the spirit of using the pragma,
105     // because if the pragma is used in a vertex shader,
106     // the only way to be able to link it to a fragment shader
107     // is to manually qualify each of fragment shader's inputs as invariant.
108     // Which defeats the purpose of this pragma - temporarily make all varyings
109     // invariant for debugging.
110     // Thus, we should be non-conformant to spec's letter here and flatten.
111     return true;
112 }
113 
writeExtensionBehavior(ShCompileOptions compileOptions)114 void TranslatorESSL::writeExtensionBehavior(ShCompileOptions compileOptions)
115 {
116     TInfoSinkBase &sink                   = getInfoSink().obj;
117     const TExtensionBehavior &extBehavior = getExtensionBehavior();
118     for (TExtensionBehavior::const_iterator iter = extBehavior.begin(); iter != extBehavior.end();
119          ++iter)
120     {
121         if (iter->second != EBhUndefined)
122         {
123             const bool isMultiview = (iter->first == TExtension::OVR_multiview) ||
124                                      (iter->first == TExtension::OVR_multiview2);
125             if (getResources().NV_shader_framebuffer_fetch &&
126                 iter->first == TExtension::EXT_shader_framebuffer_fetch)
127             {
128                 sink << "#extension GL_NV_shader_framebuffer_fetch : "
129                      << GetBehaviorString(iter->second) << "\n";
130             }
131             else if (getResources().NV_draw_buffers && iter->first == TExtension::EXT_draw_buffers)
132             {
133                 sink << "#extension GL_NV_draw_buffers : " << GetBehaviorString(iter->second)
134                      << "\n";
135             }
136             else if (isMultiview)
137             {
138                 // Only either OVR_multiview OR OVR_multiview2 should be emitted.
139                 if ((iter->first != TExtension::OVR_multiview) ||
140                     !IsExtensionEnabled(extBehavior, TExtension::OVR_multiview2))
141                 {
142                     EmitMultiviewGLSL(*this, compileOptions, iter->first, iter->second, sink);
143                 }
144             }
145             else if (iter->first == TExtension::EXT_geometry_shader ||
146                      iter->first == TExtension::OES_geometry_shader)
147             {
148                 sink << "#ifdef GL_EXT_geometry_shader\n"
149                      << "#extension GL_EXT_geometry_shader : " << GetBehaviorString(iter->second)
150                      << "\n"
151                      << "#elif defined GL_OES_geometry_shader\n"
152                      << "#extension GL_OES_geometry_shader : " << GetBehaviorString(iter->second)
153                      << "\n";
154                 if (iter->second == EBhRequire)
155                 {
156                     sink << "#else\n"
157                          << "#error \"No geometry shader extensions available.\" // Only generate "
158                             "this if the extension is \"required\"\n";
159                 }
160                 sink << "#endif\n";
161             }
162             else if (iter->first == TExtension::ANGLE_multi_draw)
163             {
164                 // Don't emit anything. This extension is emulated
165                 ASSERT((compileOptions & SH_EMULATE_GL_DRAW_ID) != 0);
166                 continue;
167             }
168             else if (iter->first == TExtension::ANGLE_base_vertex_base_instance_shader_builtin)
169             {
170                 // Don't emit anything. This extension is emulated
171                 ASSERT((compileOptions & SH_EMULATE_GL_BASE_VERTEX_BASE_INSTANCE) != 0);
172                 continue;
173             }
174             else if (iter->first == TExtension::WEBGL_video_texture)
175             {
176                 // Don't emit anything. This extension is emulated
177                 // TODO(crbug.com/776222): support external image.
178                 continue;
179             }
180             else
181             {
182                 sink << "#extension " << GetExtensionNameString(iter->first) << " : "
183                      << GetBehaviorString(iter->second) << "\n";
184             }
185         }
186     }
187 }
188 
189 }  // namespace sh
190