1
0
mirror of https://github.com/doitsujin/dxvk.git synced 2025-01-18 11:52:12 +01:00

[dxvk] Introduce copyPackedBufferImage

This commit is contained in:
Philip Rebohle 2021-06-23 16:02:13 +02:00
parent 27155539b6
commit ba9d670157
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
2 changed files with 193 additions and 0 deletions

View File

@ -1064,6 +1064,171 @@ namespace dxvk {
}
void DxvkContext::copyPackedBufferImage(
const Rc<DxvkBuffer>& dstBuffer,
VkDeviceSize dstBufferOffset,
VkOffset3D dstOffset,
VkExtent3D dstSize,
const Rc<DxvkBuffer>& srcBuffer,
VkDeviceSize srcBufferOffset,
VkOffset3D srcOffset,
VkExtent3D srcSize,
VkExtent3D extent,
VkDeviceSize elementSize) {
this->spillRenderPass(true);
this->unbindComputePipeline();
auto dstBufferSlice = dstBuffer->getSliceHandle(dstBufferOffset, elementSize * util::flattenImageExtent(dstSize));
auto srcBufferSlice = srcBuffer->getSliceHandle(srcBufferOffset, elementSize * util::flattenImageExtent(srcSize));
if (m_execBarriers.isBufferDirty(dstBufferSlice, DxvkAccess::Write)
|| m_execBarriers.isBufferDirty(srcBufferSlice, DxvkAccess::Read))
m_execBarriers.recordCommands(m_cmd);
// We'll use texel buffer views with an appropriately
// sized integer format to perform the copy
VkFormat format = VK_FORMAT_UNDEFINED;
switch (elementSize) {
case 1: format = VK_FORMAT_R8_UINT; break;
case 2: format = VK_FORMAT_R16_UINT; break;
case 4: format = VK_FORMAT_R32_UINT; break;
case 8: format = VK_FORMAT_R32G32_UINT; break;
case 12: format = VK_FORMAT_R32G32B32_UINT; break;
case 16: format = VK_FORMAT_R32G32B32A32_UINT; break;
}
if (!format) {
Logger::err(str::format("DxvkContext: copyPackedBufferImage: Unsupported element size ", elementSize));
return;
}
DxvkBufferViewCreateInfo viewInfo;
viewInfo.format = format;
viewInfo.rangeOffset = dstBufferOffset;
viewInfo.rangeLength = dstBufferSlice.length;
Rc<DxvkBufferView> dstView = m_device->createBufferView(dstBuffer, viewInfo);
viewInfo.rangeOffset = srcBufferOffset;
viewInfo.rangeLength = srcBufferSlice.length;
Rc<DxvkBufferView> srcView;
if (srcBuffer == dstBuffer
&& srcBufferSlice.offset < dstBufferSlice.offset + dstBufferSlice.length
&& srcBufferSlice.offset + srcBufferSlice.length > dstBufferSlice.offset) {
// Create temporary copy in case of overlapping regions
DxvkBufferCreateInfo bufferInfo;
bufferInfo.size = srcBufferSlice.length;
bufferInfo.usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT
| VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT;
bufferInfo.stages = VK_PIPELINE_STAGE_TRANSFER_BIT
| VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT;
bufferInfo.access = VK_ACCESS_TRANSFER_WRITE_BIT
| VK_ACCESS_SHADER_READ_BIT;
Rc<DxvkBuffer> tmpBuffer = m_device->createBuffer(bufferInfo, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
auto tmpBufferSlice = tmpBuffer->getSliceHandle();
VkBufferCopy copyRegion;
copyRegion.srcOffset = srcBufferSlice.offset;
copyRegion.dstOffset = tmpBufferSlice.offset;
copyRegion.size = tmpBufferSlice.length;
m_cmd->cmdCopyBuffer(DxvkCmdBuffer::ExecBuffer,
srcBufferSlice.handle, tmpBufferSlice.handle,
1, &copyRegion);
emitMemoryBarrier(0,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT,
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
VK_ACCESS_SHADER_READ_BIT);
viewInfo.rangeOffset = 0;
srcView = m_device->createBufferView(tmpBuffer, viewInfo);
m_cmd->trackResource<DxvkAccess::Write>(tmpBuffer);
} else {
srcView = m_device->createBufferView(srcBuffer, viewInfo);
}
auto pipeInfo = m_common->metaCopy().getCopyBufferImagePipeline();
VkDescriptorSet descriptorSet = allocateDescriptorSet(pipeInfo.dsetLayout);
std::array<VkWriteDescriptorSet, 2> descriptorWrites;
std::array<std::pair<VkDescriptorType, VkBufferView>, 2> descriptorInfos = {{
{ VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, dstView->handle() },
{ VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, srcView->handle() },
}};
for (uint32_t i = 0; i < descriptorWrites.size(); i++) {
auto write = &descriptorWrites[i];
auto info = &descriptorInfos[i];
write->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
write->pNext = nullptr;
write->dstSet = descriptorSet;
write->dstBinding = i;
write->dstArrayElement = 0;
write->descriptorCount = 1;
write->descriptorType = info->first;
write->pImageInfo = nullptr;
write->pBufferInfo = nullptr;
write->pTexelBufferView = &info->second;
}
m_cmd->updateDescriptorSets(descriptorWrites.size(), descriptorWrites.data());
DxvkCopyBufferImageArgs args = { };
args.dstOffset = dstOffset;
args.srcOffset = srcOffset;
args.extent = extent;
args.dstSize = { dstSize.width, dstSize.height };
args.srcSize = { srcSize.width, srcSize.height };
m_cmd->cmdBindPipeline(
VK_PIPELINE_BIND_POINT_COMPUTE,
pipeInfo.pipeHandle);
m_cmd->cmdBindDescriptorSet(
VK_PIPELINE_BIND_POINT_COMPUTE,
pipeInfo.pipeLayout, descriptorSet,
0, nullptr);
m_cmd->cmdPushConstants(
pipeInfo.pipeLayout,
VK_SHADER_STAGE_COMPUTE_BIT,
0, sizeof(args), &args);
m_cmd->cmdDispatch(
(extent.width + 7) / 8,
(extent.height + 7) / 8,
extent.depth);
m_execBarriers.accessBuffer(
dstView->getSliceHandle(),
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
VK_ACCESS_SHADER_WRITE_BIT,
dstBuffer->info().stages,
dstBuffer->info().access);
m_execBarriers.accessBuffer(
srcView->getSliceHandle(),
VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT,
VK_ACCESS_SHADER_READ_BIT,
srcBuffer->info().stages,
srcBuffer->info().access);
// Track all involved resources
m_cmd->trackResource<DxvkAccess::Write>(dstBuffer);
m_cmd->trackResource<DxvkAccess::Read>(srcBuffer);
m_cmd->trackResource<DxvkAccess::None>(dstView);
m_cmd->trackResource<DxvkAccess::None>(srcView);
}
void DxvkContext::copyPackedBufferToDepthStencilImage(
const Rc<DxvkImage>& dstImage,
VkImageSubresourceLayers dstSubresource,

View File

@ -444,6 +444,34 @@ namespace dxvk {
VkExtent2D srcExtent,
VkFormat format);
/**
* \brief Copies image data stored in a linear buffer to another
*
* The source and destination regions may overlap, in which case
* a temporary copy of the source buffer will be created.
* \param [in] dstBuffer Destination buffer
* \param [in] dstBufferOffset Destination subresource offset
* \param [in] dstOffset Destination image offset
* \param [in] dstSize Total size of the destination image
* \param [in] srcBuffer Source buffer
* \param [in] srcBufferOffset Source subresource offset
* \param [in] srcOffset Source image offset
* \param [in] srcSize Total size of the source image
* \param [in] extent Number of pixels to copy
* \param [in] elementSize Pixel size, in bytes
*/
void copyPackedBufferImage(
const Rc<DxvkBuffer>& dstBuffer,
VkDeviceSize dstBufferOffset,
VkOffset3D dstOffset,
VkExtent3D dstSize,
const Rc<DxvkBuffer>& srcBuffer,
VkDeviceSize srcBufferOffset,
VkOffset3D srcOffset,
VkExtent3D srcSize,
VkExtent3D extent,
VkDeviceSize elementSize);
/**
* \brief Unpacks buffer data to a depth-stencil image
*