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 {