|
@@ -28,6 +28,8 @@
|
|
|
// CHANGELOG
|
|
|
// (minor and older changes stripped away, please see git history for details)
|
|
|
// 2025-XX-XX: Platform: Added support for multiple windows via the ImGuiPlatformIO interface.
|
|
|
+// 2025-05-07- Vulkan: Fixed validation errors during window detach in multi-viewport mode. (#8600, #8176)
|
|
|
+// 2025-05-07: Vulkan: Load dynamic rendering functions using vkGetDeviceProcAddr() + try both non-KHR and KHR versions. (#8600, #8326, #8365)
|
|
|
// 2025-04-07: Vulkan: Deep-copy ImGui_ImplVulkan_InitInfo::PipelineRenderingCreateInfo's pColorAttachmentFormats buffer when set, in order to reduce common user-error of specifying a pointer to data that gets out of scope. (#8282)
|
|
|
// 2025-02-14: *BREAKING CHANGE*: Added uint32_t api_version to ImGui_ImplVulkan_LoadFunctions().
|
|
|
// 2025-02-13: Vulkan: Added ApiVersion field in ImGui_ImplVulkan_InitInfo. Default to header version if unspecified. Dynamic rendering path loads "vkCmdBeginRendering/vkCmdEndRendering" (without -KHR suffix) on API 1.3. (#8326)
|
|
@@ -1117,9 +1119,19 @@ void ImGui_ImplVulkan_DestroyDeviceObjects()
|
|
|
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
|
|
|
static void ImGui_ImplVulkan_LoadDynamicRenderingFunctions(uint32_t api_version, PFN_vkVoidFunction(*loader_func)(const char* function_name, void* user_data), void* user_data)
|
|
|
{
|
|
|
- // Manually load those two (see #5446, #8326, #8365)
|
|
|
- ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR = reinterpret_cast<PFN_vkCmdBeginRenderingKHR>(loader_func(api_version < VK_API_VERSION_1_3 ? "vkCmdBeginRenderingKHR" : "vkCmdBeginRendering", user_data));
|
|
|
- ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR = reinterpret_cast<PFN_vkCmdEndRenderingKHR>(loader_func(api_version < VK_API_VERSION_1_3 ? "vkCmdEndRenderingKHR" : "vkCmdEndRendering", user_data));
|
|
|
+ IM_UNUSED(api_version);
|
|
|
+
|
|
|
+ // Manually load those two (see #5446, #8326, #8365, #8600)
|
|
|
+ // - Try loading core (non-KHR) versions first (this will work for Vulkan 1.3+ and the device supports dynamic rendering)
|
|
|
+ ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR = reinterpret_cast<PFN_vkCmdBeginRenderingKHR>(loader_func("vkCmdBeginRendering", user_data));
|
|
|
+ ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR = reinterpret_cast<PFN_vkCmdEndRenderingKHR>(loader_func("vkCmdEndRendering", user_data));
|
|
|
+
|
|
|
+ // - Fallback to KHR versions if core not available (this will work if KHR extension is available and enabled and also the device supports dynamic rendering)
|
|
|
+ if (ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR == nullptr || ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR == nullptr)
|
|
|
+ {
|
|
|
+ ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR = reinterpret_cast<PFN_vkCmdBeginRenderingKHR>(loader_func("vkCmdBeginRenderingKHR", user_data));
|
|
|
+ ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR = reinterpret_cast<PFN_vkCmdEndRenderingKHR>(loader_func("vkCmdEndRenderingKHR", user_data));
|
|
|
+ }
|
|
|
}
|
|
|
#endif
|
|
|
|
|
@@ -1174,7 +1186,7 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info)
|
|
|
{
|
|
|
#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING
|
|
|
#ifndef IMGUI_IMPL_VULKAN_USE_LOADER
|
|
|
- ImGui_ImplVulkan_LoadDynamicRenderingFunctions(info->ApiVersion, [](const char* function_name, void* user_data) { return vkGetInstanceProcAddr((VkInstance)user_data, function_name); }, (void*)info->Instance);
|
|
|
+ ImGui_ImplVulkan_LoadDynamicRenderingFunctions(info->ApiVersion, [](const char* function_name, void* user_data) { return vkGetDeviceProcAddr((VkDevice)user_data, function_name); }, (void*)info->Device);
|
|
|
#endif
|
|
|
IM_ASSERT(ImGuiImplVulkanFuncs_vkCmdBeginRenderingKHR != nullptr);
|
|
|
IM_ASSERT(ImGuiImplVulkanFuncs_vkCmdEndRenderingKHR != nullptr);
|
|
@@ -1708,6 +1720,82 @@ void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevic
|
|
|
ImGui_ImplVulkanH_CreateWindowSwapChain(physical_device, device, wd, allocator, width, height, min_image_count);
|
|
|
//ImGui_ImplVulkan_CreatePipeline(device, allocator, VK_NULL_HANDLE, wd->RenderPass, VK_SAMPLE_COUNT_1_BIT, &wd->Pipeline, g_VulkanInitInfo.Subpass);
|
|
|
ImGui_ImplVulkanH_CreateWindowCommandBuffers(physical_device, device, wd, queue_family, allocator);
|
|
|
+
|
|
|
+ // FIXME: to submit the command buffer, we need a queue. In the examples folder, the ImGui_ImplVulkanH_CreateOrResizeWindow function is called
|
|
|
+ // before the ImGui_ImplVulkan_Init function, so we don't have access to the queue yet. Here we have the queue_family that we can use to grab
|
|
|
+ // a queue from the device and submit the command buffer. It would be better to have access to the queue as suggested in the FIXME below.
|
|
|
+ VkCommandPool command_pool;
|
|
|
+ VkCommandPoolCreateInfo pool_info = {};
|
|
|
+ pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
|
|
|
+ pool_info.queueFamilyIndex = queue_family;
|
|
|
+ pool_info.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
|
|
|
+ VkResult err = vkCreateCommandPool(device, &pool_info, allocator, &command_pool);
|
|
|
+ check_vk_result(err);
|
|
|
+
|
|
|
+ VkFenceCreateInfo fence_info = {};
|
|
|
+ fence_info.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
|
|
|
+ VkFence fence;
|
|
|
+ err = vkCreateFence(device, &fence_info, allocator, &fence);
|
|
|
+ check_vk_result(err);
|
|
|
+
|
|
|
+ VkCommandBufferAllocateInfo alloc_info = {};
|
|
|
+ alloc_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
|
|
|
+ alloc_info.commandPool = command_pool;
|
|
|
+ alloc_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
|
|
|
+ alloc_info.commandBufferCount = 1;
|
|
|
+ VkCommandBuffer command_buffer;
|
|
|
+ err = vkAllocateCommandBuffers(device, &alloc_info, &command_buffer);
|
|
|
+ check_vk_result(err);
|
|
|
+
|
|
|
+ VkCommandBufferBeginInfo begin_info = {};
|
|
|
+ begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
|
|
|
+ begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
|
|
|
+ err = vkBeginCommandBuffer(command_buffer, &begin_info);
|
|
|
+ check_vk_result(err);
|
|
|
+
|
|
|
+ // Transition the images to the correct layout for rendering
|
|
|
+ for (uint32_t i = 0; i < wd->ImageCount; i++)
|
|
|
+ {
|
|
|
+ VkImageMemoryBarrier barrier = {};
|
|
|
+ barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
|
|
|
+ barrier.image = wd->Frames[i].Backbuffer;
|
|
|
+ barrier.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
|
|
|
+ barrier.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
|
|
+ barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
|
+ barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
|
|
|
+ barrier.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
|
|
+ barrier.subresourceRange.levelCount = 1;
|
|
|
+ barrier.subresourceRange.layerCount = 1;
|
|
|
+ vkCmdPipelineBarrier(command_buffer, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 0, nullptr, 0, nullptr, 1, &barrier);
|
|
|
+ }
|
|
|
+
|
|
|
+ err = vkEndCommandBuffer(command_buffer);
|
|
|
+ check_vk_result(err);
|
|
|
+ VkSubmitInfo submit_info = {};
|
|
|
+ submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
|
|
|
+ submit_info.commandBufferCount = 1;
|
|
|
+ submit_info.pCommandBuffers = &command_buffer;
|
|
|
+
|
|
|
+ VkQueue queue;
|
|
|
+ vkGetDeviceQueue(device, queue_family, 0, &queue);
|
|
|
+ err = vkQueueSubmit(queue, 1, &submit_info, fence);
|
|
|
+ check_vk_result(err);
|
|
|
+ err = vkWaitForFences(device, 1, &fence, VK_TRUE, UINT64_MAX);
|
|
|
+ check_vk_result(err);
|
|
|
+ err = vkResetFences(device, 1, &fence);
|
|
|
+ check_vk_result(err);
|
|
|
+
|
|
|
+ err = vkResetCommandPool(device, command_pool, 0);
|
|
|
+ check_vk_result(err);
|
|
|
+
|
|
|
+ // Destroy command buffer and fence and command pool
|
|
|
+ vkFreeCommandBuffers(device, command_pool, 1, &command_buffer);
|
|
|
+ vkDestroyCommandPool(device, command_pool, allocator);
|
|
|
+ vkDestroyFence(device, fence, allocator);
|
|
|
+ command_pool = VK_NULL_HANDLE;
|
|
|
+ command_buffer = VK_NULL_HANDLE;
|
|
|
+ fence = VK_NULL_HANDLE;
|
|
|
+ queue = VK_NULL_HANDLE;
|
|
|
}
|
|
|
|
|
|
void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator)
|