mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-13 05:20:45 +00:00
Vulkan: Optimize image copies in Apply_InitialState
This uses the new image tracking to avoid unnecessary copying of image
data when applying the initial state.
This change only affects image resets when all of the following apply:
- The image initial contents tag is `BufferCopy` (not
`ClearColorImage` or `ClearDepthStencilImage`),
- The image is single sample,
- The image is non-sparse,
- The image has `ImgRefs` data,
- The image has been completely initialized at least once, and
- VulkanResourceManager::OptimizeInitialState() is true (currently
disabled by default).
When all of these conditions are met, data will only be copied for those
image subresources which require reset according to the ImgRefs data.
Change-Id: I449eabfe969229fa64e233760aaadb489776ee23
This commit is contained in:
committed by
Baldur Karlsson
parent
22203fbb02
commit
d6761de26d
@@ -38,49 +38,51 @@ TEST_CASE("Test ImgRefs type", "[imgrefs]")
|
||||
SECTION("unsplit")
|
||||
{
|
||||
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1));
|
||||
CHECK(imgRefs.SubresourceIndex(VK_IMAGE_ASPECT_STENCIL_BIT, 2, 5) == 0);
|
||||
CHECK(imgRefs.SubresourceIndex(imgRefs.AspectIndex(VK_IMAGE_ASPECT_STENCIL_BIT), 2, 5) == 0);
|
||||
};
|
||||
SECTION("split aspect")
|
||||
{
|
||||
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1));
|
||||
imgRefs.Split(true, false, false);
|
||||
CHECK(imgRefs.SubresourceIndex(VK_IMAGE_ASPECT_STENCIL_BIT, 2, 5) == 1);
|
||||
CHECK(imgRefs.SubresourceIndex(imgRefs.AspectIndex(VK_IMAGE_ASPECT_STENCIL_BIT), 2, 5) == 1);
|
||||
};
|
||||
SECTION("split levels")
|
||||
{
|
||||
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1));
|
||||
imgRefs.Split(false, true, false);
|
||||
CHECK(imgRefs.SubresourceIndex(VK_IMAGE_ASPECT_STENCIL_BIT, 2, 5) == 2);
|
||||
CHECK(imgRefs.SubresourceIndex(imgRefs.AspectIndex(VK_IMAGE_ASPECT_STENCIL_BIT), 2, 5) == 2);
|
||||
};
|
||||
SECTION("split layers")
|
||||
{
|
||||
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1));
|
||||
imgRefs.Split(false, false, true);
|
||||
CHECK(imgRefs.SubresourceIndex(VK_IMAGE_ASPECT_STENCIL_BIT, 2, 5) == 5);
|
||||
CHECK(imgRefs.SubresourceIndex(imgRefs.AspectIndex(VK_IMAGE_ASPECT_STENCIL_BIT), 2, 5) == 5);
|
||||
};
|
||||
SECTION("split aspect and levels")
|
||||
{
|
||||
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1));
|
||||
imgRefs.Split(true, true, false);
|
||||
CHECK(imgRefs.SubresourceIndex(VK_IMAGE_ASPECT_STENCIL_BIT, 2, 5) == 11 + 2);
|
||||
CHECK(imgRefs.SubresourceIndex(imgRefs.AspectIndex(VK_IMAGE_ASPECT_STENCIL_BIT), 2, 5) == 11 + 2);
|
||||
};
|
||||
SECTION("split aspect and layers")
|
||||
{
|
||||
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1));
|
||||
imgRefs.Split(true, false, true);
|
||||
CHECK(imgRefs.SubresourceIndex(VK_IMAGE_ASPECT_STENCIL_BIT, 2, 5) == 17 + 5);
|
||||
CHECK(imgRefs.SubresourceIndex(imgRefs.AspectIndex(VK_IMAGE_ASPECT_STENCIL_BIT), 2, 5) == 17 + 5);
|
||||
};
|
||||
SECTION("split levels and layers")
|
||||
{
|
||||
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1));
|
||||
imgRefs.Split(false, true, true);
|
||||
CHECK(imgRefs.SubresourceIndex(VK_IMAGE_ASPECT_STENCIL_BIT, 2, 5) == 2 * 17 + 5);
|
||||
CHECK(imgRefs.SubresourceIndex(imgRefs.AspectIndex(VK_IMAGE_ASPECT_STENCIL_BIT), 2, 5) ==
|
||||
2 * 17 + 5);
|
||||
};
|
||||
SECTION("split aspect and levels and layers")
|
||||
{
|
||||
ImgRefs imgRefs(ImageInfo(VK_FORMAT_D16_UNORM_S8_UINT, {100, 100, 1}, 11, 17, 1));
|
||||
imgRefs.Split(true, true, true);
|
||||
CHECK(imgRefs.SubresourceIndex(VK_IMAGE_ASPECT_STENCIL_BIT, 2, 5) == 11 * 17 + 2 * 17 + 5);
|
||||
CHECK(imgRefs.SubresourceIndex(imgRefs.AspectIndex(VK_IMAGE_ASPECT_STENCIL_BIT), 2, 5) ==
|
||||
11 * 17 + 2 * 17 + 5);
|
||||
};
|
||||
SECTION("update unsplit")
|
||||
{
|
||||
|
||||
@@ -1375,6 +1375,19 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten
|
||||
VkCommandBufferBeginInfo beginInfo = {VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO, NULL,
|
||||
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT};
|
||||
|
||||
ResourceId orig = GetResourceManager()->GetOriginalID(id);
|
||||
ImgRefs *imgRefs = NULL;
|
||||
bool initialized = false;
|
||||
if(GetResourceManager()->OptimizeInitialState())
|
||||
{
|
||||
imgRefs = GetResourceManager()->FindImgRefs(orig);
|
||||
if(imgRefs)
|
||||
{
|
||||
initialized = imgRefs->initializedLiveRes == live;
|
||||
imgRefs->initializedLiveRes = live;
|
||||
}
|
||||
}
|
||||
|
||||
if(initial.tag == VkInitialContents::Sparse)
|
||||
{
|
||||
Apply_SparseInitialState((WrappedVkImage *)live, initial);
|
||||
@@ -1882,6 +1895,24 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten
|
||||
SubmitAndFlushExtQueue(dstimBarrier.srcQueueFamilyIndex);
|
||||
}
|
||||
|
||||
std::vector<VkBufferImageCopy> copyRegions;
|
||||
std::vector<VkImageSubresourceRange> clearRegions;
|
||||
|
||||
#define INIT_REGION() \
|
||||
if(!initialized) \
|
||||
{ \
|
||||
copyRegions.push_back(region); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
InitReqType initReq = imgRefs->SubresourceInitReq( \
|
||||
imgRefs->AspectIndex((VkImageAspectFlagBits)region.imageSubresource.aspectMask), m, a); \
|
||||
if(initReq == eInitReq_Reset) \
|
||||
copyRegions.push_back(region); \
|
||||
else if(initReq == eInitReq_Clear) \
|
||||
clearRegions.push_back(ImageRange(region.imageSubresource)); \
|
||||
}
|
||||
|
||||
// copy each slice/mip individually
|
||||
for(int a = 0; a < m_CreationInfo.m_Image[id].arrayLayers; a++)
|
||||
{
|
||||
@@ -1919,8 +1950,7 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten
|
||||
|
||||
bufOffset += GetPlaneByteSize(extent.width, extent.height, extent.depth, fmt, 0, i);
|
||||
|
||||
ObjDisp(cmd)->CmdCopyBufferToImage(Unwrap(cmd), Unwrap(buf), ToHandle<VkImage>(live),
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||
INIT_REGION();
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -1934,8 +1964,7 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten
|
||||
// pass 0 for mip since we've already pre-downscaled extent
|
||||
bufOffset += GetByteSize(extent.width, extent.height, extent.depth, sizeFormat, 0);
|
||||
|
||||
ObjDisp(cmd)->CmdCopyBufferToImage(Unwrap(cmd), Unwrap(buf), ToHandle<VkImage>(live),
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||
INIT_REGION();
|
||||
|
||||
if(sizeFormat != fmt)
|
||||
{
|
||||
@@ -1947,8 +1976,7 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten
|
||||
|
||||
bufOffset += GetByteSize(extent.width, extent.height, extent.depth, VK_FORMAT_S8_UINT, 0);
|
||||
|
||||
ObjDisp(cmd)->CmdCopyBufferToImage(Unwrap(cmd), Unwrap(buf), ToHandle<VkImage>(live),
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, ®ion);
|
||||
INIT_REGION();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1959,6 +1987,32 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten
|
||||
}
|
||||
}
|
||||
|
||||
#undef INIT_REGION
|
||||
|
||||
if(copyRegions.size() > 0)
|
||||
ObjDisp(cmd)->CmdCopyBufferToImage(Unwrap(cmd), Unwrap(buf), ToHandle<VkImage>(live),
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
(uint32_t)copyRegions.size(), copyRegions.data());
|
||||
|
||||
if(clearRegions.size() > 0)
|
||||
{
|
||||
if(IsDepthOrStencilFormat(fmt))
|
||||
{
|
||||
VkClearDepthStencilValue val = {0, 0};
|
||||
ObjDisp(cmd)->CmdClearDepthStencilImage(Unwrap(cmd), ToHandle<VkImage>(live),
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &val,
|
||||
(uint32_t)clearRegions.size(), clearRegions.data());
|
||||
}
|
||||
else
|
||||
{
|
||||
VkClearColorValue val;
|
||||
memset(&val, 0, sizeof(val));
|
||||
ObjDisp(cmd)->CmdClearColorImage(Unwrap(cmd), ToHandle<VkImage>(live),
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &val,
|
||||
(uint32_t)clearRegions.size(), clearRegions.data());
|
||||
}
|
||||
}
|
||||
|
||||
// update the live image layout back
|
||||
dstimBarrier.oldLayout = dstimBarrier.newLayout;
|
||||
|
||||
|
||||
@@ -2930,7 +2930,7 @@ int ImgRefs::GetAspectCount() const
|
||||
return aspectCount;
|
||||
}
|
||||
|
||||
int ImgRefs::SubresourceIndex(VkImageAspectFlagBits aspect, int level, int layer) const
|
||||
int ImgRefs::AspectIndex(VkImageAspectFlagBits aspect) const
|
||||
{
|
||||
int aspectIndex = 0;
|
||||
if(areAspectsSplit)
|
||||
@@ -2943,7 +2943,7 @@ int ImgRefs::SubresourceIndex(VkImageAspectFlagBits aspect, int level, int layer
|
||||
++aspectIndex;
|
||||
}
|
||||
}
|
||||
return SubresourceIndex(aspectIndex, level, layer);
|
||||
return aspectIndex;
|
||||
}
|
||||
|
||||
int ImgRefs::SubresourceIndex(int aspectIndex, int level, int layer) const
|
||||
|
||||
@@ -1078,6 +1078,20 @@ struct ImageRange
|
||||
layerCount(range.layerCount)
|
||||
{
|
||||
}
|
||||
ImageRange(const VkBufferImageCopy &range)
|
||||
: aspectMask(range.imageSubresource.aspectMask),
|
||||
baseMipLevel(range.imageSubresource.mipLevel),
|
||||
levelCount(1),
|
||||
baseArrayLayer(range.imageSubresource.baseArrayLayer),
|
||||
layerCount(range.imageSubresource.layerCount),
|
||||
offset(range.imageOffset),
|
||||
extent(range.imageExtent)
|
||||
{
|
||||
}
|
||||
inline operator VkImageSubresourceRange() const
|
||||
{
|
||||
return {aspectMask, baseMipLevel, levelCount, baseArrayLayer, layerCount};
|
||||
}
|
||||
VkImageAspectFlags aspectMask = VK_IMAGE_ASPECT_FLAG_BITS_MAX_ENUM;
|
||||
uint32_t baseMipLevel = 0;
|
||||
uint32_t levelCount = VK_REMAINING_MIP_LEVELS;
|
||||
@@ -1115,16 +1129,20 @@ struct ImgRefs
|
||||
// Depth slices of 3D views are treated as array layers
|
||||
this->imageInfo.layerCount = imageInfo.extent.depth;
|
||||
}
|
||||
int SubresourceIndex(VkImageAspectFlagBits aspect, int level, int layer) const;
|
||||
int AspectIndex(VkImageAspectFlagBits aspect) const;
|
||||
int SubresourceIndex(int aspectIndex, int level, int layer) const;
|
||||
inline FrameRefType SubresourceRef(VkImageAspectFlagBits aspect, int level, int layer) const
|
||||
{
|
||||
return rangeRefs[SubresourceIndex(aspect, level, layer)];
|
||||
}
|
||||
inline FrameRefType SubresourceRef(int aspectIndex, int level, int layer) const
|
||||
{
|
||||
return rangeRefs[SubresourceIndex(aspectIndex, level, layer)];
|
||||
}
|
||||
inline InitReqType SubresourceInitReq(int aspectIndex, int level, int layer) const
|
||||
{
|
||||
return InitReq(SubresourceRef(aspectIndex, level, layer));
|
||||
}
|
||||
inline InitReqType SubresourceInitReq(int aspectIndex, int level, int layer, bool initialized) const
|
||||
{
|
||||
return InitReq(SubresourceRef(aspectIndex, level, layer));
|
||||
}
|
||||
void Split(bool splitAspects, bool splitLevels, bool splitLayers);
|
||||
template <typename Compose>
|
||||
FrameRefType Update(ImageRange range, FrameRefType refType, Compose comp);
|
||||
|
||||
Reference in New Issue
Block a user