tor-browser

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

ImageFunctionHLSL.cpp (12345B)


      1 //
      2 // Copyright 2017 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 // ImageFunctionHLSL: Class for writing implementations of ESSL image functions into HLSL output.
      7 //
      8 
      9 #include "compiler/translator/ImageFunctionHLSL.h"
     10 #include "compiler/translator/ImmutableStringBuilder.h"
     11 #include "compiler/translator/UtilsHLSL.h"
     12 
     13 namespace sh
     14 {
     15 
     16 // static
     17 ImmutableString ImageFunctionHLSL::GetImageReference(
     18    TInfoSinkBase &out,
     19    const ImageFunctionHLSL::ImageFunction &imageFunction)
     20 {
     21    static const ImmutableString kImageIndexStr("[index]");
     22    if (imageFunction.readonly)
     23    {
     24        static const ImmutableString kReadonlyImagesStr("readonlyImages");
     25        ImmutableString suffix(
     26            TextureGroupSuffix(imageFunction.image, imageFunction.imageInternalFormat));
     27        out << "    const uint index = imageIndex - readonlyImageIndexOffset" << suffix.data()
     28            << ";\n";
     29        ImmutableStringBuilder imageRefBuilder(kReadonlyImagesStr.length() + suffix.length() +
     30                                               kImageIndexStr.length());
     31        imageRefBuilder << kReadonlyImagesStr << suffix << kImageIndexStr;
     32        return imageRefBuilder;
     33    }
     34    else
     35    {
     36        static const ImmutableString kImagesStr("images");
     37        ImmutableString suffix(
     38            RWTextureGroupSuffix(imageFunction.image, imageFunction.imageInternalFormat));
     39        out << "    const uint index = imageIndex - imageIndexOffset" << suffix.data() << ";\n";
     40        ImmutableStringBuilder imageRefBuilder(kImagesStr.length() + suffix.length() +
     41                                               kImageIndexStr.length());
     42        imageRefBuilder << kImagesStr << suffix << kImageIndexStr;
     43        return imageRefBuilder;
     44    }
     45 }
     46 
     47 void ImageFunctionHLSL::OutputImageFunctionArgumentList(
     48    TInfoSinkBase &out,
     49    const ImageFunctionHLSL::ImageFunction &imageFunction)
     50 {
     51    out << "uint imageIndex";
     52 
     53    if (imageFunction.method == ImageFunctionHLSL::ImageFunction::Method::LOAD ||
     54        imageFunction.method == ImageFunctionHLSL::ImageFunction::Method::STORE)
     55    {
     56        switch (imageFunction.image)
     57        {
     58            case EbtImage2D:
     59            case EbtIImage2D:
     60            case EbtUImage2D:
     61                out << ", int2 p";
     62                break;
     63            case EbtImage3D:
     64            case EbtIImage3D:
     65            case EbtUImage3D:
     66            case EbtImageCube:
     67            case EbtIImageCube:
     68            case EbtUImageCube:
     69            case EbtImage2DArray:
     70            case EbtIImage2DArray:
     71            case EbtUImage2DArray:
     72                out << ", int3 p";
     73                break;
     74            case EbtUImageBuffer:
     75            case EbtIImageBuffer:
     76            case EbtImageBuffer:
     77                out << ", int p";
     78                break;
     79 
     80            default:
     81                UNREACHABLE();
     82        }
     83 
     84        if (imageFunction.method == ImageFunctionHLSL::ImageFunction::Method::STORE)
     85        {
     86            switch (imageFunction.image)
     87            {
     88                case EbtImage2D:
     89                case EbtImage3D:
     90                case EbtImageCube:
     91                case EbtImage2DArray:
     92                case EbtImageBuffer:
     93                    out << ", float4 data";
     94                    break;
     95                case EbtIImage2D:
     96                case EbtIImage3D:
     97                case EbtIImageCube:
     98                case EbtIImage2DArray:
     99                case EbtIImageBuffer:
    100                    out << ", int4 data";
    101                    break;
    102                case EbtUImage2D:
    103                case EbtUImage3D:
    104                case EbtUImageCube:
    105                case EbtUImage2DArray:
    106                case EbtUImageBuffer:
    107                    out << ", uint4 data";
    108                    break;
    109                default:
    110                    UNREACHABLE();
    111            }
    112        }
    113    }
    114 }
    115 
    116 // static
    117 void ImageFunctionHLSL::OutputImageSizeFunctionBody(
    118    TInfoSinkBase &out,
    119    const ImageFunctionHLSL::ImageFunction &imageFunction,
    120    const ImmutableString &imageReference)
    121 {
    122    if (IsImage3D(imageFunction.image) || IsImage2DArray(imageFunction.image) ||
    123        IsImageCube(imageFunction.image))
    124    {
    125        // "depth" stores either the number of layers in an array texture or 3D depth
    126        out << "    uint width; uint height; uint depth;\n"
    127            << "    " << imageReference << ".GetDimensions(width, height, depth);\n";
    128    }
    129    else if (IsImage2D(imageFunction.image))
    130    {
    131        out << "    uint width; uint height;\n"
    132            << "    " << imageReference << ".GetDimensions(width, height);\n";
    133    }
    134    else if (IsImageBuffer(imageFunction.image))
    135    {
    136        out << "    uint width;\n"
    137            << "    " << imageReference << ".GetDimensions(width);\n";
    138    }
    139    else
    140        UNREACHABLE();
    141 
    142    if (strcmp(imageFunction.getReturnType(), "int3") == 0)
    143    {
    144        out << "    return int3(width, height, depth);\n";
    145    }
    146    else if (strcmp(imageFunction.getReturnType(), "int2") == 0)
    147    {
    148        out << "    return int2(width, height);\n";
    149    }
    150    else if (strcmp(imageFunction.getReturnType(), "int") == 0)
    151        out << "    return int(width);\n";
    152    else
    153        UNREACHABLE();
    154 }
    155 
    156 // static
    157 void ImageFunctionHLSL::OutputImageLoadFunctionBody(
    158    TInfoSinkBase &out,
    159    const ImageFunctionHLSL::ImageFunction &imageFunction,
    160    const ImmutableString &imageReference)
    161 {
    162    if (IsImage3D(imageFunction.image) || IsImage2DArray(imageFunction.image) ||
    163        IsImageCube(imageFunction.image))
    164    {
    165        out << "    return " << imageReference << "[uint3(p.x, p.y, p.z)];\n";
    166    }
    167    else if (IsImage2D(imageFunction.image))
    168    {
    169        out << "    return " << imageReference << "[uint2(p.x, p.y)];\n";
    170    }
    171    else if (IsImageBuffer(imageFunction.image))
    172    {
    173        out << "    return " << imageReference << "[uint(p.x)];\n";
    174    }
    175    else
    176        UNREACHABLE();
    177 }
    178 
    179 // static
    180 void ImageFunctionHLSL::OutputImageStoreFunctionBody(
    181    TInfoSinkBase &out,
    182    const ImageFunctionHLSL::ImageFunction &imageFunction,
    183    const ImmutableString &imageReference)
    184 {
    185    if (IsImage3D(imageFunction.image) || IsImage2DArray(imageFunction.image) ||
    186        IsImage2D(imageFunction.image) || IsImageCube(imageFunction.image) ||
    187        IsImageBuffer(imageFunction.image))
    188    {
    189        out << "    " << imageReference << "[p] = data;\n";
    190    }
    191    else
    192        UNREACHABLE();
    193 }
    194 
    195 ImmutableString ImageFunctionHLSL::ImageFunction::name() const
    196 {
    197    static const ImmutableString kGlImageName("gl_image");
    198 
    199    ImmutableString suffix(nullptr);
    200    if (readonly)
    201    {
    202        suffix = ImmutableString(TextureTypeSuffix(image, imageInternalFormat));
    203    }
    204    else
    205    {
    206        suffix = ImmutableString(RWTextureTypeSuffix(image, imageInternalFormat));
    207    }
    208 
    209    ImmutableStringBuilder name(kGlImageName.length() + suffix.length() + 5u);
    210 
    211    name << kGlImageName << suffix;
    212 
    213    switch (method)
    214    {
    215        case Method::SIZE:
    216            name << "Size";
    217            break;
    218        case Method::LOAD:
    219            name << "Load";
    220            break;
    221        case Method::STORE:
    222            name << "Store";
    223            break;
    224        default:
    225            UNREACHABLE();
    226    }
    227 
    228    return name;
    229 }
    230 
    231 ImageFunctionHLSL::ImageFunction::DataType ImageFunctionHLSL::ImageFunction::getDataType(
    232    TLayoutImageInternalFormat format) const
    233 {
    234    switch (format)
    235    {
    236        case EiifRGBA32F:
    237        case EiifRGBA16F:
    238        case EiifR32F:
    239            return ImageFunction::DataType::FLOAT4;
    240        case EiifRGBA32UI:
    241        case EiifRGBA16UI:
    242        case EiifRGBA8UI:
    243        case EiifR32UI:
    244            return ImageFunction::DataType::UINT4;
    245        case EiifRGBA32I:
    246        case EiifRGBA16I:
    247        case EiifRGBA8I:
    248        case EiifR32I:
    249            return ImageFunction::DataType::INT4;
    250        case EiifRGBA8:
    251            return ImageFunction::DataType::UNORM_FLOAT4;
    252        case EiifRGBA8_SNORM:
    253            return ImageFunction::DataType::SNORM_FLOAT4;
    254        default:
    255            UNREACHABLE();
    256    }
    257 
    258    return ImageFunction::DataType::NONE;
    259 }
    260 
    261 const char *ImageFunctionHLSL::ImageFunction::getReturnType() const
    262 {
    263    if (method == ImageFunction::Method::SIZE)
    264    {
    265        switch (image)
    266        {
    267            case EbtImage2D:
    268            case EbtIImage2D:
    269            case EbtUImage2D:
    270            case EbtImageCube:
    271            case EbtIImageCube:
    272            case EbtUImageCube:
    273                return "int2";
    274            case EbtImage3D:
    275            case EbtIImage3D:
    276            case EbtUImage3D:
    277            case EbtImage2DArray:
    278            case EbtIImage2DArray:
    279            case EbtUImage2DArray:
    280                return "int3";
    281            case EbtImageBuffer:
    282            case EbtIImageBuffer:
    283            case EbtUImageBuffer:
    284                return "int";
    285            default:
    286                UNREACHABLE();
    287        }
    288    }
    289    else if (method == ImageFunction::Method::LOAD)
    290    {
    291        switch (image)
    292        {
    293            case EbtImageBuffer:
    294            case EbtImage2D:
    295            case EbtImage3D:
    296            case EbtImageCube:
    297            case EbtImage2DArray:
    298                return "float4";
    299            case EbtIImageBuffer:
    300            case EbtIImage2D:
    301            case EbtIImage3D:
    302            case EbtIImageCube:
    303            case EbtIImage2DArray:
    304                return "int4";
    305            case EbtUImageBuffer:
    306            case EbtUImage2D:
    307            case EbtUImage3D:
    308            case EbtUImageCube:
    309            case EbtUImage2DArray:
    310                return "uint4";
    311            default:
    312                UNREACHABLE();
    313        }
    314    }
    315    else if (method == ImageFunction::Method::STORE)
    316    {
    317        return "void";
    318    }
    319    else
    320    {
    321        UNREACHABLE();
    322    }
    323    return "";
    324 }
    325 
    326 bool ImageFunctionHLSL::ImageFunction::operator<(const ImageFunction &rhs) const
    327 {
    328    return std::tie(image, type, method, readonly) <
    329           std::tie(rhs.image, rhs.type, rhs.method, rhs.readonly);
    330 }
    331 
    332 ImmutableString ImageFunctionHLSL::useImageFunction(const ImmutableString &name,
    333                                                    const TBasicType &type,
    334                                                    TLayoutImageInternalFormat imageInternalFormat,
    335                                                    bool readonly)
    336 {
    337    ASSERT(IsImage(type));
    338    ImageFunction imageFunction;
    339    imageFunction.image               = type;
    340    imageFunction.imageInternalFormat = imageInternalFormat;
    341    imageFunction.readonly            = readonly;
    342    imageFunction.type                = imageFunction.getDataType(imageInternalFormat);
    343 
    344    if (name == "imageSize")
    345    {
    346        imageFunction.method = ImageFunction::Method::SIZE;
    347    }
    348    else if (name == "imageLoad")
    349    {
    350        imageFunction.method = ImageFunction::Method::LOAD;
    351    }
    352    else if (name == "imageStore")
    353    {
    354        imageFunction.method = ImageFunction::Method::STORE;
    355    }
    356    else
    357        UNREACHABLE();
    358 
    359    mUsesImage.insert(imageFunction);
    360    return imageFunction.name();
    361 }
    362 
    363 void ImageFunctionHLSL::imageFunctionHeader(TInfoSinkBase &out)
    364 {
    365    for (const ImageFunction &imageFunction : mUsesImage)
    366    {
    367        // Skip to generate image2D functions here, dynamically generate these
    368        // functions when linking, or after dispatch or draw.
    369        if (IsImage2D(imageFunction.image))
    370        {
    371            mUsedImage2DFunctionNames.insert(imageFunction.name().data());
    372            continue;
    373        }
    374        // Function header
    375        out << imageFunction.getReturnType() << " " << imageFunction.name() << "(";
    376 
    377        OutputImageFunctionArgumentList(out, imageFunction);
    378 
    379        out << ")\n"
    380               "{\n";
    381 
    382        ImmutableString imageReference = GetImageReference(out, imageFunction);
    383        if (imageFunction.method == ImageFunction::Method::SIZE)
    384        {
    385            OutputImageSizeFunctionBody(out, imageFunction, imageReference);
    386        }
    387        else if (imageFunction.method == ImageFunction::Method::LOAD)
    388        {
    389            OutputImageLoadFunctionBody(out, imageFunction, imageReference);
    390        }
    391        else
    392        {
    393            OutputImageStoreFunctionBody(out, imageFunction, imageReference);
    394        }
    395 
    396        out << "}\n"
    397               "\n";
    398    }
    399 }
    400 
    401 }  // namespace sh