Skip to content

fix(vk): graceful retired-pool eviction where retired imports were kept (Windows AMD and Intel) - #1906

Merged
NotRexed merged 1 commit into
NotRexed:mainfrom
kafasam:memory-leak-only
Nov 12, 2026
Merged

NotRexed merged 1 commit into
NotRexed:mainfrom
kafasam:memory-leak-only

Conversation

@kafasam

@kafasam kafasam commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

What

On Windows, AMD and Intel kept every retired texture pool's import for the whole session. This gives them back after an idle wait instead, so they stop accumulating. Nothing changes off Windows or on Windows NVIDIA.

Why

main's default per OS and vendor for a retired pool's import:

main this PR
Linux, any vendor given back as soon as the GPU is past it (issues 312, 413) same
Windows NVIDIA given back as soon as the GPU is past it (issue 1057) same
Windows AMD, Intel kept for the session (device losses right after a give-back: issues 17, 309, 571) given back after a wait

Kept, those retired pools only grow: multi-GB in a long session, until the system heap's budget is passed and new imports fail. RX_VK_KEEP_RETIRED=0 gives them back with no wait at all, which is the behaviour the device losses were reported against.

Changes

  • The wait (Windows AMD and Intel only). A retired pool's import goes back once the GPU is past it (same gates as before) and it has been retired for RX_VK_RETIRE_SECS seconds (default 30), oldest first. This happens whatever the memory pressure.
  • Pressure only shortens the wait. While the system heap is past RX_VK_IMPORT_HIGH percent of its budget (default 85, 0 turns it off), the wait is RX_VK_RETIRE_MIN_SECS seconds (default 2), until enough is queued to come down to RX_VK_IMPORT_LOW percent (75). Unlike imports_give_back's valve this one is on by default on Windows and is not limited to budgets under 12 GB, as it only frees pools nothing uses any more; the comments in both places say so.
  • RX_VK_KEEP_RETIRED: 1 keeps them for the session; 0, off, false or no gives them back as soon as the GPU is past them; unset or empty is the default in the table. Applies to every OS and vendor, as before.
  • The two valves no longer act on the same overshoot. What is queued in dead_imports is still in the driver's figure until the GPU is past it, so both valves count it as given back (only where retired imports wait; elsewhere imports_give_back reads what it read on main).
  • The numbers are read with env_int, the on/off switch with env_on.
  • The rule is in gpu/vk/retired_give_back.h with a check that needs no game or GPU: tests/test_retired_give_back.py.

Testing

  • tests/test_retired_give_back.py passes (the defaults by OS and vendor, the wait and its floor, the watermarks, a 20-area tour kept / at once / waited, the two valves not asking twice); gpu/vk/vk_memory.cpp compiles for Windows with llvm-mingw.
  • An earlier revision of the wait was run on an RX 6700 XT (12 GB) on Windows: 10 retired imports (704 MB) given back mid-session where main gave back none, no device loss. That was before this revision's changes and has not been repeated on it.
  • Not tested: Windows Intel Arc, the AMD parts that lost the device (Ally X, RX 6600), and the pressure path (never crossed 85% on that machine). Linux is not expected to change, and has not been run.

AI assistance disclosure: the design and fix were developed with AI assistance.

@hckrman101 hckrman101 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for picking this up, the session-long accumulation on Windows is real and a grace period is a reasonable idea. A few things before it can go in:

The branch carries two other PRs. The diff has 3 commits: #1439 (FSR 1 EASU+RCAS, the taau shaders and the vk_draw.cpp changes) and #1905 (FR_READBACK, vk_replay.cpp), with this PR's own commit 8fb0290 on top. The description says one file, 44/10, but the PR is +1200/-69 over 7 files, and it is 921 commits behind main and conflicts (#1439 and #1905 are also dirty). Please rebase onto current main with only the vk_memory.cpp commit so it can be reviewed and merged on its own. CI hasn't run on it either.

Linux changes behaviour too, and the description doesn't mention it. On main, Linux already gives retired imports back as soon as the GPU is past them (keep is false there). That was the fix for the amdgpu userptr submit cost (issues 312/413: every retired import checked at each CS, 3-4 fps in Kokiri). With this PR Linux waits 30 s, so the retired pools from a burst of merges stay in every submission's BO list for that long again. I'd keep Linux at once by default and put the grace period on the Windows path only.

The NVIDIA part is already fixed on main. The description and the new comment say every vendor leaked, but main's Windows default already gives retired imports back on NVIDIA (vendorID != 0x10DE, issue 1057, the RTX 3070 case). What this PR really changes is the Windows default for AMD and Intel, where give-back was turned off on purpose after device losses (Arc B390 entering Kokiri every time, issue 17; Ally X 309; RX 6600 571). The idea that those losses came from giving back too soon is plausible, but nothing has tested it yet: the one test is an RX 6700 XT (which OS? on Linux main would already show retired imports given back, so I guess Windows), and the pressure path, which drops the wait to 2 s and is close to the old behaviour, was never exercised. This needs runs on Windows Intel Arc and on the AMD parts that lost the device before the default flips there, and I'd leave that call to NotRexed.

The pressure valve and imports_give_back fire on the same submission and both act on the same overshoot (inline). Freeing retired imports doesn't lower the heap usage until dead_imports is reaped, so imports_give_back reads the same used a moment later and evicts live idle pools for the same deficit. On Linux with a budget under 12 GB both valves are on by default.

Nits: the comment in imports_give_back ("Off by default on Windows, as giving retired imports back is") is out of date after this. RX_VK_IMPORT_HIGH now defaults to 85 for the retired valve on Windows and 0 for the live one, and the retired valve skips the budget < 12 GB gate. That may be what you want, but say so in the comment.

Comment thread gpu/vk/vk_memory.cpp Outdated
// 85) the wait shortens to RX_VK_RETIRE_MIN_SECS seconds (default 2), down to RX_VK_IMPORT_LOW percent (75), and
// the free itself still waits for the GPU (dead_imports). RX_VK_KEEP_RETIRED=1 keeps them for the session; =0
// gives them back as soon as the GPU is past, both as before. The vendor split is gone: every vendor leaked by it
static const bool keep = getenv("RX_VK_KEEP_RETIRED") && getenv("RX_VK_KEEP_RETIRED")[0] != '0';

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

On Linux this used to be the whole default: keep false, so given back as soon as the GPU is past (issues 312/413, the amdgpu userptr CS cost). With idle_ms applied below, Linux now waits 30 s too. Suggest at_once defaulting to true off Windows, unless you've measured that the 30 s don't bring back the submit stall on RADV.

Comment thread gpu/vk/vk_memory.cpp Outdated
// RX_VK_RETIRE_SECS seconds (default 30), oldest first; past the system heap's RX_VK_IMPORT_HIGH percent (default
// 85) the wait shortens to RX_VK_RETIRE_MIN_SECS seconds (default 2), down to RX_VK_IMPORT_LOW percent (75), and
// the free itself still waits for the GPU (dead_imports). RX_VK_KEEP_RETIRED=1 keeps them for the session; =0
// gives them back as soon as the GPU is past, both as before. The vendor split is gone: every vendor leaked by it

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

"every vendor leaked by it": on main NVIDIA was already excluded from keep (issue 1057), so only AMD and Intel on Windows leaked. Worth saying, since those are the vendors whose device losses the old default was protecting against.

Comment thread gpu/vk/vk_memory.cpp Outdated
uint64_t want = 0;
if (!keep && !at_once && high > 0) {
static uint64_t calls = 0;
if (++calls % 16 == 0) {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This counter and imports_give_back's both run once per submission and reach % 16 on the same submission. What is pushed to dead_imports here isn't freed until the GPU is past it, so system_heap_usage returns the same used to imports_give_back right after, and it evicts live idle pools for the same want. Maybe pass the bytes queued here to imports_give_back and subtract them, or only probe in one place.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

You're right, and it was worse than one overshoot counted twice. Walking through it at 42ae0cd:

  • memory_begin_submission runs reap_mirrors(), then retired_imports_give_back(), then imports_give_back(), all under pools_mu, once per submission.
  • Each valve has its own static uint64_t calls, and each only counts when its own valve is enabled. Both conditions are fixed for the run (statics read once), so when both valves are on they count from the same first submission and stay in phase: they always hit % 16 == 0 on the same submission, not just sometimes.
  • The retired valve moved the pool's buffer and memory into dead_imports with value = max(mem_rec_value, last_value). Nothing is freed there. vkFreeMemory only happens in reap_mirrors() once mem_completed reaches that value, and reap_mirrors() has already run for this submission, so the earliest free is the next submission, and only if the GPU has finished this one.
  • system_heap_usage is the driver's figure (VK_EXT_memory_budget), so it cannot drop before that free. imports_give_back read the same used a few lines later, computed the same want, and evicted live idle pools for bytes that were already on their way out.
  • The same staleness also hit the retired valve itself: if the queued imports were not reaped within 16 submissions (a long GPU frame), its next probe asked for the same bytes again and shortened the wait for more pools than needed.

And as you said, at 42ae0cd this was on by default on Linux under a 12 GB budget, since the retired valve had no OS split.

What the new head (4808b1c) does, taking your first suggestion:

  • dead_import_bytes counts what sits in dead_imports: added at the push, subtracted in reap_mirrors() at the actual free.
  • The retired valve probes want(settled(used, dead_import_bytes), ...), so what it queued earlier counts as given back until it really is.
  • imports_give_back does used = settled(used, dead_import_bytes) before its watermark test, so it only evicts live pools for what the queued retired imports will not cover.
  • Off Windows the retired valve no longer probes at all (retired imports go back at every submission again, as on main), and imports_give_back skips the subtraction there, so Linux reads exactly what it read on main. The interplay is left only on Windows AMD/Intel with RX_VK_IMPORT_HIGH set by hand (the live valve defaults to off there), and that is the case the subtraction covers.

I kept two probes rather than one because the two valves have different gates on purpose (the live one is off on Windows and limited to budgets under 12 GB, the retired one is neither; the comments in both now say so). tests/retired_give_back_test.cpp has the case: 1 GB over, three pools queued, and the next probe with the same used asks for nothing.

@kafasam

kafasam commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor Author

Rebased as a single commit off current main (42ae0cd), unstacked per review: only gpu/vk/vk_memory.cpp and the leak's test fixture. Recap of the eviction policy: retired pools return to the driver only when the GPU has been quiet, the pool has been idle at least 2 s (RX_VK_RETIRE_MIN_SECS, default 2000 ms), and committed memory pressure has crossed 85% (relaxing back to 75% once under, so pools don't ping-pong).

@kafasam

kafasam commented Nov 11, 2026

Copy link
Copy Markdown
Contributor Author

That rebase landed as of this morning: the branch is now a single commit (42ae0cd) off current main — only gpu/vk/vk_memory.cpp and the leak's test fixture, +44/-10. The two stacked PRs you saw are gone (they live in #1439, itself rebased to main, and #1905 which closed in favour of #1276). The hysteresis numbers in the recap comment are corrected too: idle floor 2 s (RX_VK_RETIRE_MIN_SECS, default 2000 ms), pressure 85% with the 75% relax.

@hckrman101 hckrman101 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks for the rebase. The branch is now the one vk_memory.cpp commit on top of main and mergeable, so the stacking point is fixed.

The code itself is unchanged, though: the vk_memory.cpp diff at 42ae0cd is line for line the same as 8fb0290, so the rest of the last review still applies:

  • Linux now waits 30 s before giving retired imports back, where main gives them back once the GPU is past them (the amdgpu userptr submit cost, issues 312/413). Still open, see the inline thread: I'd keep at_once the default off Windows.
  • The two pressure valves act on the same overshoot on the same 16th submission (imports_give_back reads the same used before dead_imports is reaped and evicts live idle pools too). Still open, inline thread.
  • NVIDIA was already given back on main (issue 1057), so the real change is the Windows default on AMD and Intel, where give-back was turned off after device losses (issues 17, 309, 571). That still has no run on Windows Arc or on those AMD parts, and the pressure path was never exercised. I'd still leave flipping that default to @NotRexed.
  • Nits from last time (the stale "Off by default on Windows" comment in imports_give_back, the RX_VK_IMPORT_HIGH default split and the 12 GB gate) are untouched.

New:

  • The comments here don't describe the code. The recap says a retired pool goes back only when the heap has crossed 85%; the code gives every retired pool back after 30 s whatever the pressure, and 85% only shortens that wait to 2 s. The commit message says "the keep= default stays true" and "idle >5s", but the code drops the Windows keep default and uses 2 s. You also mention a test fixture for the leak, but the PR has only vk_memory.cpp. Please make the description and the commit message match what the code does, and add the test if you meant to.
  • CI hasn't run. The build and test workflows are waiting for a maintainer to approve them (first-time contributor), and the PR title check fails: it needs a conventional type, e.g. fix(vk): give retired pools back after an idle grace period.
  • Overlap: #2154 also edits vk_memory.cpp (new fields next to retired_epoch in struct Pool, and mirrors_give_back), so whichever lands second needs a small rebase. #2198, #2368 and #2401 are in the texture cache and replay, not this path.

@Joey-Magnus Joey-Magnus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I checked the head (42ae0cd) against main's retired_imports_give_back in gpu/vk/vk_memory.cpp. The code is the same as in hckrman101's last two reviews, so those points are all still open:

  • Linux changes too. On main, keep is false off Windows, so retired imports go back as soon as the GPU is past them (the amdgpu submit cost, issues 312/413). Here at_once is true only with RX_VK_KEEP_RETIRED=0, so by default Linux now waits 30 s.
  • The real change is the Windows default on AMD and Intel, where give-back was turned off after device losses (issues 17, 309, 571). There's still no run on Arc or on those AMD parts, and the 2 s pressure path has never run.
  • The commit message ("keep= default stays true", "idle >5s") and the recap comment don't match the code. The test fixture the comment mentions isn't in the PR.

Smaller things: the three new number switches use atoi(getenv(...)). Main has env_int in gpu/vk/compat/hookshot_env.h for this. at_once only recognises a literal 0, so RX_VK_KEEP_RETIRED=off keeps the 30 s wait. The title still needs a conventional type, e.g. fix(vk): ....

…pt (Windows AMD and Intel)

On Windows, AMD and Intel kept every retired pool's import for the session
(main's keep default there, set after device losses right after a give-back:
issues 17, 309, 571). The retired pools only grew, multi-GB in a long session,
until the system heap's budget was passed and new imports failed. NVIDIA on
Windows was already given back at once (issue 1057) and so was every vendor
off Windows (the amdgpu userptr submit cost, issues 312 and 413): neither
changes here.

Where they were kept, and only there, a retired pool's import now goes back
after a wait:
- the GPU is past it (as before: retired_value and last_value completed, no
  mirror, no inherit pending), and
- it has been retired for RX_VK_RETIRE_SECS seconds (default 30), oldest first;
- while the system heap is past RX_VK_IMPORT_HIGH percent of its budget
  (default 85, 0: off) the wait is RX_VK_RETIRE_MIN_SECS seconds (default 2),
  until what brings it down to RX_VK_IMPORT_LOW percent (75) is queued.
The free itself still waits for the GPU (dead_imports).

RX_VK_KEEP_RETIRED: 1 keeps them for the session; 0, off, false or no gives
them back as soon as the GPU is past them (it was a literal 0 only); unset or
empty is the default of the OS and vendor: at once off Windows and on Windows
NVIDIA, as on main, the wait on Windows AMD and Intel. The keep default is
gone from those two, nothing else moves. The numbers are read with env_int.

What is queued in dead_imports is still in the driver's figure of the heap's
use until the GPU is past it, so both valves count it as given back: the
retired valve at its next probe, and imports_give_back, which probes on the
same 16th submission and evicted live idle pools for the same bytes. Only
where retired imports wait; elsewhere imports_give_back reads what it read.

The rule is in gpu/vk/retired_give_back.h, with a check that needs no game or
GPU: tests/test_retired_give_back.py (the defaults by OS and vendor, the wait
and its floor, the watermarks, a 20-area tour kept, at once and waited).

Not run yet on Windows Intel Arc or on the AMD parts that lost the device
(Ally X, RX 6600), and the pressure path has not fired on real hardware.

Co-authored-by: GLM-5.3 <noreply@z.ai>
@kafasam kafasam changed the title vk: graceful retired-pool eviction — GPU gate, 30s idle, pressure hysteresis fix(vk): graceful retired-pool eviction where retired imports were kept (Windows AMD and Intel) Nov 12, 2026
@kafasam

kafasam commented Nov 12, 2026

Copy link
Copy Markdown
Contributor Author

Pushed 4808b1c: still one commit, now on current main (ef81aee). This time the code changed, going through both reviews:

Linux is back to main's behaviour. Off Windows a retired import goes back as soon as the GPU is past it, by default, exactly as on main: same gates, no wait, and the pressure probe is not even run there. The wait applies only where main's default was to keep them, Windows AMD and Intel. Windows NVIDIA stays at once too (issue 1057).

RX_VK_KEEP_RETIRED is read with env_on: 1 keeps for the session; 0, off, false or no gives back at once; unset or empty is the OS/vendor default. The numbers (RX_VK_RETIRE_SECS, RX_VK_RETIRE_MIN_SECS, RX_VK_IMPORT_HIGH, RX_VK_IMPORT_LOW) are read with env_int.

The two valves and the same overshoot (inline thread, answered there): what is queued in dead_imports is now counted as given back by both valves until the GPU is past it, so imports_give_back no longer evicts live pools for the same bytes.

Comments, commit message, title and description now say what the code does. Only AMD and Intel on Windows leaked (NVIDIA was already excluded on main); a retired pool goes back after 30 s whatever the pressure, and 85% only shortens that to 2 s (not 5); the Windows keep default is what goes away for those two vendors. The stale "Off by default on Windows, as giving retired imports back is" comment in imports_give_back is rewritten, and both places now say that the retired valve defaults to 85 on Windows and skips the 12 GB gate, and why. Title: fix(vk): .... My two earlier recap comments here were wrong on these points; the description is the accurate one now.

The test fixture. My earlier comment mentioned one that was never in the PR, and there was none to bring over. It is written now: the rule moved to gpu/vk/retired_give_back.h, checked by tests/test_retired_give_back.py + tests/retired_give_back_test.cpp (no game or GPU).

Diff against main: 4 files, +288/-13 (vk_memory.cpp +62/-13, the rest is the header and the test).

Still not done, and unchanged by this push: no run on Windows Intel Arc or on the AMD parts that lost the device (Ally X, RX 6600), and the pressure path has not fired on real hardware. The RX 6700 XT run in the description was of the earlier revision. Whether the default should flip for those two vendors without those runs is yours and @NotRexed's call; RX_VK_KEEP_RETIRED=1 gives main's behaviour back.

Overlap with #2154 noted: whichever lands second, I'll rebase.

@NotRexed
NotRexed merged commit e8ab1e3 into NotRexed:main Nov 12, 2026
1 of 2 checks passed
notquiteog added a commit to notquiteog/Hookshot that referenced this pull request Nov 12, 2026
…s behind them

Upstream's main fails 15 of its own source checks at c356bef (PRs merged without a
rebase). These are the eleven outside the upscalers:

- vk_memory.cpp: RX_VK_CAPTURE_KEEP_OLD and RX_VK_CAP_BLOCKS are on/off switches and
  were read as set-means-on, so =0 turned them on (NotRexed#2437). env_on, as the rest.
- mouse_native.c: the mouse's kept angles are let go when the camera leaves states 3
  and 4 (first-person aim, Z-targeting): they were written back on return, and the
  view snapped to where it was before (NotRexed#2617; test_mouse_native's yaw).
- menu_i18n.h: three English texts changed in vk_menu.cpp (NotRexed#1930, NotRexed#2362, NotRexed#2435), so
  their 13 translations are keyed and translated again (machine-made, as the file's
  others).
- Fixtures that cut source by its text and missed what the source gained:
  window_title (NotRexed#2116), dead_import_bytes (NotRexed#1906), env_on in reverb_frame,
  hos_xinput_pads (NotRexed#2435), wait_recorded's forward declaration (NotRexed#2458); and the
  Dockerfile check's parser, which took --no-update for a PPA.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
hckrman101 pushed a commit that referenced this pull request Nov 12, 2026
**What this is for:** restore ten game-free checks whose extracted
fixtures or expectations no longer match intentional changes on main;
[main's CI
log](https://github.com/NotRexed/Hookshot/actions/runs/43151254256)
shows these failures. **What is measured:** those ten checks on Linux
with GCC 16.2.1 and Clang 23.1.3, plus the strict full suite and
deliberate regression mutations, as detailed below. **Not measured:** a
game run, Windows execution, audio output or GPU behavior; no production
file changes in this diff.

## Cause and changes

Each row is a separate commit, naming the change that made the fixture
stale; the quoted diagnostics come from [main's failed
jobs](https://github.com/NotRexed/Hookshot/actions/runs/43149508038).

| Introduced by | Checks / CI diagnostic | Repair |
|---|---|---|
| #1544, after #2042's switch helper | `audio_aux`, `audio_biquad`:
`implicit declaration of function ‘env_on’` | Include the real helper
before the extracted DSP. |
| #2116 | `display_startup_failure`, `wayland_libdecor_hint`: `use of
undeclared identifier 'window_title'` | Extract the real title helper
along with its callers. |
| #1906 | `texel_buffer_ownership`: `use of undeclared identifier
'dead_import_bytes'` | Model the counter and check that it stays charged
until completion. |
| #2458 | `readback_part`: `extraneous closing brace ('}')` | Select the
complete `wait_recorded` definition, not its new forward declaration. |
| #2574 | `dlss_checks`: `FAIL under a third wide at line 40`;
`framegen_preset` / `rumble_menu`: undeclared `temporal_reset_failure` |
Check both sides of the intended two-pixel tolerance; supply a counted
reset hook and exercise the real scaling rows. |
| #2435 | `mods_size_table`: `undefined reference to hos_xinput_pads` |
Supply the fixture's no-controller answer; retain real merge and routing
checks. |

The diff retains the existing assertions: no check is deleted or
skipped, and it does not revert the production behavior named above.

## How it was tested

Recorded on 2026-11-11, Linux kernel `7.2.15-1-omarchy`; base
`de866017`, head `eeb09c09`, GCC 16.2.1 and Clang 23.1.3 (compiler
version output and test records).

- Untouched main `a016b7a6`: `455 passed, 15 failed, 20 skipped`; each
of these ten failures also reproduced alone with both compilers,
matching the linked CI diagnostics.
- Branch: all ten repaired checks pass independently with each compiler
(`python -I -B tests/run_all.py --strict --jobs 1 <test>` records).
- Negative controls: 14 deliberate source regressions were each rejected
with both compilers, without a compile failure—28 behavioral rejections
(mutation records). These remove Aux sizing, biquad filtering, startup
failure handling, the libdecor hint, view ownership release,
part-specific waits, preset preservation, temporal reset or mod-table
routing; the DLSS controls independently make each axis's tolerance too
narrow and too broad.
- One full `python -I -B tests/run_all.py --strict` run: **`464 passed,
6 failed, 20 skipped in 141 s`**, 32 workers, load 7.24 → 28.38
(complete suite output).

### Remaining failures and the path to green

The complete branch run names these six failures; the first five are
outside this fixture-only diff:

| Remaining check | Separate fix |
|---|---|
| `test_env_on.py` | `fix/capture-switch-values`: the three
presence-only capture switch reads from #2437. |
| `test_linux_docker_packages.py` | `test/docker-ppa-options`:
distinguish `--no-update` from its PPA operand. |
| `test_mouse_native.py` | `fix/mouse-camera-handover`: discard retained
angles while another camera owns the view. |
| `test_menu_i18n.py` | `fix/menu-hint-translations`: update three
complete hint keys and their translations. |
| `test_hdr_encode.py` | Already repaired in #2614; deliberately not
duplicated here. |
| `test_release_scripts.py` | An intermittent, unchanged release-script
concurrency failure: `SHA256SUMS still differs from the files after 5
uploads`. It passed untouched main and current main CI; isolated reruns
passed once and failed once. Neither run invokes a C/C++ compiler. |

## Not tested / risks

No Windows, game, display, controller, listening or GPU run was
performed; the evidence above is game-free only. The fixture extraction
still follows source structure, so future helper/signature changes must
update its inputs rather than remove its behavioral guards.

## Overlaps

The inspected merge hunks overlap #1834's frame-generation fixture
helpers and #2622's older readback extraction; neither contains these
repairs. #2614 owns the separate HDR initializer check. Other same-file
changes merge cleanly in the recorded overlap comparison.

Assisted-by: GPT-6 Astra
Co-Authored-By: GPT-6 Astra <noreply@openai.com>

---------

Co-authored-by: GPT-6 Astra <noreply@openai.com>
dazemc added a commit to dazemc/Hookshot-rs that referenced this pull request Nov 12, 2026
Port of upstream NotRexed#1906. Those vendors kept every retired pool's import
for the session to avoid the device losses a give-back caused, so a long
session grew by gigabytes until new imports failed. They now go back once
the GPU is past them and they have been retired for 30 s (2 s while the
system heap is past its high watermark). RX_VK_KEEP_RETIRED still chooses
keep/at-once, and the wait and watermarks are switches.

The pure rule is in retired_give_back.h; tests/retired_give_back_test.cpp
checks the defaults, waits, watermarks and a 20-area tour without a GPU,
and source-regressions now compiles and runs it.
dazemc added a commit to dazemc/Hookshot-rs that referenced this pull request Nov 12, 2026
Record the retired-import grace wait (NotRexed#1906), the green 74a7fd1, and
that v2.2.0-rs.3 was built from it with the worker, mirror, image-pool
and retired-import changes. Document the retire switches.
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.

4 participants