diff options
Diffstat (limited to 'gfx/angle/checkout/src/libANGLE/renderer/d3d/DynamicImage2DHLSL.cpp')
-rw-r--r-- | gfx/angle/checkout/src/libANGLE/renderer/d3d/DynamicImage2DHLSL.cpp | 920 |
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 |