When updating descriptor bind refs, cache resource references

* This means we don't have to iterate the whole bindrefs array every time we
  want to propagate references in the background, but we can submit them in
  batch.
This commit is contained in:
baldurk
2020-07-31 13:50:01 +01:00
parent 0b061f4565
commit 035073fac9
6 changed files with 124 additions and 33 deletions
+36
View File
@@ -609,6 +609,7 @@ public:
void MarkResourceFrameReferenced(ResourceId id, FrameRefType refType, Compose comp);
inline void MarkResourceFrameReferenced(ResourceId id, FrameRefType refType);
void MarkBackgroundFrameReferenced(const rdcarray<rdcpair<ResourceId, FrameRefType>> &refs);
///////////////////////////////////////////
// Replay-side methods
@@ -809,6 +810,41 @@ ResourceManager<Configuration>::~ResourceManager()
RenderDoc::Inst().GetCrashHandler()->UnregisterMemoryRegion(this);
}
template <typename Configuration>
void ResourceManager<Configuration>::MarkBackgroundFrameReferenced(
const rdcarray<rdcpair<ResourceId, FrameRefType>> &refs)
{
SCOPED_LOCK(m_Lock);
if(IsBackgroundCapturing(m_State))
{
if(refs.size() <= m_ResourceRefTimes.size())
{
for(const rdcpair<ResourceId, FrameRefType> &ref : refs)
{
UpdateLastPartialUseTime(ref.first, ref.second);
UpdateLastWriteTime(ref.first, ref.second);
}
}
else
{
for(const ResourceRefTimes &res : m_ResourceRefTimes)
{
const rdcpair<ResourceId, FrameRefType> *it = std::lower_bound(
refs.begin(), refs.end(), make_rdcpair(res.id, eFrameRef_None),
[](const rdcpair<ResourceId, FrameRefType> &a,
const rdcpair<ResourceId, FrameRefType> &b) { return a.first < b.first; });
if(it != refs.end() && it->first == res.id)
{
UpdateLastPartialUseTime(it->first, it->second);
UpdateLastWriteTime(it->first, it->second);
}
}
}
}
}
template <typename Configuration>
template <typename Compose>
void ResourceManager<Configuration>::MarkResourceFrameReferenced(ResourceId id,
+48 -9
View File
@@ -1098,37 +1098,76 @@ void DescriptorSetSlot::RemoveBindRefs(VulkanResourceManager *rm, VkResourceReco
imageInfo.sampler = ResourceId();
}
void DescriptorSetSlot::AddBindRefs(VulkanResourceManager *rm, VkResourceRecord *record,
FrameRefType ref)
void DescriptorSetSlot::AddBindRefs(std::set<ResourceId> &ids, VulkanResourceManager *rm,
VkResourceRecord *record, FrameRefType ref)
{
SCOPED_LOCK(record->descInfo->refLock);
if(texelBufferView != ResourceId())
{
VkResourceRecord *bufView = rm->GetResourceRecord(texelBufferView);
record->AddBindFrameRef(bufView->GetResourceID(), eFrameRef_Read,
record->AddBindFrameRef(ids, bufView->GetResourceID(), eFrameRef_Read,
bufView->resInfo && bufView->resInfo->IsSparse());
if(bufView->baseResource != ResourceId())
record->AddBindFrameRef(bufView->baseResource, eFrameRef_Read);
record->AddBindFrameRef(ids, bufView->baseResource, eFrameRef_Read);
if(bufView->baseResourceMem != ResourceId())
record->AddMemFrameRef(bufView->baseResourceMem, bufView->memOffset, bufView->memSize, ref);
record->AddMemFrameRef(ids, bufView->baseResourceMem, bufView->memOffset, bufView->memSize,
ref);
}
if(imageInfo.imageView != ResourceId())
{
VkResourceRecord *view = rm->GetResourceRecord(imageInfo.imageView);
record->AddImgFrameRef(view, ref);
record->AddImgFrameRef(ids, view, ref);
}
if(imageInfo.sampler != ResourceId())
{
record->AddBindFrameRef(imageInfo.sampler, eFrameRef_Read);
record->AddBindFrameRef(ids, imageInfo.sampler, eFrameRef_Read);
}
if(bufferInfo.buffer != ResourceId())
{
VkResourceRecord *buf = rm->GetResourceRecord(bufferInfo.buffer);
record->AddBindFrameRef(bufferInfo.buffer, eFrameRef_Read,
record->AddBindFrameRef(ids, bufferInfo.buffer, eFrameRef_Read,
buf->resInfo && buf->resInfo->IsSparse());
if(buf->baseResource != ResourceId())
record->AddMemFrameRef(buf->baseResource, buf->memOffset, buf->memSize, ref);
record->AddMemFrameRef(ids, buf->baseResource, buf->memOffset, buf->memSize, ref);
}
}
void DescriptorSetData::UpdateBackgroundRefCache(VulkanResourceManager *resourceManager,
const std::set<ResourceId> &ids)
{
SCOPED_LOCK(refLock);
rdcpair<ResourceId, FrameRefType> *cacheit = backgroundFrameRefs.begin();
for(auto refit = ids.begin(); refit != ids.end(); ++refit)
{
ResourceId id = *refit;
FrameRefType refType = bindFrameRefs[id].second;
// find the Id we're looking for in the remainder of the cache. This won't skip over any one
// that we care about because we're iterating in ascending Id order
cacheit = std::lower_bound(
cacheit, backgroundFrameRefs.end(), make_rdcpair(id, eFrameRef_None),
[](const rdcpair<ResourceId, FrameRefType> &a, const rdcpair<ResourceId, FrameRefType> &b) {
return a.first < b.first;
});
// if we didn't find a match, insert the desired entry here
if(cacheit == backgroundFrameRefs.end() || cacheit->first != id)
{
// calculate the index
size_t idx = cacheit - backgroundFrameRefs.begin();
// insert the entry
backgroundFrameRefs.insert(idx, {id, refType});
// re-initialise our iterator to point here, as the above insert might have invalidated it due
// to a resize
cacheit = backgroundFrameRefs.begin() + idx;
}
else
{
// update the frameref
cacheit->second = refType;
}
}
}
+2 -1
View File
@@ -431,7 +431,8 @@ struct DescriptorSetSlotImageInfo
struct DescriptorSetSlot
{
void RemoveBindRefs(VulkanResourceManager *rm, VkResourceRecord *record);
void AddBindRefs(VulkanResourceManager *rm, VkResourceRecord *record, FrameRefType ref);
void AddBindRefs(std::set<ResourceId> &ids, VulkanResourceManager *rm, VkResourceRecord *record,
FrameRefType ref);
// VkDescriptorBufferInfo
DescriptorSetSlotBufferInfo bufferInfo;
+16 -7
View File
@@ -1063,9 +1063,14 @@ struct DescriptorSetData
// the refcount has the high-bit set if this resource has sparse
// mapping information
static const uint32_t SPARSE_REF_BIT = 0x80000000;
std::map<ResourceId, rdcpair<uint32_t, FrameRefType> > bindFrameRefs;
std::map<ResourceId, rdcpair<uint32_t, FrameRefType>> bindFrameRefs;
std::map<ResourceId, MemRefs> bindMemRefs;
std::map<ResourceId, ImageState> bindImageStates;
void UpdateBackgroundRefCache(VulkanResourceManager *resourceManager,
const std::set<ResourceId> &ids);
rdcarray<rdcpair<ResourceId, FrameRefType>> backgroundFrameRefs;
};
struct PipelineLayoutData
@@ -1818,7 +1823,7 @@ struct ImgRefs
}
InitReqType SubresourceRangeMaxInitReq(VkImageSubresourceRange range, InitPolicy policy,
bool initialized) const;
rdcarray<rdcpair<VkImageSubresourceRange, InitReqType> > SubresourceRangeInitReqs(
rdcarray<rdcpair<VkImageSubresourceRange, InitReqType>> SubresourceRangeInitReqs(
VkImageSubresourceRange range, InitPolicy policy, bool initialized) const;
void Split(bool splitAspects, bool splitLevels, bool splitLayers);
template <typename Compose>
@@ -2116,13 +2121,15 @@ public:
cmdInfo->memFrameRefs.swap(bakedCommands->cmdInfo->memFrameRefs);
}
void AddBindFrameRef(ResourceId id, FrameRefType ref, bool hasSparse = false)
void AddBindFrameRef(std::set<ResourceId> &ids, ResourceId id, FrameRefType ref,
bool hasSparse = false)
{
if(id == ResourceId())
{
RDCERR("Unexpected NULL resource ID being added as a bind frame ref");
return;
}
ids.insert(id);
rdcpair<uint32_t, FrameRefType> &p = descInfo->bindFrameRefs[id];
if((p.first & ~DescriptorSetData::SPARSE_REF_BIT) == 0)
{
@@ -2138,12 +2145,12 @@ public:
}
}
void AddImgFrameRef(VkResourceRecord *view, FrameRefType refType)
void AddImgFrameRef(std::set<ResourceId> &ids, VkResourceRecord *view, FrameRefType refType)
{
AddBindFrameRef(view->GetResourceID(), eFrameRef_Read,
AddBindFrameRef(ids, view->GetResourceID(), eFrameRef_Read,
view->resInfo && view->resInfo->IsSparse());
if(view->baseResourceMem != ResourceId())
AddBindFrameRef(view->baseResourceMem, eFrameRef_Read, false);
AddBindFrameRef(ids, view->baseResourceMem, eFrameRef_Read, false);
rdcpair<uint32_t, FrameRefType> &p = descInfo->bindFrameRefs[view->baseResource];
if((p.first & ~DescriptorSetData::SPARSE_REF_BIT) == 0)
@@ -2167,13 +2174,15 @@ public:
p.second = ComposeFrameRefsDisjoint(p.second, maxRef);
}
void AddMemFrameRef(ResourceId mem, VkDeviceSize offset, VkDeviceSize size, FrameRefType refType)
void AddMemFrameRef(std::set<ResourceId> &ids, ResourceId mem, VkDeviceSize offset,
VkDeviceSize size, FrameRefType refType)
{
if(mem == ResourceId())
{
RDCERR("Unexpected NULL resource ID being added as a bind frame ref");
return;
}
ids.insert(mem);
rdcpair<uint32_t, FrameRefType> &p = descInfo->bindFrameRefs[mem];
if((p.first & ~DescriptorSetData::SPARSE_REF_BIT) == 0)
{
@@ -1054,6 +1054,8 @@ void WrappedVulkan::vkUpdateDescriptorSets(VkDevice device, uint32_t writeCount,
// need to track descriptor set contents whether capframing or idle
if(IsCaptureMode(m_State))
{
std::set<ResourceId> ids;
for(uint32_t i = 0; i < writeCount; i++)
{
const VkWriteDescriptorSet &descWrite = pDescriptorWrites[i];
@@ -1089,6 +1091,8 @@ void WrappedVulkan::vkUpdateDescriptorSets(VkDevice device, uint32_t writeCount,
// start at the dstArrayElement
uint32_t curIdx = descWrite.dstArrayElement;
ids.clear();
for(uint32_t d = 0; d < descWrite.descriptorCount; d++, curIdx++)
{
// roll over onto the next binding, on the assumption that it is the same
@@ -1154,8 +1158,10 @@ void WrappedVulkan::vkUpdateDescriptorSets(VkDevice device, uint32_t writeCount,
bind.bufferInfo.SetFrom(descWrite.pBufferInfo[d]);
}
bind.AddBindRefs(GetResourceManager(), record, ref);
bind.AddBindRefs(ids, GetResourceManager(), record, ref);
}
record->descInfo->UpdateBackgroundRefCache(GetResourceManager(), ids);
}
// this is almost identical to the above loop, except that instead of sourcing the descriptors
@@ -1192,6 +1198,8 @@ void WrappedVulkan::vkUpdateDescriptorSets(VkDevice device, uint32_t writeCount,
uint32_t curSrcIdx = pDescriptorCopies[i].srcArrayElement;
uint32_t curDstIdx = pDescriptorCopies[i].dstArrayElement;
ids.clear();
for(uint32_t d = 0; d < pDescriptorCopies[i].descriptorCount; d++, curSrcIdx++, curDstIdx++)
{
if(srclayoutBinding->descriptorType == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT)
@@ -1230,8 +1238,10 @@ void WrappedVulkan::vkUpdateDescriptorSets(VkDevice device, uint32_t writeCount,
bind.RemoveBindRefs(GetResourceManager(), dstrecord);
bind = (*srcbinding)[curSrcIdx];
bind.AddBindRefs(GetResourceManager(), dstrecord, ref);
bind.AddBindRefs(ids, GetResourceManager(), dstrecord, ref);
}
dstrecord->descInfo->UpdateBackgroundRefCache(GetResourceManager(), ids);
}
}
}
@@ -1475,9 +1485,12 @@ void WrappedVulkan::vkUpdateDescriptorSetWithTemplate(
// need to track descriptor set contents whether capframing or idle
if(IsCaptureMode(m_State))
{
std::set<ResourceId> ids;
for(const VkDescriptorUpdateTemplateEntry &entry : tempInfo->updates)
{
VkResourceRecord *record = GetRecord(descriptorSet);
RDCASSERT(record->descInfo && record->descInfo->layout);
const DescSetLayout &layout = *record->descInfo->layout;
@@ -1493,6 +1506,8 @@ void WrappedVulkan::vkUpdateDescriptorSetWithTemplate(
// start at the dstArrayElement
uint32_t curIdx = entry.dstArrayElement;
ids.clear();
for(uint32_t d = 0; d < entry.descriptorCount; d++, curIdx++)
{
// roll over onto the next binding, on the assumption that it is the same
@@ -1559,8 +1574,10 @@ void WrappedVulkan::vkUpdateDescriptorSetWithTemplate(
bind.bufferInfo.SetFrom(*(const VkDescriptorBufferInfo *)src);
}
bind.AddBindRefs(GetResourceManager(), record, ref);
bind.AddBindRefs(ids, GetResourceManager(), record, ref);
}
record->descInfo->UpdateBackgroundRefCache(GetResourceManager(), ids);
}
}
}
@@ -1007,19 +1007,8 @@ VkResult WrappedVulkan::vkQueueSubmit(VkQueue queue, uint32_t submitCount,
SCOPED_LOCK(setrecord->descInfo->refLock);
for(auto refit = setrecord->descInfo->bindFrameRefs.begin();
refit != setrecord->descInfo->bindFrameRefs.end(); ++refit)
{
GetResourceManager()->MarkResourceFrameReferenced(refit->first, refit->second.second);
if(refit->second.first & DescriptorSetData::SPARSE_REF_BIT)
{
VkResourceRecord *sparserecord =
GetResourceManager()->GetResourceRecord(refit->first);
GetResourceManager()->MarkSparseMapReferenced(sparserecord->resInfo);
}
}
GetResourceManager()->MarkBackgroundFrameReferenced(
setrecord->descInfo->backgroundFrameRefs);
}
record->bakedCommands->AddResourceReferences(GetResourceManager());