From 9373bab3e36d8a4202d27da987ae9c3ad720b50c Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Thu, 9 Aug 2018 23:34:03 +0200 Subject: [PATCH] [d3d11] Validate image view format compatibility correctly Prevents the application from creating illegal image views. --- src/d3d11/d3d11_texture.cpp | 56 ++++++++++++++++++++++++------------- src/d3d11/d3d11_texture.h | 2 +- 2 files changed, 38 insertions(+), 20 deletions(-) diff --git a/src/d3d11/d3d11_texture.cpp b/src/d3d11/d3d11_texture.cpp index b4b5fd86..de7397f7 100644 --- a/src/d3d11/d3d11_texture.cpp +++ b/src/d3d11/d3d11_texture.cpp @@ -205,35 +205,53 @@ namespace dxvk { bool D3D11CommonTexture::CheckViewCompatibility(UINT BindFlags, DXGI_FORMAT Format) const { + const DxvkImageCreateInfo& imageInfo = m_image->info(); + // Check whether the given bind flags are supported VkImageUsageFlags usage = GetImageUsageFlags(BindFlags); - if ((m_image->info().usage & usage) != usage) + if ((imageInfo.usage & usage) != usage) return false; // Check whether the view format is compatible DXGI_VK_FORMAT_MODE formatMode = GetFormatMode(); - DXGI_VK_FORMAT_INFO baseFormat = m_device->LookupFormat(m_desc.Format, formatMode); DXGI_VK_FORMAT_INFO viewFormat = m_device->LookupFormat(Format, formatMode); + DXGI_VK_FORMAT_INFO baseFormat = m_device->LookupFormat(m_desc.Format, formatMode); - // Identical formats always pass this test - if (baseFormat.Format == viewFormat.Format) - return true; - - // The available image aspects must match - auto baseFormatInfo = imageFormatInfo(baseFormat.Format); - auto viewFormatInfo = imageFormatInfo(viewFormat.Format); - - if (baseFormatInfo->aspectMask != viewFormatInfo->aspectMask) + if (imageInfo.flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) { + // Check whether the given combination of image + // view type and view format is actually supported + VkFormatFeatureFlags features = GetImageFormatFeatures(BindFlags); + + if (!CheckFormatFeatureSupport(viewFormat.Format, features)) + return false; + + // Using the image format itself is always legal + if (viewFormat.Format == baseFormat.Format) + return true; + + // If there is a list of compatible formats, the + // view format must be included in that list. + for (size_t i = 0; i < imageInfo.viewFormatCount; i++) { + if (imageInfo.viewFormats[i] == viewFormat.Format) + return true; + } + + // Otherwise, all bit-compatible formats can be used. + if (imageInfo.viewFormatCount == 0) { + auto baseFormatInfo = imageFormatInfo(baseFormat.Format); + auto viewFormatInfo = imageFormatInfo(viewFormat.Format); + + return baseFormatInfo->aspectMask == viewFormatInfo->aspectMask + && baseFormatInfo->elementSize == viewFormatInfo->elementSize; + } + return false; - - // Color formats can be reinterpreted. This is not restricted - // to typeless formats, we we can create SRGB views for UNORM - // textures as well etc. as long as they are bit-compatible. - if (baseFormatInfo->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) - return baseFormatInfo->elementSize == viewFormatInfo->elementSize; - - return false; + } else { + // For non-mutable images, the view format + // must be identical to the image format. + return viewFormat.Format == baseFormat.Format; + } } diff --git a/src/d3d11/d3d11_texture.h b/src/d3d11/d3d11_texture.h index 57a623fe..f6ab879f 100644 --- a/src/d3d11/d3d11_texture.h +++ b/src/d3d11/d3d11_texture.h @@ -195,7 +195,7 @@ namespace dxvk { BOOL CheckFormatFeatureSupport( VkFormat Format, - VkImageUsageFlags Features) const; + VkFormatFeatureFlags Features) const; D3D11_COMMON_TEXTURE_MAP_MODE DetermineMapMode( const DxvkImageCreateInfo* pImageInfo) const;