From 2c176f4950e695159a9b9c42aab92eb96ddc06de Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sat, 28 Sep 2024 11:52:08 +0200 Subject: [PATCH] [dxvk] Refactor meta image copies --- src/dxvk/dxvk_context.cpp | 144 ++++++++++-------------------------- src/dxvk/dxvk_context.h | 11 --- src/dxvk/dxvk_meta_copy.cpp | 62 +++++++--------- src/dxvk/dxvk_meta_copy.h | 24 +----- 4 files changed, 72 insertions(+), 169 deletions(-) diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index b38be1537..e0e5706f4 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -3747,105 +3747,33 @@ namespace dxvk { dstImage->info().format, dstSubresource.aspectMask, srcImage->info().format, srcSubresource.aspectMask); - // Usually we should be able to draw directly to the destination image, - // but in some cases this might not be possible, e.g. if when copying - // from something like D32_SFLOAT to RGBA8_UNORM. In those situations, - // create a temporary image to draw to, and then copy to the actual - // destination image using a regular Vulkan transfer function. - bool dstIsCompatible = (dstImage->info().usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) - && (dstImage->isViewCompatible(viewFormats.dstFormat)); - bool srcIsCompatible = (srcImage->info().usage & (VK_IMAGE_USAGE_SAMPLED_BIT)) - && (srcImage->isViewCompatible(viewFormats.srcFormat)); + // Guarantee that we can render to or sample the images + DxvkImageUsageInfo dstUsage = { }; + dstUsage.usage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + dstUsage.viewFormatCount = 1; + dstUsage.viewFormats = &viewFormats.dstFormat; - if (dstIsCompatible && srcIsCompatible) { - this->copyImageFbDirect( - dstImage, dstSubresource, dstOffset, viewFormats.dstFormat, - srcImage, srcSubresource, srcOffset, viewFormats.srcFormat, extent); - } else if (dstIsCompatible || srcIsCompatible) { - DxvkImageCreateInfo imageInfo = dstImage->info(); - imageInfo.flags = 0; - imageInfo.extent = extent; - imageInfo.mipLevels = 1; - imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; - imageInfo.viewFormatCount = 0; + if (dstImage->formatInfo()->aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) + dstUsage.usage = VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - if (!dstIsCompatible) { - imageInfo.format = viewFormats.dstFormat; - imageInfo.numLayers = dstSubresource.layerCount; - imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - imageInfo.layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - imageInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT; - imageInfo.access = VK_ACCESS_TRANSFER_READ_BIT; + DxvkImageUsageInfo srcUsage = { }; + srcUsage.usage = VK_IMAGE_USAGE_SAMPLED_BIT; + srcUsage.viewFormatCount = 1; + srcUsage.viewFormats = &viewFormats.srcFormat; - if (dstImage->formatInfo()->aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) { - imageInfo.usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - imageInfo.stages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - imageInfo.access |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - } else { - imageInfo.usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - imageInfo.stages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT - | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - imageInfo.access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - } - } else /* if (!srcIsCompatible) */ { - imageInfo.format = viewFormats.srcFormat; - imageInfo.numLayers = srcSubresource.layerCount; - imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT; - imageInfo.layout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL; - imageInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT; - imageInfo.access = VK_ACCESS_TRANSFER_WRITE_BIT | VK_ACCESS_SHADER_READ_BIT; - } - - Rc tmpImage = m_device->createImage(imageInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - - VkImageSubresourceLayers tmpSubresource = { }; - tmpSubresource.aspectMask = tmpImage->formatInfo()->aspectMask; - tmpSubresource.mipLevel = 0; - tmpSubresource.baseArrayLayer = 0; - tmpSubresource.layerCount = imageInfo.numLayers; - - VkOffset3D tmpOffset = { 0, 0, 0 }; - - if (!dstIsCompatible) { - this->copyImageFbDirect( - tmpImage, tmpSubresource, tmpOffset, viewFormats.dstFormat, - srcImage, srcSubresource, srcOffset, viewFormats.srcFormat, extent); - - this->copyImageHw( - dstImage, dstSubresource, dstOffset, - tmpImage, tmpSubresource, tmpOffset, extent); - } else /* if (!srcIsCompatible) */ { - this->copyImageHw( - tmpImage, tmpSubresource, tmpOffset, - srcImage, srcSubresource, srcOffset, extent); - - this->copyImageFbDirect( - dstImage, dstSubresource, dstOffset, viewFormats.dstFormat, - tmpImage, tmpSubresource, tmpOffset, viewFormats.srcFormat, extent); - } - } else { - Logger::err(str::format("DxvkContext: copyImageFb: Unsupported operation:\n" - " srcFormat = ", srcImage->info().format, " (aspect ", srcSubresource.aspectMask, ")\n", - " dstFormat = ", dstImage->info().format, " (aspect ", dstSubresource.aspectMask, ")")); + if (!ensureImageCompatibility(dstImage, dstUsage) + || !ensureImageCompatibility(srcImage, srcUsage)) { + Logger::err(str::format("DxvkContext: copyImageFb: Unsupported images:" + "\n dst format: ", dstImage->info().format, + "\n src format: ", srcImage->info().format)); + return; } - } - - void DxvkContext::copyImageFbDirect( - const Rc& dstImage, - VkImageSubresourceLayers dstSubresource, - VkOffset3D dstOffset, - VkFormat dstFormat, - const Rc& srcImage, - VkImageSubresourceLayers srcSubresource, - VkOffset3D srcOffset, - VkFormat srcFormat, - VkExtent3D extent) { this->invalidateState(); auto dstSubresourceRange = vk::makeSubresourceRange(dstSubresource); auto srcSubresourceRange = vk::makeSubresourceRange(srcSubresource); - + if (m_execBarriers.isImageDirty(dstImage, dstSubresourceRange, DxvkAccess::Write) || m_execBarriers.isImageDirty(srcImage, srcSubresourceRange, DxvkAccess::Write)) m_execBarriers.recordCommands(m_cmd); @@ -3903,22 +3831,27 @@ namespace dxvk { m_execAcquires.recordCommands(m_cmd); // Create source and destination image views - Rc views = new DxvkMetaCopyViews(m_device->vkd(), - dstImage, dstSubresource, dstFormat, - srcImage, srcSubresource, srcFormat); - + DxvkMetaCopyViews views( + dstImage, dstSubresource, viewFormats.dstFormat, + srcImage, srcSubresource, viewFormats.srcFormat); + // Create pipeline for the copy operation DxvkMetaCopyPipeline pipeInfo = m_common->metaCopy().getPipeline( - views->getSrcViewType(), dstFormat, dstImage->info().sampleCount); + views.srcImageView->info().viewType, viewFormats.dstFormat, dstImage->info().sampleCount); // Create and initialize descriptor set VkDescriptorSet descriptorSet = m_descriptorPool->alloc(pipeInfo.dsetLayout); std::array descriptorImages = {{ - { VK_NULL_HANDLE, views->getSrcView(), srcLayout }, - { VK_NULL_HANDLE, views->getSrcStencilView(), srcLayout }, + { VK_NULL_HANDLE, views.srcImageView->handle(), srcLayout }, + { VK_NULL_HANDLE, VK_NULL_HANDLE, VK_IMAGE_LAYOUT_UNDEFINED }, }}; + if (views.srcStencilView) { + descriptorImages[1].imageView = views.srcStencilView->handle(); + descriptorImages[1].imageLayout = srcLayout; + } + std::array descriptorWrites; for (uint32_t i = 0; i < descriptorWrites.size(); i++) { @@ -3950,7 +3883,7 @@ namespace dxvk { VkExtent3D mipExtent = dstImage->mipLevelExtent(dstSubresource.mipLevel); VkRenderingAttachmentInfo attachmentInfo = { VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO }; - attachmentInfo.imageView = views->getDstView(); + attachmentInfo.imageView = views.dstImageView->handle(); attachmentInfo.imageLayout = dstLayout; attachmentInfo.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; attachmentInfo.storeOp = VK_ATTACHMENT_STORE_OP_STORE; @@ -4013,7 +3946,6 @@ namespace dxvk { m_cmd->trackResource(dstImage); m_cmd->trackResource(srcImage); - m_cmd->trackResource(views); } @@ -4530,7 +4462,7 @@ namespace dxvk { VkExtent3D passExtent = dstImage->mipLevelExtent(region.dstSubresource.mipLevel); - Rc views = new DxvkMetaCopyViews(m_device->vkd(), + DxvkMetaCopyViews views( dstImage, region.dstSubresource, dstFormat, srcImage, region.srcSubresource, srcFormat); @@ -4541,10 +4473,15 @@ namespace dxvk { VkDescriptorSet descriptorSet = m_descriptorPool->alloc(pipeInfo.dsetLayout); std::array descriptorImages = {{ - { VK_NULL_HANDLE, views->getSrcView(), srcLayout }, - { VK_NULL_HANDLE, views->getSrcStencilView(), srcLayout }, + { VK_NULL_HANDLE, views.srcImageView->handle(), srcLayout }, + { VK_NULL_HANDLE, VK_NULL_HANDLE, VK_IMAGE_LAYOUT_UNDEFINED }, }}; + if (views.srcStencilView) { + descriptorImages[1].imageView = views.srcStencilView->handle(); + descriptorImages[1].imageLayout = srcLayout; + } + std::array descriptorWrites; for (uint32_t i = 0; i < descriptorWrites.size(); i++) { @@ -4574,7 +4511,7 @@ namespace dxvk { scissor.extent = { region.extent.width, region.extent.height }; VkRenderingAttachmentInfo attachmentInfo = { VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO }; - attachmentInfo.imageView = views->getDstView(); + attachmentInfo.imageView = views.dstImageView->handle(); attachmentInfo.imageLayout = dstLayout; attachmentInfo.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; attachmentInfo.storeOp = VK_ATTACHMENT_STORE_OP_STORE; @@ -4632,7 +4569,6 @@ namespace dxvk { m_cmd->trackResource(dstImage); m_cmd->trackResource(srcImage); - m_cmd->trackResource(views); } diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index a29581b9f..2b27d7147 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -1526,17 +1526,6 @@ namespace dxvk { VkImageSubresourceLayers srcSubresource, VkOffset3D srcOffset, VkExtent3D extent); - - void copyImageFbDirect( - const Rc& dstImage, - VkImageSubresourceLayers dstSubresource, - VkOffset3D dstOffset, - VkFormat dstFormat, - const Rc& srcImage, - VkImageSubresourceLayers srcSubresource, - VkOffset3D srcOffset, - VkFormat srcFormat, - VkExtent3D extent); bool copyImageClear( const Rc& dstImage, diff --git a/src/dxvk/dxvk_meta_copy.cpp b/src/dxvk/dxvk_meta_copy.cpp index 5b33d0f80..0e1cc5e44 100644 --- a/src/dxvk/dxvk_meta_copy.cpp +++ b/src/dxvk/dxvk_meta_copy.cpp @@ -16,63 +16,57 @@ namespace dxvk { DxvkMetaCopyViews::DxvkMetaCopyViews( - const Rc& vkd, const Rc& dstImage, const VkImageSubresourceLayers& dstSubresources, VkFormat dstFormat, const Rc& srcImage, const VkImageSubresourceLayers& srcSubresources, - VkFormat srcFormat) - : m_vkd(vkd) { + VkFormat srcFormat) { VkImageAspectFlags dstAspects = dstImage->formatInfo()->aspectMask; VkImageAspectFlags srcAspects = srcImage->formatInfo()->aspectMask; // We don't support 3D here, so we can safely ignore that case - m_dstViewType = dstImage->info().type == VK_IMAGE_TYPE_1D + VkImageViewType dstViewType = dstImage->info().type == VK_IMAGE_TYPE_1D ? VK_IMAGE_VIEW_TYPE_1D_ARRAY : VK_IMAGE_VIEW_TYPE_2D_ARRAY; - m_srcViewType = srcImage->info().type == VK_IMAGE_TYPE_1D + VkImageViewType srcViewType = srcImage->info().type == VK_IMAGE_TYPE_1D ? VK_IMAGE_VIEW_TYPE_1D_ARRAY : VK_IMAGE_VIEW_TYPE_2D_ARRAY; - VkImageViewUsageCreateInfo usageInfo = { VK_STRUCTURE_TYPE_IMAGE_VIEW_USAGE_CREATE_INFO }; - usageInfo.usage = (dstAspects & VK_IMAGE_ASPECT_COLOR_BIT) - ? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT - : VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + DxvkImageViewKey dstViewInfo; + dstViewInfo.viewType = dstViewType; + dstViewInfo.format = dstFormat; + dstViewInfo.aspects = dstSubresources.aspectMask; + dstViewInfo.mipIndex = dstSubresources.mipLevel; + dstViewInfo.mipCount = 1u; + dstViewInfo.layerIndex = dstSubresources.baseArrayLayer; + dstViewInfo.layerCount = dstSubresources.layerCount; + dstViewInfo.usage = (dstAspects & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) + ? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT + : VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - // Create destination view - VkImageViewCreateInfo info = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, &usageInfo }; - info.image = dstImage->handle(); - info.viewType = m_dstViewType; - info.format = dstFormat; - info.subresourceRange = vk::makeSubresourceRange(dstSubresources); - - if ((m_vkd->vkCreateImageView(m_vkd->device(), &info, nullptr, &m_dstImageView))) - throw DxvkError("DxvkMetaCopyViews: Failed to create destination image view"); + dstImageView = dstImage->createView(dstViewInfo); // Create source image views - usageInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT; + DxvkImageViewKey srcViewInfo; + srcViewInfo.viewType = srcViewType; + srcViewInfo.format = srcFormat; + srcViewInfo.aspects = srcSubresources.aspectMask & ~VK_IMAGE_ASPECT_STENCIL_BIT; + srcViewInfo.mipIndex = srcSubresources.mipLevel; + srcViewInfo.mipCount = 1u; + srcViewInfo.layerIndex = srcSubresources.baseArrayLayer; + srcViewInfo.layerCount = srcSubresources.layerCount; + srcViewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT; - info.image = srcImage->handle(); - info.viewType = m_srcViewType; - info.format = srcFormat; - info.subresourceRange = vk::makeSubresourceRange(srcSubresources); - info.subresourceRange.aspectMask = srcAspects & (VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT); - - if ((m_vkd->vkCreateImageView(m_vkd->device(), &info, nullptr, &m_srcImageView))) - throw DxvkError("DxvkMetaCopyViews: Failed to create source image view"); + srcImageView = srcImage->createView(srcViewInfo); if (srcAspects & VK_IMAGE_ASPECT_STENCIL_BIT) { - info.subresourceRange.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; - - if ((m_vkd->vkCreateImageView(m_vkd->device(), &info, nullptr, &m_srcStencilView))) - throw DxvkError("DxvkMetaCopyViews: Failed to create source stencil view"); + srcViewInfo.aspects = VK_IMAGE_ASPECT_STENCIL_BIT; + srcStencilView = srcImage->createView(srcViewInfo); } } DxvkMetaCopyViews::~DxvkMetaCopyViews() { - m_vkd->vkDestroyImageView(m_vkd->device(), m_dstImageView, nullptr); - m_vkd->vkDestroyImageView(m_vkd->device(), m_srcImageView, nullptr); - m_vkd->vkDestroyImageView(m_vkd->device(), m_srcStencilView, nullptr); + } diff --git a/src/dxvk/dxvk_meta_copy.h b/src/dxvk/dxvk_meta_copy.h index 3584ad7ed..a47f0b1eb 100644 --- a/src/dxvk/dxvk_meta_copy.h +++ b/src/dxvk/dxvk_meta_copy.h @@ -75,12 +75,11 @@ namespace dxvk { * Creates and manages views used in a * framebuffer-based copy operations. */ - class DxvkMetaCopyViews : public DxvkResource { + class DxvkMetaCopyViews { public: DxvkMetaCopyViews( - const Rc& vkd, const Rc& dstImage, const VkImageSubresourceLayers& dstSubresources, VkFormat dstFormat, @@ -90,24 +89,9 @@ namespace dxvk { ~DxvkMetaCopyViews(); - VkImageView getDstView() const { return m_dstImageView; } - VkImageView getSrcView() const { return m_srcImageView; } - VkImageView getSrcStencilView() const { return m_srcStencilView; } - - VkImageViewType getSrcViewType() const { - return m_srcViewType; - } - - private: - - Rc m_vkd; - - VkImageViewType m_srcViewType = VK_IMAGE_VIEW_TYPE_MAX_ENUM; - VkImageViewType m_dstViewType = VK_IMAGE_VIEW_TYPE_MAX_ENUM; - - VkImageView m_dstImageView = VK_NULL_HANDLE; - VkImageView m_srcImageView = VK_NULL_HANDLE; - VkImageView m_srcStencilView = VK_NULL_HANDLE; + Rc dstImageView; + Rc srcImageView; + Rc srcStencilView; };