← Blog

A Vulkan layer that brings HDR back to virtual displays

NVIDIA and AMD Vulkan drivers accept an HDR swapchain on a virtual display but don't list the format. A small implicit layer adds the missing entries.

On a virtual display, NVIDIA's and AMD's Vulkan drivers return no HDR colour space from vkGetPhysicalDeviceSurfaceFormatsKHR, even with the desktop composed in HDR. Vulkan games such as Doom: The Dark Ages and Indiana Jones and the Great Circle read that list and turn HDR off.

The driver presents what it doesn't list

A test program created an HDR swapchain on the virtual display anyway: A2B10G10R10_UNORM_PACK32 in HDR10_ST2084_EXT, a pair the driver had not listed. vkCreateSwapchainKHR, vkSetHdrMetadataEXT and every present succeeded. The HDR path works; only the list is short.

The layer

VK_LAYER_PUNKTFUNK_hdr_inject is an implicit layer between every Vulkan program and the driver.

  • It intercepts vkGetPhysicalDeviceSurfaceFormatsKHR and its 2KHR variant, calls the driver, and appends HDR10 (A2B10G10R10_UNORM_PACK32, HDR10_ST2084_EXT) and scRGB (R16G16B16A16_SFLOAT, EXTENDED_SRGB_LINEAR_EXT), skipping any already listed.
  • It intercepts vkCreateWin32SurfaceKHR to map each surface to its window.
  • On every query it asks Windows (DisplayConfigGetDeviceInfo, advanced colour info) whether HDR is on for that window's monitor. If not, the list passes through unchanged, so an SDR display never offers HDR.

The driver then presents the HDR swapchain the game asks for. The layer checks the display's HDR state, not the GPU vendor.

Shipping it

The installer's HDR Vulkan layer row, on by default, registers it under HKLM\SOFTWARE\Khronos\Vulkan\ImplicitLayers. Registered machine-wide, it loads however a game starts; scoping by environment variable misses games launched by an already running Steam.

It loads into every Vulkan process, so it has off switches:

  • DISABLE_PF_VKHDR=1, the loader's standard switch, turns it off for that process.
  • A built-in list skips kernel anti-cheat titles: cs2.exe, rainbowsix.exe, rainbowsixgame.exe, r5apex.exe.
  • PF_VKHDR_EXCLUDE=foo.exe,bar.exe extends that list.

For implementers

The loader's private create-info structures, VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO and VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO, use the values 47 and 48, not the 1000211xxx range. Match the wrong value and vkCreateInstance fails inside your layer.

For players: the short fix. Confirm the cause on your PC: DirectX HDR works, Vulkan HDR doesn't.