tor-browser

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

BuiltInFunctionEmulatorGLSL.cpp (11439B)


      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/BuiltInFunctionEmulatorGLSL.h"
      8 
      9 #include "angle_gl.h"
     10 #include "compiler/translator/BuiltInFunctionEmulator.h"
     11 #include "compiler/translator/VersionGLSL.h"
     12 #include "compiler/translator/tree_util/BuiltIn.h"
     13 
     14 namespace sh
     15 {
     16 
     17 void InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu,
     18                                                      sh::GLenum shaderType)
     19 {
     20    if (shaderType == GL_VERTEX_SHADER)
     21    {
     22        emu->addEmulatedFunction(BuiltInId::abs_Int1, "int abs_emu(int x) { return x * sign(x); }");
     23    }
     24 }
     25 
     26 void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu,
     27                                                        int targetGLSLVersion)
     28 {
     29    // isnan() is supported since GLSL 1.3.
     30    if (targetGLSLVersion < GLSL_VERSION_130)
     31        return;
     32 
     33    // !(x > 0.0 || x < 0.0 || x == 0.0) will be optimized and always equal to false.
     34    emu->addEmulatedFunction(
     35        BuiltInId::isnan_Float1,
     36        "bool isnan_emu(float x) { return (x > 0.0 || x < 0.0) ? false : x != 0.0; }");
     37    emu->addEmulatedFunction(
     38        BuiltInId::isnan_Float2,
     39        "bvec2 isnan_emu(vec2 x)\n"
     40        "{\n"
     41        "    bvec2 isnan;\n"
     42        "    for (int i = 0; i < 2; i++)\n"
     43        "    {\n"
     44        "        isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
     45        "    }\n"
     46        "    return isnan;\n"
     47        "}\n");
     48    emu->addEmulatedFunction(
     49        BuiltInId::isnan_Float3,
     50        "bvec3 isnan_emu(vec3 x)\n"
     51        "{\n"
     52        "    bvec3 isnan;\n"
     53        "    for (int i = 0; i < 3; i++)\n"
     54        "    {\n"
     55        "        isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
     56        "    }\n"
     57        "    return isnan;\n"
     58        "}\n");
     59    emu->addEmulatedFunction(
     60        BuiltInId::isnan_Float4,
     61        "bvec4 isnan_emu(vec4 x)\n"
     62        "{\n"
     63        "    bvec4 isnan;\n"
     64        "    for (int i = 0; i < 4; i++)\n"
     65        "    {\n"
     66        "        isnan[i] = (x[i] > 0.0 || x[i] < 0.0) ? false : x[i] != 0.0;\n"
     67        "    }\n"
     68        "    return isnan;\n"
     69        "}\n");
     70 }
     71 
     72 void InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu)
     73 {
     74    emu->addEmulatedFunction(BuiltInId::atan_Float1_Float1,
     75                             "emu_precision float atan_emu(emu_precision float y, emu_precision "
     76                             "float x)\n"
     77                             "{\n"
     78                             "    if (x > 0.0) return atan(y / x);\n"
     79                             "    else if (x < 0.0 && y >= 0.0) return atan(y / x) + 3.14159265;\n"
     80                             "    else if (x < 0.0 && y < 0.0) return atan(y / x) - 3.14159265;\n"
     81                             "    else return 1.57079632 * sign(y);\n"
     82                             "}\n");
     83    static const std::array<TSymbolUniqueId, 4> ids = {
     84        BuiltInId::atan_Float1_Float1,
     85        BuiltInId::atan_Float2_Float2,
     86        BuiltInId::atan_Float3_Float3,
     87        BuiltInId::atan_Float4_Float4,
     88    };
     89    for (int dim = 2; dim <= 4; ++dim)
     90    {
     91        std::stringstream ss = sh::InitializeStream<std::stringstream>();
     92        ss << "emu_precision vec" << dim << " atan_emu(emu_precision vec" << dim
     93           << " y, emu_precision vec" << dim << " x)\n"
     94           << "{\n"
     95              "    return vec"
     96           << dim << "(";
     97        for (int i = 0; i < dim; ++i)
     98        {
     99            ss << "atan_emu(y[" << i << "], x[" << i << "])";
    100            if (i < dim - 1)
    101            {
    102                ss << ", ";
    103            }
    104        }
    105        ss << ");\n"
    106              "}\n";
    107        emu->addEmulatedFunctionWithDependency(BuiltInId::atan_Float1_Float1, ids[dim - 1],
    108                                               ss.str().c_str());
    109    }
    110 }
    111 
    112 // Emulate built-in functions missing from GLSL 1.30 and higher
    113 void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator *emu,
    114                                                        sh::GLenum shaderType,
    115                                                        int targetGLSLVersion)
    116 {
    117    // Emulate packUnorm2x16 and unpackUnorm2x16 (GLSL 4.10)
    118    if (targetGLSLVersion < GLSL_VERSION_410)
    119    {
    120        // clang-format off
    121        emu->addEmulatedFunction(BuiltInId::packUnorm2x16_Float2,
    122            "uint packUnorm2x16_emu(vec2 v)\n"
    123            "{\n"
    124            "    int x = int(round(clamp(v.x, 0.0, 1.0) * 65535.0));\n"
    125            "    int y = int(round(clamp(v.y, 0.0, 1.0) * 65535.0));\n"
    126            "    return uint((y << 16) | (x & 0xFFFF));\n"
    127            "}\n");
    128 
    129        emu->addEmulatedFunction(BuiltInId::unpackUnorm2x16_UInt1,
    130            "vec2 unpackUnorm2x16_emu(uint u)\n"
    131            "{\n"
    132            "    float x = float(u & 0xFFFFu) / 65535.0;\n"
    133            "    float y = float(u >> 16) / 65535.0;\n"
    134            "    return vec2(x, y);\n"
    135            "}\n");
    136        // clang-format on
    137    }
    138 
    139    // Emulate packSnorm2x16, packHalf2x16, unpackSnorm2x16, and unpackHalf2x16 (GLSL 4.20)
    140    // by using floatBitsToInt, floatBitsToUint, intBitsToFloat, and uintBitsToFloat (GLSL 3.30).
    141    if (targetGLSLVersion >= GLSL_VERSION_330 && targetGLSLVersion < GLSL_VERSION_420)
    142    {
    143        // clang-format off
    144        emu->addEmulatedFunction(BuiltInId::packSnorm2x16_Float2,
    145            "uint packSnorm2x16_emu(vec2 v)\n"
    146            "{\n"
    147            "    #if defined(GL_ARB_shading_language_packing)\n"
    148            "        return packSnorm2x16(v);\n"
    149            "    #else\n"
    150            "        int x = int(round(clamp(v.x, -1.0, 1.0) * 32767.0));\n"
    151            "        int y = int(round(clamp(v.y, -1.0, 1.0) * 32767.0));\n"
    152            "        return uint((y << 16) | (x & 0xFFFF));\n"
    153            "    #endif\n"
    154            "}\n");
    155        emu->addEmulatedFunction(BuiltInId::unpackSnorm2x16_UInt1,
    156            "#if !defined(GL_ARB_shading_language_packing)\n"
    157            "    float fromSnorm(uint x)\n"
    158            "    {\n"
    159            "        int xi = (int(x) & 0x7FFF) - (int(x) & 0x8000);\n"
    160            "        return clamp(float(xi) / 32767.0, -1.0, 1.0);\n"
    161            "    }\n"
    162            "#endif\n"
    163            "\n"
    164            "vec2 unpackSnorm2x16_emu(uint u)\n"
    165            "{\n"
    166            "    #if defined(GL_ARB_shading_language_packing)\n"
    167            "        return unpackSnorm2x16(u);\n"
    168            "    #else\n"
    169            "        uint y = (u >> 16);\n"
    170            "        uint x = u;\n"
    171            "        return vec2(fromSnorm(x), fromSnorm(y));\n"
    172            "    #endif\n"
    173            "}\n");
    174        // Functions uint f32tof16(float val) and float f16tof32(uint val) are
    175        // based on the OpenGL redbook Appendix Session "Floating-Point Formats Used in OpenGL".
    176        emu->addEmulatedFunction(BuiltInId::packHalf2x16_Float2,
    177            "#if !defined(GL_ARB_shading_language_packing)\n"
    178            "    uint f32tof16(float val)\n"
    179            "    {\n"
    180            "        uint f32 = floatBitsToUint(val);\n"
    181            "        uint f16 = 0u;\n"
    182            "        uint sign = (f32 >> 16) & 0x8000u;\n"
    183            "        int exponent = int((f32 >> 23) & 0xFFu) - 127;\n"
    184            "        uint mantissa = f32 & 0x007FFFFFu;\n"
    185            "        if (exponent == 128)\n"
    186            "        {\n"
    187            "            // Infinity or NaN\n"
    188            "            // NaN bits that are masked out by 0x3FF get discarded.\n"
    189            "            // This can turn some NaNs to infinity, but this is allowed by the spec.\n"
    190            "            f16 = sign | (0x1Fu << 10);\n"
    191            "            f16 |= (mantissa & 0x3FFu);\n"
    192            "        }\n"
    193            "        else if (exponent > 15)\n"
    194            "        {\n"
    195            "            // Overflow - flush to Infinity\n"
    196            "            f16 = sign | (0x1Fu << 10);\n"
    197            "        }\n"
    198            "        else if (exponent > -15)\n"
    199            "        {\n"
    200            "            // Representable value\n"
    201            "            exponent += 15;\n"
    202            "            mantissa >>= 13;\n"
    203            "            f16 = sign | uint(exponent << 10) | mantissa;\n"
    204            "        }\n"
    205            "        else\n"
    206            "        {\n"
    207            "            f16 = sign;\n"
    208            "        }\n"
    209            "        return f16;\n"
    210            "    }\n"
    211            "#endif\n"
    212            "\n"
    213            "uint packHalf2x16_emu(vec2 v)\n"
    214            "{\n"
    215            "    #if defined(GL_ARB_shading_language_packing)\n"
    216            "        return packHalf2x16(v);\n"
    217            "    #else\n"
    218            "        uint x = f32tof16(v.x);\n"
    219            "        uint y = f32tof16(v.y);\n"
    220            "        return (y << 16) | x;\n"
    221            "    #endif\n"
    222            "}\n");
    223        emu->addEmulatedFunction(BuiltInId::unpackHalf2x16_UInt1,
    224            "#if !defined(GL_ARB_shading_language_packing)\n"
    225            "    float f16tof32(uint val)\n"
    226            "    {\n"
    227            "        uint sign = (val & 0x8000u) << 16;\n"
    228            "        int exponent = int((val & 0x7C00u) >> 10);\n"
    229            "        uint mantissa = val & 0x03FFu;\n"
    230            "        float f32 = 0.0;\n"
    231            "        if(exponent == 0)\n"
    232            "        {\n"
    233            "            if (mantissa != 0u)\n"
    234            "            {\n"
    235            "                const float scale = 1.0 / (1 << 24);\n"
    236            "                f32 = scale * mantissa;\n"
    237            "            }\n"
    238            "        }\n"
    239            "        else if (exponent == 31)\n"
    240            "        {\n"
    241            "            return uintBitsToFloat(sign | 0x7F800000u | mantissa);\n"
    242            "        }\n"
    243            "        else\n"
    244            "        {\n"
    245            "            exponent -= 15;\n"
    246            "            float scale;\n"
    247            "            if(exponent < 0)\n"
    248            "            {\n"
    249            "                // The negative unary operator is buggy on OSX.\n"
    250            "                // Work around this by using abs instead.\n"
    251            "                scale = 1.0 / (1 << abs(exponent));\n"
    252            "            }\n"
    253            "            else\n"
    254            "            {\n"
    255            "                scale = 1 << exponent;\n"
    256            "            }\n"
    257            "            float decimal = 1.0 + float(mantissa) / float(1 << 10);\n"
    258            "            f32 = scale * decimal;\n"
    259            "        }\n"
    260            "\n"
    261            "        if (sign != 0u)\n"
    262            "        {\n"
    263            "            f32 = -f32;\n"
    264            "        }\n"
    265            "\n"
    266            "        return f32;\n"
    267            "    }\n"
    268            "#endif\n"
    269            "\n"
    270            "vec2 unpackHalf2x16_emu(uint u)\n"
    271            "{\n"
    272            "    #if defined(GL_ARB_shading_language_packing)\n"
    273            "        return unpackHalf2x16(u);\n"
    274            "    #else\n"
    275            "        uint y = (u >> 16);\n"
    276            "        uint x = u & 0xFFFFu;\n"
    277            "        return vec2(f16tof32(x), f16tof32(y));\n"
    278            "    #endif\n"
    279            "}\n");
    280        // clang-format on
    281    }
    282 }
    283 
    284 }  // namespace sh