diff options
Diffstat (limited to 'gfx/angle/checkout/src/compiler/translator/ImageFunctionHLSL.cpp')
-rw-r--r-- | gfx/angle/checkout/src/compiler/translator/ImageFunctionHLSL.cpp | 371 |
1 files changed, 371 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/compiler/translator/ImageFunctionHLSL.cpp b/gfx/angle/checkout/src/compiler/translator/ImageFunctionHLSL.cpp new file mode 100644 index 0000000000..d60cce09e5 --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/ImageFunctionHLSL.cpp @@ -0,0 +1,371 @@ +// +// 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) + { + // 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 |