Snapshot descriptor set Resource IDs when preparing initial states

* If we only copy the slot contents without converting Vk* handles to IDs then
  we run the risk that the resource will be deleted and re-allocated mid frame
  before we do that at serialise time.
* Instead we fetch IDs immediately and serialise as IDs, then look up the
  handles on replay
This commit is contained in:
baldurk
2019-05-14 14:36:15 +01:00
parent 0ae245c4a8
commit 8e2b608975
15 changed files with 129 additions and 49 deletions
+15 -2
View File
@@ -832,7 +832,7 @@ bool IsValid(const VkWriteDescriptorSet &write, uint32_t arrayElement)
return false;
}
void DescriptorSetSlot::RemoveBindRefs(VkResourceRecord *record)
void DescriptorSetBindingElement::RemoveBindRefs(VkResourceRecord *record)
{
SCOPED_LOCK(record->descInfo->refLock);
@@ -877,7 +877,7 @@ void DescriptorSetSlot::RemoveBindRefs(VkResourceRecord *record)
imageInfo.sampler = VK_NULL_HANDLE;
}
void DescriptorSetSlot::AddBindRefs(VkResourceRecord *record, FrameRefType ref)
void DescriptorSetBindingElement::AddBindRefs(VkResourceRecord *record, FrameRefType ref)
{
SCOPED_LOCK(record->descInfo->refLock);
@@ -910,3 +910,16 @@ void DescriptorSetSlot::AddBindRefs(VkResourceRecord *record, FrameRefType ref)
record->AddMemFrameRef(buf->baseResource, buf->memOffset, buf->memSize, ref);
}
}
void DescriptorSetSlot::CreateFrom(const DescriptorSetBindingElement &slot)
{
bufferInfo.buffer = GetResID(slot.bufferInfo.buffer);
bufferInfo.offset = slot.bufferInfo.offset;
bufferInfo.range = slot.bufferInfo.range;
imageInfo.sampler = GetResID(slot.imageInfo.sampler);
imageInfo.imageView = GetResID(slot.imageInfo.imageView);
imageInfo.imageLayout = slot.imageInfo.imageLayout;
texelBufferView = GetResID(slot.texelBufferView);
}
+34 -1
View File
@@ -368,7 +368,7 @@ FrameRefType GetRefType(VkDescriptorType descType);
// the possible contents of a descriptor set slot,
// taken from the VkWriteDescriptorSet
struct DescriptorSetSlot
struct DescriptorSetBindingElement
{
VkDescriptorBufferInfo bufferInfo;
VkDescriptorImageInfo imageInfo;
@@ -378,6 +378,39 @@ struct DescriptorSetSlot
void AddBindRefs(VkResourceRecord *record, FrameRefType ref);
};
// serialisable snapshot of descriptor set slots. Needed because if we snapshot
// DescriptorSetBindingElement
// the VkBuffer or VkImageView handles may have been deleted and recreated by the time we fetch
// their ResourceId
struct DescriptorSetSlotBufferInfo
{
ResourceId buffer;
VkDeviceSize offset;
VkDeviceSize range;
};
struct DescriptorSetSlotImageInfo
{
ResourceId sampler;
ResourceId imageView;
VkImageLayout imageLayout;
};
struct DescriptorSetSlot
{
void CreateFrom(const DescriptorSetBindingElement &slot);
// VkDescriptorBufferInfo
DescriptorSetSlotBufferInfo bufferInfo;
// VkDescriptorImageInfo
DescriptorSetSlotImageInfo imageInfo;
ResourceId texelBufferView;
};
DECLARE_REFLECTION_STRUCT(DescriptorSetSlotBufferInfo);
DECLARE_REFLECTION_STRUCT(DescriptorSetSlotImageInfo);
DECLARE_REFLECTION_STRUCT(DescriptorSetSlot);
bool IsValid(const VkWriteDescriptorSet &write, uint32_t arrayElement);
+1 -1
View File
@@ -3773,7 +3773,7 @@ void WrappedVulkan::AddUsage(VulkanDrawcallTreeNode &drawNode, vector<DebugMessa
for(uint32_t a = 0; a < layout.bindings[bind].descriptorCount; a++)
{
DescriptorSetSlot &slot = descset.currentBindings[bind][a];
DescriptorSetBindingElement &slot = descset.currentBindings[bind][a];
ResourceId id;
+1 -1
View File
@@ -678,7 +678,7 @@ private:
DescriptorSetInfo(bool p = false) : push(p) {}
~DescriptorSetInfo() { clear(); }
ResourceId layout;
vector<DescriptorSetSlot *> currentBindings;
vector<DescriptorSetBindingElement *> currentBindings;
bool push;
void clear()
+8 -7
View File
@@ -124,18 +124,18 @@ void DescSetLayout::Init(VulkanResourceManager *resourceMan, VulkanCreationInfo
}
}
void DescSetLayout::CreateBindingsArray(std::vector<DescriptorSetSlot *> &descBindings) const
void DescSetLayout::CreateBindingsArray(std::vector<DescriptorSetBindingElement *> &descBindings) const
{
descBindings.resize(bindings.size());
for(size_t i = 0; i < bindings.size(); i++)
{
descBindings[i] = new DescriptorSetSlot[bindings[i].descriptorCount];
memset(descBindings[i], 0, sizeof(DescriptorSetSlot) * bindings[i].descriptorCount);
descBindings[i] = new DescriptorSetBindingElement[bindings[i].descriptorCount];
memset(descBindings[i], 0, sizeof(DescriptorSetBindingElement) * bindings[i].descriptorCount);
}
}
void DescSetLayout::UpdateBindingsArray(const DescSetLayout &prevLayout,
std::vector<DescriptorSetSlot *> &descBindings) const
std::vector<DescriptorSetBindingElement *> &descBindings) const
{
// if we have fewer bindings now, delete the orphaned bindings arrays
for(size_t i = bindings.size(); i < prevLayout.bindings.size(); i++)
@@ -148,13 +148,14 @@ void DescSetLayout::UpdateBindingsArray(const DescSetLayout &prevLayout,
for(size_t i = 0; i < bindings.size(); i++)
{
// allocate new slot array
DescriptorSetSlot *newSlots = new DescriptorSetSlot[bindings[i].descriptorCount];
memset(newSlots, 0, sizeof(DescriptorSetSlot) * bindings[i].descriptorCount);
DescriptorSetBindingElement *newSlots =
new DescriptorSetBindingElement[bindings[i].descriptorCount];
memset(newSlots, 0, sizeof(DescriptorSetBindingElement) * bindings[i].descriptorCount);
// copy over any previous bindings that overlapped
if(i < prevLayout.bindings.size())
memcpy(newSlots, descBindings[i],
sizeof(DescriptorSetSlot) *
sizeof(DescriptorSetBindingElement) *
RDCMIN(prevLayout.bindings[i].descriptorCount, bindings[i].descriptorCount));
// delete old array, and assign the new one
+2 -2
View File
@@ -59,9 +59,9 @@ struct DescSetLayout
void Init(VulkanResourceManager *resourceMan, VulkanCreationInfo &info,
const VkDescriptorSetLayoutCreateInfo *pCreateInfo);
void CreateBindingsArray(std::vector<DescriptorSetSlot *> &descBindings) const;
void CreateBindingsArray(std::vector<DescriptorSetBindingElement *> &descBindings) const;
void UpdateBindingsArray(const DescSetLayout &prevLayout,
std::vector<DescriptorSetSlot *> &descBindings) const;
std::vector<DescriptorSetBindingElement *> &descBindings) const;
struct Binding
{
+23 -11
View File
@@ -69,7 +69,7 @@ bool WrappedVulkan::Prepare_InitialState(WrappedVkRes *res)
{
for(uint32_t b = 0; b < layout.bindings[i].descriptorCount; b++)
{
initialContents.descriptorSlots[e++] = record->descInfo->descBindings[i][b];
initialContents.descriptorSlots[e++].CreateFrom(record->descInfo->descBindings[i][b]);
}
}
}
@@ -637,7 +637,7 @@ uint64_t WrappedVulkan::GetSize_InitialState(ResourceId id, const VkInitialConte
for(size_t i = 0; i < layout.bindings.size(); i++)
NumBindings += layout.bindings[i].descriptorCount;
return 32 + NumBindings * sizeof(DescriptorSetSlot);
return 32 + NumBindings * sizeof(DescriptorSetBindingElement);
}
else if(initial.type == eResBuffer)
{
@@ -695,7 +695,7 @@ bool WrappedVulkan::Serialise_InitialState(SerialiserType &ser, ResourceId id,
RDCASSERT(record->descInfo && record->descInfo->layout);
const DescSetLayout &layout = *record->descInfo->layout;
Bindings = (DescriptorSetSlot *)initial->descriptorSlots;
Bindings = initial->descriptorSlots;
for(size_t i = 0; i < layout.bindings.size(); i++)
NumBindings += layout.bindings[i].descriptorCount;
@@ -785,9 +785,9 @@ bool WrappedVulkan::Serialise_InitialState(SerialiserType &ser, ResourceId id,
// skipping any invalid descriptors.
// quick check for slots that were completely uninitialised and so don't have valid data
if(descriptorCount == 1 && src->texelBufferView == VK_NULL_HANDLE &&
src->imageInfo.sampler == VK_NULL_HANDLE && src->imageInfo.imageView == VK_NULL_HANDLE &&
src->bufferInfo.buffer == VK_NULL_HANDLE)
if(descriptorCount == 1 && src->texelBufferView == ResourceId() &&
src->imageInfo.sampler == ResourceId() && src->imageInfo.imageView == ResourceId() &&
src->bufferInfo.buffer == ResourceId())
{
// do nothing - don't increment bind so that the same write descriptor is used next time.
continue;
@@ -804,7 +804,13 @@ bool WrappedVulkan::Serialise_InitialState(SerialiserType &ser, ResourceId id,
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
{
for(uint32_t d = 0; d < descriptorCount; d++)
dstImage[d] = src[d].imageInfo;
{
dstImage[d].imageView =
GetResourceManager()->GetLiveHandle<VkImageView>(src[d].imageInfo.imageView);
dstImage[d].sampler =
GetResourceManager()->GetLiveHandle<VkSampler>(src[d].imageInfo.sampler);
dstImage[d].imageLayout = src[d].imageInfo.imageLayout;
}
if(immutableSamplers)
{
@@ -823,7 +829,8 @@ bool WrappedVulkan::Serialise_InitialState(SerialiserType &ser, ResourceId id,
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
{
for(uint32_t d = 0; d < descriptorCount; d++)
dstTexelBuffer[d] = src[d].texelBufferView;
dstTexelBuffer[d] =
GetResourceManager()->GetLiveHandle<VkBufferView>(src[d].texelBufferView);
writes[bind].pTexelBufferView = dstTexelBuffer;
// NULL the others
@@ -837,7 +844,12 @@ bool WrappedVulkan::Serialise_InitialState(SerialiserType &ser, ResourceId id,
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
{
for(uint32_t d = 0; d < descriptorCount; d++)
dstBuffer[d] = src[d].bufferInfo;
{
dstBuffer[d].buffer =
GetResourceManager()->GetLiveHandle<VkBuffer>(src[d].bufferInfo.buffer);
dstBuffer[d].offset = src[d].bufferInfo.offset;
dstBuffer[d].range = src[d].bufferInfo.range;
}
writes[bind].pBufferInfo = dstBuffer;
// NULL the others
@@ -1308,13 +1320,13 @@ void WrappedVulkan::Apply_InitialState(WrappedVkRes *live, const VkInitialConten
// need to blat over the current descriptor set contents, so these are available
// when we want to fetch pipeline state
vector<DescriptorSetSlot *> &bindings = m_DescriptorSetState[id].currentBindings;
vector<DescriptorSetBindingElement *> &bindings = m_DescriptorSetState[id].currentBindings;
for(uint32_t i = 0; i < initial.numDescriptors; i++)
{
RDCASSERT(writes[i].dstBinding < bindings.size());
DescriptorSetSlot *bind = bindings[writes[i].dstBinding];
DescriptorSetBindingElement *bind = bindings[writes[i].dstBinding];
for(uint32_t d = 0; d < writes[i].descriptorCount; d++)
{
+1 -1
View File
@@ -1493,7 +1493,7 @@ void VulkanReplay::PatchReservedDescriptors(const VulkanStatePipeline &pipe,
if(bind.descriptorCount == 0 || bind.stageFlags == 0)
continue;
DescriptorSetSlot *slot = setInfo.currentBindings[b];
DescriptorSetBindingElement *slot = setInfo.currentBindings[b];
write.dstBinding = uint32_t(b + newBindingsCount);
write.dstArrayElement = 0;
+1 -1
View File
@@ -1403,7 +1403,7 @@ void VulkanReplay::SavePipelineState(uint32_t eventId)
dst.bindings.resize(m_pDriver->m_DescriptorSetState[src].currentBindings.size());
for(size_t b = 0; b < m_pDriver->m_DescriptorSetState[src].currentBindings.size(); b++)
{
DescriptorSetSlot *info = m_pDriver->m_DescriptorSetState[src].currentBindings[b];
DescriptorSetBindingElement *info = m_pDriver->m_DescriptorSetState[src].currentBindings[b];
const DescSetLayout::Binding &layoutBind = c.m_DescSetLayout[layoutId].bindings[b];
curBind.bind = (uint32_t)b;
+1 -1
View File
@@ -955,7 +955,7 @@ struct DescriptorSetData
// descriptor set bindings for this descriptor set. Filled out on
// create from the layout.
vector<DescriptorSetSlot *> descBindings;
vector<DescriptorSetBindingElement *> descBindings;
// lock protecting bindFrameRefs and bindMemRefs
Threading::CriticalSection refLock;
+19 -3
View File
@@ -3360,6 +3360,22 @@ void Deserialise(const VkDebugUtilsMessengerCreateInfoEXT &el)
// this isn't a real vulkan type, it's our own "anything that could be in a descriptor"
// structure that
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, DescriptorSetSlotImageInfo &el)
{
SERIALISE_MEMBER(sampler).TypedAs("VkSampler");
SERIALISE_MEMBER(imageView).TypedAs("VkImageView");
SERIALISE_MEMBER(imageLayout);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, DescriptorSetSlotBufferInfo &el)
{
SERIALISE_MEMBER(buffer).TypedAs("VkBuffer");
SERIALISE_MEMBER(offset);
SERIALISE_MEMBER(range);
}
template <typename SerialiserType>
void DoSerialise(SerialiserType &ser, DescriptorSetSlot &el)
{
@@ -3372,9 +3388,9 @@ void DoSerialise(SerialiserType &ser, DescriptorSetSlot &el)
ser.SetStructArg(
uint64_t(VkDescriptorImageInfoValidity::Sampler | VkDescriptorImageInfoValidity::ImageView));
SERIALISE_MEMBER(bufferInfo);
SERIALISE_MEMBER(imageInfo);
SERIALISE_MEMBER(texelBufferView);
SERIALISE_MEMBER(bufferInfo).TypedAs("VkDescriptorBufferInfo");
SERIALISE_MEMBER(imageInfo).TypedAs("VkDescriptorImageInfo");
SERIALISE_MEMBER(texelBufferView).TypedAs("VkBufferView");
}
template <typename SerialiserType>
+1 -1
View File
@@ -462,7 +462,7 @@ void VulkanRenderState::BindDescriptorSet(const DescSetLayout &descLayout, VkCom
push.descriptorType = bind.descriptorType;
push.descriptorCount = bind.descriptorCount;
DescriptorSetSlot *slots = setInfo.currentBindings[b];
DescriptorSetBindingElement *slots = setInfo.currentBindings[b];
if(push.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ||
push.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
@@ -3502,7 +3502,7 @@ void WrappedVulkan::ApplyPushDescriptorWrites(VkPipelineBindPoint pipelineBindPo
const DescSetLayout &desclayout = m_CreationInfo.m_DescSetLayout[descSetLayouts[set]];
std::vector<DescriptorSetSlot *> &bindings = m_DescriptorSetState[setId].currentBindings;
std::vector<DescriptorSetBindingElement *> &bindings = m_DescriptorSetState[setId].currentBindings;
ResourceId prevLayout = m_DescriptorSetState[setId].layout;
if(prevLayout == ResourceId())
@@ -3523,7 +3523,7 @@ void WrappedVulkan::ApplyPushDescriptorWrites(VkPipelineBindPoint pipelineBindPo
RDCASSERT(writeDesc.dstBinding < bindings.size());
DescriptorSetSlot **bind = &bindings[writeDesc.dstBinding];
DescriptorSetBindingElement **bind = &bindings[writeDesc.dstBinding];
const DescSetLayout::Binding *layoutBinding = &desclayout.bindings[writeDesc.dstBinding];
uint32_t curIdx = writeDesc.dstArrayElement;
@@ -653,13 +653,13 @@ void WrappedVulkan::ReplayDescriptorSetWrite(VkDevice device, const VkWriteDescr
ObjDisp(device)->UpdateDescriptorSets(Unwrap(device), 1, &unwrapped, 0, NULL);
// update our local tracking
std::vector<DescriptorSetSlot *> &bindings =
std::vector<DescriptorSetBindingElement *> &bindings =
m_DescriptorSetState[GetResID(writeDesc.dstSet)].currentBindings;
{
RDCASSERT(writeDesc.dstBinding < bindings.size());
DescriptorSetSlot **bind = &bindings[writeDesc.dstBinding];
DescriptorSetBindingElement **bind = &bindings[writeDesc.dstBinding];
layoutBinding = &layout.bindings[writeDesc.dstBinding];
curIdx = writeDesc.dstArrayElement;
@@ -733,8 +733,10 @@ void WrappedVulkan::ReplayDescriptorSetCopy(VkDevice device, const VkCopyDescrip
ResourceId srcSetId = GetResID(copyDesc.srcSet);
// update our local tracking
std::vector<DescriptorSetSlot *> &dstbindings = m_DescriptorSetState[dstSetId].currentBindings;
std::vector<DescriptorSetSlot *> &srcbindings = m_DescriptorSetState[srcSetId].currentBindings;
std::vector<DescriptorSetBindingElement *> &dstbindings =
m_DescriptorSetState[dstSetId].currentBindings;
std::vector<DescriptorSetBindingElement *> &srcbindings =
m_DescriptorSetState[srcSetId].currentBindings;
{
RDCASSERT(copyDesc.dstBinding < dstbindings.size());
@@ -748,8 +750,8 @@ void WrappedVulkan::ReplayDescriptorSetCopy(VkDevice device, const VkCopyDescrip
const DescSetLayout::Binding *layoutSrcBinding = &srclayout.bindings[copyDesc.srcBinding];
const DescSetLayout::Binding *layoutDstBinding = &dstlayout.bindings[copyDesc.dstBinding];
DescriptorSetSlot **dstbind = &dstbindings[copyDesc.dstBinding];
DescriptorSetSlot **srcbind = &srcbindings[copyDesc.srcBinding];
DescriptorSetBindingElement **dstbind = &dstbindings[copyDesc.dstBinding];
DescriptorSetBindingElement **srcbind = &srcbindings[copyDesc.srcBinding];
uint32_t curDstIdx = copyDesc.dstArrayElement;
uint32_t curSrcIdx = copyDesc.srcArrayElement;
@@ -986,7 +988,7 @@ void WrappedVulkan::vkUpdateDescriptorSets(VkDevice device, uint32_t writeCount,
RDCASSERT(descWrite.dstBinding < record->descInfo->descBindings.size());
DescriptorSetSlot **binding = &record->descInfo->descBindings[descWrite.dstBinding];
DescriptorSetBindingElement **binding = &record->descInfo->descBindings[descWrite.dstBinding];
const DescSetLayout::Binding *layoutBinding = &layout.bindings[descWrite.dstBinding];
@@ -1030,7 +1032,7 @@ void WrappedVulkan::vkUpdateDescriptorSets(VkDevice device, uint32_t writeCount,
curIdx = 0;
}
DescriptorSetSlot &bind = (*binding)[curIdx];
DescriptorSetBindingElement &bind = (*binding)[curIdx];
bind.RemoveBindRefs(record);
@@ -1080,9 +1082,9 @@ void WrappedVulkan::vkUpdateDescriptorSets(VkDevice device, uint32_t writeCount,
RDCASSERT(pDescriptorCopies[i].dstBinding < dstrecord->descInfo->descBindings.size());
RDCASSERT(pDescriptorCopies[i].srcBinding < srcrecord->descInfo->descBindings.size());
DescriptorSetSlot **dstbinding =
DescriptorSetBindingElement **dstbinding =
&dstrecord->descInfo->descBindings[pDescriptorCopies[i].dstBinding];
DescriptorSetSlot **srcbinding =
DescriptorSetBindingElement **srcbinding =
&srcrecord->descInfo->descBindings[pDescriptorCopies[i].srcBinding];
const DescSetLayout::Binding *dstlayoutBinding =
@@ -1114,7 +1116,7 @@ void WrappedVulkan::vkUpdateDescriptorSets(VkDevice device, uint32_t writeCount,
curSrcIdx = 0;
}
DescriptorSetSlot &bind = (*dstbinding)[curDstIdx];
DescriptorSetBindingElement &bind = (*dstbinding)[curDstIdx];
bind.RemoveBindRefs(dstrecord);
bind = (*srcbinding)[curSrcIdx];
@@ -1367,7 +1369,7 @@ void WrappedVulkan::vkUpdateDescriptorSetWithTemplate(
RDCASSERT(entry.dstBinding < record->descInfo->descBindings.size());
DescriptorSetSlot **binding = &record->descInfo->descBindings[entry.dstBinding];
DescriptorSetBindingElement **binding = &record->descInfo->descBindings[entry.dstBinding];
const DescSetLayout::Binding *layoutBinding = &layout.bindings[entry.dstBinding];
@@ -1398,7 +1400,7 @@ void WrappedVulkan::vkUpdateDescriptorSetWithTemplate(
const byte *src = (const byte *)pData + entry.offset + entry.stride * d;
DescriptorSetSlot &bind = (*binding)[curIdx];
DescriptorSetBindingElement &bind = (*binding)[curIdx];
bind.RemoveBindRefs(record);
+5 -2
View File
@@ -1328,8 +1328,11 @@ public:
SDObject *last = current.data.children.back();
last->type.name = name;
for(SDObject *obj : last->data.children)
obj->type.name = name;
if(last->type.basetype == SDBasic::Array)
{
for(SDObject *obj : last->data.children)
obj->type.name = name;
}
}
}