From 4cdee69bc9b8d52fc778d959239b2489d4aae79e Mon Sep 17 00:00:00 2001 From: Robin Kertels Date: Mon, 10 Jan 2022 18:51:24 +0100 Subject: [PATCH] [d3d9] Always upload all managed texture mips after AddDirtyBox call Co-authored-by: Paul Gofman --- src/d3d9/d3d9_common_texture.h | 3 +++ src/d3d9/d3d9_texture.cpp | 17 +++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/d3d9/d3d9_common_texture.h b/src/d3d9/d3d9_common_texture.h index 3a6ac45e..e3da26fd 100644 --- a/src/d3d9/d3d9_common_texture.h +++ b/src/d3d9/d3d9_common_texture.h @@ -362,6 +362,9 @@ namespace dxvk { bool Srgb); D3D9SubresourceBitset& GetUploadBitmask() { return m_needsUpload; } + void SetAllNeedUpload() { + m_needsUpload.setAll(); + } void SetNeedsUpload(UINT Subresource, bool upload) { m_needsUpload.set(Subresource, upload); } bool NeedsUpload(UINT Subresource) const { return m_needsUpload.get(Subresource); } bool NeedsAnyUpload() { return m_needsUpload.any(); } diff --git a/src/d3d9/d3d9_texture.cpp b/src/d3d9/d3d9_texture.cpp index 2ef86be3..73c4c570 100644 --- a/src/d3d9/d3d9_texture.cpp +++ b/src/d3d9/d3d9_texture.cpp @@ -82,6 +82,11 @@ namespace dxvk { } else { m_texture.AddDirtyBox(nullptr, 0); } + + // Some games keep using the pointer returned in LockRect() after calling Unlock() + // and purely rely on AddDirtyRect to notify D3D9 that contents have changed. + // We have no way of knowing which mip levels were actually changed. + m_texture.SetAllNeedUpload(); return D3D_OK; } @@ -159,6 +164,11 @@ namespace dxvk { HRESULT STDMETHODCALLTYPE D3D9Texture3D::AddDirtyBox(CONST D3DBOX* pDirtyBox) { m_texture.AddDirtyBox(pDirtyBox, 0); + + // Some games keep using the pointer returned in LockBox() after calling Unlock() + // and purely rely on AddDirtyBox to notify D3D9 that contents have changed. + // We have no way of knowing which mip levels were actually changed. + m_texture.SetAllNeedUpload(); return D3D_OK; } @@ -242,6 +252,13 @@ namespace dxvk { } else { m_texture.AddDirtyBox(nullptr, Face); } + + // Some games keep using the pointer returned in LockRect() after calling Unlock() + // and purely rely on AddDirtyRect to notify D3D9 that contents have changed. + // We have no way of knowing which mip levels were actually changed. + for (uint32_t m = 0; m < m_texture.Desc()->MipLevels; m++) { + m_texture.SetNeedsUpload(m_texture.CalcSubresource(Face, m), true); + } return D3D_OK; }