mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-01-19 14:52:10 +01:00
[dxvk] Support format conversion in copyBufferToImage
This commit is contained in:
parent
501b0991da
commit
f67c8dd1da
@ -3990,25 +3990,16 @@ namespace dxvk {
|
||||
cDstLayers = dstLayer,
|
||||
cDstOffset = DstOffset,
|
||||
cDstExtent = dstExtent,
|
||||
cDstFormat = pDstTexture->GetPackedFormat(),
|
||||
cSrcBuffer = pSrcTexture->GetMappedBuffer(srcSubresource),
|
||||
cSrcLayout = pSrcTexture->GetSubresourceLayout(srcAspectMask, srcSubresource),
|
||||
cSrcOffset = pSrcTexture->ComputeMappedOffset(srcSubresource, j, SrcOffset),
|
||||
cSrcCoord = SrcOffset,
|
||||
cSrcExtent = srcMipExtent,
|
||||
cSrcFormat = pSrcTexture->GetPackedFormat()
|
||||
cSrcExtent = srcMipExtent
|
||||
] (DxvkContext* ctx) {
|
||||
if (cDstLayers.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
||||
ctx->copyBufferToImage(cDstImage, cDstLayers, cDstOffset, cDstExtent,
|
||||
cSrcBuffer, cSrcOffset, cSrcLayout.RowPitch, cSrcLayout.DepthPitch);
|
||||
} else {
|
||||
ctx->copyPackedBufferToDepthStencilImage(cDstImage, cDstLayers,
|
||||
VkOffset2D { cDstOffset.x, cDstOffset.y },
|
||||
VkExtent2D { cDstExtent.width, cDstExtent.height },
|
||||
cSrcBuffer, cSrcLayout.Offset,
|
||||
VkOffset2D { cSrcCoord.x, cSrcCoord.y },
|
||||
VkExtent2D { cSrcExtent.width, cSrcExtent.height },
|
||||
cSrcFormat);
|
||||
}
|
||||
ctx->copyBufferToImage(cDstImage, cDstLayers, cDstOffset, cDstExtent,
|
||||
cSrcBuffer, cSrcOffset, cSrcLayout.RowPitch, cSrcLayout.DepthPitch,
|
||||
cDstFormat);
|
||||
});
|
||||
} else if (srcIsImage) {
|
||||
VkImageSubresourceLayers srcLayer = { srcAspectMask,
|
||||
@ -5194,21 +5185,11 @@ namespace dxvk {
|
||||
cStagingSlice = std::move(StagingBuffer),
|
||||
cPackedFormat = pDstTexture->GetPackedFormat()
|
||||
] (DxvkContext* ctx) {
|
||||
if (cDstLayers.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
||||
ctx->copyBufferToImage(cDstImage,
|
||||
cDstLayers, cDstOffset, cDstExtent,
|
||||
cStagingSlice.buffer(),
|
||||
cStagingSlice.offset(), 0, 0);
|
||||
} else {
|
||||
ctx->copyPackedBufferToDepthStencilImage(cDstImage, cDstLayers,
|
||||
VkOffset2D { cDstOffset.x, cDstOffset.y },
|
||||
VkExtent2D { cDstExtent.width, cDstExtent.height },
|
||||
cStagingSlice.buffer(),
|
||||
cStagingSlice.offset(),
|
||||
VkOffset2D { 0, 0 },
|
||||
VkExtent2D { cDstExtent.width, cDstExtent.height },
|
||||
cPackedFormat);
|
||||
}
|
||||
ctx->copyBufferToImage(cDstImage,
|
||||
cDstLayers, cDstOffset, cDstExtent,
|
||||
cStagingSlice.buffer(),
|
||||
cStagingSlice.offset(), 0, 0,
|
||||
cPackedFormat);
|
||||
});
|
||||
} else {
|
||||
// If the destination image is backed only by a buffer, we need to use
|
||||
|
@ -675,20 +675,10 @@ namespace dxvk {
|
||||
cSrcDepthPitch = subresourceLayout.DepthPitch,
|
||||
cPackedFormat = pResource->GetPackedFormat()
|
||||
] (DxvkContext* ctx) {
|
||||
if (cDstSubresource.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
||||
ctx->copyBufferToImage(
|
||||
cDstImage, cDstSubresource, cDstOffset, cDstExtent,
|
||||
cSrcBuffer, cSrcOffset, cSrcRowPitch, cSrcDepthPitch);
|
||||
} else {
|
||||
ctx->copyPackedBufferToDepthStencilImage(
|
||||
cDstImage, cDstSubresource,
|
||||
VkOffset2D { cDstOffset.x, cDstOffset.y },
|
||||
VkExtent2D { cDstExtent.width, cDstExtent.height },
|
||||
cSrcBuffer, 0,
|
||||
VkOffset2D { cDstOffset.x, cDstOffset.y },
|
||||
VkExtent2D { cDstExtent.width, cDstExtent.height },
|
||||
cPackedFormat);
|
||||
}
|
||||
ctx->copyBufferToImage(
|
||||
cDstImage, cDstSubresource, cDstOffset, cDstExtent,
|
||||
cSrcBuffer, cSrcOffset, cSrcRowPitch, cSrcDepthPitch,
|
||||
cPackedFormat);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -5082,22 +5082,11 @@ namespace dxvk {
|
||||
cOffset = alignedDestOffset,
|
||||
cPackedDSFormat = packedDSFormat
|
||||
] (DxvkContext* ctx) {
|
||||
if (cDstLayers.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
||||
ctx->copyBufferToImage(
|
||||
cDstImage, cDstLayers,
|
||||
cOffset, cDstLevelExtent,
|
||||
cSrcSlice.buffer(), cSrcSlice.offset(),
|
||||
1, 1);
|
||||
} else {
|
||||
ctx->copyPackedBufferToDepthStencilImage(
|
||||
cDstImage, cDstLayers,
|
||||
VkOffset2D { cOffset.x, cOffset.y },
|
||||
VkExtent2D { cDstLevelExtent.width, cDstLevelExtent.height },
|
||||
cSrcSlice.buffer(), cSrcSlice.offset(),
|
||||
VkOffset2D { 0, 0 },
|
||||
VkExtent2D { cDstLevelExtent.width, cDstLevelExtent.height },
|
||||
cPackedDSFormat);
|
||||
}
|
||||
ctx->copyBufferToImage(
|
||||
cDstImage, cDstLayers,
|
||||
cOffset, cDstLevelExtent,
|
||||
cSrcSlice.buffer(), cSrcSlice.offset(),
|
||||
0, 0, cPackedDSFormat);
|
||||
});
|
||||
|
||||
TrackTextureMappingBufferSequenceNumber(pSrcTexture, SrcSubresource);
|
||||
|
@ -500,62 +500,19 @@ namespace dxvk {
|
||||
const Rc<DxvkBuffer>& srcBuffer,
|
||||
VkDeviceSize srcOffset,
|
||||
VkDeviceSize rowAlignment,
|
||||
VkDeviceSize sliceAlignment) {
|
||||
this->spillRenderPass(true);
|
||||
this->prepareImage(dstImage, vk::makeSubresourceRange(dstSubresource));
|
||||
VkDeviceSize sliceAlignment,
|
||||
VkFormat srcFormat) {
|
||||
bool useFb = (srcFormat && srcFormat != dstImage->info().format) ||
|
||||
(dstImage->formatInfo()->aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT));
|
||||
|
||||
auto srcSlice = srcBuffer->getSliceHandle(srcOffset, 0);
|
||||
|
||||
// We may copy to only one aspect at a time, but pipeline
|
||||
// barriers need to have all available aspect bits set
|
||||
auto dstFormatInfo = dstImage->formatInfo();
|
||||
|
||||
auto dstSubresourceRange = vk::makeSubresourceRange(dstSubresource);
|
||||
dstSubresourceRange.aspectMask = dstFormatInfo->aspectMask;
|
||||
|
||||
if (m_execBarriers.isImageDirty(dstImage, dstSubresourceRange, DxvkAccess::Write)
|
||||
|| m_execBarriers.isBufferDirty(srcSlice, DxvkAccess::Read))
|
||||
m_execBarriers.recordCommands(m_cmd);
|
||||
|
||||
// Initialize the image if the entire subresource is covered
|
||||
VkImageLayout dstImageLayoutInitial = dstImage->info().layout;
|
||||
VkImageLayout dstImageLayoutTransfer = dstImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
|
||||
if (dstImage->isFullSubresource(dstSubresource, dstExtent))
|
||||
dstImageLayoutInitial = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
if (dstImageLayoutTransfer != dstImageLayoutInitial) {
|
||||
m_execAcquires.accessImage(
|
||||
dstImage, dstSubresourceRange,
|
||||
dstImageLayoutInitial,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
|
||||
dstImageLayoutTransfer,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT);
|
||||
if (useFb) {
|
||||
copyBufferToImageFb(dstImage, dstSubresource, dstOffset, dstExtent,
|
||||
srcBuffer, srcOffset, rowAlignment, sliceAlignment,
|
||||
srcFormat ? srcFormat : dstImage->info().format);
|
||||
} else {
|
||||
copyBufferToImageHw(dstImage, dstSubresource, dstOffset, dstExtent,
|
||||
srcBuffer, srcOffset, rowAlignment, sliceAlignment);
|
||||
}
|
||||
|
||||
m_execAcquires.recordCommands(m_cmd);
|
||||
|
||||
this->copyImageBufferData<true>(DxvkCmdBuffer::ExecBuffer, dstImage, dstSubresource,
|
||||
dstOffset, dstExtent, dstImageLayoutTransfer, srcSlice, rowAlignment, sliceAlignment);
|
||||
|
||||
m_execBarriers.accessImage(
|
||||
dstImage, dstSubresourceRange,
|
||||
dstImageLayoutTransfer,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
dstImage->info().layout,
|
||||
dstImage->info().stages,
|
||||
dstImage->info().access);
|
||||
|
||||
m_execBarriers.accessBuffer(srcSlice,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_TRANSFER_READ_BIT,
|
||||
srcBuffer->info().stages,
|
||||
srcBuffer->info().access);
|
||||
|
||||
m_cmd->trackResource<DxvkAccess::Write>(dstImage);
|
||||
m_cmd->trackResource<DxvkAccess::Read>(srcBuffer);
|
||||
}
|
||||
|
||||
|
||||
@ -3366,6 +3323,75 @@ namespace dxvk {
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::copyBufferToImageHw(
|
||||
const Rc<DxvkImage>& image,
|
||||
const VkImageSubresourceLayers& imageSubresource,
|
||||
VkOffset3D imageOffset,
|
||||
VkExtent3D imageExtent,
|
||||
const Rc<DxvkBuffer>& buffer,
|
||||
VkDeviceSize bufferOffset,
|
||||
VkDeviceSize bufferRowAlignment,
|
||||
VkDeviceSize bufferSliceAlignment) {
|
||||
this->spillRenderPass(true);
|
||||
this->prepareImage(image, vk::makeSubresourceRange(imageSubresource));
|
||||
|
||||
VkDeviceSize dataSize = imageSubresource.layerCount * util::computeImageDataSize(
|
||||
image->info().format, imageExtent, imageSubresource.aspectMask);
|
||||
|
||||
auto bufferSlice = buffer->getSliceHandle(bufferOffset, dataSize);
|
||||
|
||||
// We may copy to only one aspect at a time, but pipeline
|
||||
// barriers need to have all available aspect bits set
|
||||
auto dstFormatInfo = image->formatInfo();
|
||||
|
||||
auto dstSubresourceRange = vk::makeSubresourceRange(imageSubresource);
|
||||
dstSubresourceRange.aspectMask = dstFormatInfo->aspectMask;
|
||||
|
||||
if (m_execBarriers.isImageDirty(image, dstSubresourceRange, DxvkAccess::Write)
|
||||
|| m_execBarriers.isBufferDirty(bufferSlice, DxvkAccess::Read))
|
||||
m_execBarriers.recordCommands(m_cmd);
|
||||
|
||||
// Initialize the image if the entire subresource is covered
|
||||
VkImageLayout dstImageLayoutInitial = image->info().layout;
|
||||
VkImageLayout dstImageLayoutTransfer = image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||
|
||||
if (image->isFullSubresource(imageSubresource, imageExtent))
|
||||
dstImageLayoutInitial = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
|
||||
m_execAcquires.accessImage(
|
||||
image, dstSubresourceRange,
|
||||
dstImageLayoutInitial,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT, 0,
|
||||
dstImageLayoutTransfer,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT);
|
||||
|
||||
m_execAcquires.recordCommands(m_cmd);
|
||||
|
||||
this->copyImageBufferData<true>(DxvkCmdBuffer::ExecBuffer,
|
||||
image, imageSubresource, imageOffset, imageExtent, dstImageLayoutTransfer,
|
||||
bufferSlice, bufferRowAlignment, bufferSliceAlignment);
|
||||
|
||||
m_execBarriers.accessImage(
|
||||
image, dstSubresourceRange,
|
||||
dstImageLayoutTransfer,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
image->info().layout,
|
||||
image->info().stages,
|
||||
image->info().access);
|
||||
|
||||
m_execBarriers.accessBuffer(bufferSlice,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT,
|
||||
VK_ACCESS_TRANSFER_READ_BIT,
|
||||
buffer->info().stages,
|
||||
buffer->info().access);
|
||||
|
||||
m_cmd->trackResource<DxvkAccess::Write>(image);
|
||||
m_cmd->trackResource<DxvkAccess::Read>(buffer);
|
||||
}
|
||||
|
||||
|
||||
void DxvkContext::copyBufferToImageFb(
|
||||
const Rc<DxvkImage>& image,
|
||||
const VkImageSubresourceLayers& imageSubresource,
|
||||
|
@ -547,6 +547,8 @@ namespace dxvk {
|
||||
* \param [in] srcOffset Source offset, in bytes
|
||||
* \param [in] rowAlignment Row alignment, in bytes
|
||||
* \param [in] sliceAlignment Slice alignment, in bytes
|
||||
* \param [in] srcFormat Buffer data format. May be
|
||||
* \c VK_FORMAT_UNKNOWN to use the image format.
|
||||
*/
|
||||
void copyBufferToImage(
|
||||
const Rc<DxvkImage>& dstImage,
|
||||
@ -556,7 +558,8 @@ namespace dxvk {
|
||||
const Rc<DxvkBuffer>& srcBuffer,
|
||||
VkDeviceSize srcOffset,
|
||||
VkDeviceSize rowAlignment,
|
||||
VkDeviceSize sliceAlignment);
|
||||
VkDeviceSize sliceAlignment,
|
||||
VkFormat srcFormat);
|
||||
|
||||
/**
|
||||
* \brief Copies data from one image to another
|
||||
@ -1508,6 +1511,16 @@ namespace dxvk {
|
||||
VkDeviceSize bufferRowAlignment,
|
||||
VkDeviceSize bufferSliceAlignment);
|
||||
|
||||
void copyBufferToImageHw(
|
||||
const Rc<DxvkImage>& image,
|
||||
const VkImageSubresourceLayers& imageSubresource,
|
||||
VkOffset3D imageOffset,
|
||||
VkExtent3D imageExtent,
|
||||
const Rc<DxvkBuffer>& buffer,
|
||||
VkDeviceSize bufferOffset,
|
||||
VkDeviceSize bufferRowAlignment,
|
||||
VkDeviceSize bufferSliceAlignment);
|
||||
|
||||
void copyBufferToImageFb(
|
||||
const Rc<DxvkImage>& image,
|
||||
const VkImageSubresourceLayers& imageSubresource,
|
||||
|
Loading…
x
Reference in New Issue
Block a user