Edit

kc3-lang/angle/src/compiler/translator/ImageFunctionHLSL.cpp

Branch :

  • Show log

    Commit

  • Author : Olli Etuaho
    Date : 2018-06-21 15:27:44
    Hash : 8fbd9d96
    Message : Use ImmutableString in ImageFunctionHLSL This code is analoguous to the code in TextureFunctionHLSL and is now implemented in a similar manner. BUG=angleproject:2267 TEST=angle_unittests, angle_end2end_tests Change-Id: Ie3503766217dad4f3848f2d4b2fc3f62b3edce0c Reviewed-on: https://chromium-review.googlesource.com/1110366 Reviewed-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Corentin Wallez <cwallez@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>

  • src/compiler/translator/ImageFunctionHLSL.cpp
  • //
    // Copyright (c) 2017 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    // ImageFunctionHLSL: Class for writing implementations of ESSL image functions into HLSL output.
    //
    
    #include "compiler/translator/ImageFunctionHLSL.h"
    #include "compiler/translator/ImmutableStringBuilder.h"
    #include "compiler/translator/UtilsHLSL.h"
    
    namespace sh
    {
    
    // static
    ImmutableString ImageFunctionHLSL::GetImageReference(
        TInfoSinkBase &out,
        const ImageFunctionHLSL::ImageFunction &imageFunction)
    {
        static const ImmutableString kImageIndexStr("[index]");
        if (imageFunction.readonly)
        {
            static const ImmutableString kReadonlyImagesStr("readonlyImages");
            ImmutableString suffix(
                TextureGroupSuffix(imageFunction.image, imageFunction.imageInternalFormat));
            out << "    const uint index = imageIndex - readonlyImageIndexOffset" << suffix.data()
                << ";\n";
            ImmutableStringBuilder imageRefBuilder(kReadonlyImagesStr.length() + suffix.length() +
                                                   kImageIndexStr.length());
            imageRefBuilder << kReadonlyImagesStr << suffix << kImageIndexStr;
            return imageRefBuilder;
        }
        else
        {
            static const ImmutableString kImagesStr("images");
            ImmutableString suffix(
                RWTextureGroupSuffix(imageFunction.image, imageFunction.imageInternalFormat));
            out << "    const uint index = imageIndex - imageIndexOffset" << suffix.data() << ";\n";
            ImmutableStringBuilder imageRefBuilder(kImagesStr.length() + suffix.length() +
                                                   kImageIndexStr.length());
            imageRefBuilder << kImagesStr << suffix << kImageIndexStr;
            return imageRefBuilder;
        }
    }
    
    void ImageFunctionHLSL::OutputImageFunctionArgumentList(
        TInfoSinkBase &out,
        const ImageFunctionHLSL::ImageFunction &imageFunction)
    {
        out << "uint imageIndex";
    
        if (imageFunction.method == ImageFunctionHLSL::ImageFunction::Method::LOAD ||
            imageFunction.method == ImageFunctionHLSL::ImageFunction::Method::STORE)
        {
            switch (imageFunction.image)
            {
                case EbtImage2D:
                case EbtIImage2D:
                case EbtUImage2D:
                    out << ", int2 p";
                    break;
                case EbtImage3D:
                case EbtIImage3D:
                case EbtUImage3D:
                case EbtImageCube:
                case EbtIImageCube:
                case EbtUImageCube:
                case EbtImage2DArray:
                case EbtIImage2DArray:
                case EbtUImage2DArray:
                    out << ", int3 p";
                    break;
                default:
                    UNREACHABLE();
            }
    
            if (imageFunction.method == ImageFunctionHLSL::ImageFunction::Method::STORE)
            {
                switch (imageFunction.image)
                {
                    case EbtImage2D:
                    case EbtImage3D:
                    case EbtImageCube:
                    case EbtImage2DArray:
                        out << ", float4 data";
                        break;
                    case EbtIImage2D:
                    case EbtIImage3D:
                    case EbtIImageCube:
                    case EbtIImage2DArray:
                        out << ", int4 data";
                        break;
                    case EbtUImage2D:
                    case EbtUImage3D:
                    case EbtUImageCube:
                    case EbtUImage2DArray:
                        out << ", uint4 data";
                        break;
                    default:
                        UNREACHABLE();
                }
            }
        }
    }
    
    // static
    void ImageFunctionHLSL::OutputImageSizeFunctionBody(
        TInfoSinkBase &out,
        const ImageFunctionHLSL::ImageFunction &imageFunction,
        const ImmutableString &imageReference)
    {
        if (IsImage3D(imageFunction.image) || IsImage2DArray(imageFunction.image) ||
            IsImageCube(imageFunction.image))
        {
            // "depth" stores either the number of layers in an array texture or 3D depth
            out << "    uint width; uint height; uint depth;\n"
                << "    " << imageReference << ".GetDimensions(width, height, depth);\n";
        }
        else if (IsImage2D(imageFunction.image))
        {
            out << "    uint width; uint height;\n"
                << "    " << imageReference << ".GetDimensions(width, height);\n";
        }
        else
            UNREACHABLE();
    
        if (strcmp(imageFunction.getReturnType(), "int3") == 0)
        {
            out << "    return int3(width, height, depth);\n";
        }
        else
        {
            out << "    return int2(width, height);\n";
        }
    }
    
    // static
    void ImageFunctionHLSL::OutputImageLoadFunctionBody(
        TInfoSinkBase &out,
        const ImageFunctionHLSL::ImageFunction &imageFunction,
        const ImmutableString &imageReference)
    {
        if (IsImage3D(imageFunction.image) || IsImage2DArray(imageFunction.image) ||
            IsImageCube(imageFunction.image))
        {
            out << "    return " << imageReference << "[uint3(p.x, p.y, p.z)];\n";
        }
        else if (IsImage2D(imageFunction.image))
        {
            out << "    return " << imageReference << "[uint2(p.x, p.y)];\n";
        }
        else
            UNREACHABLE();
    }
    
    // static
    void ImageFunctionHLSL::OutputImageStoreFunctionBody(
        TInfoSinkBase &out,
        const ImageFunctionHLSL::ImageFunction &imageFunction,
        const ImmutableString &imageReference)
    {
        if (IsImage3D(imageFunction.image) || IsImage2DArray(imageFunction.image) ||
            IsImage2D(imageFunction.image) || IsImageCube(imageFunction.image))
        {
            out << "    " << imageReference << "[p] = data;\n";
        }
        else
            UNREACHABLE();
    }
    
    ImmutableString ImageFunctionHLSL::ImageFunction::name() const
    {
        static const ImmutableString kGlImageName("gl_image");
    
        ImmutableString suffix(nullptr);
        if (readonly)
        {
            suffix = ImmutableString(TextureTypeSuffix(image, imageInternalFormat));
        }
        else
        {
            suffix = ImmutableString(RWTextureTypeSuffix(image, imageInternalFormat));
        }
    
        ImmutableStringBuilder name(kGlImageName.length() + suffix.length() + 5u);
    
        name << kGlImageName << suffix;
    
        switch (method)
        {
            case Method::SIZE:
                name << "Size";
                break;
            case Method::LOAD:
                name << "Load";
                break;
            case Method::STORE:
                name << "Store";
                break;
            default:
                UNREACHABLE();
        }
    
        return name;
    }
    
    ImageFunctionHLSL::ImageFunction::DataType ImageFunctionHLSL::ImageFunction::getDataType(
        TLayoutImageInternalFormat format) const
    {
        switch (format)
        {
            case EiifRGBA32F:
            case EiifRGBA16F:
            case EiifR32F:
                return ImageFunction::DataType::FLOAT4;
            case EiifRGBA32UI:
            case EiifRGBA16UI:
            case EiifRGBA8UI:
            case EiifR32UI:
                return ImageFunction::DataType::UINT4;
            case EiifRGBA32I:
            case EiifRGBA16I:
            case EiifRGBA8I:
            case EiifR32I:
                return ImageFunction::DataType::INT4;
            case EiifRGBA8:
                return ImageFunction::DataType::UNORM_FLOAT4;
            case EiifRGBA8_SNORM:
                return ImageFunction::DataType::SNORM_FLOAT4;
            default:
                UNREACHABLE();
        }
    
        return ImageFunction::DataType::NONE;
    }
    
    const char *ImageFunctionHLSL::ImageFunction::getReturnType() const
    {
        if (method == ImageFunction::Method::SIZE)
        {
            switch (image)
            {
                case EbtImage2D:
                case EbtIImage2D:
                case EbtUImage2D:
                case EbtImageCube:
                case EbtIImageCube:
                case EbtUImageCube:
                    return "int2";
                case EbtImage3D:
                case EbtIImage3D:
                case EbtUImage3D:
                case EbtImage2DArray:
                case EbtIImage2DArray:
                case EbtUImage2DArray:
                    return "int3";
                default:
                    UNREACHABLE();
            }
        }
        else if (method == ImageFunction::Method::LOAD)
        {
            switch (image)
            {
                case EbtImage2D:
                case EbtImage3D:
                case EbtImageCube:
                case EbtImage2DArray:
                    return "float4";
                case EbtIImage2D:
                case EbtIImage3D:
                case EbtIImageCube:
                case EbtIImage2DArray:
                    return "int4";
                case EbtUImage2D:
                case EbtUImage3D:
                case EbtUImageCube:
                case EbtUImage2DArray:
                    return "uint4";
                default:
                    UNREACHABLE();
            }
        }
        else if (method == ImageFunction::Method::STORE)
        {
            return "void";
        }
        else
        {
            UNREACHABLE();
        }
        return "";
    }
    
    bool ImageFunctionHLSL::ImageFunction::operator<(const ImageFunction &rhs) const
    {
        return std::tie(image, type, method, readonly) <
               std::tie(rhs.image, rhs.type, rhs.method, rhs.readonly);
    }
    
    ImmutableString ImageFunctionHLSL::useImageFunction(const ImmutableString &name,
                                                        const TBasicType &type,
                                                        TLayoutImageInternalFormat imageInternalFormat,
                                                        bool readonly)
    {
        ASSERT(IsImage(type));
        ImageFunction imageFunction;
        imageFunction.image               = type;
        imageFunction.imageInternalFormat = imageInternalFormat;
        imageFunction.readonly            = readonly;
        imageFunction.type                = imageFunction.getDataType(imageInternalFormat);
    
        if (name == "imageSize")
        {
            imageFunction.method = ImageFunction::Method::SIZE;
        }
        else if (name == "imageLoad")
        {
            imageFunction.method = ImageFunction::Method::LOAD;
        }
        else if (name == "imageStore")
        {
            imageFunction.method = ImageFunction::Method::STORE;
        }
        else
            UNREACHABLE();
    
        mUsesImage.insert(imageFunction);
        return imageFunction.name();
    }
    
    void ImageFunctionHLSL::imageFunctionHeader(TInfoSinkBase &out)
    {
        for (const ImageFunction &imageFunction : mUsesImage)
        {
            // Function header
            out << imageFunction.getReturnType() << " " << imageFunction.name() << "(";
    
            OutputImageFunctionArgumentList(out, imageFunction);
    
            out << ")\n"
                   "{\n";
    
            ImmutableString imageReference = GetImageReference(out, imageFunction);
            if (imageFunction.method == ImageFunction::Method::SIZE)
            {
                OutputImageSizeFunctionBody(out, imageFunction, imageReference);
            }
            else if (imageFunction.method == ImageFunction::Method::LOAD)
            {
                OutputImageLoadFunctionBody(out, imageFunction, imageReference);
            }
            else
            {
                OutputImageStoreFunctionBody(out, imageFunction, imageReference);
            }
    
            out << "}\n"
                   "\n";
        }
    }
    
    }  // namespace sh