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