Skip to content

HDR10 Presentation

Teo, Lim edited this page Oct 13, 2026 · 8 revisions

HDR10 Presentation

NWBLot supports HDR10/PQ presentation as an opt-in project preference. It preserves the normal SDR path when the active Vulkan surface cannot support HDR10.

Project Opt-in

Projects configure graphics before device creation through NWB::ConfigureProjectRuntime. Keep the preference in the application-owned startup implementation and let the loader adapter delegate to it, as described in Project API. Inside that implementation, where context is a NWB::ProjectStartupContext&, request HDR10 alongside the other startup settings:

if(!context.graphics.setHDR10OutputEnabled(true))
    return false;

setHDR10OutputEnabled is a pre-device setting. It returns false after device creation, so a project must not try to switch presentation mode during a live renderer session.

The Testbed requests HDR10 alongside its required bindless heap ABI in CoolStuff/Testbed/entry.cpp. Requesting HDR does not make it mandatory: the effective output remains a property of the selected display surface.

User Override

The loader accepts --sdr to force SDR presentation even when a project requests HDR10:

python -m launcher run testbed -- --sdr

This is a startup option. It changes the graphics request before the device and swapchain are created.

Vulkan Negotiation and Fallback

HDR10 is selected only when all of the following are true:

  • the project requested HDR10;
  • the instance enabled VK_EXT_swapchain_colorspace; and
  • the active surface advertises VK_FORMAT_A2B10G10R10_UNORM_PACK32 with VK_COLOR_SPACE_HDR10_ST2084_EXT.

When those conditions hold, the swapchain uses a 10-bit Rec.2020/PQ surface and reports HDR10 as its output mode. If the extension or surface format is unavailable, swapchain creation continues with a compatible SDR sRGB format and records an essential fallback message instead of rejecting the device. The swapchain log includes the effective format, color space, and HDR10/PQ or SDR/sRGB output mode.

VK_EXT_hdr_metadata is optional. When it is enabled for an HDR10 swapchain, the backend supplies Rec.2020/D65 metadata for a 1,000-nit mastering target.

Rendering Contract

Scene rendering, deferred composition, and AVBOIT retain linear radiance until the final Graphics presentation pass. For HDR10 that pass converts scene Rec.709 values to Rec.2020, maps reference white to 203 nits with a shoulder toward the 1,000-nit mastering peak, and applies ST.2084/PQ before writing the 10-bit swapchain image.

The SDR path uses the presentation attachment's sRGB conversion. Opaque and AVBOIT shading preserve linear RGB highlights above one until final presentation; alpha remains bounded coverage. Scene UI contributes a premultiplied display-linear Rec.709 layer. SDR blends that layer after scene exposure and tone mapping, before the attachment encodes sRGB. HDR10 converts mapped scene color and UI paper white to linear Rec.2020 nits, blends there, and encodes PQ once. UI paper white is 203 nits (NWB_HDR10_UI_PAPER_WHITE_NITS in impl/assets/graphics/common/hdr10.slangi).

impl/assets/graphics/deferred/composite_ps.slang performs the scene/UI join. Standalone UI uses impl/assets/graphics/ui/output_ps.slang to present the already-linear premultiplied layer over black, applying the same UI paper-white contract for HDR10.

Presentation Settings

PresentationSettings in impl/ecs_render/deferred/presentation_settings.h controls the display transform at the presentation boundary and is applied through RendererSystem::setPresentationSettings:

  • toneMap: LinearClamp or Reinhard (default).
  • exposure: linear multiplier applied at presentation for both output formats (default 1).
  • shoulder: SDR curve shoulder (default 0.65).

Scene lighting, transparency, refraction, and reflections always exchange linear radiance; exposure applies at presentation for both output formats. Tone map and shoulder select the SDR display transform only. HDR10 retains its calibrated reference-white/mastering-peak shoulder and PQ encoding instead of applying a second SDR curve. ValidatePresentationSettings rejects non-finite or out-of-range values before they reach the presentation pass.

Verification

Current unit coverage includes selected public presentation-receipt failure and lifetime edges in nwb_graphics_presentation_tests, plus HDR scene/UI blending and invalid presentation settings in nwb_ecs_graphics_tests (output_layer_color_tests.cpp and presentation_settings_tests.cpp). Run the normal full Linux debug verification described in Build and Verification.

Related pages: Project API, Runtime Boot, Renderer, Renderer Frame Flow, and Testbed.

Clone this wiki locally