Skip to content

Deferred inline uniform updates in TBDR mode too (toward #159) - #1367

Open
Copak731 wants to merge 1 commit into
seedds:mainfrom
Copak731:tbdr-ubd-deferral
Open

Copak731 wants to merge 1 commit into
seedds:mainfrom
Copak731:tbdr-ubd-deferral

Conversation

@Copak731

@Copak731 Copak731 commented Nov 5, 2026

Copy link
Copy Markdown
Contributor

What and why

ubd_on() (inline uniform updates inside an open pass deferred to the pass end, the draws after them reading a shadow) was off whenever tbdr_on() was, "because TBDR mode reorders passes". So with DM_NVN_TBDR=1 every inline update inside a pass ended it again, bringing back the passes and attachment traffic the deferral had removed (BotW about 158 → 386 passes), and the TBDR mode's own gain could not be measured on its own.

TBDR mode's reorderers never move a draw across an update: defer_try refuses an OP_UPDATE_UB between the deferred pass and its target pass or in the target pass before its first draw, fuse_try stops at one, the multi-draw scan (mdx_run) stops at one that writes a record it copied, hoist_try moves only clear-only passes (they read no uniforms), and the layer lookahead already asks ubd_on. A deferred pass replayed later reads the updates made before it, whether still deferred (shadows) or landed. ubd_on therefore no longer depends on tbdr_on; DM_NVN_UB_DEFER=0 still turns the deferral off. Nothing changes by default (TBDR mode is off). A step toward #159, alongside #1340 (store lookahead and bindless readers); the two are independent.

Reference entry: docs/reference/rendering.md, "Deferred uniform updates in TBDR mode".

Checked

  • Tests: new make -C dm/gfx/tests GAME=01007EF00011E000 check_t_tbdr_ubd (production mtl_exec with DM_NVN_TBDR=1, a fragment shader returning a uniform buffer's first float4, closed-form pixels): an update between two draws of one pass, one before a same-target continuation, one before a pass defer_try defers into a later one, and one between that pass and its target pass (must not be deferred). On main the pixels pass and the 6 counter checks fail (the updates end the passes); with the change 21/21. Negative control: with OP_UPDATE_UB taken out of defer_try's refusals, the last case draws the later update's colour (64 pixels wrong). make -C dm/gfx/tests GAME=01007EF00011E000 run: every other target as on main (t_border, t_transform_feedback, t_pso_archive fail in a checkout whose path has a space, dm/gfx/tests: three targets fail when the checkout path contains a space #1341; t_nvn aborts on both).
  • Games run: none. The default replay is unchanged (tbdr_on() still off), so scripts/regress.py was not run.
  • Devices and OS: MacBook, Apple M5, macOS 26.6.2, Xcode 27.2.

Docs

  • The finding is in its docs/reference/rendering.md entry (and docs/env_switches.tsv), and python3 dm/tools/docs_symptoms.py was run (the symptom index)
  • No game files, keys or data extracted from a game in the change or the attachments

🤖 Generated with Claude Code

ubd_on was off whenever tbdr_on was, because TBDR mode reorders passes. Its
reorderers never move a draw across an update (defer_try refuses an
OP_UPDATE_UB in its window, fuse_try and the multi-draw scan stop at one,
hoist_try moves only clear-only passes, the layer lookahead asks ubd_on), so
with DM_NVN_TBDR=1 every inline update inside a pass ended it again for no
reason. DM_NVN_UB_DEFER=0 still turns the deferral off; nothing changes by
default (TBDR mode is off).

New check_t_tbdr_ubd: production mtl_exec with DM_NVN_TBDR=1, closed-form
pixels for in-pass, same-target continuation, deferred-pass and
update-between cases. On main the pixels pass and 6 counter checks fail.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Documentation nvn NVN on Metal and its tests (dm/gfx/nvn, dm/gfx/tests)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant