summaryrefslogtreecommitdiffstats
path: root/gfx/angle/checkout/src/libANGLE/renderer/d3d/DynamicImage2DHLSL.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/checkout/src/libANGLE/renderer/d3d/DynamicImage2DHLSL.cpp')
-rw-r--r--gfx/angle/checkout/src/libANGLE/renderer/d3d/DynamicImage2DHLSL.cpp920
1 files changed, 920 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/libANGLE/renderer/d3d/DynamicImage2DHLSL.cpp b/gfx/angle/checkout/src/libANGLE/renderer/d3d/DynamicImage2DHLSL.cpp
new file mode 100644
index 0000000000..7027549325
--- /dev/null
+++ b/gfx/angle/checkout/src/libANGLE/renderer/d3d/DynamicImage2DHLSL.cpp
@@ -0,0 +1,920 @@
+//
+// Copyright 2019 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.
+//
+// DynamicImage2DHLSL.cpp: Implementation for link and run-time HLSL generation
+//
+
+#include "libANGLE/renderer/d3d/DynamicImage2DHLSL.h"
+
+#include "common/string_utils.h"
+#include "libANGLE/renderer/d3d/ProgramD3D.h"
+#include "libANGLE/renderer/d3d/ShaderD3D.h"
+
+using namespace gl;
+
+namespace rx
+{
+
+namespace
+{
+
+enum Image2DHLSLGroup
+{
+ IMAGE2D_R_FLOAT4,
+ IMAGE2D_MIN = IMAGE2D_R_FLOAT4,
+ IMAGE2D_R_UNORM,
+ IMAGE2D_R_SNORM,
+ IMAGE2D_R_UINT4,
+ IMAGE2D_R_INT4,
+ IMAGE2D_W_FLOAT4,
+ IMAGE2D_W_UNORM,
+ IMAGE2D_W_SNORM,
+ IMAGE2D_W_UINT4,
+ IMAGE2D_W_INT4,
+ IMAGE2D_UNKNOWN,
+ IMAGE2D_MAX = IMAGE2D_UNKNOWN
+};
+
+enum Image2DMethod
+{
+ IMAGE2DSIZE,
+ IMAGE2DLOAD,
+ IMAGE2DSTORE
+};
+
+Image2DHLSLGroup image2DHLSLGroup(const sh::Uniform &uniform)
+{
+ GLenum format = uniform.imageUnitFormat;
+ bool readonly = uniform.readonly;
+ switch (uniform.type)
+ {
+ case GL_IMAGE_2D:
+ {
+ switch (format)
+ {
+ case GL_RGBA32F:
+ case GL_RGBA16F:
+ case GL_R32F:
+ return readonly ? IMAGE2D_R_FLOAT4 : IMAGE2D_W_FLOAT4;
+ case GL_RGBA8:
+ return readonly ? IMAGE2D_R_UNORM : IMAGE2D_W_UNORM;
+ case GL_RGBA8_SNORM:
+ return readonly ? IMAGE2D_R_SNORM : IMAGE2D_W_SNORM;
+ default:
+ UNREACHABLE();
+ return IMAGE2D_UNKNOWN;
+ }
+ }
+ case GL_INT_IMAGE_2D:
+ {
+ switch (format)
+ {
+ case GL_RGBA32I:
+ case GL_RGBA16I:
+ case GL_RGBA8I:
+ case GL_R32I:
+ return readonly ? IMAGE2D_R_INT4 : IMAGE2D_W_INT4;
+ default:
+ UNREACHABLE();
+ return IMAGE2D_UNKNOWN;
+ }
+ }
+ case GL_UNSIGNED_INT_IMAGE_2D:
+ {
+ switch (format)
+ {
+ case GL_RGBA32UI:
+ case GL_RGBA16UI:
+ case GL_RGBA8UI:
+ case GL_R32UI:
+ return readonly ? IMAGE2D_R_UINT4 : IMAGE2D_W_UINT4;
+ default:
+ UNREACHABLE();
+ return IMAGE2D_UNKNOWN;
+ }
+ }
+ default:
+ UNREACHABLE();
+ return IMAGE2D_UNKNOWN;
+ }
+}
+
+std::string Image2DHLSLGroupSuffix(Image2DHLSLGroup group)
+{
+ switch (group)
+ {
+ case IMAGE2D_R_FLOAT4:
+ return "2D";
+ case IMAGE2D_R_UNORM:
+ return "2D_unorm_float4_";
+ case IMAGE2D_R_SNORM:
+ return "2D_snorm_float4_";
+ case IMAGE2D_R_UINT4:
+ return "2D_uint4_";
+ case IMAGE2D_R_INT4:
+ return "2D_int4_";
+ case IMAGE2D_W_FLOAT4:
+ return "RW2D_float4_";
+ case IMAGE2D_W_UNORM:
+ return "RW2D_unorm_float4_";
+ case IMAGE2D_W_SNORM:
+ return "RW2D_snorm_float4_";
+ case IMAGE2D_W_UINT4:
+ return "RW2D_uint4_";
+ case IMAGE2D_W_INT4:
+ return "RW2D_int4_";
+ default:
+ UNREACHABLE();
+ }
+
+ return "<unknown group type>";
+}
+
+std::string Image2DHLSLTextureString(Image2DHLSLGroup group, gl::TextureType type)
+{
+ std::string textureString;
+ switch (group)
+ {
+ case IMAGE2D_R_FLOAT4:
+ case IMAGE2D_R_UNORM:
+ case IMAGE2D_R_SNORM:
+ case IMAGE2D_R_UINT4:
+ case IMAGE2D_R_INT4:
+ break;
+ case IMAGE2D_W_FLOAT4:
+ case IMAGE2D_W_UNORM:
+ case IMAGE2D_W_SNORM:
+ case IMAGE2D_W_UINT4:
+ case IMAGE2D_W_INT4:
+ textureString += "RW";
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ textureString += "Texture";
+
+ switch (type)
+ {
+ case gl::TextureType::_2D:
+ textureString += "2D";
+ break;
+ case gl::TextureType::_3D:
+ textureString += "3D";
+ break;
+ case gl::TextureType::_2DArray:
+ textureString += "2DArray";
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ switch (group)
+ {
+ case IMAGE2D_R_FLOAT4:
+ case IMAGE2D_W_FLOAT4:
+ textureString += "<float4>";
+ break;
+ case IMAGE2D_R_UNORM:
+ case IMAGE2D_W_UNORM:
+ textureString += "<unorm float4>";
+ break;
+ case IMAGE2D_R_SNORM:
+ case IMAGE2D_W_SNORM:
+ textureString += "<snorm float4>";
+ break;
+ case IMAGE2D_R_UINT4:
+ case IMAGE2D_W_UINT4:
+ textureString += "<uint4>";
+ break;
+ case IMAGE2D_R_INT4:
+ case IMAGE2D_W_INT4:
+ textureString += "<int4>";
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return textureString;
+}
+
+std::string Image2DHLSLGroupOffsetPrefix(Image2DHLSLGroup group)
+{
+ switch (group)
+ {
+ case IMAGE2D_R_FLOAT4:
+ case IMAGE2D_R_UNORM:
+ case IMAGE2D_R_SNORM:
+ case IMAGE2D_R_UINT4:
+ case IMAGE2D_R_INT4:
+ return "readonlyImageIndexOffset";
+ case IMAGE2D_W_FLOAT4:
+ case IMAGE2D_W_UNORM:
+ case IMAGE2D_W_SNORM:
+ case IMAGE2D_W_UINT4:
+ case IMAGE2D_W_INT4:
+ return "imageIndexOffset";
+ default:
+ UNREACHABLE();
+ }
+
+ return "<unknown group type>";
+}
+
+std::string Image2DHLSLGroupDeclarationPrefix(Image2DHLSLGroup group)
+{
+ switch (group)
+ {
+ case IMAGE2D_R_FLOAT4:
+ case IMAGE2D_R_UNORM:
+ case IMAGE2D_R_SNORM:
+ case IMAGE2D_R_UINT4:
+ case IMAGE2D_R_INT4:
+ return "readonlyImages";
+ case IMAGE2D_W_FLOAT4:
+ case IMAGE2D_W_UNORM:
+ case IMAGE2D_W_SNORM:
+ case IMAGE2D_W_UINT4:
+ case IMAGE2D_W_INT4:
+ return "images";
+ default:
+ UNREACHABLE();
+ }
+
+ return "<unknown group type>";
+}
+
+std::string Image2DHLSLGroupRegisterSuffix(Image2DHLSLGroup group)
+{
+ switch (group)
+ {
+ case IMAGE2D_R_FLOAT4:
+ case IMAGE2D_R_UNORM:
+ case IMAGE2D_R_SNORM:
+ case IMAGE2D_R_UINT4:
+ case IMAGE2D_R_INT4:
+ return "t";
+ case IMAGE2D_W_FLOAT4:
+ case IMAGE2D_W_UNORM:
+ case IMAGE2D_W_SNORM:
+ case IMAGE2D_W_UINT4:
+ case IMAGE2D_W_INT4:
+ return "u";
+ default:
+ UNREACHABLE();
+ }
+
+ return "<unknown group type>";
+}
+
+std::string Image2DHLSLGroupFunctionName(Image2DHLSLGroup group, Image2DMethod method)
+{
+ std::string name = "gl_image";
+ name += Image2DHLSLGroupSuffix(group);
+ switch (method)
+ {
+ case IMAGE2DSIZE:
+ name += "Size";
+ break;
+ case IMAGE2DLOAD:
+ name += "Load";
+ break;
+ case IMAGE2DSTORE:
+ name += "Store";
+ break;
+ default:
+ UNREACHABLE();
+ }
+
+ return name;
+}
+
+std::string getImage2DGroupReturnType(Image2DHLSLGroup group, Image2DMethod method)
+{
+ switch (method)
+ {
+ case IMAGE2DSIZE:
+ return "int2";
+ case IMAGE2DLOAD:
+ switch (group)
+ {
+ case IMAGE2D_R_FLOAT4:
+ case IMAGE2D_R_UNORM:
+ case IMAGE2D_R_SNORM:
+ case IMAGE2D_W_FLOAT4:
+ case IMAGE2D_W_UNORM:
+ case IMAGE2D_W_SNORM:
+ return "float4";
+ case IMAGE2D_R_UINT4:
+ case IMAGE2D_W_UINT4:
+ return "uint4";
+ case IMAGE2D_R_INT4:
+ case IMAGE2D_W_INT4:
+ return "int4";
+ default:
+ UNREACHABLE();
+ return "unknown group type";
+ }
+ case IMAGE2DSTORE:
+ return "void";
+ default:
+ UNREACHABLE();
+ return "unknown image method";
+ }
+}
+
+std::string getImageMetadata(Image2DHLSLGroup group)
+{
+ switch (group)
+ {
+ case IMAGE2D_R_FLOAT4:
+ case IMAGE2D_R_UNORM:
+ case IMAGE2D_R_SNORM:
+ case IMAGE2D_R_UINT4:
+ case IMAGE2D_R_INT4:
+ return "readonlyImageMetadata[imageIndex - readonlyImageIndexStart]";
+ case IMAGE2D_W_FLOAT4:
+ case IMAGE2D_W_UNORM:
+ case IMAGE2D_W_SNORM:
+ case IMAGE2D_W_UINT4:
+ case IMAGE2D_W_INT4:
+ return "imageMetadata[imageIndex - imageIndexStart]";
+ default:
+ UNREACHABLE();
+ return "unknown image method";
+ }
+}
+
+void OutputImage2DFunctionArgumentList(std::ostringstream &out,
+ Image2DHLSLGroup group,
+ Image2DMethod method)
+{
+ out << "uint imageIndex";
+
+ if (method == IMAGE2DLOAD || method == IMAGE2DSTORE)
+ {
+ out << ", int2 p";
+ if (method == IMAGE2DSTORE)
+ {
+ switch (group)
+ {
+ case IMAGE2D_R_FLOAT4:
+ case IMAGE2D_R_UNORM:
+ case IMAGE2D_R_SNORM:
+ case IMAGE2D_W_FLOAT4:
+ case IMAGE2D_W_UNORM:
+ case IMAGE2D_W_SNORM:
+ out << ", float4 data";
+ break;
+ case IMAGE2D_R_UINT4:
+ case IMAGE2D_W_UINT4:
+ out << ", uint4 data";
+ break;
+ case IMAGE2D_R_INT4:
+ case IMAGE2D_W_INT4:
+ out << ", int4 data";
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+ }
+}
+
+void OutputImage2DSizeFunction(std::ostringstream &out,
+ Image2DHLSLGroup textureGroup,
+ unsigned int totalCount,
+ unsigned int texture2DCount,
+ unsigned int texture3DCount,
+ unsigned int texture2DArrayCount,
+ const std::string &offsetStr,
+ const std::string &declarationStr,
+ bool getDimensionsIgnoresBaseLevel)
+{
+ out << getImage2DGroupReturnType(textureGroup, IMAGE2DSIZE) << " "
+ << Image2DHLSLGroupFunctionName(textureGroup, IMAGE2DSIZE) << "(";
+ OutputImage2DFunctionArgumentList(out, textureGroup, IMAGE2DSIZE);
+ out << ")\n"
+ "{\n";
+ out << " uint width, height;\n";
+
+ if (texture2DCount > 0)
+ {
+ if (texture2DCount == totalCount)
+ {
+ out << " const uint index = imageIndex - " << offsetStr << "2D;\n";
+ if (getDimensionsIgnoresBaseLevel)
+ {
+ out << " uint levelCount;\n";
+ out << " const uint level = " << getImageMetadata(textureGroup) << ".level;\n";
+ out << " " << declarationStr
+ << "2D[index].GetDimensions(level, width, height, levelCount);\n";
+ }
+ else
+ {
+ out << " " << declarationStr << "2D[index].GetDimensions(width, height);\n";
+ }
+ }
+ else
+ {
+ out << " if (imageIndex >= " << offsetStr << "2D && imageIndex < " << offsetStr
+ << "2D + " << texture2DCount << ")\n";
+ out << " {\n";
+ out << " const uint index = imageIndex - " << offsetStr << "2D;\n";
+ out << " " << declarationStr << "2D[index].GetDimensions(width, height);\n";
+ out << " }\n";
+ }
+ }
+
+ if (texture3DCount > 0)
+ {
+ if (texture3DCount == totalCount)
+ {
+ out << " const uint index = imageIndex - " << offsetStr << "3D;\n";
+ out << " uint depth;\n";
+ out << " " << declarationStr << "3D[index].GetDimensions(width, height, depth);\n";
+ }
+ else
+ {
+ if (texture2DArrayCount == 0)
+ {
+ out << " else\n";
+ }
+ else
+ {
+ if (texture2DCount == 0)
+ {
+ out << " if ";
+ }
+ else
+ {
+ out << " else if";
+ }
+ out << "(imageIndex >= " << offsetStr << "3D && imageIndex < " << offsetStr
+ << "3D + " << texture3DCount << ")\n";
+ }
+ out << " {\n";
+ out << " const uint index = imageIndex - " << offsetStr << "3D;\n";
+ out << " uint depth;\n";
+ out << " " << declarationStr
+ << "3D[index].GetDimensions(width, height, depth);\n";
+ out << " }\n";
+ }
+ }
+
+ if (texture2DArrayCount > 0)
+ {
+ if (texture2DArrayCount == totalCount)
+ {
+ out << " const uint index = imageIndex - " << offsetStr << "2DArray;\n";
+ out << " uint depth;\n";
+ out << " " << declarationStr
+ << "2DArray[index].GetDimensions(width, height, depth);\n";
+ }
+ else
+ {
+ out << " else\n";
+ out << " {\n";
+ out << " const uint index = imageIndex - " << offsetStr << "2DArray;\n";
+ out << " uint depth;\n";
+ out << " " << declarationStr
+ << "2DArray[index].GetDimensions(width, height, depth);\n";
+ out << " }\n";
+ }
+ }
+ out << " return int2(width, height);\n";
+
+ out << "}\n";
+}
+
+void OutputImage2DLoadFunction(std::ostringstream &out,
+ Image2DHLSLGroup textureGroup,
+ unsigned int totalCount,
+ unsigned int texture2DCount,
+ unsigned int texture3DCount,
+ unsigned int texture2DArrayCount,
+ const std::string &offsetStr,
+ const std::string &declarationStr)
+{
+ out << getImage2DGroupReturnType(textureGroup, IMAGE2DLOAD) << " "
+ << Image2DHLSLGroupFunctionName(textureGroup, IMAGE2DLOAD) << "(";
+ OutputImage2DFunctionArgumentList(out, textureGroup, IMAGE2DLOAD);
+ out << ")\n"
+ "{\n";
+
+ out << " " << getImage2DGroupReturnType(textureGroup, IMAGE2DLOAD) << " result;\n";
+
+ if (texture2DCount > 0)
+ {
+ if (texture2DCount == totalCount)
+ {
+ out << " const uint index = imageIndex - " << offsetStr << "2D;\n";
+ out << " result = " << declarationStr << "2D[index][uint2(p.x, p.y)];\n";
+ }
+ else
+ {
+ out << " if (imageIndex >= " << offsetStr << "2D && imageIndex < " << offsetStr
+ << "2D + " << texture2DCount << ")\n";
+ out << " {\n";
+ out << " const uint index = imageIndex - " << offsetStr << "2D;\n";
+ out << " result = " << declarationStr << "2D[index][uint2(p.x, p.y)];\n";
+ out << " }\n";
+ }
+ }
+
+ if (texture3DCount > 0)
+ {
+ if (texture3DCount == totalCount)
+ {
+ out << " const uint index = imageIndex - " << offsetStr << "3D;\n";
+ out << " result = " << declarationStr << "3D[index][uint3(p.x, p.y, "
+ << getImageMetadata(textureGroup) << ".layer)];\n";
+ }
+ else
+ {
+ if (texture2DArrayCount == 0)
+ {
+ out << " else\n";
+ }
+ else
+ {
+ if (texture2DCount == 0)
+ {
+ out << " if ";
+ }
+ else
+ {
+ out << " else if";
+ }
+ out << "(imageIndex >= " << offsetStr << "3D && imageIndex < " << offsetStr
+ << "3D + " << texture3DCount << ")\n";
+ }
+ out << " {\n";
+ out << " const uint index = imageIndex - " << offsetStr << "3D;\n";
+ out << " result = " << declarationStr << "3D[index][uint3(p.x, p.y, "
+ << getImageMetadata(textureGroup) << ".layer)];\n";
+ out << " }\n";
+ }
+ }
+
+ if (texture2DArrayCount > 0)
+ {
+ if (texture2DArrayCount == totalCount)
+ {
+ out << " const uint index = imageIndex - " << offsetStr << "2DArray;\n";
+ out << " result = " << declarationStr << "2DArray[index][uint3(p.x, p.y, "
+ << getImageMetadata(textureGroup) << ".layer)];\n";
+ }
+ else
+ {
+ out << " else\n";
+ out << " {\n";
+ out << " const uint index = imageIndex - " << offsetStr << "2DArray;\n";
+ out << " result = " << declarationStr << "2DArray[index][uint3(p.x, p.y, "
+ << getImageMetadata(textureGroup) << ".layer)];\n";
+ out << " }\n";
+ }
+ }
+
+ out << " return result;\n";
+ out << "}\n";
+}
+
+void OutputImage2DStoreFunction(std::ostringstream &out,
+ Image2DHLSLGroup textureGroup,
+ unsigned int totalCount,
+ unsigned int texture2DCount,
+ unsigned int texture3DCount,
+ unsigned int texture2DArrayCount,
+ const std::string &offsetStr,
+ const std::string &declarationStr)
+{
+ out << getImage2DGroupReturnType(textureGroup, IMAGE2DSTORE) << " "
+ << Image2DHLSLGroupFunctionName(textureGroup, IMAGE2DSTORE) << "(";
+ OutputImage2DFunctionArgumentList(out, textureGroup, IMAGE2DSTORE);
+ out << ")\n"
+ "{\n";
+
+ if (texture2DCount > 0)
+ {
+ if (texture2DCount == totalCount)
+ {
+ out << " const uint index = imageIndex - " << offsetStr << "2D;\n";
+ out << " " << declarationStr << "2D[index][uint2(p.x, p.y)] = data;\n";
+ }
+ else
+ {
+ out << " if (imageIndex >= " << offsetStr << "2D && imageIndex < " << offsetStr
+ << "2D + " << texture2DCount << ")\n";
+ out << " {\n";
+ out << " const uint index = imageIndex - " << offsetStr << "2D;\n";
+ out << " " << declarationStr << "2D[index][uint2(p.x, p.y)] = data;\n";
+ out << " }\n";
+ }
+ }
+
+ if (texture3DCount > 0)
+ {
+ if (texture3DCount == totalCount)
+ {
+ out << " const uint index = imageIndex - " << offsetStr << "3D;\n";
+ out << " " << declarationStr << "3D[index][uint3(p.x, p.y, "
+ << getImageMetadata(textureGroup) << ".layer)] = data;\n";
+ }
+ else
+ {
+ if (texture2DArrayCount == 0)
+ {
+ out << " else\n";
+ }
+ else
+ {
+ if (texture2DCount == 0)
+ {
+ out << " if ";
+ }
+ else
+ {
+ out << " else if";
+ }
+ out << "(imageIndex >= " << offsetStr << "3D && imageIndex < " << offsetStr
+ << "3D + " << texture3DCount << ")\n";
+ }
+ out << " {\n";
+ out << " const uint index = imageIndex - " << offsetStr << "3D;\n";
+ out << " " << declarationStr << "3D[index][uint3(p.x, p.y, "
+ << getImageMetadata(textureGroup) << ".layer)] = data;\n";
+ out << " }\n";
+ }
+ }
+
+ if (texture2DArrayCount > 0)
+ {
+ if (texture2DArrayCount == totalCount)
+ {
+ out << " const uint index = imageIndex - " << offsetStr << "2DArray;\n";
+ out << " " << declarationStr << "2DArray[index][uint3(p.x, p.y, "
+ << getImageMetadata(textureGroup) << ".layer)] = data;\n";
+ }
+ else
+ {
+ out << " else\n";
+ out << " {\n";
+ out << " const uint index = imageIndex - " << offsetStr << "2DArray;\n";
+ out << " " << declarationStr << "2DArray[index][uint3(p.x, p.y, "
+ << getImageMetadata(textureGroup) << ".layer)] = data;\n";
+ out << " }\n";
+ }
+ }
+
+ out << "}\n";
+}
+
+unsigned int *GetImage2DRegisterIndex(Image2DHLSLGroup textureGroup,
+ unsigned int *groupTextureRegisterIndex,
+ unsigned int *groupRWTextureRegisterIndex)
+{
+ switch (textureGroup)
+ {
+ case IMAGE2D_R_FLOAT4:
+ case IMAGE2D_R_UNORM:
+ case IMAGE2D_R_SNORM:
+ case IMAGE2D_R_UINT4:
+ case IMAGE2D_R_INT4:
+ return groupTextureRegisterIndex;
+ case IMAGE2D_W_FLOAT4:
+ case IMAGE2D_W_UNORM:
+ case IMAGE2D_W_SNORM:
+ case IMAGE2D_W_UINT4:
+ case IMAGE2D_W_INT4:
+ return groupRWTextureRegisterIndex;
+ default:
+ UNREACHABLE();
+ return nullptr;
+ }
+}
+
+void OutputHLSLImage2DUniformGroup(ProgramD3D &programD3D,
+ const gl::ProgramState &programData,
+ gl::ShaderType shaderType,
+ std::ostringstream &out,
+ const Image2DHLSLGroup textureGroup,
+ const std::vector<sh::Uniform> &group,
+ const gl::ImageUnitTextureTypeMap &image2DBindLayout,
+ unsigned int *groupTextureRegisterIndex,
+ unsigned int *groupRWTextureRegisterIndex,
+ unsigned int *image2DTexture3D,
+ unsigned int *image2DTexture2DArray,
+ unsigned int *image2DTexture2D)
+{
+ if (group.empty())
+ {
+ return;
+ }
+
+ unsigned int texture2DCount = 0, texture3DCount = 0, texture2DArrayCount = 0;
+ for (const sh::Uniform &uniform : group)
+ {
+ if (!programD3D.hasNamedUniform(uniform.name))
+ {
+ continue;
+ }
+ for (unsigned int index = 0; index < uniform.getArraySizeProduct(); index++)
+ {
+ switch (image2DBindLayout.at(uniform.binding + index))
+ {
+ case gl::TextureType::_2D:
+ texture2DCount++;
+ break;
+ case gl::TextureType::_3D:
+ texture3DCount++;
+ break;
+ case gl::TextureType::_2DArray:
+ case gl::TextureType::CubeMap:
+ texture2DArrayCount++;
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+ }
+
+ unsigned int totalCount = texture2DCount + texture3DCount + texture2DArrayCount;
+ unsigned int *image2DRegisterIndex = GetImage2DRegisterIndex(
+ textureGroup, groupTextureRegisterIndex, groupRWTextureRegisterIndex);
+ unsigned int texture2DRegisterIndex = *image2DRegisterIndex;
+ unsigned int texture3DRegisterIndex = texture2DRegisterIndex + texture2DCount;
+ unsigned int texture2DArrayRegisterIndex = texture3DRegisterIndex + texture3DCount;
+ *image2DRegisterIndex += totalCount;
+
+ std::string offsetStr =
+ Image2DHLSLGroupOffsetPrefix(textureGroup) + Image2DHLSLGroupSuffix(textureGroup);
+ std::string declarationStr =
+ Image2DHLSLGroupDeclarationPrefix(textureGroup) + Image2DHLSLGroupSuffix(textureGroup);
+ std::string registerStr = Image2DHLSLGroupRegisterSuffix(textureGroup);
+ if (texture2DCount > 0)
+ {
+ out << "static const uint " << offsetStr << "2D = " << texture2DRegisterIndex << ";\n";
+ out << "uniform " << Image2DHLSLTextureString(textureGroup, gl::TextureType::_2D) << " "
+ << declarationStr << "2D[" << texture2DCount << "]"
+ << " : register(" << registerStr << texture2DRegisterIndex << ");\n";
+ }
+ if (texture3DCount > 0)
+ {
+ out << "static const uint " << offsetStr << "3D = " << texture3DRegisterIndex << ";\n";
+ out << "uniform " << Image2DHLSLTextureString(textureGroup, gl::TextureType::_3D) << " "
+ << declarationStr << "3D[" << texture3DCount << "]"
+ << " : register(" << registerStr << texture3DRegisterIndex << ");\n";
+ }
+ if (texture2DArrayCount > 0)
+ {
+ out << "static const uint " << offsetStr << "2DArray = " << texture2DArrayRegisterIndex
+ << ";\n";
+ out << "uniform " << Image2DHLSLTextureString(textureGroup, gl::TextureType::_2DArray)
+ << " " << declarationStr << "2DArray[" << texture2DArrayCount << "]"
+ << " : register(" << registerStr << texture2DArrayRegisterIndex << ");\n";
+ }
+ for (const sh::Uniform &uniform : group)
+ {
+ if (!programD3D.hasNamedUniform(uniform.name))
+ {
+ continue;
+ }
+
+ out << "static const uint " << DecorateVariable(uniform.name)
+ << ArrayIndexString(uniform.arraySizes) << " = {";
+ for (unsigned int index = 0; index < uniform.getArraySizeProduct(); index++)
+ {
+ if (index > 0)
+ {
+ out << ", ";
+ }
+ switch (image2DBindLayout.at(uniform.binding + index))
+ {
+ case gl::TextureType::_2D:
+ {
+ out << texture2DRegisterIndex;
+ programD3D.assignImage2DRegisters(texture2DRegisterIndex,
+ uniform.binding + index, uniform.readonly);
+ texture2DRegisterIndex++;
+ break;
+ }
+ case gl::TextureType::_3D:
+ {
+ out << texture3DRegisterIndex;
+ programD3D.assignImage2DRegisters(texture3DRegisterIndex,
+ uniform.binding + index, uniform.readonly);
+ texture3DRegisterIndex++;
+ break;
+ }
+ case gl::TextureType::_2DArray:
+ case gl::TextureType::CubeMap:
+ {
+ out << texture2DArrayRegisterIndex;
+ programD3D.assignImage2DRegisters(texture2DArrayRegisterIndex,
+ uniform.binding + index, uniform.readonly);
+ texture2DArrayRegisterIndex++;
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+ }
+ out << "};\n";
+ }
+
+ gl::Shader *shaderGL = programData.getAttachedShader(shaderType);
+ const ShaderD3D *shaderD3D = GetImplAs<ShaderD3D>(shaderGL);
+ const bool getDimensionsIgnoresBaseLevel = programD3D.usesGetDimensionsIgnoresBaseLevel();
+
+ if (shaderD3D->useImage2DFunction(Image2DHLSLGroupFunctionName(textureGroup, IMAGE2DSIZE)))
+ {
+ OutputImage2DSizeFunction(out, textureGroup, totalCount, texture2DCount, texture3DCount,
+ texture2DArrayCount, offsetStr, declarationStr,
+ getDimensionsIgnoresBaseLevel);
+ }
+ if (shaderD3D->useImage2DFunction(Image2DHLSLGroupFunctionName(textureGroup, IMAGE2DLOAD)))
+ {
+ OutputImage2DLoadFunction(out, textureGroup, totalCount, texture2DCount, texture3DCount,
+ texture2DArrayCount, offsetStr, declarationStr);
+ }
+ if (shaderD3D->useImage2DFunction(Image2DHLSLGroupFunctionName(textureGroup, IMAGE2DSTORE)))
+ {
+ OutputImage2DStoreFunction(out, textureGroup, totalCount, texture2DCount, texture3DCount,
+ texture2DArrayCount, offsetStr, declarationStr);
+ }
+}
+
+// kImage2DFunctionString must be the same as outputHLSL.
+constexpr const char kImage2DFunctionString[] = "// @@ IMAGE2D DECLARATION FUNCTION STRING @@";
+} // anonymous namespace
+
+std::string generateShaderForImage2DBindSignature(
+ const d3d::Context *context,
+ ProgramD3D &programD3D,
+ const gl::ProgramState &programData,
+ gl::ShaderType shaderType,
+ std::vector<sh::Uniform> &image2DUniforms,
+ const gl::ImageUnitTextureTypeMap &image2DBindLayout)
+{
+ std::vector<std::vector<sh::Uniform>> groupedImage2DUniforms(IMAGE2D_MAX + 1);
+ unsigned int image2DTexture2DCount = 0, image2DTexture3DCount = 0,
+ image2DTexture2DArrayCount = 0;
+ for (sh::Uniform &image2D : image2DUniforms)
+ {
+ for (unsigned int index = 0; index < image2D.getArraySizeProduct(); index++)
+ {
+ // Any image variable declared without a binding qualifier is initially bound to unit
+ // zero.
+ if (image2D.binding == -1)
+ {
+ image2D.binding = 0;
+ }
+ switch (image2DBindLayout.at(image2D.binding + index))
+ {
+ case gl::TextureType::_2D:
+ image2DTexture2DCount++;
+ break;
+ case gl::TextureType::_3D:
+ image2DTexture3DCount++;
+ break;
+ case gl::TextureType::_2DArray:
+ case gl::TextureType::CubeMap:
+ image2DTexture2DArrayCount++;
+ break;
+ default:
+ UNREACHABLE();
+ }
+ }
+ Image2DHLSLGroup group = image2DHLSLGroup(image2D);
+ groupedImage2DUniforms[group].push_back(image2D);
+ }
+
+ gl::Shader *shaderGL = programData.getAttachedShader(shaderType);
+ const ShaderD3D *shaderD3D = GetImplAs<ShaderD3D>(shaderGL);
+ unsigned int groupTextureRegisterIndex = shaderD3D->getReadonlyImage2DRegisterIndex();
+ unsigned int groupRWTextureRegisterIndex = shaderD3D->getImage2DRegisterIndex();
+ unsigned int image2DTexture3DIndex = 0;
+ unsigned int image2DTexture2DArrayIndex = image2DTexture3DCount;
+ unsigned int image2DTexture2DIndex = image2DTexture3DCount + image2DTexture2DArrayCount;
+ std::ostringstream out;
+
+ for (int groupId = IMAGE2D_MIN; groupId < IMAGE2D_MAX; ++groupId)
+ {
+ OutputHLSLImage2DUniformGroup(programD3D, programData, shaderType, out,
+ Image2DHLSLGroup(groupId), groupedImage2DUniforms[groupId],
+ image2DBindLayout, &groupTextureRegisterIndex,
+ &groupRWTextureRegisterIndex, &image2DTexture3DIndex,
+ &image2DTexture2DArrayIndex, &image2DTexture2DIndex);
+ }
+
+ std::string shaderHLSL(programData.getAttachedShader(shaderType)->getTranslatedSource());
+ bool success = angle::ReplaceSubstring(&shaderHLSL, kImage2DFunctionString, out.str());
+ ASSERT(success);
+
+ return shaderHLSL;
+}
+
+} // namespace rx