Autodesk: Avoid evicting graphics pipelines in use in resource garbage collection
Description of Change(s)
Removing use of GC_Threshold for the graphics pipeline registry. Replaced by use of recycle count (see.GarbageCollect call) to hold pipelines in use in the cache and prevent eviction by garbage collection.
This change will improve performance of USD editing as well. Without it, all graphics pipelines are evicted from the cache whenever garbage collection is called.
Graphics pipelines are bound at draw time and will always be evicted here by the GarbageCollector (for Metal, Vulkan). Using a recycle count of one prevents pipelines in use from being evicted from the registry. I removed the previous fix based on GC_Threshold. I did not encounter any issues with other resources in the registry and garbage collection so I this only applies to graphics pipelines.
Fixes Issue(s)
- N/A
- [X] I have verified that all unit tests pass with the proposed changes
- [X] I have submitted a signed Contributor License Agreement
Filed as internal issue #USD-9981
/AzurePipelines run
Azure Pipelines successfully started running 1 pipeline(s).
@erikaharrison-adsk Would it be possible to get more context on the issue and the fix? When are you seeing the issue?
When I run usdview with a simple asset using your change, upon exiting the program I get several Vulkan validation errors that lead me to think the graphics pipeline object isn't getting destroyed properly. Are you seeing anything like this?
Coding Error: in _VulkanDebugCallback at line 52 of pxr/imaging/hgiVulkan/diagnostic.cpp -- VULKAN_ERROR: Validation Error: [ VUID-vkDestroyDevice-device-00378 ] Object 0: handle = 0x7f96cf004350, type = VK_OBJECT_TYPE_DEVICE; Object 1: handle = 0x7ddd740000000051, type = VK_OBJECT_TYPE_PIPELINE_LAYOUT; | MessageID = 0x71500fba | OBJ ERROR : For VkDevice 0x7f96cf004350[], VkPipelineLayout 0x7ddd740000000051[] has not been destroyed. The Vulkan spec states: All child objects created on device must have been destroyed prior to destroying device (https://vulkan.lunarg.com/doc/view/1.3.243.0/linux/1.3-extensions/vkspec.html#VUID-vkDestroyDevice-device-00378)
Coding Error: in _VulkanDebugCallback at line 52 of pxr/imaging/hgiVulkan/diagnostic.cpp -- VULKAN_ERROR: Validation Error: [ VUID-vkDestroyDevice-device-00378 ] Object 0: handle = 0x7f96cf004350, type = VK_OBJECT_TYPE_DEVICE; Object 1: handle = 0x2a7f70000000053, type = VK_OBJECT_TYPE_PIPELINE; | MessageID = 0x71500fba | OBJ ERROR : For VkDevice 0x7f96cf004350[], VkPipeline 0x2a7f70000000053[] has not been destroyed. The Vulkan spec states: All child objects created on device must have been destroyed prior to destroying device (https://vulkan.lunarg.com/doc/view/1.3.243.0/linux/1.3-extensions/vkspec.html#VUID-vkDestroyDevice-device-00378)
Coding Error: in _VulkanDebugCallback at line 52 of pxr/imaging/hgiVulkan/diagnostic.cpp -- VULKAN_ERROR: Validation Error: [ VUID-vkDestroyDevice-device-00378 ] Object 0: handle = 0x7f96cf004350, type = VK_OBJECT_TYPE_DEVICE; Object 1: handle = 0x72303f0000000052, type = VK_OBJECT_TYPE_RENDER_PASS; | MessageID = 0x71500fba | OBJ ERROR : For VkDevice 0x7f96cf004350[], VkRenderPass 0x72303f0000000052[] has not been destroyed. The Vulkan spec states: All child objects created on device must have been destroyed prior to destroying device (https://vulkan.lunarg.com/doc/view/1.3.243.0/linux/1.3-extensions/vkspec.html#VUID-vkDestroyDevice-device-00378)
Coding Error: in _VulkanDebugCallback at line 52 of pxr/imaging/hgiVulkan/diagnostic.cpp -- VULKAN_ERROR: Validation Error: [ VUID-vkDestroyDevice-device-00378 ] Object 0: handle = 0x7f96cf004350, type = VK_OBJECT_TYPE_DEVICE; Object 1: handle = 0x7f79ad0000000050, type = VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT; | MessageID = 0x71500fba | OBJ ERROR : For VkDevice 0x7f96cf004350[], VkDescriptorSetLayout 0x7f79ad0000000050[] has not been destroyed. The Vulkan spec states: All child objects created on device must have been destroyed prior to destroying device (https://vulkan.lunarg.com/doc/view/1.3.243.0/linux/1.3-extensions/vkspec.html#VUID-vkDestroyDevice-device-00378)
Coding Error: in _VulkanDebugCallback at line 52 of pxr/imaging/hgiVulkan/diagnostic.cpp -- VULKAN_ERROR: Validation Error: [ VUID-vkDestroyDevice-device-00378 ] Object 0: handle = 0x7f96cf004350, type = VK_OBJECT_TYPE_DEVICE; Object 1: handle = 0x73b89b0000000057, type = VK_OBJECT_TYPE_FRAMEBUFFER; | MessageID = 0x71500fba | OBJ ERROR : For VkDevice 0x7f96cf004350[], VkFramebuffer 0x73b89b0000000057[] has not been destroyed. The Vulkan spec states: All child objects created on device must have been destroyed prior to destroying device (https://vulkan.lunarg.com/doc/view/1.3.243.0/linux/1.3-extensions/vkspec.html#VUID-vkDestroyDevice-device-00378)
@clach We have a SceneIndex-based HLOD system that updates the scene depending on the view. This issue caused continuous recreation of graphics pipelines and was a performance bottleneck. However, I could also recreate this with light USD editing; no graphics pipeline would survive garbage collection. I tested it on macOS/Metal, but we were also seeing this on webGPU. OpenGL does not have this problem due to indirect draw being different. I have not tried it on Vulkan.
Note: Noticed an issue with memory leaks. Added commit to address.
/AzurePipelines run
Azure Pipelines successfully started running 1 pipeline(s).