vulkan: Fix crash during async pipeline compilation and handle destruction - #39
Closed
olehkuznetsov wants to merge 1 commit into
Closed
vulkan: Fix crash during async pipeline compilation and handle destruction#39olehkuznetsov wants to merge 1 commit into
olehkuznetsov wants to merge 1 commit into
Conversation
olehkuznetsov
force-pushed
the
fix-mt-pipeline
branch
from
September 3, 2026 16:33
33da10f to
73cd30d
Compare
Author
|
Will be reviewed properly during upstream |
olehkuznetsov
force-pushed
the
fix-mt-pipeline
branch
2 times, most recently
from
September 4, 2026 15:28
b2b3bf5 to
112e50e
Compare
…ction - Track handles used by asynchronous compilation tasks using reference-counted task IDs, synchronizing all referencing tasks in DestroyAsyncHandle and only releasing shared handles when all tasks finish to prevent use-after-free. - Consolidate handle destruction across VkPipeline, VkPipelineLayout, VkRenderPass, and VkShaderModule using DestroyTrackedHandle to defer destruction until referencing async tasks complete. - Safely track and destroy associated VkPipelineCache instances across batched and shared pipeline creations, avoiding premature destruction. - Enforce bounds assertions in sync_handle and log fatal on worker exceptions to prevent silent invalid handle propagation. - Capture pipeline handles by value in completion callbacks to avoid dangling pointer references when futures are cleared. Bug: Test: existing Change-Id: I95e28781a53afd8d2d409d2a8ce343196a6a6964
olehkuznetsov
force-pushed
the
fix-mt-pipeline
branch
from
September 7, 2026 13:57
112e50e to
dac0262
Compare
Author
|
Taking upstream version |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
When replaying traces with parallel pipeline creation enabled (
--pipeline-creation-jobs/--pcj), background worker threads compile pipelines asynchronously. Several edge cases in async handle tracking, handle destruction, and pipeline cache lifecycle caused driver crashes and race conditions.Key issues and fixes:
Reference-counted handle tracking across concurrent tasks:
Multiple async pipeline creation tasks frequently share common dependencies (
VkPipelineLayout,VkRenderPass,VkShaderModule). Previously, dependencies were tracked globally without task reference counting. When the first task finished, it cleared the handle, allowing premature destruction and use-after-free in subsequent tasks still compiling on background threads (e.g.SIGSEGVinSPIR_Parser::parse).struct AsyncTrackedHandle(async_tracked_handles_) and per-task sync callbacks inasync_task_sync_fns_. A handle is only cleared when all referencing tasks have finished. InDestroyAsyncHandle, all referencing tasks are synchronized before destroying the handle.Handle destruction lifecycle and consolidation:
Consolidate handle destruction across
VkPipeline,VkPipelineLayout,VkRenderPass, andVkShaderModuleviaDestroyTrackedHandle. Defer destruction when handles are tracked by active async tasks viaDestroyAsyncHandle.Intercept
VkPipelineLayoutdestruction:During async pipeline compilation, the main thread previously destroyed
VkPipelineLayouthandles immediately viavkDestroyPipelineLayoutbecause GFXReconstruct lacked an override, crashing background compilation threads accessing the layout.OverrideDestroyPipelineLayouttoreplay_overrides.jsonand defer layout destruction viaDestroyTrackedHandleuntil referencing async tasks complete.Shared pipeline cache lifecycle and dispatch ordering:
In batched creations or shared caches, multiple pipelines reference the same pipeline cache ID.
OverrideDestroyPipelinepreviously destroyed the cache on the first pipeline destruction, leading to assertion failures (tracked_pipeline_caches_) or missed cache saves. Additionally, capturingout_pipelines.data()by raw pointer into theMainThreadQueuecompletion callback caused dangling pointers because the result vector in the future's shared state is freed once all handles in the batch have synced their futures (object->future = {}).DestroyAssociatedPipelineCacheand track remaining correspondences (sameIdFound) sovkDestroyPipelineCacheandSavePipelineCacheexecute only after the last pipeline is destroyed. Capturepipeline_handlesby value into completion closures. InDestroyAsyncHandle, drainmain_thread_queue_.poll()after worker synchronization so cache registrations dispatch before destruction, and assert all referencing tasks have erased their IDs.Exception handling and future synchronization invariants:
In
sync_handle, unhandled worker thread exceptions could escape during handle synchronization.object->future_handle_index < async_handles.size()invariant viaGFXRECON_ASSERT, catchconst std::exception&withGFXRECON_LOG_FATALto fail fast with diagnostic information, and clearobject->future = {}upon resolution to release the future's shared state and prevent redundant synchronization.