From 2fbf8a509e68cb21fcc1e28f6837d693b82d6edd Mon Sep 17 00:00:00 2001 From: Joshua Ashton Date: Tue, 15 Oct 2019 18:38:41 +0100 Subject: [PATCH] [d3d9] Support unsupported formats for D3DPOOL_SCRATCH Impacts #417 --- src/d3d9/d3d9_adapter.h | 5 +++ src/d3d9/d3d9_common_texture.cpp | 44 ++++++++++++++++++++--- src/d3d9/d3d9_common_texture.h | 4 ++- src/d3d9/d3d9_device.cpp | 62 +++++++++----------------------- src/d3d9/d3d9_device.h | 3 ++ src/d3d9/d3d9_format.cpp | 42 ++++++++++++++++++++++ src/d3d9/d3d9_format.h | 9 +++++ 7 files changed, 118 insertions(+), 51 deletions(-) diff --git a/src/d3d9/d3d9_adapter.h b/src/d3d9/d3d9_adapter.h index ff08885427..991287aec2 100644 --- a/src/d3d9/d3d9_adapter.h +++ b/src/d3d9/d3d9_adapter.h @@ -83,6 +83,11 @@ namespace dxvk { return m_d3d9Formats.GetFormatMapping(Format); } + DxvkFormatInfo GetUnsupportedFormatInfo( + D3D9Format Format) const { + return m_d3d9Formats.GetUnsupportedFormatInfo(Format); + } + private: HRESULT CheckDeviceVkFormat( diff --git a/src/d3d9/d3d9_common_texture.cpp b/src/d3d9/d3d9_common_texture.cpp index fddefc5de2..256cd5571b 100644 --- a/src/d3d9/d3d9_common_texture.cpp +++ b/src/d3d9/d3d9_common_texture.cpp @@ -67,7 +67,39 @@ namespace dxvk { } - HRESULT D3D9CommonTexture::NormalizeTextureProperties(D3D9_COMMON_TEXTURE_DESC* pDesc) { + HRESULT D3D9CommonTexture::NormalizeTextureProperties( + D3D9DeviceEx* pDevice, + D3D9_COMMON_TEXTURE_DESC* pDesc, + D3D9_VK_FORMAT_MAPPING* pMapping) { + auto* options = pDevice->GetOptions(); + + ////////////////////// + // Mapping Validation + + *pMapping = pDevice->LookupFormat(pDesc->Format); + + // Handle DisableA8RT hack for The Sims 2 + if (pDesc->Format == D3D9Format::A8 && + (pDesc->Usage & D3DUSAGE_RENDERTARGET) && + options->disableA8RT) + return D3DERR_INVALIDCALL; + + // If the mapping is invalid then lets return invalid + // Some edge cases: + // NULL format does not map to anything, but should succeed + // SCRATCH textures can still be made if the device does not support + // the format at all. + + if (!pMapping->IsValid() && pDesc->Format != D3D9Format::NULL_FORMAT) { + auto info = pDevice->UnsupportedFormatInfo(pDesc->Format); + + if (pDesc->Pool != D3DPOOL_SCRATCH || info.elementSize == 0) + return D3DERR_INVALIDCALL; + } + + /////////////////// + // Desc Validation + if (pDesc->Width == 0 || pDesc->Height == 0 || pDesc->Depth == 0) return D3DERR_INVALIDCALL; @@ -96,7 +128,7 @@ namespace dxvk { if (pDesc->MipLevels == 0 || pDesc->MipLevels > maxMipLevelCount) pDesc->MipLevels = maxMipLevelCount; - + return D3D_OK; } @@ -135,15 +167,17 @@ namespace dxvk { VkDeviceSize D3D9CommonTexture::GetMipSize(UINT Subresource) const { const UINT MipLevel = Subresource % m_desc.MipLevels; - const DxvkFormatInfo* formatInfo = imageFormatInfo(m_mapping.FormatColor); + const DxvkFormatInfo formatInfo = m_mapping.FormatColor != VK_FORMAT_UNDEFINED + ? *imageFormatInfo(m_mapping.FormatColor) + : m_device->UnsupportedFormatInfo(m_desc.Format); const VkExtent3D mipExtent = util::computeMipLevelExtent( m_adjustedExtent, MipLevel); const VkExtent3D blockCount = util::computeBlockCount( - mipExtent, formatInfo->blockSize); + mipExtent, formatInfo.blockSize); - return formatInfo->elementSize + return formatInfo.elementSize * blockCount.width * blockCount.height * blockCount.depth; diff --git a/src/d3d9/d3d9_common_texture.h b/src/d3d9/d3d9_common_texture.h index 05066ad592..fe22bcea07 100644 --- a/src/d3d9/d3d9_common_texture.h +++ b/src/d3d9/d3d9_common_texture.h @@ -195,7 +195,9 @@ namespace dxvk { * \returns \c S_OK if the parameters are valid */ static HRESULT NormalizeTextureProperties( - D3D9_COMMON_TEXTURE_DESC* pDesc); + D3D9DeviceEx* pDevice, + D3D9_COMMON_TEXTURE_DESC* pDesc, + D3D9_VK_FORMAT_MAPPING* pMapping); /** * \brief Lock Flags diff --git a/src/d3d9/d3d9_device.cpp b/src/d3d9/d3d9_device.cpp index 7cd194b0cc..ee634ee208 100644 --- a/src/d3d9/d3d9_device.cpp +++ b/src/d3d9/d3d9_device.cpp @@ -405,16 +405,8 @@ namespace dxvk { desc.MultiSample = D3DMULTISAMPLE_NONE; desc.MultisampleQuality = 0; - if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(&desc))) - return D3DERR_INVALIDCALL; - - if (desc.Format == D3D9Format::A8 && - (desc.Usage & D3DUSAGE_RENDERTARGET) && - m_d3d9Options.disableA8RT) - return D3DERR_INVALIDCALL; - - auto mapping = LookupFormat(desc.Format); - if (!mapping.IsValid() && desc.Format != D3D9Format::NULL_FORMAT) + D3D9_VK_FORMAT_MAPPING mapping; + if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(this, &desc, &mapping))) return D3DERR_INVALIDCALL; try { @@ -469,11 +461,8 @@ namespace dxvk { desc.MultiSample = D3DMULTISAMPLE_NONE; desc.MultisampleQuality = 0; - if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(&desc))) - return D3DERR_INVALIDCALL; - - auto mapping = LookupFormat(desc.Format); - if (!mapping.IsValid() && desc.Format != D3D9Format::NULL_FORMAT) + D3D9_VK_FORMAT_MAPPING mapping; + if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(this, &desc, &mapping))) return D3DERR_INVALIDCALL; try { @@ -518,11 +507,8 @@ namespace dxvk { desc.MultiSample = D3DMULTISAMPLE_NONE; desc.MultisampleQuality = 0; - if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(&desc))) - return D3DERR_INVALIDCALL; - - auto mapping = LookupFormat(desc.Format); - if (!mapping.IsValid() && desc.Format != D3D9Format::NULL_FORMAT) + D3D9_VK_FORMAT_MAPPING mapping; + if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(this, &desc, &mapping))) return D3DERR_INVALIDCALL; try { @@ -3278,16 +3264,8 @@ namespace dxvk { desc.MultiSample = MultiSample; desc.MultisampleQuality = MultisampleQuality; - if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(&desc))) - return D3DERR_INVALIDCALL; - - if (desc.Format == D3D9Format::A8 && - (desc.Usage & D3DUSAGE_RENDERTARGET) && - m_d3d9Options.disableA8RT) - return D3DERR_INVALIDCALL; - - auto mapping = LookupFormat(desc.Format); - if (!mapping.IsValid() && desc.Format != D3D9Format::NULL_FORMAT) + D3D9_VK_FORMAT_MAPPING mapping; + if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(this, &desc, &mapping))) return D3DERR_INVALIDCALL; try { @@ -3330,16 +3308,8 @@ namespace dxvk { desc.MultiSample = D3DMULTISAMPLE_NONE; desc.MultisampleQuality = 0; - if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(&desc))) - return D3DERR_INVALIDCALL; - - if (desc.Format == D3D9Format::A8 && - (desc.Usage & D3DUSAGE_RENDERTARGET) && - m_d3d9Options.disableA8RT) - return D3DERR_INVALIDCALL; - - auto mapping = LookupFormat(desc.Format); - if (!mapping.IsValid() && desc.Format != D3D9Format::NULL_FORMAT) + D3D9_VK_FORMAT_MAPPING mapping; + if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(this, &desc, &mapping))) return D3DERR_INVALIDCALL; try { @@ -3384,11 +3354,8 @@ namespace dxvk { desc.MultiSample = MultiSample; desc.MultisampleQuality = MultisampleQuality; - if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(&desc))) - return D3DERR_INVALIDCALL; - - auto mapping = LookupFormat(desc.Format); - if (!mapping.IsValid() && desc.Format != D3D9Format::NULL_FORMAT) + D3D9_VK_FORMAT_MAPPING mapping; + if (FAILED(D3D9CommonTexture::NormalizeTextureProperties(this, &desc, &mapping))) return D3DERR_INVALIDCALL; try { @@ -4000,6 +3967,11 @@ namespace dxvk { return m_adapter->GetFormatMapping(Format); } + DxvkFormatInfo D3D9DeviceEx::UnsupportedFormatInfo( + D3D9Format Format) const { + return m_adapter->GetUnsupportedFormatInfo(Format); + } + bool D3D9DeviceEx::WaitForResource( const Rc& Resource, DWORD MapFlags) { diff --git a/src/d3d9/d3d9_device.h b/src/d3d9/d3d9_device.h index ae7701543e..20cc9ada2b 100644 --- a/src/d3d9/d3d9_device.h +++ b/src/d3d9/d3d9_device.h @@ -658,6 +658,9 @@ namespace dxvk { D3D9_VK_FORMAT_MAPPING LookupFormat( D3D9Format Format) const; + DxvkFormatInfo UnsupportedFormatInfo( + D3D9Format Format) const; + bool WaitForResource( const Rc& Resource, DWORD MapFlags); diff --git a/src/d3d9/d3d9_format.cpp b/src/d3d9/d3d9_format.cpp index 5427f6dd4b..380ca6a8a9 100644 --- a/src/d3d9/d3d9_format.cpp +++ b/src/d3d9/d3d9_format.cpp @@ -435,6 +435,48 @@ namespace dxvk { return mapping; } + + + DxvkFormatInfo D3D9VkFormatTable::GetUnsupportedFormatInfo( + D3D9Format Format) const { + switch (Format) { + case D3D9Format::R8G8B8: + return { 3, VK_IMAGE_ASPECT_COLOR_BIT }; + + case D3D9Format::R3G3B2: + return { 1, VK_IMAGE_ASPECT_COLOR_BIT }; + + case D3D9Format::A8R3G3B2: + return { 2, VK_IMAGE_ASPECT_COLOR_BIT }; + + case D3D9Format::A8P8: + return { 2, VK_IMAGE_ASPECT_COLOR_BIT }; + + case D3D9Format::P8: + return { 1, VK_IMAGE_ASPECT_COLOR_BIT }; + + case D3D9Format::L6V5U5: + return { 2, VK_IMAGE_ASPECT_COLOR_BIT }; + + case D3D9Format::X8L8V8U8: + return { 4, VK_IMAGE_ASPECT_COLOR_BIT }; + + case D3D9Format::A2W10V10U10: + return { 4, VK_IMAGE_ASPECT_COLOR_BIT }; + + // MULTI2_ARGB8 -> Don't have a clue what this is. + + case D3D9Format::CxV8U8: + return { 2, VK_IMAGE_ASPECT_COLOR_BIT }; + + // A1 -> Doesn't map nicely here cause it's not byte aligned. + // Gonna just pretend that doesn't exist until something + // depends on that. + + default: + return {}; + } + } bool D3D9VkFormatTable::CheckImageFormatSupport( diff --git a/src/d3d9/d3d9_format.h b/src/d3d9/d3d9_format.h index ec8f5b65d0..0118b319a3 100644 --- a/src/d3d9/d3d9_format.h +++ b/src/d3d9/d3d9_format.h @@ -188,6 +188,15 @@ namespace dxvk { D3D9_VK_FORMAT_MAPPING GetFormatMapping( D3D9Format Format) const; + /** + * \brief Retrieves format info for unsupported + * formats. + * + * \param [in] Format The D3D9 format to look up + */ + DxvkFormatInfo GetUnsupportedFormatInfo( + D3D9Format Format) const; + private: bool CheckImageFormatSupport(