fix(vdisplay/encode): feed NVENC packed RGB for HDR 4:4:4 #599
Open
enricobuehler
wants to merge 2 commits from
fix/vdisplay-hdr-444 into wp/vp-p4-drain-clock
pull from: fix/vdisplay-hdr-444
merge into: :wp/vp-p4-drain-clock
:main
:fix/edid-physical-size
:fix/cursor-dpi-normalise
:fix/vdisplay-rearrival-hdr
:fix/vdisplay-refused-diag
:fix/vdisplay-resize-reopen
:fix/vdisplay-keyframe-republish
:fix/vdisplay-hdr-444
:wp/vp-s6-bypass
:wp/g3-parity-battery
:wp/vp-s6-inwindow
:wp/vp-p4-drain-clock
:wp/vp-g4-harness
:wp/vp-p4-encode-stall-probe
:wp/vp-p4-stale-comments
:wp/vp-p4-split
:spike/webos-glprobe
:wp/vp-p4-classify
:wp/vp-p3-cut
:wp/vp-p3-int2
:wp/vp-p3-rungs
:wp/vp-p3-int
:wp/vp-p3-driver
:wp/vp-p2-s5
:wp/vp-p3-host
:wp/vp-p3-proto
:wp/vp-p1-hcount
:wp/vp-p2-spike-base
:wp/vp-p2-driver-build
:wp/vp-p1-11
:wp/vp-p1-stack
:wp/vp-p2-encode-win
:wp/vp-p1-10
:wp/vp-p1-9
:wp/vp-p1-6
:wp/vp-p1-7
:wp/vp-p1-8
:wp/vp-p1-3
:wp/vp-p1-4
:wp/vp-p1-5
:wp/vp-p1-2
:wp/vp-p1-1
:wp/vp-p0-4
:wp/vp-phase0-driver
:wp/vp-p0-3
:wp/vp-phase0-host
:wp/vp-p0-2
:wp/vp-p0-1
:feat/host-own-session-launch
:fix/handshake-test-module-order
:fix-windows-build-break
:fix-adapter-reload-verify
:fix/flatpak-setup-win-prune
:feat/windows-multiseat-addon
:fix-reassert-concede
:live-kill-recovery-gate
:live-wedged-worker-gate
:fix-reassert-breaker-window
:live-fence-ring-gate
:fix-live-create-drop-linger
:worktree-fix-apple-tvos-decoded-hardening
:worktree-wp11-connector-leases
:fix-manager-test-imports
:feat/store-launch-kinds
:worktree-wp7-host-fence-v3
:worktree-fix-stale-pairing-toasts
:worktree-wp10-topology-txn
:worktree-wp7-driver-fence-v2
:worktree-wp13-recovery-fsm
:worktree-wp7-fence-ring
:fix-steam-proto-doc-lint
:worktree-wp14-stream-continuity
:worktree-wp13-recovery-wiring-v2
:feat/installer-win-done-polish
:worktree-wp9-snapshot-readers-v2
:worktree-wp8-display-snapshot
:worktree-fix-tvos-focus
:fix/installer-win-smoke-findings
:smoke/installer-win-stack
:feat/installer-win-client
:feat/installer-win-inno-migration
:worktree-wp4-header-v3
:feat/installer-win-ci-engine
:fix/android-decoder-bare-rung
:feat/installer-win-pack
:spike/installer-win-s2
:spike/installer-win-s1
:feat/installer-v2-client
:feat/installer-v2-tui
:feat/installer-v2-engine
:worktree-omarchy-client-theme
:release/v0.34.0
:docs/stale-support-claims
:fix/openapi-spec-drift
:worktree-sc2-usb-macos
:pr-425-gapfix
:worktree-host-actions
:worktree-omarchy-installer-gaps
:worktree-docs-universal-installer
:worktree-keep-host-audio-parity
:worktree-standby-sink-investigation
:worktree-security-review-fixes
:worktree-abr-dscp-default
:worktree-abr-control-loop
:worktree-abr-transmission-plane
:worktree-pyrowave-forces-auto
:worktree-web-console-native-identity
:worktree-abr-encode-downdriver
:worktree-gamescope-exclusive-panel-off
:worktree-bitrate-picker
:worktree-fix-mic-tap-format-abort
:worktree-release-0313-recut
:ci-skia-download-retry
:worktree-audio-devnode-orphans
:worktree-gamescope-rebuild-keeps-hdr
:worktree-gamescope-idled-handback
:worktree-hevc-idr-storm-coalesce
:worktree-gamestream-pad-heartbeat
:worktree-steam-prelaunch-latch
:worktree-release-0312-prep
:worktree-firewall-program-scoped-rules
:worktree-blackscreen-data-plane-source-ip
:worktree-fix-frozen-local-ip
:worktree-android-pad-mapping-regression
:worktree-android-console-extra-keys
:worktree-data-plane-firewall-and-delivery-truth
:worktree-android-gamepad-ui-and-corner
:worktree-android-pad-hid-remap
:worktree-gamestream-xbox-hid-parity
:worktree-release-next-prep
:worktree-win-client-installer
:worktree-kwin-vout-enable-repair
:worktree-wp4-install-script
:docs-wp2-to-main
:worktree-docs-wp0-wp1-anti-drift
:worktree-kwin-vout-failed-permanent
:worktree-android-asc-hdr-dataspace
:worktree-console-controllers-page
:worktree-gamepad-probe-stack
:worktree-agents-md-setup
:worktree-android-skia-console
:worktree-android-asc-presenter
:worktree-win-teardown-abort
:worktree-audio-hires-default-on
:worktree-console-ui-aa
:worktree-pr270-review-fixes
:worktree-console-ui-overhaul
:worktree-hires-audio-pcm
:worktree-audio-stutter-fixes
:worktree-ds-pad-sink-pro-audio
:worktree-console-diagnostics
:worktree-ds-inhibit-storm
:worktree-security-review-2026-08-15-fixes
:worktree-pairing-friendly-device-name
:worktree-shield-select-back-quit
:worktree-android-canary-open-testing
:fix-host-cer-alias-null-key
:worktree-azure-trusted-signing
:worktree-audio-soft-limit-gain
:worktree-gamescope-exclusive-dpms
:fix/playnite-launcher-resolve
:worktree-macos-mic-rebuild-loop
:worktree-hyprland-cursor-mode-negotiation
:worktree-hd2-idle-recording-default
:worktree-steam-art-root-windows
:worktree-android-aaudio-shield-silence
:worktree-unpair-all-button
:worktree-appletv-present-depth
:worktree-av1-level-sentinel
:worktree-nix-plugin-runner-resolve
:worktree-release-0280
:worktree-console-plugin-update-all
:worktree-flatpak-skia-099-pin
:worktree-debian-ubuntu-support
:worktree-wowlan-support
:worktree-decky-shortcut-dup
:worktree-vk-level-gate-clamp
:worktree-edition-2024
:worktree-win-sleep-blockers
:worktree-rt-gpu-priority-defaults
:worktree-black-stream-fixes
:worktree-edid-lock-toggle
:worktree-gate-double-arm-fix
:chore/rust-safety-programme
:worktree-console-pinned-profile-library
:worktree-blackscreen-fixes
:build/web-silence-rollup-directive-warnings
:worktree-android-console-visual-refresh
:worktree-nixos-capped-compositor-exe-denied
:worktree-release-0270
:worktree-dm-helper-diagnosis
:worktree-gamescope-pin-bump-nobara
:worktree-notes-capsysnice-correction
:worktree-bazzite-docs-warning
:worktree-kwin-capability-identification
:worktree-gamescope-rpm-deb-builddeps
:worktree-pyrowave-wire-dead-code
:worktree-release-0260
:worktree-cursor-composite-hardening
:worktree-library-settings-origin-split
:worktree-native-decode-m0
:worktree-july-rpm-and-cursor
:worktree-presenter-cadence-wp1
:worktree-decky-brand-name
:worktree-win-amd-decoder-order
:worktree-stall-ride-through
:fix/pad-audio-wasapi-module-path
:feat/android-pad-audio
:worktree-adl-emul-probe
:worktree-haptics-m12-dry
:worktree-haptics-m9-richfb
:worktree-haptics-m11-settings
:worktree-apple-store-screenshots
:worktree-decky-slim-rework
:worktree-appstore-copy
:worktree-haptics-m10-wire
:worktree-haptics-m8-proto
:worktree-haptics-m7-windows
:worktree-haptics-m6-presenter
:worktree-wire-mtu-resilience
:worktree-haptics-m5-android
:worktree-haptics-m4-apple
:worktree-haptics-m3-rumble-engine
:worktree-android-presenter-023-triage
:worktree-vdisplay-resume-recovery
:worktree-kwin-vout-demirror
:fix/web-console-sweep
:fix/windows-web-console-lifecycle
:chore/windows-rerender-semantics
:fix/pf-encode-phase8
:fix/pf-encode-phase7
:feat/cursor-channel
:feat/desktop-mouse-mode
:feat/plugin-kit
:fix/network-split-standing-latency
:fix/windows-msix-arm64-and-manifest
:fix/encode-medium-tier
:fix/encode-rfi-taint-and-oob
:fix/encode-init-leak-and-twin-drift
:fix/encode-teardown-uaf
:feat/pyrowave-windows
:fix/ubuntu-2404-host-deb
:fix/ios-archive-provisioning
:merge/first-frame-latency
:feat/shared-clipboard-v2
:feat/apple-live-activities-widgets
:debug/touch-finger-logging
:feat/shared-clipboard
:midstream-resize
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
HDR combined with 4:4:4 regressed at the cutover, and the driver told the host otherwise. Found while tracing what gate 3's 4:4:4 parity clause could actually be measured with.
What was wrong
spec_formapped every HDR session to a 10-bit planar input, consultingchroma444only for the PyroWave arm. NVENC then computedwant_444 = chroma_444 && full_chroma_input, which is false for a 10-bit planar input, so it encoded 4:2:0.The interesting part is the lie, and it is not quite what it looked like. NVENC does own an input-format gate — "4:4:4 negotiated but the capturer delivered subsampled YUV" — but it runs at the first
submit.open()was a pure struct build that ignored its_formatargument, socaps(), which the driver reads immediately and returns in theSET_ENCODEreply before any frame exists, echoed the request back. The check was not missing; it ran too late to reach the reply. The host's own mismatch warning atstream.rs:3898was being silenced by that echo, and NVENC's later complaint never left the driver host process.The fix
Honest capabilities, at the point they are computed.
NvencD3d11Encoder::opennow uses itsformatargument to seedbuffer_fmtand to clear the effectivechroma_444when that format is not packed RGB.openandsubmitshare two new helpers so they cannot drift apart again.chroma_444_requestedkeeps the negotiated value, so a later RGB re-initialisation recovers 4:4:4 exactly as before. That fixes it for every caller ofpf-encode-win, not only the driver.The capability is restored, not just declared absent.
EncodeInput::Rgb10drives theHdrRgb10Converterthat was already in the tree and unused, intoR10G10B10A2_UNORMpool slots withBIND_RENDER_TARGET— the same bind flags the pre-cutover out-ring used, checked against the commit before the cutover. Cursor blend, deferred scratch and fence paths needed no change, sinceRgb10reads FP16 and lands in the existing deferred-scratch arm.Restricting packed RGB to NVENC narrows nothing: the handshake only ever asks 4:4:4 of NVENC or PyroWave.
One structural call worth reviewing
The input-kind decision moved into
pf-driver-proto::encode::EncodeInput(chooseplusfull_chroma), with the driver'sInputKindnow an alias. That is what lets the test run on macOS, and it puts the choice next to the reply it has to agree with rather than two crates away.Probe
EncodeProbeRequest::flagsgains HDR and 4:4:4 bits — no wire change,flagswas reserved.spec()now calls the sameInputKind::choosethatSET_ENCODEcalls, so the probe exercises the shipping decision instead of a copy, which is why the old probe could never have caught this: it hard-coded 8-bit 4:2:0. The open line logs the chosen input and the resultingchroma_444. Fixed in passing: the probe reply hard-codedbackend_opened = 1, so it always claimed NVENC.Test
a_444_request_picks_a_full_chroma_input— a table over backend, HDR and 4:4:4 pinning the chosen input, plus a loop asserting that both backends the host negotiates 4:4:4 for land on a full-chroma input at both depths. The HDR-plus-4:4:4 row is the regression. It runs on macOS: 52 tests pass inpf-driver-proto.CI, and a correction
I claimed in #594 that the clippy fix turns
windows-drivers.ymlgreen. That was wrong, and this branch proved it. A dispatch of that workflow fails 40 seconds in, before any Rust compiles, inpyrowave-sys's CMake with a path-too-long error, because the runner's checkout root pushes a tlog past the Windows path limit — exactly the hazard the workflow's own comment predicted. The same job fails identically on the base branch, so this lane is red on the whole stack for an infrastructure reason, not a code one. The clippy error was real and is still worth fixing; it simply was not what that lane was dying on.The driver therefore builds by hand instead: all four CI steps run in a short path on the build box, every exit code 0.
Residual
caps().chroma_444still cannot reflect the GPU's own HEVC 4:4:4 support at driver open, because that is only known after a device exists. The host already gates it before the handshake, so the only exposure is a multi-GPU box resolving a different adapter host-side than driver-side.View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.