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,
|
cDstLayers = dstLayer,
|
||||||
cDstOffset = DstOffset,
|
cDstOffset = DstOffset,
|
||||||
cDstExtent = dstExtent,
|
cDstExtent = dstExtent,
|
||||||
|
cDstFormat = pDstTexture->GetPackedFormat(),
|
||||||
cSrcBuffer = pSrcTexture->GetMappedBuffer(srcSubresource),
|
cSrcBuffer = pSrcTexture->GetMappedBuffer(srcSubresource),
|
||||||
cSrcLayout = pSrcTexture->GetSubresourceLayout(srcAspectMask, srcSubresource),
|
cSrcLayout = pSrcTexture->GetSubresourceLayout(srcAspectMask, srcSubresource),
|
||||||
cSrcOffset = pSrcTexture->ComputeMappedOffset(srcSubresource, j, SrcOffset),
|
cSrcOffset = pSrcTexture->ComputeMappedOffset(srcSubresource, j, SrcOffset),
|
||||||
cSrcCoord = SrcOffset,
|
cSrcCoord = SrcOffset,
|
||||||
cSrcExtent = srcMipExtent,
|
cSrcExtent = srcMipExtent
|
||||||
cSrcFormat = pSrcTexture->GetPackedFormat()
|
|
||||||
] (DxvkContext* ctx) {
|
] (DxvkContext* ctx) {
|
||||||
if (cDstLayers.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
ctx->copyBufferToImage(cDstImage, cDstLayers, cDstOffset, cDstExtent,
|
||||||
ctx->copyBufferToImage(cDstImage, cDstLayers, cDstOffset, cDstExtent,
|
cSrcBuffer, cSrcOffset, cSrcLayout.RowPitch, cSrcLayout.DepthPitch,
|
||||||
cSrcBuffer, cSrcOffset, cSrcLayout.RowPitch, cSrcLayout.DepthPitch);
|
cDstFormat);
|
||||||
} 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);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
} else if (srcIsImage) {
|
} else if (srcIsImage) {
|
||||||
VkImageSubresourceLayers srcLayer = { srcAspectMask,
|
VkImageSubresourceLayers srcLayer = { srcAspectMask,
|
||||||
@ -5194,21 +5185,11 @@ namespace dxvk {
|
|||||||
cStagingSlice = std::move(StagingBuffer),
|
cStagingSlice = std::move(StagingBuffer),
|
||||||
cPackedFormat = pDstTexture->GetPackedFormat()
|
cPackedFormat = pDstTexture->GetPackedFormat()
|
||||||
] (DxvkContext* ctx) {
|
] (DxvkContext* ctx) {
|
||||||
if (cDstLayers.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
ctx->copyBufferToImage(cDstImage,
|
||||||
ctx->copyBufferToImage(cDstImage,
|
cDstLayers, cDstOffset, cDstExtent,
|
||||||
cDstLayers, cDstOffset, cDstExtent,
|
cStagingSlice.buffer(),
|
||||||
cStagingSlice.buffer(),
|
cStagingSlice.offset(), 0, 0,
|
||||||
cStagingSlice.offset(), 0, 0);
|
cPackedFormat);
|
||||||
} 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);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
// If the destination image is backed only by a buffer, we need to use
|
// If the destination image is backed only by a buffer, we need to use
|
||||||
|
@ -675,20 +675,10 @@ namespace dxvk {
|
|||||||
cSrcDepthPitch = subresourceLayout.DepthPitch,
|
cSrcDepthPitch = subresourceLayout.DepthPitch,
|
||||||
cPackedFormat = pResource->GetPackedFormat()
|
cPackedFormat = pResource->GetPackedFormat()
|
||||||
] (DxvkContext* ctx) {
|
] (DxvkContext* ctx) {
|
||||||
if (cDstSubresource.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
ctx->copyBufferToImage(
|
||||||
ctx->copyBufferToImage(
|
cDstImage, cDstSubresource, cDstOffset, cDstExtent,
|
||||||
cDstImage, cDstSubresource, cDstOffset, cDstExtent,
|
cSrcBuffer, cSrcOffset, cSrcRowPitch, cSrcDepthPitch,
|
||||||
cSrcBuffer, cSrcOffset, cSrcRowPitch, cSrcDepthPitch);
|
cPackedFormat);
|
||||||
} 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);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5082,22 +5082,11 @@ namespace dxvk {
|
|||||||
cOffset = alignedDestOffset,
|
cOffset = alignedDestOffset,
|
||||||
cPackedDSFormat = packedDSFormat
|
cPackedDSFormat = packedDSFormat
|
||||||
] (DxvkContext* ctx) {
|
] (DxvkContext* ctx) {
|
||||||
if (cDstLayers.aspectMask != (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) {
|
ctx->copyBufferToImage(
|
||||||
ctx->copyBufferToImage(
|
cDstImage, cDstLayers,
|
||||||
cDstImage, cDstLayers,
|
cOffset, cDstLevelExtent,
|
||||||
cOffset, cDstLevelExtent,
|
cSrcSlice.buffer(), cSrcSlice.offset(),
|
||||||
cSrcSlice.buffer(), cSrcSlice.offset(),
|
0, 0, cPackedDSFormat);
|
||||||
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);
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
TrackTextureMappingBufferSequenceNumber(pSrcTexture, SrcSubresource);
|
TrackTextureMappingBufferSequenceNumber(pSrcTexture, SrcSubresource);
|
||||||
|
@ -500,62 +500,19 @@ namespace dxvk {
|
|||||||
const Rc<DxvkBuffer>& srcBuffer,
|
const Rc<DxvkBuffer>& srcBuffer,
|
||||||
VkDeviceSize srcOffset,
|
VkDeviceSize srcOffset,
|
||||||
VkDeviceSize rowAlignment,
|
VkDeviceSize rowAlignment,
|
||||||
VkDeviceSize sliceAlignment) {
|
VkDeviceSize sliceAlignment,
|
||||||
this->spillRenderPass(true);
|
VkFormat srcFormat) {
|
||||||
this->prepareImage(dstImage, vk::makeSubresourceRange(dstSubresource));
|
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);
|
if (useFb) {
|
||||||
|
copyBufferToImageFb(dstImage, dstSubresource, dstOffset, dstExtent,
|
||||||
// We may copy to only one aspect at a time, but pipeline
|
srcBuffer, srcOffset, rowAlignment, sliceAlignment,
|
||||||
// barriers need to have all available aspect bits set
|
srcFormat ? srcFormat : dstImage->info().format);
|
||||||
auto dstFormatInfo = dstImage->formatInfo();
|
} else {
|
||||||
|
copyBufferToImageHw(dstImage, dstSubresource, dstOffset, dstExtent,
|
||||||
auto dstSubresourceRange = vk::makeSubresourceRange(dstSubresource);
|
srcBuffer, srcOffset, rowAlignment, sliceAlignment);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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(
|
void DxvkContext::copyBufferToImageFb(
|
||||||
const Rc<DxvkImage>& image,
|
const Rc<DxvkImage>& image,
|
||||||
const VkImageSubresourceLayers& imageSubresource,
|
const VkImageSubresourceLayers& imageSubresource,
|
||||||
|
@ -547,6 +547,8 @@ namespace dxvk {
|
|||||||
* \param [in] srcOffset Source offset, in bytes
|
* \param [in] srcOffset Source offset, in bytes
|
||||||
* \param [in] rowAlignment Row alignment, in bytes
|
* \param [in] rowAlignment Row alignment, in bytes
|
||||||
* \param [in] sliceAlignment Slice 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(
|
void copyBufferToImage(
|
||||||
const Rc<DxvkImage>& dstImage,
|
const Rc<DxvkImage>& dstImage,
|
||||||
@ -556,7 +558,8 @@ namespace dxvk {
|
|||||||
const Rc<DxvkBuffer>& srcBuffer,
|
const Rc<DxvkBuffer>& srcBuffer,
|
||||||
VkDeviceSize srcOffset,
|
VkDeviceSize srcOffset,
|
||||||
VkDeviceSize rowAlignment,
|
VkDeviceSize rowAlignment,
|
||||||
VkDeviceSize sliceAlignment);
|
VkDeviceSize sliceAlignment,
|
||||||
|
VkFormat srcFormat);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \brief Copies data from one image to another
|
* \brief Copies data from one image to another
|
||||||
@ -1508,6 +1511,16 @@ namespace dxvk {
|
|||||||
VkDeviceSize bufferRowAlignment,
|
VkDeviceSize bufferRowAlignment,
|
||||||
VkDeviceSize bufferSliceAlignment);
|
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(
|
void copyBufferToImageFb(
|
||||||
const Rc<DxvkImage>& image,
|
const Rc<DxvkImage>& image,
|
||||||
const VkImageSubresourceLayers& imageSubresource,
|
const VkImageSubresourceLayers& imageSubresource,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user