mirror of
https://github.com/tangerineturtle1/NX2navi.git
synced 2026-11-15 19:19:58 -04:00
Keep the fast link's waits at 3 ms a pipeline and 6 ms a frame.
The 8 ms and 16 ms tried in their place left fewer draws out in a scripted walk, but in play a frame that takes 10 to 14 ms longer felt worse to the player than one that is left out, in two sessions on the same install. The wait stays counted once for each pipeline, and a frame that has left a draw out already still waits for nothing more. Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
This commit is contained in:
@@ -161,9 +161,9 @@ of them.
|
||||
What this step leaves for play, and the shared pipeline list. The step translates every shader's default variant
|
||||
and the shader list's variants and builds each one's stage library or compute pipeline. A whole graphics pipeline
|
||||
is built ahead at the start of a game folder that has drawn it before (`pipeline-keys.bin`) or whose release
|
||||
listed it (below); a pipeline met for the first time is linked from its stage libraries in 2 to 8 ms, which its
|
||||
first draw waits for (`pipe_link_draw_ms`, 8 ms from the pipeline's first miss; `runtime/vk_exec_draw.c`
|
||||
`link_budget`), except a mesh
|
||||
listed it (below); a pipeline met for the first time is linked from its stage libraries in 2 to 8 ms, of which its
|
||||
first draw waits 3 (`pipe_link_draw_ms`, from the pipeline's first miss; `runtime/vk_exec_draw.c` `link_budget`),
|
||||
except a mesh
|
||||
pipeline, which has no libraries and compiles whole (0.2 to 1.1 s, its draws left out of the picture meanwhile),
|
||||
and many of them on a first visit add up to hitches. `tools/pipeline_list.py merge` folds the `pipeline-keys.bin`
|
||||
and `shader-answers.bin` of game folders that were played, and lists made before, into a pipeline list, with the
|
||||
|
||||
@@ -24,19 +24,17 @@ for the launcher; a GPU with Vulkan 1.3 and `VK_EXT_external_memory_host` (curre
|
||||
1,769 draws wait for their pipelines, 461 ms in all, the longest frame 88 ms. In a first walk through Kakariko
|
||||
Village on fresh caches no draw waited for a pipeline with the list, where 634 pipelines were missed without it, and
|
||||
the first minute had 10 frames over 25 ms instead of 137. `pipe_seed = 0` in nx2navi.ini leaves the list out.
|
||||
- **A pipeline the list does not have costs its frame less.** Such a pipeline is linked from the shader libraries the
|
||||
install prepared, and its first draw waits for that. The wait was 3 ms for each draw, just under what the link
|
||||
takes: in a first-visit session on a new install 66 of 87 such draws gave up at the end of it, and their frame was
|
||||
then not shown, so the picture before it stayed for one frame more. Of the 67 pipelines that session met outside
|
||||
the list, 61 were ready within 8 ms. The wait is now 8 ms, counted once for each pipeline from the first draw that
|
||||
needed it, so a pipeline the driver has to compile costs one frame that much and the frames after it nothing
|
||||
(`pipe_link_draw_ms`, and `pipe_link_ms` for all the pipelines of one frame, now 16). A frame that has already
|
||||
left a draw out waits for nothing more. In a walk through Kakariko with no pipeline recorded at all, the picture
|
||||
stood still 15 times instead of 50 and 1 frame was shown incomplete instead of 22, with the frame times unchanged.
|
||||
- **Less waiting for a pipeline the list does not have.** Such a pipeline is linked from the shader libraries the
|
||||
install prepared, and its draws waited 3 ms for that in every frame until it was there. The 3 ms are now counted
|
||||
once for each pipeline, from the first draw that needed it, and a frame that has already left a draw out waits for
|
||||
nothing more: a pipeline the driver has to compile costs one frame the wait and the frames after it nothing.
|
||||
`pipe_link_draw_ms` and `pipe_link_ms` set longer waits, which leave fewer draws out of a frame and make that frame
|
||||
longer.
|
||||
- **Compute shader variants are prepared too.** The list now carries the 629 compute shader variants met in play. No
|
||||
pipeline record names a compute shader, so a variant the shader list lacked was translated on the frame that first
|
||||
used it, 30 and 38 ms in two frames of that session. Fourteen of the list's variants are of shaders the preparation
|
||||
does not read from the game yet, three of that session's four among them: those are still translated at first use.
|
||||
used it, 30 and 38 ms in two frames of one first-visit session. Fourteen of the list's variants are of shaders the
|
||||
preparation does not read from the game yet, three of that session's four among them: those are still translated at
|
||||
first use.
|
||||
- **The draw replay runs on several CPU cores by default** (`replay_workers = 3`; contributed by epicmeme546): a
|
||||
frame's large groups of draws are recorded on three threads beside the one that submits them. On an RX 7900 XT in
|
||||
Hyrule Field it gave 51.7 instead of 43.6 fps standing. `replay_workers = 0` records on one thread as before; try
|
||||
|
||||
@@ -126,11 +126,11 @@
|
||||
# pipe_skip_steady = 1
|
||||
# How many milliseconds the draws of one frame may wait, in all, for a missing pipeline to be linked from the shader
|
||||
# libraries in the graphics driver's cache before they are dropped (0 to 100; 0: dropped at once, as before).
|
||||
# pipe_link_ms = 16
|
||||
# pipe_link_ms = 6
|
||||
# How many milliseconds one missing pipeline is waited for, counted from the first draw that needed it (1 to 50).
|
||||
# With its shader libraries in the driver's cache a pipeline takes 3 to 8 ms; one that takes longer is being
|
||||
# compiled, and its draws are left out of the frames until it is ready.
|
||||
# pipe_link_draw_ms = 8
|
||||
# With its shader libraries in the driver's cache a pipeline takes 2 to 8 ms; what is not ready by then is left out
|
||||
# of the frames until it is. A longer wait leaves fewer draws out and makes those frames longer.
|
||||
# pipe_link_draw_ms = 3
|
||||
# When a draw finds its pipeline missing, the rest of the commands the game submitted with it are read ahead and the
|
||||
# shader libraries of every other pipeline they will need are built at once on background threads, so the later draws
|
||||
# find theirs ready instead of waiting one after another or being left out of a frame. 0: off, as before.
|
||||
|
||||
@@ -261,8 +261,8 @@ static const CfgMeta metas[] = {
|
||||
{"CACHE_DIE", "1", "0|1|ab", RESTART}, {"ONE_PER_CORE", "0", "0|1|ab", RESTART}, // perf.c cpu_placement
|
||||
// shaders and pipelines
|
||||
{"PIPE_WAIT", "default", "default|draw", RESTART}, {"PIPE_SKIP", "any", "strict|any|fullscreen", RESTART},
|
||||
{"PIPE_LINK_MS", "16", "0..100", RESTART}, // vk_exec_draw.c link_budget
|
||||
{"PIPE_LINK_DRAW_MS", "8", "1..50", RESTART}, // vk_exec_draw.c link_draw_ms
|
||||
{"PIPE_LINK_MS", "6", "0..100", RESTART}, // vk_exec_draw.c link_budget
|
||||
{"PIPE_LINK_DRAW_MS", "3", "1..50", RESTART}, // vk_exec_draw.c link_draw_ms
|
||||
{"PIPE_FRAME_WAIT_MS", "50", "0..500", RESTART}, // vk_exec_draw.c frame_wait
|
||||
{"PIPE_SKIP_STEADY", "1", "0|1", RESTART}, // vk_exec.c steady_on
|
||||
{"PREPARE_PIPELINES", "all", "0|mesh|all", RESTART}, // vk_pipeline.c seed_pipelines
|
||||
|
||||
@@ -3829,7 +3829,7 @@ static int pipe_skip_mode(void) {
|
||||
return mode;
|
||||
}
|
||||
|
||||
// NX2NAVI_PIPE_LINK_MS (default 16; 0 = off): how long the draws of one presented frame may wait, in all, for the fast
|
||||
// NX2NAVI_PIPE_LINK_MS (default 6; 0 = off): how long the draws of one presented frame may wait, in all, for the fast
|
||||
// link of a pipeline that is missing, LINK_DRAW_MS at most each. A draw into a per-frame pass used to be skipped at
|
||||
// once and for as long as its pipeline built, also when its stage libraries were in the driver's cache and the link
|
||||
// took under a millisecond: geometry seen for the first time (ground, a wall, a character) was missing for a frame or
|
||||
@@ -3837,19 +3837,19 @@ static int pipe_skip_mode(void) {
|
||||
// cold it runs out after a few draws and the rest are skipped as before, so a burst of cold pipelines costs a frame
|
||||
// this much and no more. Measured on an RX 7900 XT, first walk through a village with no pipeline recorded: 2,349
|
||||
// draws skipped without the budget, with the libraries warm in both runs.
|
||||
// NX2NAVI_PIPE_LINK_DRAW_MS (default 8): the wait for one pipeline, counted from its first miss and shared by all its
|
||||
// NX2NAVI_PIPE_LINK_DRAW_MS (default 3): the wait for one pipeline, counted from its first miss and shared by all its
|
||||
// draws (prepare_draw_ex), so a pipeline whose libraries the driver has to compile costs its first frame this much and
|
||||
// the frames after it nothing. It was 3 ms for each draw, in every frame, 6 ms a frame: just under what a pipeline
|
||||
// takes with its two shader libraries in the driver's cache. On a new install's first visits (RTX 5090, the
|
||||
// libraries prepared, 67 pipelines the install's list did not hold) 44 were usable under 4 ms after their miss, 17
|
||||
// after 4 to 8 ms and 6 later, and of 87 draws that waited for a fast link 66 were skipped at the end of their 3 ms:
|
||||
// each of those frames paid the wait and was then not shown, the previous picture staying for one frame more.
|
||||
// A frame that has left a draw out already waits for no fast link (prepare_draw_ex): it is held back or shown without
|
||||
// that draw whatever its other pipelines do, and at an area's first frames, with hundreds of pipelines new at once,
|
||||
// every frame spent its whole budget that way. A walk through a village with no pipeline recorded (610 missed, the
|
||||
// libraries of most in the driver's cache), 3 ms and 6 ms against 8 ms and 16 ms with this rule: the picture stood
|
||||
// still 50 times against 15, 73 frames held back against 31, 22 frames shown incomplete against 1, and 17 frames over
|
||||
// 25 ms against 15 in the minute of the area's load. Without the rule the longer waits gave 49 frames over 25 ms.
|
||||
// the frames after it nothing; it was 3 ms for each draw, in every frame. A frame that has left a draw out already
|
||||
// waits for no fast link either (pending_draws): it is held back or shown without that draw whatever its other
|
||||
// pipelines do.
|
||||
// The 3 ms are just under what a pipeline takes with its two shader libraries in the driver's cache: on a new
|
||||
// install's first visits (RTX 5090, the libraries prepared, 67 pipelines the install's list did not hold) 44 were
|
||||
// usable under 4 ms after their miss, 17 after 4 to 8 ms and 6 later, and of 87 draws that waited 66 were skipped at
|
||||
// the end of the wait, their frame then held back. 8 ms a pipeline and 16 ms a frame were tried for that. A scripted
|
||||
// walk through a village with no pipeline recorded (610 missed) had the picture stand still 15 times against 50 and
|
||||
// 15 frames over 25 ms against 17, but in play it felt worse to the player than the 3 ms it replaced, in two sessions
|
||||
// on the same install: a frame that takes 10 to 14 ms longer showed more than one that is left out. The waits stay
|
||||
// short; the settings take longer ones.
|
||||
// NX2NAVI_PIPE_FRAME_WAIT_MS (default 50; 0 to 500): the wait pool of one presented frame. Its full-screen draws and
|
||||
// its one-shot draws (NX2NAVI_ONESHOT_BUDGET) wait for their shaders and pipelines from it, each for what the ones
|
||||
// before left, and are skipped once it is spent, so the pipelines of one frame hold the replay thread this long in
|
||||
|
||||
Reference in New Issue
Block a user