From 7812e836e433e4a0c0f89d4d61f17127812e7442 Mon Sep 17 00:00:00 2001 From: sean <43609023+spnda@users.noreply.github.com> Date: Sat, 19 Feb 2022 20:15:58 +0100 Subject: [PATCH] Backends: Vulkan: Support for dynamic_rendering (#5446, #5037) Co-authored-by: Caio Oliveira Simplified for master branch. # Conflicts: # backends/imgui_impl_vulkan.cpp --- backends/imgui_impl_vulkan.cpp | 45 +++++++++++++++++++++++++++++++--- backends/imgui_impl_vulkan.h | 3 +++ 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index c5ee279f..57a68345 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -212,6 +212,11 @@ IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_DEF) #undef IMGUI_VULKAN_FUNC_DEF #endif // VK_NO_PROTOTYPES +#if defined(VK_VERSION_1_3) || defined(VK_KHR_dynamic_rendering) +static PFN_vkCmdBeginRenderingKHR imgui_vkCmdBeginRenderingKHR; +static PFN_vkCmdEndRenderingKHR imgui_vkCmdEndRenderingKHR; +#endif + //----------------------------------------------------------------------------- // SHADERS //----------------------------------------------------------------------------- @@ -840,6 +845,19 @@ static void ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationC info.layout = bd->PipelineLayout; info.renderPass = renderPass; info.subpass = subpass; + +#if defined(VK_VERSION_1_3) || defined(VK_KHR_dynamic_rendering) + VkPipelineRenderingCreateInfoKHR pipelineRenderingCreateInfo = {}; + pipelineRenderingCreateInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR; + pipelineRenderingCreateInfo.colorAttachmentCount = 1; + pipelineRenderingCreateInfo.pColorAttachmentFormats = &bd->VulkanInitInfo.ColorAttachmentFormat; + + if (bd->VulkanInitInfo.UseDynamicRendering) { + info.pNext = &pipelineRenderingCreateInfo; + info.renderPass = VK_NULL_HANDLE; // Just make sure it's actually nullptr. + } +#endif + VkResult err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &info, allocator, pipeline); check_vk_result(err); } @@ -952,10 +970,16 @@ bool ImGui_ImplVulkan_LoadFunctions(PFN_vkVoidFunction(*loader_func)(const ch return false; IMGUI_VULKAN_FUNC_MAP(IMGUI_VULKAN_FUNC_LOAD) #undef IMGUI_VULKAN_FUNC_LOAD + +#if defined(VK_VERSION_1_3) || defined(VK_KHR_dynamic_rendering) + imgui_vkCmdBeginRenderingKHR = reinterpret_cast(loader_func("vkCmdBeginRenderingKHR", user_data)); + imgui_vkCmdEndRenderingKHR = reinterpret_cast(loader_func("vkCmdEndRenderingKHR", user_data)); +#endif #else IM_UNUSED(loader_func); IM_UNUSED(user_data); #endif + g_FunctionsLoaded = true; return true; } @@ -964,6 +988,20 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass rend { IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!"); + if (info->UseDynamicRendering) { +#if defined(VK_VERSION_1_3) || defined(VK_KHR_dynamic_rendering) +#ifndef VK_NO_PROTOTYPES + imgui_vkCmdBeginRenderingKHR = reinterpret_cast(vkGetInstanceProcAddr(info->Instance, "vkCmdBeginRenderingKHR")); + imgui_vkCmdEndRenderingKHR = reinterpret_cast(vkGetInstanceProcAddr(info->Instance, "vkCmdEndRenderingKHR")); +#endif + + IM_ASSERT(imgui_vkCmdBeginRenderingKHR != nullptr); + IM_ASSERT(imgui_vkCmdEndRenderingKHR != nullptr); +#else + IM_ASSERT(!"Can't use dynamic rendering when neither VK_VERSION_1_3 or VK_KHR_dynamic_rendering is defined."); +#endif + } + ImGuiIO& io = ImGui::GetIO(); IM_ASSERT(io.BackendRendererUserData == nullptr && "Already initialized a renderer backend!"); @@ -980,7 +1018,8 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info, VkRenderPass rend IM_ASSERT(info->DescriptorPool != VK_NULL_HANDLE); IM_ASSERT(info->MinImageCount >= 2); IM_ASSERT(info->ImageCount >= info->MinImageCount); - IM_ASSERT(render_pass != VK_NULL_HANDLE); + if (!info->UseDynamicRendering) + IM_ASSERT(render_pass != VK_NULL_HANDLE); bd->VulkanInitInfo = *info; bd->RenderPass = render_pass; @@ -1297,7 +1336,7 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V vkDestroySwapchainKHR(device, old_swapchain, allocator); // Create the Render Pass - { + if (!wd->UseDynamicRendering) { VkAttachmentDescription attachment = {}; attachment.format = wd->SurfaceFormat.format; attachment.samples = VK_SAMPLE_COUNT_1_BIT; @@ -1359,7 +1398,7 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V } // Create Framebuffer - { + if (!wd->UseDynamicRendering) { VkImageView attachment[1]; VkFramebufferCreateInfo info = {}; info.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index 64cc887c..363c130c 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -61,6 +61,8 @@ struct ImGui_ImplVulkan_InitInfo VkSampleCountFlagBits MSAASamples; // >= VK_SAMPLE_COUNT_1_BIT (0 -> default to VK_SAMPLE_COUNT_1_BIT) const VkAllocationCallbacks* Allocator; void (*CheckVkResultFn)(VkResult err); + bool UseDynamicRendering; // Need to explicitly enable VK_KHR_dynamic_rendering extension to use this, even for Vulkan 1.3. + VkFormat ColorAttachmentFormat; }; // Called by user code @@ -139,6 +141,7 @@ struct ImGui_ImplVulkanH_Window VkPresentModeKHR PresentMode; VkRenderPass RenderPass; VkPipeline Pipeline; // The window pipeline may uses a different VkRenderPass than the one passed in ImGui_ImplVulkan_InitInfo + bool UseDynamicRendering; bool ClearEnable; VkClearValue ClearValue; uint32_t FrameIndex; // Current frame being rendered to (0 <= FrameIndex < FrameInFlightCount)