diff --git a/ShaderRecomp/shader_common.hlsli b/ShaderRecomp/shader_common.hlsli index 4ab7f4e..c3a176b 100644 --- a/ShaderRecomp/shader_common.hlsli +++ b/ShaderRecomp/shader_common.hlsli @@ -35,14 +35,14 @@ struct PushConstants [[vk::offset(132)]] float g_AlphaThreshold PACK_OFFSET(c8.y); \ [[vk::offset(136)]] uint g_Booleans PACK_OFFSET(c8.z); \ [[vk::offset(140)]] uint g_SwappedTexcoords PACK_OFFSET(c8.w); \ - [[vk::offset(144)]] uint g_InputLayoutFlags PACK_OFFSET(c9.x) + [[vk::offset(144)]] uint g_InputLayoutFlags PACK_OFFSET(c9.x); \ + [[vk::offset(148)]] bool g_EnableGIBicubicFiltering PACK_OFFSET(c9.y) Texture2D g_Texture2DDescriptorHeap[] : register(t0, space0); Texture3D g_Texture3DDescriptorHeap[] : register(t0, space1); TextureCube g_TextureCubeDescriptorHeap[] : register(t0, space2); SamplerState g_SamplerDescriptorHeap[] : register(s0, space3); - float4 tfetch2D(uint resourceDescriptorIndex, uint samplerDescriptorIndex, float2 texCoord, float2 offset) { Texture2D texture = g_Texture2DDescriptorHeap[resourceDescriptorIndex]; @@ -63,6 +63,80 @@ float2 getWeights2D(uint resourceDescriptorIndex, uint samplerDescriptorIndex, f return frac(texCoord * dimensions + offset - 0.5); } +float w0(float a) +{ + return (1.0f / 6.0f) * (a * (a * (-a + 3.0f) - 3.0f) + 1.0f); +} + +float w1(float a) +{ + return (1.0f / 6.0f) * (a * a * (3.0f * a - 6.0f) + 4.0f); +} + +float w2(float a) +{ + return (1.0f / 6.0f) * (a * (a * (-3.0f * a + 3.0f) + 3.0f) + 1.0f); +} + +float w3(float a) +{ + return (1.0f / 6.0f) * (a * a * a); +} + +float g0(float a) +{ + return w0(a) + w1(a); +} + +float g1(float a) +{ + return w2(a) + w3(a); +} + +float h0(float a) +{ + return -1.0f + w1(a) / (w0(a) + w1(a)) + 0.5f; +} + +float h1(float a) +{ + return 1.0f + w3(a) / (w2(a) + w3(a)) + 0.5f; +} + +float4 tfetch2DBicubic(uint resourceDescriptorIndex, uint samplerDescriptorIndex, float2 texCoord, float2 offset) +{ + Texture2D texture = g_Texture2DDescriptorHeap[resourceDescriptorIndex]; + SamplerState samplerState = g_SamplerDescriptorHeap[samplerDescriptorIndex]; + + uint2 dimensions; + texture.GetDimensions(dimensions.x, dimensions.y); + + float x = texCoord.x * dimensions.x + offset.x; + float y = texCoord.y * dimensions.y + offset.y; + + x -= 0.5f; + y -= 0.5f; + float px = floor(x); + float py = floor(y); + float fx = x - px; + float fy = y - py; + + float g0x = g0(fx); + float g1x = g1(fx); + float h0x = h0(fx); + float h1x = h1(fx); + float h0y = h0(fy); + float h1y = h1(fy); + + float4 r = + g0(fy) * (g0x * texture.Sample(samplerState, float2(px + h0x, py + h0y) / float2(dimensions)) + + g1x * texture.Sample(samplerState, float2(px + h1x, py + h0y) / float2(dimensions))) + + g1(fy) * (g0x * texture.Sample(samplerState, float2(px + h0x, py + h1y) / float2(dimensions)) + + g1x * texture.Sample(samplerState, float2(px + h1x, py + h1y) / float2(dimensions))); + + return r; +} + float4 tfetch3D(uint resourceDescriptorIndex, uint samplerDescriptorIndex, float3 texCoord) { return g_Texture3DDescriptorHeap[resourceDescriptorIndex].Sample(g_SamplerDescriptorHeap[samplerDescriptorIndex], texCoord); diff --git a/ShaderRecomp/shader_recompiler.cpp b/ShaderRecomp/shader_recompiler.cpp index 6713984..1e697b7 100644 --- a/ShaderRecomp/shader_recompiler.cpp +++ b/ShaderRecomp/shader_recompiler.cpp @@ -214,7 +214,7 @@ void ShaderRecompiler::recompile(const VertexFetchInstruction& instr, uint32_t a } } -void ShaderRecompiler::recompile(const TextureFetchInstruction& instr) +void ShaderRecompiler::recompile(const TextureFetchInstruction& instr, bool bicubic) { if (instr.opcode != FetchOpcode::TextureFetch && instr.opcode != FetchOpcode::GetTextureWeights) return; @@ -248,23 +248,28 @@ void ShaderRecompiler::recompile(const TextureFetchInstruction& instr) switch (instr.dimension) { case TextureDimension::Texture1D: - out += "1D("; + out += "1D"; componentCount = 1; break; case TextureDimension::Texture2D: - out += "2D("; + out += "2D"; componentCount = 2; break; case TextureDimension::Texture3D: - out += "3D("; + out += "3D"; componentCount = 3; break; case TextureDimension::TextureCube: - out += "Cube("; + out += "Cube"; componentCount = 3; break; } + 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); @@ -1441,7 +1446,7 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData) if (simpleControlFlow) { indent(); - println("for (aL = 0; aL < i{}.x; aL++)", uint32_t(cfInstr.loopStart.loopId)); + println("[unroll] for (aL = 0; aL < i{}.x; aL++)", uint32_t(cfInstr.loopStart.loopId)); indent(); out += "{\n"; ++indentation; @@ -1536,9 +1541,41 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData) if ((sequence & 0x1) != 0) { if (vertexFetch.opcode == FetchOpcode::VertexFetch) + { recompile(vertexFetch, address + i); + } else - recompile(textureFetch); + { + if (textureFetch.constIndex == 10) // g_GISampler + { + indent(); + out += "[branch] if (GET_SHARED_CONSTANT(g_EnableGIBicubicFiltering))"; + indent(); + out += '{'; + + ++indentation; + recompile(textureFetch, true); + --indentation; + + indent(); + out += "}"; + indent(); + out += "else"; + indent(); + out += '{'; + + ++indentation; + recompile(textureFetch, false); + --indentation; + + indent(); + out += '}'; + } + else + { + recompile(textureFetch, false); + } + } } else { @@ -1554,7 +1591,7 @@ void ShaderRecompiler::recompile(const uint8_t* shaderData) if (isPixelShader) { indent(); - out += "if (GET_SHARED_CONSTANT(g_AlphaTestMode) != 0) clip(oC0.w - GET_SHARED_CONSTANT(g_AlphaThreshold));\n"; + out += "[branch] if (GET_SHARED_CONSTANT(g_AlphaTestMode) != 0) clip(oC0.w - GET_SHARED_CONSTANT(g_AlphaThreshold));\n"; } else if (isCsdShader) { diff --git a/ShaderRecomp/shader_recompiler.h b/ShaderRecomp/shader_recompiler.h index f4094e7..20ca6eb 100644 --- a/ShaderRecomp/shader_recompiler.h +++ b/ShaderRecomp/shader_recompiler.h @@ -43,7 +43,7 @@ struct ShaderRecompiler : StringBuffer void printDstSwizzle01(uint32_t dstRegister, uint32_t dstSwizzle); void recompile(const VertexFetchInstruction& instr, uint32_t address); - void recompile(const TextureFetchInstruction& instr); + void recompile(const TextureFetchInstruction& instr, bool bicubic); void recompile(const AluInstruction& instr); void recompile(const uint8_t* shaderData);