diff --git a/src/d3d9/d3d9_common_texture.cpp b/src/d3d9/d3d9_common_texture.cpp index 9b6e1ba37..cd29209de 100644 --- a/src/d3d9/d3d9_common_texture.cpp +++ b/src/d3d9/d3d9_common_texture.cpp @@ -156,6 +156,16 @@ namespace dxvk { if (pDesc->Width == 0 || pDesc->Height == 0 || pDesc->Depth == 0) return D3DERR_INVALIDCALL; + + // Native drivers won't allow the creation of DXT format + // textures that aren't aligned to block dimensions. + if (IsDXTFormat(pDesc->Format)) { + D3D9_FORMAT_BLOCK_SIZE blockSize = GetFormatBlockSize(pDesc->Format); + + if ((blockSize.Width && (pDesc->Width & (blockSize.Width - 1))) + || (blockSize.Height && (pDesc->Height & (blockSize.Height - 1)))) + return D3DERR_INVALIDCALL; + } if (FAILED(DecodeMultiSampleType(pDevice->GetDXVKDevice(), pDesc->MultiSample, pDesc->MultisampleQuality, nullptr))) return D3DERR_INVALIDCALL; diff --git a/src/d3d9/d3d9_format.cpp b/src/d3d9/d3d9_format.cpp index d094b03de..544ecdb4f 100644 --- a/src/d3d9/d3d9_format.cpp +++ b/src/d3d9/d3d9_format.cpp @@ -439,6 +439,27 @@ namespace dxvk { } } + // Block size of formats that require some form of alignment + D3D9_FORMAT_BLOCK_SIZE GetFormatBlockSize(D3D9Format Format) { + switch (Format) { + case D3D9Format::DXT1: + case D3D9Format::DXT2: + case D3D9Format::DXT3: + case D3D9Format::DXT4: + case D3D9Format::DXT5: + case D3D9Format::ATI1: + case D3D9Format::ATI2: + return { 4, 4, 1 }; + + case D3D9Format::YUY2: + case D3D9Format::UYVY: + return { 2, 1, 1 }; + + default: + return {}; // Irrelevant or unknown block size + } + } + D3D9VkFormatTable::D3D9VkFormatTable( const Rc& adapter, const D3D9Options& options) { diff --git a/src/d3d9/d3d9_format.h b/src/d3d9/d3d9_format.h index 4efbd07df..fd4da88ae 100644 --- a/src/d3d9/d3d9_format.h +++ b/src/d3d9/d3d9_format.h @@ -147,6 +147,12 @@ namespace dxvk { VkFormat FormatSrgb = VK_FORMAT_UNDEFINED; }; + struct D3D9_FORMAT_BLOCK_SIZE { + uint8_t Width = 0; + uint8_t Height = 0; + uint8_t Depth = 0; + }; + /** * \brief Format mapping * @@ -171,6 +177,8 @@ namespace dxvk { D3D9_VK_FORMAT_MAPPING ConvertFormatUnfixed(D3D9Format Format); + D3D9_FORMAT_BLOCK_SIZE GetFormatBlockSize(D3D9Format Format); + /** * \brief Format table * @@ -239,4 +247,12 @@ namespace dxvk { && format != D3D9Format::DXT5; } + inline bool IsDXTFormat(D3D9Format format) { + return format == D3D9Format::DXT1 + || format == D3D9Format::DXT2 + || format == D3D9Format::DXT3 + || format == D3D9Format::DXT4 + || format == D3D9Format::DXT5; + } + }