diff --git a/src/d3d11/d3d11_device.cpp b/src/d3d11/d3d11_device.cpp index db7f1516..6fb7d3a4 100644 --- a/src/d3d11/d3d11_device.cpp +++ b/src/d3d11/d3d11_device.cpp @@ -299,8 +299,10 @@ namespace dxvk { ID3D11ShaderResourceView** ppSRView) { InitReturnPtr(ppSRView); + uint32_t plane = GetViewPlaneIndex(pResource, pDesc ? pDesc->Format : DXGI_FORMAT_UNKNOWN); + D3D11_SHADER_RESOURCE_VIEW_DESC1 desc = pDesc - ? D3D11ShaderResourceView::PromoteDesc(pDesc) + ? D3D11ShaderResourceView::PromoteDesc(pDesc, plane) : D3D11_SHADER_RESOURCE_VIEW_DESC1(); ID3D11ShaderResourceView1* view = nullptr; @@ -342,13 +344,16 @@ namespace dxvk { if (FAILED(D3D11ShaderResourceView::NormalizeDesc(pResource, &desc))) return E_INVALIDARG; } + + uint32_t plane = D3D11ShaderResourceView::GetPlaneSlice(&desc); - if (!CheckResourceViewCompatibility(pResource, D3D11_BIND_SHADER_RESOURCE, desc.Format)) { + if (!CheckResourceViewCompatibility(pResource, D3D11_BIND_SHADER_RESOURCE, desc.Format, plane)) { Logger::err(str::format("D3D11: Cannot create shader resource view:", "\n Resource type: ", resourceDesc.Dim, "\n Resource usage: ", resourceDesc.BindFlags, "\n Resource format: ", resourceDesc.Format, - "\n View format: ", desc.Format)); + "\n View format: ", desc.Format, + "\n View plane: ", plane)); return E_INVALIDARG; } @@ -415,7 +420,7 @@ namespace dxvk { return E_INVALIDARG; } - if (!CheckResourceViewCompatibility(pResource, D3D11_BIND_UNORDERED_ACCESS, desc.Format)) { + if (!CheckResourceViewCompatibility(pResource, D3D11_BIND_UNORDERED_ACCESS, desc.Format, 0)) { Logger::err(str::format("D3D11: Cannot create unordered access view:", "\n Resource type: ", resourceDesc.Dim, "\n Resource usage: ", resourceDesc.BindFlags, @@ -495,7 +500,7 @@ namespace dxvk { return E_INVALIDARG; } - if (!CheckResourceViewCompatibility(pResource, D3D11_BIND_RENDER_TARGET, desc.Format)) { + if (!CheckResourceViewCompatibility(pResource, D3D11_BIND_RENDER_TARGET, desc.Format, 0)) { Logger::err(str::format("D3D11: Cannot create render target view:", "\n Resource type: ", resourceDesc.Dim, "\n Resource usage: ", resourceDesc.BindFlags, @@ -543,7 +548,7 @@ namespace dxvk { return E_INVALIDARG; } - if (!CheckResourceViewCompatibility(pResource, D3D11_BIND_DEPTH_STENCIL, desc.Format)) { + if (!CheckResourceViewCompatibility(pResource, D3D11_BIND_DEPTH_STENCIL, desc.Format, 0)) { Logger::err(str::format("D3D11: Cannot create depth-stencil view:", "\n Resource type: ", resourceDesc.Dim, "\n Resource usage: ", resourceDesc.BindFlags, @@ -2219,6 +2224,32 @@ namespace dxvk { } + uint32_t D3D11Device::GetViewPlaneIndex( + ID3D11Resource* pResource, + DXGI_FORMAT ViewFormat) { + auto texture = GetCommonTexture(pResource); + + if (!texture) + return 0; + + uint32_t planeCount = texture->GetPlaneCount(); + + if (planeCount == 1) + return 0; + + auto formatMode = texture->GetFormatMode(); + auto formatFamily = LookupFamily(texture->Desc()->Format, formatMode); + auto viewFormat = LookupFormat(ViewFormat, formatMode); + + for (uint32_t i = 0; i < formatFamily.FormatCount; i++) { + if (formatFamily.Formats[i] == viewFormat.Format) + return i % planeCount; + } + + return ~0u; + } + + template void D3D11Device::CopySubresourceData( Void* pData, diff --git a/src/d3d11/d3d11_device.h b/src/d3d11/d3d11_device.h index a773b0ff..935b0e60 100644 --- a/src/d3d11/d3d11_device.h +++ b/src/d3d11/d3d11_device.h @@ -471,6 +471,10 @@ namespace dxvk { BOOL GetImageTypeSupport( VkFormat Format, VkImageType Type) const; + + uint32_t GetViewPlaneIndex( + ID3D11Resource* pResource, + DXGI_FORMAT ViewFormat); template void CopySubresourceData( diff --git a/src/d3d11/d3d11_resource.cpp b/src/d3d11/d3d11_resource.cpp index 3eb6f2e6..7ba71367 100644 --- a/src/d3d11/d3d11_resource.cpp +++ b/src/d3d11/d3d11_resource.cpp @@ -187,12 +187,13 @@ namespace dxvk { BOOL CheckResourceViewCompatibility( ID3D11Resource* pResource, UINT BindFlags, - DXGI_FORMAT Format) { + DXGI_FORMAT Format, + UINT Plane) { auto texture = GetCommonTexture(pResource); auto buffer = GetCommonBuffer (pResource); return texture != nullptr - ? texture->CheckViewCompatibility(BindFlags, Format) + ? texture->CheckViewCompatibility(BindFlags, Format, Plane) : buffer ->CheckViewCompatibility(BindFlags, Format); } diff --git a/src/d3d11/d3d11_resource.h b/src/d3d11/d3d11_resource.h index e809bcab..7d91a305 100644 --- a/src/d3d11/d3d11_resource.h +++ b/src/d3d11/d3d11_resource.h @@ -111,13 +111,16 @@ namespace dxvk { * texture, certain restrictions apply on which formats * can be used to view the resource. * \param [in] pResource The resource to check + * \param [in] BindFlags Bind flags required for the view * \param [in] Format The desired view format + * \param [in] Plane Plane slice for planar formats * \returns \c true if the format is compatible */ BOOL CheckResourceViewCompatibility( ID3D11Resource* pResource, UINT BindFlags, - DXGI_FORMAT Format); + DXGI_FORMAT Format, + UINT Plane); /** * \brief Increments private reference count of a resource diff --git a/src/d3d11/d3d11_texture.cpp b/src/d3d11/d3d11_texture.cpp index 79513e8e..e2d2c807 100644 --- a/src/d3d11/d3d11_texture.cpp +++ b/src/d3d11/d3d11_texture.cpp @@ -294,7 +294,12 @@ namespace dxvk { } - bool D3D11CommonTexture::CheckViewCompatibility(UINT BindFlags, DXGI_FORMAT Format) const { + uint32_t D3D11CommonTexture::GetPlaneCount() const { + return vk::getPlaneCount(m_image->formatInfo()->aspectMask); + } + + + bool D3D11CommonTexture::CheckViewCompatibility(UINT BindFlags, DXGI_FORMAT Format, UINT Plane) const { const DxvkImageCreateInfo& imageInfo = m_image->info(); // Check whether the given bind flags are supported @@ -306,6 +311,12 @@ namespace dxvk { DXGI_VK_FORMAT_INFO viewFormat = m_device->LookupFormat(Format, formatMode); DXGI_VK_FORMAT_INFO baseFormat = m_device->LookupFormat(m_desc.Format, formatMode); + // Check whether the plane index is valid for the given format + uint32_t planeCount = GetPlaneCount(); + + if (Plane >= planeCount) + return false; + if (imageInfo.flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) { // Check whether the given combination of image // view type and view format is actually supported @@ -314,19 +325,21 @@ namespace dxvk { if (!CheckFormatFeatureSupport(viewFormat.Format, features)) return false; - // Using the image format itself is always legal - if (viewFormat.Format == baseFormat.Format) + // Using the image format itself is supported for non-planar formats + if (viewFormat.Format == baseFormat.Format && planeCount == 1) 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) + // If there is a list of compatible formats, the view format must be + // included in that list. For planar formats, the list is laid out in + // such a way that the n-th format is supported for the n-th plane. + for (size_t i = Plane; i < imageInfo.viewFormatCount; i += planeCount) { + if (imageInfo.viewFormats[i] == viewFormat.Format) { return true; + } } // Otherwise, all bit-compatible formats can be used. - if (imageInfo.viewFormatCount == 0) { + if (imageInfo.viewFormatCount == 0 && planeCount == 1) { auto baseFormatInfo = imageFormatInfo(baseFormat.Format); auto viewFormatInfo = imageFormatInfo(viewFormat.Format); @@ -338,7 +351,7 @@ namespace dxvk { } else { // For non-mutable images, the view format // must be identical to the image format. - return viewFormat.Format == baseFormat.Format; + return viewFormat.Format == baseFormat.Format && planeCount == 1; } } diff --git a/src/d3d11/d3d11_texture.h b/src/d3d11/d3d11_texture.h index dab849c4..3b0ace60 100644 --- a/src/d3d11/d3d11_texture.h +++ b/src/d3d11/d3d11_texture.h @@ -206,7 +206,15 @@ namespace dxvk { * \returns Format mode */ DXGI_VK_FORMAT_MODE GetFormatMode() const; - + + /** + * \brief Computes plane count + * + * For non-planar formats, the plane count will be 1. + * \returns Image plane count + */ + uint32_t GetPlaneCount() const; + /** * \brief Checks whether a view can be created for this textue * @@ -216,11 +224,13 @@ namespace dxvk { * 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 + * \param [in] Plane Plane slice for planar formats * \returns \c true if the format is compatible */ bool CheckViewCompatibility( UINT BindFlags, - DXGI_FORMAT Format) const; + DXGI_FORMAT Format, + UINT Plane) const; /** * \brief Normalizes and validates texture description diff --git a/src/d3d11/d3d11_view_srv.cpp b/src/d3d11/d3d11_view_srv.cpp index 16ce5921..64e813d5 100644 --- a/src/d3d11/d3d11_view_srv.cpp +++ b/src/d3d11/d3d11_view_srv.cpp @@ -71,15 +71,15 @@ namespace dxvk { m_bufferView = pDevice->GetDXVKDevice()->createBufferView( buffer->GetBuffer(), viewInfo); } else { - const DXGI_VK_FORMAT_INFO formatInfo = pDevice->LookupFormat( - pDesc->Format, GetCommonTexture(pResource)->GetFormatMode()); + auto texture = GetCommonTexture(pResource); + auto formatInfo = pDevice->LookupFormat(pDesc->Format, texture->GetFormatMode()); DxvkImageViewCreateInfo viewInfo; viewInfo.format = formatInfo.Format; viewInfo.aspect = formatInfo.Aspect; viewInfo.swizzle = formatInfo.Swizzle; viewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT; - + // Shaders expect the stencil value in the G component if (viewInfo.aspect == VK_IMAGE_ASPECT_STENCIL_BIT) { viewInfo.swizzle = VkComponentMapping { @@ -164,6 +164,9 @@ namespace dxvk { throw DxvkError("D3D11: Invalid view dimension for image SRV"); } + if (texture->GetPlaneCount() > 1) + viewInfo.aspect = vk::getPlaneAspect(GetPlaneSlice(pDesc)); + // Populate view info struct m_info.Image.Aspects = viewInfo.aspect; m_info.Image.MinLevel = viewInfo.minLevel; @@ -172,8 +175,7 @@ namespace dxvk { m_info.Image.NumLayers = viewInfo.numLayers; // Create the underlying image view object - m_imageView = pDevice->GetDXVKDevice()->createImageView( - GetCommonTexture(pResource)->GetImage(), viewInfo); + m_imageView = pDevice->GetDXVKDevice()->createImageView(texture->GetImage(), viewInfo); } } @@ -371,7 +373,8 @@ namespace dxvk { D3D11_SHADER_RESOURCE_VIEW_DESC1 D3D11ShaderResourceView::PromoteDesc( - const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc) { + const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc, + UINT Plane) { D3D11_SHADER_RESOURCE_VIEW_DESC1 dstDesc; dstDesc.Format = pDesc->Format; dstDesc.ViewDimension = pDesc->ViewDimension; @@ -395,7 +398,7 @@ namespace dxvk { case D3D11_SRV_DIMENSION_TEXTURE2D: dstDesc.Texture2D.MostDetailedMip = pDesc->Texture2D.MostDetailedMip; dstDesc.Texture2D.MipLevels = pDesc->Texture2D.MipLevels; - dstDesc.Texture2D.PlaneSlice = 0; + dstDesc.Texture2D.PlaneSlice = Plane; break; case D3D11_SRV_DIMENSION_TEXTURE2DARRAY: @@ -403,7 +406,7 @@ namespace dxvk { dstDesc.Texture2DArray.MipLevels = pDesc->Texture2DArray.MipLevels; dstDesc.Texture2DArray.FirstArraySlice = pDesc->Texture2DArray.FirstArraySlice; dstDesc.Texture2DArray.ArraySize = pDesc->Texture2DArray.ArraySize; - dstDesc.Texture2DArray.PlaneSlice = 0; + dstDesc.Texture2DArray.PlaneSlice = Plane; break; case D3D11_SRV_DIMENSION_TEXTURE2DMS: @@ -535,9 +538,6 @@ namespace dxvk { case D3D11_SRV_DIMENSION_TEXTURE2D: if (pDesc->Texture2D.MipLevels > mipLevels - pDesc->Texture2D.MostDetailedMip) pDesc->Texture2D.MipLevels = mipLevels - pDesc->Texture2D.MostDetailedMip; - - if (pDesc->Texture2D.PlaneSlice != 0) - return E_INVALIDARG; break; case D3D11_SRV_DIMENSION_TEXTURE2DARRAY: @@ -545,9 +545,6 @@ namespace dxvk { pDesc->Texture2DArray.MipLevels = mipLevels - pDesc->Texture2DArray.MostDetailedMip; if (pDesc->Texture2DArray.ArraySize > numLayers - pDesc->Texture2DArray.FirstArraySlice) pDesc->Texture2DArray.ArraySize = numLayers - pDesc->Texture2DArray.FirstArraySlice; - - if (pDesc->Texture2DArray.PlaneSlice != 0) - return E_INVALIDARG; break; case D3D11_SRV_DIMENSION_TEXTURE2DMSARRAY: @@ -579,4 +576,16 @@ namespace dxvk { return S_OK; } + + UINT D3D11ShaderResourceView::GetPlaneSlice(const D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc) { + switch (pDesc->ViewDimension) { + case D3D11_SRV_DIMENSION_TEXTURE2D: + return pDesc->Texture2D.PlaneSlice; + case D3D11_SRV_DIMENSION_TEXTURE2DARRAY: + return pDesc->Texture2DArray.PlaneSlice; + default: + return 0; + } + } + } diff --git a/src/d3d11/d3d11_view_srv.h b/src/d3d11/d3d11_view_srv.h index 89b534c8..e7c5872e 100644 --- a/src/d3d11/d3d11_view_srv.h +++ b/src/d3d11/d3d11_view_srv.h @@ -70,12 +70,16 @@ namespace dxvk { D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc); static D3D11_SHADER_RESOURCE_VIEW_DESC1 PromoteDesc( - const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc); + const D3D11_SHADER_RESOURCE_VIEW_DESC* pDesc, + UINT Plane); static HRESULT NormalizeDesc( ID3D11Resource* pResource, D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc); - + + static UINT GetPlaneSlice( + const D3D11_SHADER_RESOURCE_VIEW_DESC1* pDesc); + private: ID3D11Resource* m_resource;