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

[dxvk] Optimize image layout transitions

This should reduce unnecessary execution dependencies when
transitioning image layouts before executing image copies.
This commit is contained in:
Philip Rebohle 2018-06-28 13:00:03 +02:00
parent 8c65203ac2
commit db2b6e1219
No known key found for this signature in database
GPG Key ID: C8CC613427A31C99
2 changed files with 37 additions and 45 deletions

View File

@ -650,7 +650,9 @@ namespace dxvk {
dstSubresource.baseArrayLayer, dstSubresource.baseArrayLayer,
dstSubresource.layerCount }; dstSubresource.layerCount };
m_barriers.recordCommands(m_cmd); if (m_barriers.isImageDirty(dstImage, dstSubresourceRange, DxvkAccess::Write)
|| m_barriers.isBufferDirty(srcSlice, DxvkAccess::Read))
m_barriers.recordCommands(m_cmd);
// Initialize the image if the entire subresource is covered // Initialize the image if the entire subresource is covered
VkImageLayout dstImageLayoutInitial = dstImage->info().layout; VkImageLayout dstImageLayoutInitial = dstImage->info().layout;
@ -659,16 +661,14 @@ namespace dxvk {
if (dstImage->isFullSubresource(dstSubresource, dstExtent)) if (dstImage->isFullSubresource(dstSubresource, dstExtent))
dstImageLayoutInitial = VK_IMAGE_LAYOUT_UNDEFINED; dstImageLayoutInitial = VK_IMAGE_LAYOUT_UNDEFINED;
m_barriers.accessImage( m_transitions.accessImage(
dstImage, dstSubresourceRange, dstImage, dstSubresourceRange,
dstImageLayoutInitial, dstImageLayoutInitial, 0, 0,
dstImage->info().stages,
dstImage->info().access,
dstImageLayoutTransfer, dstImageLayoutTransfer,
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT); VK_ACCESS_TRANSFER_WRITE_BIT);
m_barriers.recordCommands(m_cmd); m_transitions.recordCommands(m_cmd);
VkBufferImageCopy copyRegion; VkBufferImageCopy copyRegion;
copyRegion.bufferOffset = srcSlice.offset(); copyRegion.bufferOffset = srcSlice.offset();
@ -733,34 +733,26 @@ namespace dxvk {
VkImageLayout dstImageLayout = dstImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL); VkImageLayout dstImageLayout = dstImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
VkImageLayout srcImageLayout = srcImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); VkImageLayout srcImageLayout = srcImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
if (dstImageLayout != dstImage->info().layout) { VkImageLayout dstInitImageLayout = dstImage->info().layout;
VkImageLayout dstInitImageLayout = dstImage->info().layout;
if (dstImage->mipLevelExtent(dstSubresource.mipLevel) == extent) if (dstImage->isFullSubresource(dstSubresource, extent))
dstInitImageLayout = VK_IMAGE_LAYOUT_UNDEFINED; dstInitImageLayout = VK_IMAGE_LAYOUT_UNDEFINED;
m_barriers.accessImage( m_transitions.accessImage(
dstImage, dstSubresourceRange, dstImage, dstSubresourceRange,
dstInitImageLayout, dstInitImageLayout, 0, 0,
dstImage->info().stages, dstImageLayout,
dstImage->info().access, VK_PIPELINE_STAGE_TRANSFER_BIT,
dstImageLayout, VK_ACCESS_TRANSFER_WRITE_BIT);
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT);
}
if (srcImageLayout != srcImage->info().layout) { m_transitions.accessImage(
m_barriers.accessImage( srcImage, srcSubresourceRange,
srcImage, srcSubresourceRange, srcImage->info().layout, 0, 0,
srcImage->info().layout, srcImageLayout,
srcImage->info().stages, VK_PIPELINE_STAGE_TRANSFER_BIT,
srcImage->info().access, VK_ACCESS_TRANSFER_READ_BIT);
srcImageLayout,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_READ_BIT);
}
m_barriers.recordCommands(m_cmd); m_transitions.recordCommands(m_cmd);
if (dstSubresource.aspectMask == srcSubresource.aspectMask) { if (dstSubresource.aspectMask == srcSubresource.aspectMask) {
VkImageCopy imageRegion; VkImageCopy imageRegion;
@ -874,21 +866,21 @@ namespace dxvk {
srcSubresource.baseArrayLayer, srcSubresource.baseArrayLayer,
srcSubresource.layerCount }; srcSubresource.layerCount };
m_barriers.recordCommands(m_cmd); if (m_barriers.isImageDirty(srcImage, srcSubresourceRange, DxvkAccess::Write)
|| m_barriers.isBufferDirty(dstSlice, DxvkAccess::Write))
m_barriers.recordCommands(m_cmd);
// Select a suitable image layout for the transfer op // Select a suitable image layout for the transfer op
VkImageLayout srcImageLayoutTransfer = srcImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL); VkImageLayout srcImageLayoutTransfer = srcImage->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
m_barriers.accessImage( m_transitions.accessImage(
srcImage, srcSubresourceRange, srcImage, srcSubresourceRange,
srcImage->info().layout, srcImage->info().layout, 0, 0,
srcImage->info().stages,
srcImage->info().access,
srcImageLayoutTransfer, srcImageLayoutTransfer,
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_READ_BIT); VK_ACCESS_TRANSFER_READ_BIT);
m_barriers.recordCommands(m_cmd); m_transitions.recordCommands(m_cmd);
VkBufferImageCopy copyRegion; VkBufferImageCopy copyRegion;
copyRegion.bufferOffset = dstSlice.offset(); copyRegion.bufferOffset = dstSlice.offset();
@ -1043,8 +1035,7 @@ namespace dxvk {
const Rc<DxvkImage>& image, const Rc<DxvkImage>& image,
const VkImageSubresourceRange& subresources) { const VkImageSubresourceRange& subresources) {
m_barriers.accessImage(image, subresources, m_barriers.accessImage(image, subresources,
VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_UNDEFINED, 0, 0,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, 0,
image->info().layout, image->info().layout,
image->info().stages, image->info().stages,
image->info().access); image->info().access);
@ -1471,13 +1462,14 @@ namespace dxvk {
// Prepare the image layout. If the given extent covers // Prepare the image layout. If the given extent covers
// the entire image, we may discard its previous contents. // the entire image, we may discard its previous contents.
VkImageSubresourceRange subresourceRange; VkImageSubresourceRange subresourceRange;
subresourceRange.aspectMask = subresources.aspectMask; subresourceRange.aspectMask = formatInfo->aspectMask;
subresourceRange.baseMipLevel = subresources.mipLevel; subresourceRange.baseMipLevel = subresources.mipLevel;
subresourceRange.levelCount = 1; subresourceRange.levelCount = 1;
subresourceRange.baseArrayLayer = subresources.baseArrayLayer; subresourceRange.baseArrayLayer = subresources.baseArrayLayer;
subresourceRange.layerCount = subresources.layerCount; subresourceRange.layerCount = subresources.layerCount;
m_barriers.recordCommands(m_cmd); if (m_barriers.isImageDirty(image, subresourceRange, DxvkAccess::Write))
m_barriers.recordCommands(m_cmd);
// Initialize the image if the entire subresource is covered // Initialize the image if the entire subresource is covered
VkImageLayout imageLayoutInitial = image->info().layout; VkImageLayout imageLayoutInitial = image->info().layout;
@ -1486,16 +1478,14 @@ namespace dxvk {
if (image->isFullSubresource(subresources, imageExtent)) if (image->isFullSubresource(subresources, imageExtent))
imageLayoutInitial = VK_IMAGE_LAYOUT_UNDEFINED; imageLayoutInitial = VK_IMAGE_LAYOUT_UNDEFINED;
m_barriers.accessImage( m_transitions.accessImage(
image, subresourceRange, image, subresourceRange,
imageLayoutInitial, imageLayoutInitial, 0, 0,
image->info().stages,
image->info().access,
imageLayoutTransfer, imageLayoutTransfer,
VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_ACCESS_TRANSFER_WRITE_BIT); VK_ACCESS_TRANSFER_WRITE_BIT);
m_barriers.recordCommands(m_cmd); m_transitions.recordCommands(m_cmd);
// Copy contents of the staging buffer into the image. // Copy contents of the staging buffer into the image.
// Since our source data is tightly packed, we do not // Since our source data is tightly packed, we do not

View File

@ -631,7 +631,9 @@ namespace dxvk {
Rc<DxvkCommandList> m_cmd; Rc<DxvkCommandList> m_cmd;
DxvkContextFlags m_flags; DxvkContextFlags m_flags;
DxvkContextState m_state; DxvkContextState m_state;
DxvkBarrierSet m_barriers; DxvkBarrierSet m_barriers;
DxvkBarrierSet m_transitions;
// TODO implement this properly... // TODO implement this properly...
Rc<DxvkQueryPool> m_queryPools[3] = { nullptr, nullptr, nullptr }; Rc<DxvkQueryPool> m_queryPools[3] = { nullptr, nullptr, nullptr };