feat(client): HDR pass-through on the D3D11VA path

A PQ stream on the D3D11VA backend was always tone-mapped to sRGB by the
VideoProcessor — with D3D11VA now auto's first choice on Intel (40030e90),
Intel Windows users would have lost HDR entirely. When the presenter can
import an RGB10A2 D3D11 texture AND offers an HDR10 swapchain (the new
VulkanDecodeDevice::d3d11_hdr10 probe), the hand-off ring switches to
RGB10A2 and the VideoProcessor does a pure colorspace conversion (YCbCr
G2084 -> RGB G2084, no tone mapping); the emitted frame carries PQ/BT.2020
color, so the presenter flips its HDR10 swapchain and video image exactly
as it does for Vulkan Video PQ frames, and the blit passes the PQ values
through untouched. SDR-only paths keep the tonemap-to-sRGB BGRA8 ring;
in-band PQ flips rebuild the ring like a resize (generation-bumped).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-19 14:19:35 +02:00
parent 40030e90c8
commit fb8deb31a5
5 changed files with 143 additions and 46 deletions
+14 -2
View File
@@ -94,8 +94,9 @@ impl Presenter {
// (vkGetPhysicalDeviceImageFormatProperties2 — creating an unsupported external
// image is UB, observed as VK_ERROR_DEVICE_LOST at the first submits on NVIDIA).
#[cfg(windows)]
let win_capable = crate::d3d11::DEVICE_EXTENSIONS.iter().all(|n| has(n))
&& crate::d3d11::import_supported(&instance, pdev);
let (import_bgra8, import_rgb10) = crate::d3d11::import_supported(&instance, pdev);
#[cfg(windows)]
let win_capable = crate::d3d11::DEVICE_EXTENSIONS.iter().all(|n| has(n)) && import_bgra8;
#[cfg(windows)]
if win_capable {
dev_exts.extend(crate::d3d11::DEVICE_EXTENSIONS.iter().map(|n| n.as_ptr()));
@@ -392,14 +393,25 @@ impl Presenter {
d3d11_import: win_capable,
#[cfg(not(windows))]
d3d11_import: false,
// Filled in below — the HDR10 surface facts arrive with pick_formats.
d3d11_hdr10: false,
adapter_luid,
queue_lock: queue_lock.clone(),
})
} else {
None
};
#[cfg(windows)]
let mut video_export = video_export;
let (format, hdr10_format) = pick_formats(&surface_i, pdev, surface, has_colorspace_ext)?;
// The D3D11VA backend may emit its HDR (RGB10 PQ) ring only when this device can
// import the 10-bit texture AND the surface offers an HDR10 swapchain to pass it
// through to; otherwise a PQ stream keeps the decoder-side tonemap to sRGB.
#[cfg(windows)]
if let Some(v) = video_export.as_mut() {
v.d3d11_hdr10 = win_capable && import_rgb10 && hdr10_format.is_some();
}
let present_mode = pick_present_mode(&surface_i, pdev, surface)?;
tracing::info!(
?format,