TranslatorGLSL.cpp (14106B)
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/TranslatorGLSL.h" 8 9 #include "angle_gl.h" 10 #include "compiler/translator/BuiltInFunctionEmulatorGLSL.h" 11 #include "compiler/translator/ExtensionGLSL.h" 12 #include "compiler/translator/OutputGLSL.h" 13 #include "compiler/translator/VersionGLSL.h" 14 #include "compiler/translator/tree_ops/RewriteTexelFetchOffset.h" 15 #include "compiler/translator/tree_ops/apple/RewriteRowMajorMatrices.h" 16 #include "compiler/translator/tree_ops/apple/RewriteUnaryMinusOperatorFloat.h" 17 18 namespace sh 19 { 20 21 TranslatorGLSL::TranslatorGLSL(sh::GLenum type, ShShaderSpec spec, ShShaderOutput output) 22 : TCompiler(type, spec, output) 23 {} 24 25 void TranslatorGLSL::initBuiltInFunctionEmulator(BuiltInFunctionEmulator *emu, 26 const ShCompileOptions &compileOptions) 27 { 28 if (compileOptions.emulateAbsIntFunction) 29 { 30 InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(emu, getShaderType()); 31 } 32 33 if (compileOptions.emulateIsnanFloatFunction) 34 { 35 InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(emu, getShaderVersion()); 36 } 37 38 if (compileOptions.emulateAtan2FloatFunction) 39 { 40 InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(emu); 41 } 42 43 int targetGLSLVersion = ShaderOutputTypeToGLSLVersion(getOutputType()); 44 InitBuiltInFunctionEmulatorForGLSLMissingFunctions(emu, getShaderType(), targetGLSLVersion); 45 } 46 47 bool TranslatorGLSL::translate(TIntermBlock *root, 48 const ShCompileOptions &compileOptions, 49 PerformanceDiagnostics * /*perfDiagnostics*/) 50 { 51 TInfoSinkBase &sink = getInfoSink().obj; 52 53 // Write GLSL version. 54 writeVersion(root); 55 56 // Write extension behaviour as needed 57 writeExtensionBehavior(root, compileOptions); 58 59 // Write pragmas after extensions because some drivers consider pragmas 60 // like non-preprocessor tokens. 61 WritePragma(sink, compileOptions, getPragma()); 62 63 // If flattening the global invariant pragma, write invariant declarations for built-in 64 // variables. It should be harmless to do this twice in the case that the shader also explicitly 65 // did this. However, it's important to emit invariant qualifiers only for those built-in 66 // variables that are actually used, to avoid affecting the behavior of the shader. 67 if (compileOptions.flattenPragmaSTDGLInvariantAll && getPragma().stdgl.invariantAll && 68 !sh::RemoveInvariant(getShaderType(), getShaderVersion(), getOutputType(), compileOptions)) 69 { 70 ASSERT(wereVariablesCollected()); 71 72 switch (getShaderType()) 73 { 74 case GL_VERTEX_SHADER: 75 sink << "invariant gl_Position;\n"; 76 77 // gl_PointSize should be declared invariant in both ESSL 1.00 and 3.00 fragment 78 // shaders if it's statically referenced. 79 conditionallyOutputInvariantDeclaration("gl_PointSize"); 80 break; 81 case GL_FRAGMENT_SHADER: 82 // The preprocessor will reject this pragma if it's used in ESSL 3.00 fragment 83 // shaders, so we can use simple logic to determine whether to declare these 84 // variables invariant. 85 conditionallyOutputInvariantDeclaration("gl_FragCoord"); 86 conditionallyOutputInvariantDeclaration("gl_PointCoord"); 87 break; 88 default: 89 // Currently not reached, but leave this in for future expansion. 90 ASSERT(false); 91 break; 92 } 93 } 94 95 if (compileOptions.rewriteTexelFetchOffsetToTexelFetch) 96 { 97 if (!sh::RewriteTexelFetchOffset(this, root, getSymbolTable(), getShaderVersion())) 98 { 99 return false; 100 } 101 } 102 103 if (compileOptions.rewriteFloatUnaryMinusOperator) 104 { 105 if (!sh::RewriteUnaryMinusOperatorFloat(this, root)) 106 { 107 return false; 108 } 109 } 110 111 if (compileOptions.rewriteRowMajorMatrices && getShaderVersion() >= 300) 112 { 113 if (!RewriteRowMajorMatrices(this, root, &getSymbolTable())) 114 { 115 return false; 116 } 117 } 118 119 // Write emulated built-in functions if needed. 120 if (!getBuiltInFunctionEmulator().isOutputEmpty()) 121 { 122 sink << "// BEGIN: Generated code for built-in function emulation\n\n"; 123 sink << "#define emu_precision\n\n"; 124 getBuiltInFunctionEmulator().outputEmulatedFunctions(sink); 125 sink << "// END: Generated code for built-in function emulation\n\n"; 126 } 127 128 // Declare gl_FragColor and glFragData as webgl_FragColor and webgl_FragData 129 // if it's core profile shaders and they are used. 130 if (getShaderType() == GL_FRAGMENT_SHADER) 131 { 132 const bool mayHaveESSL1SecondaryOutputs = 133 IsExtensionEnabled(getExtensionBehavior(), TExtension::EXT_blend_func_extended) && 134 getShaderVersion() == 100; 135 const bool declareGLFragmentOutputs = IsGLSL130OrNewer(getOutputType()); 136 137 bool hasGLFragColor = false; 138 bool hasGLFragData = false; 139 bool hasGLSecondaryFragColor = false; 140 bool hasGLSecondaryFragData = false; 141 142 for (const auto &outputVar : mOutputVariables) 143 { 144 if (declareGLFragmentOutputs) 145 { 146 if (outputVar.name == "gl_FragColor") 147 { 148 ASSERT(!hasGLFragColor); 149 hasGLFragColor = true; 150 continue; 151 } 152 else if (outputVar.name == "gl_FragData") 153 { 154 ASSERT(!hasGLFragData); 155 hasGLFragData = true; 156 continue; 157 } 158 } 159 if (mayHaveESSL1SecondaryOutputs) 160 { 161 if (outputVar.name == "gl_SecondaryFragColorEXT") 162 { 163 ASSERT(!hasGLSecondaryFragColor); 164 hasGLSecondaryFragColor = true; 165 continue; 166 } 167 else if (outputVar.name == "gl_SecondaryFragDataEXT") 168 { 169 ASSERT(!hasGLSecondaryFragData); 170 hasGLSecondaryFragData = true; 171 continue; 172 } 173 } 174 } 175 ASSERT(!((hasGLFragColor || hasGLSecondaryFragColor) && 176 (hasGLFragData || hasGLSecondaryFragData))); 177 if (hasGLFragColor) 178 { 179 sink << "out vec4 webgl_FragColor;\n"; 180 } 181 if (hasGLFragData) 182 { 183 sink << "out vec4 webgl_FragData[gl_MaxDrawBuffers];\n"; 184 } 185 if (hasGLSecondaryFragColor) 186 { 187 sink << "out vec4 webgl_SecondaryFragColor;\n"; 188 } 189 if (hasGLSecondaryFragData) 190 { 191 sink << "out vec4 webgl_SecondaryFragData[" << getResources().MaxDualSourceDrawBuffers 192 << "];\n"; 193 } 194 195 EmitEarlyFragmentTestsGLSL(*this, sink); 196 } 197 198 if (getShaderType() == GL_COMPUTE_SHADER) 199 { 200 EmitWorkGroupSizeGLSL(*this, sink); 201 } 202 203 if (getShaderType() == GL_GEOMETRY_SHADER_EXT) 204 { 205 WriteGeometryShaderLayoutQualifiers( 206 sink, getGeometryShaderInputPrimitiveType(), getGeometryShaderInvocations(), 207 getGeometryShaderOutputPrimitiveType(), getGeometryShaderMaxVertices()); 208 } 209 210 // Write translated shader. 211 TOutputGLSL outputGLSL(this, sink, compileOptions); 212 213 root->traverse(&outputGLSL); 214 215 return true; 216 } 217 218 bool TranslatorGLSL::shouldFlattenPragmaStdglInvariantAll() 219 { 220 // Required when outputting to any GLSL version greater than 1.20, but since ANGLE doesn't 221 // translate to that version, return true for the next higher version. 222 return IsGLSL130OrNewer(getOutputType()); 223 } 224 225 bool TranslatorGLSL::shouldCollectVariables(const ShCompileOptions &compileOptions) 226 { 227 return compileOptions.flattenPragmaSTDGLInvariantAll || 228 TCompiler::shouldCollectVariables(compileOptions); 229 } 230 231 void TranslatorGLSL::writeVersion(TIntermNode *root) 232 { 233 TVersionGLSL versionGLSL(getShaderType(), getPragma(), getOutputType()); 234 root->traverse(&versionGLSL); 235 int version = versionGLSL.getVersion(); 236 // We need to write version directive only if it is greater than 110. 237 // If there is no version directive in the shader, 110 is implied. 238 if (version > 110) 239 { 240 TInfoSinkBase &sink = getInfoSink().obj; 241 sink << "#version " << version << "\n"; 242 } 243 } 244 245 void TranslatorGLSL::writeExtensionBehavior(TIntermNode *root, 246 const ShCompileOptions &compileOptions) 247 { 248 bool usesTextureCubeMapArray = false; 249 bool usesTextureBuffer = false; 250 251 TInfoSinkBase &sink = getInfoSink().obj; 252 const TExtensionBehavior &extBehavior = getExtensionBehavior(); 253 for (const auto &iter : extBehavior) 254 { 255 if (iter.second == EBhUndefined) 256 { 257 continue; 258 } 259 260 if (getOutputType() == SH_GLSL_COMPATIBILITY_OUTPUT) 261 { 262 // For GLSL output, we don't need to emit most extensions explicitly, 263 // but some we need to translate in GL compatibility profile. 264 if (iter.first == TExtension::EXT_shader_texture_lod) 265 { 266 sink << "#extension GL_ARB_shader_texture_lod : " << GetBehaviorString(iter.second) 267 << "\n"; 268 } 269 270 if (iter.first == TExtension::EXT_draw_buffers) 271 { 272 sink << "#extension GL_ARB_draw_buffers : " << GetBehaviorString(iter.second) 273 << "\n"; 274 } 275 276 if (iter.first == TExtension::EXT_geometry_shader || 277 iter.first == TExtension::OES_geometry_shader) 278 { 279 sink << "#extension GL_ARB_geometry_shader4 : " << GetBehaviorString(iter.second) 280 << "\n"; 281 } 282 } 283 284 const bool isMultiview = 285 (iter.first == TExtension::OVR_multiview) || (iter.first == TExtension::OVR_multiview2); 286 if (isMultiview) 287 { 288 // Only either OVR_multiview or OVR_multiview2 should be emitted. 289 if ((iter.first != TExtension::OVR_multiview) || 290 !IsExtensionEnabled(extBehavior, TExtension::OVR_multiview2)) 291 { 292 EmitMultiviewGLSL(*this, compileOptions, iter.first, iter.second, sink); 293 } 294 } 295 296 // Support ANGLE_texture_multisample extension on GLSL300 297 if (getShaderVersion() >= 300 && iter.first == TExtension::ANGLE_texture_multisample && 298 getOutputType() < SH_GLSL_330_CORE_OUTPUT) 299 { 300 sink << "#extension GL_ARB_texture_multisample : " << GetBehaviorString(iter.second) 301 << "\n"; 302 } 303 304 if ((iter.first == TExtension::OES_texture_cube_map_array || 305 iter.first == TExtension::EXT_texture_cube_map_array) && 306 (iter.second == EBhRequire || iter.second == EBhEnable)) 307 { 308 usesTextureCubeMapArray = true; 309 } 310 311 if ((iter.first == TExtension::OES_texture_buffer || 312 iter.first == TExtension::EXT_texture_buffer) && 313 (iter.second == EBhRequire || iter.second == EBhEnable)) 314 { 315 usesTextureBuffer = true; 316 } 317 } 318 319 // GLSL ES 3 explicit location qualifiers need to use an extension before GLSL 330 320 if (getShaderVersion() >= 300 && getOutputType() < SH_GLSL_330_CORE_OUTPUT && 321 getShaderType() != GL_COMPUTE_SHADER) 322 { 323 sink << "#extension GL_ARB_explicit_attrib_location : require\n"; 324 } 325 326 // Need to enable gpu_shader5 to have index constant sampler array indexing 327 if (getOutputType() != SH_ESSL_OUTPUT && getOutputType() < SH_GLSL_400_CORE_OUTPUT && 328 getShaderVersion() == 100) 329 { 330 // Don't use "require" on to avoid breaking WebGL 1 on drivers that silently 331 // support index constant sampler array indexing, but don't have the extension or 332 // on drivers that don't have the extension at all as it would break WebGL 1 for 333 // some users. 334 sink << "#extension GL_ARB_gpu_shader5 : enable\n"; 335 sink << "#extension GL_EXT_gpu_shader5 : enable\n"; 336 } 337 338 if (usesTextureCubeMapArray) 339 { 340 if (getOutputType() >= SH_GLSL_COMPATIBILITY_OUTPUT && 341 getOutputType() < SH_GLSL_400_CORE_OUTPUT) 342 { 343 sink << "#extension GL_ARB_texture_cube_map_array : enable\n"; 344 } 345 else if (getOutputType() == SH_ESSL_OUTPUT && getShaderVersion() < 320) 346 { 347 sink << "#extension GL_OES_texture_cube_map_array : enable\n"; 348 sink << "#extension GL_EXT_texture_cube_map_array : enable\n"; 349 } 350 } 351 352 if (usesTextureBuffer) 353 { 354 if (getOutputType() >= SH_GLSL_COMPATIBILITY_OUTPUT && 355 getOutputType() < SH_GLSL_400_CORE_OUTPUT) 356 { 357 sink << "#extension GL_ARB_texture_buffer_objects : enable\n"; 358 } 359 else if (getOutputType() == SH_ESSL_OUTPUT && getShaderVersion() < 320) 360 { 361 sink << "#extension GL_OES_texture_buffer : enable\n"; 362 sink << "#extension GL_EXT_texture_buffer : enable\n"; 363 } 364 } 365 366 TExtensionGLSL extensionGLSL(getOutputType()); 367 root->traverse(&extensionGLSL); 368 369 for (const auto &ext : extensionGLSL.getEnabledExtensions()) 370 { 371 sink << "#extension " << ext << " : enable\n"; 372 } 373 for (const auto &ext : extensionGLSL.getRequiredExtensions()) 374 { 375 sink << "#extension " << ext << " : require\n"; 376 } 377 } 378 379 void TranslatorGLSL::conditionallyOutputInvariantDeclaration(const char *builtinVaryingName) 380 { 381 if (isVaryingDefined(builtinVaryingName)) 382 { 383 TInfoSinkBase &sink = getInfoSink().obj; 384 sink << "invariant " << builtinVaryingName << ";\n"; 385 } 386 } 387 388 } // namespace sh