Forced reference images/samplers/views when using descriptor buffers

This commit is contained in:
baldurk
2025-06-09 16:34:00 +01:00
parent 5b5e4f9bbb
commit f86c36d4f6
3 changed files with 73 additions and 5 deletions
+2 -2
View File
@@ -2545,13 +2545,13 @@ void WrappedVulkan::StartFrameCapture(DeviceOwnedWindow devWnd)
// way of knowing how it's used
for(auto it = forced.begin(); it != forced.end(); ++it)
{
// reference the buffer
// reference the buffer/image
GetResourceManager()->MarkResourceFrameReferenced((*it)->GetResourceID(), eFrameRef_Read);
// and its backing memory
GetResourceManager()->MarkMemoryFrameReferenced((*it)->baseResourceMem, (*it)->memOffset,
(*it)->memSize, eFrameRef_ReadBeforeWrite);
// and sparse memory (yuck yuck yuck)
if((*it)->resType == eResBuffer && (*it)->resInfo)
if(((*it)->resType == eResBuffer || (*it)->resType == eResImage) && (*it)->resInfo)
GetResourceManager()->MarkSparseMapReferenced((*it)->resInfo);
}
}
@@ -173,12 +173,10 @@ static void MakeSubpassLoadRP(RPCreateInfo &info, const RPCreateInfo *origInfo,
}
DESTROY_IMPL(VkBufferView, DestroyBufferView)
DESTROY_IMPL(VkImageView, DestroyImageView)
DESTROY_IMPL(VkShaderModule, DestroyShaderModule)
DESTROY_IMPL(VkPipeline, DestroyPipeline)
DESTROY_IMPL(VkPipelineCache, DestroyPipelineCache)
DESTROY_IMPL(VkPipelineLayout, DestroyPipelineLayout)
DESTROY_IMPL(VkSampler, DestroySampler)
DESTROY_IMPL(VkDescriptorSetLayout, DestroyDescriptorSetLayout)
DESTROY_IMPL(VkDescriptorPool, DestroyDescriptorPool)
DESTROY_IMPL(VkSemaphore, DestroySemaphore)
@@ -192,6 +190,36 @@ DESTROY_IMPL(VkShaderEXT, DestroyShaderEXT)
#undef DESTROY_IMPL
void WrappedVulkan::vkDestroyImageView(VkDevice device, VkImageView obj, const VkAllocationCallbacks *)
{
if(obj == VK_NULL_HANDLE)
return;
VkImageView unwrappedObj = Unwrap(obj);
{
SCOPED_LOCK(m_ForcedReferencesLock);
m_ForcedReferences.removeOne(GetRecord(obj));
}
if(IsReplayMode(m_State))
m_CreationInfo.erase(GetResID(obj));
GetResourceManager()->ReleaseWrappedResource(obj, true);
ObjDisp(device)->DestroyImageView(Unwrap(device), unwrappedObj, NULL);
}
void WrappedVulkan::vkDestroySampler(VkDevice device, VkSampler obj, const VkAllocationCallbacks *)
{
if(obj == VK_NULL_HANDLE)
return;
VkSampler unwrappedObj = Unwrap(obj);
{
SCOPED_LOCK(m_ForcedReferencesLock);
m_ForcedReferences.removeOne(GetRecord(obj));
}
if(IsReplayMode(m_State))
m_CreationInfo.erase(GetResID(obj));
GetResourceManager()->ReleaseWrappedResource(obj, true);
ObjDisp(device)->DestroySampler(Unwrap(device), unwrappedObj, NULL);
}
void WrappedVulkan::vkDestroyAccelerationStructureKHR(VkDevice device, VkAccelerationStructureKHR obj,
const VkAllocationCallbacks *)
{
@@ -350,6 +378,11 @@ void WrappedVulkan::vkDestroyImage(VkDevice device, VkImage obj, const VkAllocat
if(obj == VK_NULL_HANDLE)
return;
{
SCOPED_LOCK(m_ForcedReferencesLock);
m_ForcedReferences.removeOne(GetRecord(obj));
}
VkImage unwrappedObj = Unwrap(obj);
GetResourceManager()->ReleaseWrappedResource(obj, true);
@@ -756,6 +789,11 @@ VkResult WrappedVulkan::vkCreateSampler(VkDevice device, const VkSamplerCreateIn
VkResourceRecord *record = GetResourceManager()->AddResourceRecord(*pSampler);
record->AddChunk(chunk);
// can't differentiate whether this sampler will be used with descriptor buffers, must force
// reference all samplers
if(DescriptorBuffers())
AddForcedReference(record);
const VkSamplerYcbcrConversionInfo *ycbcr =
(const VkSamplerYcbcrConversionInfo *)FindNextStruct(
pCreateInfo, VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO);
@@ -1814,6 +1814,15 @@ VkResult WrappedVulkan::vkBindImageMemory(VkDevice device, VkImage image, VkDevi
record->AddParent(memrecord);
// if the image was force-referenced, do the same with the memory
if(IsForcedReference(record))
{
// AddForcedReference will also call MarkResourceFrameReferenced() on the image in case
// we're currently capturing, do the same with the memory with the correct semantics.
GetResourceManager()->MarkMemoryFrameReferenced(
GetResID(mem), memOffset, record->resInfo->memreqs.size, eFrameRef_ReadBeforeWrite);
}
// images are a base resource but we want to track where their memory comes from.
// Anything that looks up a baseResource for an image knows not to chase further
// than the image.
@@ -2728,6 +2737,11 @@ VkResult WrappedVulkan::vkCreateImage(VkDevice device, const VkImageCreateInfo *
VkResourceRecord *record = GetResourceManager()->AddResourceRecord(*pImage);
record->AddChunk(chunk);
// can't differentiate whether this image will be used with descriptor buffers, must force
// reference all images
if(DescriptorBuffers())
AddForcedReference(record);
record->resInfo = new ResourceInfo();
record->resInfo->parentResInfo = record->resInfo;
ResourceInfo &resInfo = *record->resInfo;
@@ -3147,6 +3161,11 @@ VkResult WrappedVulkan::vkCreateImageView(VkDevice device, const VkImageViewCrea
record->AddChunk(chunk);
record->AddParent(imageRecord);
// can't differentiate whether this image will be used with descriptor buffers, must force
// reference all images
if(DescriptorBuffers())
AddForcedReference(record);
// store the base resource. Note images have a baseResource pointing
// to their memory, which we will also need so we store that separately
record->baseResource = imageRecord->GetResourceID();
@@ -3524,6 +3543,16 @@ VkResult WrappedVulkan::vkBindImageMemory2(VkDevice device, uint32_t bindInfoCou
// to memory mid-frame
imgrecord->AddChunk(chunk);
// if the image was force-referenced, do the same with the memory
if(IsForcedReference(imgrecord))
{
// AddForcedReference will also call MarkResourceFrameReferenced() on the buffer in case
// we're currently capturing, do the same with the memory with the correct semantics.
GetResourceManager()->MarkMemoryFrameReferenced(
GetResID(pBindInfos[i].memory), pBindInfos[i].memoryOffset,
imgrecord->resInfo->memreqs.size, eFrameRef_ReadBeforeWrite);
}
const VkBindImageMemorySwapchainInfoKHR *swapBind =
(const VkBindImageMemorySwapchainInfoKHR *)FindNextStruct(
&pBindInfos[i], VK_STRUCTURE_TYPE_BIND_IMAGE_MEMORY_SWAPCHAIN_INFO_KHR);
@@ -3785,11 +3814,12 @@ VkResult WrappedVulkan::vkCreateAccelerationStructureKHR(
GetResourceManager()->MarkDirtyResource(id);
if(pCreateInfo->type == VK_ACCELERATION_STRUCTURE_TYPE_BOTTOM_LEVEL_KHR ||
pCreateInfo->type == VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR)
pCreateInfo->type == VK_ACCELERATION_STRUCTURE_TYPE_GENERIC_KHR || DescriptorBuffers())
{
// We force reference BLASs as it is not feasible to track at the API level which TLASs
// reference them. We force ref generics too as they could bottom or top level so we
// conservatively assume they are bottom
// when descriptor buffers are enabled, we must force reference all ASs
AddForcedReference(record);
// in case we're currently capturing, immediately consider the AS as referenced