From adaa19cbf7f5d1ad7847ab0156e052e35a20f665 Mon Sep 17 00:00:00 2001 From: Carlo Refice Date: Thu, 18 Apr 2024 16:34:46 +0200 Subject: [PATCH] vulkan: Add support for A2R10G10B10 HDR format (#16435) --- gfx/common/vulkan_common.c | 14 ++++- gfx/common/vulkan_common.h | 4 ++ gfx/drivers/vulkan.c | 94 ++++++++++++++-------------- gfx/drivers_shader/shader_vulkan.cpp | 2 +- 4 files changed, 64 insertions(+), 50 deletions(-) diff --git a/gfx/common/vulkan_common.c b/gfx/common/vulkan_common.c index 9ffb1cd9a2..c37b58cbf8 100644 --- a/gfx/common/vulkan_common.c +++ b/gfx/common/vulkan_common.c @@ -1886,6 +1886,17 @@ retry: vulkan_acquire_wait_fences(vk); } +#ifdef VULKAN_HDR_SWAPCHAIN +bool vulkan_is_hdr10_format(VkFormat format) +{ + return + ( + format == VK_FORMAT_A2B10G10R10_UNORM_PACK32 + || format == VK_FORMAT_A2R10G10B10_UNORM_PACK32 + ); +} +#endif /* VULKAN_HDR_SWAPCHAIN */ + bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk, unsigned width, unsigned height, unsigned swap_interval) @@ -2067,11 +2078,12 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk, for (i = 0; i < format_count; i++) { - if ( (formats[i].format == VK_FORMAT_A2B10G10R10_UNORM_PACK32) + if ( (vulkan_is_hdr10_format(formats[i].format)) && (formats[i].colorSpace == VK_COLOR_SPACE_HDR10_ST2084_EXT)) { format = formats[i]; video_driver_set_hdr_support(); + break; } } diff --git a/gfx/common/vulkan_common.h b/gfx/common/vulkan_common.h index 4007164612..cba04993e3 100644 --- a/gfx/common/vulkan_common.h +++ b/gfx/common/vulkan_common.h @@ -728,6 +728,10 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk, void vulkan_debug_mark_image(VkDevice device, VkImage image); void vulkan_debug_mark_memory(VkDevice device, VkDeviceMemory memory); +#ifdef VULKAN_HDR_SWAPCHAIN +bool vulkan_is_hdr10_format(VkFormat format); +#endif /* VULKAN_HDR_SWAPCHAIN */ + RETRO_END_DECLS #endif diff --git a/gfx/drivers/vulkan.c b/gfx/drivers/vulkan.c index 5d4473133c..4d8a6c3015 100644 --- a/gfx/drivers/vulkan.c +++ b/gfx/drivers/vulkan.c @@ -2776,31 +2776,30 @@ static bool vulkan_init_default_filter_chain(vk_t *vk) : VK_FORMAT_UNDEFINED; bool emits_hdr10 = shader_preset && shader_preset->passes && vulkan_filter_chain_emits_hdr10(vk->filter_chain); - switch (rt_format) + if (vulkan_is_hdr10_format(rt_format)) { - case VK_FORMAT_A2B10G10R10_UNORM_PACK32: - /* If the last shader pass uses a RGB10A2 back buffer - * and HDR has been enabled, assume we want to skip - * the inverse tonemapper and HDR10 conversion. - * If we just inherited HDR10 format based on backbuffer, - * we would have used RGBA8, and thus we should do inverse tonemap as expected. */ - vulkan_set_hdr_inverse_tonemap(vk, !emits_hdr10); - vulkan_set_hdr10(vk, !emits_hdr10); - vk->flags |= VK_FLAG_SHOULD_RESIZE; - break; - case VK_FORMAT_R16G16B16A16_SFLOAT: - /* If the last shader pass uses a RGBA16 backbuffer - * and HDR has been enabled, assume we want to - * skip the inverse tonemapper */ - vulkan_set_hdr_inverse_tonemap(vk, false); - vulkan_set_hdr10(vk, true); - vk->flags |= VK_FLAG_SHOULD_RESIZE; - break; - case VK_FORMAT_UNDEFINED: - default: - vulkan_set_hdr_inverse_tonemap(vk, true); - vulkan_set_hdr10(vk, true); - break; + /* If the last shader pass uses a RGB10A2 back buffer + * and HDR has been enabled, assume we want to skip + * the inverse tonemapper and HDR10 conversion. + * If we just inherited HDR10 format based on backbuffer, + * we would have used RGBA8, and thus we should do inverse tonemap as expected. */ + vulkan_set_hdr_inverse_tonemap(vk, !emits_hdr10); + vulkan_set_hdr10(vk, !emits_hdr10); + vk->flags |= VK_FLAG_SHOULD_RESIZE; + } + else if (rt_format == VK_FORMAT_R16G16B16A16_SFLOAT) + { + /* If the last shader pass uses a RGBA16 backbuffer + * and HDR has been enabled, assume we want to + * skip the inverse tonemapper */ + vulkan_set_hdr_inverse_tonemap(vk, false); + vulkan_set_hdr10(vk, true); + vk->flags |= VK_FLAG_SHOULD_RESIZE; + } + else + { + vulkan_set_hdr_inverse_tonemap(vk, true); + vulkan_set_hdr10(vk, true); } } #endif /* VULKAN_HDR_SWAPCHAIN */ @@ -2848,31 +2847,30 @@ static bool vulkan_init_filter_chain_preset(vk_t *vk, const char *shader_path) : VK_FORMAT_UNDEFINED; bool emits_hdr10 = shader_preset && shader_preset->passes && vulkan_filter_chain_emits_hdr10(vk->filter_chain); - switch (rt_format) + if (vulkan_is_hdr10_format(rt_format)) { - case VK_FORMAT_A2B10G10R10_UNORM_PACK32: - /* If the last shader pass uses a RGB10A2 backbuffer - * and HDR has been enabled, assume we want to - * skip the inverse tonemapper and HDR10 conversion - * If we just inherited HDR10 format based on backbuffer, - * we would have used RGBA8, and thus we should do inverse tonemap as expected. */ - vulkan_set_hdr_inverse_tonemap(vk, !emits_hdr10); - vulkan_set_hdr10(vk, !emits_hdr10); - vk->flags |= VK_FLAG_SHOULD_RESIZE; - break; - case VK_FORMAT_R16G16B16A16_SFLOAT: - /* If the last shader pass uses a RGBA16 backbuffer - * and HDR has been enabled, assume we want to - * skip the inverse tonemapper */ - vulkan_set_hdr_inverse_tonemap(vk, false); - vulkan_set_hdr10(vk, true); - vk->flags |= VK_FLAG_SHOULD_RESIZE; - break; - case VK_FORMAT_UNDEFINED: - default: - vulkan_set_hdr_inverse_tonemap(vk, true); - vulkan_set_hdr10(vk, true); - break; + /* If the last shader pass uses a RGB10A2 back buffer + * and HDR has been enabled, assume we want to skip + * the inverse tonemapper and HDR10 conversion. + * If we just inherited HDR10 format based on backbuffer, + * we would have used RGBA8, and thus we should do inverse tonemap as expected. */ + vulkan_set_hdr_inverse_tonemap(vk, !emits_hdr10); + vulkan_set_hdr10(vk, !emits_hdr10); + vk->flags |= VK_FLAG_SHOULD_RESIZE; + } + else if (rt_format == VK_FORMAT_R16G16B16A16_SFLOAT) + { + /* If the last shader pass uses a RGBA16 backbuffer + * and HDR has been enabled, assume we want to + * skip the inverse tonemapper */ + vulkan_set_hdr_inverse_tonemap(vk, false); + vulkan_set_hdr10(vk, true); + vk->flags |= VK_FLAG_SHOULD_RESIZE; + } + else + { + vulkan_set_hdr_inverse_tonemap(vk, true); + vulkan_set_hdr10(vk, true); } } #endif /* VULKAN_HDR_SWAPCHAIN */ diff --git a/gfx/drivers_shader/shader_vulkan.cpp b/gfx/drivers_shader/shader_vulkan.cpp index 78a48f49ca..1c529791c6 100644 --- a/gfx/drivers_shader/shader_vulkan.cpp +++ b/gfx/drivers_shader/shader_vulkan.cpp @@ -3262,7 +3262,7 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset( VkFormat pass_format = glslang_format_to_vk(output.meta.rt_format); /* If final pass explicitly emits RGB10, consider it HDR color space. */ - if (explicit_format && pass_format == VK_FORMAT_A2B10G10R10_UNORM_PACK32) + if (explicit_format && vulkan_is_hdr10_format(pass_format)) chain->set_hdr10(); if (explicit_format && pass_format != pass_info.rt_format)