From b804ed1f036051ac4ee3a637bae873b72c90ac04 Mon Sep 17 00:00:00 2001 From: Anthony Date: Tue, 14 Sep 2021 20:37:22 +1200 Subject: [PATCH 1/3] Fix flicker in antialias sample Improve X_D3DSWAP_COPY behaviour --- src/core/hle/D3D8/Direct3D9/Direct3D9.cpp | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp b/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp index ede4bcc3d..655498807 100644 --- a/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp +++ b/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp @@ -183,6 +183,8 @@ static xbox::X_D3DBaseTexture CxbxActiveTextureCopies[xbox::X_D3DTS_STAGE xbox::X_D3DVIEWPORT8 g_Xbox_Viewport = { 0 }; float g_Xbox_BackbufferScaleX = 1; float g_Xbox_BackbufferScaleY = 1; +xbox::X_D3DSWAP g_LastD3DSwap = (xbox::X_D3DSWAP) -1; + static constexpr size_t INDEX_BUFFER_CACHE_SIZE = 10000; @@ -2960,6 +2962,12 @@ void GetScreenScaleFactors(float& scaleX, float& scaleY) { return; } + if (g_LastD3DSwap == xbox::X_D3DSWAP_COPY) { + // HACK: Pretend we are drawing to the frontbuffer + // by disabling scale factors. + return; + } + // Example: // NFS HP2 renders in-game at 640*480 // The title uses MSAA, which increases the rendertarget size, but leaves the screen scale unaffected @@ -5203,13 +5211,14 @@ xbox::dword_xt WINAPI xbox::EMUPATCH(D3DDevice_Swap) if (Flags != 0 && Flags != CXBX_SWAP_PRESENT_FORWARD) LOG_TEST_CASE("D3DDevice_Swap: Flags != 0"); - // TODO handle swap flags - if (Flags & X_D3DSWAP_COPY) { - // This flag resets the backbuffer scale? + g_LastD3DSwap = (xbox::X_D3DSWAP) Flags; + + // TODO handle swap flags correctly + if (Flags == X_D3DSWAP_COPY) { // Test case: Antialias sample, Backbufferscale use this flag - // Test case: Need for Speed: Hot Pursuit 2 does not, but uses backbufferscale - g_Xbox_BackbufferScaleX = 1; - g_Xbox_BackbufferScaleY = 1; + // This is supposed to allow rendering to the frontbuffer, but we don't maintain one right now + // Return so we don't Present + return g_Xbox_SwapData.Swap; } // Fetch the host backbuffer From 32fa33ddab2ddbfafeaa3a9304fd30908bef205e Mon Sep 17 00:00:00 2001 From: Anthony Date: Thu, 7 Oct 2021 00:20:49 +1300 Subject: [PATCH 2/3] Fix MotoGP flicker Hack to handle BYPASSCOPY --- src/core/hle/D3D8/Direct3D9/Direct3D9.cpp | 36 +++++++++++++++-------- src/core/hle/D3D8/XbD3D8Types.h | 2 ++ 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp b/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp index 655498807..746fdae1b 100644 --- a/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp +++ b/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp @@ -5207,19 +5207,31 @@ xbox::dword_xt WINAPI xbox::EMUPATCH(D3DDevice_Swap) { LOG_FUNC_ONE_ARG(Flags); - // TODO: Ensure this flag is always the same across library versions - if (Flags != 0 && Flags != CXBX_SWAP_PRESENT_FORWARD) - LOG_TEST_CASE("D3DDevice_Swap: Flags != 0"); - - g_LastD3DSwap = (xbox::X_D3DSWAP) Flags; - - // TODO handle swap flags correctly - if (Flags == X_D3DSWAP_COPY) { - // Test case: Antialias sample, Backbufferscale use this flag - // This is supposed to allow rendering to the frontbuffer, but we don't maintain one right now - // Return so we don't Present - return g_Xbox_SwapData.Swap; + // Handle swap flags + // We don't maintain a swap chain, and draw everything to backbuffer 0 + // so just hack around the swap flags for now... + static float prevBackBufferScaleX; + if (Flags == X_D3DSWAP_BYPASSCOPY) { + // Test case: MotoGp2 + // Title handles copying to the frontbuffer itself, but we don't keep track of one + // MotoGp2 seems to copy a black rectangle over the backbuffer + // HACK: Effectively disable drawing - so the title can't copy anything around via draws + // and we just have to hope the title leaves the backbuffer untouched... + prevBackBufferScaleX = g_Xbox_BackbufferScaleX; + g_Xbox_BackbufferScaleX = 0; } + else if (g_LastD3DSwap == X_D3DSWAP_BYPASSCOPY) { + g_Xbox_BackbufferScaleX = prevBackBufferScaleX; + } + + g_LastD3DSwap = (xbox::X_D3DSWAP)Flags; + + // Early exit if we're not ready to present + // Test Case: Antialias sample, BackBufferScale sample + // Which use D3DSWAP_COPY to render UI directly to the frontbuffer + // If we present before the UI is drawn, it will flicker + if(Flags != X_D3DSWAP_DEFAULT && !(Flags & X_D3DSWAP_FINISH)) + return g_Xbox_SwapData.Swap; // Fetch the host backbuffer IDirect3DSurface *pCurrentHostBackBuffer = nullptr; diff --git a/src/core/hle/D3D8/XbD3D8Types.h b/src/core/hle/D3D8/XbD3D8Types.h index 33040d5c0..002f28b1d 100644 --- a/src/core/hle/D3D8/XbD3D8Types.h +++ b/src/core/hle/D3D8/XbD3D8Types.h @@ -664,7 +664,9 @@ X_D3DSWAPDATA; typedef enum _X_D3DSWAP { + X_D3DSWAP_DEFAULT = 0, X_D3DSWAP_COPY = 1, + X_D3DSWAP_BYPASSCOPY = 2, X_D3DSWAP_FINISH = 4, } X_D3DSWAP; From b86343290486247a30ecf26adf3970dd2e5884a0 Mon Sep 17 00:00:00 2001 From: Anthony Date: Thu, 7 Oct 2021 21:38:08 +1300 Subject: [PATCH 3/3] Add LOG_TEST_CASE for uncommon swap flags --- src/core/hle/D3D8/Direct3D9/Direct3D9.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp b/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp index 746fdae1b..8819f0abe 100644 --- a/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp +++ b/src/core/hle/D3D8/Direct3D9/Direct3D9.cpp @@ -5230,8 +5230,11 @@ xbox::dword_xt WINAPI xbox::EMUPATCH(D3DDevice_Swap) // Test Case: Antialias sample, BackBufferScale sample // Which use D3DSWAP_COPY to render UI directly to the frontbuffer // If we present before the UI is drawn, it will flicker - if(Flags != X_D3DSWAP_DEFAULT && !(Flags & X_D3DSWAP_FINISH)) + if (Flags != X_D3DSWAP_DEFAULT && !(Flags & X_D3DSWAP_FINISH)) { + if (Flags == X_D3DSWAP_COPY) { LOG_TEST_CASE("X_D3DSWAP_COPY"); } + if (Flags == X_D3DSWAP_BYPASSCOPY) { LOG_TEST_CASE("X_D3DSWAP_BYPASSCOPY"); } return g_Xbox_SwapData.Swap; + } // Fetch the host backbuffer IDirect3DSurface *pCurrentHostBackBuffer = nullptr;