Edit

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

Branch :

  • Show log

    Commit

  • Author : Stuart Morgan
    Date : 2019-08-14 12:25:12
    Hash : 9d737966
    Message : Standardize copyright notices to project style For all "ANGLE Project" copyrights, standardize to the format specified by the style guide. Changes: - "Copyright (c)" and "Copyright(c)" changed to just "Copyright". - Removed the second half of date ranges ("Y1Y1-Y2Y2"->"Y1Y1"). - Fixed a small number of files that had no copyright date using the initial commit year from the version control history. - Fixed one instance of copyright being "The ANGLE Project" rather than "The ANGLE Project Authors" These changes are applied both to the copyright of source file, and where applicable to copyright statements that are generated by templates. BUG=angleproject:3811 Change-Id: I973dd65e4ef9deeba232d5be74c768256a0eb2e5 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1754397 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: Jamie Madill <jmadill@chromium.org>

  • src/compiler/translator/ImageFunctionHLSL.cpp
  • //
    // Copyright 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)
        {
            // Skip to generate image2D functions here, dynamically generate these
            // functions when linking, or after dispatch or draw.
            if (IsImage2D(imageFunction.image))
            {
                mUsedImage2DFunctionNames.insert(imageFunction.name().data());
                continue;
            }
            // 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