Skip to content

beta.1: tested profiles, headset settings menu, standby fix, frame budget and image quality (.66-.134) - #23

Merged
JMS1717 merged 149 commits into
mainfrom
claude/frame-budget
Oct 9, 2026
Merged

JMS1717 merged 149 commits into
mainfrom
claude/frame-budget

Conversation

@JMS1717

@JMS1717 JMS1717 commented Oct 7, 2026 •

Copy link
Copy Markdown
Owner

Everything on claude/frame-budget since alpha.9 (.63), up to .134. Merging this makes main the beta.1 release.

For players

  • Seven tested streaming profiles plus a fresh-install Starter 72 Hz, with a guide: docs/PROFILES.md. Recommended over USB: Quality 120 Hz (2272 x 2432 per eye, CDF 5/3, 1500 Mbit/s).
  • Headset settings menu: hold both thumbsticks for about 0.7 s. Pick a profile or change refresh, bitrate, stream and render size, chroma and overlay; every row explains itself.
  • No more drops to 10 FPS after a reconnect (.134): the driver counts overlapping connections and keeps SteamVR from idling a streaming headset.
  • Colour fixes (full range, Quest colour gamut), sharper PC downsampling, encoder tuning for full-size streams, 4:4:4 at 120 Hz, direct eye copy and paired chroma by default, four wired connections, refresh-rate fixes.

Measured on .134 (one Quest 3, USB, short screens, heavy SteamVR Home)

Profile Fresh FPS ALVR latency estimate
Quality 120 Hz 119.4 of 120 35 ms
Godlike 120 Hz (Haar) 117.5, 115.9 of 120 43 ms
Godlike 90 Hz (CDF 5/3) 88.9, 90.1 of 90 48-54 ms

No standby while streaming in five cells. Not checked: sustained play, the Wi-Fi profiles live, optical latency.

Release notes: docs/RELEASE-beta.1.md.

Constant bitrate was spread over the refresh rate. A game presenting 150-180 fps on a
207 Hz panel then got bitrate/207 per frame and used only 77-87% of the bitrate.
adapt_to_framerate is now on by default and follows an exponential average of the
present interval: rising rates apply at once, falling rates at the 1 s update, and a
frame is at most twice the refresh-rate frame size.
When no head sample reaches the PC between two vsyncs, the server
extrapolates the newest head pose by its velocity to a marked timestamp
and renders from that instead of re-rendering the previous pose. The
client keeps the motion it sent and resolves the marked timestamp with
the same extrapolation for reprojection. Head velocity is now sent
(was zeroed). Setting: headset.extrapolate_late_head_poses (default on).

ALVR stream socket and PyroWave transport default to UDP (Wi-Fi only;
USB stays TCP). Wi-Fi 6E, 120 Hz / 1250 Mbps: UDP 2.9% vs TCP 4.2%
repeated poses.

Scene: Q3PW_SCENE_OVERDRAW for a GPU-bound test scene.
125 % (2592x2784 after alignment) holds 115.5 fresh FPS at 120 Hz wired with a
7.7 ms decode fence; 3072x3216 reaches 86. Offline at 1500 Mbps, 2560x2720 keeps
1.3 dB more PSNR-HVS-M against a 3072x3216 render than 2080x2208.
ABBA, wired CDF 5/3: network p99 7.8-7.9 -> 5.1-5.2 ms at 207 Hz/1000 Mbps and
16.7-18.2 -> 14.8-14.9 ms at 120 Hz/2000 Mbps (stream 125 %), same fresh FPS.
@JMS1717 JMS1717 changed the title Frame budget from the present rate; server-predicted head poses; UDP on Wi-Fi (.66–.68) Frame budget, server-predicted head poses, UDP on Wi-Fi, supersampled stream, 4 wired connections (.66–.70) Oct 8, 2026
JMS1717 added 21 commits October 7, 2026 20:33
…text

tools/downsample/entropy_model.py costs the same quantized CDF 5/3 coefficients as
PyroWave's raw bit-planes, a neighbour/parent-context coder and a static per-group
code, and reports PSNR at the live byte caps. docs/ENTROPY.md records the results.
debug.q3pw.sharpen=1..100 applies FidelityFX CAS (cross neighbourhood, luma only) in the packed-YCbCr eye shader. Off by default; not applied with light foveated encoding.
… (.72)

The headset's eye shader applies CAS at the configured sharpness; debug.q3pw.sharpen still overrides it for tests (0 forces off).
The rest is drawn with the plain program, as foveation draws its bands. debug.q3pw.sharpen_area (10-100) sets the share for tests.
Centre-only CAS at 50: free at 120 Hz/100 %, about -5 FPS at 207 Hz and -8 at 120 Hz/125 %; whole-image cost 19 FPS in both.
…ass (.74)

Luma, Cb and Cr are written as 2x2 quads side by side in one RGBA8 AHB 3/2
the frame width; ALVR's eye shader reads full-resolution chroma at the luma
pixel. 4:4:4 with CDF 5/3 asks for mode 7 by default and falls back to mode 3.
Offline at 120 Hz/1500 (2080) linear 0.15/neighbour keeps +1.69 dB PSNR-HVS-M
over no sharpening against +1.23 for CAS 50, with fewer overshooting pixels
(8.3 % vs 9.8 %). debug.q3pw.sharpen_kernel=cas keeps CAS for A/B.
…decode 2.65 ms

tools/entropy: coefficient dump, QR coder (CPU encode/decode), Vulkan decode shader and a bench that checks every coefficient. On the Quest the decode reaches 2.65 ms with lane-interleaved stores, longest blocks first and branch-uniform steps; it is close to throughput-bound. Results, rejected variants and what building it would take are in docs/ENTROPY.md; parked until the owner's 120 Hz tests.
JMS1717 added 26 commits October 9, 2026 04:32
… (.121)

HorizonOS clears debug.oculus.gpuLevel whenever the client restarts. The display
helper rewrote it with a wake and a client restart and, after two clears, stopped
forcing it until the server restarted, so the GPU fell to level 4 (640 MHz) in
long sessions. The runtime applies the level live (cleared: level 4 within 3 s;
7: 690 MHz within 6 s), so a GPU-only change is now written directly. Reverts are
counted only when a display change restarts the client.
Quality 120 4:4:4 (CDF 5/3, 2270x2429 per eye, 1500 Mbps, wired) on .121, ABAB:
forced LOW 118.6/119.6/119.9 fresh against 115.7/113.6/116.2 at default priority;
frames superseded after decode fall from 4-6.5/s to 0-0.4/s. Latency excluding
game time is a tie (about 38 ms): decode runs longer under LOW, the vsync queue
shortens by about the same amount.
.122 gave 4:4:4 the 4:2:0 limit (2.0 Gpx/s), which put full-size 4:4:4 at
90 Hz (1.79 G) on LOW. There CDF 5/3 4:4:4 decode takes 8.2-8.5 ms of the
11.1 ms period and LOW gave 75.5/75.6 fresh against 83.6/83.4 at default
(wired, 1500 Mbps, level 7). Quality 120 4:4:4 (1.33 G) keeps LOW.
4:4:4 with Haar fell back to the old path (R8 planes plus pyroclient's
conversion pass). The multilevel Haar pass is per component, so 4:4:4
chroma takes the luma schedule and its final pass stores quads at
x = width/2 and width, the layout Decoder V2 mode 7 and ALVR's eye shader
already use. The decoder accepts haar32 modes 1-3 and 7 for 4:4:4;
pyroclient asks for 7 when 5-6 are requested and steps down to 3 without
storage on the AHB. decoder_ab gains AB_CHROMA=444 and haar32m7/cdf53v2m7
arms for the exactness gate.
Writes the next N (at most 16) complete PyroWave codec frames to the app's
external files dir, once per new property value, for offline bitstream and
entropy-coding analysis. Off by default.
tools/entropy/pw2qcf.py parses a complete PyroWave frame (wavelet_dequant.comp's
layout) into QCF1 for qrenc and reports the quant side information's entropy.
qrcodec.hpp: a context with one symbol has frequency 4096, which overflowed the
32-bit renormalization bound to 0 and looped forever; use 64 bits.
A stream taller than the panel's 2208 rows loses much of its finest band to
the display resample. The CSF's level-0 frequency now scales by rows / 2208:
23.6 cycles/degree at full size instead of 16.2. Offline at panel resolution,
full size, 120 Hz: +0.6/+0.7 dB PSNR-HVS-M at 1500/1000 Mbps; neutral at 2784
rows. csf_study.py gains STUDY_FULL / STUDY_STREAM display-referred scoring.
…ile streaming (.131)

The in-headset settings menu gains a Profile row that applies a whole tested
profile (Quality 120, Godlike 120/90, Colour 4:4:4, Wi-Fi Quality 120, Wi-Fi 90,
Competitive 207, Starter 72) and shows two lines of help for the selected row.
The streamer rejects USB-only profiles on Wi-Fi and profiles that need a refresh
rate the headset did not offer. The dashboard list drops the superseded bitrate
and latency experiments.

The driver blocks SteamVR's motion-idle standby while a client streams: a still
head or a headset on a bench no longer drops the stream to 10 Hz.
… streaming (.132)

At 120 Hz full size, CDF 5/3 held 112 fresh FPS against Haar's 116-117 and
added 5 ms to ALVR's latency estimate with frames queueing for the decoder, so
Godlike 120 keeps Haar. Godlike 90 has 11 ms a frame and uses CDF 5/3 for the
cleanest full-size image.

One of four .131 cells still entered SteamVR standby 12 s into a stream. The
driver now logs standby queries, entries and stream start/stop
([Q3PW_STANDBY]), and when SteamVR enters standby while a client streams it
re-asserts presence with a proximity change, as a stream start does. The
Apply help in the headset menu says a profile can restart SteamVR.
@JMS1717 JMS1717 changed the title Frame budget, server-predicted poses, UDP on Wi-Fi, supersampled stream, fast 4:4:4, refresh-rate fixes (.66–.92) beta.1: tested profiles, headset settings menu, standby fix, frame budget and image quality (.66-.134) Oct 9, 2026
@JMS1717
JMS1717 marked this pull request as ready for review October 9, 2026 15:52
@JMS1717
JMS1717 merged commit 8aca735 into main Oct 9, 2026
6 checks passed
@JMS1717
JMS1717 deleted the claude/frame-budget branch October 9, 2026 17:45
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