From 11efd5092e4895ec69dbd70cf7cfaeb4e2f2be83 Mon Sep 17 00:00:00 2001 From: Robin Kertels Date: Tue, 30 Jul 2024 10:04:05 +0200 Subject: [PATCH] [d3d9] Handle remaining edge cases of Discard & Lockable --- src/d3d9/d3d9_adapter.cpp | 4 ++-- src/d3d9/d3d9_common_texture.cpp | 11 +++++++++++ src/d3d9/d3d9_device.cpp | 18 ++++++++---------- src/d3d9/d3d9_swapchain.cpp | 9 ++++----- src/d3d9/d3d9_swapchain.h | 3 ++- src/d3d9/d3d9_util.cpp | 11 +++++++++++ src/d3d9/d3d9_util.h | 5 +++++ 7 files changed, 43 insertions(+), 18 deletions(-) diff --git a/src/d3d9/d3d9_adapter.cpp b/src/d3d9/d3d9_adapter.cpp index faf9a038..f44bab70 100644 --- a/src/d3d9/d3d9_adapter.cpp +++ b/src/d3d9/d3d9_adapter.cpp @@ -134,7 +134,7 @@ namespace dxvk { if (rt && CheckFormat == D3D9Format::A8 && m_parent->GetOptions().disableA8RT) return D3DERR_NOTAVAILABLE; - if (ds && !IsDepthFormat(CheckFormat)) + if (ds && !IsDepthStencilFormat(CheckFormat)) return D3DERR_NOTAVAILABLE; if (rt && CheckFormat == D3D9Format::NULL_FORMAT && twoDimensional) @@ -228,7 +228,7 @@ namespace dxvk { D3D9Format AdapterFormat, D3D9Format RenderTargetFormat, D3D9Format DepthStencilFormat) { - if (!IsDepthFormat(DepthStencilFormat)) + if (!IsDepthStencilFormat(DepthStencilFormat)) return D3DERR_NOTAVAILABLE; auto dsfMapping = GetFormatMapping(DepthStencilFormat); diff --git a/src/d3d9/d3d9_common_texture.cpp b/src/d3d9/d3d9_common_texture.cpp index be7474b5..06587196 100644 --- a/src/d3d9/d3d9_common_texture.cpp +++ b/src/d3d9/d3d9_common_texture.cpp @@ -184,6 +184,17 @@ namespace dxvk { if (pDesc->MipLevels == 0 || pDesc->MipLevels > maxMipLevelCount) pDesc->MipLevels = maxMipLevelCount; + if (unlikely(pDesc->Discard)) { + if (!IsDepthStencilFormat(pDesc->Format)) + return D3DERR_INVALIDCALL; + + if (pDesc->Format == D3D9Format::D32_LOCKABLE + || pDesc->Format == D3D9Format::D32F_LOCKABLE + || pDesc->Format == D3D9Format::D16_LOCKABLE + || pDesc->Format == D3D9Format::S8_LOCKABLE) + return D3DERR_INVALIDCALL; + } + return D3D_OK; } diff --git a/src/d3d9/d3d9_device.cpp b/src/d3d9/d3d9_device.cpp index 48dc9ade..31154dc5 100644 --- a/src/d3d9/d3d9_device.cpp +++ b/src/d3d9/d3d9_device.cpp @@ -1225,10 +1225,10 @@ namespace dxvk { uint32_t(blitInfo.dstOffsets[1].y - blitInfo.dstOffsets[0].y), uint32_t(blitInfo.dstOffsets[1].z - blitInfo.dstOffsets[0].z) }; - bool srcIsDepth = IsDepthFormat(srcFormat); - bool dstIsDepth = IsDepthFormat(dstFormat); - if (unlikely(srcIsDepth || dstIsDepth)) { - if (unlikely(!srcIsDepth || !dstIsDepth)) + bool srcIsDS = IsDepthStencilFormat(srcFormat); + bool dstIsDS = IsDepthStencilFormat(dstFormat); + if (unlikely(srcIsDS || dstIsDS)) { + if (unlikely(!srcIsDS || !dstIsDS)) return D3DERR_INVALIDCALL; if (unlikely(srcTextureInfo->Desc()->Discard || dstTextureInfo->Desc()->Discard)) @@ -1250,7 +1250,7 @@ namespace dxvk { if (unlikely(pSourceSurface == pDestSurface)) return D3DERR_INVALIDCALL; - if (unlikely(dstIsDepth)) + if (unlikely(dstIsDS)) return D3DERR_INVALIDCALL; // The docs say that stretching is only allowed if the destination is either a render target surface or a render target texture. @@ -3950,8 +3950,7 @@ namespace dxvk { desc.MultisampleQuality = MultisampleQuality; desc.IsBackBuffer = FALSE; desc.IsAttachmentOnly = TRUE; - // Docs don't say anything, so just assume it's lockable. - desc.IsLockable = TRUE; + desc.IsLockable = IsLockableDepthStencilFormat(desc.Format); if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(this, D3DRTYPE_TEXTURE, &desc))) return D3DERR_INVALIDCALL; @@ -7977,13 +7976,12 @@ namespace dxvk { desc.Usage = D3DUSAGE_DEPTHSTENCIL; desc.Format = EnumerateFormat(pPresentationParameters->AutoDepthStencilFormat); desc.Pool = D3DPOOL_DEFAULT; - desc.Discard = FALSE; + desc.Discard = (pPresentationParameters->Flags & D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL) != 0; desc.MultiSample = pPresentationParameters->MultiSampleType; desc.MultisampleQuality = pPresentationParameters->MultiSampleQuality; desc.IsBackBuffer = FALSE; desc.IsAttachmentOnly = TRUE; - // Docs: Also note that - unlike textures - swap chain back buffers, render targets [..] can be locked - desc.IsLockable = TRUE; + desc.IsLockable = IsLockableDepthStencilFormat(desc.Format); if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(this, D3DRTYPE_TEXTURE, &desc))) return D3DERR_NOTAVAILABLE; diff --git a/src/d3d9/d3d9_swapchain.cpp b/src/d3d9/d3d9_swapchain.cpp index 3fba731c..d7e43210 100644 --- a/src/d3d9/d3d9_swapchain.cpp +++ b/src/d3d9/d3d9_swapchain.cpp @@ -45,7 +45,7 @@ namespace dxvk { RecreateSwapChain(); } - if (FAILED(CreateBackBuffers(m_presentParams.BackBufferCount))) + if (FAILED(CreateBackBuffers(m_presentParams.BackBufferCount, m_presentParams.Flags))) throw DxvkError("D3D9: Failed to create swapchain backbuffers"); CreateBlitter(); @@ -627,7 +627,7 @@ namespace dxvk { if (changeFullscreen) SetGammaRamp(0, &m_ramp); - hr = CreateBackBuffers(m_presentParams.BackBufferCount); + hr = CreateBackBuffers(m_presentParams.BackBufferCount, m_presentParams.Flags); if (FAILED(hr)) return hr; @@ -1013,7 +1013,7 @@ namespace dxvk { } - HRESULT D3D9SwapChainEx::CreateBackBuffers(uint32_t NumBackBuffers) { + HRESULT D3D9SwapChainEx::CreateBackBuffers(uint32_t NumBackBuffers, DWORD Flags) { // Explicitly destroy current swap image before // creating a new one to free up resources DestroyBackBuffers(); @@ -1038,8 +1038,7 @@ namespace dxvk { desc.Discard = FALSE; desc.IsBackBuffer = TRUE; desc.IsAttachmentOnly = FALSE; - // Docs: Also note that - unlike textures - swap chain back buffers, render targets [..] can be locked - desc.IsLockable = TRUE; + desc.IsLockable = (Flags & D3DPRESENTFLAG_LOCKABLE_BACKBUFFER) != 0; for (uint32_t i = 0; i < NumBuffers; i++) { D3D9Surface* surface; diff --git a/src/d3d9/d3d9_swapchain.h b/src/d3d9/d3d9_swapchain.h index 325ba18a..d2fbd5fe 100644 --- a/src/d3d9/d3d9_swapchain.h +++ b/src/d3d9/d3d9_swapchain.h @@ -205,7 +205,8 @@ namespace dxvk { void CreateRenderTargetViews(); HRESULT CreateBackBuffers( - uint32_t NumBackBuffers); + uint32_t NumBackBuffers, + DWORD Flags); void CreateBlitter(); diff --git a/src/d3d9/d3d9_util.cpp b/src/d3d9/d3d9_util.cpp index 43f68d3e..ba0eaf66 100644 --- a/src/d3d9/d3d9_util.cpp +++ b/src/d3d9/d3d9_util.cpp @@ -420,4 +420,15 @@ namespace dxvk { || Format == D3D9Format::INTZ; } + bool IsDepthStencilFormat(D3D9Format Format) { + return IsDepthFormat(Format) || Format == D3D9Format::S8_LOCKABLE; + } + + bool IsLockableDepthStencilFormat(D3D9Format Format) { + return Format == D3D9Format::S8_LOCKABLE + || Format == D3D9Format::D16_LOCKABLE + || Format == D3D9Format::D32_LOCKABLE + || Format == D3D9Format::D32F_LOCKABLE; + } + } \ No newline at end of file diff --git a/src/d3d9/d3d9_util.h b/src/d3d9/d3d9_util.h index ecd21a3f..0bdfb2b9 100644 --- a/src/d3d9/d3d9_util.h +++ b/src/d3d9/d3d9_util.h @@ -204,6 +204,11 @@ namespace dxvk { bool IsDepthFormat(D3D9Format Format); + bool IsDepthStencilFormat(D3D9Format Format); + + bool IsLockableDepthStencilFormat(D3D9Format Format); + + inline bool IsPoolManaged(D3DPOOL Pool) { return Pool == D3DPOOL_MANAGED || Pool == D3DPOOL_MANAGED_EX; }