mirror of
https://github.com/doitsujin/dxvk.git
synced 2025-02-24 13:54:17 +01:00
[dxvk] Ignore uninitialized image subresources during relocation
This commit is contained in:
parent
de4de00e04
commit
e5482a2405
@ -6271,32 +6271,55 @@ namespace dxvk {
|
|||||||
const auto& info = imageInfos[i];
|
const auto& info = imageInfos[i];
|
||||||
auto oldStorage = info.image->storage();
|
auto oldStorage = info.image->storage();
|
||||||
|
|
||||||
VkImageMemoryBarrier2 dstBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2 };
|
// The source image may only be partially initialized. Ignore any subresources
|
||||||
dstBarrier.srcStageMask = info.image->info().stages;
|
// that aren't, but try to do process as much in one go as possible.
|
||||||
dstBarrier.srcAccessMask = info.image->info().access;
|
VkImageSubresourceRange availableSubresources = info.image->getAvailableSubresources();
|
||||||
dstBarrier.dstStageMask = info.image->info().stages;
|
|
||||||
dstBarrier.dstAccessMask = info.image->info().access;
|
|
||||||
dstBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
||||||
dstBarrier.newLayout = info.image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
|
||||||
dstBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
||||||
dstBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
||||||
dstBarrier.image = info.storage->getImageInfo().image;
|
|
||||||
dstBarrier.subresourceRange = info.image->getAvailableSubresources();
|
|
||||||
|
|
||||||
VkImageMemoryBarrier2 srcBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2 };
|
uint32_t mipStep = info.image->isInitialized(availableSubresources)
|
||||||
srcBarrier.srcStageMask = info.image->info().stages;
|
? availableSubresources.levelCount : 1u;
|
||||||
srcBarrier.srcAccessMask = info.image->info().access;
|
|
||||||
srcBarrier.dstStageMask = info.image->info().stages;
|
|
||||||
srcBarrier.dstAccessMask = info.image->info().access;
|
|
||||||
srcBarrier.oldLayout = info.image->info().layout;
|
|
||||||
srcBarrier.newLayout = info.image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
|
||||||
srcBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
||||||
srcBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
||||||
srcBarrier.image = oldStorage->getImageInfo().image;
|
|
||||||
srcBarrier.subresourceRange = info.image->getAvailableSubresources();
|
|
||||||
|
|
||||||
imageBarriers.push_back(dstBarrier);
|
for (uint32_t m = 0; m < availableSubresources.levelCount; m += mipStep) {
|
||||||
imageBarriers.push_back(srcBarrier);
|
VkImageSubresourceRange subresourceRange = availableSubresources;
|
||||||
|
subresourceRange.baseMipLevel = m;
|
||||||
|
subresourceRange.levelCount = mipStep;
|
||||||
|
|
||||||
|
uint32_t layerStep = info.image->isInitialized(subresourceRange)
|
||||||
|
? availableSubresources.layerCount : 1u;
|
||||||
|
|
||||||
|
for (uint32_t l = 0; l < availableSubresources.layerCount; l += layerStep) {
|
||||||
|
subresourceRange.baseArrayLayer = l;
|
||||||
|
subresourceRange.layerCount = layerStep;
|
||||||
|
|
||||||
|
if (info.image->isInitialized(subresourceRange)) {
|
||||||
|
VkImageMemoryBarrier2 dstBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2 };
|
||||||
|
dstBarrier.srcStageMask = info.image->info().stages;
|
||||||
|
dstBarrier.srcAccessMask = info.image->info().access;
|
||||||
|
dstBarrier.dstStageMask = info.image->info().stages;
|
||||||
|
dstBarrier.dstAccessMask = info.image->info().access;
|
||||||
|
dstBarrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
||||||
|
dstBarrier.newLayout = info.image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||||
|
dstBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||||
|
dstBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||||
|
dstBarrier.image = info.storage->getImageInfo().image;
|
||||||
|
dstBarrier.subresourceRange = subresourceRange;
|
||||||
|
|
||||||
|
VkImageMemoryBarrier2 srcBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2 };
|
||||||
|
srcBarrier.srcStageMask = info.image->info().stages;
|
||||||
|
srcBarrier.srcAccessMask = info.image->info().access;
|
||||||
|
srcBarrier.dstStageMask = info.image->info().stages;
|
||||||
|
srcBarrier.dstAccessMask = info.image->info().access;
|
||||||
|
srcBarrier.oldLayout = info.image->info().layout;
|
||||||
|
srcBarrier.newLayout = info.image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
|
||||||
|
srcBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||||
|
srcBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||||
|
srcBarrier.image = oldStorage->getImageInfo().image;
|
||||||
|
srcBarrier.subresourceRange = subresourceRange;
|
||||||
|
|
||||||
|
imageBarriers.push_back(dstBarrier);
|
||||||
|
imageBarriers.push_back(srcBarrier);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Submit all pending barriers in one go
|
// Submit all pending barriers in one go
|
||||||
@ -6349,6 +6372,8 @@ namespace dxvk {
|
|||||||
DxvkResourceImageInfo dstInfo = info.storage->getImageInfo();
|
DxvkResourceImageInfo dstInfo = info.storage->getImageInfo();
|
||||||
DxvkResourceImageInfo srcInfo = oldStorage->getImageInfo();
|
DxvkResourceImageInfo srcInfo = oldStorage->getImageInfo();
|
||||||
|
|
||||||
|
VkImageSubresourceRange availableSubresources = info.image->getAvailableSubresources();
|
||||||
|
|
||||||
// Iterate over all subresources and compute copy regions. We need
|
// Iterate over all subresources and compute copy regions. We need
|
||||||
// one region per mip or plane, so size the local array accordingly.
|
// one region per mip or plane, so size the local array accordingly.
|
||||||
small_vector<VkImageCopy2, 16> imageRegions;
|
small_vector<VkImageCopy2, 16> imageRegions;
|
||||||
@ -6362,23 +6387,54 @@ namespace dxvk {
|
|||||||
|
|
||||||
for (uint32_t p = 0; p < planeCount; p++) {
|
for (uint32_t p = 0; p < planeCount; p++) {
|
||||||
for (uint32_t m = 0; m < info.image->info().mipLevels; m++) {
|
for (uint32_t m = 0; m < info.image->info().mipLevels; m++) {
|
||||||
VkImageCopy2 region = { VK_STRUCTURE_TYPE_IMAGE_COPY_2 };
|
VkImageSubresourceRange subresourceRange = availableSubresources;
|
||||||
region.dstSubresource.aspectMask = formatInfo->aspectMask;
|
subresourceRange.baseMipLevel = m;
|
||||||
region.dstSubresource.mipLevel = m;
|
subresourceRange.levelCount = 1u;
|
||||||
region.dstSubresource.baseArrayLayer = 0;
|
|
||||||
region.dstSubresource.layerCount = info.image->info().numLayers;
|
|
||||||
region.srcSubresource = region.dstSubresource;
|
|
||||||
region.extent = info.image->mipLevelExtent(m);
|
|
||||||
|
|
||||||
if (formatInfo->flags.test(DxvkFormatFlag::MultiPlane)) {
|
uint32_t layerStep = info.image->isInitialized(subresourceRange)
|
||||||
region.dstSubresource.aspectMask = vk::getPlaneAspect(p);
|
? subresourceRange.layerCount : 1u;
|
||||||
region.srcSubresource.aspectMask = vk::getPlaneAspect(p);
|
|
||||||
|
|
||||||
region.extent.width /= formatInfo->planes[p].blockSize.width;
|
for (uint32_t l = 0; l < subresourceRange.layerCount; l += layerStep) {
|
||||||
region.extent.height /= formatInfo->planes[p].blockSize.height;
|
subresourceRange.baseArrayLayer = l;
|
||||||
|
subresourceRange.layerCount = layerStep;
|
||||||
|
|
||||||
|
if (info.image->isInitialized(subresourceRange)) {
|
||||||
|
VkImageCopy2 region = { VK_STRUCTURE_TYPE_IMAGE_COPY_2 };
|
||||||
|
region.dstSubresource.aspectMask = formatInfo->aspectMask;
|
||||||
|
region.dstSubresource.mipLevel = m;
|
||||||
|
region.dstSubresource.baseArrayLayer = l;
|
||||||
|
region.dstSubresource.layerCount = layerStep;
|
||||||
|
region.srcSubresource = region.dstSubresource;
|
||||||
|
region.extent = info.image->mipLevelExtent(m);
|
||||||
|
|
||||||
|
if (formatInfo->flags.test(DxvkFormatFlag::MultiPlane)) {
|
||||||
|
region.dstSubresource.aspectMask = vk::getPlaneAspect(p);
|
||||||
|
region.srcSubresource.aspectMask = vk::getPlaneAspect(p);
|
||||||
|
|
||||||
|
region.extent.width /= formatInfo->planes[p].blockSize.width;
|
||||||
|
region.extent.height /= formatInfo->planes[p].blockSize.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
imageRegions.push_back(region);
|
||||||
|
|
||||||
|
// Emit image barrier for this region. We could in theory transition the
|
||||||
|
// entire image in one go as long as all subresources are initialized,
|
||||||
|
// but there is usually no reason to do so.
|
||||||
|
VkImageMemoryBarrier2 dstBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2 };
|
||||||
|
dstBarrier.srcStageMask = info.image->info().stages;
|
||||||
|
dstBarrier.srcAccessMask = info.image->info().access;
|
||||||
|
dstBarrier.dstStageMask = info.image->info().stages;
|
||||||
|
dstBarrier.dstAccessMask = info.image->info().access;
|
||||||
|
dstBarrier.oldLayout = info.image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
||||||
|
dstBarrier.newLayout = info.image->info().layout;
|
||||||
|
dstBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||||
|
dstBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
||||||
|
dstBarrier.image = info.storage->getImageInfo().image;
|
||||||
|
dstBarrier.subresourceRange = vk::makeSubresourceRange(region.dstSubresource),
|
||||||
|
|
||||||
|
imageBarriers.push_back(dstBarrier);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
imageRegions.push_back(region);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -6393,22 +6449,7 @@ namespace dxvk {
|
|||||||
m_cmd->cmdCopyImage(DxvkCmdBuffer::ExecBuffer, ©);
|
m_cmd->cmdCopyImage(DxvkCmdBuffer::ExecBuffer, ©);
|
||||||
m_cmd->track(info.image, DxvkAccess::Write);
|
m_cmd->track(info.image, DxvkAccess::Write);
|
||||||
|
|
||||||
// Invalidate image and emit post-copy barrier to use the correct layout
|
|
||||||
invalidateImageWithUsage(info.image, Rc<DxvkResourceAllocation>(info.storage), info.usageInfo);
|
invalidateImageWithUsage(info.image, Rc<DxvkResourceAllocation>(info.storage), info.usageInfo);
|
||||||
|
|
||||||
VkImageMemoryBarrier2 dstBarrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER_2 };
|
|
||||||
dstBarrier.srcStageMask = info.image->info().stages;
|
|
||||||
dstBarrier.srcAccessMask = info.image->info().access;
|
|
||||||
dstBarrier.dstStageMask = info.image->info().stages;
|
|
||||||
dstBarrier.dstAccessMask = info.image->info().access;
|
|
||||||
dstBarrier.oldLayout = info.image->pickLayout(VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
|
||||||
dstBarrier.newLayout = info.image->info().layout;
|
|
||||||
dstBarrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
||||||
dstBarrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
||||||
dstBarrier.image = info.storage->getImageInfo().image;
|
|
||||||
dstBarrier.subresourceRange = info.image->getAvailableSubresources();
|
|
||||||
|
|
||||||
imageBarriers.push_back(dstBarrier);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Submit post-copy barriers
|
// Submit post-copy barriers
|
||||||
|
Loading…
x
Reference in New Issue
Block a user