diff --git a/UnleashedRecomp/gpu/video.cpp b/UnleashedRecomp/gpu/video.cpp index 6dc44ccd..e19301f9 100644 --- a/UnleashedRecomp/gpu/video.cpp +++ b/UnleashedRecomp/gpu/video.cpp @@ -90,7 +90,6 @@ static GuestSurface* g_depthStencil; static RenderFramebuffer* g_framebuffer; static RenderViewport g_viewport(0.0f, 0.0f, 1280.0f, 720.0f); static bool g_halfPixel = true; -static uint32_t g_zFunc; static PipelineState g_pipelineState; static SharedConstants g_sharedConstants; static RenderSamplerDesc g_samplerDescs[16]; @@ -879,8 +878,41 @@ static void ProcSetRenderState(const RenderCommand& cmd) } case D3DRS_ZFUNC: { - g_zFunc = value; - SetDirtyValue(g_dirtyStates.pipelineState, g_pipelineState.zFunc, ConvertComparisonFunc(value, g_viewport.minDepth >= g_viewport.maxDepth)); + RenderComparisonFunction comparisonFunc; + + switch (value) + { + case D3DCMP_NEVER: + comparisonFunc = RenderComparisonFunction::NEVER; + break; + case D3DCMP_LESS: + comparisonFunc = RenderComparisonFunction::LESS; + break; + case D3DCMP_EQUAL: + comparisonFunc = RenderComparisonFunction::EQUAL; + break; + case D3DCMP_LESSEQUAL: + comparisonFunc = RenderComparisonFunction::LESS_EQUAL; + break; + case D3DCMP_GREATER: + comparisonFunc = RenderComparisonFunction::GREATER; + break; + case D3DCMP_NOTEQUAL: + comparisonFunc = RenderComparisonFunction::NOT_EQUAL; + break; + case D3DCMP_GREATEREQUAL: + comparisonFunc = RenderComparisonFunction::GREATER_EQUAL; + break; + case D3DCMP_ALWAYS: + comparisonFunc = RenderComparisonFunction::ALWAYS; + break; + default: + assert(false && "Unknown comparison function"); + comparisonFunc = RenderComparisonFunction::NEVER; + break; + } + + SetDirtyValue(g_dirtyStates.pipelineState, g_pipelineState.zFunc, comparisonFunc); break; } case D3DRS_ALPHAREF: @@ -2005,11 +2037,8 @@ static void FlushViewport() viewport.height *= height / 720.0f; } - if (viewport.minDepth >= viewport.maxDepth) - { - viewport.minDepth = 1.0f - viewport.minDepth; - viewport.maxDepth = 1.0f - viewport.maxDepth; - } + if (viewport.minDepth > viewport.maxDepth) + std::swap(viewport.minDepth, viewport.maxDepth); commandList->setViewports(viewport); @@ -2321,8 +2350,7 @@ static void ProcClear(const RenderCommand& cmd) if (!canClearInOnePass) SetFramebuffer(nullptr, g_depthStencil, true); - // The condition here is done by the game to determine reverse Z. - commandList->clearDepth(true, g_depthStencil->guestFormat == D3DFMT_D24FS8 ? (1.0f - args.z) : args.z); + commandList->clearDepth(true, args.z); } } @@ -2356,11 +2384,16 @@ static void ProcSetViewport(const RenderCommand& cmd) SetDirtyValue(g_dirtyStates.viewport, g_viewport.height, args.height); SetDirtyValue(g_dirtyStates.viewport, g_viewport.minDepth, args.minDepth); SetDirtyValue(g_dirtyStates.viewport, g_viewport.maxDepth, args.maxDepth); + + uint32_t specConstants = g_pipelineState.specConstants; + if (args.minDepth > args.maxDepth) + specConstants |= SPEC_CONSTANT_REVERSE_Z; + else + specConstants &= ~SPEC_CONSTANT_REVERSE_Z; + + SetDirtyValue(g_dirtyStates.pipelineState, g_pipelineState.specConstants, specConstants); g_dirtyStates.scissorRect |= g_dirtyStates.viewport; - - // Update Z function as it's dependent on reverse Z. - SetDirtyValue(g_dirtyStates.pipelineState, g_pipelineState.zFunc, ConvertComparisonFunc(g_zFunc, args.minDepth >= args.maxDepth)); } static void SetTexture(GuestDevice* device, uint32_t index, GuestTexture* texture) @@ -4128,6 +4161,16 @@ void ParticleTestDrawIndexedPrimitiveMidAsmHook(PPCRegister& r7) r7.u64 = std::size(g_particleTestIndexBuffer); } +void MotionBlurPrevInvViewProjectionMidAsmHook(PPCRegister& r10) +{ + auto mtxProjection = reinterpret_cast*>(g_memory.Translate(r10.u32)); + + // Reverse Z. Have to be done on CPU side because the matrix multiplications + // add up and it loses precision by the time it's sent to GPU. + mtxProjection[10] = -(mtxProjection[10] + 1.0f); + mtxProjection[14] = -mtxProjection[14]; +} + GUEST_FUNCTION_HOOK(sub_82BD99B0, CreateDevice); GUEST_FUNCTION_HOOK(sub_82BE6230, DestructResource); diff --git a/UnleashedRecompLib/config/SWA.toml b/UnleashedRecompLib/config/SWA.toml index e154e37b..596835b9 100644 --- a/UnleashedRecompLib/config/SWA.toml +++ b/UnleashedRecompLib/config/SWA.toml @@ -422,3 +422,8 @@ registers = ["r7"] name = "LoadingScreenSpeedFixMidAsmHook" address = 0x824DAB60 registers = ["r4"] + +[[midasm_hook]] +name = "MotionBlurPrevInvViewProjectionMidAsmHook" +address = 0x82BA9E7C +registers = ["r10"] diff --git a/thirdparty/ShaderRecomp b/thirdparty/ShaderRecomp index 73f17ee2..11128441 160000 --- a/thirdparty/ShaderRecomp +++ b/thirdparty/ShaderRecomp @@ -1 +1 @@ -Subproject commit 73f17ee29ad7fe5333df326a50e7f96867e63b20 +Subproject commit 11128441c618f7c8ff3f9520f0b6c5e868473ae2