Implement bicubic filtering.

This commit is contained in:
Skyth 2024-10-22 16:28:30 +03:00
parent 6477f65937
commit f315ae49ba
3 changed files with 122 additions and 11 deletions

View file

@ -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<float4> g_Texture2DDescriptorHeap[] : register(t0, space0);
Texture3D<float4> g_Texture3DDescriptorHeap[] : register(t0, space1);
TextureCube<float4> g_TextureCubeDescriptorHeap[] : register(t0, space2);
SamplerState g_SamplerDescriptorHeap[] : register(s0, space3);
float4 tfetch2D(uint resourceDescriptorIndex, uint samplerDescriptorIndex, float2 texCoord, float2 offset)
{
Texture2D<float4> 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<float4> 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);

View file

@ -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)
{

View file

@ -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);