Skip to content

agc: Driver::stop waits for every queued library prebuild, so the first session on a new build takes minutes to exit #8470

Closed

Description

@CPritch

Driver::stop calls CloseRegistrationPreparation() (Lifecycle.cpp:166) before device.Reset() (line 170), where the teardown pipeline-cache save runs (PipelineCache.cpp:86). RegistrationPreparePool::Close() waits until its queue is empty (ShaderRegistry.cpp:1205), and the prebuild pool has one thread unless APS5_PREBUILD_THREADS is set (line 1118). After a shader recompiler change, when many libraries are not in the driver's cache yet, every queued prebuild is built before the process can exit.

Measured on GTA V (PPSA04263 01.010.002), Performance mode, the time from SIGINT (SDL turns it into the normal quit path) to process exit:

  • Linux, RTX 5060 Laptop GPU, NVIDIA 615.71.09: 554 s on main eaa5c92 and 455 s on main d14a186, each the first run of that build.
  • Linux, RTX 4060, NVIDIA 580.126.20: 573 s on main eaa5c92, first run of that build.
  • The same builds on later runs, with warm caches: 1 to 3 s.

Each run did write the teardown save once the queue was empty. A player or script that ends the process before that loses every pipeline built in the session, so the next start is cold again.

Prebuilds only build libraries ahead of first use with a placeholder state, so skipping the queued ones at shutdown loses nothing a later run needs. I'd like to open a PR that drops the queued (not the running) prebuild tasks when the pool closes at shutdown, with a test that queues several and checks that close returns after the running one and that the queued ones never run. The shader-preparation pool and AwaitLibraryPrebuilds in device replacement would stay as they are.

@adriadam10, since this is the prebuild from #4152: is dropping queued prebuilds at shutdown acceptable, or would you rather they stay and the teardown save move ahead of the close?

AI-assisted: yes

Activity

  1. MarcZX10 commented on Oct 20, 2026

    @MarcZX10
    Contributor

    I traced the current pool lifecycle. CloseRegistrationPreparation() calls CloseAll(), which closes both the registration-preparation pool and the separate library-prebuild pool. AwaitLibraryPrebuilds() is also used during Vulkan device replacement, so any queue cancellation should be limited to shutdown and the prebuild pool; the device-replacement wait should keep draining normally.

    For shutdown, finishing the currently running prebuild, dropping only not-yet-started speculative prebuilds, and then continuing to device.Reset()/the pipeline-cache save seems consistent with the behavior described here. One detail for the implementation: discarded tasks need their unfinished tickets removed and idle waiters notified, or a concurrent AwaitSubmitted() could wait forever. The existing ShutdownThreads test already exercises pool shutdown; it could cover a blocked running task, queued tasks that must not run, and waiter wakeup.

  2. CPritch commented on Oct 20, 2026

    @CPritch
    ContributorAuthor

    Thanks @MarcZX10, that matches what I measured. The PR is up as #8678: the prebuild pool drops its not-started tasks at close, erases their tickets from unfinished and notifies idle, and waits for the running one; the preparation pool and the device-replacement wait are unchanged. The new ShutdownThreads case covers a blocked running prebuild and queued ones that must not run. I'll add the concurrent AwaitSubmitted waiter you mention to that test.

    GTA V, cold library caches, SIGINT to exit: 432 and 630 s on main against 2 s with the change (RTX 5060 Laptop, 615.71.09), and 859 and 865 s against 2 s (RTX 4060, 580.126.20).

    AI-assisted: yes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions