rendervulkan: Forward HDR metadata in nested
This commit is contained in:
parent
3401da5469
commit
2a16508054
3 changed files with 81 additions and 1 deletions
|
@ -397,6 +397,12 @@ color_xy_to_u16(float v)
|
||||||
return (uint16_t)round(v * 50000.0f);
|
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
|
static inline uint16_t
|
||||||
nits_to_u16(float nits)
|
nits_to_u16(float nits)
|
||||||
{
|
{
|
||||||
|
@ -411,6 +417,12 @@ nits_to_u16(float nits)
|
||||||
return (uint16_t)round(nits);
|
return (uint16_t)round(nits);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline float
|
||||||
|
nits_from_u16(uint16_t v)
|
||||||
|
{
|
||||||
|
return float(v);
|
||||||
|
}
|
||||||
|
|
||||||
static inline uint16_t
|
static inline uint16_t
|
||||||
nits_to_u16_dark(float nits)
|
nits_to_u16_dark(float nits)
|
||||||
{
|
{
|
||||||
|
@ -424,6 +436,12 @@ nits_to_u16_dark(float nits)
|
||||||
return (uint16_t)round(nits * 10000.0f);
|
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
|
static constexpr displaycolorimetry_t displaycolorimetry_steamdeck_spec
|
||||||
{
|
{
|
||||||
.primaries = { { 0.602f, 0.355f }, { 0.340f, 0.574f }, { 0.164f, 0.121f } },
|
.primaries = { { 0.602f, 0.355f }, { 0.340f, 0.574f }, { 0.164f, 0.121f } },
|
||||||
|
|
|
@ -361,6 +361,7 @@ bool CVulkanDevice::createDevice()
|
||||||
|
|
||||||
bool hasDrmProps = false;
|
bool hasDrmProps = false;
|
||||||
bool supportsForeignQueue = false;
|
bool supportsForeignQueue = false;
|
||||||
|
bool supportsHDRMetadata = false;
|
||||||
for ( uint32_t i = 0; i < supportedExtensionCount; ++i )
|
for ( uint32_t i = 0; i < supportedExtensionCount; ++i )
|
||||||
{
|
{
|
||||||
if ( strcmp(supportedExts[i].extensionName,
|
if ( strcmp(supportedExts[i].extensionName,
|
||||||
|
@ -374,6 +375,10 @@ bool CVulkanDevice::createDevice()
|
||||||
if ( strcmp(supportedExts[i].extensionName,
|
if ( strcmp(supportedExts[i].extensionName,
|
||||||
VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME) == 0 )
|
VK_EXT_QUEUE_FAMILY_FOREIGN_EXTENSION_NAME) == 0 )
|
||||||
supportsForeignQueue = true;
|
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" );
|
vk_log.infof( "physical device %s DRM format modifiers", m_bSupportsModifiers ? "supports" : "does not support" );
|
||||||
|
@ -492,6 +497,9 @@ bool CVulkanDevice::createDevice()
|
||||||
enabledExtensions.push_back( VK_KHR_MAINTENANCE_5_EXTENSION_NAME );
|
enabledExtensions.push_back( VK_KHR_MAINTENANCE_5_EXTENSION_NAME );
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if ( supportsHDRMetadata )
|
||||||
|
enabledExtensions.push_back( VK_EXT_HDR_METADATA_EXTENSION_NAME );
|
||||||
|
|
||||||
if ( BIsVRSession() )
|
if ( BIsVRSession() )
|
||||||
{
|
{
|
||||||
#if HAVE_OPENVR
|
#if HAVE_OPENVR
|
||||||
|
@ -2559,12 +2567,62 @@ 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 )
|
void vulkan_present_to_window( void )
|
||||||
{
|
{
|
||||||
static uint64_t s_lastPresentId = 0;
|
static uint64_t s_lastPresentId = 0;
|
||||||
|
|
||||||
uint64_t presentId = ++s_lastPresentId;
|
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 = {
|
VkPresentIdKHR presentIdInfo = {
|
||||||
.sType = VK_STRUCTURE_TYPE_PRESENT_ID_KHR,
|
.sType = VK_STRUCTURE_TYPE_PRESENT_ID_KHR,
|
||||||
.swapchainCount = 1,
|
.swapchainCount = 1,
|
||||||
|
@ -2748,6 +2806,8 @@ bool vulkan_make_swapchain( VulkanOutput_t *pOutput )
|
||||||
|
|
||||||
g_device.vk.CreateFence( g_device.device(), &fenceInfo, nullptr, &pOutput->acquireFence );
|
g_device.vk.CreateFence( g_device.device(), &fenceInfo, nullptr, &pOutput->acquireFence );
|
||||||
|
|
||||||
|
vulkan_update_swapchain_hdr_metadata(pOutput);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -475,6 +475,7 @@ struct VulkanOutput_t
|
||||||
std::vector< VkPresentModeKHR > presentModes;
|
std::vector< VkPresentModeKHR > presentModes;
|
||||||
|
|
||||||
|
|
||||||
|
std::shared_ptr<wlserver_hdr_metadata> swapchainHDRMetadata;
|
||||||
VkSwapchainKHR swapChain;
|
VkSwapchainKHR swapChain;
|
||||||
VkFence acquireFence;
|
VkFence acquireFence;
|
||||||
|
|
||||||
|
@ -681,7 +682,8 @@ static inline uint32_t div_roundup(uint32_t x, uint32_t y)
|
||||||
VK_FUNC(UpdateDescriptorSets) \
|
VK_FUNC(UpdateDescriptorSets) \
|
||||||
VK_FUNC(WaitForFences) \
|
VK_FUNC(WaitForFences) \
|
||||||
VK_FUNC(WaitForPresentKHR) \
|
VK_FUNC(WaitForPresentKHR) \
|
||||||
VK_FUNC(WaitSemaphores)
|
VK_FUNC(WaitSemaphores) \
|
||||||
|
VK_FUNC(SetHdrMetadataEXT)
|
||||||
|
|
||||||
class CVulkanDevice
|
class CVulkanDevice
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue