| // |
| // 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::ShaderVariable &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::ShaderVariable> &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::ShaderVariable &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::ShaderVariable &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::ShaderVariable> &image2DUniforms, |
| const gl::ImageUnitTextureTypeMap &image2DBindLayout) |
| { |
| std::vector<std::vector<sh::ShaderVariable>> groupedImage2DUniforms(IMAGE2D_MAX + 1); |
| unsigned int image2DTexture2DCount = 0, image2DTexture3DCount = 0, |
| image2DTexture2DArrayCount = 0; |
| for (sh::ShaderVariable &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 |