From 81778981513c57e234a51a5dda4e50c9c9a7058d Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sat, 5 May 2018 15:13:35 +0200 Subject: [PATCH] [d3d11] Validate image view format compatibility Fixes Vulkan validation errors in Far Cry 5. --- src/d3d11/d3d11_device.cpp | 34 +++++++++++++++++++++++++++++++++- src/d3d11/d3d11_texture.cpp | 19 +++++++++++++++++++ src/d3d11/d3d11_texture.h | 11 +++++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp index 4a885c8b..57a71b0b 100644 --- a/src/d3d11/d3d11_device.cpp +++ b/src/d3d11/d3d11_device.cpp @@ -360,7 +360,15 @@ namespace dxvk { const D3D11CommonTexture* textureInfo = GetCommonTexture(pResource); if ((textureInfo->Desc()->BindFlags & D3D11_BIND_SHADER_RESOURCE) == 0) { - Logger::warn("D3D11: Trying to create SRV for texture without D3D11_BIND_SHADER_RESOURCE"); + Logger::err("D3D11: Trying to create SRV for texture without D3D11_BIND_SHADER_RESOURCE"); + return E_INVALIDARG; + } + + // Check whether we can use the requested format for the view + if (!textureInfo->CheckViewFormatCompatibility(desc.Format)) { + Logger::err(str::format("D3D11: Incompatible SRV formats", + "\n Base format: ", textureInfo->Desc()->Format, + "\n View format: ", desc.Format)); return E_INVALIDARG; } @@ -567,6 +575,14 @@ namespace dxvk { return E_INVALIDARG; } + // Check whether we can use the requested format for the view + if (!textureInfo->CheckViewFormatCompatibility(desc.Format)) { + Logger::err(str::format("D3D11: Incompatible UAV formats", + "\n Base format: ", textureInfo->Desc()->Format, + "\n View format: ", desc.Format)); + return E_INVALIDARG; + } + // Fill in the view info. The view type depends solely // on the view dimension field in the view description, // not on the resource type. @@ -687,6 +703,14 @@ namespace dxvk { return E_INVALIDARG; } + // Check whether we can use the requested format for the view + if (!textureInfo->CheckViewFormatCompatibility(desc.Format)) { + Logger::err(str::format("D3D11: Incompatible RTV formats", + "\n Base format: ", textureInfo->Desc()->Format, + "\n View format: ", desc.Format)); + return E_INVALIDARG; + } + // Fill in Vulkan image view info DxvkImageViewCreateInfo viewInfo; viewInfo.format = m_dxgiAdapter->LookupFormat(desc.Format, DXGI_VK_FORMAT_MODE_COLOR).Format; @@ -805,6 +829,14 @@ namespace dxvk { return E_INVALIDARG; } + // Check whether we can use the requested format for the view + if (!textureInfo->CheckViewFormatCompatibility(desc.Format)) { + Logger::err(str::format("D3D11: Incompatible DSV formats", + "\n Base format: ", textureInfo->Desc()->Format, + "\n View format: ", desc.Format)); + return E_INVALIDARG; + } + // Fill in Vulkan image view info DxvkImageViewCreateInfo viewInfo; viewInfo.format = m_dxgiAdapter->LookupFormat(desc.Format, DXGI_VK_FORMAT_MODE_DEPTH).Format; diff --git a/src/d3d11/d3d11_texture.cpp b/src/d3d11/d3d11_texture.cpp index 59c27f89..830948d7 100644 --- a/src/d3d11/d3d11_texture.cpp +++ b/src/d3d11/d3d11_texture.cpp @@ -166,6 +166,25 @@ namespace dxvk { } + bool D3D11CommonTexture::CheckViewFormatCompatibility(DXGI_FORMAT Format) const { + DXGI_VK_FORMAT_MAPPING baseFormat = m_device->GetFormatMapping(m_desc.Format); + DXGI_VK_FORMAT_MAPPING viewFormat = m_device->GetFormatMapping(Format); + + // The view format cannot be typeless + if (Format == viewFormat.FormatFamily) + return false; + + // If the resource is strongly typed, the view + // format must be identical to the base format. + if (m_desc.Format != baseFormat.FormatFamily) + return Format == m_desc.Format; + + // If the resource is typeless, the view format + // must be part of the same format family. + return viewFormat.FormatFamily == baseFormat.FormatFamily; + } + + HRESULT D3D11CommonTexture::NormalizeTextureProperties(D3D11_COMMON_TEXTURE_DESC* pDesc) { if (FAILED(DecodeSampleCount(pDesc->SampleDesc.Count, nullptr))) return E_INVALIDARG; diff --git a/src/d3d11/d3d11_texture.h b/src/d3d11/d3d11_texture.h index 0d0ace57..9f6f8d25 100644 --- a/src/d3d11/d3d11_texture.h +++ b/src/d3d11/d3d11_texture.h @@ -148,6 +148,17 @@ namespace dxvk { */ void GetDevice(ID3D11Device** ppDevice) const; + /** + * \brief Checks whether a format can be used to view this textue + * + * View formats are only compatible if they are either identical + * or from the same family of typeless formats, where the resource + * format must be typeless and the view format must be typed. + * \param [in] Format The desired view format + * \returns \c true if the format is compatible + */ + bool CheckViewFormatCompatibility(DXGI_FORMAT Format) const; + /** * \brief Normalizes and validates texture description *