From 2489145820713afe12231e2c1d4526c14cf64085 Mon Sep 17 00:00:00 2001 From: Skyth <19259897+blueskythlikesclouds@users.noreply.github.com> Date: Thu, 24 Oct 2024 14:56:26 +0300 Subject: [PATCH] Implement alpha to coverage. --- ShaderRecomp/shader_common.hlsli | 35 +++++++++------ ShaderRecomp/shader_recompiler.cpp | 69 ++++++++++++++++++++++++------ 2 files changed, 78 insertions(+), 26 deletions(-) diff --git a/ShaderRecomp/shader_common.hlsli b/ShaderRecomp/shader_common.hlsli index c3a176b..3805968 100644 --- a/ShaderRecomp/shader_common.hlsli +++ b/ShaderRecomp/shader_common.hlsli @@ -43,24 +43,23 @@ Texture3D g_Texture3DDescriptorHeap[] : register(t0, space1); TextureCube g_TextureCubeDescriptorHeap[] : register(t0, space2); SamplerState g_SamplerDescriptorHeap[] : register(s0, space3); +uint2 getTexture2DDimensions(Texture2D texture) +{ + uint2 dimensions; + texture.GetDimensions(dimensions.x, dimensions.y); + return dimensions; +} + float4 tfetch2D(uint resourceDescriptorIndex, uint samplerDescriptorIndex, float2 texCoord, float2 offset) { Texture2D texture = g_Texture2DDescriptorHeap[resourceDescriptorIndex]; - - uint2 dimensions; - texture.GetDimensions(dimensions.x, dimensions.y); - - return texture.Sample(g_SamplerDescriptorHeap[samplerDescriptorIndex], texCoord + offset / dimensions); + return texture.Sample(g_SamplerDescriptorHeap[samplerDescriptorIndex], texCoord + offset / getTexture2DDimensions(texture)); } float2 getWeights2D(uint resourceDescriptorIndex, uint samplerDescriptorIndex, float2 texCoord, float2 offset) { Texture2D texture = g_Texture2DDescriptorHeap[resourceDescriptorIndex]; - - uint2 dimensions; - texture.GetDimensions(dimensions.x, dimensions.y); - - return frac(texCoord * dimensions + offset - 0.5); + return frac(texCoord * getTexture2DDimensions(texture) + offset - 0.5); } float w0(float a) @@ -107,9 +106,7 @@ float4 tfetch2DBicubic(uint resourceDescriptorIndex, uint samplerDescriptorIndex { Texture2D texture = g_Texture2DDescriptorHeap[resourceDescriptorIndex]; SamplerState samplerState = g_SamplerDescriptorHeap[samplerDescriptorIndex]; - - uint2 dimensions; - texture.GetDimensions(dimensions.x, dimensions.y); + uint2 dimensions = getTexture2DDimensions(texture); float x = texCoord.x * dimensions.x + offset.x; float y = texCoord.y * dimensions.y + offset.y; @@ -198,3 +195,15 @@ float4 max4(float4 src0) return max(max(src0.x, src0.y), max(src0.z, src0.w)); } +float2 getPixelCoord(uint resourceDescriptorIndex, float2 texCoord) +{ + return getTexture2DDimensions(g_Texture2DDescriptorHeap[resourceDescriptorIndex]) * texCoord; +} + +float computeMipLevel(float2 pixelCoord) +{ + float2 dx = ddx(pixelCoord); + float2 dy = ddy(pixelCoord); + float deltaMaxSqr = max(dot(dx, dx), dot(dy, dy)); + return max(0.0, 0.5 * log2(deltaMaxSqr)); +} diff --git a/ShaderRecomp/shader_recompiler.cpp b/ShaderRecomp/shader_recompiler.cpp index 1e697b7..5636648 100644 --- a/ShaderRecomp/shader_recompiler.cpp +++ b/ShaderRecomp/shader_recompiler.cpp @@ -229,6 +229,36 @@ void ShaderRecompiler::recompile(const TextureFetchInstruction& instr, bool bicu ++indentation; } + auto printSrcRegister = [&](size_t componentCount) + { + print("r{}.", instr.srcRegister); + + for (size_t i = 0; i < componentCount; i++) + out += SWIZZLES[((instr.srcSwizzle >> (i * 2))) & 0x3]; + }; + + std::string constName; + const char* constNamePtr = nullptr; + + auto findResult = samplers.find(instr.constIndex); + if (findResult != samplers.end()) + { + constNamePtr = findResult->second; + } + else + { + constName = std::format("s{}", instr.constIndex); + constNamePtr = constName.c_str(); + } + + if (instr.constIndex == 0 && instr.dimension == TextureDimension::Texture2D) + { + indent(); + print("pixelCoord = getPixelCoord(GET_SHARED_CONSTANT({}_ResourceDescriptorIndex), ", constNamePtr); + printSrcRegister(2); + out += ");\n"; + } + indent(); print("r{}.", instr.dstRegister); printDstSwizzle(instr.dstSwizzle, false); @@ -268,18 +298,8 @@ void ShaderRecompiler::recompile(const TextureFetchInstruction& instr, bool bicu if (bicubic) out += "Bicubic"; - out += '('; - - auto findResult = samplers.find(instr.constIndex); - if (findResult != samplers.end()) - print("GET_SHARED_CONSTANT({}_ResourceDescriptorIndex), GET_SHARED_CONSTANT({}_SamplerDescriptorIndex)", findResult->second, findResult->second); - else - print("GET_SHARED_CONSTANT(s{}_ResourceDescriptorIndex), GET_SHARED_CONSTANT(s{}_SamplerDescriptorIndex)", instr.constIndex, instr.constIndex); - - print(", r{}.", instr.srcRegister); - - for (size_t i = 0; i < componentCount; i++) - out += SWIZZLES[((instr.srcSwizzle >> (i * 2))) & 0x3]; + print("(GET_SHARED_CONSTANT({0}_ResourceDescriptorIndex), GET_SHARED_CONSTANT({0}_SamplerDescriptorIndex), ", constNamePtr); + printSrcRegister(componentCount); switch (instr.dimension) { @@ -1290,7 +1310,10 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData) out += "\tbool p0 = false;\n"; out += "\tfloat ps = 0.0;\n"; if (isPixelShader) + { + out += "\tfloat2 pixelCoord = 0.0;\n"; out += "\tCubeMapData cubeMapData = (CubeMapData)0;\n"; + } const be* code = reinterpret_cast*>(shaderData + shaderContainer->virtualSize + shader->physicalOffset); @@ -1591,7 +1614,27 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData) if (isPixelShader) { indent(); - out += "[branch] if (GET_SHARED_CONSTANT(g_AlphaTestMode) != 0) clip(oC0.w - GET_SHARED_CONSTANT(g_AlphaThreshold));\n"; + out += "[branch] if (GET_SHARED_CONSTANT(g_AlphaTestMode) == 1)"; + indent(); + out += '{'; + + indent(); + out += "\tclip(oC0.w - GET_SHARED_CONSTANT(g_AlphaThreshold));\n"; + + indent(); + out += "}"; + indent(); + out += "else if (GET_SHARED_CONSTANT(g_AlphaTestMode) == 2)"; + indent(); + out += '{'; + + indent(); + out += "\toC0.w *= 1.0 + computeMipLevel(pixelCoord) * 0.25;\n"; + indent(); + out += "\toC0.w = 0.5 + (oC0.w - GET_SHARED_CONSTANT(g_AlphaThreshold)) / max(fwidth(oC0.w), 1e-6);\n"; + + indent(); + out += '}'; } else if (isCsdShader) {