Skip to content

feat(d3d11): DXR_WEAVE_GPU_TIMING per-stage weave timing (2D-under-the-lens P0) - #302

Merged
dfattal merged 2 commits into
mainfrom
feat/weave-timing-p0
Oct 5, 2026
Merged

dfattal merged 2 commits into
mainfrom
feat/weave-timing-p0

Conversation

@dfattal

@dfattal dfattal commented Oct 5, 2026 •

Copy link
Copy Markdown
Contributor

What

P0 of the "near-zero-cost 2D under the lens" plan: instrumentation only, in the D3D11 DP (leia_display_processor_d3d11.cpp). The runtime PR (DisplayXR/displayxr-runtime#1824) extends the service-side DXR_WEAVE_GPU_TIMING=1 diagnostic. Its weave stage covers the whole process_atlas call. This PR splits that stage inside the DP.

Knob

The knob is DXR_WEAVE_GPU_TIMING=1, the same one the runtime's D3D11 service reads. The DP runs in the service process, so one env var arms both lines. DXR_LEIA_DP_WEAVE_TIMING=1 is accepted as a plug-in-only alias.

Both are read with std::getenv and cached, like the plug-in's other knobs. The default is off. When off, the only per-call cost is one cached-bool check; no state is allocated and nothing is logged.

What is measured

GPU. Each 3D process_atlas gets four D3D11 timestamps plus a disjoint query, on the caller's immediate context. They are read back non-blocking from an 8-slot ring, a few frames late. A set still in flight when the ring wraps is dropped, never waited on.

stage brackets averaged over
pre_weave WGC bg compose-under, or the chroma-key fill frames where a pre-pass ran
sr_weave 2D-layer hand-off (set_compose_filter_strength + set_compose_layer) + leiasr_d3d11_weave, i.e. the SR weave including SR's in-weave compose all 3D weaves
alpha_gate the post-weave alpha gate (has_overlay=2 when the layer was composited) frames where it ran; with 2D layer= counts the has_overlay=2 subset
ck_strip the chroma-key strip, the other post-weave pass frames where it ran

CPU. sr_weave: wall time of the leiasr_d3d11_weave call itself, via QPC.

Per-window counts:

  • process_atlas calls: 3D weaves, 2D passthrough blits, and not-ready/absent flat blits;
  • 2D layer offered: the runtime called set_overlay_2d with a layer;
  • 2D layer composed: SR accepted it for this weave, i.e. compose was active;
  • 2D layer unchanged: offered and declared unchanged by the client (v14);
  • filter strength for composed frames: last, min and max (<0 = SR default);
  • bg-compose: WGC compose-under frames.

SR's own refilter count is already in the SR log, so it is not duplicated here.

How to read the log line

One WARN line per DP every 5 s, never per frame:

Leia D3D11 DP timing <window>s: process_atlas=N (3D weave=N, 2D blit=N, not-ready/absent=N) | 2D layer: offered=N composed=N unchanged=N strength last=S min=S max=S (<0 = SR default) | bg-compose=N | CPU sr_weave ms avg/max A/M | GPU ms avg/max n=N disjoint=N: pre_weave A/M (n=N) sr_weave A/M alpha_gate A/M (n=N, with 2D layer=N) ck_strip A/M (n=N)
  • The runtime's weave stage ≈ this line's pre_weave + sr_weave + alpha_gate/ck_strip, plus the DP's state-setting overhead.
  • composed vs offered: when composed < offered, SR refused the layer at weave time (it is also logged once as an error).
  • unchanged/offered is how often the client let SR reuse its prefilter. Compare it with SR's refilter count in the SR log.
  • A large gap between CPU sr_weave and GPU sr_weave means SR's CPU-side work (predictor, state), not GPU work.

Build

Built with scripts\build-windows.bat build from a worktree, against the local ../displayxr-runtime headers (ABI 5): green (DisplayXR-LeiaSR.dll linked and staged to _package/bin/plugins/). No runtime header changes are needed; this PR is independent of the runtime PR at compile time.

Testing

Not panel-tested yet; the hub session runs the panel A/B. Deploy by rename-swapping the dev DLL into C:\Program Files\DisplayXR\Plugins\LeiaSR\, then start the service with DXR_WEAVE_GPU_TIMING=1 in its environment.

🤖 Generated with Claude Code

…e-lens P0)

Under DXR_WEAVE_GPU_TIMING=1 (the runtime service's knob; alias
DXR_LEIA_DP_WEAVE_TIMING=1), the D3D11 DP logs one WARN line every 5 s:

- GPU time (non-blocking D3D11 timestamp queries, 8-slot ring, read back
  frames late) of the pre-weave pass (bg compose / chroma-key fill), the
  SR weave call (incl. the 2D-layer hand-off and SR's in-weave compose),
  and the post-weave alpha gate (has_overlay=2 subset counted) or
  chroma-key strip, separately;
- CPU wall time of leiasr_d3d11_weave;
- process_atlas counts (3D weave / 2D blit / not-ready), 2D layer
  offered / composed / declared-unchanged (v14), and the v15 filter
  strength (last/min/max) on composed frames.

Off by default; state is allocated only when the knob is on.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… the CRT getenv

On the panel box the plug-in's timing line never armed although the
runtime's read of the same knob in the same service process did. Read it
with GetEnvironmentVariableA, as env_present_opaque() already does, and
log the off state once at INFO so a missing line is diagnosable.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@dfattal
dfattal marked this pull request as ready for review October 5, 2026 08:26
@dfattal
dfattal merged commit c25b587 into main Oct 5, 2026
16 checks passed
@dfattal
dfattal deleted the feat/weave-timing-p0 branch October 5, 2026 08:26
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.

1 participant