Commit Graph
4 Commits
Author SHA1 Message Date
Gjon Gojcevic c9ba43bfb7 feat(videoout): present PQ display buffers through an HDR10 swapchain
Detect HDR output on the host: on Windows the monitor showing the window
must run in HDR10 (DXGI IDXGIOutput6), and on every host the window's
Vulkan surface must offer a 10-bit VK_COLOR_SPACE_HDR10_ST2084_EXT
swapchain with VK_EXT_swapchain_colorspace and VK_EXT_hdr_metadata. The
monitor's luminance comes from DXGI; hosts that report none get 1000
nits peak and full frame, 0 nits black.

While HDR output is available, sceVideoOutGetOutputStatus reports
dynamic range 2 and flag bit 0, sceSystemServiceGetHdrToneMapLuminance
reports the monitor's luminance, and every open port's output mode
event fires when that changes. PQ display buffers are presented
unchanged through an HDR10 swapchain with HDR metadata; any other
display buffer switches back to the SDR swapchain. Without HDR output
the PQ to SDR conversion uses the peak the title was last told as its
white level.

AI-assisted: yes
2026-10-14 02:55:21 -04:00
Gjon Gojcevic 76c0ba53e3 feat(agc): present BT.2100 PQ display buffers on an SDR output
Accept the 10-bit BT.2100 PQ display formats 0x8100070422000000 (red
in the low bits) and 0x8100070400000000 (blue in the low bits) and
convert them to 8-bit sRGB when presented: PQ EOTF, BT.2020 to BT.709
primaries, a luminance tone map whose white level is the tone-map
luminance sceSystemServiceGetHdrToneMapLuminance reports (reference
white min(203 nits, white level)), and the sRGB encoding.

The conversion runs on the CPU for linear buffers and DCC clear values,
in the color transfer shader for tiled guest buffers, and in the
presentation pass for resident images. The three share the PQ EOTF
table computed once in double precision.

AI-assisted: yes
2026-10-14 02:55:21 -04:00
Dean Galvin 3ddfc2395d test(agc): present slice 1 of an array image through the presentation pass 2026-10-14 17:41:55 +13:00
Dean Galvin c60b52d2d8 perf(agc): present resident displays without the 4K convert chain
A 10-bit resident display buffer (and an 8-bit one in the other channel
order or an sRGB type) went through vkCmdCopyImageToBuffer, the color
transfer's convert dispatch, vkCmdCopyBufferToImage into the scaler source
and a blit, all at the display's resolution, plus a full clear of the
swapchain image.

PresentationPass now draws such an image straight into the swapchain image
with one fragment pass: it reads the raw texels through an R32_UINT view,
decodes them as the guest-memory path does (the display's channel order, the
10-bit variant truncated to 8 bits), scales with a bilinear filter of the
decoded values and writes black outside the aspect-fit rectangle, so it
needs neither intermediate buffer nor a clear. The swapchain stays
B8G8R8A8_UNORM and now also allows color attachment use. A 16-bit float
display buffer keeps the convert chain: its encode goes through the
scanout threshold tables, and the pass refuses it.

The blit paths clear only the letterbox bands (blits from a 1x1 black
image) instead of the whole swapchain image, and the scaler source image is
only used by the guest-memory, uniform and 16-bit float paths. GPU frame
dumps of a drawn image are drawn by the same pass at the dump size,
sampling every n-th texel, so they hold the same bytes as before.

Test: agc_driver_presentation_pass compares the pass with the convert path
for both 8-bit and both 10-bit channel orders (identical unscaled and
letterboxed, within two levels of the blit filter scaled), checks that a
10-bit destination keeps every source bit, that dumps
equal the subsampled guest-path frame, that the band clears equal a full
clear, and that a 16-bit float display buffer is refused.
2026-10-14 05:40:11 +13:00