tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

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