diff --git a/src/d3d9/d3d9_common_texture.h b/src/d3d9/d3d9_common_texture.h index fcd9f2a0..cc27bcd2 100644 --- a/src/d3d9/d3d9_common_texture.h +++ b/src/d3d9/d3d9_common_texture.h @@ -47,6 +47,7 @@ namespace dxvk { bool Discard; bool IsBackBuffer; bool IsAttachmentOnly; + bool IsLockable; }; struct D3D9ColorView { diff --git a/src/d3d9/d3d9_device.cpp b/src/d3d9/d3d9_device.cpp index 93da5ce3..f35dcc72 100644 --- a/src/d3d9/d3d9_device.cpp +++ b/src/d3d9/d3d9_device.cpp @@ -482,6 +482,12 @@ namespace dxvk { desc.MultisampleQuality = 0; desc.IsBackBuffer = FALSE; desc.IsAttachmentOnly = FALSE; + // Docs: + // Textures placed in the D3DPOOL_DEFAULT pool cannot be locked + // unless they are dynamic textures or they are private, FOURCC, driver formats. + desc.IsLockable = Pool != D3DPOOL_DEFAULT + || (Usage & D3DUSAGE_DYNAMIC) + || IsVendorFormat(EnumerateFormat(Format)); if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(this, &desc))) return D3DERR_INVALIDCALL; @@ -543,6 +549,12 @@ namespace dxvk { desc.MultisampleQuality = 0; desc.IsBackBuffer = FALSE; desc.IsAttachmentOnly = FALSE; + // Docs: + // Textures placed in the D3DPOOL_DEFAULT pool cannot be locked + // unless they are dynamic textures or they are private, FOURCC, driver formats. + desc.IsLockable = Pool != D3DPOOL_DEFAULT + || (Usage & D3DUSAGE_DYNAMIC) + || IsVendorFormat(EnumerateFormat(Format)); if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(this, &desc))) return D3DERR_INVALIDCALL; @@ -591,6 +603,12 @@ namespace dxvk { desc.MultisampleQuality = 0; desc.IsBackBuffer = FALSE; desc.IsAttachmentOnly = FALSE; + // Docs: + // Textures placed in the D3DPOOL_DEFAULT pool cannot be locked + // unless they are dynamic textures or they are private, FOURCC, driver formats. + desc.IsLockable = Pool != D3DPOOL_DEFAULT + || (Usage & D3DUSAGE_DYNAMIC) + || IsVendorFormat(EnumerateFormat(Format)); if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(this, &desc))) return D3DERR_INVALIDCALL; @@ -3539,6 +3557,7 @@ namespace dxvk { desc.MultisampleQuality = MultisampleQuality; desc.IsBackBuffer = FALSE; desc.IsAttachmentOnly = TRUE; + desc.IsLockable = Lockable; if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(this, &desc))) return D3DERR_INVALIDCALL; @@ -3583,6 +3602,8 @@ namespace dxvk { desc.MultisampleQuality = 0; desc.IsBackBuffer = FALSE; desc.IsAttachmentOnly = Pool == D3DPOOL_DEFAULT; + // Docs: Off-screen plain surfaces are always lockable, regardless of their pool types. + desc.IsLockable = TRUE; if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(this, &desc))) return D3DERR_INVALIDCALL; @@ -3632,6 +3653,8 @@ 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; if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(this, &desc))) return D3DERR_INVALIDCALL; @@ -4243,13 +4266,7 @@ namespace dxvk { auto& desc = *(pResource->Desc()); - // MSDN: - // Textures placed in the D3DPOOL_DEFAULT pool cannot be locked - // unless they are dynamic textures or they are private, FOURCC, driver formats. - // Also note that - unlike textures - swap chain back buffers, render targets [..] can be locked - if (unlikely(desc.Pool == D3DPOOL_DEFAULT - && !(desc.Usage & (D3DUSAGE_DYNAMIC | D3DUSAGE_RENDERTARGET | D3DUSAGE_DEPTHSTENCIL)) - && !IsFourCCFormat(desc.Format))) + if (unlikely(!desc.IsLockable)) return D3DERR_INVALIDCALL; auto& formatMapping = pResource->GetFormatMapping(); @@ -7311,6 +7328,8 @@ namespace dxvk { 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; if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(this, &desc))) return D3DERR_NOTAVAILABLE; diff --git a/src/d3d9/d3d9_format.h b/src/d3d9/d3d9_format.h index b09b9d46..c38f6fe4 100644 --- a/src/d3d9/d3d9_format.h +++ b/src/d3d9/d3d9_format.h @@ -226,4 +226,17 @@ namespace dxvk { return format > D3D9Format::BINARYBUFFER; } + inline bool IsVendorFormat(D3D9Format format) { + return IsFourCCFormat(format) + && format != D3D9Format::MULTI2_ARGB8 + && format != D3D9Format::UYVY + && format != D3D9Format::R8G8_B8G8 + && format != D3D9Format::G8R8_G8B8 + && format != D3D9Format::DXT1 + && format != D3D9Format::DXT2 + && format != D3D9Format::DXT3 + && format != D3D9Format::DXT4 + && format != D3D9Format::DXT5; + } + } diff --git a/src/d3d9/d3d9_swapchain.cpp b/src/d3d9/d3d9_swapchain.cpp index 807740e7..e01c8041 100644 --- a/src/d3d9/d3d9_swapchain.cpp +++ b/src/d3d9/d3d9_swapchain.cpp @@ -897,6 +897,8 @@ 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; for (uint32_t i = 0; i < m_backBuffers.size(); i++) m_backBuffers[i] = new D3D9Surface(m_parent, &desc, this, nullptr);