From f86c36d4f645fd4e4038cae2faaba8f57fafa751 Mon Sep 17 00:00:00 2001 From: baldurk Date: Mon, 9 Jun 2025 16:34:00 +0100 Subject: [PATCH] Forced reference images/samplers/views when using descriptor buffers --- renderdoc/driver/vulkan/vk_core.cpp | 4 +- .../driver/vulkan/wrappers/vk_misc_funcs.cpp | 42 ++++++++++++++++++- .../vulkan/wrappers/vk_resource_funcs.cpp | 32 +++++++++++++- 3 files changed, 73 insertions(+), 5 deletions(-) diff --git a/renderdoc/driver/vulkan/vk_core.cpp b/renderdoc/driver/vulkan/vk_core.cpp index 7ca8bd2a1..118b783a9 100644 --- a/renderdoc/driver/vulkan/vk_core.cpp +++ b/renderdoc/driver/vulkan/vk_core.cpp @@ -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); } } diff --git a/renderdoc/driver/vulkan/wrappers/vk_misc_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_misc_funcs.cpp index 3dd7d4f58..cffee70ae 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_misc_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_misc_funcs.cpp @@ -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); diff --git a/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp b/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp index e0cd82a63..17a973f38 100644 --- a/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp +++ b/renderdoc/driver/vulkan/wrappers/vk_resource_funcs.cpp @@ -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