From a7ae5999a962004fe477fd4f0abdf066e3c768d2 Mon Sep 17 00:00:00 2001 From: Robin Kertels Date: Mon, 8 Jul 2024 23:55:44 +0200 Subject: [PATCH] [d3d8] Slightly clean up CopyRects --- src/d3d8/d3d8_device.cpp | 122 ++++++++++++++++++--------------------- src/d3d9/d3d9_bridge.h | 4 +- 2 files changed, 56 insertions(+), 70 deletions(-) diff --git a/src/d3d8/d3d8_device.cpp b/src/d3d8/d3d8_device.cpp index 61be21e1d..a2b958942 100644 --- a/src/d3d8/d3d8_device.cpp +++ b/src/d3d8/d3d8_device.cpp @@ -562,11 +562,11 @@ namespace dxvk { /** * \brief D3D8 CopyRects implementation - * + * * \details * The following table shows the possible combinations of source * and destination surface pools, and how we handle each of them. - * + * * ┌────────────┬───────────────────────────┬───────────────────────┬───────────────────────┬──────────┐ * │ Src/Dst │ DEFAULT │ MANAGED │ SYSTEMMEM │ SCRATCH │ * ├────────────┼───────────────────────────┼───────────────────────┼───────────────────────┼──────────┤ @@ -587,7 +587,7 @@ namespace dxvk { } // TODO: No format conversion, no stretching, no clipping. - // All src/dest rectangles must fit within the dest surface. + // All src/dest rectangles must fit within the dest surface. Com src = static_cast(pSourceSurface); Com dst = static_cast(pDestinationSurface); @@ -618,8 +618,6 @@ namespace dxvk { pDestPointsArray = &point; } - HRESULT res = D3DERR_INVALIDCALL; - for (UINT i = 0; i < cRects; i++) { RECT srcRect, dstRect; @@ -639,10 +637,10 @@ namespace dxvk { dstRect.bottom = dstRect.top + (srcRect.bottom - srcRect.top); asymmetric = dstRect.left != srcRect.left || dstRect.top != srcRect.top || dstRect.right != srcRect.right || dstRect.bottom != srcRect.bottom; - + stretch = (dstRect.right-dstRect.left) != (srcRect.right-srcRect.left) || (dstRect.bottom-dstRect.top) != (srcRect.bottom-srcRect.top); - + offset = !stretch && asymmetric; } else { dstRect = srcRect; @@ -651,102 +649,103 @@ namespace dxvk { POINT dstPt = { dstRect.left, dstRect.top }; - res = D3DERR_INVALIDCALL; - auto unhandled = [&] { - Logger::debug(str::format("CopyRects: Hit unhandled case from src pool ", srcDesc.Pool, " to dst pool ", dstDesc.Pool)); + Logger::warn(str::format("CopyRects: Hit unhandled case from src pool ", srcDesc.Pool, " to dst pool ", dstDesc.Pool)); return D3DERR_INVALIDCALL; }; + auto logError = [&] (HRESULT res) { + if (FAILED(res)) { + // Only a debug message because some games mess up CopyRects every frame in a way + // that fails on native too but are perfectly fine with it. + Logger::debug(str::format("CopyRects: FAILED to copy from src pool ", srcDesc.Pool, " to dst pool ", dstDesc.Pool)); + } + return res; + }; + switch (dstDesc.Pool) { - + // Dest: DEFAULT - case D3DPOOL_DEFAULT: + case d3d9::D3DPOOL_DEFAULT: switch (srcDesc.Pool) { - case D3DPOOL_DEFAULT: { + case d3d9::D3DPOOL_DEFAULT: { // DEFAULT -> DEFAULT: use StretchRect - res = GetD3D9()->StretchRect( + return logError(GetD3D9()->StretchRect( src->GetD3D9(), &srcRect, dst->GetD3D9(), &dstRect, d3d9::D3DTEXF_NONE - ); - goto done; + )); } - case D3DPOOL_MANAGED: { + case d3d9::D3DPOOL_MANAGED: { // MANAGED -> DEFAULT: UpdateTextureFromBuffer - res = m_bridge->UpdateTextureFromBuffer( + return logError(m_bridge->UpdateTextureFromBuffer( src->GetD3D9(), dst->GetD3D9(), &srcRect, &dstPt - ); - goto done; + )); } - case D3DPOOL_SYSTEMMEM: { + case d3d9::D3DPOOL_SYSTEMMEM: { // SYSTEMMEM -> DEFAULT: use UpdateSurface - res = GetD3D9()->UpdateSurface( + return logError(GetD3D9()->UpdateSurface( src->GetD3D9(), &srcRect, dst->GetD3D9(), &dstPt - ); - goto done; + )); } - case D3DPOOL_SCRATCH: + case d3d9::D3DPOOL_SCRATCH: default: { // TODO: Unhandled case. return unhandled(); } } break; - + // Dest: MANAGED - case D3DPOOL_MANAGED: + case d3d9::D3DPOOL_MANAGED: switch (srcDesc.Pool) { - case D3DPOOL_DEFAULT: { + case d3d9::D3DPOOL_DEFAULT: { // TODO: Copy on GPU (handle MANAGED similarly to SYSTEMMEM for now) - + // Get temporary off-screen surface for stretching. Com pBlitImage = dst->GetBlitImage(); // Stretch the source RT to the temporary surface. - res = GetD3D9()->StretchRect( + HRESULT res = GetD3D9()->StretchRect( src->GetD3D9(), &srcRect, pBlitImage.ptr(), &dstRect, d3d9::D3DTEXF_NONE); + if (FAILED(res)) { - goto done; + return logError(res); } // Now sync the rendertarget data into main memory. - res = GetD3D9()->GetRenderTargetData(pBlitImage.ptr(), dst->GetD3D9()); - goto done; + return logError(GetD3D9()->GetRenderTargetData(pBlitImage.ptr(), dst->GetD3D9())); } - case D3DPOOL_MANAGED: - case D3DPOOL_SYSTEMMEM: { + case d3d9::D3DPOOL_MANAGED: + case d3d9::D3DPOOL_SYSTEMMEM: { // SYSTEMMEM -> MANAGED: LockRect / memcpy - + if (stretch) { - res = D3DERR_INVALIDCALL; - goto done; + return logError(D3DERR_INVALIDCALL); } - res = copyTextureBuffers(src.ptr(), dst.ptr(), srcDesc, dstDesc, srcRect, dstRect); - - goto done; + return logError(copyTextureBuffers(src.ptr(), dst.ptr(), srcDesc, dstDesc, srcRect, dstRect)); } - case D3DPOOL_SCRATCH: + case d3d9::D3DPOOL_SCRATCH: default: { // TODO: Unhandled case. return unhandled(); } } break; - + // DEST: SYSTEMMEM - case D3DPOOL_SYSTEMMEM: { + case d3d9::D3DPOOL_SYSTEMMEM: { // RT (DEFAULT) -> SYSTEMMEM: Use GetRenderTargetData as fast path if possible if ((srcDesc.Usage & D3DUSAGE_RENDERTARGET || m_renderTarget.ptr() == src.ptr())) { @@ -757,44 +756,40 @@ namespace dxvk { && srcDesc.Height == dstDesc.Height && srcDesc.Format == dstDesc.Format && !asymmetric) { - res = GetD3D9()->GetRenderTargetData(src->GetD3D9(), dst->GetD3D9()); - goto done; + return logError(GetD3D9()->GetRenderTargetData(src->GetD3D9(), dst->GetD3D9())); } } switch (srcDesc.Pool) { - case D3DPOOL_DEFAULT: { + case d3d9::D3DPOOL_DEFAULT: { // Get temporary off-screen surface for stretching. Com pBlitImage = dst->GetBlitImage(); // Stretch the source RT to the temporary surface. - res = GetD3D9()->StretchRect( + HRESULT res = GetD3D9()->StretchRect( src->GetD3D9(), &srcRect, pBlitImage.ptr(), &dstRect, d3d9::D3DTEXF_NONE); if (FAILED(res)) { - goto done; + return logError(res); } // Now sync the rendertarget data into main memory. - res = GetD3D9()->GetRenderTargetData(pBlitImage.ptr(), dst->GetD3D9()); - goto done; + return logError(GetD3D9()->GetRenderTargetData(pBlitImage.ptr(), dst->GetD3D9())); } // SYSMEM/MANAGED -> SYSMEM: LockRect / memcpy - case D3DPOOL_MANAGED: - case D3DPOOL_SYSTEMMEM: { + case d3d9::D3DPOOL_MANAGED: + case d3d9::D3DPOOL_SYSTEMMEM: { if (stretch) { - res = D3DERR_INVALIDCALL; - goto done; + return logError(D3DERR_INVALIDCALL); } - res = copyTextureBuffers(src.ptr(), dst.ptr(), srcDesc, dstDesc, srcRect, dstRect); - goto done; + return logError(copyTextureBuffers(src.ptr(), dst.ptr(), srcDesc, dstDesc, srcRect, dstRect)); } - case D3DPOOL_SCRATCH: + case d3d9::D3DPOOL_SCRATCH: default: { // TODO: Unhandled case. return unhandled(); @@ -803,22 +798,15 @@ namespace dxvk { } // DEST: SCRATCH - case D3DPOOL_SCRATCH: + case d3d9::D3DPOOL_SCRATCH: default: { // TODO: Unhandled case. return unhandled(); } } - - done: - if (FAILED(res)) { - Logger::debug(str::format("CopyRects: FAILED to copy from src pool ", srcDesc.Pool, " to dst pool ", dstDesc.Pool)); - return res; - } - } - return res; + return D3DERR_INVALIDCALL; } HRESULT STDMETHODCALLTYPE D3D8Device::UpdateTexture( diff --git a/src/d3d9/d3d9_bridge.h b/src/d3d9/d3d9_bridge.h index 7ed00a750..5887fa678 100644 --- a/src/d3d9/d3d9_bridge.h +++ b/src/d3d9/d3d9_bridge.h @@ -3,8 +3,6 @@ #include #include "../util/config/config.h" -#include "../vulkan/vulkan_loader.h" - /** * The D3D9 bridge allows D3D8 to access DXVK internals. * For Vulkan interop without needing DXVK internals, see d3d9_interop.h. @@ -111,7 +109,7 @@ namespace dxvk { void** ppvObject); const Config* GetConfig() const; - + protected: D3D9InterfaceEx* m_interface; };