From 96e102beff04317b2d0463a774f5b083e6bcf748 Mon Sep 17 00:00:00 2001 From: Philip Rebohle Date: Sat, 2 Jul 2022 03:32:31 +0200 Subject: [PATCH] [dxvk] Use dynamic rendering for copies Significantly reworks framebuffer copies as well. We'll no longer create dummy samplers to work around glslang versions not supporting texture descriptors without samplers, and copyImageFb was cleaned up to factor out the part where a temporary image is created. --- src/dxvk/dxvk_context.cpp | 349 ++++++------ src/dxvk/dxvk_context.h | 10 + src/dxvk/dxvk_meta_copy.cpp | 531 +++++------------- src/dxvk/dxvk_meta_copy.h | 58 +- src/dxvk/shaders/dxvk_copy_color_1d.frag | 4 +- src/dxvk/shaders/dxvk_copy_color_2d.frag | 4 +- src/dxvk/shaders/dxvk_copy_color_ms.frag | 4 +- src/dxvk/shaders/dxvk_copy_depth_1d.frag | 4 +- src/dxvk/shaders/dxvk_copy_depth_2d.frag | 4 +- src/dxvk/shaders/dxvk_copy_depth_ms.frag | 4 +- .../shaders/dxvk_copy_depth_stencil_1d.frag | 7 +- .../shaders/dxvk_copy_depth_stencil_2d.frag | 5 +- .../shaders/dxvk_copy_depth_stencil_ms.frag | 5 +- 13 files changed, 387 insertions(+), 602 deletions(-) diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index 66399112d..3192b6453 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -3232,6 +3232,82 @@ namespace dxvk { VkImageSubresourceLayers srcSubresource, VkOffset3D srcOffset, VkExtent3D extent) { + VkFormat viewFormat = m_common->metaCopy().getCopyDestinationFormat( + dstSubresource.aspectMask, + srcSubresource.aspectMask, + srcImage->info().format); + + if (!viewFormat) { + Logger::err("DxvkContext: copyImageFb: Unsupported format"); + return; + } + + // 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 useDirectCopy = (dstImage->info().usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) + && (dstImage->isViewCompatible(viewFormat)); + + if (useDirectCopy) { + this->copyImageFbDirect( + dstImage, dstSubresource, dstOffset, viewFormat, + srcImage, srcSubresource, srcOffset, extent); + } else { + DxvkImageCreateInfo imageInfo = dstImage->info(); + imageInfo.format = viewFormat; + imageInfo.flags = 0; + imageInfo.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT; + imageInfo.extent = extent; + imageInfo.numLayers = dstSubresource.layerCount; + imageInfo.mipLevels = 1; + imageInfo.tiling = VK_IMAGE_TILING_OPTIMAL; + imageInfo.layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; + imageInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT; + imageInfo.access = VK_ACCESS_TRANSFER_READ_BIT; + imageInfo.viewFormatCount = 0; + + 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; + } + + Rc tmpImage = m_device->createImage(imageInfo, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + + VkImageSubresourceLayers tmpSubresource = dstSubresource; + tmpSubresource.mipLevel = 0; + tmpSubresource.baseArrayLayer = 0; + + VkOffset3D tmpOffset = { 0, 0, 0 }; + + this->copyImageFbDirect( + tmpImage, tmpSubresource, tmpOffset, viewFormat, + srcImage, srcSubresource, srcOffset, extent); + + this->copyImageHw( + dstImage, dstSubresource, dstOffset, + tmpImage, tmpSubresource, tmpOffset, extent); + } + } + + + void DxvkContext::copyImageFbDirect( + const Rc& dstImage, + VkImageSubresourceLayers dstSubresource, + VkOffset3D dstOffset, + VkFormat dstFormat, + const Rc& srcImage, + VkImageSubresourceLayers srcSubresource, + VkOffset3D srcOffset, + VkExtent3D extent) { this->invalidateState(); auto dstSubresourceRange = vk::makeSubresourceRange(dstSubresource); @@ -3241,24 +3317,33 @@ namespace dxvk { || m_execBarriers.isImageDirty(srcImage, srcSubresourceRange, DxvkAccess::Write)) m_execBarriers.recordCommands(m_cmd); - // Source image needs to be readable - if (!(srcImage->info().usage & VK_IMAGE_USAGE_SAMPLED_BIT)) { - Logger::err("DxvkContext: copyImageFb: Source image not readable"); - return; + // Flag used to determine whether we can do an UNDEFINED transition + bool doDiscard = dstImage->isFullSubresource(dstSubresource, extent); + + // This function can process both color and depth-stencil images, so + // some things change a lot depending on the destination image type + VkPipelineStageFlags dstStages; + VkAccessFlags dstAccess; + VkImageLayout dstLayout; + + if (dstSubresource.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) { + dstLayout = dstImage->pickLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL); + dstStages = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; + dstAccess = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; + + if (!doDiscard) + dstAccess |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; + } else { + dstLayout = dstImage->pickLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); + dstStages = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT + | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; + dstAccess = VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; + + if (!doDiscard) + dstAccess |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; } - // Render target format to use for this copy - VkFormat viewFormat = m_common->metaCopy().getCopyDestinationFormat( - dstSubresource.aspectMask, - srcSubresource.aspectMask, - srcImage->info().format); - - if (viewFormat == VK_FORMAT_UNDEFINED) { - Logger::err("DxvkContext: copyImageFb: Unsupported format"); - return; - } - - // We might have to transition the source image layout + // Might have to transition source image as well VkImageLayout srcLayout = (srcSubresource.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) ? srcImage->pickLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL) : srcImage->pickLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL); @@ -3271,183 +3356,131 @@ namespace dxvk { srcLayout, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_ACCESS_SHADER_READ_BIT); - - m_execAcquires.recordCommands(m_cmd); } - // In some cases, we may be able to render to the destination - // image directly, which is faster than using a temporary image - VkImageUsageFlagBits tgtUsage = (dstSubresource.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) - ? VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT - : VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; - - bool useDirectRender = (dstImage->isViewCompatible(viewFormat)) - && (dstImage->info().usage & tgtUsage); - - // If needed, create a temporary render target for the copy - Rc tgtImage; - VkImageSubresourceLayers tgtSubresource = dstSubresource; - VkOffset3D tgtOffset = dstOffset; - - if (!useDirectRender) { - DxvkImageCreateInfo info; - info.type = dstImage->info().type; - info.format = viewFormat; - info.flags = 0; - info.sampleCount = dstImage->info().sampleCount; - info.extent = extent; - info.numLayers = dstSubresource.layerCount; - info.mipLevels = 1; - info.usage = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | tgtUsage; - info.stages = VK_PIPELINE_STAGE_TRANSFER_BIT; - info.access = VK_ACCESS_TRANSFER_READ_BIT; - info.tiling = VK_IMAGE_TILING_OPTIMAL; - info.layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL; - - tgtImage = m_device->createImage(info, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); - - tgtSubresource.mipLevel = 0; - tgtSubresource.baseArrayLayer = 0; - - tgtOffset = { 0, 0, 0 }; - } else { - tgtImage = dstImage; + if (dstImage->info().layout != dstLayout) { + m_execAcquires.accessImage( + dstImage, dstSubresourceRange, + doDiscard ? VK_IMAGE_LAYOUT_UNDEFINED + : dstImage->info().layout, + dstImage->info().stages, 0, + dstLayout, dstStages, dstAccess); } - + + m_execAcquires.recordCommands(m_cmd); + // Create source and destination image views - VkImageViewType viewType = dstImage->info().type == VK_IMAGE_TYPE_1D - ? VK_IMAGE_VIEW_TYPE_1D_ARRAY - : VK_IMAGE_VIEW_TYPE_2D_ARRAY; + Rc views = new DxvkMetaCopyViews(m_device->vkd(), + dstImage, dstSubresource, dstFormat, + srcImage, srcSubresource); - DxvkImageViewCreateInfo tgtViewInfo; - tgtViewInfo.type = viewType; - tgtViewInfo.format = viewFormat; - tgtViewInfo.usage = tgtUsage; - tgtViewInfo.aspect = tgtSubresource.aspectMask; - tgtViewInfo.minLevel = tgtSubresource.mipLevel; - tgtViewInfo.numLevels = 1; - tgtViewInfo.minLayer = tgtSubresource.baseArrayLayer; - tgtViewInfo.numLayers = tgtSubresource.layerCount; + // Create pipeline for the copy operation + DxvkMetaCopyPipeline pipeInfo = m_common->metaCopy().getPipeline( + views->getSrcViewType(), dstFormat, dstImage->info().sampleCount); - DxvkImageViewCreateInfo srcViewInfo; - srcViewInfo.type = viewType; - srcViewInfo.format = srcImage->info().format; - srcViewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT; - srcViewInfo.aspect = srcSubresource.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_COLOR_BIT); - srcViewInfo.minLevel = srcSubresource.mipLevel; - srcViewInfo.numLevels = 1; - srcViewInfo.minLayer = srcSubresource.baseArrayLayer; - srcViewInfo.numLayers = srcSubresource.layerCount; + // Create and initialize descriptor set + VkDescriptorSet descriptorSet = m_descriptorPool->alloc(pipeInfo.dsetLayout); - Rc tgtImageView = m_device->createImageView(tgtImage, tgtViewInfo); - Rc srcImageView = m_device->createImageView(srcImage, srcViewInfo); - Rc srcStencilView; + std::array descriptorImages = {{ + { VK_NULL_HANDLE, views->getSrcView(), srcLayout }, + { VK_NULL_HANDLE, views->getSrcStencilView(), srcLayout }, + }}; - if (srcSubresource.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) { - srcViewInfo.aspect = VK_IMAGE_ASPECT_STENCIL_BIT; - srcStencilView = m_device->createImageView(srcImage, srcViewInfo); + std::array descriptorWrites; + + for (uint32_t i = 0; i < descriptorWrites.size(); i++) { + descriptorWrites[i] = { VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET }; + descriptorWrites[i].dstSet = descriptorSet; + descriptorWrites[i].dstBinding = i; + descriptorWrites[i].descriptorCount = 1; + descriptorWrites[i].descriptorType = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE; + descriptorWrites[i].pImageInfo = &descriptorImages[i]; } - // Create framebuffer and pipeline for the copy - Rc fb = new DxvkMetaCopyRenderPass( - m_device->vkd(), tgtImageView, srcImageView, srcStencilView, - tgtImage->isFullSubresource(tgtSubresource, extent)); - - auto pipeInfo = m_common->metaCopy().getPipeline( - viewType, viewFormat, tgtImage->info().sampleCount); - - VkDescriptorImageInfo descriptorImage; - descriptorImage.sampler = VK_NULL_HANDLE; - descriptorImage.imageView = srcImageView->handle(); - descriptorImage.imageLayout = srcLayout; + m_cmd->updateDescriptorSets( + descriptorWrites.size(), + descriptorWrites.data()); - VkWriteDescriptorSet descriptorWrite; - descriptorWrite.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; - descriptorWrite.pNext = nullptr; - descriptorWrite.dstBinding = 0; - descriptorWrite.dstArrayElement = 0; - descriptorWrite.descriptorCount = 1; - descriptorWrite.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - descriptorWrite.pImageInfo = &descriptorImage; - descriptorWrite.pBufferInfo = nullptr; - descriptorWrite.pTexelBufferView = nullptr; - - descriptorWrite.dstSet = m_descriptorPool->alloc(pipeInfo.dsetLayout); - m_cmd->updateDescriptorSets(1, &descriptorWrite); - - if (srcSubresource.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) { - descriptorImage.imageView = srcStencilView->handle(); - descriptorWrite.dstBinding = 1; - m_cmd->updateDescriptorSets(1, &descriptorWrite); - } - + // Set up render state VkViewport viewport; - viewport.x = float(tgtOffset.x); - viewport.y = float(tgtOffset.y); - viewport.width = float(extent.width); - viewport.height = float(extent.height); + viewport.x = float(dstOffset.x); + viewport.y = float(dstOffset.y); + viewport.width = float(extent.width); + viewport.height = float(extent.height); viewport.minDepth = 0.0f; viewport.maxDepth = 1.0f; VkRect2D scissor; - scissor.offset = { tgtOffset.x, tgtOffset.y }; - scissor.extent = { extent.width, extent.height }; + scissor.offset = { dstOffset.x, dstOffset.y }; + scissor.extent = { extent.width, extent.height }; - VkRenderPassBeginInfo info; - info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - info.pNext = nullptr; - info.renderPass = fb->renderPass(); - info.framebuffer = fb->framebuffer(); - info.renderArea.offset = { 0, 0 }; - info.renderArea.extent = { - tgtImage->mipLevelExtent(tgtSubresource.mipLevel).width, - tgtImage->mipLevelExtent(tgtSubresource.mipLevel).height }; - info.clearValueCount = 0; - info.pClearValues = nullptr; + VkExtent3D mipExtent = dstImage->mipLevelExtent(dstSubresource.mipLevel); + + VkRenderingAttachmentInfoKHR attachmentInfo = { VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR }; + attachmentInfo.imageView = views->getDstView(); + attachmentInfo.imageLayout = dstLayout; + attachmentInfo.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; + attachmentInfo.storeOp = VK_ATTACHMENT_STORE_OP_STORE; + + if (doDiscard) + attachmentInfo.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; + + VkRenderingInfoKHR renderingInfo = { VK_STRUCTURE_TYPE_RENDERING_INFO_KHR }; + renderingInfo.renderArea.offset = VkOffset2D { 0, 0 }; + renderingInfo.renderArea.extent = VkExtent2D { mipExtent.width, mipExtent.height }; + renderingInfo.layerCount = dstSubresource.layerCount; + + VkImageAspectFlags dstAspects = dstImage->formatInfo()->aspectMask; + + if (dstAspects & VK_IMAGE_ASPECT_COLOR_BIT) { + renderingInfo.colorAttachmentCount = 1; + renderingInfo.pColorAttachments = &attachmentInfo; + } else { + if (dstAspects & VK_IMAGE_ASPECT_DEPTH_BIT) + renderingInfo.pDepthAttachment = &attachmentInfo; + if (dstAspects & VK_IMAGE_ASPECT_STENCIL_BIT) + renderingInfo.pStencilAttachment = &attachmentInfo; + } // Perform the actual copy operation - m_cmd->cmdBeginRenderPass(&info, VK_SUBPASS_CONTENTS_INLINE); + m_cmd->cmdBeginRendering(&renderingInfo); m_cmd->cmdBindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, pipeInfo.pipeHandle); m_cmd->cmdBindDescriptorSet(VK_PIPELINE_BIND_POINT_GRAPHICS, - pipeInfo.pipeLayout, descriptorWrite.dstSet, 0, nullptr); + pipeInfo.pipeLayout, descriptorSet, 0, nullptr); m_cmd->cmdSetViewport(0, 1, &viewport); m_cmd->cmdSetScissor (0, 1, &scissor); VkOffset2D srcCoordOffset = { - srcOffset.x - tgtOffset.x, - srcOffset.y - tgtOffset.y }; + srcOffset.x - dstOffset.x, + srcOffset.y - dstOffset.y }; m_cmd->cmdPushConstants(pipeInfo.pipeLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(srcCoordOffset), &srcCoordOffset); - m_cmd->cmdDraw(3, tgtSubresource.layerCount, 0, 0); - m_cmd->cmdEndRenderPass(); + m_cmd->cmdDraw(3, dstSubresource.layerCount, 0, 0); + m_cmd->cmdEndRendering(); - if (srcLayout != srcImage->info().layout) { - m_execBarriers.accessImage( - srcImage, srcSubresourceRange, srcLayout, - srcImage->info().stages, - srcImage->info().access, - srcImage->info().layout, - srcImage->info().stages, - srcImage->info().access); - } + m_execBarriers.accessImage( + srcImage, srcSubresourceRange, srcLayout, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_ACCESS_SHADER_READ_BIT, + srcImage->info().layout, + srcImage->info().stages, + srcImage->info().access); - m_cmd->trackResource(tgtImage); + m_execBarriers.accessImage( + dstImage, dstSubresourceRange, + dstLayout, dstStages, dstAccess, + dstImage->info().layout, + dstImage->info().stages, + dstImage->info().access); + + m_cmd->trackResource(dstImage); m_cmd->trackResource(srcImage); - m_cmd->trackResource(fb); - - // If necessary, copy the temporary image - // to the original destination image - if (!useDirectRender) { - this->copyImageHw( - dstImage, dstSubresource, dstOffset, - tgtImage, tgtSubresource, tgtOffset, - extent); - } + m_cmd->trackResource(views); } diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index 443ba8640..de29f3c22 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -1224,6 +1224,16 @@ namespace dxvk { VkOffset3D srcOffset, VkExtent3D extent); + void copyImageFbDirect( + const Rc& dstImage, + VkImageSubresourceLayers dstSubresource, + VkOffset3D dstOffset, + VkFormat dstFormat, + const Rc& srcImage, + VkImageSubresourceLayers srcSubresource, + VkOffset3D srcOffset, + VkExtent3D extent); + bool copyImageClear( const Rc& dstImage, VkImageSubresourceLayers dstSubresource, diff --git a/src/dxvk/dxvk_meta_copy.cpp b/src/dxvk/dxvk_meta_copy.cpp index ed79bb4ae..6f1bdf234 100644 --- a/src/dxvk/dxvk_meta_copy.cpp +++ b/src/dxvk/dxvk_meta_copy.cpp @@ -18,143 +18,68 @@ namespace dxvk { - DxvkMetaCopyRenderPass::DxvkMetaCopyRenderPass( - const Rc& vkd, - const Rc& dstImageView, - const Rc& srcImageView, - const Rc& srcStencilView, - bool discardDst) - : m_vkd (vkd), - m_dstImageView (dstImageView), - m_srcImageView (srcImageView), - m_srcStencilView(srcStencilView), - m_renderPass (createRenderPass(discardDst)), - m_framebuffer (createFramebuffer()) { + DxvkMetaCopyViews::DxvkMetaCopyViews( + const Rc& vkd, + const Rc& dstImage, + const VkImageSubresourceLayers& dstSubresources, + VkFormat dstFormat, + const Rc& srcImage, + const VkImageSubresourceLayers& srcSubresources) + : m_vkd(vkd) { + 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 + ? VK_IMAGE_VIEW_TYPE_1D_ARRAY : VK_IMAGE_VIEW_TYPE_2D_ARRAY; + m_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; + + // 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"); + + // Create source image views + usageInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT; + + info.image = srcImage->handle(); + info.viewType = m_srcViewType; + info.format = srcImage->info().format; + 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"); + + 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"); + } } - DxvkMetaCopyRenderPass::~DxvkMetaCopyRenderPass() { - m_vkd->vkDestroyFramebuffer(m_vkd->device(), m_framebuffer, nullptr); - m_vkd->vkDestroyRenderPass (m_vkd->device(), m_renderPass, nullptr); + 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); } - VkRenderPass DxvkMetaCopyRenderPass::createRenderPass(bool discard) const { - auto aspect = m_dstImageView->info().aspect; - - VkPipelineStageFlags cpyStages = 0; - VkAccessFlags cpyAccess = 0; - - VkAttachmentDescription attachment; - attachment.flags = 0; - attachment.format = m_dstImageView->info().format; - attachment.samples = m_dstImageView->imageInfo().sampleCount; - attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; - attachment.initialLayout = m_dstImageView->imageInfo().layout; - attachment.finalLayout = m_dstImageView->imageInfo().layout; - - if (discard) { - attachment.loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - attachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - } - - VkAttachmentReference attachmentRef; - attachmentRef.attachment = 0; - attachmentRef.layout = (aspect & VK_IMAGE_ASPECT_COLOR_BIT) - ? m_dstImageView->pickLayout(VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) - : m_dstImageView->pickLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); - - VkSubpassDescription subpass; - subpass.flags = 0; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.inputAttachmentCount = 0; - subpass.pInputAttachments = nullptr; - subpass.colorAttachmentCount = 0; - subpass.pColorAttachments = nullptr; - subpass.pResolveAttachments = nullptr; - subpass.pDepthStencilAttachment = nullptr; - subpass.preserveAttachmentCount = 0; - subpass.pPreserveAttachments = nullptr; - - if (aspect & VK_IMAGE_ASPECT_COLOR_BIT) { - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &attachmentRef; - - cpyStages |= VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - cpyAccess |= VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - - if (!discard) - cpyAccess |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT; - } else { - subpass.pDepthStencilAttachment = &attachmentRef; - - cpyStages |= VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT - | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT; - cpyAccess |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT; - - if (!discard) - cpyAccess |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT; - } - - // We have to be somewhat conservative here since we cannot assume - // that the backend blocks stages that are only used for meta ops - VkPipelineStageFlags extStages = m_dstImageView->imageInfo().stages | m_srcImageView->imageInfo().stages; - VkAccessFlags extAccess = m_dstImageView->imageInfo().access; - - std::array dependencies = {{ - { VK_SUBPASS_EXTERNAL, 0, extStages, cpyStages, 0, cpyAccess, 0 }, - { 0, VK_SUBPASS_EXTERNAL, cpyStages, extStages, cpyAccess, extAccess, 0 }, - }}; - - VkRenderPassCreateInfo info; - info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - info.pNext = nullptr; - info.flags = 0; - info.attachmentCount = 1; - info.pAttachments = &attachment; - info.subpassCount = 1; - info.pSubpasses = &subpass; - info.dependencyCount = dependencies.size(); - info.pDependencies = dependencies.data(); - - VkRenderPass result = VK_NULL_HANDLE; - if (m_vkd->vkCreateRenderPass(m_vkd->device(), &info, nullptr, &result) != VK_SUCCESS) - throw DxvkError("DxvkMetaCopyRenderPass: Failed to create render pass"); - return result; - } - - - VkFramebuffer DxvkMetaCopyRenderPass::createFramebuffer() const { - VkImageView dstViewHandle = m_dstImageView->handle(); - VkImageSubresourceRange dstSubresources = m_dstImageView->subresources(); - VkExtent3D dstExtent = m_dstImageView->mipLevelExtent(0); - - VkFramebufferCreateInfo fboInfo; - fboInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - fboInfo.pNext = nullptr; - fboInfo.flags = 0; - fboInfo.renderPass = m_renderPass; - fboInfo.attachmentCount = 1; - fboInfo.pAttachments = &dstViewHandle; - fboInfo.width = dstExtent.width; - fboInfo.height = dstExtent.height; - fboInfo.layers = dstSubresources.layerCount; - - VkFramebuffer result = VK_NULL_HANDLE; - if (m_vkd->vkCreateFramebuffer(m_vkd->device(), &fboInfo, nullptr, &result) != VK_SUCCESS) - throw DxvkError("DxvkMetaCopyRenderPass: Failed to create target framebuffer"); - return result; - } - - DxvkMetaCopyObjects::DxvkMetaCopyObjects(const DxvkDevice* device) : m_vkd (device->vkd()), - m_sampler (createSampler()), m_color { createShaderModule(dxvk_copy_color_1d), createShaderModule(dxvk_copy_color_2d), @@ -188,7 +113,6 @@ namespace dxvk { m_vkd->vkDestroyPipeline(m_vkd->device(), pair.second.pipeHandle, nullptr); m_vkd->vkDestroyPipelineLayout(m_vkd->device(), pair.second.pipeLayout, nullptr); m_vkd->vkDestroyDescriptorSetLayout (m_vkd->device(), pair.second.dsetLayout, nullptr); - m_vkd->vkDestroyRenderPass(m_vkd->device(), pair.second.renderPass, nullptr); } m_vkd->vkDestroyShaderModule(m_vkd->device(), m_depthStencil.fragMs, nullptr); @@ -202,8 +126,6 @@ namespace dxvk { m_vkd->vkDestroyShaderModule(m_vkd->device(), m_color.frag1D, nullptr); m_vkd->vkDestroyShaderModule(m_vkd->device(), m_shaderGeom, nullptr); m_vkd->vkDestroyShaderModule(m_vkd->device(), m_shaderVert, nullptr); - - m_vkd->vkDestroySampler(m_vkd->device(), m_sampler, nullptr); } @@ -267,34 +189,6 @@ namespace dxvk { } - VkSampler DxvkMetaCopyObjects::createSampler() const { - VkSamplerCreateInfo info; - info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO; - info.pNext = nullptr; - info.flags = 0; - info.magFilter = VK_FILTER_NEAREST; - info.minFilter = VK_FILTER_NEAREST; - info.mipmapMode = VK_SAMPLER_MIPMAP_MODE_NEAREST; - info.addressModeU = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - info.addressModeV = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - info.addressModeW = VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE; - info.mipLodBias = 0.0f; - info.anisotropyEnable = VK_FALSE; - info.maxAnisotropy = 1.0f; - info.compareEnable = VK_FALSE; - info.compareOp = VK_COMPARE_OP_ALWAYS; - info.minLod = 0.0f; - info.maxLod = 0.0f; - info.borderColor = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK; - info.unnormalizedCoordinates = VK_FALSE; - - VkSampler result = VK_NULL_HANDLE; - if (m_vkd->vkCreateSampler(m_vkd->device(), &info, nullptr, &result) != VK_SUCCESS) - throw DxvkError("DxvkMetaCopyObjects: Failed to create sampler"); - return result; - } - - VkShaderModule DxvkMetaCopyObjects::createShaderModule( const SpirvCodeBuffer& code) const { VkShaderModuleCreateInfo info; @@ -313,17 +207,13 @@ namespace dxvk { DxvkMetaCopyPipeline DxvkMetaCopyObjects::createCopyBufferImagePipeline() { DxvkMetaCopyPipeline pipeline; - pipeline.renderPass = VK_NULL_HANDLE; std::array bindings = {{ { 0, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr }, { 1, VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1, VK_SHADER_STAGE_COMPUTE_BIT, nullptr }, }}; - VkDescriptorSetLayoutCreateInfo setLayoutInfo; - setLayoutInfo.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - setLayoutInfo.pNext = nullptr; - setLayoutInfo.flags = 0; + VkDescriptorSetLayoutCreateInfo setLayoutInfo = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO }; setLayoutInfo.bindingCount = bindings.size(); setLayoutInfo.pBindings = bindings.data(); @@ -332,10 +222,7 @@ namespace dxvk { VkPushConstantRange pushRange = { VK_SHADER_STAGE_COMPUTE_BIT, 0, sizeof(DxvkCopyBufferImageArgs) }; - VkPipelineLayoutCreateInfo pipelineLayoutInfo; - pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipelineLayoutInfo.pNext = nullptr; - pipelineLayoutInfo.flags = 0; + VkPipelineLayoutCreateInfo pipelineLayoutInfo = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO }; pipelineLayoutInfo.setLayoutCount = 1; pipelineLayoutInfo.pSetLayouts = &pipeline.dsetLayout; pipelineLayoutInfo.pushConstantRangeCount = 1; @@ -346,19 +233,12 @@ namespace dxvk { VkShaderModule shaderModule = createShaderModule(dxvk_copy_buffer_image); - VkComputePipelineCreateInfo pipelineInfo; - pipelineInfo.sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO; - pipelineInfo.pNext = nullptr; - pipelineInfo.flags = 0; + VkComputePipelineCreateInfo pipelineInfo = { VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO }; pipelineInfo.layout = pipeline.pipeLayout; pipelineInfo.stage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - pipelineInfo.stage.pNext = nullptr; - pipelineInfo.stage.flags = 0; pipelineInfo.stage.stage = VK_SHADER_STAGE_COMPUTE_BIT; pipelineInfo.stage.module = shaderModule; pipelineInfo.stage.pName = "main"; - pipelineInfo.stage.pSpecializationInfo = nullptr; - pipelineInfo.basePipelineHandle = VK_NULL_HANDLE; pipelineInfo.basePipelineIndex = -1; if (m_vkd->vkCreateComputePipelines(m_vkd->device(), VK_NULL_HANDLE, @@ -373,96 +253,24 @@ namespace dxvk { DxvkMetaCopyPipeline DxvkMetaCopyObjects::createPipeline( const DxvkMetaCopyPipelineKey& key) { DxvkMetaCopyPipeline pipeline; - pipeline.renderPass = this->createRenderPass(key); pipeline.dsetLayout = this->createDescriptorSetLayout(key); pipeline.pipeLayout = this->createPipelineLayout(pipeline.dsetLayout); - pipeline.pipeHandle = this->createPipelineObject(key, pipeline.pipeLayout, pipeline.renderPass); + pipeline.pipeHandle = this->createPipelineObject(key, pipeline.pipeLayout); return pipeline; } - VkRenderPass DxvkMetaCopyObjects::createRenderPass( - const DxvkMetaCopyPipelineKey& key) const { - auto aspect = imageFormatInfo(key.format)->aspectMask; - - VkAttachmentDescription attachment; - attachment.flags = 0; - attachment.format = key.format; - attachment.samples = key.samples; - attachment.loadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - attachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - attachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD; - attachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE; - attachment.initialLayout = VK_IMAGE_LAYOUT_GENERAL; - attachment.finalLayout = VK_IMAGE_LAYOUT_GENERAL; - - VkAttachmentReference attachmentRef; - attachmentRef.attachment = 0; - attachmentRef.layout = (aspect & VK_IMAGE_ASPECT_COLOR_BIT) - ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL - : VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL; - - VkSubpassDescription subpass; - subpass.flags = 0; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.inputAttachmentCount = 0; - subpass.pInputAttachments = nullptr; - subpass.colorAttachmentCount = 0; - subpass.pColorAttachments = nullptr; - subpass.pResolveAttachments = nullptr; - subpass.pDepthStencilAttachment = nullptr; - subpass.preserveAttachmentCount = 0; - subpass.pPreserveAttachments = nullptr; - - if (aspect & VK_IMAGE_ASPECT_COLOR_BIT) { - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &attachmentRef; - } else { - subpass.pDepthStencilAttachment = &attachmentRef; - } - - VkRenderPassCreateInfo info; - info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - info.pNext = nullptr; - info.flags = 0; - info.attachmentCount = 1; - info.pAttachments = &attachment; - info.subpassCount = 1; - info.pSubpasses = &subpass; - info.dependencyCount = 0; - info.pDependencies = nullptr; - - VkRenderPass result = VK_NULL_HANDLE; - if (m_vkd->vkCreateRenderPass(m_vkd->device(), &info, nullptr, &result) != VK_SUCCESS) - throw DxvkError("DxvkMetaCopyObjects: Failed to create render pass"); - return result; - } - - VkDescriptorSetLayout DxvkMetaCopyObjects::createDescriptorSetLayout( const DxvkMetaCopyPipelineKey& key) const { - std::array bindings; - - for (uint32_t i = 0; i < 2; i++) { - bindings[i].binding = i; - bindings[i].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; - bindings[i].descriptorCount = 1; - bindings[i].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - bindings[i].pImmutableSamplers = &m_sampler; - } + std::array bindings = {{ + { 0, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT }, + { 1, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1, VK_SHADER_STAGE_FRAGMENT_BIT }, + }}; - VkDescriptorSetLayoutCreateInfo info; - info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO; - info.pNext = nullptr; - info.flags = 0; - info.bindingCount = 1; - info.pBindings = bindings.data(); + VkDescriptorSetLayoutCreateInfo info = { VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO }; + info.bindingCount = bindings.size(); + info.pBindings = bindings.data(); - auto format = imageFormatInfo(key.format); - - if (format->aspectMask == (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) - info.bindingCount = 2; - VkDescriptorSetLayout result = VK_NULL_HANDLE; if (m_vkd->vkCreateDescriptorSetLayout(m_vkd->device(), &info, nullptr, &result) != VK_SUCCESS) throw DxvkError("DxvkMetaCopyObjects: Failed to create descriptor set layout"); @@ -472,15 +280,9 @@ namespace dxvk { VkPipelineLayout DxvkMetaCopyObjects::createPipelineLayout( VkDescriptorSetLayout descriptorSetLayout) const { - VkPushConstantRange push; - push.stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; - push.offset = 0; - push.size = sizeof(VkOffset2D); + VkPushConstantRange push = { VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(VkOffset2D) }; - VkPipelineLayoutCreateInfo info; - info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - info.pNext = nullptr; - info.flags = 0; + VkPipelineLayoutCreateInfo info = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO }; info.setLayoutCount = 1; info.pSetLayouts = &descriptorSetLayout; info.pushConstantRangeCount = 1; @@ -495,42 +297,22 @@ namespace dxvk { VkPipeline DxvkMetaCopyObjects::createPipelineObject( const DxvkMetaCopyPipelineKey& key, - VkPipelineLayout pipelineLayout, - VkRenderPass renderPass) { + VkPipelineLayout pipelineLayout) { auto aspect = imageFormatInfo(key.format)->aspectMask; std::array stages; uint32_t stageCount = 0; - VkPipelineShaderStageCreateInfo& vsStage = stages[stageCount++]; - vsStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - vsStage.pNext = nullptr; - vsStage.flags = 0; - vsStage.stage = VK_SHADER_STAGE_VERTEX_BIT; - vsStage.module = m_shaderVert; - vsStage.pName = "main"; - vsStage.pSpecializationInfo = nullptr; + stages[stageCount++] = VkPipelineShaderStageCreateInfo { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, nullptr, 0, + VK_SHADER_STAGE_VERTEX_BIT, m_shaderVert, "main" }; if (m_shaderGeom) { - VkPipelineShaderStageCreateInfo& gsStage = stages[stageCount++]; - gsStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - gsStage.pNext = nullptr; - gsStage.flags = 0; - gsStage.stage = VK_SHADER_STAGE_GEOMETRY_BIT; - gsStage.module = m_shaderGeom; - gsStage.pName = "main"; - gsStage.pSpecializationInfo = nullptr; + stages[stageCount++] = VkPipelineShaderStageCreateInfo { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, nullptr, 0, + VK_SHADER_STAGE_GEOMETRY_BIT, m_shaderGeom, "main" }; } - VkPipelineShaderStageCreateInfo& psStage = stages[stageCount++]; - psStage.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - psStage.pNext = nullptr; - psStage.flags = 0; - psStage.stage = VK_SHADER_STAGE_FRAGMENT_BIT; - psStage.module = VK_NULL_HANDLE; - psStage.pName = "main"; - psStage.pSpecializationInfo = nullptr; - std::array, 3> shaderSets = {{ { &m_color, VK_IMAGE_ASPECT_COLOR_BIT }, { &m_depth, VK_IMAGE_ASPECT_DEPTH_BIT }, @@ -545,135 +327,95 @@ namespace dxvk { } if (!shaderSet) - throw DxvkError("DxvkMetaCopyObjects: Unsupported aspect mask"); + throw DxvkError(str::format("DxvkMetaCopyObjects: Unsupported aspect mask: ", aspect)); + + VkShaderModule psModule = VK_NULL_HANDLE; if (key.viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY) - psStage.module = shaderSet->frag1D; + psModule = shaderSet->frag1D; else if (key.samples == VK_SAMPLE_COUNT_1_BIT) - psStage.module = shaderSet->frag2D; + psModule = shaderSet->frag2D; else - psStage.module = shaderSet->fragMs; + psModule = shaderSet->fragMs; + stages[stageCount++] = VkPipelineShaderStageCreateInfo { + VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, nullptr, 0, + VK_SHADER_STAGE_FRAGMENT_BIT, psModule, "main" }; + std::array dynStates = {{ VK_DYNAMIC_STATE_VIEWPORT, VK_DYNAMIC_STATE_SCISSOR, }}; - VkPipelineDynamicStateCreateInfo dynState; - dynState.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO; - dynState.pNext = nullptr; - dynState.flags = 0; - dynState.dynamicStateCount = dynStates.size(); - dynState.pDynamicStates = dynStates.data(); + VkPipelineDynamicStateCreateInfo dynState = { VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO }; + dynState.dynamicStateCount = dynStates.size(); + dynState.pDynamicStates = dynStates.data(); - VkPipelineVertexInputStateCreateInfo viState; - viState.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - viState.pNext = nullptr; - viState.flags = 0; - viState.vertexBindingDescriptionCount = 0; - viState.pVertexBindingDescriptions = nullptr; - viState.vertexAttributeDescriptionCount = 0; - viState.pVertexAttributeDescriptions = nullptr; + VkPipelineVertexInputStateCreateInfo viState = { VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO }; - VkPipelineInputAssemblyStateCreateInfo iaState; - iaState.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - iaState.pNext = nullptr; - iaState.flags = 0; - iaState.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - iaState.primitiveRestartEnable = VK_FALSE; + VkPipelineInputAssemblyStateCreateInfo iaState = { VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO }; + iaState.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - VkPipelineViewportStateCreateInfo vpState; - vpState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - vpState.pNext = nullptr; - vpState.flags = 0; - vpState.viewportCount = 1; - vpState.pViewports = nullptr; - vpState.scissorCount = 1; - vpState.pScissors = nullptr; + VkPipelineViewportStateCreateInfo vpState = { VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO }; + vpState.viewportCount = 1; + vpState.scissorCount = 1; - VkPipelineRasterizationStateCreateInfo rsState; - rsState.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rsState.pNext = nullptr; - rsState.flags = 0; - rsState.depthClampEnable = VK_TRUE; - rsState.rasterizerDiscardEnable = VK_FALSE; - rsState.polygonMode = VK_POLYGON_MODE_FILL; - rsState.cullMode = VK_CULL_MODE_NONE; - rsState.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; - rsState.depthBiasEnable = VK_FALSE; - rsState.depthBiasConstantFactor = 0.0f; - rsState.depthBiasClamp = 0.0f; - rsState.depthBiasSlopeFactor = 0.0f; - rsState.lineWidth = 1.0f; + VkPipelineRasterizationStateCreateInfo rsState = { VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO }; + rsState.depthClampEnable = VK_TRUE; + rsState.polygonMode = VK_POLYGON_MODE_FILL; + rsState.cullMode = VK_CULL_MODE_NONE; + rsState.frontFace = VK_FRONT_FACE_COUNTER_CLOCKWISE; + rsState.lineWidth = 1.0f; uint32_t msMask = 0xFFFFFFFF; - VkPipelineMultisampleStateCreateInfo msState; - msState.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - msState.pNext = nullptr; - msState.flags = 0; - msState.rasterizationSamples = key.samples; - msState.sampleShadingEnable = key.samples != VK_SAMPLE_COUNT_1_BIT; - msState.minSampleShading = 1.0f; - msState.pSampleMask = &msMask; - msState.alphaToCoverageEnable = VK_FALSE; - msState.alphaToOneEnable = VK_FALSE; + VkPipelineMultisampleStateCreateInfo msState = { VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO }; + msState.rasterizationSamples = key.samples; + msState.sampleShadingEnable = key.samples != VK_SAMPLE_COUNT_1_BIT; + msState.minSampleShading = 1.0f; + msState.pSampleMask = &msMask; - VkPipelineColorBlendAttachmentState cbAttachment; - cbAttachment.blendEnable = VK_FALSE; - cbAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_ONE; - cbAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ZERO; - cbAttachment.colorBlendOp = VK_BLEND_OP_ADD; - cbAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE; - cbAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO; - cbAttachment.alphaBlendOp = VK_BLEND_OP_ADD; - cbAttachment.colorWriteMask = + VkPipelineColorBlendAttachmentState cbAttachment = { }; + cbAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; - VkPipelineColorBlendStateCreateInfo cbState; - cbState.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; - cbState.pNext = nullptr; - cbState.flags = 0; - cbState.logicOpEnable = VK_FALSE; - cbState.logicOp = VK_LOGIC_OP_NO_OP; - cbState.attachmentCount = 1; - cbState.pAttachments = &cbAttachment; + VkPipelineColorBlendStateCreateInfo cbState = { VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO }; + cbState.attachmentCount = 1; + cbState.pAttachments = &cbAttachment; - for (uint32_t i = 0; i < 4; i++) - cbState.blendConstants[i] = 0.0f; + VkStencilOpState stencilOp = { }; + stencilOp.failOp = VK_STENCIL_OP_REPLACE; + stencilOp.passOp = VK_STENCIL_OP_REPLACE; + stencilOp.depthFailOp = VK_STENCIL_OP_REPLACE; + stencilOp.compareOp = VK_COMPARE_OP_ALWAYS; + stencilOp.compareMask = 0xFFFFFFFF; + stencilOp.writeMask = 0xFFFFFFFF; - VkStencilOpState stencilOp; - stencilOp.failOp = VK_STENCIL_OP_REPLACE; - stencilOp.passOp = VK_STENCIL_OP_REPLACE; - stencilOp.depthFailOp = VK_STENCIL_OP_REPLACE; - stencilOp.compareOp = VK_COMPARE_OP_ALWAYS; - stencilOp.compareMask = 0xFFFFFFFF; - stencilOp.writeMask = 0xFFFFFFFF; - stencilOp.reference = 0; + VkPipelineDepthStencilStateCreateInfo dsState = { VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO }; + dsState.depthTestEnable = VK_TRUE; + dsState.depthWriteEnable = VK_TRUE; + dsState.depthCompareOp = VK_COMPARE_OP_ALWAYS; + dsState.stencilTestEnable = VK_TRUE; + dsState.front = stencilOp; + dsState.back = stencilOp; - VkPipelineDepthStencilStateCreateInfo dsState; - dsState.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO; - dsState.pNext = nullptr; - dsState.flags = 0; - dsState.depthTestEnable = VK_TRUE; - dsState.depthWriteEnable = VK_TRUE; - dsState.depthCompareOp = VK_COMPARE_OP_ALWAYS; - dsState.depthBoundsTestEnable = VK_FALSE; - dsState.stencilTestEnable = VK_TRUE; - dsState.front = stencilOp; - dsState.back = stencilOp; - dsState.minDepthBounds = 0.0f; - dsState.maxDepthBounds = 1.0f; - - VkGraphicsPipelineCreateInfo info; - info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - info.pNext = nullptr; - info.flags = 0; + VkPipelineRenderingCreateInfoKHR rtState = { VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR }; + + if (aspect & VK_IMAGE_ASPECT_COLOR_BIT) { + rtState.colorAttachmentCount = 1; + rtState.pColorAttachmentFormats = &key.format; + } else { + if (aspect & VK_IMAGE_ASPECT_DEPTH_BIT) + rtState.depthAttachmentFormat = key.format; + if (aspect & VK_IMAGE_ASPECT_STENCIL_BIT) + rtState.stencilAttachmentFormat = key.format; + } + + VkGraphicsPipelineCreateInfo info = { VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, &rtState }; info.stageCount = stageCount; info.pStages = stages.data(); info.pVertexInputState = &viState; info.pInputAssemblyState = &iaState; - info.pTessellationState = nullptr; info.pViewportState = &vpState; info.pRasterizationState = &rsState; info.pMultisampleState = &msState; @@ -681,9 +423,6 @@ namespace dxvk { info.pDepthStencilState = (aspect & VK_IMAGE_ASPECT_COLOR_BIT) ? nullptr : &dsState; info.pDynamicState = &dynState; info.layout = pipelineLayout; - info.renderPass = renderPass; - info.subpass = 0; - info.basePipelineHandle = VK_NULL_HANDLE; info.basePipelineIndex = -1; VkPipeline result = VK_NULL_HANDLE; diff --git a/src/dxvk/dxvk_meta_copy.h b/src/dxvk/dxvk_meta_copy.h index c80b7f797..bb7481fc9 100644 --- a/src/dxvk/dxvk_meta_copy.h +++ b/src/dxvk/dxvk_meta_copy.h @@ -32,7 +32,6 @@ namespace dxvk { * that is used for fragment shader copies. */ struct DxvkMetaCopyPipeline { - VkRenderPass renderPass; VkDescriptorSetLayout dsetLayout; VkPipelineLayout pipeLayout; VkPipeline pipeHandle; @@ -63,46 +62,43 @@ namespace dxvk { }; /** - * \brief Copy framebuffer and render pass + * \brief Copy view objects * - * Creates a framebuffer and render - * pass object for an image view. + * Creates and manages views used in a + * framebuffer-based copy operations. */ - class DxvkMetaCopyRenderPass : public DxvkResource { + class DxvkMetaCopyViews : public DxvkResource { public: - DxvkMetaCopyRenderPass( - const Rc& vkd, - const Rc& dstImageView, - const Rc& srcImageView, - const Rc& srcStencilView, - bool discardDst); + DxvkMetaCopyViews( + const Rc& vkd, + const Rc& dstImage, + const VkImageSubresourceLayers& dstSubresources, + VkFormat dstFormat, + const Rc& srcImage, + const VkImageSubresourceLayers& srcSubresources); - ~DxvkMetaCopyRenderPass(); + ~DxvkMetaCopyViews(); - VkRenderPass renderPass() const { - return m_renderPass; - } + VkImageView getDstView() const { return m_dstImageView; } + VkImageView getSrcView() const { return m_srcImageView; } + VkImageView getSrcStencilView() const { return m_srcStencilView; } - VkFramebuffer framebuffer() const { - return m_framebuffer; + VkImageViewType getSrcViewType() const { + return m_srcViewType; } private: Rc m_vkd; - Rc m_dstImageView; - Rc m_srcImageView; - Rc m_srcStencilView; - - VkRenderPass m_renderPass = VK_NULL_HANDLE; - VkFramebuffer m_framebuffer = VK_NULL_HANDLE; + VkImageViewType m_srcViewType = VK_IMAGE_VIEW_TYPE_MAX_ENUM; + VkImageViewType m_dstViewType = VK_IMAGE_VIEW_TYPE_MAX_ENUM; - VkRenderPass createRenderPass(bool discard) const; - - VkFramebuffer createFramebuffer() const; + VkImageView m_dstImageView = VK_NULL_HANDLE; + VkImageView m_srcImageView = VK_NULL_HANDLE; + VkImageView m_srcStencilView = VK_NULL_HANDLE; }; @@ -162,8 +158,6 @@ namespace dxvk { Rc m_vkd; - VkSampler m_sampler; - VkShaderModule m_shaderVert = VK_NULL_HANDLE; VkShaderModule m_shaderGeom = VK_NULL_HANDLE; @@ -180,8 +174,6 @@ namespace dxvk { DxvkMetaCopyPipeline m_copyBufferImagePipeline = { }; - VkSampler createSampler() const; - VkShaderModule createShaderModule( const SpirvCodeBuffer& code) const; @@ -190,9 +182,6 @@ namespace dxvk { DxvkMetaCopyPipeline createPipeline( const DxvkMetaCopyPipelineKey& key); - VkRenderPass createRenderPass( - const DxvkMetaCopyPipelineKey& key) const; - VkDescriptorSetLayout createDescriptorSetLayout( const DxvkMetaCopyPipelineKey& key) const; @@ -201,8 +190,7 @@ namespace dxvk { VkPipeline createPipelineObject( const DxvkMetaCopyPipelineKey& key, - VkPipelineLayout pipelineLayout, - VkRenderPass renderPass); + VkPipelineLayout pipelineLayout); }; diff --git a/src/dxvk/shaders/dxvk_copy_color_1d.frag b/src/dxvk/shaders/dxvk_copy_color_1d.frag index 76e83dac3..b91067d91 100644 --- a/src/dxvk/shaders/dxvk_copy_color_1d.frag +++ b/src/dxvk/shaders/dxvk_copy_color_1d.frag @@ -1,7 +1,9 @@ #version 450 +#extension GL_EXT_samplerless_texture_functions : require + layout(set = 0, binding = 0) -uniform sampler1DArray s_image; +uniform texture1DArray s_image; layout(location = 0) out vec4 o_color; diff --git a/src/dxvk/shaders/dxvk_copy_color_2d.frag b/src/dxvk/shaders/dxvk_copy_color_2d.frag index db76c2483..99a0cc270 100644 --- a/src/dxvk/shaders/dxvk_copy_color_2d.frag +++ b/src/dxvk/shaders/dxvk_copy_color_2d.frag @@ -1,7 +1,9 @@ #version 450 +#extension GL_EXT_samplerless_texture_functions : require + layout(set = 0, binding = 0) -uniform sampler2DArray s_image; +uniform texture2DArray s_image; layout(location = 0) out vec4 o_color; diff --git a/src/dxvk/shaders/dxvk_copy_color_ms.frag b/src/dxvk/shaders/dxvk_copy_color_ms.frag index 61b81241d..b7a79057f 100644 --- a/src/dxvk/shaders/dxvk_copy_color_ms.frag +++ b/src/dxvk/shaders/dxvk_copy_color_ms.frag @@ -1,7 +1,9 @@ #version 450 +#extension GL_EXT_samplerless_texture_functions : require + layout(set = 0, binding = 0) -uniform sampler2DMSArray s_image; +uniform texture2DMSArray s_image; layout(location = 0) out vec4 o_color; diff --git a/src/dxvk/shaders/dxvk_copy_depth_1d.frag b/src/dxvk/shaders/dxvk_copy_depth_1d.frag index 7150db10d..acf627293 100644 --- a/src/dxvk/shaders/dxvk_copy_depth_1d.frag +++ b/src/dxvk/shaders/dxvk_copy_depth_1d.frag @@ -1,7 +1,9 @@ #version 450 +#extension GL_EXT_samplerless_texture_functions : require + layout(set = 0, binding = 0) -uniform sampler1DArray s_image; +uniform texture1DArray s_image; layout(push_constant) uniform u_info_t { diff --git a/src/dxvk/shaders/dxvk_copy_depth_2d.frag b/src/dxvk/shaders/dxvk_copy_depth_2d.frag index a5eaf4e93..dabcd4a56 100644 --- a/src/dxvk/shaders/dxvk_copy_depth_2d.frag +++ b/src/dxvk/shaders/dxvk_copy_depth_2d.frag @@ -1,7 +1,9 @@ #version 450 +#extension GL_EXT_samplerless_texture_functions : require + layout(set = 0, binding = 0) -uniform sampler2DArray s_image; +uniform texture2DArray s_image; layout(push_constant) uniform u_info_t { diff --git a/src/dxvk/shaders/dxvk_copy_depth_ms.frag b/src/dxvk/shaders/dxvk_copy_depth_ms.frag index 4264c0387..44c07c305 100644 --- a/src/dxvk/shaders/dxvk_copy_depth_ms.frag +++ b/src/dxvk/shaders/dxvk_copy_depth_ms.frag @@ -1,7 +1,9 @@ #version 450 +#extension GL_EXT_samplerless_texture_functions : require + layout(set = 0, binding = 0) -uniform sampler2DMSArray s_image; +uniform texture2DMSArray s_image; layout(push_constant) uniform u_info_t { diff --git a/src/dxvk/shaders/dxvk_copy_depth_stencil_1d.frag b/src/dxvk/shaders/dxvk_copy_depth_stencil_1d.frag index e017145df..fb5bea678 100644 --- a/src/dxvk/shaders/dxvk_copy_depth_stencil_1d.frag +++ b/src/dxvk/shaders/dxvk_copy_depth_stencil_1d.frag @@ -1,12 +1,13 @@ #version 450 -#extension GL_ARB_shader_stencil_export : enable +#extension GL_ARB_shader_stencil_export : require +#extension GL_EXT_samplerless_texture_functions : require layout(set = 0, binding = 0) -uniform sampler1DArray s_depth; +uniform texture1DArray s_depth; layout(set = 0, binding = 1) -uniform usampler1DArray s_stencil; +uniform utexture1DArray s_stencil; layout(push_constant) uniform u_info_t { diff --git a/src/dxvk/shaders/dxvk_copy_depth_stencil_2d.frag b/src/dxvk/shaders/dxvk_copy_depth_stencil_2d.frag index 29e7d6b0b..2b5fad670 100644 --- a/src/dxvk/shaders/dxvk_copy_depth_stencil_2d.frag +++ b/src/dxvk/shaders/dxvk_copy_depth_stencil_2d.frag @@ -1,12 +1,13 @@ #version 450 #extension GL_ARB_shader_stencil_export : enable +#extension GL_EXT_samplerless_texture_functions : require layout(set = 0, binding = 0) -uniform sampler2DArray s_depth; +uniform texture2DArray s_depth; layout(set = 0, binding = 1) -uniform usampler2DArray s_stencil; +uniform utexture2DArray s_stencil; layout(push_constant) uniform u_info_t { diff --git a/src/dxvk/shaders/dxvk_copy_depth_stencil_ms.frag b/src/dxvk/shaders/dxvk_copy_depth_stencil_ms.frag index dfb5f0058..0c6a27d39 100644 --- a/src/dxvk/shaders/dxvk_copy_depth_stencil_ms.frag +++ b/src/dxvk/shaders/dxvk_copy_depth_stencil_ms.frag @@ -1,12 +1,13 @@ #version 450 #extension GL_ARB_shader_stencil_export : enable +#extension GL_EXT_samplerless_texture_functions : require layout(set = 0, binding = 0) -uniform sampler2DMSArray s_depth; +uniform texture2DMSArray s_depth; layout(set = 0, binding = 1) -uniform usampler2DMSArray s_stencil; +uniform utexture2DMSArray s_stencil; layout(push_constant) uniform u_info_t {