From 1a228a4e789b00bb9eb1237286b5a0a9cfbc7f7f Mon Sep 17 00:00:00 2001 From: MajorPainTheCactus <89490246+MajorPainTheCactus@users.noreply.github.com> Date: Sat, 8 Jan 2022 12:22:34 +0000 Subject: [PATCH] Added HDR support to Vulkan driver (#13456) --- gfx/common/vulkan_common.c | 36 +- gfx/common/vulkan_common.h | 53 ++- gfx/drivers/d3d12.c | 2 + gfx/drivers/vulkan.c | 493 +++++++++++++++++++++++- gfx/drivers/vulkan_shaders/hdr.frag | 112 ++++++ gfx/drivers/vulkan_shaders/hdr.frag.inc | 434 +++++++++++++++++++++ gfx/drivers_shader/shader_vulkan.cpp | 34 +- gfx/drivers_shader/shader_vulkan.h | 4 + 8 files changed, 1148 insertions(+), 20 deletions(-) create mode 100644 gfx/drivers/vulkan_shaders/hdr.frag create mode 100644 gfx/drivers/vulkan_shaders/hdr.frag.inc diff --git a/gfx/common/vulkan_common.c b/gfx/common/vulkan_common.c index b3f5bea530..1c3370768a 100644 --- a/gfx/common/vulkan_common.c +++ b/gfx/common/vulkan_common.c @@ -3055,15 +3055,38 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk, { RARCH_ERR("[Vulkan]: Surface has no formats.\n"); return false; - } + } + +#ifdef VULKAN_HDR_SWAPCHAIN + vk->context.hdr_enable = settings->bools.video_hdr_enable; + + video_driver_unset_hdr_support(); for (i = 0; i < format_count; i++) { - if ( - formats[i].format == VK_FORMAT_R8G8B8A8_UNORM || - formats[i].format == VK_FORMAT_B8G8R8A8_UNORM || - formats[i].format == VK_FORMAT_A8B8G8R8_UNORM_PACK32) + if (formats[i].format == VK_FORMAT_A2B10G10R10_UNORM_PACK32 && formats[i].colorSpace == VK_COLOR_SPACE_HDR10_ST2084_EXT) + { format = formats[i]; + video_driver_set_hdr_support(); + } + } + + if (!vk->context.hdr_enable || format.format == VK_FORMAT_UNDEFINED) + { + vk->context.hdr_enable = false; + } + + if (!vk->context.hdr_enable) +#endif // VULKAN_HDR_SWAPCHAIN + { + for (i = 0; i < format_count; i++) + { + if ( + formats[i].format == VK_FORMAT_R8G8B8A8_UNORM || + formats[i].format == VK_FORMAT_B8G8R8A8_UNORM || + formats[i].format == VK_FORMAT_A8B8G8R8_UNORM_PACK32) + format = formats[i]; + } } if (format.format == VK_FORMAT_UNDEFINED) @@ -3187,6 +3210,9 @@ bool vulkan_create_swapchain(gfx_ctx_vulkan_data_t *vk, vk->context.swapchain_width = swapchain_size.width; vk->context.swapchain_height = swapchain_size.height; +#ifdef VULKAN_HDR_SWAPCHAIN + vk->context.swapchain_colour_space = format.colorSpace; +#endif // VULKAN_HDR_SWAPCHAIN /* Make sure we create a backbuffer format that is as we expect. */ switch (format.format) diff --git a/gfx/common/vulkan_common.h b/gfx/common/vulkan_common.h index aa980b30b2..14e34d8000 100644 --- a/gfx/common/vulkan_common.h +++ b/gfx/common/vulkan_common.h @@ -31,6 +31,8 @@ #define VULKAN_DIRTY_DYNAMIC_BIT 0x0001 +#define VULKAN_HDR_SWAPCHAIN + #include "vksym.h" #include @@ -90,6 +92,28 @@ enum vulkan_wsi_type VULKAN_WSI_MVK_IOS, }; +#ifdef VULKAN_HDR_SWAPCHAIN + +#ifndef ALIGN +#ifdef _MSC_VER +#define ALIGN(x) __declspec(align(x)) +#else +#define ALIGN(x) __attribute__((aligned(x))) +#endif +#endif + +typedef struct ALIGN(16) +{ + math_matrix_4x4 mvp; + float contrast; /* 2.0f */ + float paper_white_nits; /* 200.0f */ + float max_nits; /* 1000.0f */ + float expand_gamut; /* 1.0f */ + float inverse_tonemap; /* 1.0f */ + float hdr10; /* 1.0f */ +} vulkan_hdr_uniform_t; +#endif // VULKAN_HDR_SWAPCHAIN + typedef struct vulkan_context { slock_t *queue_lock; @@ -106,6 +130,9 @@ typedef struct vulkan_context VkImage swapchain_images[VULKAN_MAX_SWAPCHAIN_IMAGES]; VkFence swapchain_fences[VULKAN_MAX_SWAPCHAIN_IMAGES]; VkFormat swapchain_format; +#ifdef VULKAN_HDR_SWAPCHAIN + VkColorSpaceKHR swapchain_colour_space; +#endif // VULKAN_HDR_SWAPCHAIN VkSemaphore swapchain_semaphores[VULKAN_MAX_SWAPCHAIN_IMAGES]; VkSemaphore swapchain_acquire_semaphore; @@ -131,6 +158,11 @@ typedef struct vulkan_context bool swapchain_is_srgb; bool swap_interval_emulation_lock; bool has_acquired_swapchain; + +#ifdef VULKAN_HDR_SWAPCHAIN + bool hdr_enable; +#endif // VULKAN_HDR_SWAPCHAIN + } vulkan_context_t; struct vulkan_emulated_mailbox @@ -197,6 +229,7 @@ struct vk_image VkImage image; /* ptr alignment */ VkImageView view; /* ptr alignment */ VkFramebuffer framebuffer; /* ptr alignment */ + VkDeviceMemory memory; /* ptr alignment */ }; struct vk_texture @@ -311,6 +344,9 @@ typedef struct vk const gfx_ctx_driver_t *ctx_driver; struct vk_per_frame *chain; struct vk_image *backbuffer; +#ifdef VULKAN_HDR_SWAPCHAIN + struct vk_image main_buffer; +#endif // VULKAN_HDR_SWAPCHAIN unsigned video_width; unsigned video_height; @@ -359,6 +395,9 @@ typedef struct vk { VkPipeline alpha_blend; VkPipeline font; +#ifdef VULKAN_HDR_SWAPCHAIN + VkPipeline hdr; +#endif // VULKAN_HDR_SWAPCHAIN VkDescriptorSetLayout set_layout; VkPipelineLayout layout; VkPipelineCache cache; @@ -366,11 +405,23 @@ typedef struct vk struct { - VkPipeline pipelines[7 * 2]; + VkPipeline pipelines[8 * 2]; struct vk_texture blank_texture; bool blend; } display; +#ifdef VULKAN_HDR_SWAPCHAIN + struct + { + struct vk_buffer ubo; + float max_output_nits; + float min_output_nits; + float max_cll; + float max_fall; + bool support; + } hdr; +#endif // VULKAN_HDR_SWAPCHAIN + struct { struct vk_texture textures[VULKAN_MAX_SWAPCHAIN_IMAGES]; diff --git a/gfx/drivers/d3d12.c b/gfx/drivers/d3d12.c index 77754abd02..ecc22156cc 100644 --- a/gfx/drivers/d3d12.c +++ b/gfx/drivers/d3d12.c @@ -667,6 +667,7 @@ static bool d3d12_gfx_set_shader(void* data, enum rarch_shader_type type, const } } +#ifdef HAVE_DXGI_HDR if (d3d12->hdr.enable) { if(d3d12->shader_preset && d3d12->shader_preset->passes && (d3d12->pass[d3d12->shader_preset->passes - 1].semantics.format == SLANG_FORMAT_A2B10G10R10_UNORM_PACK32)) @@ -689,6 +690,7 @@ static bool d3d12_gfx_set_shader(void* data, enum rarch_shader_type type, const d3d12_set_hdr10(d3d12, true); } } +#endif // HAVE_DXGI_HDR for (i = 0; i < d3d12->shader_preset->luts; i++) { diff --git a/gfx/drivers/vulkan.c b/gfx/drivers/vulkan.c index c2340a4943..ecbc160021 100644 --- a/gfx/drivers/vulkan.c +++ b/gfx/drivers/vulkan.c @@ -187,7 +187,7 @@ static void vulkan_init_pipeline_layout( VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO }; VkPipelineLayoutCreateInfo layout_info = { VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO }; - VkDescriptorSetLayoutBinding bindings[2] = {{0}}; + VkDescriptorSetLayoutBinding bindings[3] = {{0}}; bindings[0].binding = 0; bindings[0].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER; @@ -200,8 +200,14 @@ static void vulkan_init_pipeline_layout( bindings[1].descriptorCount = 1; bindings[1].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; bindings[1].pImmutableSamplers = NULL; + + bindings[2].binding = 2; + bindings[2].descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + bindings[2].descriptorCount = 1; + bindings[2].stageFlags = VK_SHADER_STAGE_FRAGMENT_BIT; + bindings[2].pImmutableSamplers = NULL; - set_layout_info.bindingCount = 2; + set_layout_info.bindingCount = 3; set_layout_info.pBindings = bindings; vkCreateDescriptorSetLayout(vk->context->device, @@ -216,6 +222,12 @@ static void vulkan_init_pipeline_layout( static void vulkan_init_pipelines(vk_t *vk) { +#ifdef VULKAN_HDR_SWAPCHAIN + static const uint32_t hdr_frag[] = +#include "vulkan_shaders/hdr.frag.inc" + ; +#endif // VULKAN_HDR_SWAPCHAIN + static const uint32_t alpha_blend_vert[] = #include "vulkan_shaders/alpha_blend.vert.inc" ; @@ -417,11 +429,38 @@ static void vulkan_init_pipelines(vk_t *vk) 1, &pipe, NULL, &vk->display.pipelines[i]); } - vkDestroyShaderModule(vk->context->device, shader_stages[0].module, NULL); vkDestroyShaderModule(vk->context->device, shader_stages[1].module, NULL); +#ifdef VULKAN_HDR_SWAPCHAIN + blend_attachment.blendEnable = false; + + /* HDR pipeline. */ + module_info.codeSize = sizeof(hdr_frag); + module_info.pCode = hdr_frag; + shader_stages[1].stage = VK_SHADER_STAGE_FRAGMENT_BIT; + shader_stages[1].pName = "main"; + vkCreateShaderModule(vk->context->device, + &module_info, NULL, &shader_stages[1].module); + + vkCreateGraphicsPipelines(vk->context->device, vk->pipelines.cache, + 1, &pipe, NULL, &vk->pipelines.hdr); + + /* Build display hdr pipelines. */ + for (i = 4; i < 6; i++) + { + input_assembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP; + blend_attachment.blendEnable = false; + vkCreateGraphicsPipelines(vk->context->device, vk->pipelines.cache, + 1, &pipe, NULL, &vk->display.pipelines[i]); + } + + vkDestroyShaderModule(vk->context->device, shader_stages[1].module, NULL); +#endif // VULKAN_HDR_SWAPCHAIN + + vkDestroyShaderModule(vk->context->device, shader_stages[0].module, NULL); + /* Other menu pipelines. */ - for (i = 0; i < ARRAY_SIZE(vk->display.pipelines) - 4; i++) + for (i = 0; i < ARRAY_SIZE(vk->display.pipelines) - 6; i++) { switch (i >> 1) { @@ -515,7 +554,7 @@ static void vulkan_init_pipelines(vk_t *vk) VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; vkCreateGraphicsPipelines(vk->context->device, vk->pipelines.cache, - 1, &pipe, NULL, &vk->display.pipelines[4 + i]); + 1, &pipe, NULL, &vk->display.pipelines[6 + i]); vkDestroyShaderModule(vk->context->device, shader_stages[0].module, NULL); vkDestroyShaderModule(vk->context->device, shader_stages[1].module, NULL); @@ -739,6 +778,10 @@ static void vulkan_deinit_pipelines(vk_t *vk) vk->pipelines.alpha_blend, NULL); vkDestroyPipeline(vk->context->device, vk->pipelines.font, NULL); +#ifdef VULKAN_HDR_SWAPCHAIN + vkDestroyPipeline(vk->context->device, + vk->pipelines.hdr, NULL); +#endif // VULKAN_HDR_SWAPCHAIN for (i = 0; i < ARRAY_SIZE(vk->display.pipelines); i++) vkDestroyPipeline(vk->context->device, @@ -766,6 +809,65 @@ static void vulkan_deinit_framebuffers(vk_t *vk) vkDestroyRenderPass(vk->context->device, vk->render_pass, NULL); } +#ifdef VULKAN_HDR_SWAPCHAIN +static void vulkan_set_hdr_max_nits(void* data, float max_nits) +{ + vk_t *vk = (vk_t*)data; + vulkan_hdr_uniform_t* mapped_ubo = (vulkan_hdr_uniform_t*)vk->hdr.ubo.mapped; + + vk->hdr.max_output_nits = max_nits; + mapped_ubo->max_nits = max_nits; + + //vulkan_set_hdr_metadata( + // vk->chain.handle, + // vk->hdr.support, + // vk->chain.bit_depth, + // vk->chain.color_space, + // vk->hdr.max_output_nits, + // vk->hdr.min_output_nits, + // vk->hdr.max_cll, + // vk->hdr.max_fall); +} + +static void vulkan_set_hdr_paper_white_nits(void* data, float paper_white_nits) +{ + vk_t *vk = (vk_t*)data; + vulkan_hdr_uniform_t* mapped_ubo = (vulkan_hdr_uniform_t*)vk->hdr.ubo.mapped; + + mapped_ubo->paper_white_nits = paper_white_nits; +} + +static void vulkan_set_hdr_contrast(void* data, float contrast) +{ + vk_t *vk = (vk_t*)data; + vulkan_hdr_uniform_t* mapped_ubo = (vulkan_hdr_uniform_t*)vk->hdr.ubo.mapped; + + mapped_ubo->contrast = contrast; +} + +static void vulkan_set_hdr_expand_gamut(void* data, bool expand_gamut) +{ + vk_t *vk = (vk_t*)data; + vulkan_hdr_uniform_t* mapped_ubo = (vulkan_hdr_uniform_t*)vk->hdr.ubo.mapped; + + mapped_ubo->expand_gamut = expand_gamut ? 1.0f : 0.0f; +} + +static void vulkan_set_hdr_inverse_tonemap(vk_t* vk, bool inverse_tonemap) +{ + vulkan_hdr_uniform_t* mapped_ubo = (vulkan_hdr_uniform_t*)vk->hdr.ubo.mapped; + + mapped_ubo->inverse_tonemap = inverse_tonemap ? 1.0f : 0.0f; +} + +static void vulkan_set_hdr10(vk_t* vk, bool hdr10) +{ + vulkan_hdr_uniform_t* mapped_ubo = (vulkan_hdr_uniform_t*)vk->hdr.ubo.mapped; + + mapped_ubo->hdr10 = hdr10 ? 1.0f : 0.0f; +} +#endif // VULKAN_HDR_SWAPCHAIN + static bool vulkan_init_default_filter_chain(vk_t *vk) { struct vulkan_filter_chain_create_info info; @@ -800,6 +902,33 @@ static bool vulkan_init_default_filter_chain(vk_t *vk) return false; } +#ifdef VULKAN_HDR_SWAPCHAIN + if (vk->context->hdr_enable) + { + struct video_shader* shader_preset = vulkan_filter_chain_get_preset(vk->filter_chain); + + if(shader_preset && shader_preset->passes && (vulkan_filter_chain_get_pass_rt_format(vk->filter_chain, shader_preset->passes - 1) == 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 */ + vulkan_set_hdr_inverse_tonemap(vk, false); + vulkan_set_hdr10(vk, false); + vk->should_resize = true; + } + else if(shader_preset && shader_preset->passes && (vulkan_filter_chain_get_pass_rt_format(vk->filter_chain, shader_preset->passes - 1) == VK_FORMAT_R16G16B16A16_SFLOAT)) + { + /* If the last shader pass uses a RGBA16 back buffer 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->should_resize = true; + } + else + { + vulkan_set_hdr_inverse_tonemap(vk, true); + vulkan_set_hdr10(vk, true); + } + } +#endif // VULKAN_HDR_SWAPCHAIN + return true; } @@ -834,6 +963,33 @@ static bool vulkan_init_filter_chain_preset(vk_t *vk, const char *shader_path) return false; } +#ifdef VULKAN_HDR_SWAPCHAIN + if (vk->context->hdr_enable) + { + struct video_shader* shader_preset = vulkan_filter_chain_get_preset(vk->filter_chain); + + if(shader_preset && shader_preset->passes && (vulkan_filter_chain_get_pass_rt_format(vk->filter_chain, shader_preset->passes - 1) == 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 */ + vulkan_set_hdr_inverse_tonemap(vk, false); + vulkan_set_hdr10(vk, false); + vk->should_resize = true; + } + else if(shader_preset && shader_preset->passes && (vulkan_filter_chain_get_pass_rt_format(vk->filter_chain, shader_preset->passes - 1) == VK_FORMAT_R16G16B16A16_SFLOAT)) + { + /* If the last shader pass uses a RGBA16 back buffer 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->should_resize = true; + } + else + { + vulkan_set_hdr_inverse_tonemap(vk, true); + vulkan_set_hdr10(vk, true); + } + } +#endif // VULKAN_HDR_SWAPCHAIN + return true; } @@ -983,6 +1139,10 @@ static void vulkan_free(void *data) if (vk->filter_chain) vulkan_filter_chain_free((vulkan_filter_chain_t*)vk->filter_chain); +#ifdef VULKAN_HDR_SWAPCHAIN + video_driver_unset_hdr_support(); +#endif // VULKAN_HDR_SWAPCHAIN + if (vk->ctx_driver && vk->ctx_driver->destroy) vk->ctx_driver->destroy(vk->ctx_data); video_context_driver_free(); @@ -1199,6 +1359,13 @@ static void *vulkan_init(const video_info_t *video, goto error; } +#ifdef VULKAN_HDR_SWAPCHAIN + vk->hdr.max_output_nits = settings->floats.video_hdr_max_nits; + vk->hdr.min_output_nits = 0.001f; + vk->hdr.max_cll = 0.0f; + vk->hdr.max_fall = 0.0f; +#endif // VULKAN_HDR_SWAPCHAIN + vk->video = *video; vk->ctx_driver = ctx_driver; @@ -1280,6 +1447,20 @@ static void *vulkan_init(const video_info_t *video, * the viewport sizes before we start running. */ vulkan_set_viewport(vk, temp_width, temp_height, false, true); +#ifdef VULKAN_HDR_SWAPCHAIN + vk->hdr.ubo = vulkan_create_buffer(vk->context, sizeof(vulkan_hdr_uniform_t), VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT); + + vulkan_hdr_uniform_t* mapped_ubo = (vulkan_hdr_uniform_t*)vk->hdr.ubo.mapped; + + mapped_ubo->mvp = vk->mvp_no_rot; + mapped_ubo->max_nits = settings->floats.video_hdr_max_nits; + mapped_ubo->paper_white_nits = settings->floats.video_hdr_paper_white_nits; + mapped_ubo->contrast = VIDEO_HDR_MAX_CONTRAST - settings->floats.video_hdr_display_contrast; + mapped_ubo->expand_gamut = settings->bools.video_hdr_expand_gamut; + mapped_ubo->inverse_tonemap = 1.0f; /* Use this to turn on/off the inverse tonemap */ + mapped_ubo->hdr10 = 1.0f; /* Use this to turn on/off the hdr10 */ +#endif // VULKAN_HDR_SWAPCHAIN + vulkan_init_hw_render(vk); vulkan_init_static_resources(vk); vulkan_init_resources(vk); @@ -1943,12 +2124,24 @@ static bool vulkan_frame(void *data, const void *frame, } else { - struct vk_texture *tex = &vk->swapchain[vk->last_valid_index].texture; - if (vk->swapchain[vk->last_valid_index].texture_optimal.memory - != VK_NULL_HANDLE) - tex = &vk->swapchain[vk->last_valid_index].texture_optimal; - else + struct vk_texture *tex = NULL; + +#ifdef VULKAN_HDR_SWAPCHIN + if(vk->context->hdr_enable) + { + tex = &vk->main_buffer.texture; vulkan_transition_texture(vk, vk->cmd, tex); + } + else +#endif // VULKAN_HDR_SWAPCHIN + { + tex = &vk->swapchain[vk->last_valid_index].texture; + if (vk->swapchain[vk->last_valid_index].texture_optimal.memory + != VK_NULL_HANDLE) + tex = &vk->swapchain[vk->last_valid_index].texture_optimal; + else + vulkan_transition_texture(vk, vk->cmd, tex); + } input.image = tex->image; input.view = tex->view; @@ -1994,6 +2187,13 @@ static bool vulkan_frame(void *data, const void *frame, } #endif +#ifdef VULKAN_HDR_SWAPCHAIN + if(vk->context->hdr_enable) + { + backbuffer = &vk->main_buffer; + } +#endif // VULKAN_HDR_SWAPCHAIN + /* Render to backbuffer. */ if ( (backbuffer->image != VK_NULL_HANDLE) && vk->context->has_acquired_swapchain) @@ -2097,6 +2297,151 @@ static bool vulkan_frame(void *data, const void *frame, /* End the render pass. We're done rendering to backbuffer now. */ vkCmdEndRenderPass(vk->cmd); + +#ifdef VULKAN_HDR_SWAPCHAIN + /* Copy over back buffer to swap chain render targets */ + if (vk->context->hdr_enable) + { + backbuffer = &vk->backbuffers[swapchain_index]; + + vulkan_hdr_uniform_t* mapped_ubo = (vulkan_hdr_uniform_t*)vk->hdr.ubo.mapped; + + mapped_ubo->mvp = vk->mvp_no_rot; + + rp_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; + rp_info.pNext = NULL; + rp_info.renderPass = vk->render_pass; + rp_info.framebuffer = backbuffer->framebuffer; + rp_info.renderArea.offset.x = 0; + rp_info.renderArea.offset.y = 0; + rp_info.renderArea.extent.width = vk->context->swapchain_width; + rp_info.renderArea.extent.height = vk->context->swapchain_height; + rp_info.clearValueCount = 1; + rp_info.pClearValues = &clear_color; + + clear_color.color.float32[0] = 0.0f; + clear_color.color.float32[1] = 0.0f; + clear_color.color.float32[2] = 0.0f; + clear_color.color.float32[3] = 0.0f; + + /* Prepare backbuffer for rendering. */ + VULKAN_IMAGE_LAYOUT_TRANSITION(vk->cmd, backbuffer->image, + VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + 0, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT); + + VULKAN_IMAGE_LAYOUT_TRANSITION(vk->cmd, vk->main_buffer.image, + VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, + VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, VK_ACCESS_SHADER_READ_BIT, + VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, + VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT); + + /* Begin render pass and set up viewport */ + vkCmdBeginRenderPass(vk->cmd, &rp_info, VK_SUBPASS_CONTENTS_INLINE); + + { + if (vk->pipelines.hdr != vk->tracker.pipeline) + { + vkCmdBindPipeline(vk->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, vk->pipelines.hdr); + + vk->tracker.pipeline = vk->pipelines.hdr; + /* Changing pipeline invalidates dynamic state. */ + vk->tracker.dirty |= VULKAN_DIRTY_DYNAMIC_BIT; + } + } + + { + VkDescriptorSet set; + + set = vulkan_descriptor_manager_alloc( + vk->context->device, + &vk->chain->descriptor_manager); + + vulkan_set_uniform_buffer(vk->context->device, + set, + 0, + vk->hdr.ubo.buffer, + 0, + vk->hdr.ubo.size); + + VkWriteDescriptorSet write; + VkDescriptorImageInfo image_info; + + image_info.sampler = vk->samplers.nearest; + image_info.imageView = vk->main_buffer.view; + image_info.imageLayout = VK_IMAGE_LAYOUT_GENERAL; + + write.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; + write.pNext = NULL; + write.dstSet = set; + write.dstBinding = 2; + write.dstArrayElement = 0; + write.descriptorCount = 1; + write.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; + write.pImageInfo = &image_info; + write.pBufferInfo = NULL; + write.pTexelBufferView = NULL; + + vkUpdateDescriptorSets(vk->context->device, 1, &write, 0, NULL); + + vkCmdBindDescriptorSets(vk->cmd, VK_PIPELINE_BIND_POINT_GRAPHICS, + vk->pipelines.layout, 0, + 1, &set, 0, NULL); + + vk->tracker.view = vk->main_buffer.view; + vk->tracker.sampler = vk->samplers.nearest; + } + + { + VkViewport viewport; + + viewport.x = 0.0f; + viewport.y = 0.0f; + viewport.width = vk->context->swapchain_width; + viewport.height = vk->context->swapchain_height; + + const VkRect2D scissor = { + { + (int32_t)viewport.x, + (int32_t)viewport.y + }, + { + (uint32_t)viewport.width, + (uint32_t)viewport.height + }, + }; + vkCmdSetViewport(vk->cmd, 0, 1, &viewport); + vkCmdSetScissor(vk->cmd, 0, 1, &scissor); + } + + /* Upload VBO */ + { + struct vk_buffer_range range; + + vulkan_buffer_chain_alloc(vk->context, &vk->chain->vbo, 6 * sizeof(struct vk_vertex), &range); + + { + struct vk_vertex *pv = (struct vk_vertex*)range.data; + struct vk_color color; + + color.r = 1.0f; + color.g = 1.0f; + color.b = 1.0f; + color.a = 1.0f; + + VULKAN_WRITE_QUAD_VBO(pv, 0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 0.0f, 1.0f, 1.0f, &color); + } + + vkCmdBindVertexBuffers(vk->cmd, 0, 1, + &range.buffer, &range.offset); + } + + vkCmdDraw(vk->cmd, 6, 1, 0, 0); + + vkCmdEndRenderPass(vk->cmd); + } +#endif // VULKAN_HDR_SWAPCHAIN } /* End the filter chain frame. @@ -2271,8 +2616,39 @@ static bool vulkan_frame(void *data, const void *frame, /* Handle spurious swapchain invalidations as soon as we can, * i.e. right after swap buffers. */ +#ifdef VULKAN_HDR_SWAPCHAIN + bool video_hdr_enable = video_info->hdr_enable; + if (vk->should_resize || (vk->context->hdr_enable != video_hdr_enable)) +#else if (vk->should_resize) +#endif // VULKAN_HDR_SWAPCHAIN { +#ifdef VULKAN_HDR_SWAPCHAIN + vk->context->hdr_enable = video_hdr_enable; + + if (vk->context->hdr_enable) + { +#ifdef HAVE_THREADS + slock_lock(vk->context->queue_lock); +#endif + vkQueueWaitIdle(vk->context->queue); +#ifdef HAVE_THREADS + slock_unlock(vk->context->queue_lock); +#endif + + struct vk_image* img = &vk->main_buffer; + + if (img->framebuffer) + vkDestroyFramebuffer(vk->context->device, img->framebuffer, NULL); + if (img->view) + vkDestroyImageView(vk->context->device, img->view, NULL); + if (img->image) + vkDestroyImage(vk->context->device, img->image, NULL); + if (img->memory) + vkFreeMemory(vk->context->device, img->memory, NULL); + } +#endif // VULKAN_HDR_SWAPCHAIN + gfx_ctx_mode_t mode; mode.width = width; mode.height = height; @@ -2280,6 +2656,96 @@ static bool vulkan_frame(void *data, const void *frame, if (vk->ctx_driver->set_resize) vk->ctx_driver->set_resize(vk->ctx_data, mode.width, mode.height); +#ifdef VULKAN_HDR_SWAPCHAIN + if (!(vk->hdr.support = vk->context->swapchain_colour_space == VK_COLOR_SPACE_HDR10_ST2084_EXT)) + vk->context->hdr_enable = false; + + if(vk->context->hdr_enable) + { + memset(&vk->main_buffer, 0, sizeof(vk->main_buffer)); + + struct video_shader* shader_preset = vulkan_filter_chain_get_preset(vk->filter_chain); + VkFormat format = shader_preset && shader_preset->passes ? vulkan_filter_chain_get_pass_rt_format(vk->filter_chain, shader_preset->passes - 1) : VK_FORMAT_R8G8B8A8_UNORM; + + { + /* Create the image */ + VkMemoryRequirements mem_reqs; + VkImageCreateInfo image_info = { VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO }; + VkMemoryAllocateInfo alloc = { VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO }; + + image_info.imageType = VK_IMAGE_TYPE_2D; + image_info.format = format; + image_info.extent.width = video_width; + image_info.extent.height = video_height; + image_info.extent.depth = 1; + image_info.mipLevels = 1; + image_info.arrayLayers = 1; + image_info.samples = VK_SAMPLE_COUNT_1_BIT; + image_info.tiling = VK_IMAGE_TILING_OPTIMAL; + image_info.usage = VK_IMAGE_USAGE_SAMPLED_BIT | + VK_IMAGE_USAGE_TRANSFER_SRC_BIT | + VK_IMAGE_USAGE_TRANSFER_DST_BIT; + image_info.initialLayout = VK_IMAGE_LAYOUT_GENERAL; /* VK_IMAGE_LAYOUT_UNDEFINED; */ + + vkCreateImage(vk->context->device, &image_info, NULL, &vk->main_buffer.image); + vkGetImageMemoryRequirements(vk->context->device, vk->main_buffer.image, &mem_reqs); + + alloc.allocationSize = mem_reqs.size; + alloc.memoryTypeIndex = vulkan_find_memory_type( + &vk->context->memory_properties, + mem_reqs.memoryTypeBits, + VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT); + + vkAllocateMemory(vk->context->device, &alloc, NULL, &vk->main_buffer.memory); + + vkBindImageMemory(vk->context->device, vk->main_buffer.image, vk->main_buffer.memory, 0); + } + + { + /* Create an image view which we can render into. */ + VkImageViewCreateInfo view = { VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO }; + + view.viewType = VK_IMAGE_VIEW_TYPE_2D; + view.format = format; + view.image = vk->main_buffer.image; + view.subresourceRange.baseMipLevel = 0; + view.subresourceRange.baseArrayLayer = 0; + view.subresourceRange.levelCount = 1; + view.subresourceRange.layerCount = 1; + view.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; + view.components.r = VK_COMPONENT_SWIZZLE_R; + view.components.g = VK_COMPONENT_SWIZZLE_G; + view.components.b = VK_COMPONENT_SWIZZLE_B; + view.components.a = VK_COMPONENT_SWIZZLE_A; + + vkCreateImageView(vk->context->device, &view, NULL, &vk->main_buffer.view); + } + + { + /* Create the framebuffer */ + VkFramebufferCreateInfo info = { VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO }; + + info.renderPass = vk->render_pass; + info.attachmentCount = 1; + info.pAttachments = &vk->main_buffer.view; + info.width = vk->context->swapchain_width; + info.height = vk->context->swapchain_height; + info.layers = 1; + + vkCreateFramebuffer(vk->context->device, &info, NULL, &vk->main_buffer.framebuffer); + } + } + + //vulkan_set_hdr_metadata( + // vk->hdr.support, + // vk->context->swapchain_format, + // vk->context->swapchain_color_space, + // vk->hdr.max_output_nits, + // vk->hdr.min_output_nits, + // vk->hdr.max_cll, + // vk->hdr.max_fall); +#endif // VULKAN_HDR_SWAPCHAIN + vk->should_resize = false; } @@ -2648,10 +3114,17 @@ static const video_poke_interface_t vulkan_poke_interface = { vulkan_get_current_shader, vulkan_get_current_sw_framebuffer, vulkan_get_hw_render_interface, +#ifdef VULKAN_HDR_SWAPCHAIN + vulkan_set_hdr_max_nits, + vulkan_set_hdr_paper_white_nits, + vulkan_set_hdr_contrast, + vulkan_set_hdr_expand_gamut +#else NULL, /* set_hdr_max_nits */ NULL, /* set_hdr_paper_white_nits */ NULL, /* set_hdr_contrast */ NULL /* set_hdr_expand_gamut */ +#endif // VULKAN_HDR_SWAPCHAIN }; static void vulkan_get_poke_interface(void *data, diff --git a/gfx/drivers/vulkan_shaders/hdr.frag b/gfx/drivers/vulkan_shaders/hdr.frag new file mode 100644 index 0000000000..95c9a74aec --- /dev/null +++ b/gfx/drivers/vulkan_shaders/hdr.frag @@ -0,0 +1,112 @@ +#version 310 es +precision highp float; +layout(location = 0) in vec2 vTexCoord; +layout(location = 0) out vec4 FragColor; +layout(set = 0, binding = 2) uniform highp sampler2D Source; + +layout(std140, set = 0, binding = 0) uniform UBO +{ + mat4 MVP; + float contrast; /* 2.0f; */ + float paper_white_nits; /* 200.0f; */ + float max_nits; /* 1000.0f; */ + float expand_gamut; /* 1.0f; */ + float inverse_tonemap; + float hdr10; +} global; + +/* Inverse Tonemap section */ +#define kMaxNitsFor2084 10000.0f +#define kEpsilon 0.0001f +#define kLumaChannelRatio 0.25f + +vec3 InverseTonemap(vec3 sdr) +{ + vec3 hdr; + + if(global.inverse_tonemap > 0.0f) + { + sdr = pow(abs(sdr), vec3(global.contrast / 2.2f)); /* Display Gamma - needs to be determined by calibration screen */ + + float luma = dot(sdr, vec3(0.2126, 0.7152, 0.0722)); /* Rec BT.709 luma coefficients - https://en.wikipedia.org/wiki/Luma_(video) */ + + /* Inverse reinhard tonemap */ + float maxValue = (global.max_nits / global.paper_white_nits) + kEpsilon; + float elbow = maxValue / (maxValue - 1.0f); + float offset = 1.0f - ((0.5f * elbow) / (elbow - 0.5f)); + + float hdrLumaInvTonemap = offset + ((luma * elbow) / (elbow - luma)); + float sdrLumaInvTonemap = luma / ((1.0f + kEpsilon) - luma); /* Convert the srd < 0.5 to 0.0 -> 1.0 range */ + + float lumaInvTonemap = (luma > 0.5f) ? hdrLumaInvTonemap : sdrLumaInvTonemap; + vec3 perLuma = sdr / (luma + kEpsilon) * lumaInvTonemap; + + vec3 hdrInvTonemap = offset + ((sdr * elbow) / (elbow - sdr)); + vec3 sdrInvTonemap = sdr / ((1.0f + kEpsilon) - sdr); /* Convert the srd < 0.5 to 0.0 -> 1.0 range */ + + vec3 perChannel = vec3(sdr.x > 0.5f ? hdrInvTonemap.x : sdrInvTonemap.x, + sdr.y > 0.5f ? hdrInvTonemap.y : sdrInvTonemap.y, + sdr.z > 0.5f ? hdrInvTonemap.z : sdrInvTonemap.z); + + hdr = mix(perLuma, perChannel, vec3(kLumaChannelRatio)); + } + else + { + hdr = sdr; + } + + return hdr; +} + +/* HDR10 section */ +#define kMaxNitsFor2084 10000.0f + +const mat3 k709to2020 = mat3 ( + 0.6274040f, 0.3292820f, 0.0433136f, + 0.0690970f, 0.9195400f, 0.0113612f, + 0.0163916f, 0.0880132f, 0.8955950f); + +/* START Converted from (Copyright (c) Microsoft Corporation - Licensed under the MIT License.) https://github.com/microsoft/Xbox-ATG-Samples/tree/master/Kits/ATGTK/HDR */ +const mat3 kExpanded709to2020 = mat3 ( + 0.6274040f, 0.3292820f, 0.0433136f, + 0.0457456, 0.941777, 0.0124772, + -0.00121055, 0.0176041, 0.983607); + +vec3 LinearToST2084(vec3 normalizedLinearValue) +{ + vec3 ST2084 = pow((0.8359375f + 18.8515625f * pow(abs(normalizedLinearValue), vec3(0.1593017578f))) / (1.0f + 18.6875f * pow(abs(normalizedLinearValue), vec3(0.1593017578f))), vec3(78.84375f)); + return ST2084; /* Don't clamp between [0..1], so we can still perform operations on scene values higher than 10,000 nits */ +} +/* END Converted from (Copyright (c) Microsoft Corporation - Licensed under the MIT License.) https://github.com/microsoft/Xbox-ATG-Samples/tree/master/Kits/ATGTK/HDR */ + +vec3 Hdr10(vec3 hdr) +{ + vec3 hdr10; + + if(global.hdr10 > 0.0f) + { + /* Now convert into HDR10 */ + vec3 rec2020 = hdr * k709to2020; + + if(global.expand_gamut > 0.0f) + { + rec2020 = hdr * kExpanded709to2020; + } + + vec3 linearColour = rec2020 * (global.paper_white_nits / kMaxNitsFor2084); + hdr10 = LinearToST2084(linearColour); + } + else + { + hdr10 = hdr; + } + + return hdr10; +} + +void main() +{ + vec4 sdr = texture(Source, vTexCoord); + vec4 hdr = vec4(InverseTonemap(sdr.rgb), sdr.a); + FragColor = vec4(Hdr10(hdr.rgb), hdr.a); +} diff --git a/gfx/drivers/vulkan_shaders/hdr.frag.inc b/gfx/drivers/vulkan_shaders/hdr.frag.inc new file mode 100644 index 0000000000..c3f6f2d695 --- /dev/null +++ b/gfx/drivers/vulkan_shaders/hdr.frag.inc @@ -0,0 +1,434 @@ +{0x07230203,0x00010000,0x000d000a,0x00000125, +0x00000000,0x00020011,0x00000001,0x0006000b, +0x00000001,0x4c534c47,0x6474732e,0x3035342e, +0x00000000,0x0003000e,0x00000000,0x00000001, +0x0007000f,0x00000004,0x00000004,0x6e69616d, +0x00000000,0x0000010a,0x0000011a,0x00030010, +0x00000004,0x00000007,0x00030003,0x00000001, +0x00000136,0x000a0004,0x475f4c47,0x4c474f4f, +0x70635f45,0x74735f70,0x5f656c79,0x656e696c, +0x7269645f,0x69746365,0x00006576,0x00080004, +0x475f4c47,0x4c474f4f,0x6e695f45,0x64756c63, +0x69645f65,0x74636572,0x00657669,0x00040005, +0x00000004,0x6e69616d,0x00000000,0x00070005, +0x0000000b,0x65766e49,0x54657372,0x6d656e6f, +0x76287061,0x003b3366,0x00030005,0x0000000a, +0x00726473,0x00070005,0x0000000e,0x656e694c, +0x6f547261,0x30325453,0x76283438,0x003b3366, +0x00080005,0x0000000d,0x6d726f6e,0x7a696c61, +0x694c6465,0x7261656e,0x756c6156,0x00000065, +0x00050005,0x00000011,0x31726448,0x66762830, +0x00003b33,0x00030005,0x00000010,0x00726468, +0x00030005,0x00000015,0x004f4255,0x00040006, +0x00000015,0x00000000,0x0050564d,0x00060006, +0x00000015,0x00000001,0x746e6f63,0x74736172, +0x00000000,0x00080006,0x00000015,0x00000002, +0x65706170,0x68775f72,0x5f657469,0x7374696e, +0x00000000,0x00060006,0x00000015,0x00000003, +0x5f78616d,0x7374696e,0x00000000,0x00070006, +0x00000015,0x00000004,0x61707865,0x675f646e, +0x74756d61,0x00000000,0x00070006,0x00000015, +0x00000005,0x65766e69,0x5f657372,0x656e6f74, +0x0070616d,0x00050006,0x00000015,0x00000006, +0x31726468,0x00000030,0x00040005,0x00000017, +0x626f6c67,0x00006c61,0x00040005,0x0000002c, +0x616d756c,0x00000000,0x00050005,0x00000033, +0x5678616d,0x65756c61,0x00000000,0x00040005, +0x0000003d,0x6f626c65,0x00000077,0x00040005, +0x00000043,0x7366666f,0x00007465,0x00070005, +0x0000004b,0x4c726468,0x49616d75,0x6f54766e, +0x616d656e,0x00000070,0x00070005,0x00000055, +0x4c726473,0x49616d75,0x6f54766e,0x616d656e, +0x00000070,0x00060005,0x0000005b,0x616d756c, +0x54766e49,0x6d656e6f,0x00007061,0x00040005, +0x00000061,0x4c726570,0x00616d75,0x00060005, +0x00000069,0x49726468,0x6f54766e,0x616d656e, +0x00000070,0x00060005,0x00000075,0x49726473, +0x6f54766e,0x616d656e,0x00000070,0x00050005, +0x0000007b,0x43726570,0x6e6e6168,0x00006c65, +0x00030005,0x000000a5,0x00726468,0x00040005, +0x000000b0,0x30325453,0x00003438,0x00040005, +0x000000cf,0x32636572,0x00303230,0x00060005, +0x000000f1,0x656e696c,0x6f437261,0x72756f6c, +0x00000000,0x00040005,0x000000f8,0x31726468, +0x00000030,0x00040005,0x000000f9,0x61726170, +0x0000006d,0x00030005,0x00000102,0x00726473, +0x00040005,0x00000106,0x72756f53,0x00006563, +0x00050005,0x0000010a,0x78655476,0x726f6f43, +0x00000064,0x00030005,0x0000010d,0x00726468, +0x00040005,0x0000010e,0x61726170,0x0000006d, +0x00050005,0x0000011a,0x67617246,0x6f6c6f43, +0x00000072,0x00040005,0x0000011b,0x61726170, +0x0000006d,0x00040048,0x00000015,0x00000000, +0x00000005,0x00050048,0x00000015,0x00000000, +0x00000023,0x00000000,0x00050048,0x00000015, +0x00000000,0x00000007,0x00000010,0x00050048, +0x00000015,0x00000001,0x00000023,0x00000040, +0x00050048,0x00000015,0x00000002,0x00000023, +0x00000044,0x00050048,0x00000015,0x00000003, +0x00000023,0x00000048,0x00050048,0x00000015, +0x00000004,0x00000023,0x0000004c,0x00050048, +0x00000015,0x00000005,0x00000023,0x00000050, +0x00050048,0x00000015,0x00000006,0x00000023, +0x00000054,0x00030047,0x00000015,0x00000002, +0x00040047,0x00000017,0x00000022,0x00000000, +0x00040047,0x00000017,0x00000021,0x00000000, +0x00040047,0x00000106,0x00000022,0x00000000, +0x00040047,0x00000106,0x00000021,0x00000002, +0x00040047,0x0000010a,0x0000001e,0x00000000, +0x00040047,0x0000011a,0x0000001e,0x00000000, +0x00020013,0x00000002,0x00030021,0x00000003, +0x00000002,0x00030016,0x00000006,0x00000020, +0x00040017,0x00000007,0x00000006,0x00000003, +0x00040020,0x00000008,0x00000007,0x00000007, +0x00040021,0x00000009,0x00000007,0x00000008, +0x00040017,0x00000013,0x00000006,0x00000004, +0x00040018,0x00000014,0x00000013,0x00000004, +0x0009001e,0x00000015,0x00000014,0x00000006, +0x00000006,0x00000006,0x00000006,0x00000006, +0x00000006,0x00040020,0x00000016,0x00000002, +0x00000015,0x0004003b,0x00000016,0x00000017, +0x00000002,0x00040015,0x00000018,0x00000020, +0x00000001,0x0004002b,0x00000018,0x00000019, +0x00000005,0x00040020,0x0000001a,0x00000002, +0x00000006,0x0004002b,0x00000006,0x0000001d, +0x00000000,0x00020014,0x0000001e,0x0004002b, +0x00000018,0x00000024,0x00000001,0x0004002b, +0x00000006,0x00000027,0x400ccccd,0x00040020, +0x0000002b,0x00000007,0x00000006,0x0004002b, +0x00000006,0x0000002e,0x3e59b3d0,0x0004002b, +0x00000006,0x0000002f,0x3f371759,0x0004002b, +0x00000006,0x00000030,0x3d93dd98,0x0006002c, +0x00000007,0x00000031,0x0000002e,0x0000002f, +0x00000030,0x0004002b,0x00000018,0x00000034, +0x00000003,0x0004002b,0x00000018,0x00000037, +0x00000002,0x0004002b,0x00000006,0x0000003b, +0x38d1b717,0x0004002b,0x00000006,0x00000040, +0x3f800000,0x0004002b,0x00000006,0x00000044, +0x3f000000,0x0004002b,0x00000006,0x00000057, +0x3f800347,0x00040015,0x0000007c,0x00000020, +0x00000000,0x0004002b,0x0000007c,0x0000007d, +0x00000000,0x0004002b,0x0000007c,0x0000008a, +0x00000001,0x0004002b,0x0000007c,0x00000097, +0x00000002,0x0004002b,0x00000006,0x000000a8, +0x3e800000,0x0006002c,0x00000007,0x000000a9, +0x000000a8,0x000000a8,0x000000a8,0x0004002b, +0x00000006,0x000000b1,0x3f560000,0x0004002b, +0x00000006,0x000000b2,0x4196d000,0x0004002b, +0x00000006,0x000000b5,0x3e232000,0x0006002c, +0x00000007,0x000000b6,0x000000b5,0x000000b5, +0x000000b5,0x0004002b,0x00000006,0x000000bb, +0x41958000,0x0004002b,0x00000006,0x000000c3, +0x429db000,0x0006002c,0x00000007,0x000000c4, +0x000000c3,0x000000c3,0x000000c3,0x0004002b, +0x00000018,0x000000c9,0x00000006,0x00040018, +0x000000d1,0x00000007,0x00000003,0x0004002b, +0x00000006,0x000000d2,0x3f209d8c,0x0004002b, +0x00000006,0x000000d3,0x3ea897a6,0x0004002b, +0x00000006,0x000000d4,0x3d31699a,0x0006002c, +0x00000007,0x000000d5,0x000000d2,0x000000d3, +0x000000d4,0x0004002b,0x00000006,0x000000d6, +0x3d8d82ba,0x0004002b,0x00000006,0x000000d7, +0x3f6b66f9,0x0004002b,0x00000006,0x000000d8, +0x3c3a2454,0x0006002c,0x00000007,0x000000d9, +0x000000d6,0x000000d7,0x000000d8,0x0004002b, +0x00000006,0x000000da,0x3c8647ad,0x0004002b, +0x00000006,0x000000db,0x3db44044,0x0004002b, +0x00000006,0x000000dc,0x3f6545b7,0x0006002c, +0x00000007,0x000000dd,0x000000da,0x000000db, +0x000000dc,0x0006002c,0x000000d1,0x000000de, +0x000000d5,0x000000d9,0x000000dd,0x0004002b, +0x00000018,0x000000e0,0x00000004,0x0004002b, +0x00000006,0x000000e7,0x3d3b5fbd,0x0004002b, +0x00000006,0x000000e8,0x3f71184c,0x0004002b, +0x00000006,0x000000e9,0x3c4c6d2b,0x0006002c, +0x00000007,0x000000ea,0x000000e7,0x000000e8, +0x000000e9,0x0004002b,0x00000006,0x000000eb, +0xba9eab51,0x0004002b,0x00000006,0x000000ec, +0x3c903679,0x0004002b,0x00000006,0x000000ed, +0x3f7bcdab,0x0006002c,0x00000007,0x000000ee, +0x000000eb,0x000000ec,0x000000ed,0x0006002c, +0x000000d1,0x000000ef,0x000000d5,0x000000ea, +0x000000ee,0x0004002b,0x00000006,0x000000f5, +0x461c4000,0x00040020,0x00000101,0x00000007, +0x00000013,0x00090019,0x00000103,0x00000006, +0x00000001,0x00000000,0x00000000,0x00000000, +0x00000001,0x00000000,0x0003001b,0x00000104, +0x00000103,0x00040020,0x00000105,0x00000000, +0x00000104,0x0004003b,0x00000105,0x00000106, +0x00000000,0x00040017,0x00000108,0x00000006, +0x00000002,0x00040020,0x00000109,0x00000001, +0x00000108,0x0004003b,0x00000109,0x0000010a, +0x00000001,0x0004002b,0x0000007c,0x00000112, +0x00000003,0x00040020,0x00000119,0x00000003, +0x00000013,0x0004003b,0x00000119,0x0000011a, +0x00000003,0x00050036,0x00000002,0x00000004, +0x00000000,0x00000003,0x000200f8,0x00000005, +0x0004003b,0x00000101,0x00000102,0x00000007, +0x0004003b,0x00000101,0x0000010d,0x00000007, +0x0004003b,0x00000008,0x0000010e,0x00000007, +0x0004003b,0x00000008,0x0000011b,0x00000007, +0x0004003d,0x00000104,0x00000107,0x00000106, +0x0004003d,0x00000108,0x0000010b,0x0000010a, +0x00050057,0x00000013,0x0000010c,0x00000107, +0x0000010b,0x0003003e,0x00000102,0x0000010c, +0x0004003d,0x00000013,0x0000010f,0x00000102, +0x0008004f,0x00000007,0x00000110,0x0000010f, +0x0000010f,0x00000000,0x00000001,0x00000002, +0x0003003e,0x0000010e,0x00000110,0x00050039, +0x00000007,0x00000111,0x0000000b,0x0000010e, +0x00050041,0x0000002b,0x00000113,0x00000102, +0x00000112,0x0004003d,0x00000006,0x00000114, +0x00000113,0x00050051,0x00000006,0x00000115, +0x00000111,0x00000000,0x00050051,0x00000006, +0x00000116,0x00000111,0x00000001,0x00050051, +0x00000006,0x00000117,0x00000111,0x00000002, +0x00070050,0x00000013,0x00000118,0x00000115, +0x00000116,0x00000117,0x00000114,0x0003003e, +0x0000010d,0x00000118,0x0004003d,0x00000013, +0x0000011c,0x0000010d,0x0008004f,0x00000007, +0x0000011d,0x0000011c,0x0000011c,0x00000000, +0x00000001,0x00000002,0x0003003e,0x0000011b, +0x0000011d,0x00050039,0x00000007,0x0000011e, +0x00000011,0x0000011b,0x00050041,0x0000002b, +0x0000011f,0x0000010d,0x00000112,0x0004003d, +0x00000006,0x00000120,0x0000011f,0x00050051, +0x00000006,0x00000121,0x0000011e,0x00000000, +0x00050051,0x00000006,0x00000122,0x0000011e, +0x00000001,0x00050051,0x00000006,0x00000123, +0x0000011e,0x00000002,0x00070050,0x00000013, +0x00000124,0x00000121,0x00000122,0x00000123, +0x00000120,0x0003003e,0x0000011a,0x00000124, +0x000100fd,0x00010038,0x00050036,0x00000007, +0x0000000b,0x00000000,0x00000009,0x00030037, +0x00000008,0x0000000a,0x000200f8,0x0000000c, +0x0004003b,0x0000002b,0x0000002c,0x00000007, +0x0004003b,0x0000002b,0x00000033,0x00000007, +0x0004003b,0x0000002b,0x0000003d,0x00000007, +0x0004003b,0x0000002b,0x00000043,0x00000007, +0x0004003b,0x0000002b,0x0000004b,0x00000007, +0x0004003b,0x0000002b,0x00000055,0x00000007, +0x0004003b,0x0000002b,0x0000005b,0x00000007, +0x0004003b,0x00000008,0x00000061,0x00000007, +0x0004003b,0x00000008,0x00000069,0x00000007, +0x0004003b,0x00000008,0x00000075,0x00000007, +0x0004003b,0x00000008,0x0000007b,0x00000007, +0x0004003b,0x0000002b,0x00000081,0x00000007, +0x0004003b,0x0000002b,0x0000008e,0x00000007, +0x0004003b,0x0000002b,0x0000009b,0x00000007, +0x0004003b,0x00000008,0x000000a5,0x00000007, +0x00050041,0x0000001a,0x0000001b,0x00000017, +0x00000019,0x0004003d,0x00000006,0x0000001c, +0x0000001b,0x000500ba,0x0000001e,0x0000001f, +0x0000001c,0x0000001d,0x000300f7,0x00000021, +0x00000000,0x000400fa,0x0000001f,0x00000020, +0x000000ab,0x000200f8,0x00000020,0x0004003d, +0x00000007,0x00000022,0x0000000a,0x0006000c, +0x00000007,0x00000023,0x00000001,0x00000004, +0x00000022,0x00050041,0x0000001a,0x00000025, +0x00000017,0x00000024,0x0004003d,0x00000006, +0x00000026,0x00000025,0x00050088,0x00000006, +0x00000028,0x00000026,0x00000027,0x00060050, +0x00000007,0x00000029,0x00000028,0x00000028, +0x00000028,0x0007000c,0x00000007,0x0000002a, +0x00000001,0x0000001a,0x00000023,0x00000029, +0x0003003e,0x0000000a,0x0000002a,0x0004003d, +0x00000007,0x0000002d,0x0000000a,0x00050094, +0x00000006,0x00000032,0x0000002d,0x00000031, +0x0003003e,0x0000002c,0x00000032,0x00050041, +0x0000001a,0x00000035,0x00000017,0x00000034, +0x0004003d,0x00000006,0x00000036,0x00000035, +0x00050041,0x0000001a,0x00000038,0x00000017, +0x00000037,0x0004003d,0x00000006,0x00000039, +0x00000038,0x00050088,0x00000006,0x0000003a, +0x00000036,0x00000039,0x00050081,0x00000006, +0x0000003c,0x0000003a,0x0000003b,0x0003003e, +0x00000033,0x0000003c,0x0004003d,0x00000006, +0x0000003e,0x00000033,0x0004003d,0x00000006, +0x0000003f,0x00000033,0x00050083,0x00000006, +0x00000041,0x0000003f,0x00000040,0x00050088, +0x00000006,0x00000042,0x0000003e,0x00000041, +0x0003003e,0x0000003d,0x00000042,0x0004003d, +0x00000006,0x00000045,0x0000003d,0x00050085, +0x00000006,0x00000046,0x00000044,0x00000045, +0x0004003d,0x00000006,0x00000047,0x0000003d, +0x00050083,0x00000006,0x00000048,0x00000047, +0x00000044,0x00050088,0x00000006,0x00000049, +0x00000046,0x00000048,0x00050083,0x00000006, +0x0000004a,0x00000040,0x00000049,0x0003003e, +0x00000043,0x0000004a,0x0004003d,0x00000006, +0x0000004c,0x00000043,0x0004003d,0x00000006, +0x0000004d,0x0000002c,0x0004003d,0x00000006, +0x0000004e,0x0000003d,0x00050085,0x00000006, +0x0000004f,0x0000004d,0x0000004e,0x0004003d, +0x00000006,0x00000050,0x0000003d,0x0004003d, +0x00000006,0x00000051,0x0000002c,0x00050083, +0x00000006,0x00000052,0x00000050,0x00000051, +0x00050088,0x00000006,0x00000053,0x0000004f, +0x00000052,0x00050081,0x00000006,0x00000054, +0x0000004c,0x00000053,0x0003003e,0x0000004b, +0x00000054,0x0004003d,0x00000006,0x00000056, +0x0000002c,0x0004003d,0x00000006,0x00000058, +0x0000002c,0x00050083,0x00000006,0x00000059, +0x00000057,0x00000058,0x00050088,0x00000006, +0x0000005a,0x00000056,0x00000059,0x0003003e, +0x00000055,0x0000005a,0x0004003d,0x00000006, +0x0000005c,0x0000002c,0x000500ba,0x0000001e, +0x0000005d,0x0000005c,0x00000044,0x0004003d, +0x00000006,0x0000005e,0x0000004b,0x0004003d, +0x00000006,0x0000005f,0x00000055,0x000600a9, +0x00000006,0x00000060,0x0000005d,0x0000005e, +0x0000005f,0x0003003e,0x0000005b,0x00000060, +0x0004003d,0x00000007,0x00000062,0x0000000a, +0x0004003d,0x00000006,0x00000063,0x0000002c, +0x00050081,0x00000006,0x00000064,0x00000063, +0x0000003b,0x00060050,0x00000007,0x00000065, +0x00000064,0x00000064,0x00000064,0x00050088, +0x00000007,0x00000066,0x00000062,0x00000065, +0x0004003d,0x00000006,0x00000067,0x0000005b, +0x0005008e,0x00000007,0x00000068,0x00000066, +0x00000067,0x0003003e,0x00000061,0x00000068, +0x0004003d,0x00000006,0x0000006a,0x00000043, +0x0004003d,0x00000007,0x0000006b,0x0000000a, +0x0004003d,0x00000006,0x0000006c,0x0000003d, +0x0005008e,0x00000007,0x0000006d,0x0000006b, +0x0000006c,0x0004003d,0x00000006,0x0000006e, +0x0000003d,0x0004003d,0x00000007,0x0000006f, +0x0000000a,0x00060050,0x00000007,0x00000070, +0x0000006e,0x0000006e,0x0000006e,0x00050083, +0x00000007,0x00000071,0x00000070,0x0000006f, +0x00050088,0x00000007,0x00000072,0x0000006d, +0x00000071,0x00060050,0x00000007,0x00000073, +0x0000006a,0x0000006a,0x0000006a,0x00050081, +0x00000007,0x00000074,0x00000073,0x00000072, +0x0003003e,0x00000069,0x00000074,0x0004003d, +0x00000007,0x00000076,0x0000000a,0x0004003d, +0x00000007,0x00000077,0x0000000a,0x00060050, +0x00000007,0x00000078,0x00000057,0x00000057, +0x00000057,0x00050083,0x00000007,0x00000079, +0x00000078,0x00000077,0x00050088,0x00000007, +0x0000007a,0x00000076,0x00000079,0x0003003e, +0x00000075,0x0000007a,0x00050041,0x0000002b, +0x0000007e,0x0000000a,0x0000007d,0x0004003d, +0x00000006,0x0000007f,0x0000007e,0x000500ba, +0x0000001e,0x00000080,0x0000007f,0x00000044, +0x000300f7,0x00000083,0x00000000,0x000400fa, +0x00000080,0x00000082,0x00000086,0x000200f8, +0x00000082,0x00050041,0x0000002b,0x00000084, +0x00000069,0x0000007d,0x0004003d,0x00000006, +0x00000085,0x00000084,0x0003003e,0x00000081, +0x00000085,0x000200f9,0x00000083,0x000200f8, +0x00000086,0x00050041,0x0000002b,0x00000087, +0x00000075,0x0000007d,0x0004003d,0x00000006, +0x00000088,0x00000087,0x0003003e,0x00000081, +0x00000088,0x000200f9,0x00000083,0x000200f8, +0x00000083,0x0004003d,0x00000006,0x00000089, +0x00000081,0x00050041,0x0000002b,0x0000008b, +0x0000000a,0x0000008a,0x0004003d,0x00000006, +0x0000008c,0x0000008b,0x000500ba,0x0000001e, +0x0000008d,0x0000008c,0x00000044,0x000300f7, +0x00000090,0x00000000,0x000400fa,0x0000008d, +0x0000008f,0x00000093,0x000200f8,0x0000008f, +0x00050041,0x0000002b,0x00000091,0x00000069, +0x0000008a,0x0004003d,0x00000006,0x00000092, +0x00000091,0x0003003e,0x0000008e,0x00000092, +0x000200f9,0x00000090,0x000200f8,0x00000093, +0x00050041,0x0000002b,0x00000094,0x00000075, +0x0000008a,0x0004003d,0x00000006,0x00000095, +0x00000094,0x0003003e,0x0000008e,0x00000095, +0x000200f9,0x00000090,0x000200f8,0x00000090, +0x0004003d,0x00000006,0x00000096,0x0000008e, +0x00050041,0x0000002b,0x00000098,0x0000000a, +0x00000097,0x0004003d,0x00000006,0x00000099, +0x00000098,0x000500ba,0x0000001e,0x0000009a, +0x00000099,0x00000044,0x000300f7,0x0000009d, +0x00000000,0x000400fa,0x0000009a,0x0000009c, +0x000000a0,0x000200f8,0x0000009c,0x00050041, +0x0000002b,0x0000009e,0x00000069,0x00000097, +0x0004003d,0x00000006,0x0000009f,0x0000009e, +0x0003003e,0x0000009b,0x0000009f,0x000200f9, +0x0000009d,0x000200f8,0x000000a0,0x00050041, +0x0000002b,0x000000a1,0x00000075,0x00000097, +0x0004003d,0x00000006,0x000000a2,0x000000a1, +0x0003003e,0x0000009b,0x000000a2,0x000200f9, +0x0000009d,0x000200f8,0x0000009d,0x0004003d, +0x00000006,0x000000a3,0x0000009b,0x00060050, +0x00000007,0x000000a4,0x00000089,0x00000096, +0x000000a3,0x0003003e,0x0000007b,0x000000a4, +0x0004003d,0x00000007,0x000000a6,0x00000061, +0x0004003d,0x00000007,0x000000a7,0x0000007b, +0x0008000c,0x00000007,0x000000aa,0x00000001, +0x0000002e,0x000000a6,0x000000a7,0x000000a9, +0x0003003e,0x000000a5,0x000000aa,0x000200f9, +0x00000021,0x000200f8,0x000000ab,0x0004003d, +0x00000007,0x000000ac,0x0000000a,0x0003003e, +0x000000a5,0x000000ac,0x000200f9,0x00000021, +0x000200f8,0x00000021,0x0004003d,0x00000007, +0x000000ad,0x000000a5,0x000200fe,0x000000ad, +0x00010038,0x00050036,0x00000007,0x0000000e, +0x00000000,0x00000009,0x00030037,0x00000008, +0x0000000d,0x000200f8,0x0000000f,0x0004003b, +0x00000008,0x000000b0,0x00000007,0x0004003d, +0x00000007,0x000000b3,0x0000000d,0x0006000c, +0x00000007,0x000000b4,0x00000001,0x00000004, +0x000000b3,0x0007000c,0x00000007,0x000000b7, +0x00000001,0x0000001a,0x000000b4,0x000000b6, +0x0005008e,0x00000007,0x000000b8,0x000000b7, +0x000000b2,0x00060050,0x00000007,0x000000b9, +0x000000b1,0x000000b1,0x000000b1,0x00050081, +0x00000007,0x000000ba,0x000000b9,0x000000b8, +0x0004003d,0x00000007,0x000000bc,0x0000000d, +0x0006000c,0x00000007,0x000000bd,0x00000001, +0x00000004,0x000000bc,0x0007000c,0x00000007, +0x000000be,0x00000001,0x0000001a,0x000000bd, +0x000000b6,0x0005008e,0x00000007,0x000000bf, +0x000000be,0x000000bb,0x00060050,0x00000007, +0x000000c0,0x00000040,0x00000040,0x00000040, +0x00050081,0x00000007,0x000000c1,0x000000c0, +0x000000bf,0x00050088,0x00000007,0x000000c2, +0x000000ba,0x000000c1,0x0007000c,0x00000007, +0x000000c5,0x00000001,0x0000001a,0x000000c2, +0x000000c4,0x0003003e,0x000000b0,0x000000c5, +0x0004003d,0x00000007,0x000000c6,0x000000b0, +0x000200fe,0x000000c6,0x00010038,0x00050036, +0x00000007,0x00000011,0x00000000,0x00000009, +0x00030037,0x00000008,0x00000010,0x000200f8, +0x00000012,0x0004003b,0x00000008,0x000000cf, +0x00000007,0x0004003b,0x00000008,0x000000f1, +0x00000007,0x0004003b,0x00000008,0x000000f8, +0x00000007,0x0004003b,0x00000008,0x000000f9, +0x00000007,0x00050041,0x0000001a,0x000000ca, +0x00000017,0x000000c9,0x0004003d,0x00000006, +0x000000cb,0x000000ca,0x000500ba,0x0000001e, +0x000000cc,0x000000cb,0x0000001d,0x000300f7, +0x000000ce,0x00000000,0x000400fa,0x000000cc, +0x000000cd,0x000000fc,0x000200f8,0x000000cd, +0x0004003d,0x00000007,0x000000d0,0x00000010, +0x00050090,0x00000007,0x000000df,0x000000d0, +0x000000de,0x0003003e,0x000000cf,0x000000df, +0x00050041,0x0000001a,0x000000e1,0x00000017, +0x000000e0,0x0004003d,0x00000006,0x000000e2, +0x000000e1,0x000500ba,0x0000001e,0x000000e3, +0x000000e2,0x0000001d,0x000300f7,0x000000e5, +0x00000000,0x000400fa,0x000000e3,0x000000e4, +0x000000e5,0x000200f8,0x000000e4,0x0004003d, +0x00000007,0x000000e6,0x00000010,0x00050090, +0x00000007,0x000000f0,0x000000e6,0x000000ef, +0x0003003e,0x000000cf,0x000000f0,0x000200f9, +0x000000e5,0x000200f8,0x000000e5,0x0004003d, +0x00000007,0x000000f2,0x000000cf,0x00050041, +0x0000001a,0x000000f3,0x00000017,0x00000037, +0x0004003d,0x00000006,0x000000f4,0x000000f3, +0x00050088,0x00000006,0x000000f6,0x000000f4, +0x000000f5,0x0005008e,0x00000007,0x000000f7, +0x000000f2,0x000000f6,0x0003003e,0x000000f1, +0x000000f7,0x0004003d,0x00000007,0x000000fa, +0x000000f1,0x0003003e,0x000000f9,0x000000fa, +0x00050039,0x00000007,0x000000fb,0x0000000e, +0x000000f9,0x0003003e,0x000000f8,0x000000fb, +0x000200f9,0x000000ce,0x000200f8,0x000000fc, +0x0004003d,0x00000007,0x000000fd,0x00000010, +0x0003003e,0x000000f8,0x000000fd,0x000200f9, +0x000000ce,0x000200f8,0x000000ce,0x0004003d, +0x00000007,0x000000fe,0x000000f8,0x000200fe, +0x000000fe,0x00010038} diff --git a/gfx/drivers_shader/shader_vulkan.cpp b/gfx/drivers_shader/shader_vulkan.cpp index 0337892cf8..e0fdcc6acf 100644 --- a/gfx/drivers_shader/shader_vulkan.cpp +++ b/gfx/drivers_shader/shader_vulkan.cpp @@ -395,6 +395,8 @@ struct vulkan_filter_chain void add_parameter(unsigned pass, unsigned parameter_index, const std::string &id); void release_staging_buffers(); + VkFormat get_pass_rt_format(unsigned pass); + private: VkDevice device; VkPhysicalDevice gpu; @@ -1196,6 +1198,11 @@ void vulkan_filter_chain::set_pass_info(unsigned pass, pass_info[pass] = info; } + VkFormat vulkan_filter_chain::get_pass_rt_format(unsigned pass) + { + return pass_info[pass].rt_format; + } + void vulkan_filter_chain::set_num_passes(unsigned num_passes) { unsigned i; @@ -2726,11 +2733,23 @@ vulkan_filter_chain_t *vulkan_filter_chain_create_from_preset( { pass_info.scale_type_x = GLSLANG_FILTER_CHAIN_SCALE_VIEWPORT; pass_info.scale_type_y = GLSLANG_FILTER_CHAIN_SCALE_VIEWPORT; - pass_info.rt_format = tmpinfo.swapchain.format; +#ifdef VULKAN_HDR_SWAPCHAIN + if (tmpinfo.swapchain.format == VK_FORMAT_A2B10G10R10_UNORM_PACK32) + { + pass_info.rt_format = glslang_format_to_vk( output.meta.rt_format); - if (explicit_format) - RARCH_WARN("[slang]: Using explicit format for last pass in chain," - " but it is not rendered to framebuffer, using swapchain format instead.\n"); + RARCH_LOG("[slang]: Using render target format %s for pass output #%u.\n", + glslang_format_to_string(output.meta.rt_format), i); + } + else +#endif // VULKAN_HDR_SWAPCHAIN + { + pass_info.rt_format = tmpinfo.swapchain.format; + + if (explicit_format) + RARCH_WARN("[slang]: Using explicit format for last pass in chain," + " but it is not rendered to framebuffer, using swapchain format instead.\n"); + } } else { @@ -2865,6 +2884,13 @@ void vulkan_filter_chain_set_pass_info( chain->set_pass_info(pass, *info); } +VkFormat vulkan_filter_chain_get_pass_rt_format( + vulkan_filter_chain_t *chain, + unsigned pass) +{ + return chain->get_pass_rt_format(pass); +} + bool vulkan_filter_chain_update_swapchain_info( vulkan_filter_chain_t *chain, const vulkan_filter_chain_swapchain_info *info) diff --git a/gfx/drivers_shader/shader_vulkan.h b/gfx/drivers_shader/shader_vulkan.h index 3acd76df1d..c274e22468 100644 --- a/gfx/drivers_shader/shader_vulkan.h +++ b/gfx/drivers_shader/shader_vulkan.h @@ -102,6 +102,10 @@ void vulkan_filter_chain_set_pass_info(vulkan_filter_chain_t *chain, unsigned pass, const struct vulkan_filter_chain_pass_info *info); +VkFormat vulkan_filter_chain_get_pass_rt_format( + vulkan_filter_chain_t *chain, + unsigned pass); + bool vulkan_filter_chain_update_swapchain_info(vulkan_filter_chain_t *chain, const struct vulkan_filter_chain_swapchain_info *info);