25 Commits
Author SHA1 Message Date
itaskaev2andClaude Opus 5.5 e8fd6fd7a5 Describe deswizzle, kspin_us, pcore, rec_async and rec_spin_us in docs/settings.md
tests/settings_doc_check.py failed on dev with these five names in known[] and described nowhere. The rows follow the
code: vk_deswizzle.c (TOTK_DESWIZZLE), kernel.c kspin_ns, main.c (rt_knob PCORE), vk_rec.c rec_submit and rec_main.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 16:28:21 +01:00
Valiantsin DzerakhandClaude Opus 5.5 1c1ff975f3 Default dynamic_res to 1 so the game keeps its own dynamic resolution
With dynamic_res at 0 by default the fixres set held the scene at 100 % for every player, the reason #573 was turned
down. The default is now 1, so the set stays off unless a player turns dynamic resolution off in the menu or
totk.ini, and the Steam Deck profile no longer needs its own entry.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-10 18:20:31 +03:00
itaskaev2 59eb026bd7 Merge branch 'dev' into carry/dynamic-res-100 2026-11-09 09:55:24 +01:00
Valiantsin DzerakhandClaude Opus 5.5 29cb79086f Take 64 MiB blocks from the driver for buffers and other images
Since the textures moved to a pool of their own, the default device-local
blocks hold mirrors and other buffers. With VMA's 256 MiB blocks one block
held 53 MiB of them after 10 minutes in the field, and the headroom thread
kept half a block of each device-local type ahead. TOTK_VMA_BLOCK_MIB
(default 64, 0 = VMA's 256) sets the size; the headroom spare follows it.

On the RX 9070, 10 minutes in the field: VMA blocks 3582 -> 3252 MiB,
process commit 8614 -> 8327 MB, slow frames 13 (2.8 s) -> 9 (1.1 s).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-09 10:51:49 +03:00
Valiantsin DzerakhandClaude Opus 5.5 cf44e9013c Merge task/memoom: wait out a short out-of-memory spell instead of ending the game
Conflicts: the image retry goes through vk_texture_image, sweep_pressure keeps the released-texture cap on the new
drop helpers, and vk_headroom_release also frees the texture pool's anchor.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-09 10:12:55 +03:00
Valiantsin DzerakhandClaude Opus 5.5 8e05d2b409 Give textures a pool of their own with 64 MiB blocks
Textures shared the default 256 MiB blocks with the mirrors and other buffers, and a block went back to the driver
only once everything in it was gone. On the RX 9070 after a few minutes of roaming the field, 3 of 9 device-local
blocks were 13-27% full, held by a hundred small textures and buffers each, and blocks held 0.8-1.4 GB more than their
allocations; where device memory takes process commit, that commit backs nothing.

Own-memory textures now go to a VMA pool with 64 MiB blocks (TOTK_TEX_BLOCK_MIB, 0 = the default pools). Images of a
quarter block or more, images the driver wants a dedicated allocation for, and images the pool's memory type does not
take get memory of their own; the requirements are read before the image is made, since VMA checks neither for a
custom pool. The headroom thread keeps the pool's next block ahead like the default pools'.

Same 10-minute route: 807 MiB of blocks beyond their allocations instead of 1037, most pool blocks 75-100% full, slow
frames not up. Probes pass on v143.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-09 10:11:44 +03:00
Valiantsin DzerakhandClaude Opus 5.5 34b340a208 Cap the released-texture cache by bytes
Released textures stayed until 2048 of them were kept or VRAM passed 90% of the budget. On the RX 9070 a 10-minute
field run kept 818 MiB of them, while almost every take-back came within a second. TOTK_TEX_RELEASED_MIB (default
256) runs the same drops as under VRAM pressure while the released entries hold more own memory than that. On the
same route the run ended with 1.1 GB less process commit and 1 GB less in VMA blocks; 15 dropped textures were
created again and the slow frames did not change.

Also documents TOTK_MEM_RESERVE_MIB.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-09 09:57:32 +03:00
Valiantsin DzerakhandClaude Opus 5.5 213bc6af6a Wait out a short out-of-memory spell instead of ending the game
Crash logs ended in fatal errors when the system's commit ran out for a moment: a staging buffer (-2), a guest commit
with the system at 24442 of 24447 MB, image creation (-2). Windows grows a system-managed page file and some drivers
charge device memory to the process commit, so the same request often succeeds a moment later.

oom.c holds the wait nvn_api_cmd.c realloc_wait already used: it requests a release, retries every 10 ms for up to
30 s, logs the first 8 with the commit numbers. rt_oom_request sets a flag that vk_texture_new_submit takes (one atomic
load per submit): it drops up to 256 released textures of the two kinds sweep_pressure drops (overwritten, clean
mirrored), never GPU-written content, and frees the headroom blocks. vk_oom_release does at once what needs no submit:
headroom blocks, finished upload batches and deferred objects.

- memory.c commit: waits and retries without frz_lock between tries; every caller waits, boot ones too.
- vk_staging and the draw-data chunks (vk_exec_draw.c scratch): release, then wait; the open upload batch is not
  submitted, its caller still records into it.
- create_tex: release and one retry; no wait under the texture lock, the texture is asked for again at its next use.
- the texture write-back buffer: release, then wait.
- the headroom thread keeps no spare block for 30 s after a failure.

TOTK_TEST_OOM=<site>:<n> (commit, staging, image, chunk) fails the first n attempts; probe-kernel forces 3 refused
commits, probe-vkexec 2 staging buffers, 1 image and 1 chunk, and both pass through them.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-09 09:53:30 +03:00
Valiantsin DzerakhandClaude Opus 5.5 0704543249 Merge pull request #947: sync shadow pools from the per-submission write-watch snapshots (corne-ac)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 20:41:23 +03:00
Valiantsin DzerakhandClaude Opus 5.5 35b3d37ea3 Make a chunk's new texture entries follow replay order, and add a knob that records chunks out of order
entry_of decides at record time whether a new texture takes the content of a live GPU-written texture at its storage
(alias_copy) or the storage bytes. In a chunked replay the source's GPU ownership is set when a chunk records its
render, so the choice followed the order the threads got to the chunks: a later chunk could take the old bytes before
an earlier chunk recorded the render, and a mirrored texture keeps them. Now a chunk that makes an entry while a live
colour texture of its size sits at the storage waits until the chunks before it are recorded (vk_exec_chunk_settle,
the texture lock released for the wait), skips sources the scan revives at a later op, and ignores GPU ownership a
later chunk set in this submission. slot_resolve and vk_texture_by_id_locked no longer read tslots through a pointer
taken before the wait.

TOTK_REPLAY_SKEW_US (debug) makes the even chunks wait before they record, so the chunk after each one records
first in every submission. With it at 3000 us and 4 threads the field save runs clean (grass drawn, 0 validation errors); the alias path
did not fire there (0 copied, 0 filled from storage), so this does not reproduce the missing grass reported on
RADV, and the fix there stays unconfirmed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-08 19:53:12 +03:00
ipavlin98 6b4d84ec50 Record large submissions in chunks on several threads
replay_workers = N (0, the default, keeps the sequential replay) records a submission of enough draws in chunks that start between passes, on N threads and in twice as many chunks, and submits them in order. In the town at 4K on an RTX 5070, 4 threads take the replay from 8.2 to 4.5 ms a frame and the frame rate from 71 to 79.

A sequential scan on the submitting thread applies only what is queue state (fixed-function and bind ops, render targets, render enable and conditions, samples-passed counting) and keeps a copy of it where each chunk starts, with how far its lists got: inline uniform updates, RENDER_COND results, contact shadow marches and the ops that drop uniform copies. A chunk takes those from the lists instead of from the chunks before it, starts with every image in GENERAL and ends with a full barrier, so its recording depends only on the copy and the lists.

Each thread records with a context of its own: the replay's memos, descriptor state, occlusion query segments and per-command-buffer state moved from file statics into VkExec and VkExecDraw, and the tables the contexts share (stand-ins, depth twins, views, mirrors, timestamps, completion callbacks, crumbs) take locks or atomics. The scan makes render targets live in replay order and notes the op (vk_texture_revive), since a chunk can sample a storage before the chunk that renders it got there or after the scan went past a later target there: a chunk's texture slots resolve as of its own op, and the chunks after a texture with no entry yet wait for the chunk that makes it. Uniform copies are dropped at the op that writes them (vk_usnap_drop_at).

Contact shadows plan their march in replay order (vk_contact_plan) and the chunk that holds its op records it; the HDR source keeps the copy that comes last in replay order. DLSS and fxaa = 0 act on the frame draw by draw and keep the replay sequential. TOTK_REPLAY_STATE_CHECK=1 compares the state after the last chunk with the scan's.

A draw or dispatch whose shaders write storage buffers drops the uniform copies they cover from its own op on, as the other GPU writes do (scan_writes). The scan still translates no shader: it reads the shaders the recording contexts translated from a table shared with them (vk_exec_draw_writes), and an op whose shader no context translated yet holds the chunks after it until it is recorded. Before, the chunk that recorded such a write dropped the copies for every position at that moment, so a later chunk recorded first bound the copy taken at the submit call: on an RX 7800 XT on RADV the grass near the camera came out dark or unshaded in some runs with 4 threads.

TOTK_TRACE=perf counts the chunks held per submission by reason and logs when each chunk of the last submission began. The settings menu has the thread count under Advanced, Scheduling, with the count this run uses under it.

The recorder thread begins, ends and submits the submission's open part (vk_rec.c rec_end_cb), so a chunk's mirror prologue stays off it: vk_sync_part waits until the recorder is idle, as the part pool allows one thread at a time, then records, ends and submits the prologue itself. Through the recorder the prologue could reach the queue before it was ended, and the GPU lost the device at the title screen.

(cherry picked from commit b94e2e9642)
2026-11-08 19:39:17 +03:00
corne-acandClaude Opus 5.5 a733b94645 Keep shadow_snap off by default under Wine until it has been measured there
Shadow storage is on by default under Wine as well, and the region snapshots were only measured on a native Linux
host. TOTK_SHADOW_SNAP=1 still turns them on under Wine.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 22:20:03 +02:00
corne-acandClaude Opus 5.5 02752376f7 Sync shadow pools from the per-submission write-watch snapshots
Each 2 MiB region is now queried at most once per guest submission, shared with the texture checks, instead of once
per pool at every part of a submission. On a Steam Deck at Lookout Landing the replay thread's write tracking fell
from about 4.4 to 1.3 ms a frame and the frame rate rose about 7.5%. TOTK_SHADOW_SNAP=0 restores the old queries.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 22:01:05 +02:00
ProSepandClaude Opus 5.5 a6c33b072c Hold the game's dynamic resolution at 100 % and let the scene grow past 4096 wide
The game picks a scene tier of 100, 90 or 80 % mostly from a fixed cost model made for the Switch that grows with the
scene width squared, so on a wide output it drops to 80 % on any GPU: at 5120x1440 every frame drew 80 % of the scene.
Patch set fixres replaces the one instruction that moves the tier's scale into the controller's result (1.2.1
main+0xcc2c00, 1.4.3 main+0x5848a8 as MacNativeGames patches it) with 1.0. The new setting dynamic_res (menu toggle,
live) brings the game's stepping back and is on by default in the Steam Deck profile.

The scene cap goes from 4096 to 8192 a side, so render_scale above 80 works on a 32:9 output, and the scene also stays
within a DynamicTextureAllocatorMem under 2 GiB; the log says when it was made smaller. The memory selftest now maps
past the real pool size instead of a fixed 4 GiB, which a larger scene grows past.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 10:55:54 +01:00
Valiantsin DzerakhandClaude Opus 5.5 2eb5adebd6 Merge #898: record only the dynamic states that changed since the last pipeline state
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 11:07:22 +03:00
Valiantsin DzerakhandClaude Opus 5.5 6c6f48c40d Merge #897: overlay uniform updates between passes too, and clear the overlays once their copies are recorded
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-07 11:07:22 +03:00
Claude 752e15bcc7 Record only the dynamic states that changed since the last pipeline state in the command buffer
Each change of pipeline state in prepare_draw re-recorded the whole dynamic state through vk_pipeline_set_dynamic:
about twenty commands, the vertex input packet rebuilt, and the blend enable, equation and write mask of every
attachment, however few fields differed. Every replay pipeline declares the same dynamic states, which a pipeline bind
leaves as they were, so vk_pipeline_set_dynamic_delta compares the values with what the command buffer already holds
and records only the commands that differ; the vertex input is rebuilt only when the vertex shader, attributes or
streams change. The record is per command buffer (B.dyn_valid, cleared with the rest of B on a new one or a split).
TOTK_DYN_DELTA=0 records the full set as before; ab alternates; TOTK_TRACE=perf counts calls, commands and calls that
changed nothing.

1.4.3, RTX 4070 Ti, 2560x1440 DLAA, standing still on Great Sky Island, TOTK_AB=10 (tools/ab_summary.py): 13.75 ms
a frame with the full sets, 12.59 ms with the deltas (-8.5%, 72.7 to 79.4 fps); replay 7.77 to 6.67 ms. An A/A run
with the same method moved the frame by 0.08 ms.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BspNcezsiV8zT8wcnXrrME
2026-11-07 03:00:57 +00:00
Claude 49b2314dd8 Overlay uniform updates between passes too, so a run of them before a pass costs one barrier
An update between passes was copied at once behind a full barrier of its own, and the copy it recorded made the next
update or pass begin need another: a run of k updates before a pass cost k + 1 full barriers, about 250 updates a
frame on Great Sky Island. They now become overlays like the updates inside a pass; every GPU reader of the real
buffer after them comes behind barrier_to, which records the copies first. TOTK_UB_OVERLAY_OUT: 1, 0, ab; the perf
line counts the overlays made between passes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BspNcezsiV8zT8wcnXrrME
2026-11-06 22:35:01 +00:00
itaskaev2andClaude Opus 5.5 5cd48ea696 Describe probe_movie_bench in docs/settings.md
tests/settings_doc_check.py failed on dev since 3cd2410 added TOTK_PROBE_MOVIE_BENCH to known[] without a row.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 19:07:38 +01:00
Valiantsin Dzerakh 959033e1fb Merge the latest head of pull request #743 2026-11-06 11:25:30 +03:00
Valiantsin DzerakhandClaude Opus 5.5 a959eab275 Merge task/vrampress: drop released textures the game has overwritten under VRAM pressure (#754)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 10:08:32 +03:00
Valiantsin DzerakhandClaude Opus 5.5 895d202cce Let the recorder thread begin, end and submit the parts it records.
The part command buffers and their pool were used by two threads. The submitting thread still waits for the
submission, so the queue order is unchanged. TOTK_REC_END=0 brings the old split back.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-06 10:07:45 +03:00
Claude 0be3472fe0 Describe ub_overlay in docs/settings.md, which tests/settings_doc_check.py now asks of every name in known[]
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BspNcezsiV8zT8wcnXrrME
2026-11-05 22:21:07 +00:00
Valiantsin DzerakhandClaude Opus 5.5 beda188776 Drop released textures the game has overwritten when VRAM runs short.
Under pressure only clean mirrored entries could go, so once those ran out the render targets stayed: 1.7-2.0 GiB of released images with the use still over the line. Most of them sit on storage the game has since given to another texture, and they are never taken back. The pressure path now drops those first, 30 s after their release and when no finalized slot has bound them for 600 submits. Clean entries wait 5 s, which ends the re-creation churn in fights, and both kinds stop once the use is back under the line.

TOTK_TRACE=perf gains mem: released lines that split released memory by kind, age, overlap and dedicated memory, and count take-backs and re-creations. TOTK_VRAM_LIMIT_MIB caps the budget the port sees, so the path can be driven on a large card.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 12:53:17 +03:00
Valiantsin DzerakhandClaude Opus 5.5 9712658328 List the settings totk.ini.example leaves out in docs/settings.md
146 of the 254 names in known[] (runtime/cfg.c) were described nowhere for a reader: diagnostics, test hooks, paths and
experiments. docs/settings.md gives each one what it does, the effect of changing it and a safety level. The rows come
from reading the code, and most effects have not been checked in a run.

tests/settings_doc_check.py fails when a known name is in neither file, when the page lists an unknown name, or when a
default on the page differs from metas[] or an rt_knob call.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 10:18:50 +03:00