diff --git a/src/dxvk/dxvk_context.cpp b/src/dxvk/dxvk_context.cpp index e78f513b..e8355519 100644 --- a/src/dxvk/dxvk_context.cpp +++ b/src/dxvk/dxvk_context.cpp @@ -921,6 +921,116 @@ namespace dxvk { } + void DxvkContext::copyDepthStencilImageToPackedBuffer( + const Rc& dstBuffer, + VkDeviceSize dstOffset, + const Rc& srcImage, + VkImageSubresourceLayers srcSubresource, + VkOffset2D srcOffset, + VkExtent2D srcExtent, + VkFormat format) { + this->spillRenderPass(); + this->unbindComputePipeline(); + + // Retrieve compute pipeline for the given format + auto pipeInfo = m_metaPack->getPipeline(format); + + if (!pipeInfo.pipeHandle) + return; + + // Create one depth view and one stencil view + DxvkImageViewCreateInfo dViewInfo; + dViewInfo.type = VK_IMAGE_VIEW_TYPE_2D_ARRAY; + dViewInfo.format = srcImage->info().format; + dViewInfo.usage = VK_IMAGE_USAGE_SAMPLED_BIT; + dViewInfo.aspect = VK_IMAGE_ASPECT_DEPTH_BIT; + dViewInfo.minLevel = srcSubresource.mipLevel; + dViewInfo.numLevels = 1; + dViewInfo.minLayer = srcSubresource.baseArrayLayer; + dViewInfo.numLayers = srcSubresource.layerCount; + + DxvkImageViewCreateInfo sViewInfo = dViewInfo; + sViewInfo.aspect = VK_IMAGE_ASPECT_STENCIL_BIT; + + Rc dView = m_device->createImageView(srcImage, dViewInfo); + Rc sView = m_device->createImageView(srcImage, sViewInfo); + + // Create a descriptor set for the pack operation + VkImageLayout layout = srcImage->pickLayout(VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL); + + DxvkMetaPackDescriptors descriptors; + descriptors.dstBuffer = dstBuffer->getDescriptor(0, VK_WHOLE_SIZE).buffer; + descriptors.srcDepth = dView->getDescriptor(VK_IMAGE_VIEW_TYPE_2D_ARRAY, layout).image; + descriptors.srcStencil = sView->getDescriptor(VK_IMAGE_VIEW_TYPE_2D_ARRAY, layout).image; + + VkDescriptorSet dset = m_cmd->allocateDescriptorSet(pipeInfo.dsetLayout); + m_cmd->updateDescriptorSetWithTemplate(dset, pipeInfo.dsetTemplate, &descriptors); + + // Since this is a meta operation, the image may be + // in a different layout and we have to transition it + auto subresourceRange = vk::makeSubresourceRange(srcSubresource); + + if (m_barriers.isImageDirty(srcImage, subresourceRange, DxvkAccess::Write)) + m_barriers.recordCommands(m_cmd); + + if (srcImage->info().layout != layout) { + m_transitions.accessImage( + srcImage, subresourceRange, + srcImage->info().layout, 0, 0, + layout, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_ACCESS_SHADER_READ_BIT); + + m_transitions.recordCommands(m_cmd); + } + + // Execute the actual pack operation + DxvkMetaPackArgs args; + args.srcOffset = srcOffset; + args.srcExtent = srcExtent; + + m_cmd->cmdBindPipeline( + VK_PIPELINE_BIND_POINT_COMPUTE, + pipeInfo.pipeHandle); + + m_cmd->cmdBindDescriptorSet( + VK_PIPELINE_BIND_POINT_COMPUTE, + pipeInfo.pipeLayout, dset, + 0, nullptr); + + m_cmd->cmdPushConstants( + pipeInfo.pipeLayout, + VK_SHADER_STAGE_COMPUTE_BIT, + 0, sizeof(args), &args); + + m_cmd->cmdDispatch( + (srcExtent.width + 7) / 8, + (srcExtent.height + 7) / 8, + srcSubresource.layerCount); + + m_barriers.accessImage( + srcImage, subresourceRange, layout, + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_ACCESS_SHADER_READ_BIT, + srcImage->info().layout, + srcImage->info().stages, + srcImage->info().access); + + m_barriers.accessBuffer( + dstBuffer->slice(), + VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, + VK_ACCESS_SHADER_WRITE_BIT, + dstBuffer->info().stages, + dstBuffer->info().access); + + m_cmd->trackResource(dView); + m_cmd->trackResource(sView); + + m_cmd->trackResource(srcImage); + m_cmd->trackResource(dstBuffer->resource()); + } + + void DxvkContext::discardBuffer( const Rc& buffer) { if (m_barriers.isBufferDirty(buffer->slice(), DxvkAccess::Write)) diff --git a/src/dxvk/dxvk_context.h b/src/dxvk/dxvk_context.h index dd54fc9c..ad3fca46 100644 --- a/src/dxvk/dxvk_context.h +++ b/src/dxvk/dxvk_context.h @@ -401,6 +401,30 @@ namespace dxvk { VkOffset3D srcOffset, VkExtent3D srcExtent); + /** + * \brief Packs depth-stencil image data to a buffer + * + * Packs data from both the depth and stencil aspects + * of an image into a buffer. The supported formats are: + * - \c VK_FORMAT_D24_UNORM_S8_UINT: 0xssdddddd + * - \c VK_FORMAT_D32_SFLOAT_S8_UINT: 0xdddddddd 0x000000ss + * \param [in] dstBuffer Destination buffer + * \param [in] dstOffset Destination offset, in bytes + * \param [in] srcImage Source image + * \param [in] srcSubresource Source subresource + * \param [in] srcOffset Source area offset + * \param [in] srcExtent Source area size + * \param [in] format Packed data format + */ + void copyDepthStencilImageToPackedBuffer( + const Rc& dstBuffer, + VkDeviceSize dstOffset, + const Rc& srcImage, + VkImageSubresourceLayers srcSubresource, + VkOffset2D srcOffset, + VkExtent2D srcExtent, + VkFormat format); + /** * \brief Discards a buffer *