From b06eb4fe2a2a0d4e20cb394395f386851a4fd29b Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Thu, 9 Aug 2018 21:58:58 +0200 Subject: [PATCH] [d3d11] Validate image view bind flags Since the bind flags of the texture may not always match the image usage flags of the underlying Vulkan image, we should use the latter to check whether a view can be created. --- src/d3d11/d3d11_device.cpp | 48 +++--------------------------------- src/d3d11/d3d11_resource.cpp | 15 +++-------- src/d3d11/d3d11_resource.h | 18 ++------------ src/d3d11/d3d11_texture.cpp | 11 +++++++-- src/d3d11/d3d11_texture.h | 10 +++++--- 5 files changed, 25 insertions(+), 77 deletions(-) diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp index 3e8b66c57..2f17803be 100644 --- a/src/d3d11/d3d11_device.cpp +++ b/src/d3d11/d3d11_device.cpp @@ -288,19 +288,9 @@ namespace dxvk { return E_INVALIDARG; } - // Check whether SRVs are supported for the resource at all - if (!CheckResourceBindFlags(pResource, D3D11_BIND_SHADER_RESOURCE)) { - Logger::err("D3D11: Trying to create SRV for texture without D3D11_BIND_SHADER_RESOURCE"); + if (!CheckResourceViewCompatibility(pResource, D3D11_BIND_SHADER_RESOURCE, desc.Format)) return E_INVALIDARG; - } - // Check whether we can use the requested format for the view - if (!CheckResourceViewFormatCompatibility(pResource, desc.Format)) { - Logger::err(str::format("D3D11: Incompatible SRV format: ", desc.Format)); - return E_INVALIDARG; - } - - // Create the actual view if requested if (ppSRView == nullptr) return S_FALSE; @@ -337,19 +327,9 @@ namespace dxvk { return E_INVALIDARG; } - // Check whether UAVs are supported for the resource at all - if (!CheckResourceBindFlags(pResource, D3D11_BIND_UNORDERED_ACCESS)) { - Logger::err("D3D11: Trying to create UAV for texture without D3D11_BIND_UNORDERED_ACCESS"); + if (!CheckResourceViewCompatibility(pResource, D3D11_BIND_UNORDERED_ACCESS, desc.Format)) return E_INVALIDARG; - } - - // Check whether we can use the requested format for the view - if (!CheckResourceViewFormatCompatibility(pResource, desc.Format)) { - Logger::err(str::format("D3D11: Incompatible UAV format: ", desc.Format)); - return E_INVALIDARG; - } - // Create the view if requested if (ppUAView == nullptr) return S_FALSE; @@ -392,19 +372,9 @@ namespace dxvk { return E_INVALIDARG; } - // Check whether UAVs are supported for the resource at all - if (!CheckResourceBindFlags(pResource, D3D11_BIND_RENDER_TARGET)) { - Logger::err("D3D11: Trying to create RTV for texture without D3D11_BIND_RENDER_TARGET"); + if (!CheckResourceViewCompatibility(pResource, D3D11_BIND_RENDER_TARGET, desc.Format)) return E_INVALIDARG; - } - - // Check whether we can use the requested format for the view - if (!CheckResourceViewFormatCompatibility(pResource, desc.Format)) { - Logger::err(str::format("D3D11: Incompatible RTV format: ", desc.Format)); - return E_INVALIDARG; - } - // Create the actual image view if requested if (ppRTView == nullptr) return S_FALSE; @@ -438,19 +408,9 @@ namespace dxvk { return E_INVALIDARG; } - // Check whether DSVs are supported for the resource at all - if (!CheckResourceBindFlags(pResource, D3D11_BIND_DEPTH_STENCIL)) { - Logger::warn("D3D11: Trying to create DSV for texture without D3D11_BIND_DEPTH_STENCIL"); + if (!CheckResourceViewCompatibility(pResource, D3D11_BIND_DEPTH_STENCIL, desc.Format)) return E_INVALIDARG; - } - // Check whether we can use the requested format for the view - if (!CheckResourceViewFormatCompatibility(pResource, desc.Format)) { - Logger::err(str::format("D3D11: Incompatible DSV format: ", desc.Format)); - return E_INVALIDARG; - } - - // Create the actual image view if requested if (ppDepthStencilView == nullptr) return S_FALSE; diff --git a/src/d3d11/d3d11_resource.cpp b/src/d3d11/d3d11_resource.cpp index 55899c7c5..f91130720 100644 --- a/src/d3d11/d3d11_resource.cpp +++ b/src/d3d11/d3d11_resource.cpp @@ -30,23 +30,14 @@ namespace dxvk { } - BOOL CheckResourceBindFlags( - ID3D11Resource* pResource, - UINT BindFlags) { - D3D11_COMMON_RESOURCE_DESC desc; - GetCommonResourceDesc(pResource, &desc); - - return (desc.BindFlags & BindFlags) == BindFlags; - } - - - BOOL CheckResourceViewFormatCompatibility( + BOOL CheckResourceViewCompatibility( ID3D11Resource* pResource, + UINT BindFlags, DXGI_FORMAT Format) { auto texture = GetCommonTexture(pResource); return texture != nullptr - ? texture->CheckViewFormatCompatibility(Format) + ? texture->CheckViewCompatibility(BindFlags, Format) : true; /* for buffers */ } diff --git a/src/d3d11/d3d11_resource.h b/src/d3d11/d3d11_resource.h index e20f2ff4e..b2a1a7168 100644 --- a/src/d3d11/d3d11_resource.h +++ b/src/d3d11/d3d11_resource.h @@ -31,21 +31,6 @@ namespace dxvk { ID3D11Resource* pResource, D3D11_COMMON_RESOURCE_DESC* pDesc); - /** - * \brief Checks whether a resource has the given bind flags - * - * Convenience method that checks whether a resource - * was created with \c all the specified bind flags - * set. Can be used to check whether a specific type - * of view can be created for this resource. - * \param [in] pResource The resource to check - * \param [in] BindFlags Bind flags to check - * \returns \c true if the resource supports the flags - */ - BOOL CheckResourceBindFlags( - ID3D11Resource* pResource, - UINT BindFlags); - /** * \brief Checks whether a format can be used to view a resource * @@ -56,8 +41,9 @@ namespace dxvk { * \param [in] Format The desired view format * \returns \c true if the format is compatible */ - BOOL CheckResourceViewFormatCompatibility( + BOOL CheckResourceViewCompatibility( ID3D11Resource* pResource, + UINT BindFlags, DXGI_FORMAT Format); /** diff --git a/src/d3d11/d3d11_texture.cpp b/src/d3d11/d3d11_texture.cpp index 8a7f8287e..b4b5fd866 100644 --- a/src/d3d11/d3d11_texture.cpp +++ b/src/d3d11/d3d11_texture.cpp @@ -204,10 +204,17 @@ namespace dxvk { } - bool D3D11CommonTexture::CheckViewFormatCompatibility(DXGI_FORMAT Format) const { + bool D3D11CommonTexture::CheckViewCompatibility(UINT BindFlags, DXGI_FORMAT Format) const { + // Check whether the given bind flags are supported + VkImageUsageFlags usage = GetImageUsageFlags(BindFlags); + + if ((m_image->info().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 viewFormat = m_device->LookupFormat(Format, formatMode); // Identical formats always pass this test if (baseFormat.Format == viewFormat.Format) diff --git a/src/d3d11/d3d11_texture.h b/src/d3d11/d3d11_texture.h index 2d6411da6..57a623fef 100644 --- a/src/d3d11/d3d11_texture.h +++ b/src/d3d11/d3d11_texture.h @@ -149,15 +149,19 @@ namespace dxvk { void GetDevice(ID3D11Device** ppDevice) const; /** - * \brief Checks whether a format can be used to view this textue + * \brief Checks whether a view can be created for 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. + * format must be typeless and the view format must be typed. This + * will also check whether the required bind flags are supported. + * \param [in] BindFlags Bind flags for the view * \param [in] Format The desired view format * \returns \c true if the format is compatible */ - bool CheckViewFormatCompatibility(DXGI_FORMAT Format) const; + bool CheckViewCompatibility( + UINT BindFlags, + DXGI_FORMAT Format) const; /** * \brief Normalizes and validates texture description