Skip to content

Commit

Permalink
rendervulkan: Forward HDR metadata in nested
Browse files Browse the repository at this point in the history
  • Loading branch information
misyltoad committed Oct 18, 2023
1 parent 3401da5 commit 2a16508
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 1 deletion.
18 changes: 18 additions & 0 deletions src/color_helpers.h
Original file line number Diff line number Diff line change
Expand Up @@ -397,6 +397,12 @@ color_xy_to_u16(float v)
return (uint16_t)round(v * 50000.0f);
}

static inline float
color_xy_from_u16(uint16_t v)
{
return v / 50000.0f;
}

static inline uint16_t
nits_to_u16(float nits)
{
Expand All @@ -411,6 +417,12 @@ nits_to_u16(float nits)
return (uint16_t)round(nits);
}

static inline float
nits_from_u16(uint16_t v)
{
return float(v);
}

static inline uint16_t
nits_to_u16_dark(float nits)
{
Expand All @@ -424,6 +436,12 @@ nits_to_u16_dark(float nits)
return (uint16_t)round(nits * 10000.0f);
}

static inline float
nits_from_u16_dark(uint16_t v)
{
return v / 10000.0f;
}

static constexpr displaycolorimetry_t displaycolorimetry_steamdeck_spec
{
.primaries = { { 0.602f, 0.355f }, { 0.340f, 0.574f }, { 0.164f, 0.121f } },
Expand Down
60 changes: 60 additions & 0 deletions src/rendervulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,7 @@ bool CVulkanDevice::createDevice()

bool hasDrmProps = false;
bool supportsForeignQueue = false;
bool supportsHDRMetadata = false;
for ( uint32_t i = 0; i < supportedExtensionCount; ++i )
{
if ( strcmp(supportedExts[i].extensionName,
Expand All @@ -374,6 +375,10 @@ bool CVulkanDevice::createDevice()
if ( strcmp(supportedExts[i].extensionName,
VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME) == 0 )
supportsForeignQueue = true;

if ( strcmp(supportedExts[i].extensionName,
VK_EXT_HDR_METADATA_EXTENSION_NAME) == 0 )
supportsHDRMetadata = true;
}

vk_log.infof( "physical device %s DRM format modifiers", m_bSupportsModifiers ? "supports" : "does not support" );
Expand Down Expand Up @@ -492,6 +497,9 @@ bool CVulkanDevice::createDevice()
enabledExtensions.push_back( VK_KHR_MAINTENANCE_5_EXTENSION_NAME );
#endif

if ( supportsHDRMetadata )
enabledExtensions.push_back( VK_EXT_HDR_METADATA_EXTENSION_NAME );

if ( BIsVRSession() )
{
#if HAVE_OPENVR
Expand Down Expand Up @@ -2559,11 +2567,61 @@ static void present_wait_thread_func( void )
}
}

void vulkan_update_swapchain_hdr_metadata( VulkanOutput_t *pOutput )
{
if (!g_output.swapchainHDRMetadata)
return;

if ( !g_device.vk.SetHdrMetadataEXT )
{
static bool s_bWarned = false;
if (!s_bWarned)
{
vk_log.errorf("Unable to forward HDR metadata with Vulkan as vkSetMetadataEXT is not supported.");
s_bWarned = true;
}
return;
}

hdr_metadata_infoframe &infoframe = g_output.swapchainHDRMetadata->metadata.hdmi_metadata_type1;
VkHdrMetadataEXT metadata =
{
.sType = VK_STRUCTURE_TYPE_HDR_METADATA_EXT,
.displayPrimaryRed = VkXYColorEXT { color_xy_from_u16(infoframe.display_primaries[0].x), color_xy_from_u16(infoframe.display_primaries[0].y) },
.displayPrimaryGreen = VkXYColorEXT { color_xy_from_u16(infoframe.display_primaries[1].x), color_xy_from_u16(infoframe.display_primaries[1].y), },
.displayPrimaryBlue = VkXYColorEXT { color_xy_from_u16(infoframe.display_primaries[2].x), color_xy_from_u16(infoframe.display_primaries[2].y), },
.whitePoint = VkXYColorEXT { color_xy_from_u16(infoframe.white_point.x), color_xy_from_u16(infoframe.white_point.y), },
.maxLuminance = nits_from_u16(infoframe.max_display_mastering_luminance),
.minLuminance = nits_from_u16_dark(infoframe.min_display_mastering_luminance),
.maxContentLightLevel = nits_from_u16(infoframe.max_cll),
.maxFrameAverageLightLevel = nits_from_u16(infoframe.max_fall),
};
g_device.vk.SetHdrMetadataEXT(g_device.device(), 1, &g_output.swapChain, &metadata);
}

void vulkan_present_to_window( void )
{
static uint64_t s_lastPresentId = 0;

uint64_t presentId = ++s_lastPresentId;

auto feedback = steamcompmgr_get_base_layer_swapchain_feedback();
if (feedback && feedback->hdr_metadata_blob)
{
if ( feedback->hdr_metadata_blob != g_output.swapchainHDRMetadata )
{
g_output.swapchainHDRMetadata = feedback->hdr_metadata_blob;
vulkan_update_swapchain_hdr_metadata( &g_output );
}
}
else if ( g_output.swapchainHDRMetadata != nullptr )
{
// Only way to clear hdr metadata for a swapchain in Vulkan
// is to recreate the swapchain.
g_output.swapchainHDRMetadata = nullptr;
vulkan_remake_swapchain();
}


VkPresentIdKHR presentIdInfo = {
.sType = VK_STRUCTURE_TYPE_PRESENT_ID_KHR,
Expand Down Expand Up @@ -2748,6 +2806,8 @@ bool vulkan_make_swapchain( VulkanOutput_t *pOutput )

g_device.vk.CreateFence( g_device.device(), &fenceInfo, nullptr, &pOutput->acquireFence );

vulkan_update_swapchain_hdr_metadata(pOutput);

return true;
}

Expand Down
4 changes: 3 additions & 1 deletion src/rendervulkan.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -475,6 +475,7 @@ struct VulkanOutput_t
std::vector< VkPresentModeKHR > presentModes;


std::shared_ptr<wlserver_hdr_metadata> swapchainHDRMetadata;
VkSwapchainKHR swapChain;
VkFence acquireFence;

Expand Down Expand Up @@ -681,7 +682,8 @@ static inline uint32_t div_roundup(uint32_t x, uint32_t y)
VK_FUNC(UpdateDescriptorSets) \
VK_FUNC(WaitForFences) \
VK_FUNC(WaitForPresentKHR) \
VK_FUNC(WaitSemaphores)
VK_FUNC(WaitSemaphores) \
VK_FUNC(SetHdrMetadataEXT)

class CVulkanDevice
{
Expand Down

0 comments on commit 2a16508

Please sign in to comment.