Skip to content

vulkan: Link unskippable pipelines inline and help drain build jobs during stalls (Fixes #591) - #651

Open
jfpaardoo wants to merge 1 commit into
Revivedx:testfrom
jfpaardoo:perf/menu-stutter-pipeline-link
Open

jfpaardoo wants to merge 1 commit into
Revivedx:testfrom
jfpaardoo:perf/menu-stutter-pipeline-link

Conversation

@jfpaardoo

Copy link
Copy Markdown
Contributor

What this changes

Fixes #591.

In Alpha 5, inline pipeline links (link_now) were introduced to link ready shader stage libraries (0.2 ms each with VK_EXT_graphics_pipeline_library) directly on the render thread up to a budget (SAVAGEWIND_PIPE_LINK_MS, default 3 ms per frame), queuing any remaining pipeline creations to the background worker pool to be skipped while building.

However, for unskippable draws—such as one-shot targets (one_shot_target(), which includes blur capture and texture targets drawn once when opening the pause/inventory menu) and terrain arrays (draw_must_happen()):

  1. When opening the Weapons/Food/Quests inventory (TAB), dozens of icons and UI elements are drawn into one-shot targets. Once the 3 ms frame budget was exceeded, link_now returned false and queued the pipelines to the worker threads.
  2. But right after, line 8110 executed if (atomic_load(&pp->state) == 0 && (one_shot_target() || draw_must_happen())) wait_built(&pp->state);.
  3. Because these draws cannot be skipped, the render thread entered wait_built, stalling in a while (atomic_load(state) == 0) SDL_Delay(1); loop for every single unskippable pipeline while workers slowly processed the queue. On setups where worker threads were busy or where hundreds of menu items queued, this caused a 5-to-10-second freeze every time TAB was pressed.

This patch:

  1. Passes must_happen (one_shot_target() || draw_must_happen()) to link_now(pp, must_happen). When a draw cannot be skipped anyway, it bypasses the 3 ms budget to link inline immediately in ~0.2 ms rather than queuing to a worker and then blocking the render thread on it.
  2. In wait_built(), allows the calling thread (the render queue thread) to help execute pending build jobs from jobs_head (job_run_one()) and spin briefly with exec_relax() before sleeping SDL_Delay(1). If the job being waited on is queued, it is executed immediately on the spot, completely eliminating the idle stall.

How it was tested

  • Build verification: make runtime-objs -j8 compiled with 0 warnings or errors under MSYS2 UCRT64 / Clang.
  • Subsystem test suite:
    • make test-pc-controls: PASS
    • git diff --check: PASS
  • Verified pipeline linking and queue-stealing logic on unskippable draws.

Checklist

  • Based on the latest test and opened against test
  • Built and run locally, and checked in the game
  • No game files, keys, firmware, generated game code or save files in the changes

Copilot AI balanced review requested due to automatic review settings November 9, 2026 19:31

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has insufficient remaining quota. Try requesting a review at a lower effort level.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants