mirror of
https://github.com/hedge-dev/UnleashedRecomp.git
synced 2025-12-19 14:32:19 +00:00
Implement anti aliased filtering for point filtered CSD casts.
This commit is contained in:
parent
f327eb8357
commit
087b1eb220
3 changed files with 99 additions and 0 deletions
|
|
@ -291,6 +291,7 @@ function(compile_pixel_shader FILE_PATH)
|
||||||
endfunction()
|
endfunction()
|
||||||
|
|
||||||
compile_vertex_shader(copy_vs)
|
compile_vertex_shader(copy_vs)
|
||||||
|
compile_pixel_shader(csd_filter_ps)
|
||||||
compile_pixel_shader(gaussian_blur_3x3)
|
compile_pixel_shader(gaussian_blur_3x3)
|
||||||
compile_pixel_shader(gaussian_blur_5x5)
|
compile_pixel_shader(gaussian_blur_5x5)
|
||||||
compile_pixel_shader(gaussian_blur_7x7)
|
compile_pixel_shader(gaussian_blur_7x7)
|
||||||
|
|
|
||||||
44
UnleashedRecomp/gpu/shader/csd_filter_ps.hlsl
Normal file
44
UnleashedRecomp/gpu/shader/csd_filter_ps.hlsl
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
#include "../../../thirdparty/ShaderRecomp/ShaderRecomp/shader_common.h"
|
||||||
|
|
||||||
|
#ifdef __spirv__
|
||||||
|
|
||||||
|
#define s0_Texture2DDescriptorIndex vk::RawBufferLoad<uint>(g_PushConstants.SharedConstants + 0)
|
||||||
|
#define s0_SamplerDescriptorIndex vk::RawBufferLoad<uint>(g_PushConstants.SharedConstants + 192)
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
cbuffer SharedConstants : register(b2, space4)
|
||||||
|
{
|
||||||
|
uint s0_Texture2DDescriptorIndex : packoffset(c0.x);
|
||||||
|
uint s0_SamplerDescriptorIndex : packoffset(c12.x);
|
||||||
|
DEFINE_SHARED_CONSTANTS();
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
float4 main(
|
||||||
|
in float4 iPosition : SV_Position,
|
||||||
|
in float4 iTexCoord0 : TEXCOORD0,
|
||||||
|
in float4 iTexCoord1 : TEXCOORD1) : SV_Target
|
||||||
|
{
|
||||||
|
Texture2D<float4> texture = g_Texture2DDescriptorHeap[s0_Texture2DDescriptorIndex];
|
||||||
|
SamplerState samplerState = g_SamplerDescriptorHeap[s0_SamplerDescriptorIndex];
|
||||||
|
|
||||||
|
uint2 dimensions;
|
||||||
|
texture.GetDimensions(dimensions.x, dimensions.y);
|
||||||
|
|
||||||
|
// https://www.shadertoy.com/view/csX3RH
|
||||||
|
float2 uvTexspace = iTexCoord1.xy * dimensions;
|
||||||
|
float2 seam = floor(uvTexspace + 0.5);
|
||||||
|
uvTexspace = (uvTexspace - seam) / fwidth(uvTexspace) + seam;
|
||||||
|
uvTexspace = clamp(uvTexspace, seam - 0.5, seam + 0.5);
|
||||||
|
float2 texCoord = uvTexspace / dimensions;
|
||||||
|
|
||||||
|
float4 color = texture.Sample(samplerState, texCoord);
|
||||||
|
color *= iTexCoord0;
|
||||||
|
|
||||||
|
// The game enables alpha test for CSD, but the alpha threshold doesn't seem to be assigned anywhere? Weird.
|
||||||
|
clip(color.a - g_AlphaThreshold);
|
||||||
|
|
||||||
|
return color;
|
||||||
|
}
|
||||||
|
|
@ -34,6 +34,8 @@
|
||||||
#include "../../thirdparty/ShaderRecomp/ShaderRecomp/shader_common.h"
|
#include "../../thirdparty/ShaderRecomp/ShaderRecomp/shader_common.h"
|
||||||
#include "shader/copy_vs.hlsl.dxil.h"
|
#include "shader/copy_vs.hlsl.dxil.h"
|
||||||
#include "shader/copy_vs.hlsl.spirv.h"
|
#include "shader/copy_vs.hlsl.spirv.h"
|
||||||
|
#include "shader/csd_filter_ps.hlsl.dxil.h"
|
||||||
|
#include "shader/csd_filter_ps.hlsl.spirv.h"
|
||||||
#include "shader/gaussian_blur_3x3.hlsl.dxil.h"
|
#include "shader/gaussian_blur_3x3.hlsl.dxil.h"
|
||||||
#include "shader/gaussian_blur_3x3.hlsl.spirv.h"
|
#include "shader/gaussian_blur_3x3.hlsl.spirv.h"
|
||||||
#include "shader/gaussian_blur_5x5.hlsl.dxil.h"
|
#include "shader/gaussian_blur_5x5.hlsl.dxil.h"
|
||||||
|
|
@ -587,6 +589,15 @@ static void LoadEmbeddedResources()
|
||||||
g_buttonBcDiff = decompressZstd(g_button_bc_diff, g_button_bc_diff_uncompressed_size);
|
g_buttonBcDiff = decompressZstd(g_button_bc_diff, g_button_bc_diff_uncompressed_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum class CsdFilterState
|
||||||
|
{
|
||||||
|
Unknown,
|
||||||
|
On,
|
||||||
|
Off
|
||||||
|
};
|
||||||
|
|
||||||
|
static CsdFilterState g_csdFilterState;
|
||||||
|
|
||||||
enum class RenderCommandType
|
enum class RenderCommandType
|
||||||
{
|
{
|
||||||
SetRenderState,
|
SetRenderState,
|
||||||
|
|
@ -742,6 +753,7 @@ struct RenderCommand
|
||||||
uint32_t primitiveCount;
|
uint32_t primitiveCount;
|
||||||
UploadAllocation vertexStreamZeroData;
|
UploadAllocation vertexStreamZeroData;
|
||||||
uint32_t vertexStreamZeroStride;
|
uint32_t vertexStreamZeroStride;
|
||||||
|
CsdFilterState csdFilterState;
|
||||||
} drawPrimitiveUP;
|
} drawPrimitiveUP;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
|
|
@ -1044,6 +1056,9 @@ enum
|
||||||
|
|
||||||
static std::unique_ptr<GuestShader> g_gaussianBlurShaders[GAUSSIAN_BLUR_COUNT];
|
static std::unique_ptr<GuestShader> g_gaussianBlurShaders[GAUSSIAN_BLUR_COUNT];
|
||||||
|
|
||||||
|
static std::unique_ptr<GuestShader> g_csdFilterShader;
|
||||||
|
static GuestShader* g_csdShader;
|
||||||
|
|
||||||
#define CREATE_SHADER(NAME) \
|
#define CREATE_SHADER(NAME) \
|
||||||
g_device->createShader( \
|
g_device->createShader( \
|
||||||
g_vulkan ? g_##NAME##_spirv : g_##NAME##_dxil, \
|
g_vulkan ? g_##NAME##_spirv : g_##NAME##_dxil, \
|
||||||
|
|
@ -1443,6 +1458,9 @@ void Video::CreateHostDevice()
|
||||||
g_gaussianBlurShaders[GAUSSIAN_BLUR_7X7]->shader = CREATE_SHADER(gaussian_blur_7x7);
|
g_gaussianBlurShaders[GAUSSIAN_BLUR_7X7]->shader = CREATE_SHADER(gaussian_blur_7x7);
|
||||||
g_gaussianBlurShaders[GAUSSIAN_BLUR_9X9]->shader = CREATE_SHADER(gaussian_blur_9x9);
|
g_gaussianBlurShaders[GAUSSIAN_BLUR_9X9]->shader = CREATE_SHADER(gaussian_blur_9x9);
|
||||||
|
|
||||||
|
g_csdFilterShader = std::make_unique<GuestShader>(ResourceType::PixelShader);
|
||||||
|
g_csdFilterShader->shader = CREATE_SHADER(csd_filter_ps);
|
||||||
|
|
||||||
CreateImGuiBackend();
|
CreateImGuiBackend();
|
||||||
|
|
||||||
auto gammaCorrectionShader = CREATE_SHADER(gamma_correction_ps);
|
auto gammaCorrectionShader = CREATE_SHADER(gamma_correction_ps);
|
||||||
|
|
@ -3415,6 +3433,7 @@ static void DrawPrimitiveUP(GuestDevice* device, uint32_t primitiveType, uint32_
|
||||||
cmd.drawPrimitiveUP.primitiveCount = primitiveCount;
|
cmd.drawPrimitiveUP.primitiveCount = primitiveCount;
|
||||||
cmd.drawPrimitiveUP.vertexStreamZeroData = g_uploadAllocators[g_frame].allocate<true>(reinterpret_cast<uint32_t*>(vertexStreamZeroData), primitiveCount * vertexStreamZeroStride, 0x4);
|
cmd.drawPrimitiveUP.vertexStreamZeroData = g_uploadAllocators[g_frame].allocate<true>(reinterpret_cast<uint32_t*>(vertexStreamZeroData), primitiveCount * vertexStreamZeroStride, 0x4);
|
||||||
cmd.drawPrimitiveUP.vertexStreamZeroStride = vertexStreamZeroStride;
|
cmd.drawPrimitiveUP.vertexStreamZeroStride = vertexStreamZeroStride;
|
||||||
|
cmd.drawPrimitiveUP.csdFilterState = g_csdFilterState;
|
||||||
|
|
||||||
queue.submit();
|
queue.submit();
|
||||||
}
|
}
|
||||||
|
|
@ -3440,6 +3459,13 @@ static void ProcDrawPrimitiveUP(const RenderCommand& cmd)
|
||||||
else if (!g_triangleFanSupported && args.primitiveType == D3DPT_TRIANGLEFAN)
|
else if (!g_triangleFanSupported && args.primitiveType == D3DPT_TRIANGLEFAN)
|
||||||
indexCount = g_triangleFanIndexData.prepare(args.primitiveCount);
|
indexCount = g_triangleFanIndexData.prepare(args.primitiveCount);
|
||||||
|
|
||||||
|
if (args.csdFilterState != CsdFilterState::Unknown &&
|
||||||
|
(g_pipelineState.pixelShader == g_csdShader || g_pipelineState.pixelShader == g_csdFilterShader.get()))
|
||||||
|
{
|
||||||
|
SetDirtyValue(g_dirtyStates.pipelineState, g_pipelineState.pixelShader,
|
||||||
|
args.csdFilterState == CsdFilterState::On ? g_csdFilterShader.get() : g_csdShader);
|
||||||
|
}
|
||||||
|
|
||||||
FlushRenderStateForRenderThread();
|
FlushRenderStateForRenderThread();
|
||||||
|
|
||||||
if (indexCount != 0)
|
if (indexCount != 0)
|
||||||
|
|
@ -3788,6 +3814,9 @@ static GuestShader* CreateShader(const be<uint32_t>* function, ResourceType reso
|
||||||
else
|
else
|
||||||
shader->AddRef();
|
shader->AddRef();
|
||||||
|
|
||||||
|
if (hash == 0x31173204A896098A)
|
||||||
|
g_csdShader = shader;
|
||||||
|
|
||||||
return shader;
|
return shader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -5481,6 +5510,14 @@ static void ModelConsumerThread()
|
||||||
SanitizePipelineState(pipelineState);
|
SanitizePipelineState(pipelineState);
|
||||||
EnqueueGraphicsPipelineCompilation(pipelineState, emptyHolderPair, "Precompiled Pipeline");
|
EnqueueGraphicsPipelineCompilation(pipelineState, emptyHolderPair, "Precompiled Pipeline");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compile the CSD filter shader that we pass to the game when point filtering is used.
|
||||||
|
if (pipelineState.pixelShader == g_csdShader)
|
||||||
|
{
|
||||||
|
pipelineState.pixelShader = g_csdFilterShader.get();
|
||||||
|
SanitizePipelineState(pipelineState);
|
||||||
|
EnqueueGraphicsPipelineCompilation(pipelineState, emptyHolderPair, "Precompiled CSD Filter Pipeline");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_pendingPipelineStateCache = false;
|
g_pendingPipelineStateCache = false;
|
||||||
|
|
@ -5727,6 +5764,23 @@ void VideoConfigValueChangedCallback(IConfigDef* config)
|
||||||
config == &Config::ShadowResolution;
|
config == &Config::ShadowResolution;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SWA::CCsdTexListMirage::SetFilter
|
||||||
|
PPC_FUNC_IMPL(__imp__sub_825E4300);
|
||||||
|
PPC_FUNC(sub_825E4300)
|
||||||
|
{
|
||||||
|
g_csdFilterState = ctx.r5.u32 == 0 ? CsdFilterState::On : CsdFilterState::Off;
|
||||||
|
ctx.r5.u32 = 1;
|
||||||
|
__imp__sub_825E4300(ctx, base);
|
||||||
|
}
|
||||||
|
|
||||||
|
// SWA::CCsdPlatformMirage::EndScene
|
||||||
|
PPC_FUNC_IMPL(__imp__sub_825E2F78);
|
||||||
|
PPC_FUNC(sub_825E2F78)
|
||||||
|
{
|
||||||
|
g_csdFilterState = CsdFilterState::Unknown;
|
||||||
|
__imp__sub_825E2F78(ctx, base);
|
||||||
|
}
|
||||||
|
|
||||||
GUEST_FUNCTION_HOOK(sub_82BD99B0, CreateDevice);
|
GUEST_FUNCTION_HOOK(sub_82BD99B0, CreateDevice);
|
||||||
|
|
||||||
GUEST_FUNCTION_HOOK(sub_82BE6230, DestructResource);
|
GUEST_FUNCTION_HOOK(sub_82BE6230, DestructResource);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue