Fix image state merge with secondary command buffers.

If a secondary command buffer referenced an image but its layout is unknown, it remains unknown when merged into a primary command buffer.
This commit is contained in:
James Sumihiro
2025-04-10 08:42:13 -07:00
committed by Baldur Karlsson
parent 92c13a3247
commit c3f1ccc38e
2 changed files with 19 additions and 1 deletions
+9 -1
View File
@@ -941,7 +941,15 @@ void ImageState::Merge(rdcflatmap<ResourceId, ImageState> &states,
{
if(it == states.end() || dstIt->first < it->first)
{
it = states.insert(it, {dstIt->first, dstIt->second.InitialState()});
// If we're merging in an image state our source hasn't seen before, we first add an initial
// state for that image, then merge in the current image state. However, if the destination
// only referenced the image and never recorded an explicit layout transition the layout of
// that image will be unknown. In that case we copy it as-is to avoid improperly recording a
// transition back to initial state.
if(dstIt->second.subresourceStates.IsInitialised())
it = states.insert(it, {dstIt->first, dstIt->second.InitialState()});
else
it = states.insert(it, *dstIt);
}
else if(it->first < dstIt->first)
{
+10
View File
@@ -1593,6 +1593,16 @@ public:
m_value = ImageSubresourceState(VK_QUEUE_FAMILY_IGNORED, UNKNOWN_PREV_IMG_LAYOUT, refType);
}
bool IsInitialised() const
{
// When merging image states from a secondary command buffer into a primary, some of those image
// states may have been added in an unknown layout when the image was referenced and never
// updated. These cases need to be detected and handled separately, otherwise the layout
// transitions recorded to the primary may be improperly overwritten.
return (!m_values.empty() || m_value.oldLayout != UNKNOWN_PREV_IMG_LAYOUT ||
m_value.newLayout != UNKNOWN_PREV_IMG_LAYOUT);
}
void ToArray(rdcarray<ImageSubresourceStateForRange> &arr);
void FromArray(const rdcarray<ImageSubresourceStateForRange> &arr);