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