From e749a4a4acf35d9d58d16695b1658b0e07413d20 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Wed, 19 May 2021 21:18:22 +0200 Subject: [PATCH] [d3d11] Create shadow copy of video input images if sampled bit is not set This can happen with RGB input views since not having any bind flags set is legal for video input views, and SHADER_RESOURCE is actually explicitly disallowed, but we don't always want to set sampled bit for those resources. --- src/d3d11/d3d11_video.cpp | 41 +++++++++++++++++++++++++++++++++++++-- src/d3d11/d3d11_video.h | 18 +++++++++++++++++ 2 files changed, 57 insertions(+), 2 deletions(-) diff --git a/src/d3d11/d3d11_video.cpp b/src/d3d11/d3d11_video.cpp index 8d843055..db534659 100644 --- a/src/d3d11/d3d11_video.cpp +++ b/src/d3d11/d3d11_video.cpp @@ -142,6 +142,20 @@ namespace dxvk { D3D11_COMMON_RESOURCE_DESC resourceDesc = { }; GetCommonResourceDesc(pResource, &resourceDesc); + Rc dxvkImage = GetCommonTexture(pResource)->GetImage(); + + if (!(dxvkImage->info().usage & VK_IMAGE_USAGE_SAMPLED_BIT)) { + DxvkImageCreateInfo info = dxvkImage->info(); + info.flags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT; + info.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; + info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; + info.access = VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT; + info.tiling = VK_IMAGE_TILING_OPTIMAL; + info.layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + info.shared = VK_FALSE; + dxvkImage = m_copy = pDevice->GetDXVKDevice()->createImage(info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + } + DXGI_VK_FORMAT_INFO formatInfo = pDevice->LookupFormat(resourceDesc.Format, DXGI_VK_FORMAT_MODE_COLOR); DXGI_VK_FORMAT_FAMILY formatFamily = pDevice->LookupFamily(resourceDesc.Format, DXGI_VK_FORMAT_MODE_COLOR); @@ -165,14 +179,18 @@ namespace dxvk { throw DxvkError("Invalid view dimension"); } + m_subresources.aspectMask = aspectMask; + m_subresources.baseArrayLayer = viewInfo.minLayer; + m_subresources.layerCount = viewInfo.numLayers; + m_subresources.mipLevel = viewInfo.minLevel; + for (uint32_t i = 0; aspectMask && i < m_views.size(); i++) { viewInfo.aspect = vk::getNextAspect(aspectMask); if (viewInfo.aspect != VK_IMAGE_ASPECT_COLOR_BIT) viewInfo.format = formatFamily.Formats[i]; - m_views[i] = pDevice->GetDXVKDevice()->createImageView( - GetCommonTexture(pResource)->GetImage(), viewInfo); + m_views[i] = pDevice->GetDXVKDevice()->createImageView(dxvkImage, viewInfo); } m_isYCbCr = IsYCbCrFormat(resourceDesc.Format); @@ -1208,6 +1226,25 @@ namespace dxvk { auto view = static_cast(pStream->pInputSurface); + if (view->NeedsCopy()) { + m_ctx->EmitCs([ + cDstImage = view->GetShadowCopy(), + cSrcImage = view->GetImage(), + cSrcLayers = view->GetImageSubresources() + ] (DxvkContext* ctx) { + VkImageSubresourceLayers cDstLayers; + cDstLayers.aspectMask = cSrcLayers.aspectMask; + cDstLayers.baseArrayLayer = 0; + cDstLayers.layerCount = cSrcLayers.layerCount; + cDstLayers.mipLevel = cSrcLayers.mipLevel; + + ctx->copyImage( + cDstImage, cDstLayers, VkOffset3D(), + cSrcImage, cSrcLayers, VkOffset3D(), + cDstImage->info().extent); + }); + } + m_ctx->EmitCs([this, cStreamState = *pStreamState, cViews = view->GetViews(), diff --git a/src/d3d11/d3d11_video.h b/src/d3d11/d3d11_video.h index 510b8b45..85979eb8 100644 --- a/src/d3d11/d3d11_video.h +++ b/src/d3d11/d3d11_video.h @@ -138,6 +138,22 @@ namespace dxvk { return m_isYCbCr; } + const bool NeedsCopy() const { + return m_copy != nullptr; + } + + Rc GetImage() const { + return GetCommonTexture(m_resource.ptr())->GetImage(); + } + + VkImageSubresourceLayers GetImageSubresources() const { + return m_subresources; + } + + Rc GetShadowCopy() const { + return m_copy; + } + std::array, 2> GetViews() const { return m_views; } @@ -146,6 +162,8 @@ namespace dxvk { Com m_resource; D3D11_VIDEO_PROCESSOR_INPUT_VIEW_DESC m_desc; + VkImageSubresourceLayers m_subresources; + Rc m_copy; std::array, 2> m_views; bool m_isYCbCr = false;