tor-browser

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

DynamicImage2DHLSL.cpp (31502B)


      1 //
      2 // Copyright 2019 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 // DynamicImage2DHLSL.cpp: Implementation for link and run-time HLSL generation
      7 //
      8 
      9 #include "libANGLE/renderer/d3d/DynamicImage2DHLSL.h"
     10 
     11 #include "common/string_utils.h"
     12 #include "libANGLE/renderer/d3d/ProgramD3D.h"
     13 #include "libANGLE/renderer/d3d/ShaderD3D.h"
     14 
     15 using namespace gl;
     16 
     17 namespace rx
     18 {
     19 
     20 namespace
     21 {
     22 
     23 enum Image2DHLSLGroup
     24 {
     25    IMAGE2D_R_FLOAT4,
     26    IMAGE2D_MIN = IMAGE2D_R_FLOAT4,
     27    IMAGE2D_R_UNORM,
     28    IMAGE2D_R_SNORM,
     29    IMAGE2D_R_UINT4,
     30    IMAGE2D_R_INT4,
     31    IMAGE2D_W_FLOAT4,
     32    IMAGE2D_W_UNORM,
     33    IMAGE2D_W_SNORM,
     34    IMAGE2D_W_UINT4,
     35    IMAGE2D_W_INT4,
     36    IMAGE2D_UNKNOWN,
     37    IMAGE2D_MAX = IMAGE2D_UNKNOWN
     38 };
     39 
     40 enum Image2DMethod
     41 {
     42    IMAGE2DSIZE,
     43    IMAGE2DLOAD,
     44    IMAGE2DSTORE
     45 };
     46 
     47 Image2DHLSLGroup image2DHLSLGroup(const sh::ShaderVariable &uniform)
     48 {
     49    GLenum format = uniform.imageUnitFormat;
     50    bool readonly = uniform.readonly;
     51    switch (uniform.type)
     52    {
     53        case GL_IMAGE_2D:
     54        {
     55            switch (format)
     56            {
     57                case GL_RGBA32F:
     58                case GL_RGBA16F:
     59                case GL_R32F:
     60                    return readonly ? IMAGE2D_R_FLOAT4 : IMAGE2D_W_FLOAT4;
     61                case GL_RGBA8:
     62                    return readonly ? IMAGE2D_R_UNORM : IMAGE2D_W_UNORM;
     63                case GL_RGBA8_SNORM:
     64                    return readonly ? IMAGE2D_R_SNORM : IMAGE2D_W_SNORM;
     65                default:
     66                    UNREACHABLE();
     67                    return IMAGE2D_UNKNOWN;
     68            }
     69        }
     70        case GL_INT_IMAGE_2D:
     71        {
     72            switch (format)
     73            {
     74                case GL_RGBA32I:
     75                case GL_RGBA16I:
     76                case GL_RGBA8I:
     77                case GL_R32I:
     78                    return readonly ? IMAGE2D_R_INT4 : IMAGE2D_W_INT4;
     79                default:
     80                    UNREACHABLE();
     81                    return IMAGE2D_UNKNOWN;
     82            }
     83        }
     84        case GL_UNSIGNED_INT_IMAGE_2D:
     85        {
     86            switch (format)
     87            {
     88                case GL_RGBA32UI:
     89                case GL_RGBA16UI:
     90                case GL_RGBA8UI:
     91                case GL_R32UI:
     92                    return readonly ? IMAGE2D_R_UINT4 : IMAGE2D_W_UINT4;
     93                default:
     94                    UNREACHABLE();
     95                    return IMAGE2D_UNKNOWN;
     96            }
     97        }
     98        default:
     99            UNREACHABLE();
    100            return IMAGE2D_UNKNOWN;
    101    }
    102 }
    103 
    104 std::string Image2DHLSLGroupSuffix(Image2DHLSLGroup group)
    105 {
    106    switch (group)
    107    {
    108        case IMAGE2D_R_FLOAT4:
    109            return "2D";
    110        case IMAGE2D_R_UNORM:
    111            return "2D_unorm_float4_";
    112        case IMAGE2D_R_SNORM:
    113            return "2D_snorm_float4_";
    114        case IMAGE2D_R_UINT4:
    115            return "2D_uint4_";
    116        case IMAGE2D_R_INT4:
    117            return "2D_int4_";
    118        case IMAGE2D_W_FLOAT4:
    119            return "RW2D_float4_";
    120        case IMAGE2D_W_UNORM:
    121            return "RW2D_unorm_float4_";
    122        case IMAGE2D_W_SNORM:
    123            return "RW2D_snorm_float4_";
    124        case IMAGE2D_W_UINT4:
    125            return "RW2D_uint4_";
    126        case IMAGE2D_W_INT4:
    127            return "RW2D_int4_";
    128        default:
    129            UNREACHABLE();
    130    }
    131 
    132    return "<unknown group type>";
    133 }
    134 
    135 std::string Image2DHLSLTextureString(Image2DHLSLGroup group,
    136                                     gl::TextureType type,
    137                                     bool rasterOrdered)
    138 {
    139    std::string textureString;
    140    switch (group)
    141    {
    142        case IMAGE2D_R_FLOAT4:
    143        case IMAGE2D_R_UNORM:
    144        case IMAGE2D_R_SNORM:
    145        case IMAGE2D_R_UINT4:
    146        case IMAGE2D_R_INT4:
    147            break;
    148        case IMAGE2D_W_FLOAT4:
    149        case IMAGE2D_W_UNORM:
    150        case IMAGE2D_W_SNORM:
    151        case IMAGE2D_W_UINT4:
    152        case IMAGE2D_W_INT4:
    153            textureString += rasterOrdered ? "RasterizerOrdered" : "RW";
    154            break;
    155        default:
    156            UNREACHABLE();
    157    }
    158 
    159    textureString += "Texture";
    160 
    161    switch (type)
    162    {
    163        case gl::TextureType::_2D:
    164            textureString += "2D";
    165            break;
    166        case gl::TextureType::_3D:
    167            textureString += "3D";
    168            break;
    169        case gl::TextureType::_2DArray:
    170            textureString += "2DArray";
    171            break;
    172        default:
    173            UNREACHABLE();
    174    }
    175 
    176    switch (group)
    177    {
    178        case IMAGE2D_R_FLOAT4:
    179        case IMAGE2D_W_FLOAT4:
    180            textureString += "<float4>";
    181            break;
    182        case IMAGE2D_R_UNORM:
    183        case IMAGE2D_W_UNORM:
    184            textureString += "<unorm float4>";
    185            break;
    186        case IMAGE2D_R_SNORM:
    187        case IMAGE2D_W_SNORM:
    188            textureString += "<snorm float4>";
    189            break;
    190        case IMAGE2D_R_UINT4:
    191        case IMAGE2D_W_UINT4:
    192            textureString += "<uint4>";
    193            break;
    194        case IMAGE2D_R_INT4:
    195        case IMAGE2D_W_INT4:
    196            textureString += "<int4>";
    197            break;
    198        default:
    199            UNREACHABLE();
    200    }
    201 
    202    return textureString;
    203 }
    204 
    205 std::string Image2DHLSLGroupOffsetPrefix(Image2DHLSLGroup group)
    206 {
    207    switch (group)
    208    {
    209        case IMAGE2D_R_FLOAT4:
    210        case IMAGE2D_R_UNORM:
    211        case IMAGE2D_R_SNORM:
    212        case IMAGE2D_R_UINT4:
    213        case IMAGE2D_R_INT4:
    214            return "readonlyImageIndexOffset";
    215        case IMAGE2D_W_FLOAT4:
    216        case IMAGE2D_W_UNORM:
    217        case IMAGE2D_W_SNORM:
    218        case IMAGE2D_W_UINT4:
    219        case IMAGE2D_W_INT4:
    220            return "imageIndexOffset";
    221        default:
    222            UNREACHABLE();
    223    }
    224 
    225    return "<unknown group type>";
    226 }
    227 
    228 std::string Image2DHLSLGroupDeclarationPrefix(Image2DHLSLGroup group)
    229 {
    230    switch (group)
    231    {
    232        case IMAGE2D_R_FLOAT4:
    233        case IMAGE2D_R_UNORM:
    234        case IMAGE2D_R_SNORM:
    235        case IMAGE2D_R_UINT4:
    236        case IMAGE2D_R_INT4:
    237            return "readonlyImages";
    238        case IMAGE2D_W_FLOAT4:
    239        case IMAGE2D_W_UNORM:
    240        case IMAGE2D_W_SNORM:
    241        case IMAGE2D_W_UINT4:
    242        case IMAGE2D_W_INT4:
    243            return "images";
    244        default:
    245            UNREACHABLE();
    246    }
    247 
    248    return "<unknown group type>";
    249 }
    250 
    251 std::string Image2DHLSLGroupRegisterSuffix(Image2DHLSLGroup group)
    252 {
    253    switch (group)
    254    {
    255        case IMAGE2D_R_FLOAT4:
    256        case IMAGE2D_R_UNORM:
    257        case IMAGE2D_R_SNORM:
    258        case IMAGE2D_R_UINT4:
    259        case IMAGE2D_R_INT4:
    260            return "t";
    261        case IMAGE2D_W_FLOAT4:
    262        case IMAGE2D_W_UNORM:
    263        case IMAGE2D_W_SNORM:
    264        case IMAGE2D_W_UINT4:
    265        case IMAGE2D_W_INT4:
    266            return "u";
    267        default:
    268            UNREACHABLE();
    269    }
    270 
    271    return "<unknown group type>";
    272 }
    273 
    274 std::string Image2DHLSLGroupFunctionName(Image2DHLSLGroup group, Image2DMethod method)
    275 {
    276    std::string name = "gl_image";
    277    name += Image2DHLSLGroupSuffix(group);
    278    switch (method)
    279    {
    280        case IMAGE2DSIZE:
    281            name += "Size";
    282            break;
    283        case IMAGE2DLOAD:
    284            name += "Load";
    285            break;
    286        case IMAGE2DSTORE:
    287            name += "Store";
    288            break;
    289        default:
    290            UNREACHABLE();
    291    }
    292 
    293    return name;
    294 }
    295 
    296 std::string getImage2DGroupReturnType(Image2DHLSLGroup group, Image2DMethod method)
    297 {
    298    switch (method)
    299    {
    300        case IMAGE2DSIZE:
    301            return "int2";
    302        case IMAGE2DLOAD:
    303            switch (group)
    304            {
    305                case IMAGE2D_R_FLOAT4:
    306                case IMAGE2D_R_UNORM:
    307                case IMAGE2D_R_SNORM:
    308                case IMAGE2D_W_FLOAT4:
    309                case IMAGE2D_W_UNORM:
    310                case IMAGE2D_W_SNORM:
    311                    return "float4";
    312                case IMAGE2D_R_UINT4:
    313                case IMAGE2D_W_UINT4:
    314                    return "uint4";
    315                case IMAGE2D_R_INT4:
    316                case IMAGE2D_W_INT4:
    317                    return "int4";
    318                default:
    319                    UNREACHABLE();
    320                    return "unknown group type";
    321            }
    322        case IMAGE2DSTORE:
    323            return "void";
    324        default:
    325            UNREACHABLE();
    326            return "unknown image method";
    327    }
    328 }
    329 
    330 std::string getImageMetadata(Image2DHLSLGroup group)
    331 {
    332    switch (group)
    333    {
    334        case IMAGE2D_R_FLOAT4:
    335        case IMAGE2D_R_UNORM:
    336        case IMAGE2D_R_SNORM:
    337        case IMAGE2D_R_UINT4:
    338        case IMAGE2D_R_INT4:
    339            return "readonlyImageMetadata[imageIndex - readonlyImageIndexStart]";
    340        case IMAGE2D_W_FLOAT4:
    341        case IMAGE2D_W_UNORM:
    342        case IMAGE2D_W_SNORM:
    343        case IMAGE2D_W_UINT4:
    344        case IMAGE2D_W_INT4:
    345            return "imageMetadata[imageIndex - imageIndexStart]";
    346        default:
    347            UNREACHABLE();
    348            return "unknown image method";
    349    }
    350 }
    351 
    352 void OutputImage2DFunctionArgumentList(std::ostringstream &out,
    353                                       Image2DHLSLGroup group,
    354                                       Image2DMethod method)
    355 {
    356    out << "uint imageIndex";
    357 
    358    if (method == IMAGE2DLOAD || method == IMAGE2DSTORE)
    359    {
    360        out << ", int2 p";
    361        if (method == IMAGE2DSTORE)
    362        {
    363            switch (group)
    364            {
    365                case IMAGE2D_R_FLOAT4:
    366                case IMAGE2D_R_UNORM:
    367                case IMAGE2D_R_SNORM:
    368                case IMAGE2D_W_FLOAT4:
    369                case IMAGE2D_W_UNORM:
    370                case IMAGE2D_W_SNORM:
    371                    out << ", float4 data";
    372                    break;
    373                case IMAGE2D_R_UINT4:
    374                case IMAGE2D_W_UINT4:
    375                    out << ", uint4 data";
    376                    break;
    377                case IMAGE2D_R_INT4:
    378                case IMAGE2D_W_INT4:
    379                    out << ", int4 data";
    380                    break;
    381                default:
    382                    UNREACHABLE();
    383            }
    384        }
    385    }
    386 }
    387 
    388 void OutputImage2DSizeFunction(std::ostringstream &out,
    389                               Image2DHLSLGroup textureGroup,
    390                               unsigned int totalCount,
    391                               unsigned int texture2DCount,
    392                               unsigned int texture3DCount,
    393                               unsigned int texture2DArrayCount,
    394                               const std::string &offsetStr,
    395                               const std::string &declarationStr)
    396 {
    397    out << getImage2DGroupReturnType(textureGroup, IMAGE2DSIZE) << " "
    398        << Image2DHLSLGroupFunctionName(textureGroup, IMAGE2DSIZE) << "(";
    399    OutputImage2DFunctionArgumentList(out, textureGroup, IMAGE2DSIZE);
    400    out << ")\n"
    401           "{\n";
    402    out << "    uint width, height;\n";
    403 
    404    if (texture2DCount > 0)
    405    {
    406        if (texture2DCount == totalCount)
    407        {
    408            out << "    const uint index = imageIndex -  " << offsetStr << "2D;\n";
    409            out << "    " << declarationStr << "2D[index].GetDimensions(width, height);\n";
    410        }
    411        else
    412        {
    413            out << "    if (imageIndex >= " << offsetStr << "2D && imageIndex < " << offsetStr
    414                << "2D + " << texture2DCount << ")\n";
    415            out << "    {\n";
    416            out << "        const uint index = imageIndex -  " << offsetStr << "2D;\n";
    417            out << "        " << declarationStr << "2D[index].GetDimensions(width, height);\n";
    418            out << "    }\n";
    419        }
    420    }
    421 
    422    if (texture3DCount > 0)
    423    {
    424        if (texture3DCount == totalCount)
    425        {
    426            out << "    const uint index = imageIndex -  " << offsetStr << "3D;\n";
    427            out << "    uint depth;\n";
    428            out << "    " << declarationStr << "3D[index].GetDimensions(width, height, depth);\n";
    429        }
    430        else
    431        {
    432            if (texture2DArrayCount == 0)
    433            {
    434                out << "    else\n";
    435            }
    436            else
    437            {
    438                if (texture2DCount == 0)
    439                {
    440                    out << "    if ";
    441                }
    442                else
    443                {
    444                    out << "    else if";
    445                }
    446                out << "(imageIndex >= " << offsetStr << "3D && imageIndex < " << offsetStr
    447                    << "3D + " << texture3DCount << ")\n";
    448            }
    449            out << "    {\n";
    450            out << "        const uint index = imageIndex -  " << offsetStr << "3D;\n";
    451            out << "        uint depth;\n";
    452            out << "        " << declarationStr
    453                << "3D[index].GetDimensions(width, height, depth);\n";
    454            out << "    }\n";
    455        }
    456    }
    457 
    458    if (texture2DArrayCount > 0)
    459    {
    460        if (texture2DArrayCount == totalCount)
    461        {
    462            out << "    const uint index = imageIndex -  " << offsetStr << "2DArray;\n";
    463            out << "    uint depth;\n";
    464            out << "    " << declarationStr
    465                << "2DArray[index].GetDimensions(width, height, depth);\n";
    466        }
    467        else
    468        {
    469            out << "    else\n";
    470            out << "    {\n";
    471            out << "        const uint index = imageIndex -  " << offsetStr << "2DArray;\n";
    472            out << "        uint depth;\n";
    473            out << "        " << declarationStr
    474                << "2DArray[index].GetDimensions(width, height, depth);\n";
    475            out << "    }\n";
    476        }
    477    }
    478    out << "    return int2(width, height);\n";
    479 
    480    out << "}\n";
    481 }
    482 
    483 void OutputImage2DLoadFunction(std::ostringstream &out,
    484                               Image2DHLSLGroup textureGroup,
    485                               unsigned int totalCount,
    486                               unsigned int texture2DCount,
    487                               unsigned int texture3DCount,
    488                               unsigned int texture2DArrayCount,
    489                               const std::string &offsetStr,
    490                               const std::string &declarationStr)
    491 {
    492    out << getImage2DGroupReturnType(textureGroup, IMAGE2DLOAD) << " "
    493        << Image2DHLSLGroupFunctionName(textureGroup, IMAGE2DLOAD) << "(";
    494    OutputImage2DFunctionArgumentList(out, textureGroup, IMAGE2DLOAD);
    495    out << ")\n"
    496           "{\n";
    497 
    498    out << "    " << getImage2DGroupReturnType(textureGroup, IMAGE2DLOAD) << " result;\n";
    499 
    500    if (texture2DCount > 0)
    501    {
    502        if (texture2DCount == totalCount)
    503        {
    504            out << "    const uint index = imageIndex -  " << offsetStr << "2D;\n";
    505            out << "    result = " << declarationStr << "2D[index][uint2(p.x, p.y)];\n";
    506        }
    507        else
    508        {
    509            out << "    if (imageIndex >= " << offsetStr << "2D && imageIndex < " << offsetStr
    510                << "2D + " << texture2DCount << ")\n";
    511            out << "    {\n";
    512            out << "        const uint index = imageIndex -  " << offsetStr << "2D;\n";
    513            out << "        result = " << declarationStr << "2D[index][uint2(p.x, p.y)];\n";
    514            out << "    }\n";
    515        }
    516    }
    517 
    518    if (texture3DCount > 0)
    519    {
    520        if (texture3DCount == totalCount)
    521        {
    522            out << "    const uint index = imageIndex -  " << offsetStr << "3D;\n";
    523            out << "    result = " << declarationStr << "3D[index][uint3(p.x, p.y, "
    524                << getImageMetadata(textureGroup) << ".layer)];\n";
    525        }
    526        else
    527        {
    528            if (texture2DArrayCount == 0)
    529            {
    530                out << "    else\n";
    531            }
    532            else
    533            {
    534                if (texture2DCount == 0)
    535                {
    536                    out << "    if ";
    537                }
    538                else
    539                {
    540                    out << "    else if";
    541                }
    542                out << "(imageIndex >= " << offsetStr << "3D && imageIndex < " << offsetStr
    543                    << "3D + " << texture3DCount << ")\n";
    544            }
    545            out << "    {\n";
    546            out << "        const uint index = imageIndex -  " << offsetStr << "3D;\n";
    547            out << "        result = " << declarationStr << "3D[index][uint3(p.x, p.y, "
    548                << getImageMetadata(textureGroup) << ".layer)];\n";
    549            out << "    }\n";
    550        }
    551    }
    552 
    553    if (texture2DArrayCount > 0)
    554    {
    555        if (texture2DArrayCount == totalCount)
    556        {
    557            out << "    const uint index = imageIndex -  " << offsetStr << "2DArray;\n";
    558            out << "    result = " << declarationStr << "2DArray[index][uint3(p.x, p.y, "
    559                << getImageMetadata(textureGroup) << ".layer)];\n";
    560        }
    561        else
    562        {
    563            out << "    else\n";
    564            out << "    {\n";
    565            out << "        const uint index = imageIndex -  " << offsetStr << "2DArray;\n";
    566            out << "        result = " << declarationStr << "2DArray[index][uint3(p.x, p.y, "
    567                << getImageMetadata(textureGroup) << ".layer)];\n";
    568            out << "    }\n";
    569        }
    570    }
    571 
    572    out << "    return result;\n";
    573    out << "}\n";
    574 }
    575 
    576 void OutputImage2DStoreFunction(std::ostringstream &out,
    577                                Image2DHLSLGroup textureGroup,
    578                                unsigned int totalCount,
    579                                unsigned int texture2DCount,
    580                                unsigned int texture3DCount,
    581                                unsigned int texture2DArrayCount,
    582                                const std::string &offsetStr,
    583                                const std::string &declarationStr)
    584 {
    585    out << getImage2DGroupReturnType(textureGroup, IMAGE2DSTORE) << " "
    586        << Image2DHLSLGroupFunctionName(textureGroup, IMAGE2DSTORE) << "(";
    587    OutputImage2DFunctionArgumentList(out, textureGroup, IMAGE2DSTORE);
    588    out << ")\n"
    589           "{\n";
    590 
    591    if (texture2DCount > 0)
    592    {
    593        if (texture2DCount == totalCount)
    594        {
    595            out << "    const uint index = imageIndex -  " << offsetStr << "2D;\n";
    596            out << "    " << declarationStr << "2D[index][uint2(p.x, p.y)] = data;\n";
    597        }
    598        else
    599        {
    600            out << "    if (imageIndex >= " << offsetStr << "2D && imageIndex < " << offsetStr
    601                << "2D + " << texture2DCount << ")\n";
    602            out << "    {\n";
    603            out << "        const uint index = imageIndex -  " << offsetStr << "2D;\n";
    604            out << "        " << declarationStr << "2D[index][uint2(p.x, p.y)] = data;\n";
    605            out << "    }\n";
    606        }
    607    }
    608 
    609    if (texture3DCount > 0)
    610    {
    611        if (texture3DCount == totalCount)
    612        {
    613            out << "    const uint index = imageIndex -  " << offsetStr << "3D;\n";
    614            out << "    " << declarationStr << "3D[index][uint3(p.x, p.y, "
    615                << getImageMetadata(textureGroup) << ".layer)] = data;\n";
    616        }
    617        else
    618        {
    619            if (texture2DArrayCount == 0)
    620            {
    621                out << "    else\n";
    622            }
    623            else
    624            {
    625                if (texture2DCount == 0)
    626                {
    627                    out << "    if ";
    628                }
    629                else
    630                {
    631                    out << "    else if";
    632                }
    633                out << "(imageIndex >= " << offsetStr << "3D && imageIndex < " << offsetStr
    634                    << "3D + " << texture3DCount << ")\n";
    635            }
    636            out << "    {\n";
    637            out << "        const uint index = imageIndex -  " << offsetStr << "3D;\n";
    638            out << "        " << declarationStr << "3D[index][uint3(p.x, p.y, "
    639                << getImageMetadata(textureGroup) << ".layer)] = data;\n";
    640            out << "    }\n";
    641        }
    642    }
    643 
    644    if (texture2DArrayCount > 0)
    645    {
    646        if (texture2DArrayCount == totalCount)
    647        {
    648            out << "    const uint index = imageIndex -  " << offsetStr << "2DArray;\n";
    649            out << "    " << declarationStr << "2DArray[index][uint3(p.x, p.y, "
    650                << getImageMetadata(textureGroup) << ".layer)] = data;\n";
    651        }
    652        else
    653        {
    654            out << "    else\n";
    655            out << "    {\n";
    656            out << "        const uint index = imageIndex -  " << offsetStr << "2DArray;\n";
    657            out << "        " << declarationStr << "2DArray[index][uint3(p.x, p.y, "
    658                << getImageMetadata(textureGroup) << ".layer)] = data;\n";
    659            out << "    }\n";
    660        }
    661    }
    662 
    663    out << "}\n";
    664 }
    665 
    666 unsigned int *GetImage2DRegisterIndex(Image2DHLSLGroup textureGroup,
    667                                      unsigned int *groupTextureRegisterIndex,
    668                                      unsigned int *groupRWTextureRegisterIndex)
    669 {
    670    switch (textureGroup)
    671    {
    672        case IMAGE2D_R_FLOAT4:
    673        case IMAGE2D_R_UNORM:
    674        case IMAGE2D_R_SNORM:
    675        case IMAGE2D_R_UINT4:
    676        case IMAGE2D_R_INT4:
    677            return groupTextureRegisterIndex;
    678        case IMAGE2D_W_FLOAT4:
    679        case IMAGE2D_W_UNORM:
    680        case IMAGE2D_W_SNORM:
    681        case IMAGE2D_W_UINT4:
    682        case IMAGE2D_W_INT4:
    683            return groupRWTextureRegisterIndex;
    684        default:
    685            UNREACHABLE();
    686            return nullptr;
    687    }
    688 }
    689 
    690 void OutputHLSLImage2DUniformGroup(ProgramD3D &programD3D,
    691                                   const gl::ProgramState &programData,
    692                                   gl::ShaderType shaderType,
    693                                   std::ostringstream &out,
    694                                   const Image2DHLSLGroup textureGroup,
    695                                   const std::vector<sh::ShaderVariable> &group,
    696                                   const gl::ImageUnitTextureTypeMap &image2DBindLayout,
    697                                   unsigned int baseUAVRegister,
    698                                   unsigned int *groupTextureRegisterIndex,
    699                                   unsigned int *groupRWTextureRegisterIndex,
    700                                   unsigned int *image2DTexture3D,
    701                                   unsigned int *image2DTexture2DArray,
    702                                   unsigned int *image2DTexture2D)
    703 {
    704    if (group.empty())
    705    {
    706        return;
    707    }
    708 
    709    unsigned int texture2DCount = 0, texture3DCount = 0, texture2DArrayCount = 0;
    710    bool texture2DRasterOrdered = false, texture3DRasterOrdered = false,
    711         texture2DArrayRasterOrdered = false;
    712    for (const sh::ShaderVariable &uniform : group)
    713    {
    714        if (!programD3D.hasNamedUniform(uniform.name))
    715        {
    716            continue;
    717        }
    718        for (unsigned int index = 0; index < uniform.getArraySizeProduct(); index++)
    719        {
    720            switch (image2DBindLayout.at(uniform.binding + index))
    721            {
    722                case gl::TextureType::_2D:
    723                    texture2DCount++;
    724                    texture2DRasterOrdered |= uniform.rasterOrdered;
    725                    break;
    726                case gl::TextureType::_3D:
    727                    texture3DCount++;
    728                    texture3DRasterOrdered |= uniform.rasterOrdered;
    729                    break;
    730                case gl::TextureType::_2DArray:
    731                case gl::TextureType::CubeMap:
    732                    texture2DArrayCount++;
    733                    texture2DArrayRasterOrdered |= uniform.rasterOrdered;
    734                    break;
    735                default:
    736                    UNREACHABLE();
    737            }
    738        }
    739    }
    740 
    741    unsigned int totalCount            = texture2DCount + texture3DCount + texture2DArrayCount;
    742    unsigned int *image2DRegisterIndex = GetImage2DRegisterIndex(
    743        textureGroup, groupTextureRegisterIndex, groupRWTextureRegisterIndex);
    744    unsigned int texture2DRegisterIndex      = *image2DRegisterIndex;
    745    unsigned int texture3DRegisterIndex      = texture2DRegisterIndex + texture2DCount;
    746    unsigned int texture2DArrayRegisterIndex = texture3DRegisterIndex + texture3DCount;
    747    *image2DRegisterIndex += totalCount;
    748 
    749    std::string offsetStr =
    750        Image2DHLSLGroupOffsetPrefix(textureGroup) + Image2DHLSLGroupSuffix(textureGroup);
    751    std::string declarationStr =
    752        Image2DHLSLGroupDeclarationPrefix(textureGroup) + Image2DHLSLGroupSuffix(textureGroup);
    753    std::string registerStr = Image2DHLSLGroupRegisterSuffix(textureGroup);
    754    if (texture2DCount > 0)
    755    {
    756        out << "static const uint " << offsetStr << "2D = " << texture2DRegisterIndex << ";\n";
    757        out << "uniform "
    758            << Image2DHLSLTextureString(textureGroup, gl::TextureType::_2D, texture2DRasterOrdered)
    759            << " " << declarationStr << "2D[" << texture2DCount << "]"
    760            << " : register(" << registerStr << baseUAVRegister + texture2DRegisterIndex << ");\n";
    761    }
    762    if (texture3DCount > 0)
    763    {
    764        out << "static const uint " << offsetStr << "3D = " << texture3DRegisterIndex << ";\n";
    765        out << "uniform "
    766            << Image2DHLSLTextureString(textureGroup, gl::TextureType::_3D, texture3DRasterOrdered)
    767            << " " << declarationStr << "3D[" << texture3DCount << "]"
    768            << " : register(" << registerStr << baseUAVRegister + texture3DRegisterIndex << ");\n";
    769    }
    770    if (texture2DArrayCount > 0)
    771    {
    772        out << "static const uint " << offsetStr << "2DArray = " << texture2DArrayRegisterIndex
    773            << ";\n";
    774        out << "uniform "
    775            << Image2DHLSLTextureString(textureGroup, gl::TextureType::_2DArray,
    776                                        texture2DArrayRasterOrdered)
    777            << " " << declarationStr << "2DArray[" << texture2DArrayCount << "]"
    778            << " : register(" << registerStr << baseUAVRegister + texture2DArrayRegisterIndex
    779            << ");\n";
    780    }
    781    for (const sh::ShaderVariable &uniform : group)
    782    {
    783        if (!programD3D.hasNamedUniform(uniform.name))
    784        {
    785            continue;
    786        }
    787 
    788        out << "static const uint " << DecorateVariable(uniform.name)
    789            << ArrayIndexString(uniform.arraySizes) << " = {";
    790        for (unsigned int index = 0; index < uniform.getArraySizeProduct(); index++)
    791        {
    792            if (index > 0)
    793            {
    794                out << ", ";
    795            }
    796            switch (image2DBindLayout.at(uniform.binding + index))
    797            {
    798                case gl::TextureType::_2D:
    799                {
    800                    out << texture2DRegisterIndex;
    801                    programD3D.assignImage2DRegisters(shaderType, texture2DRegisterIndex,
    802                                                      uniform.binding + index, uniform.readonly);
    803                    texture2DRegisterIndex++;
    804                    break;
    805                }
    806                case gl::TextureType::_3D:
    807                {
    808                    out << texture3DRegisterIndex;
    809                    programD3D.assignImage2DRegisters(shaderType, texture3DRegisterIndex,
    810                                                      uniform.binding + index, uniform.readonly);
    811                    texture3DRegisterIndex++;
    812                    break;
    813                }
    814                case gl::TextureType::_2DArray:
    815                case gl::TextureType::CubeMap:
    816                {
    817                    out << texture2DArrayRegisterIndex;
    818                    programD3D.assignImage2DRegisters(shaderType, texture2DArrayRegisterIndex,
    819                                                      uniform.binding + index, uniform.readonly);
    820                    texture2DArrayRegisterIndex++;
    821                    break;
    822                }
    823                default:
    824                    UNREACHABLE();
    825            }
    826        }
    827        out << "};\n";
    828    }
    829 
    830    gl::Shader *shaderGL       = programData.getAttachedShader(shaderType);
    831    const ShaderD3D *shaderD3D = GetImplAs<ShaderD3D>(shaderGL);
    832 
    833    if (shaderD3D->useImage2DFunction(Image2DHLSLGroupFunctionName(textureGroup, IMAGE2DSIZE)))
    834    {
    835        OutputImage2DSizeFunction(out, textureGroup, totalCount, texture2DCount, texture3DCount,
    836                                  texture2DArrayCount, offsetStr, declarationStr);
    837    }
    838    if (shaderD3D->useImage2DFunction(Image2DHLSLGroupFunctionName(textureGroup, IMAGE2DLOAD)))
    839    {
    840        OutputImage2DLoadFunction(out, textureGroup, totalCount, texture2DCount, texture3DCount,
    841                                  texture2DArrayCount, offsetStr, declarationStr);
    842    }
    843    if (shaderD3D->useImage2DFunction(Image2DHLSLGroupFunctionName(textureGroup, IMAGE2DSTORE)))
    844    {
    845        OutputImage2DStoreFunction(out, textureGroup, totalCount, texture2DCount, texture3DCount,
    846                                   texture2DArrayCount, offsetStr, declarationStr);
    847    }
    848 }
    849 
    850 // kImage2DFunctionString must be the same as outputHLSL.
    851 constexpr const char kImage2DFunctionString[] = "// @@ IMAGE2D DECLARATION FUNCTION STRING @@";
    852 }  // anonymous namespace
    853 
    854 std::string GenerateShaderForImage2DBindSignature(
    855    ProgramD3D &programD3D,
    856    const gl::ProgramState &programData,
    857    gl::ShaderType shaderType,
    858    const std::string &shaderHLSL,
    859    std::vector<sh::ShaderVariable> &image2DUniforms,
    860    const gl::ImageUnitTextureTypeMap &image2DBindLayout,
    861    unsigned int baseUAVRegister)
    862 {
    863    std::vector<std::vector<sh::ShaderVariable>> groupedImage2DUniforms(IMAGE2D_MAX + 1);
    864    unsigned int image2DTexture3DCount = 0, image2DTexture2DArrayCount = 0;
    865    for (sh::ShaderVariable &image2D : image2DUniforms)
    866    {
    867        for (unsigned int index = 0; index < image2D.getArraySizeProduct(); index++)
    868        {
    869            // Any image variable declared without a binding qualifier is initially bound to unit
    870            // zero.
    871            if (image2D.binding == -1)
    872            {
    873                image2D.binding = 0;
    874            }
    875            switch (image2DBindLayout.at(image2D.binding + index))
    876            {
    877                case gl::TextureType::_2D:
    878                    break;
    879                case gl::TextureType::_3D:
    880                    image2DTexture3DCount++;
    881                    break;
    882                case gl::TextureType::_2DArray:
    883                case gl::TextureType::CubeMap:
    884                    image2DTexture2DArrayCount++;
    885                    break;
    886                default:
    887                    UNREACHABLE();
    888            }
    889        }
    890        Image2DHLSLGroup group = image2DHLSLGroup(image2D);
    891        groupedImage2DUniforms[group].push_back(image2D);
    892    }
    893 
    894    gl::Shader *shaderGL                     = programData.getAttachedShader(shaderType);
    895    const ShaderD3D *shaderD3D               = GetImplAs<ShaderD3D>(shaderGL);
    896    unsigned int groupTextureRegisterIndex   = shaderD3D->getReadonlyImage2DRegisterIndex();
    897    unsigned int groupRWTextureRegisterIndex = shaderD3D->getImage2DRegisterIndex();
    898    unsigned int image2DTexture3DIndex       = 0;
    899    unsigned int image2DTexture2DArrayIndex  = image2DTexture3DCount;
    900    unsigned int image2DTexture2DIndex       = image2DTexture3DCount + image2DTexture2DArrayCount;
    901    std::ostringstream out;
    902 
    903    for (int groupId = IMAGE2D_MIN; groupId < IMAGE2D_MAX; ++groupId)
    904    {
    905        OutputHLSLImage2DUniformGroup(
    906            programD3D, programData, shaderType, out, Image2DHLSLGroup(groupId),
    907            groupedImage2DUniforms[groupId], image2DBindLayout, baseUAVRegister,
    908            &groupTextureRegisterIndex, &groupRWTextureRegisterIndex, &image2DTexture3DIndex,
    909            &image2DTexture2DArrayIndex, &image2DTexture2DIndex);
    910    }
    911 
    912    std::string result = shaderHLSL;
    913    bool success       = angle::ReplaceSubstring(&result, kImage2DFunctionString, out.str());
    914    ASSERT(success);
    915 
    916    return result;
    917 }
    918 
    919 }  // namespace rx