1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-02-20 19:54:19 +01:00

[dxvk] Implement depth-stencil unpacking

This commit is contained in:
Philip Rebohle 2019-03-26 14:47:21 +01:00
parent de45ffd749
commit 0d889e0dcd
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
2 changed files with 199 additions and 0 deletions

View File

@ -1072,6 +1072,182 @@ namespace dxvk {
}
void DxvkContext::copyPackedBufferToDepthStencilImage(
const Rc<DxvkImage>& dstImage,
VkImageSubresourceLayers dstSubresource,
VkOffset2D dstOffset,
VkExtent2D dstExtent,
const Rc<DxvkBuffer>& srcBuffer,
VkDeviceSize srcOffset,
VkFormat format) {
this->spillRenderPass();
this->unbindComputePipeline();
if (m_barriers.isBufferDirty(srcBuffer->getSliceHandle(), DxvkAccess::Read))
m_barriers.recordCommands(m_cmd);
// Retrieve compute pipeline for the given format
auto pipeInfo = m_metaPack->getUnpackPipeline(
dstImage->info().format, format);
if (!pipeInfo.pipeHandle) {
Logger::err(str::format(
"DxvkContext: copyPackedBufferToDepthStencilImage: Unhandled formats"
"\n dstFormat = ", dstImage->info().format,
"\n srcFormat = ", format));
return;
}
// Pick depth and stencil data formats
VkFormat dataFormatD = VK_FORMAT_UNDEFINED;
VkFormat dataFormatS = VK_FORMAT_UNDEFINED;
const std::array<std::tuple<VkFormat, VkFormat, VkFormat>, 2> formats = {{
{ VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_R32_UINT, VK_FORMAT_R8_UINT },
{ VK_FORMAT_D32_SFLOAT_S8_UINT, VK_FORMAT_R32_SFLOAT, VK_FORMAT_R8_UINT },
}};
for (const auto& e : formats) {
if (std::get<0>(e) == dstImage->info().format) {
dataFormatD = std::get<1>(e);
dataFormatS = std::get<2>(e);
}
}
// Create temporary buffer for depth/stencil data
VkDeviceSize pixelCount = dstExtent.width * dstExtent.height * dstSubresource.layerCount;
VkDeviceSize dataSizeD = align(pixelCount * imageFormatInfo(dataFormatD)->elementSize, 256);
VkDeviceSize dataSizeS = align(pixelCount * imageFormatInfo(dataFormatS)->elementSize, 256);
DxvkBufferCreateInfo tmpBufferInfo;
tmpBufferInfo.size = dataSizeD + dataSizeS;
tmpBufferInfo.usage = VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT
| VK_BUFFER_USAGE_TRANSFER_SRC_BIT;
tmpBufferInfo.stages = VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT
| VK_PIPELINE_STAGE_TRANSFER_BIT;
tmpBufferInfo.access = VK_ACCESS_SHADER_WRITE_BIT
| VK_ACCESS_TRANSFER_READ_BIT;
auto tmpBuffer = m_device->createBuffer(tmpBufferInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
// Create formatted buffer views
DxvkBufferViewCreateInfo tmpViewInfoD;
tmpViewInfoD.format = dataFormatD;
tmpViewInfoD.rangeOffset = 0;
tmpViewInfoD.rangeLength = dataSizeD;
DxvkBufferViewCreateInfo tmpViewInfoS;
tmpViewInfoS.format = dataFormatS;
tmpViewInfoS.rangeOffset = dataSizeD;
tmpViewInfoS.rangeLength = dataSizeS;
auto tmpBufferViewD = m_device->createBufferView(tmpBuffer, tmpViewInfoD);
auto tmpBufferViewS = m_device->createBufferView(tmpBuffer, tmpViewInfoS);
// Create descriptor set for the unpack operation
DxvkMetaUnpackDescriptors descriptors;
descriptors.dstDepth = tmpBufferViewD->handle();
descriptors.dstStencil = tmpBufferViewS->handle();
descriptors.srcBuffer = srcBuffer->getDescriptor(srcOffset, VK_WHOLE_SIZE).buffer;
VkDescriptorSet dset = allocateDescriptorSet(pipeInfo.dsetLayout);
m_cmd->updateDescriptorSetWithTemplate(dset, pipeInfo.dsetTemplate, &descriptors);
// Unpack the source buffer to temporary buffers
DxvkMetaUnpackArgs args;
args.dstExtent = dstExtent;
args.srcExtent = dstExtent;
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(
(dstExtent.width + 63) / 64,
dstExtent.height,
dstSubresource.layerCount);
m_barriers.accessBuffer(
tmpBuffer->getSliceHandle(),
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
VK_ACCESS_SHADER_WRITE_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_READ_BIT);
m_barriers.accessBuffer(
srcBuffer->getSliceHandle(),
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
VK_ACCESS_SHADER_READ_BIT,
srcBuffer->info().stages,
srcBuffer->info().access);
// Prepare image for the data transfer operation
VkOffset3D dstOffset3D = { dstOffset.x, dstOffset.y, 0 };
VkExtent3D dstExtent3D = { dstExtent.width, dstExtent.height, 1 };
VkImageLayout initialImageLayout = dstImage->info().layout;
if (dstImage->isFullSubresource(dstSubresource, dstExtent3D))
initialImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
m_barriers.accessImage(
dstImage, vk::makeSubresourceRange(dstSubresource),
initialImageLayout,
dstImage->info().stages,
dstImage->info().access,
dstImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL),
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT);
m_barriers.recordCommands(m_cmd);
// Copy temporary buffer data to depth-stencil image
VkImageSubresourceLayers dstSubresourceD = dstSubresource;
dstSubresourceD.aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT;
VkImageSubresourceLayers dstSubresourceS = dstSubresource;
dstSubresourceS.aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT;
std::array<VkBufferImageCopy, 2> copyRegions = {{
{ tmpBufferViewD->info().rangeOffset, 0, 0, dstSubresourceD, dstOffset3D, dstExtent3D },
{ tmpBufferViewS->info().rangeOffset, 0, 0, dstSubresourceS, dstOffset3D, dstExtent3D },
}};
m_cmd->cmdCopyBufferToImage(
tmpBuffer->getSliceHandle().handle,
dstImage->handle(),
dstImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL),
copyRegions.size(),
copyRegions.data());
m_barriers.accessImage(
dstImage, vk::makeSubresourceRange(dstSubresource),
dstImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL),
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT,
dstImage->info().layout,
dstImage->info().stages,
dstImage->info().access);
// Track all involved resources
m_cmd->trackResource(dstImage);
m_cmd->trackResource(srcBuffer);
m_cmd->trackResource(tmpBufferViewD);
m_cmd->trackResource(tmpBufferViewS);
}
void DxvkContext::discardBuffer(
const Rc<DxvkBuffer>& buffer) {
if (m_barriers.isBufferDirty(buffer->getSliceHandle(), DxvkAccess::Write))

View File

@ -425,6 +425,29 @@ namespace dxvk {
VkExtent2D srcExtent,
VkFormat format);
/**
* \brief Unpacks buffer data to a depth-stencil image
*
* Writes the packed depth-stencil data to an image.
* See \ref copyDepthStencilImageToPackedBuffer for
* which formats are supported and how they are packed.
* \param [in] dstImage Destination image
* \param [in] dstSubresource Destination subresource
* \param [in] dstOffset Image area offset
* \param [in] dstExtent Image area size
* \param [in] srcBuffer Packed data buffer
* \param [in] srcOffset Packed data offset
* \param [in] format Packed data format
*/
void copyPackedBufferToDepthStencilImage(
const Rc<DxvkImage>& dstImage,
VkImageSubresourceLayers dstSubresource,
VkOffset2D dstOffset,
VkExtent2D dstExtent,
const Rc<DxvkBuffer>& srcBuffer,
VkDeviceSize srcOffset,
VkFormat format);
/**
* \brief Discards a buffer
*