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()
|
||||
|
||||
compile_vertex_shader(copy_vs)
|
||||
compile_pixel_shader(csd_filter_ps)
|
||||
compile_pixel_shader(gaussian_blur_3x3)
|
||||
compile_pixel_shader(gaussian_blur_5x5)
|
||||
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 "shader/copy_vs.hlsl.dxil.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.spirv.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);
|
||||
}
|
||||
|
||||
enum class CsdFilterState
|
||||
{
|
||||
Unknown,
|
||||
On,
|
||||
Off
|
||||
};
|
||||
|
||||
static CsdFilterState g_csdFilterState;
|
||||
|
||||
enum class RenderCommandType
|
||||
{
|
||||
SetRenderState,
|
||||
|
|
@ -742,6 +753,7 @@ struct RenderCommand
|
|||
uint32_t primitiveCount;
|
||||
UploadAllocation vertexStreamZeroData;
|
||||
uint32_t vertexStreamZeroStride;
|
||||
CsdFilterState csdFilterState;
|
||||
} drawPrimitiveUP;
|
||||
|
||||
struct
|
||||
|
|
@ -1044,6 +1056,9 @@ enum
|
|||
|
||||
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) \
|
||||
g_device->createShader( \
|
||||
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_9X9]->shader = CREATE_SHADER(gaussian_blur_9x9);
|
||||
|
||||
g_csdFilterShader = std::make_unique<GuestShader>(ResourceType::PixelShader);
|
||||
g_csdFilterShader->shader = CREATE_SHADER(csd_filter_ps);
|
||||
|
||||
CreateImGuiBackend();
|
||||
|
||||
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.vertexStreamZeroData = g_uploadAllocators[g_frame].allocate<true>(reinterpret_cast<uint32_t*>(vertexStreamZeroData), primitiveCount * vertexStreamZeroStride, 0x4);
|
||||
cmd.drawPrimitiveUP.vertexStreamZeroStride = vertexStreamZeroStride;
|
||||
cmd.drawPrimitiveUP.csdFilterState = g_csdFilterState;
|
||||
|
||||
queue.submit();
|
||||
}
|
||||
|
|
@ -3440,6 +3459,13 @@ static void ProcDrawPrimitiveUP(const RenderCommand& cmd)
|
|||
else if (!g_triangleFanSupported && args.primitiveType == D3DPT_TRIANGLEFAN)
|
||||
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();
|
||||
|
||||
if (indexCount != 0)
|
||||
|
|
@ -3788,6 +3814,9 @@ static GuestShader* CreateShader(const be<uint32_t>* function, ResourceType reso
|
|||
else
|
||||
shader->AddRef();
|
||||
|
||||
if (hash == 0x31173204A896098A)
|
||||
g_csdShader = shader;
|
||||
|
||||
return shader;
|
||||
}
|
||||
|
||||
|
|
@ -5481,6 +5510,14 @@ static void ModelConsumerThread()
|
|||
SanitizePipelineState(pipelineState);
|
||||
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;
|
||||
|
|
@ -5727,6 +5764,23 @@ void VideoConfigValueChangedCallback(IConfigDef* config)
|
|||
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_82BE6230, DestructResource);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue