From eb980474122434d64320e90af612ad1b67455ec6 Mon Sep 17 00:00:00 2001 From: WinterSnowfall Date: Wed, 6 Nov 2024 22:23:45 +0200 Subject: [PATCH] [d3d9] Skip some validations when hDeviceWindow is NULL --- src/d3d9/d3d9_device.cpp | 9 ++++--- src/d3d9/d3d9_interface.cpp | 47 +++++++++++++++++++++++++++++++++++++ src/d3d9/d3d9_interface.h | 43 +-------------------------------- 3 files changed, 54 insertions(+), 45 deletions(-) diff --git a/src/d3d9/d3d9_device.cpp b/src/d3d9/d3d9_device.cpp index f1ae522ec..4b96afda2 100644 --- a/src/d3d9/d3d9_device.cpp +++ b/src/d3d9/d3d9_device.cpp @@ -8309,9 +8309,12 @@ namespace dxvk { " - Windowed: ", pPresentationParameters->Windowed ? "true" : "false", "\n", " - Swap effect: ", pPresentationParameters->SwapEffect, "\n")); - if (!pPresentationParameters->Windowed && - (pPresentationParameters->BackBufferWidth == 0 - || pPresentationParameters->BackBufferHeight == 0)) { + // Black Desert creates a device with a NULL hDeviceWindow and + // seemingly expects this validation to not prevent a swapchain reset. + if (pPresentationParameters->hDeviceWindow != nullptr && + !pPresentationParameters->Windowed && + (pPresentationParameters->BackBufferWidth == 0 + || pPresentationParameters->BackBufferHeight == 0)) { return D3DERR_INVALIDCALL; } diff --git a/src/d3d9/d3d9_interface.cpp b/src/d3d9/d3d9_interface.cpp index d30aa148b..12ec02f26 100644 --- a/src/d3d9/d3d9_interface.cpp +++ b/src/d3d9/d3d9_interface.cpp @@ -406,4 +406,51 @@ namespace dxvk { return D3DERR_INVALIDCALL; } + + HRESULT D3D9InterfaceEx::ValidatePresentationParameters(D3DPRESENT_PARAMETERS* pPresentationParameters) { + if (m_extended) { + // The swap effect value on a D3D9Ex device + // can not be higher than D3DSWAPEFFECT_FLIPEX. + if (unlikely(pPresentationParameters->SwapEffect > D3DSWAPEFFECT_FLIPEX)) + return D3DERR_INVALIDCALL; + } else { + // The swap effect value on a non-Ex D3D9 device + // can not be higher than D3DSWAPEFFECT_COPY. + if (unlikely(pPresentationParameters->SwapEffect > D3DSWAPEFFECT_COPY)) + return D3DERR_INVALIDCALL; + } + + // The swap effect value can not be 0. + // Black Desert sets this to 0 with a NULL hDeviceWindow + // and expects device creation to succeed. + if (unlikely(pPresentationParameters->hDeviceWindow != nullptr + && !pPresentationParameters->SwapEffect)) + return D3DERR_INVALIDCALL; + + // D3DSWAPEFFECT_COPY can not be used with more than one back buffer. + // Allow D3DSWAPEFFECT_COPY to bypass this restriction in D3D8 compatibility + // mode, since it may be a remapping of D3DSWAPEFFECT_COPY_VSYNC and RC Cars + // depends on it not being validated. + if (unlikely(!IsD3D8Compatible() + && pPresentationParameters->SwapEffect == D3DSWAPEFFECT_COPY + && pPresentationParameters->BackBufferCount > 1)) + return D3DERR_INVALIDCALL; + + // 3 is the highest supported back buffer count. + if (unlikely(pPresentationParameters->BackBufferCount > 3)) + return D3DERR_INVALIDCALL; + + // Valid fullscreen presentation intervals must be known values. + if (unlikely(!pPresentationParameters->Windowed + && !(pPresentationParameters->PresentationInterval == D3DPRESENT_INTERVAL_DEFAULT + || pPresentationParameters->PresentationInterval == D3DPRESENT_INTERVAL_ONE + || pPresentationParameters->PresentationInterval == D3DPRESENT_INTERVAL_TWO + || pPresentationParameters->PresentationInterval == D3DPRESENT_INTERVAL_THREE + || pPresentationParameters->PresentationInterval == D3DPRESENT_INTERVAL_FOUR + || pPresentationParameters->PresentationInterval == D3DPRESENT_INTERVAL_IMMEDIATE))) + return D3DERR_INVALIDCALL; + + return D3D_OK; + } + } \ No newline at end of file diff --git a/src/d3d9/d3d9_interface.h b/src/d3d9/d3d9_interface.h index 2449694b2..9f3cd86df 100644 --- a/src/d3d9/d3d9_interface.h +++ b/src/d3d9/d3d9_interface.h @@ -121,48 +121,7 @@ namespace dxvk { HRESULT STDMETHODCALLTYPE GetAdapterLUID(UINT Adapter, LUID* pLUID); - HRESULT ValidatePresentationParameters(D3DPRESENT_PARAMETERS* pPresentationParameters) { - if (m_extended) { - // The swap effect value on a D3D9Ex device - // can not be higher than D3DSWAPEFFECT_FLIPEX. - if (unlikely(pPresentationParameters->SwapEffect > D3DSWAPEFFECT_FLIPEX)) - return D3DERR_INVALIDCALL; - } else { - // The swap effect value on a non-Ex D3D9 device - // can not be higher than D3DSWAPEFFECT_COPY. - if (unlikely(pPresentationParameters->SwapEffect > D3DSWAPEFFECT_COPY)) - return D3DERR_INVALIDCALL; - } - - // The swap effect value can not be 0. - if (unlikely(!pPresentationParameters->SwapEffect)) - return D3DERR_INVALIDCALL; - - // D3DSWAPEFFECT_COPY can not be used with more than one back buffer. - // Allow D3DSWAPEFFECT_COPY to bypass this restriction in D3D8 compatibility - // mode, since it may be a remapping of D3DSWAPEFFECT_COPY_VSYNC and RC Cars - // depends on it not being validated. - if (unlikely(!IsD3D8Compatible() - && pPresentationParameters->SwapEffect == D3DSWAPEFFECT_COPY - && pPresentationParameters->BackBufferCount > 1)) - return D3DERR_INVALIDCALL; - - // 3 is the highest supported back buffer count. - if (unlikely(pPresentationParameters->BackBufferCount > 3)) - return D3DERR_INVALIDCALL; - - // Valid fullscreen presentation intervals must be known values. - if (unlikely(!pPresentationParameters->Windowed - && !(pPresentationParameters->PresentationInterval == D3DPRESENT_INTERVAL_DEFAULT - || pPresentationParameters->PresentationInterval == D3DPRESENT_INTERVAL_ONE - || pPresentationParameters->PresentationInterval == D3DPRESENT_INTERVAL_TWO - || pPresentationParameters->PresentationInterval == D3DPRESENT_INTERVAL_THREE - || pPresentationParameters->PresentationInterval == D3DPRESENT_INTERVAL_FOUR - || pPresentationParameters->PresentationInterval == D3DPRESENT_INTERVAL_IMMEDIATE))) - return D3DERR_INVALIDCALL; - - return D3D_OK; - } + HRESULT ValidatePresentationParameters(D3DPRESENT_PARAMETERS* pPresentationParameters); const D3D9Options& GetOptions() { return m_d3d9Options; }