Path: blob/main_old/src/compiler/translator/ImageFunctionHLSL.cpp
1693 views
//1// Copyright 2017 The ANGLE Project Authors. All rights reserved.2// Use of this source code is governed by a BSD-style license that can be3// found in the LICENSE file.4//5// ImageFunctionHLSL: Class for writing implementations of ESSL image functions into HLSL output.6//78#include "compiler/translator/ImageFunctionHLSL.h"9#include "compiler/translator/ImmutableStringBuilder.h"10#include "compiler/translator/UtilsHLSL.h"1112namespace sh13{1415// static16ImmutableString ImageFunctionHLSL::GetImageReference(17TInfoSinkBase &out,18const ImageFunctionHLSL::ImageFunction &imageFunction)19{20static const ImmutableString kImageIndexStr("[index]");21if (imageFunction.readonly)22{23static const ImmutableString kReadonlyImagesStr("readonlyImages");24ImmutableString suffix(25TextureGroupSuffix(imageFunction.image, imageFunction.imageInternalFormat));26out << " const uint index = imageIndex - readonlyImageIndexOffset" << suffix.data()27<< ";\n";28ImmutableStringBuilder imageRefBuilder(kReadonlyImagesStr.length() + suffix.length() +29kImageIndexStr.length());30imageRefBuilder << kReadonlyImagesStr << suffix << kImageIndexStr;31return imageRefBuilder;32}33else34{35static const ImmutableString kImagesStr("images");36ImmutableString suffix(37RWTextureGroupSuffix(imageFunction.image, imageFunction.imageInternalFormat));38out << " const uint index = imageIndex - imageIndexOffset" << suffix.data() << ";\n";39ImmutableStringBuilder imageRefBuilder(kImagesStr.length() + suffix.length() +40kImageIndexStr.length());41imageRefBuilder << kImagesStr << suffix << kImageIndexStr;42return imageRefBuilder;43}44}4546void ImageFunctionHLSL::OutputImageFunctionArgumentList(47TInfoSinkBase &out,48const ImageFunctionHLSL::ImageFunction &imageFunction)49{50out << "uint imageIndex";5152if (imageFunction.method == ImageFunctionHLSL::ImageFunction::Method::LOAD ||53imageFunction.method == ImageFunctionHLSL::ImageFunction::Method::STORE)54{55switch (imageFunction.image)56{57case EbtImage2D:58case EbtIImage2D:59case EbtUImage2D:60out << ", int2 p";61break;62case EbtImage3D:63case EbtIImage3D:64case EbtUImage3D:65case EbtImageCube:66case EbtIImageCube:67case EbtUImageCube:68case EbtImage2DArray:69case EbtIImage2DArray:70case EbtUImage2DArray:71out << ", int3 p";72break;73default:74UNREACHABLE();75}7677if (imageFunction.method == ImageFunctionHLSL::ImageFunction::Method::STORE)78{79switch (imageFunction.image)80{81case EbtImage2D:82case EbtImage3D:83case EbtImageCube:84case EbtImage2DArray:85out << ", float4 data";86break;87case EbtIImage2D:88case EbtIImage3D:89case EbtIImageCube:90case EbtIImage2DArray:91out << ", int4 data";92break;93case EbtUImage2D:94case EbtUImage3D:95case EbtUImageCube:96case EbtUImage2DArray:97out << ", uint4 data";98break;99default:100UNREACHABLE();101}102}103}104}105106// static107void ImageFunctionHLSL::OutputImageSizeFunctionBody(108TInfoSinkBase &out,109const ImageFunctionHLSL::ImageFunction &imageFunction,110const ImmutableString &imageReference)111{112if (IsImage3D(imageFunction.image) || IsImage2DArray(imageFunction.image) ||113IsImageCube(imageFunction.image))114{115// "depth" stores either the number of layers in an array texture or 3D depth116out << " uint width; uint height; uint depth;\n"117<< " " << imageReference << ".GetDimensions(width, height, depth);\n";118}119else if (IsImage2D(imageFunction.image))120{121out << " uint width; uint height;\n"122<< " " << imageReference << ".GetDimensions(width, height);\n";123}124else125UNREACHABLE();126127if (strcmp(imageFunction.getReturnType(), "int3") == 0)128{129out << " return int3(width, height, depth);\n";130}131else132{133out << " return int2(width, height);\n";134}135}136137// static138void ImageFunctionHLSL::OutputImageLoadFunctionBody(139TInfoSinkBase &out,140const ImageFunctionHLSL::ImageFunction &imageFunction,141const ImmutableString &imageReference)142{143if (IsImage3D(imageFunction.image) || IsImage2DArray(imageFunction.image) ||144IsImageCube(imageFunction.image))145{146out << " return " << imageReference << "[uint3(p.x, p.y, p.z)];\n";147}148else if (IsImage2D(imageFunction.image))149{150out << " return " << imageReference << "[uint2(p.x, p.y)];\n";151}152else153UNREACHABLE();154}155156// static157void ImageFunctionHLSL::OutputImageStoreFunctionBody(158TInfoSinkBase &out,159const ImageFunctionHLSL::ImageFunction &imageFunction,160const ImmutableString &imageReference)161{162if (IsImage3D(imageFunction.image) || IsImage2DArray(imageFunction.image) ||163IsImage2D(imageFunction.image) || IsImageCube(imageFunction.image))164{165out << " " << imageReference << "[p] = data;\n";166}167else168UNREACHABLE();169}170171ImmutableString ImageFunctionHLSL::ImageFunction::name() const172{173static const ImmutableString kGlImageName("gl_image");174175ImmutableString suffix(nullptr);176if (readonly)177{178suffix = ImmutableString(TextureTypeSuffix(image, imageInternalFormat));179}180else181{182suffix = ImmutableString(RWTextureTypeSuffix(image, imageInternalFormat));183}184185ImmutableStringBuilder name(kGlImageName.length() + suffix.length() + 5u);186187name << kGlImageName << suffix;188189switch (method)190{191case Method::SIZE:192name << "Size";193break;194case Method::LOAD:195name << "Load";196break;197case Method::STORE:198name << "Store";199break;200default:201UNREACHABLE();202}203204return name;205}206207ImageFunctionHLSL::ImageFunction::DataType ImageFunctionHLSL::ImageFunction::getDataType(208TLayoutImageInternalFormat format) const209{210switch (format)211{212case EiifRGBA32F:213case EiifRGBA16F:214case EiifR32F:215return ImageFunction::DataType::FLOAT4;216case EiifRGBA32UI:217case EiifRGBA16UI:218case EiifRGBA8UI:219case EiifR32UI:220return ImageFunction::DataType::UINT4;221case EiifRGBA32I:222case EiifRGBA16I:223case EiifRGBA8I:224case EiifR32I:225return ImageFunction::DataType::INT4;226case EiifRGBA8:227return ImageFunction::DataType::UNORM_FLOAT4;228case EiifRGBA8_SNORM:229return ImageFunction::DataType::SNORM_FLOAT4;230default:231UNREACHABLE();232}233234return ImageFunction::DataType::NONE;235}236237const char *ImageFunctionHLSL::ImageFunction::getReturnType() const238{239if (method == ImageFunction::Method::SIZE)240{241switch (image)242{243case EbtImage2D:244case EbtIImage2D:245case EbtUImage2D:246case EbtImageCube:247case EbtIImageCube:248case EbtUImageCube:249return "int2";250case EbtImage3D:251case EbtIImage3D:252case EbtUImage3D:253case EbtImage2DArray:254case EbtIImage2DArray:255case EbtUImage2DArray:256return "int3";257default:258UNREACHABLE();259}260}261else if (method == ImageFunction::Method::LOAD)262{263switch (image)264{265case EbtImage2D:266case EbtImage3D:267case EbtImageCube:268case EbtImage2DArray:269return "float4";270case EbtIImage2D:271case EbtIImage3D:272case EbtIImageCube:273case EbtIImage2DArray:274return "int4";275case EbtUImage2D:276case EbtUImage3D:277case EbtUImageCube:278case EbtUImage2DArray:279return "uint4";280default:281UNREACHABLE();282}283}284else if (method == ImageFunction::Method::STORE)285{286return "void";287}288else289{290UNREACHABLE();291}292return "";293}294295bool ImageFunctionHLSL::ImageFunction::operator<(const ImageFunction &rhs) const296{297return std::tie(image, type, method, readonly) <298std::tie(rhs.image, rhs.type, rhs.method, rhs.readonly);299}300301ImmutableString ImageFunctionHLSL::useImageFunction(const ImmutableString &name,302const TBasicType &type,303TLayoutImageInternalFormat imageInternalFormat,304bool readonly)305{306ASSERT(IsImage(type));307ImageFunction imageFunction;308imageFunction.image = type;309imageFunction.imageInternalFormat = imageInternalFormat;310imageFunction.readonly = readonly;311imageFunction.type = imageFunction.getDataType(imageInternalFormat);312313if (name == "imageSize")314{315imageFunction.method = ImageFunction::Method::SIZE;316}317else if (name == "imageLoad")318{319imageFunction.method = ImageFunction::Method::LOAD;320}321else if (name == "imageStore")322{323imageFunction.method = ImageFunction::Method::STORE;324}325else326UNREACHABLE();327328mUsesImage.insert(imageFunction);329return imageFunction.name();330}331332void ImageFunctionHLSL::imageFunctionHeader(TInfoSinkBase &out)333{334for (const ImageFunction &imageFunction : mUsesImage)335{336// Skip to generate image2D functions here, dynamically generate these337// functions when linking, or after dispatch or draw.338if (IsImage2D(imageFunction.image))339{340mUsedImage2DFunctionNames.insert(imageFunction.name().data());341continue;342}343// Function header344out << imageFunction.getReturnType() << " " << imageFunction.name() << "(";345346OutputImageFunctionArgumentList(out, imageFunction);347348out << ")\n"349"{\n";350351ImmutableString imageReference = GetImageReference(out, imageFunction);352if (imageFunction.method == ImageFunction::Method::SIZE)353{354OutputImageSizeFunctionBody(out, imageFunction, imageReference);355}356else if (imageFunction.method == ImageFunction::Method::LOAD)357{358OutputImageLoadFunctionBody(out, imageFunction, imageReference);359}360else361{362OutputImageStoreFunctionBody(out, imageFunction, imageReference);363}364365out << "}\n"366"\n";367}368}369370} // namespace sh371372373