From ef351ee31b74b350d0c94f373b49c9fc57d56f78 Mon Sep 17 00:00:00 2001 From: Luke Usher Date: Sat, 9 Jun 2018 08:01:01 +0100 Subject: [PATCH] Add new speedhack: Render Directly to Host BackBuffer --- resource/Cxbx.rc | 8 ++++-- src/Cxbx/ResCxbx.h | 6 +++-- src/Cxbx/WndMain.cpp | 19 ++++++++++++++ src/Cxbx/WndMain.h | 5 ++-- src/CxbxKrnl/CxbxKrnl.cpp | 3 +++ src/CxbxKrnl/Emu.cpp | 3 ++- src/CxbxKrnl/Emu.h | 3 ++- src/CxbxKrnl/EmuD3D8.cpp | 53 ++++++++++++++++++++++++++------------- src/CxbxKrnl/EmuShared.h | 7 ++++-- 9 files changed, 80 insertions(+), 27 deletions(-) diff --git a/resource/Cxbx.rc b/resource/Cxbx.rc index ca2bf1e9a..8962b63d3 100644 --- a/resource/Cxbx.rc +++ b/resource/Cxbx.rc @@ -482,9 +482,13 @@ BEGIN END POPUP "Hacks", 65535,MFT_STRING,MFS_ENABLED BEGIN + POPUP "Speed Hacks", ID_HACKS_SPEEDHACKS,MFT_STRING,MFS_ENABLED + BEGIN + MENUITEM "Run Xbox threads on all cores", ID_HACKS_RUNXBOXTHREADSONALLCORES,MFT_STRING,MFS_ENABLED + MENUITEM "Render directly to Host Backbuffer", ID_HACKS_RENDERDIRECTLYTOHOSTBACKBUFFER,MFT_STRING,MFS_ENABLED + MENUITEM "Uncap Framerate", ID_HACKS_UNCAPFRAMERATE,MFT_STRING,MFS_ENABLED + END MENUITEM "Disable Pixel Shaders", ID_HACKS_DISABLEPIXELSHADERS,MFT_STRING,MFS_ENABLED - MENUITEM "Uncap Framerate", ID_HACKS_UNCAPFRAMERATE,MFT_STRING,MFS_ENABLED - MENUITEM "Run Xbox threads on all cores", ID_HACKS_RUNXBOXTHREADSONALLCORES,MFT_STRING,MFS_ENABLED MENUITEM "Skip rdtsc patching", ID_HACKS_SKIPRDTSCPATCHING,MFT_STRING,MFS_ENABLED MENUITEM "Scale Xbox viewport to host (and back)", ID_HACKS_SCALEVIEWPORT,MFT_STRING,MFS_ENABLED END diff --git a/src/Cxbx/ResCxbx.h b/src/Cxbx/ResCxbx.h index 4af625fe9..d6ff58168 100644 --- a/src/Cxbx/ResCxbx.h +++ b/src/Cxbx/ResCxbx.h @@ -1,6 +1,6 @@ //{{NO_DEPENDENCIES}} // Microsoft Visual C++ generated include file. -// Used by C:\Work\Cxbx-Reloaded\resource\Cxbx.rc +// Used by C:\Users\lukeu\Desktop\Projects\cxbx-reloaded\resource\Cxbx.rc // #define IDI_CXBX 101 #define IDB_SPLASH 102 @@ -277,6 +277,8 @@ #define ID_HACKS_SKIPRDTSCPATCHING 40099 #define ID_HACKS_SCALEVIEWPORT 40100 #define ID_SETTINGS_CONFIG_XBOX_CONTROLLER_MAPPING 40101 +#define ID_HACKS_RENDERDIRECTLYTOHOSTBACKBUFFER 40102 +#define ID_HACKS_SPEEDHACKS 40103 #define IDC_STATIC -1 // Next default values for new objects @@ -284,7 +286,7 @@ #ifdef APSTUDIO_INVOKED #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 135 -#define _APS_NEXT_COMMAND_VALUE 40102 +#define _APS_NEXT_COMMAND_VALUE 40104 #define _APS_NEXT_CONTROL_VALUE 1256 #define _APS_NEXT_SYMED_VALUE 104 #endif diff --git a/src/Cxbx/WndMain.cpp b/src/Cxbx/WndMain.cpp index e70821060..eac425f03 100644 --- a/src/Cxbx/WndMain.cpp +++ b/src/Cxbx/WndMain.cpp @@ -225,6 +225,13 @@ WndMain::WndMain(HINSTANCE x_hInstance) : m_ScaleViewport = 0; } + dwType = REG_DWORD; dwSize = sizeof(DWORD); + result = RegQueryValueEx(hKey, "HackDirectBackBufferAccess", NULL, &dwType, (PBYTE)&m_DirectHostBackBufferAccess, &dwSize); + if (result != ERROR_SUCCESS) { + m_DirectHostBackBufferAccess = 0; + } + + dwType = REG_DWORD; dwSize = sizeof(DWORD); result = RegQueryValueEx(hKey, "CxbxDebug", NULL, &dwType, (PBYTE)&m_CxbxDebug, &dwSize); if (result != ERROR_SUCCESS) { @@ -390,6 +397,9 @@ WndMain::~WndMain() dwType = REG_DWORD; dwSize = sizeof(DWORD); RegSetValueEx(hKey, "HackScaleViewport", 0, dwType, (PBYTE)&m_ScaleViewport, dwSize); + dwType = REG_DWORD; dwSize = sizeof(DWORD); + RegSetValueEx(hKey, "HackDirectBackBufferAccess", 0, dwType, (PBYTE)&m_DirectHostBackBufferAccess, dwSize); + dwType = REG_DWORD; dwSize = sizeof(DWORD); RegSetValueEx(hKey, "CxbxDebug", 0, dwType, (PBYTE)&m_CxbxDebug, dwSize); @@ -1367,6 +1377,11 @@ LRESULT CALLBACK WndMain::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lP RefreshMenus(); break; + case ID_HACKS_RENDERDIRECTLYTOHOSTBACKBUFFER: + m_DirectHostBackBufferAccess = !m_DirectHostBackBufferAccess; + RefreshMenus(); + break; + case ID_HELP_ABOUT: { ShowAboutDialog(hwnd); @@ -1800,6 +1815,9 @@ void WndMain::RefreshMenus() chk_flag = (m_ScaleViewport) ? MF_CHECKED : MF_UNCHECKED; CheckMenuItem(settings_menu, ID_HACKS_SCALEVIEWPORT, chk_flag); + + chk_flag = (m_DirectHostBackBufferAccess) ? MF_CHECKED : MF_UNCHECKED; + CheckMenuItem(settings_menu, ID_HACKS_RENDERDIRECTLYTOHOSTBACKBUFFER, chk_flag); } // emulation menu @@ -2175,6 +2193,7 @@ void WndMain::StartEmulation(HWND hwndParent, DebuggerState LocalDebuggerState / g_EmuShared->SetUseAllCores(&m_UseAllCores); g_EmuShared->SetSkipRdtscPatching(&m_SkipRdtscPatching); g_EmuShared->SetScaleViewport(&m_ScaleViewport); + g_EmuShared->SetDirectHostBackBufferAccess(&m_DirectHostBackBufferAccess); if (m_ScaleViewport) { // Set the window size to emulation dimensions diff --git a/src/Cxbx/WndMain.h b/src/Cxbx/WndMain.h index 229d0eb83..50a4507e3 100644 --- a/src/Cxbx/WndMain.h +++ b/src/Cxbx/WndMain.h @@ -222,7 +222,8 @@ class WndMain : public Wnd int m_UncapFramerate; int m_UseAllCores; int m_SkipRdtscPatching; - int m_ScaleViewport; + int m_ScaleViewport; + int m_DirectHostBackBufferAccess; // ****************************************************************** // * debug output filenames @@ -232,4 +233,4 @@ class WndMain : public Wnd }; -#endif \ No newline at end of file +#endif diff --git a/src/CxbxKrnl/CxbxKrnl.cpp b/src/CxbxKrnl/CxbxKrnl.cpp index 7e00ff917..5a2ba43a1 100644 --- a/src/CxbxKrnl/CxbxKrnl.cpp +++ b/src/CxbxKrnl/CxbxKrnl.cpp @@ -607,6 +607,7 @@ void PrintCurrentConfigurationLog() printf("Run Xbox threads on all cores: %s\n", g_UseAllCores == 1 ? "On" : "Off"); printf("Skip RDTSC Patching: %s\n", g_SkipRdtscPatching == 1 ? "On" : "Off"); printf("Scale Xbox to host viewport (and back): %s\n", g_ScaleViewport == 1 ? "On" : "Off"); + printf("Render directly to Host BackBuffer: %s\n", g_DirectHostBackBufferAccess == 1 ? "On" : "Off"); } printf("------------------------- END OF CONFIG LOG ------------------------\n"); @@ -1252,6 +1253,8 @@ __declspec(noreturn) void CxbxKrnlInit g_SkipRdtscPatching = !!HackEnabled; g_EmuShared->GetScaleViewport(&HackEnabled); g_ScaleViewport = !!HackEnabled; + g_EmuShared->GetDirectHostBackBufferAccess(&HackEnabled); + g_DirectHostBackBufferAccess = !!HackEnabled; } #ifdef _DEBUG_PRINT_CURRENT_CONF diff --git a/src/CxbxKrnl/Emu.cpp b/src/CxbxKrnl/Emu.cpp index 947867fd3..260c64d73 100644 --- a/src/CxbxKrnl/Emu.cpp +++ b/src/CxbxKrnl/Emu.cpp @@ -68,7 +68,8 @@ bool g_DisablePixelShaders = false; bool g_UncapFramerate = false; bool g_UseAllCores = false; bool g_SkipRdtscPatching = false; -bool g_ScaleViewport = false; +bool g_ScaleViewport = false; +bool g_DirectHostBackBufferAccess = false; // Delta added to host SystemTime, used in xboxkrnl::KeQuerySystemTime and xboxkrnl::NtSetSystemTime LARGE_INTEGER HostSystemTimeDelta = {}; diff --git a/src/CxbxKrnl/Emu.h b/src/CxbxKrnl/Emu.h index 79aad3310..994f27081 100644 --- a/src/CxbxKrnl/Emu.h +++ b/src/CxbxKrnl/Emu.h @@ -111,5 +111,6 @@ extern bool g_DisablePixelShaders; extern bool g_UncapFramerate; extern bool g_UseAllCores; extern bool g_SkipRdtscPatching; -extern bool g_ScaleViewport; +extern bool g_ScaleViewport; +extern bool g_DirectHostBackBufferAccess; #endif diff --git a/src/CxbxKrnl/EmuD3D8.cpp b/src/CxbxKrnl/EmuD3D8.cpp index a43378b72..f96d1dd77 100644 --- a/src/CxbxKrnl/EmuD3D8.cpp +++ b/src/CxbxKrnl/EmuD3D8.cpp @@ -4601,24 +4601,26 @@ DWORD WINAPI XTL::EMUPATCH(D3DDevice_Swap) // Previously we used D3DX_FILTER_POINT here, but that gave jagged edges in Dashboard. // Dxbx note : D3DX_FILTER_LINEAR gives a smoother image, but 'bleeds' across borders - auto pXboxBackBufferHostSurface = GetHostSurface(g_XboxBackBufferSurface); - if (pXboxBackBufferHostSurface) { - // Blit Xbox BackBuffer to host BackBuffer - // TODO: This could be much faster if we used the XboxBackBufferSurface as a texture and blitted with a fullscreen quad - // This way, the scaling/format conversion would be handled by the GPU instead - // If we were using native D3D9, we could just use StretchRects instead, but D3D8 doesn't have that feature! - hRet = D3DXLoadSurfaceFromSurface( - /* pDestSurface = */ pCurrentHostBackBuffer, - /* pDestPalette = */ nullptr, - /* pDestRect = */ nullptr, - /* pSrcSurface = */ pXboxBackBufferHostSurface, - /* pSrcPalette = */ nullptr, - /* pSrcRect = */ nullptr, - /* Filter = */ LoadSurfaceFilter, - /* ColorKey = */ 0); + if (!g_DirectHostBackBufferAccess) { + auto pXboxBackBufferHostSurface = GetHostSurface(g_XboxBackBufferSurface); + if (pXboxBackBufferHostSurface) { + // Blit Xbox BackBuffer to host BackBuffer + // TODO: This could be much faster if we used the XboxBackBufferSurface as a texture and blitted with a fullscreen quad + // This way, the scaling/format conversion would be handled by the GPU instead + // If we were using native D3D9, we could just use StretchRects instead, but D3D8 doesn't have that feature! + hRet = D3DXLoadSurfaceFromSurface( + /* pDestSurface = */ pCurrentHostBackBuffer, + /* pDestPalette = */ nullptr, + /* pDestRect = */ nullptr, + /* pSrcSurface = */ pXboxBackBufferHostSurface, + /* pSrcPalette = */ nullptr, + /* pSrcRect = */ nullptr, + /* Filter = */ LoadSurfaceFilter, + /* ColorKey = */ 0); - if (hRet != D3D_OK) { - EmuWarning("Couldn't blit Xbox BackBuffer to host BackBuffer : %X", hRet); + if (hRet != D3D_OK) { + EmuWarning("Couldn't blit Xbox BackBuffer to host BackBuffer : %X", hRet); + } } } @@ -8087,6 +8089,19 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetRenderTarget) g_pXboxDepthStencil = pNewZStencil; pHostDepthStencil = GetHostSurface(g_pXboxDepthStencil, D3DUSAGE_DEPTHSTENCIL); + if (g_DirectHostBackBufferAccess && pRenderTarget == g_XboxBackBufferSurface) { + HRESULT hRet = g_pD3DDevice->GetBackBuffer( + #ifdef CXBX_USE_D3D9 + 0, // iSwapChain + #endif + 0, D3DBACKBUFFER_TYPE_MONO, &pHostRenderTarget); + DEBUG_D3DRESULT(hRet, "g_pD3DDevice->GetBackBuffer"); + + if (FAILED(hRet)) { + CxbxKrnlCleanup("Could not get host backbuffer"); + } + } + HRESULT hRet; #ifdef CXBX_USE_D3D9 // Mimick Direct3D 8 SetRenderTarget by only setting render target if non-null @@ -8106,6 +8121,10 @@ VOID WINAPI XTL::EMUPATCH(D3DDevice_SetRenderTarget) DEBUG_D3DRESULT(hRet, "g_pD3DDevice->SetRenderTarget"); #endif + if (g_DirectHostBackBufferAccess && pRenderTarget == g_XboxBackBufferSurface) { + pHostRenderTarget->Release(); + } + if (SUCCEEDED(hRet)) { // Once we're sure the host depth-stencil is activated... UpdateDepthStencilFlags(pHostDepthStencil); diff --git a/src/CxbxKrnl/EmuShared.h b/src/CxbxKrnl/EmuShared.h index 0dc6e802d..9846b5961 100644 --- a/src/CxbxKrnl/EmuShared.h +++ b/src/CxbxKrnl/EmuShared.h @@ -129,7 +129,9 @@ class EmuShared : public Mutex void GetSkipRdtscPatching(int* value) { Lock(); *value = m_SkipRdtscPatching; Unlock(); } void SetSkipRdtscPatching(int* value) { Lock(); m_SkipRdtscPatching = *value; Unlock(); } void GetScaleViewport(int* value) { Lock(); *value = m_ScaleViewport; Unlock(); } - void SetScaleViewport(int* value) { Lock(); m_ScaleViewport = *value; Unlock(); } + void SetScaleViewport(int* value) { Lock(); m_ScaleViewport = *value; Unlock(); } + void GetDirectHostBackBufferAccess(int* value) { Lock(); *value = m_DirectHostBackBufferAccess; Unlock(); } + void SetDirectHostBackBufferAccess(int* value) { Lock(); m_DirectHostBackBufferAccess = *value; Unlock(); } // ****************************************************************** // * MSpF/Benchmark values Accessors @@ -204,7 +206,8 @@ class EmuShared : public Mutex bool m_bMultiXbeFlag; bool m_bDebugging; int m_LedSequence[4]; - int m_ScaleViewport; + int m_ScaleViewport; + int m_DirectHostBackBufferAccess; }; // ******************************************************************