mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-05-29 13:20:54 +00:00
Share code between Record and Merge Transitions
This commit is contained in:
@@ -49,6 +49,144 @@ bool VulkanResourceManager::SerialisableResource(ResourceId id, VkResourceRecord
|
||||
#define TRDBG(...)
|
||||
#endif
|
||||
|
||||
template<typename SrcTransType>
|
||||
void VulkanResourceManager::RecordSingleTransition(vector< pair<ResourceId, ImageRegionState> > &dsttrans, ResourceId id, const SrcTransType &t, uint32_t nummips, uint32_t numslices)
|
||||
{
|
||||
bool done = false;
|
||||
|
||||
auto it = dsttrans.begin();
|
||||
for(; it != dsttrans.end(); ++it)
|
||||
{
|
||||
// image transitions are handled by initially inserting one subresource range for each aspect,
|
||||
// and whenever we need more fine-grained detail we split it immediately for one range for
|
||||
// each subresource in that aspect. Thereafter if a transition comes in that covers multiple
|
||||
// subresources, we transition all matching ranges.
|
||||
|
||||
// find the transitions matching this id
|
||||
if(it->first < id) continue;
|
||||
if(it->first != id) break;
|
||||
|
||||
if(it->second.subresourceRange.aspectMask & t.subresourceRange.aspectMask)
|
||||
{
|
||||
// we've found a range that completely matches our region, doesn't matter if that's
|
||||
// a whole image and the transition is the whole image, or it's one subresource.
|
||||
// note that for images with only one array/mip slice (e.g. render targets) we'll never
|
||||
// really have to worry about the else{} branch
|
||||
if(it->second.subresourceRange.baseMipLevel == t.subresourceRange.baseMipLevel &&
|
||||
it->second.subresourceRange.mipLevels == nummips &&
|
||||
it->second.subresourceRange.baseArrayLayer == t.subresourceRange.baseArrayLayer &&
|
||||
it->second.subresourceRange.arraySize == numslices)
|
||||
{
|
||||
// verify
|
||||
//RDCASSERT(it->second.state == t.oldLayout);
|
||||
|
||||
// apply it (prevstate is from the start of all transitions, so only set once)
|
||||
if(it->second.oldLayout == UNTRANSITIONED_IMG_STATE)
|
||||
it->second.oldLayout = t.oldLayout;
|
||||
it->second.newLayout = t.newLayout;
|
||||
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// this handles the case where the transition covers a number of subresources and we need
|
||||
// to transition each matching subresource. If the transition was only one mip & array slice
|
||||
// it would have hit the case above. Find each subresource within the range, transition it,
|
||||
// and continue (marking as done so whenever we stop finding matching ranges, we are
|
||||
// satisfied.
|
||||
//
|
||||
// note that regardless of how we lay out our subresources (slice-major or mip-major) the new
|
||||
// range could be sparse, but that's OK as we only break out of the loop once we go past the whole
|
||||
// aspect. Any subresources that don't match the range, after the split, will fail to meet any
|
||||
// of the handled cases, so we'll just continue processing.
|
||||
if(it->second.subresourceRange.mipLevels == 1 &&
|
||||
it->second.subresourceRange.arraySize == 1 &&
|
||||
it->second.subresourceRange.baseMipLevel >= t.subresourceRange.baseMipLevel &&
|
||||
it->second.subresourceRange.baseMipLevel < t.subresourceRange.baseMipLevel+nummips &&
|
||||
it->second.subresourceRange.baseArrayLayer >= t.subresourceRange.baseArrayLayer &&
|
||||
it->second.subresourceRange.baseArrayLayer < t.subresourceRange.baseArrayLayer+numslices)
|
||||
{
|
||||
// apply it (prevstate is from the start of all transitions, so only set once)
|
||||
if(it->second.oldLayout == UNTRANSITIONED_IMG_STATE)
|
||||
it->second.oldLayout = t.oldLayout;
|
||||
it->second.newLayout = t.newLayout;
|
||||
|
||||
// continue as there might be more, but we're done
|
||||
done = true;
|
||||
continue;
|
||||
}
|
||||
// finally handle the case where we have a range that covers a whole image but we need to
|
||||
// split it. If the transition covered the whole image too it would have hit the very first
|
||||
// case, so we know that the transition doesn't cover the whole range.
|
||||
// Also, if we've already done the split this case won't be hit and we'll either fall into
|
||||
// the case above, or we'll finish as we've covered the whole transition.
|
||||
else if(it->second.subresourceRange.mipLevels > 1 || it->second.subresourceRange.arraySize > 1)
|
||||
{
|
||||
pair<ResourceId, ImageRegionState> existing = *it;
|
||||
|
||||
// remember where we were in the array, as after this iterators will be
|
||||
// invalidated.
|
||||
size_t offs = it - dsttrans.begin();
|
||||
size_t count = it->second.subresourceRange.mipLevels * it->second.subresourceRange.arraySize;
|
||||
|
||||
// only insert count-1 as we want count entries total - one per subresource
|
||||
dsttrans.insert(it, count-1, existing);
|
||||
|
||||
// it now points at the first subresource, but we need to modify the ranges
|
||||
// to be valid
|
||||
it = dsttrans.begin()+offs;
|
||||
|
||||
for(size_t i=0; i < count; i++)
|
||||
{
|
||||
it->second.subresourceRange.mipLevels = 1;
|
||||
it->second.subresourceRange.arraySize = 1;
|
||||
|
||||
// slice-major
|
||||
it->second.subresourceRange.baseArrayLayer = uint32_t(i / existing.second.subresourceRange.mipLevels);
|
||||
it->second.subresourceRange.baseMipLevel = uint32_t(i % existing.second.subresourceRange.mipLevels);
|
||||
it++;
|
||||
}
|
||||
|
||||
// reset the iterator to point to the first subresource
|
||||
it = dsttrans.begin()+offs;
|
||||
|
||||
// the loop will continue after this point and look at the next subresources
|
||||
// so we need to check to see if the first subresource lies in the range here
|
||||
if(it->second.subresourceRange.baseMipLevel >= t.subresourceRange.baseMipLevel &&
|
||||
it->second.subresourceRange.baseMipLevel < t.subresourceRange.baseMipLevel+nummips &&
|
||||
it->second.subresourceRange.baseArrayLayer >= t.subresourceRange.baseArrayLayer &&
|
||||
it->second.subresourceRange.baseArrayLayer < t.subresourceRange.baseArrayLayer+numslices)
|
||||
{
|
||||
// apply it (prevstate is from the start of all transitions, so only set once)
|
||||
if(it->second.oldLayout == UNTRANSITIONED_IMG_STATE)
|
||||
it->second.oldLayout = t.oldLayout;
|
||||
it->second.newLayout = t.newLayout;
|
||||
|
||||
// continue as there might be more, but we're done
|
||||
done = true;
|
||||
}
|
||||
|
||||
// continue processing from here
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if we've gone past where the new subresource range would sit
|
||||
if(it->second.subresourceRange.aspectMask > t.subresourceRange.aspectMask)
|
||||
break;
|
||||
|
||||
// otherwise continue to try and find the subresource range
|
||||
}
|
||||
|
||||
if(done) return;
|
||||
|
||||
// we don't have an existing transition for this memory region, insert into place. it points to
|
||||
// where it should be inserted
|
||||
dsttrans.insert(it, std::make_pair(id, ImageRegionState(t.subresourceRange, t.oldLayout, t.newLayout)));
|
||||
}
|
||||
|
||||
void VulkanResourceManager::RecordTransitions(vector< pair<ResourceId, ImageRegionState> > &trans, map<ResourceId, ImageLayouts> &states,
|
||||
uint32_t numTransitions, const VkImageMemoryBarrier *transitions)
|
||||
{
|
||||
@@ -65,139 +203,7 @@ void VulkanResourceManager::RecordTransitions(vector< pair<ResourceId, ImageRegi
|
||||
if(nummips == VK_REMAINING_MIP_LEVELS) nummips = states[id].mipLevels - t.subresourceRange.baseMipLevel;
|
||||
if(numslices == VK_REMAINING_ARRAY_LAYERS) numslices = states[id].arraySize - t.subresourceRange.baseArrayLayer;
|
||||
|
||||
bool done = false;
|
||||
|
||||
auto it = trans.begin();
|
||||
for(; it != trans.end(); ++it)
|
||||
{
|
||||
// image transitions are handled by initially inserting one subresource range for each aspect,
|
||||
// and whenever we need more fine-grained detail we split it immediately for one range for
|
||||
// each subresource in that aspect. Thereafter if a transition comes in that covers multiple
|
||||
// subresources, we transition all matching ranges.
|
||||
|
||||
// find the transitions matching this id
|
||||
if(it->first < id) continue;
|
||||
if(it->first != id) break;
|
||||
|
||||
if(it->second.subresourceRange.aspectMask & t.subresourceRange.aspectMask)
|
||||
{
|
||||
// we've found a range that completely matches our region, doesn't matter if that's
|
||||
// a whole image and the transition is the whole image, or it's one subresource.
|
||||
// note that for images with only one array/mip slice (e.g. render targets) we'll never
|
||||
// really have to worry about the else{} branch
|
||||
if(it->second.subresourceRange.baseMipLevel == t.subresourceRange.baseMipLevel &&
|
||||
it->second.subresourceRange.mipLevels == nummips &&
|
||||
it->second.subresourceRange.baseArrayLayer == t.subresourceRange.baseArrayLayer &&
|
||||
it->second.subresourceRange.arraySize == numslices)
|
||||
{
|
||||
// verify
|
||||
//RDCASSERT(it->second.state == t.oldLayout);
|
||||
|
||||
// apply it (prevstate is from the start of all transitions, so only set once)
|
||||
if(it->second.oldLayout == UNTRANSITIONED_IMG_STATE)
|
||||
it->second.oldLayout = t.oldLayout;
|
||||
it->second.newLayout = t.newLayout;
|
||||
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// this handles the case where the transition covers a number of subresources and we need
|
||||
// to transition each matching subresource. If the transition was only one mip & array slice
|
||||
// it would have hit the case above. Find each subresource within the range, transition it,
|
||||
// and continue (marking as done so whenever we stop finding matching ranges, we are
|
||||
// satisfied.
|
||||
//
|
||||
// note that regardless of how we lay out our subresources (slice-major or mip-major) the new
|
||||
// range could be sparse, but that's OK as we only break out of the loop once we go past the whole
|
||||
// aspect. Any subresources that don't match the range, after the split, will fail to meet any
|
||||
// of the handled cases, so we'll just continue processing.
|
||||
if(it->second.subresourceRange.mipLevels == 1 &&
|
||||
it->second.subresourceRange.arraySize == 1 &&
|
||||
it->second.subresourceRange.baseMipLevel >= t.subresourceRange.baseMipLevel &&
|
||||
it->second.subresourceRange.baseMipLevel < t.subresourceRange.baseMipLevel+nummips &&
|
||||
it->second.subresourceRange.baseArrayLayer >= t.subresourceRange.baseArrayLayer &&
|
||||
it->second.subresourceRange.baseArrayLayer < t.subresourceRange.baseArrayLayer+numslices)
|
||||
{
|
||||
// apply it (prevstate is from the start of all transitions, so only set once)
|
||||
if(it->second.oldLayout == UNTRANSITIONED_IMG_STATE)
|
||||
it->second.oldLayout = t.oldLayout;
|
||||
it->second.newLayout = t.newLayout;
|
||||
|
||||
// continue as there might be more, but we're done
|
||||
done = true;
|
||||
continue;
|
||||
}
|
||||
// finally handle the case where we have a range that covers a whole image but we need to
|
||||
// split it. If the transition covered the whole image too it would have hit the very first
|
||||
// case, so we know that the transition doesn't cover the whole range.
|
||||
// Also, if we've already done the split this case won't be hit and we'll either fall into
|
||||
// the case above, or we'll finish as we've covered the whole transition.
|
||||
else if(it->second.subresourceRange.mipLevels > 1 || it->second.subresourceRange.arraySize > 1)
|
||||
{
|
||||
pair<ResourceId, ImageRegionState> existing = *it;
|
||||
|
||||
// remember where we were in the array, as after this iterators will be
|
||||
// invalidated.
|
||||
size_t offs = it - trans.begin();
|
||||
size_t count = it->second.subresourceRange.mipLevels * it->second.subresourceRange.arraySize;
|
||||
|
||||
// only insert count-1 as we want count entries total - one per subresource
|
||||
trans.insert(it, count-1, existing);
|
||||
|
||||
// it now points at the first subresource, but we need to modify the ranges
|
||||
// to be valid
|
||||
it = trans.begin()+offs;
|
||||
|
||||
for(size_t i=0; i < count; i++)
|
||||
{
|
||||
it->second.subresourceRange.mipLevels = 1;
|
||||
it->second.subresourceRange.arraySize = 1;
|
||||
|
||||
// slice-major
|
||||
it->second.subresourceRange.baseArrayLayer = uint32_t(i / existing.second.subresourceRange.mipLevels);
|
||||
it->second.subresourceRange.baseMipLevel = uint32_t(i % existing.second.subresourceRange.mipLevels);
|
||||
it++;
|
||||
}
|
||||
|
||||
// reset the iterator to point to the first subresource
|
||||
it = trans.begin()+offs;
|
||||
|
||||
// the loop will continue after this point and look at the next subresources
|
||||
// so we need to check to see if the first subresource lies in the range here
|
||||
if(it->second.subresourceRange.baseMipLevel >= t.subresourceRange.baseMipLevel &&
|
||||
it->second.subresourceRange.baseMipLevel < t.subresourceRange.baseMipLevel+nummips &&
|
||||
it->second.subresourceRange.baseArrayLayer >= t.subresourceRange.baseArrayLayer &&
|
||||
it->second.subresourceRange.baseArrayLayer < t.subresourceRange.baseArrayLayer+numslices)
|
||||
{
|
||||
// apply it (prevstate is from the start of all transitions, so only set once)
|
||||
if(it->second.oldLayout == UNTRANSITIONED_IMG_STATE)
|
||||
it->second.oldLayout = t.oldLayout;
|
||||
it->second.newLayout = t.newLayout;
|
||||
|
||||
// continue as there might be more, but we're done
|
||||
done = true;
|
||||
}
|
||||
|
||||
// continue processing from here
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if we've gone past where the new subresource range would sit
|
||||
if(it->second.subresourceRange.aspectMask > t.subresourceRange.aspectMask)
|
||||
break;
|
||||
|
||||
// otherwise continue to try and find the subresource range
|
||||
}
|
||||
|
||||
if(done) continue;
|
||||
|
||||
// we don't have an existing transition for this memory region, insert into place. it points to
|
||||
// where it should be inserted
|
||||
trans.insert(it, std::make_pair(id, ImageRegionState(t.subresourceRange, t.oldLayout, t.newLayout)));
|
||||
RecordSingleTransition(trans, id, t, nummips, numslices);
|
||||
}
|
||||
|
||||
TRDBG("Post-record, there are %u transitions", (uint32_t)trans.size());
|
||||
@@ -210,145 +216,8 @@ void VulkanResourceManager::MergeTransitions(vector< pair<ResourceId, ImageRegio
|
||||
|
||||
for(size_t ti=0; ti < srctrans.size(); ti++)
|
||||
{
|
||||
ResourceId id = srctrans[ti].first;
|
||||
const ImageRegionState &t = srctrans[ti].second;
|
||||
|
||||
uint32_t nummips = t.subresourceRange.mipLevels;
|
||||
uint32_t numslices = t.subresourceRange.arraySize;
|
||||
|
||||
bool done = false;
|
||||
|
||||
auto it = dsttrans.begin();
|
||||
for(; it != dsttrans.end(); ++it)
|
||||
{
|
||||
// image transitions are handled by initially inserting one subresource range for each aspect,
|
||||
// and whenever we need more fine-grained detail we split it immediately for one range for
|
||||
// each subresource in that aspect. Thereafter if a transition comes in that covers multiple
|
||||
// subresources, we transition all matching ranges.
|
||||
|
||||
// find the transitions matching this id
|
||||
if(it->first < id) continue;
|
||||
if(it->first != id) break;
|
||||
|
||||
if(it->second.subresourceRange.aspectMask & t.subresourceRange.aspectMask)
|
||||
{
|
||||
// we've found a range that completely matches our region, doesn't matter if that's
|
||||
// a whole image and the transition is the whole image, or it's one subresource.
|
||||
// note that for images with only one array/mip slice (e.g. render targets) we'll never
|
||||
// really have to worry about the else{} branch
|
||||
if(it->second.subresourceRange.baseMipLevel == t.subresourceRange.baseMipLevel &&
|
||||
it->second.subresourceRange.mipLevels == nummips &&
|
||||
it->second.subresourceRange.baseArrayLayer == t.subresourceRange.baseArrayLayer &&
|
||||
it->second.subresourceRange.arraySize == numslices)
|
||||
{
|
||||
// verify
|
||||
//RDCASSERT(it->second.state == t.prevstate);
|
||||
|
||||
// apply it (prevstate is from the start of all transitions, so only set once)
|
||||
if(it->second.oldLayout == UNTRANSITIONED_IMG_STATE)
|
||||
it->second.oldLayout = t.oldLayout;
|
||||
it->second.newLayout = t.newLayout;
|
||||
|
||||
done = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// this handles the case where the transition covers a number of subresources and we need
|
||||
// to transition each matching subresource. If the transition was only one mip & array slice
|
||||
// it would have hit the case above. Find each subresource within the range, transition it,
|
||||
// and continue (marking as done so whenever we stop finding matching ranges, we are
|
||||
// satisfied.
|
||||
//
|
||||
// note that regardless of how we lay out our subresources (slice-major or mip-major) the new
|
||||
// range could be sparse, but that's OK as we only break out of the loop once we go past the whole
|
||||
// aspect. Any subresources that don't match the range, after the split, will fail to meet any
|
||||
// of the handled cases, so we'll just continue processing.
|
||||
if(it->second.subresourceRange.mipLevels == 1 &&
|
||||
it->second.subresourceRange.arraySize == 1 &&
|
||||
it->second.subresourceRange.baseMipLevel >= t.subresourceRange.baseMipLevel &&
|
||||
it->second.subresourceRange.baseMipLevel < t.subresourceRange.baseMipLevel+nummips &&
|
||||
it->second.subresourceRange.baseArrayLayer >= t.subresourceRange.baseArrayLayer &&
|
||||
it->second.subresourceRange.baseArrayLayer < t.subresourceRange.baseArrayLayer+numslices)
|
||||
{
|
||||
// apply it (prevstate is from the start of all transitions, so only set once)
|
||||
if(it->second.oldLayout == UNTRANSITIONED_IMG_STATE)
|
||||
it->second.oldLayout = t.oldLayout;
|
||||
it->second.newLayout = t.newLayout;
|
||||
|
||||
// continue as there might be more, but we're done
|
||||
done = true;
|
||||
continue;
|
||||
}
|
||||
// finally handle the case where we have a range that covers a whole image but we need to
|
||||
// split it. If the transition covered the whole image too it would have hit the very first
|
||||
// case, so we know that the transition doesn't cover the whole range.
|
||||
// Also, if we've already done the split this case won't be hit and we'll either fall into
|
||||
// the case above, or we'll finish as we've covered the whole transition.
|
||||
else if(it->second.subresourceRange.mipLevels > 1 || it->second.subresourceRange.arraySize > 1)
|
||||
{
|
||||
pair<ResourceId, ImageRegionState> existing = *it;
|
||||
|
||||
// remember where we were in the array, as after this iterators will be
|
||||
// invalidated.
|
||||
size_t offs = it - dsttrans.begin();
|
||||
size_t count = it->second.subresourceRange.mipLevels * it->second.subresourceRange.arraySize;
|
||||
|
||||
// only insert count-1 as we want count entries total - one per subresource
|
||||
dsttrans.insert(it, count-1, existing);
|
||||
|
||||
// it now points at the first subresource, but we need to modify the ranges
|
||||
// to be valid
|
||||
it = dsttrans.begin()+offs;
|
||||
|
||||
for(size_t i=0; i < count; i++)
|
||||
{
|
||||
it->second.subresourceRange.mipLevels = 1;
|
||||
it->second.subresourceRange.arraySize = 1;
|
||||
|
||||
// slice-major
|
||||
it->second.subresourceRange.baseArrayLayer = uint32_t(i / existing.second.subresourceRange.mipLevels);
|
||||
it->second.subresourceRange.baseMipLevel = uint32_t(i % existing.second.subresourceRange.mipLevels);
|
||||
it++;
|
||||
}
|
||||
|
||||
// reset the iterator to point to the first subresource
|
||||
it = dsttrans.begin()+offs;
|
||||
|
||||
// the loop will continue after this point and look at the next subresources
|
||||
// so we need to check to see if the first subresource lies in the range here
|
||||
if(it->second.subresourceRange.baseMipLevel >= t.subresourceRange.baseMipLevel &&
|
||||
it->second.subresourceRange.baseMipLevel < t.subresourceRange.baseMipLevel+nummips &&
|
||||
it->second.subresourceRange.baseArrayLayer >= t.subresourceRange.baseArrayLayer &&
|
||||
it->second.subresourceRange.baseArrayLayer < t.subresourceRange.baseArrayLayer+numslices)
|
||||
{
|
||||
// apply it (prevstate is from the start of all transitions, so only set once)
|
||||
if(it->second.oldLayout == UNTRANSITIONED_IMG_STATE)
|
||||
it->second.oldLayout = t.oldLayout;
|
||||
it->second.newLayout = t.newLayout;
|
||||
|
||||
// continue as there might be more, but we're done
|
||||
done = true;
|
||||
}
|
||||
|
||||
// continue processing from here
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if we've gone past where the new subresource range would sit
|
||||
if(it->second.subresourceRange.aspectMask > t.subresourceRange.aspectMask)
|
||||
break;
|
||||
|
||||
// otherwise continue to try and find the subresource range
|
||||
}
|
||||
|
||||
if(done) continue;
|
||||
|
||||
// we don't have an existing transition for this memory region, insert into place. it points to
|
||||
// where it should be inserted
|
||||
dsttrans.insert(it, std::make_pair(id, ImageRegionState(t.subresourceRange, t.oldLayout, t.newLayout)));
|
||||
RecordSingleTransition(dsttrans, srctrans[ti].first, t, t.subresourceRange.mipLevels, t.subresourceRange.arraySize);
|
||||
}
|
||||
|
||||
TRDBG("Post-merge, there are %u transitions", (uint32_t)dsttrans.size());
|
||||
|
||||
@@ -99,8 +99,12 @@ class VulkanResourceManager : public ResourceManager<WrappedVkRes*, TypedRealHan
|
||||
}
|
||||
|
||||
// handling memory & image transitions
|
||||
template<typename SrcTransType>
|
||||
void RecordSingleTransition(vector< pair<ResourceId, ImageRegionState> > &trans, ResourceId id, const SrcTransType &t, uint32_t nummips, uint32_t numslices);
|
||||
|
||||
void RecordTransitions(vector< pair<ResourceId, ImageRegionState> > &trans, map<ResourceId, ImageLayouts> &states,
|
||||
uint32_t numTransitions, const VkImageMemoryBarrier *transitions);
|
||||
|
||||
void MergeTransitions(vector< pair<ResourceId, ImageRegionState> > &dsttrans,
|
||||
vector< pair<ResourceId, ImageRegionState> > &srctrans);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user