From 719ea9c2284069c52135f1400d7fb7640e3d54ad Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 24 Sep 2025 15:00:24 +0200 Subject: [PATCH 1/9] Comments --- backends/imgui_impl_sdl2.cpp | 1 + backends/imgui_impl_sdl3.cpp | 1 + docs/CHANGELOG.txt | 1 + 3 files changed, 3 insertions(+) diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index 53336995e..12a8438b9 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -676,6 +676,7 @@ static void ImGui_ImplSDL2_UpdateMouseData() SDL_WarpMouseInWindow(bd->Window, (int)io.MousePos.x, (int)io.MousePos.y); // (Optional) Fallback to provide unclamped mouse position when focused but not hovered (SDL_MOUSEMOTION already provides this when hovered or captured) + // Note that SDL_GetGlobalMouseState() is in theory slow on X11, but this only runs on rather specific cases. If a problem we may provide a way to opt-out this feature. SDL_Window* hovered_window = SDL_GetMouseFocus(); const bool is_relative_mouse_mode = SDL_GetRelativeMouseMode() != 0; if (hovered_window == NULL && bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0 && !is_relative_mouse_mode) diff --git a/backends/imgui_impl_sdl3.cpp b/backends/imgui_impl_sdl3.cpp index 77e5b94a8..564131a4d 100644 --- a/backends/imgui_impl_sdl3.cpp +++ b/backends/imgui_impl_sdl3.cpp @@ -638,6 +638,7 @@ static void ImGui_ImplSDL3_UpdateMouseData() SDL_WarpMouseInWindow(bd->Window, io.MousePos.x, io.MousePos.y); // (Optional) Fallback to provide unclamped mouse position when focused but not hovered (SDL_EVENT_MOUSE_MOTION already provides this when hovered or captured) + // Note that SDL_GetGlobalMouseState() is in theory slow on X11, but this only runs on rather specific cases. If a problem we may provide a way to opt-out this feature. SDL_Window* hovered_window = SDL_GetMouseFocus(); const bool is_relative_mouse_mode = SDL_GetWindowRelativeMouseMode(bd->Window); if (hovered_window == NULL && bd->MouseCanUseGlobalState && bd->MouseButtonsDown == 0 && !is_relative_mouse_mode) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 9906174a5..3357a1547 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -60,6 +60,7 @@ Other Changes: - Backends: SDL2,SDL3: avoid using the SDL_GetGlobalMouseState() path when one of our window is hovered, as the event data is reliable and enough in this case. - Fix mouse coordinates issue in fullscreen apps with macOS notch. (#7919, #7786) + - Essentially a working for SDL3 bug which will be fixed in SDL 3.3.0. - Better perf on X11 as querying global position requires a round trip to X11 server. - Backends: Win32: minor optimization not submitting gamepad io again if XInput's dwPacketNumber has not changed. (#8556) [@MidTerm-CN] From 940627d008b8f0584b7f50d24574537cf24a32e1 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 24 Sep 2025 15:29:00 +0200 Subject: [PATCH 2/9] Backends: SDL2: Fixed build for Emscripten and SDL_HAS_CAPTURE_AND_GLOBAL_MOUSE=0 platforms. Amend e06b5df. --- backends/imgui_impl_sdl2.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/backends/imgui_impl_sdl2.cpp b/backends/imgui_impl_sdl2.cpp index 12a8438b9..c2dae4053 100644 --- a/backends/imgui_impl_sdl2.cpp +++ b/backends/imgui_impl_sdl2.cpp @@ -667,6 +667,7 @@ static void ImGui_ImplSDL2_UpdateMouseData() SDL_Window* focused_window = SDL_GetKeyboardFocus(); const bool is_app_focused = (bd->Window == focused_window); #else + SDL_Window* focused_window = bd->Window; const bool is_app_focused = (SDL_GetWindowFlags(bd->Window) & SDL_WINDOW_INPUT_FOCUS) != 0; // SDL 2.0.3 and non-windowed systems: single-viewport only #endif if (is_app_focused) From cee40f8af99eee390eb17adfe79a68a26d83c436 Mon Sep 17 00:00:00 2001 From: ocornut Date: Wed, 24 Sep 2025 17:48:48 +0200 Subject: [PATCH 3/9] Examples: made examples's main.cpp consistent with returning 1 on error. --- docs/CHANGELOG.txt | 1 + examples/example_sdl2_directx11/main.cpp | 4 ++-- examples/example_sdl2_metal/main.mm | 2 +- examples/example_sdl2_opengl2/main.cpp | 4 ++-- examples/example_sdl2_opengl3/main.cpp | 6 +++--- examples/example_sdl2_sdlrenderer2/main.cpp | 6 +++--- examples/example_sdl2_vulkan/main.cpp | 4 ++-- examples/example_sdl3_directx11/main.cpp | 6 +++--- examples/example_sdl3_metal/main.mm | 10 +++++----- examples/example_sdl3_opengl3/main.cpp | 6 +++--- examples/example_sdl3_sdlgpu3/main.cpp | 8 ++++---- examples/example_sdl3_sdlrenderer3/main.cpp | 6 +++--- examples/example_sdl3_vulkan/main.cpp | 4 ++-- 13 files changed, 34 insertions(+), 33 deletions(-) diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 3357a1547..04ca7ef1c 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -67,6 +67,7 @@ Other Changes: - Examples: SDL2+DirectX11: Try WARP software driver if hardware driver is not available. (#5924, #5562) - Examples: SDL3+DirectX11: Added SDL3+DirectX11 example. (#8956, #8957) [@tomaz82] +- Examples: made examples's main.cpp consistent with returning 1 on error. ----------------------------------------------------------------------- diff --git a/examples/example_sdl2_directx11/main.cpp b/examples/example_sdl2_directx11/main.cpp index ec6602f83..e14085dd3 100644 --- a/examples/example_sdl2_directx11/main.cpp +++ b/examples/example_sdl2_directx11/main.cpp @@ -39,7 +39,7 @@ int main(int, char**) if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0) { printf("Error: %s\n", SDL_GetError()); - return -1; + return 1; } // From 2.0.18: Enable native IME. @@ -54,7 +54,7 @@ int main(int, char**) if (window == nullptr) { printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); - return -1; + return 1; } SDL_SysWMinfo wmInfo; diff --git a/examples/example_sdl2_metal/main.mm b/examples/example_sdl2_metal/main.mm index 80c7e7b1a..0f60d771d 100644 --- a/examples/example_sdl2_metal/main.mm +++ b/examples/example_sdl2_metal/main.mm @@ -51,7 +51,7 @@ int main(int, char**) if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0) { printf("Error: %s\n", SDL_GetError()); - return -1; + return 1; } // Inform SDL that we will be using metal for rendering. Without this hint initialization of metal renderer may fail. diff --git a/examples/example_sdl2_opengl2/main.cpp b/examples/example_sdl2_opengl2/main.cpp index a06b58c8c..327780e20 100644 --- a/examples/example_sdl2_opengl2/main.cpp +++ b/examples/example_sdl2_opengl2/main.cpp @@ -31,7 +31,7 @@ int main(int, char**) if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0) { printf("Error: %s\n", SDL_GetError()); - return -1; + return 1; } // From 2.0.18: Enable native IME. @@ -51,7 +51,7 @@ int main(int, char**) if (window == nullptr) { printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); - return -1; + return 1; } SDL_GLContext gl_context = SDL_GL_CreateContext(window); diff --git a/examples/example_sdl2_opengl3/main.cpp b/examples/example_sdl2_opengl3/main.cpp index 96631271b..4a655ac61 100644 --- a/examples/example_sdl2_opengl3/main.cpp +++ b/examples/example_sdl2_opengl3/main.cpp @@ -36,7 +36,7 @@ int main(int, char**) if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0) { printf("Error: %s\n", SDL_GetError()); - return -1; + return 1; } // Decide GL+GLSL versions @@ -85,14 +85,14 @@ int main(int, char**) if (window == nullptr) { printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); - return -1; + return 1; } SDL_GLContext gl_context = SDL_GL_CreateContext(window); if (gl_context == nullptr) { printf("Error: SDL_GL_CreateContext(): %s\n", SDL_GetError()); - return -1; + return 1; } SDL_GL_MakeCurrent(window, gl_context); diff --git a/examples/example_sdl2_sdlrenderer2/main.cpp b/examples/example_sdl2_sdlrenderer2/main.cpp index 60b365e6e..214f6f471 100644 --- a/examples/example_sdl2_sdlrenderer2/main.cpp +++ b/examples/example_sdl2_sdlrenderer2/main.cpp @@ -33,7 +33,7 @@ int main(int, char**) if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0) { printf("Error: %s\n", SDL_GetError()); - return -1; + return 1; } // From 2.0.18: Enable native IME. @@ -48,13 +48,13 @@ int main(int, char**) if (window == nullptr) { printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); - return -1; + return 1; } SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_PRESENTVSYNC | SDL_RENDERER_ACCELERATED); if (renderer == nullptr) { SDL_Log("Error creating SDL_Renderer!"); - return -1; + return 1; } //SDL_RendererInfo info; //SDL_GetRendererInfo(renderer, &info); diff --git a/examples/example_sdl2_vulkan/main.cpp b/examples/example_sdl2_vulkan/main.cpp index 4a1228058..8dd505889 100644 --- a/examples/example_sdl2_vulkan/main.cpp +++ b/examples/example_sdl2_vulkan/main.cpp @@ -349,7 +349,7 @@ int main(int, char**) if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_GAMECONTROLLER) != 0) { printf("Error: %s\n", SDL_GetError()); - return -1; + return 1; } // From 2.0.18: Enable native IME. @@ -364,7 +364,7 @@ int main(int, char**) if (window == nullptr) { printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); - return -1; + return 1; } ImVector extensions; diff --git a/examples/example_sdl3_directx11/main.cpp b/examples/example_sdl3_directx11/main.cpp index bc8889b8c..946992409 100644 --- a/examples/example_sdl3_directx11/main.cpp +++ b/examples/example_sdl3_directx11/main.cpp @@ -34,7 +34,7 @@ int main(int, char**) if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) { printf("Error: SDL_Init(): %s\n", SDL_GetError()); - return -1; + return 1; } // Setup window @@ -44,7 +44,7 @@ int main(int, char**) if (window == nullptr) { printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); - return -1; + return 1; } SDL_PropertiesID props = SDL_GetWindowProperties(window); @@ -54,7 +54,7 @@ int main(int, char**) if (!CreateDeviceD3D(hwnd)) { CleanupDeviceD3D(); - return -1; + return 1; } SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); diff --git a/examples/example_sdl3_metal/main.mm b/examples/example_sdl3_metal/main.mm index 022e0f432..1dd80d010 100644 --- a/examples/example_sdl3_metal/main.mm +++ b/examples/example_sdl3_metal/main.mm @@ -24,7 +24,7 @@ int main(int, char**) if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) { printf("Error: SDL_Init(): %s\n", SDL_GetError()); - return -1; + return 1; } // Create SDL window graphics context @@ -34,19 +34,19 @@ int main(int, char**) if (window == nullptr) { printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); - return -1; + return 1; } SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); SDL_ShowWindow(window); // Create Metal device _before_ creating the view/layer - id metalDevice = MTLCreateSystemDefaultDevice(); + id metalDevice = MTLCreateSystemDefaultDevice(); if (!metalDevice) { printf("Error: failed to create Metal device.\n"); SDL_DestroyWindow(window); SDL_Quit(); - return -1; + return 1; } SDL_MetalView view = SDL_Metal_CreateView(window); CAMetalLayer* layer = (__bridge CAMetalLayer*)SDL_Metal_GetLayer(view); @@ -128,7 +128,7 @@ int main(int, char**) int width, height; SDL_GetWindowSizeInPixels(window, &width, &height); - + layer.drawableSize = CGSizeMake(width, height); id drawable = [layer nextDrawable]; diff --git a/examples/example_sdl3_opengl3/main.cpp b/examples/example_sdl3_opengl3/main.cpp index 36b5e2eba..44a6417d1 100644 --- a/examples/example_sdl3_opengl3/main.cpp +++ b/examples/example_sdl3_opengl3/main.cpp @@ -30,7 +30,7 @@ int main(int, char**) if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) { printf("Error: SDL_Init(): %s\n", SDL_GetError()); - return -1; + return 1; } // Decide GL+GLSL versions @@ -74,13 +74,13 @@ int main(int, char**) if (window == nullptr) { printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); - return -1; + return 1; } SDL_GLContext gl_context = SDL_GL_CreateContext(window); if (gl_context == nullptr) { printf("Error: SDL_GL_CreateContext(): %s\n", SDL_GetError()); - return -1; + return 1; } SDL_GL_MakeCurrent(window, gl_context); diff --git a/examples/example_sdl3_sdlgpu3/main.cpp b/examples/example_sdl3_sdlgpu3/main.cpp index 3f797ecd6..84b0a254f 100644 --- a/examples/example_sdl3_sdlgpu3/main.cpp +++ b/examples/example_sdl3_sdlgpu3/main.cpp @@ -31,7 +31,7 @@ int main(int, char**) if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) { printf("Error: SDL_Init(): %s\n", SDL_GetError()); - return -1; + return 1; } // Create SDL window graphics context @@ -41,7 +41,7 @@ int main(int, char**) if (window == nullptr) { printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); - return -1; + return 1; } SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); SDL_ShowWindow(window); @@ -51,14 +51,14 @@ int main(int, char**) if (gpu_device == nullptr) { printf("Error: SDL_CreateGPUDevice(): %s\n", SDL_GetError()); - return -1; + return 1; } // Claim window for GPU Device if (!SDL_ClaimWindowForGPUDevice(gpu_device, window)) { printf("Error: SDL_ClaimWindowForGPUDevice(): %s\n", SDL_GetError()); - return -1; + return 1; } SDL_SetGPUSwapchainParameters(gpu_device, window, SDL_GPU_SWAPCHAINCOMPOSITION_SDR, SDL_GPU_PRESENTMODE_VSYNC); diff --git a/examples/example_sdl3_sdlrenderer3/main.cpp b/examples/example_sdl3_sdlrenderer3/main.cpp index 2256b7da7..39870f2c6 100644 --- a/examples/example_sdl3_sdlrenderer3/main.cpp +++ b/examples/example_sdl3_sdlrenderer3/main.cpp @@ -28,7 +28,7 @@ int main(int, char**) if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) { printf("Error: SDL_Init(): %s\n", SDL_GetError()); - return -1; + return 1; } // Create window with SDL_Renderer graphics context @@ -38,14 +38,14 @@ int main(int, char**) if (window == nullptr) { printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); - return -1; + return 1; } SDL_Renderer* renderer = SDL_CreateRenderer(window, nullptr); SDL_SetRenderVSync(renderer, 1); if (renderer == nullptr) { SDL_Log("Error: SDL_CreateRenderer(): %s\n", SDL_GetError()); - return -1; + return 1; } SDL_SetWindowPosition(window, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED); SDL_ShowWindow(window); diff --git a/examples/example_sdl3_vulkan/main.cpp b/examples/example_sdl3_vulkan/main.cpp index dd9a460c9..060855259 100644 --- a/examples/example_sdl3_vulkan/main.cpp +++ b/examples/example_sdl3_vulkan/main.cpp @@ -349,7 +349,7 @@ int main(int, char**) if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_GAMEPAD)) { printf("Error: SDL_Init(): %s\n", SDL_GetError()); - return -1; + return 1; } // Create window with Vulkan graphics context @@ -359,7 +359,7 @@ int main(int, char**) if (window == nullptr) { printf("Error: SDL_CreateWindow(): %s\n", SDL_GetError()); - return -1; + return 1; } ImVector extensions; From bf2e0b2c6f053c5633b8288d7ffc17ab92ea923c Mon Sep 17 00:00:00 2001 From: ocornut Date: Thu, 25 Sep 2025 19:07:51 +0200 Subject: [PATCH 4/9] Tables: change ImGuiTableFlags_NoBordersInBody behavior to not draw border in body even when resizing. (#8893) --- imgui_tables.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/imgui_tables.cpp b/imgui_tables.cpp index 21d5335c6..af0e8c6cf 100644 --- a/imgui_tables.cpp +++ b/imgui_tables.cpp @@ -2818,8 +2818,13 @@ void ImGui::TableDrawBorders(ImGuiTable* table) continue; // Draw in outer window so right-most column won't be clipped - // Always draw full height border when being resized/hovered, or on the delimitation of frozen column scrolling. - float draw_y2 = (is_hovered || is_resized || is_frozen_separator || (table->Flags & (ImGuiTableFlags_NoBordersInBody | ImGuiTableFlags_NoBordersInBodyUntilResize)) == 0) ? draw_y2_body : draw_y2_head; + float draw_y2 = draw_y2_head; + if (is_frozen_separator) + draw_y2 = draw_y2_body; + else if ((table->Flags & ImGuiTableFlags_NoBordersInBodyUntilResize) != 0 && (is_hovered || is_resized)) + draw_y2 = draw_y2_body; + else if ((table->Flags & (ImGuiTableFlags_NoBordersInBodyUntilResize | ImGuiTableFlags_NoBordersInBody)) == 0) + draw_y2 = draw_y2_body; if (draw_y2 > draw_y1) inner_drawlist->AddLine(ImVec2(column->MaxX, draw_y1), ImVec2(column->MaxX, draw_y2), TableGetColumnBorderCol(table, order_n, column_n), border_size); } From 01686c6294a778b017f63eaad4c9d391fd77495a Mon Sep 17 00:00:00 2001 From: johan0A Date: Sat, 5 Apr 2025 21:36:20 +0200 Subject: [PATCH 5/9] Backends: Vulkan: added a way to specify custom vertex/fragment shaders. (#8585, #8271) --- backends/imgui_impl_vulkan.cpp | 25 ++++++++++++++----------- backends/imgui_impl_vulkan.h | 8 +++++++- docs/CHANGELOG.txt | 2 ++ 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 4a0a5a947..0e0ba719b 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -27,6 +27,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-09-26: Vulkan: Added a way to customize shaders by filling ImGui_ImplVulkan_InitInfo::CustomShaderVertCreateInfo/CustomShaderFragCreateInfo. (#8585) // 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. // 2025-09-04: Vulkan: Added ImGui_ImplVulkan_CreateMainPipeline(). (#8110, #8111) // 2025-07-27: Vulkan: Fixed texture update corruption introduced on 2025-06-11. (#8801, #8755, #8840) @@ -887,24 +888,26 @@ void ImGui_ImplVulkan_UpdateTexture(ImTextureData* tex) static void ImGui_ImplVulkan_CreateShaderModules(VkDevice device, const VkAllocationCallbacks* allocator) { - // Create the shader modules ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); + ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; if (bd->ShaderModuleVert == VK_NULL_HANDLE) { - VkShaderModuleCreateInfo vert_info = {}; - vert_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - vert_info.codeSize = sizeof(__glsl_shader_vert_spv); - vert_info.pCode = (uint32_t*)__glsl_shader_vert_spv; - VkResult err = vkCreateShaderModule(device, &vert_info, allocator, &bd->ShaderModuleVert); + VkShaderModuleCreateInfo default_vert_info = {}; + default_vert_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + default_vert_info.codeSize = sizeof(__glsl_shader_vert_spv); + default_vert_info.pCode = (uint32_t*)__glsl_shader_vert_spv; + VkShaderModuleCreateInfo* p_vert_info = (v->CustomShaderVertCreateInfo.sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO) ? &v->CustomShaderVertCreateInfo : &default_vert_info; + VkResult err = vkCreateShaderModule(device, p_vert_info, allocator, &bd->ShaderModuleVert); check_vk_result(err); } if (bd->ShaderModuleFrag == VK_NULL_HANDLE) { - VkShaderModuleCreateInfo frag_info = {}; - frag_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - frag_info.codeSize = sizeof(__glsl_shader_frag_spv); - frag_info.pCode = (uint32_t*)__glsl_shader_frag_spv; - VkResult err = vkCreateShaderModule(device, &frag_info, allocator, &bd->ShaderModuleFrag); + VkShaderModuleCreateInfo default_frag_info = {}; + default_frag_info.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; + default_frag_info.codeSize = sizeof(__glsl_shader_frag_spv); + default_frag_info.pCode = (uint32_t*)__glsl_shader_frag_spv; + VkShaderModuleCreateInfo* p_frag_info = (v->CustomShaderFragCreateInfo.sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO) ? &v->CustomShaderFragCreateInfo : &default_frag_info; + VkResult err = vkCreateShaderModule(device, p_frag_info, allocator, &bd->ShaderModuleFrag); check_vk_result(err); } } diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index a24cb2cdb..cf1a5b9a1 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -102,7 +102,13 @@ struct ImGui_ImplVulkan_InitInfo // (Optional) Allocation, Debugging const VkAllocationCallbacks* Allocator; void (*CheckVkResultFn)(VkResult err); - VkDeviceSize MinAllocationSize; // Minimum allocation size. Set to 1024*1024 to satisfy zealous best practices validation layer and waste a little memory. + VkDeviceSize MinAllocationSize; // Minimum allocation size. Set to 1024*1024 to satisfy zealous best practices validation layer and waste a little memory. + + // (Optional) Customize default vertex/fragment shaders. + // - if .sType == VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO we use specified structs, otherwise we use defaults. + // - Shader inputs/outputs need to match ours. Code/data pointed to by the structure needs to survive for whole during of backend usage. + VkShaderModuleCreateInfo CustomShaderVertCreateInfo; + VkShaderModuleCreateInfo CustomShaderFragCreateInfo; }; // Follow "Getting Started" link and check examples/ folder to learn about using backends! diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 04ca7ef1c..ce9a22f5a 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -64,6 +64,8 @@ Other Changes: - Better perf on X11 as querying global position requires a round trip to X11 server. - Backends: Win32: minor optimization not submitting gamepad io again if XInput's dwPacketNumber has not changed. (#8556) [@MidTerm-CN] +- Backends: Vulkan: added a way to specify custom shaders by filling init fields + CustomShaderVertCreateInfo and CustomShaderFragCreateInfo. (#8585, #8271) [@johan0A] - Examples: SDL2+DirectX11: Try WARP software driver if hardware driver is not available. (#5924, #5562) - Examples: SDL3+DirectX11: Added SDL3+DirectX11 example. (#8956, #8957) [@tomaz82] From 5fe962216ac8af5688602ea01d51313f3b949c74 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 26 Sep 2025 17:32:39 +0200 Subject: [PATCH 6/9] (Breaking) Backends: Vulkan: added 'VkImageUsageFlags image_usage' parameter to ImGui_ImplVulkanH_CreateOrResizeWindow(). (#8946, #8110, #8111, #8686) Default to VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT. --- backends/imgui_impl_vulkan.cpp | 12 +++++++----- backends/imgui_impl_vulkan.h | 4 ++-- docs/CHANGELOG.txt | 6 ++++++ examples/example_glfw_vulkan/main.cpp | 5 +++-- examples/example_sdl2_vulkan/main.cpp | 5 +++-- examples/example_sdl3_vulkan/main.cpp | 5 +++-- examples/example_win32_vulkan/main.cpp | 5 +++-- 7 files changed, 27 insertions(+), 15 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 0e0ba719b..7a8d26362 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -27,6 +27,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-09-26: *BREAKING CHANGE*: helper ImGui_ImplVulkanH_CreateOrResizeWindow() added a VkImageUsageFlags image_usage` argument, default to VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT if 0. // 2025-09-26: Vulkan: Added a way to customize shaders by filling ImGui_ImplVulkan_InitInfo::CustomShaderVertCreateInfo/CustomShaderFragCreateInfo. (#8585) // 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. // 2025-09-04: Vulkan: Added ImGui_ImplVulkan_CreateMainPipeline(). (#8110, #8111) @@ -118,7 +119,7 @@ void ImGui_ImplVulkan_DestroyFrameRenderBuffers(VkDevice device, ImGui_ImplVulka void ImGui_ImplVulkan_DestroyWindowRenderBuffers(VkDevice device, ImGui_ImplVulkan_WindowRenderBuffers* buffers, const VkAllocationCallbacks* allocator); void ImGui_ImplVulkanH_DestroyFrame(VkDevice device, ImGui_ImplVulkanH_Frame* fd, const VkAllocationCallbacks* allocator); void ImGui_ImplVulkanH_DestroyFrameSemaphores(VkDevice device, ImGui_ImplVulkanH_FrameSemaphores* fsd, const VkAllocationCallbacks* allocator); -void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count); +void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count, VkImageUsageFlags image_usage); void ImGui_ImplVulkanH_CreateWindowCommandBuffers(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator); // Vulkan prototypes for use with custom loaders @@ -1605,7 +1606,7 @@ int ImGui_ImplVulkanH_GetMinImageCountFromPresentMode(VkPresentModeKHR present_m } // Also destroy old swap chain and in-flight frames data, if any. -void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count) +void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count, VkImageUsageFlags image_usage) { VkResult err; VkSwapchainKHR old_swapchain = wd->Swapchain; @@ -1644,7 +1645,7 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V info.imageFormat = wd->SurfaceFormat.format; info.imageColorSpace = wd->SurfaceFormat.colorSpace; info.imageArrayLayers = 1; - info.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; + info.imageUsage = (image_usage != 0) ? image_usage : VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; info.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; // Assume that graphics family == present family info.preTransform = (cap.supportedTransforms & VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR) ? VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR : cap.currentTransform; info.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; @@ -1772,11 +1773,12 @@ void ImGui_ImplVulkanH_CreateWindowSwapChain(VkPhysicalDevice physical_device, V } // Create or resize window -void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int width, int height, uint32_t min_image_count) +// - 2025/09/26: v1.92.4 added a trailing 'VkImageUsageFlags image_usage' parameter which is usually VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT. +void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int width, int height, uint32_t min_image_count, VkImageUsageFlags image_usage) { IM_ASSERT(g_FunctionsLoaded && "Need to call ImGui_ImplVulkan_LoadFunctions() if IMGUI_IMPL_VULKAN_NO_PROTOTYPES or VK_NO_PROTOTYPES are set!"); (void)instance; - ImGui_ImplVulkanH_CreateWindowSwapChain(physical_device, device, wd, allocator, width, height, min_image_count); + ImGui_ImplVulkanH_CreateWindowSwapChain(physical_device, device, wd, allocator, width, height, min_image_count, image_usage); 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 diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index cf1a5b9a1..62158b7f9 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -181,8 +181,8 @@ struct ImGui_ImplVulkanH_Frame; struct ImGui_ImplVulkanH_Window; // Helpers -IMGUI_IMPL_API void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wnd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count); -IMGUI_IMPL_API void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Window* wnd, const VkAllocationCallbacks* allocator); +IMGUI_IMPL_API void ImGui_ImplVulkanH_CreateOrResizeWindow(VkInstance instance, VkPhysicalDevice physical_device, VkDevice device, ImGui_ImplVulkanH_Window* wd, uint32_t queue_family, const VkAllocationCallbacks* allocator, int w, int h, uint32_t min_image_count, VkImageUsageFlags image_usage); +IMGUI_IMPL_API void ImGui_ImplVulkanH_DestroyWindow(VkInstance instance, VkDevice device, ImGui_ImplVulkanH_Window* wd, const VkAllocationCallbacks* allocator); IMGUI_IMPL_API VkSurfaceFormatKHR ImGui_ImplVulkanH_SelectSurfaceFormat(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkFormat* request_formats, int request_formats_count, VkColorSpaceKHR request_color_space); IMGUI_IMPL_API VkPresentModeKHR ImGui_ImplVulkanH_SelectPresentMode(VkPhysicalDevice physical_device, VkSurfaceKHR surface, const VkPresentModeKHR* request_modes, int request_modes_count); IMGUI_IMPL_API VkPhysicalDevice ImGui_ImplVulkanH_SelectPhysicalDevice(VkInstance instance); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index ce9a22f5a..1f6e463f5 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -41,6 +41,12 @@ HOW TO UPDATE? Breaking Changes: +- Backends: Vulkan: helper ImGui_ImplVulkanH_CreateOrResizeWindow() added a + `VkImageUsageFlags image_usage` argument. + It was previously hardcoded to `VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT` and defaults + to that when the value is 0. In theory the function is an internal helper but + since it's used by our examples some may have used it. (#8946, #8111, #8686) + Other Changes: - Windows: added lower-right resize grip on child windows using both diff --git a/examples/example_glfw_vulkan/main.cpp b/examples/example_glfw_vulkan/main.cpp index ebc78bdd5..176c8c4d3 100644 --- a/examples/example_glfw_vulkan/main.cpp +++ b/examples/example_glfw_vulkan/main.cpp @@ -54,6 +54,7 @@ static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; static ImGui_ImplVulkanH_Window g_MainWindowData; static uint32_t g_MinImageCount = 2; static bool g_SwapChainRebuild = false; +static VkImageUsageFlags g_SwapChainImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; static void glfw_error_callback(int error, const char* description) { @@ -239,7 +240,7 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface // Create SwapChain, RenderPass, Framebuffer, etc. IM_ASSERT(g_MinImageCount >= 2); - ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount); + ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount, g_SwapChainImageUsage); } static void CleanupVulkan() @@ -456,7 +457,7 @@ int main(int, char**) if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height)) { ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount); - ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, &g_MainWindowData, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount); + ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount, g_SwapChainImageUsage); g_MainWindowData.FrameIndex = 0; g_SwapChainRebuild = false; } diff --git a/examples/example_sdl2_vulkan/main.cpp b/examples/example_sdl2_vulkan/main.cpp index 8dd505889..21e892779 100644 --- a/examples/example_sdl2_vulkan/main.cpp +++ b/examples/example_sdl2_vulkan/main.cpp @@ -49,6 +49,7 @@ static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; static ImGui_ImplVulkanH_Window g_MainWindowData; static uint32_t g_MinImageCount = 2; static bool g_SwapChainRebuild = false; +static VkImageUsageFlags g_SwapChainImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; static void check_vk_result(VkResult err) { @@ -230,7 +231,7 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface // Create SwapChain, RenderPass, Framebuffer, etc. IM_ASSERT(g_MinImageCount >= 2); - ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount); + ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount, g_SwapChainImageUsage); } static void CleanupVulkan() @@ -476,7 +477,7 @@ int main(int, char**) if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height)) { ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount); - ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, &g_MainWindowData, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount); + ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount, g_SwapChainImageUsage); g_MainWindowData.FrameIndex = 0; g_SwapChainRebuild = false; } diff --git a/examples/example_sdl3_vulkan/main.cpp b/examples/example_sdl3_vulkan/main.cpp index 060855259..e4cecf210 100644 --- a/examples/example_sdl3_vulkan/main.cpp +++ b/examples/example_sdl3_vulkan/main.cpp @@ -51,6 +51,7 @@ static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; static ImGui_ImplVulkanH_Window g_MainWindowData; static uint32_t g_MinImageCount = 2; static bool g_SwapChainRebuild = false; +static VkImageUsageFlags g_SwapChainImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; static void check_vk_result(VkResult err) { @@ -232,7 +233,7 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface // Create SwapChain, RenderPass, Framebuffer, etc. IM_ASSERT(g_MinImageCount >= 2); - ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount); + ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount, g_SwapChainImageUsage); } static void CleanupVulkan() @@ -478,7 +479,7 @@ int main(int, char**) if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height)) { ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount); - ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, &g_MainWindowData, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount); + ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, fb_height, fb_height, g_MinImageCount, g_SwapChainImageUsage); g_MainWindowData.FrameIndex = 0; g_SwapChainRebuild = false; } diff --git a/examples/example_win32_vulkan/main.cpp b/examples/example_win32_vulkan/main.cpp index 6063437d8..7a68ccbdd 100644 --- a/examples/example_win32_vulkan/main.cpp +++ b/examples/example_win32_vulkan/main.cpp @@ -47,6 +47,7 @@ static VkDescriptorPool g_DescriptorPool = VK_NULL_HANDLE; static ImGui_ImplVulkanH_Window g_MainWindowData; static uint32_t g_MinImageCount = 2; static bool g_SwapChainRebuild = false; +static VkImageUsageFlags g_SwapChainImageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; static void check_vk_result(VkResult err) { @@ -228,7 +229,7 @@ static void SetupVulkanWindow(ImGui_ImplVulkanH_Window* wd, VkSurfaceKHR surface // Create SwapChain, RenderPass, Framebuffer, etc. IM_ASSERT(g_MinImageCount >= 2); - ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount); + ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, wd, g_QueueFamily, g_Allocator, width, height, g_MinImageCount, g_SwapChainImageUsage); } static void CleanupVulkan() @@ -549,7 +550,7 @@ LRESULT WINAPI WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) if (fb_width > 0 && fb_height > 0 && (g_SwapChainRebuild || g_MainWindowData.Width != fb_width || g_MainWindowData.Height != fb_height)) { ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount); - ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, &g_MainWindowData, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount); + ImGui_ImplVulkanH_CreateOrResizeWindow(g_Instance, g_PhysicalDevice, g_Device, &g_MainWindowData, g_QueueFamily, g_Allocator, fb_width, fb_height, g_MinImageCount, g_SwapChainImageUsage); g_MainWindowData.FrameIndex = 0; g_SwapChainRebuild = false; } From cc0a6690bfb5af6ae38723587ec74e120142c67b Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 26 Sep 2025 17:33:32 +0200 Subject: [PATCH 7/9] Backends: Vulkan: minor internal renames/tweaks to reduce further patches. (#8946, #8110, #8111, #8686) --- backends/imgui_impl_vulkan.cpp | 45 +++++++++++++++++----------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 7a8d26362..49ceeef0b 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -1001,22 +1001,22 @@ static VkPipeline ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAlloc dynamic_state.dynamicStateCount = (uint32_t)IM_ARRAYSIZE(dynamic_states); dynamic_state.pDynamicStates = dynamic_states; - VkGraphicsPipelineCreateInfo info = {}; - info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - info.flags = bd->PipelineCreateFlags; - info.stageCount = 2; - info.pStages = stage; - info.pVertexInputState = &vertex_info; - info.pInputAssemblyState = &ia_info; - info.pViewportState = &viewport_info; - info.pRasterizationState = &raster_info; - info.pMultisampleState = &ms_info; - info.pDepthStencilState = &depth_info; - info.pColorBlendState = &blend_info; - info.pDynamicState = &dynamic_state; - info.layout = bd->PipelineLayout; - info.renderPass = renderPass; - info.subpass = subpass; + VkGraphicsPipelineCreateInfo create_info = {}; + create_info.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; + create_info.flags = bd->PipelineCreateFlags; + create_info.stageCount = 2; + create_info.pStages = stage; + create_info.pVertexInputState = &vertex_info; + create_info.pInputAssemblyState = &ia_info; + create_info.pViewportState = &viewport_info; + create_info.pRasterizationState = &raster_info; + create_info.pMultisampleState = &ms_info; + create_info.pDepthStencilState = &depth_info; + create_info.pColorBlendState = &blend_info; + create_info.pDynamicState = &dynamic_state; + create_info.layout = bd->PipelineLayout; + create_info.renderPass = renderPass; + create_info.subpass = subpass; #ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING if (bd->VulkanInitInfo.UseDynamicRendering) @@ -1024,14 +1024,14 @@ static VkPipeline ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAlloc IM_ASSERT(pipeline_rendering_create_info && "PipelineRenderingCreateInfo must not be nullptr when using dynamic rendering"); IM_ASSERT(pipeline_rendering_create_info->sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR && "PipelineRenderingCreateInfo::sType must be VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR"); IM_ASSERT(pipeline_rendering_create_info->pNext == nullptr && "PipelineRenderingCreateInfo::pNext must be nullptr"); - info.pNext = pipeline_rendering_create_info; - info.renderPass = VK_NULL_HANDLE; // Just make sure it's actually nullptr. + create_info.pNext = pipeline_rendering_create_info; + create_info.renderPass = VK_NULL_HANDLE; // Just make sure it's actually nullptr. } #else IM_ASSERT(pipeline_rendering_create_info == nullptr); #endif VkPipeline pipeline; - VkResult err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &info, allocator, &pipeline); + VkResult err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &create_info, allocator, &pipeline); check_vk_result(err); return pipeline; } @@ -1108,11 +1108,11 @@ bool ImGui_ImplVulkan_CreateDeviceObjects() } // Create pipeline - if (v->RenderPass + bool create_main_pipeline = (v->RenderPass != VK_NULL_HANDLE); #ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING - || (v->UseDynamicRendering && v->PipelineRenderingCreateInfo.sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR) + create_main_pipeline |= (v->UseDynamicRendering && v->PipelineRenderingCreateInfo.sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR); #endif - ) + if (create_main_pipeline) { ImGui_ImplVulkan_MainPipelineCreateInfo mp_info = {}; mp_info.RenderPass = v->RenderPass; @@ -1292,6 +1292,7 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info) io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, allowing for large meshes. io.BackendFlags |= ImGuiBackendFlags_RendererHasTextures; // We can honor ImGuiPlatformIO::Textures[] requests during render. + // Sanity checks IM_ASSERT(info->Instance != VK_NULL_HANDLE); IM_ASSERT(info->PhysicalDevice != VK_NULL_HANDLE); IM_ASSERT(info->Device != VK_NULL_HANDLE); From e312b99296336c01b43ca91d42036022c6c20844 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 26 Sep 2025 17:37:42 +0200 Subject: [PATCH 8/9] (Breaking) Backends: Vulkan: renamed ImGui_ImplVulkan_MainPipelineCreateInfo to ImGui_ImplVulkan_PipelineInfo. (#8110, #8111) --- backends/imgui_impl_vulkan.cpp | 5 +++-- backends/imgui_impl_vulkan.h | 4 ++-- docs/CHANGELOG.txt | 3 +++ 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index 49ceeef0b..ecd8b98d2 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -27,6 +27,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-09-26: *BREAKING CHANGE*: renamed ImGui_ImplVulkan_MainPipelineCreateInfo to ImGui_ImplVulkan_PipelineInfo. Introduced very recently so shouldn't affect many users. // 2025-09-26: *BREAKING CHANGE*: helper ImGui_ImplVulkanH_CreateOrResizeWindow() added a VkImageUsageFlags image_usage` argument, default to VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT if 0. // 2025-09-26: Vulkan: Added a way to customize shaders by filling ImGui_ImplVulkan_InitInfo::CustomShaderVertCreateInfo/CustomShaderFragCreateInfo. (#8585) // 2025-09-18: Call platform_io.ClearRendererHandlers() on shutdown. @@ -1114,7 +1115,7 @@ bool ImGui_ImplVulkan_CreateDeviceObjects() #endif if (create_main_pipeline) { - ImGui_ImplVulkan_MainPipelineCreateInfo mp_info = {}; + ImGui_ImplVulkan_PipelineInfo mp_info = {}; mp_info.RenderPass = v->RenderPass; mp_info.Subpass = v->Subpass; mp_info.MSAASamples = v->MSAASamples; @@ -1147,7 +1148,7 @@ bool ImGui_ImplVulkan_CreateDeviceObjects() return true; } -void ImGui_ImplVulkan_CreateMainPipeline(const ImGui_ImplVulkan_MainPipelineCreateInfo& info) +void ImGui_ImplVulkan_CreateMainPipeline(const ImGui_ImplVulkan_PipelineInfo& info) { ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index 62158b7f9..a174e72d5 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -121,7 +121,7 @@ IMGUI_IMPL_API void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_i // (Advanced) Use e.g. if you need to recreate pipeline without reinitializing the backend (see #8110, #8111) // The main window pipeline will be created by ImGui_ImplVulkan_Init() if possible (== RenderPass xor (UseDynamicRendering && PipelineRenderingCreateInfo->sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR)) // Else, the pipeline can be created, or re-created, using ImGui_ImplVulkan_CreateMainPipeline() before rendering. -struct ImGui_ImplVulkan_MainPipelineCreateInfo +struct ImGui_ImplVulkan_PipelineInfo { VkRenderPass RenderPass = VK_NULL_HANDLE; uint32_t Subpass = 0; @@ -130,7 +130,7 @@ struct ImGui_ImplVulkan_MainPipelineCreateInfo VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo; // Optional, valid if .sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR #endif }; -IMGUI_IMPL_API void ImGui_ImplVulkan_CreateMainPipeline(const ImGui_ImplVulkan_MainPipelineCreateInfo& info); // (render_pass xor (p_dynamic_rendering && p_dynamic_rendering is correct (sType and pNext))) +IMGUI_IMPL_API void ImGui_ImplVulkan_CreateMainPipeline(const ImGui_ImplVulkan_PipelineInfo& info); // (render_pass xor (p_dynamic_rendering && p_dynamic_rendering is correct (sType and pNext))) // (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually. IMGUI_IMPL_API void ImGui_ImplVulkan_UpdateTexture(ImTextureData* tex); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 1f6e463f5..912527734 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -41,6 +41,9 @@ HOW TO UPDATE? Breaking Changes: +- Backends: Vulkan: renamed ImGui_ImplVulkan_MainPipelineCreateInfo --> ImGui_ImplVulkan_PipelineInfo + (introduced very recently and only used by `ImGui_ImplVulkan_CreateMainPipeline()` + so it should not affect many users). (#8110, #8111) - Backends: Vulkan: helper ImGui_ImplVulkanH_CreateOrResizeWindow() added a `VkImageUsageFlags image_usage` argument. It was previously hardcoded to `VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT` and defaults From 3470e6112b8bb81059ec461e56385dc91d89dcb7 Mon Sep 17 00:00:00 2001 From: ocornut Date: Fri, 26 Sep 2025 18:23:03 +0200 Subject: [PATCH 9/9] (Breaking) Backends: Vulkan: moved fields in ImGui_ImplVulkan_InitInfo: RenderPass, Subpass, MSAASamples, PipelineRenderingCreateInfo. (#8946, #8110, #8111, #8686) --- backends/imgui_impl_vulkan.cpp | 70 +++++++++++--------------- backends/imgui_impl_vulkan.h | 36 ++++++------- docs/CHANGELOG.txt | 7 +++ examples/example_glfw_vulkan/main.cpp | 6 +-- examples/example_sdl2_vulkan/main.cpp | 6 +-- examples/example_sdl3_vulkan/main.cpp | 6 +-- examples/example_win32_vulkan/main.cpp | 6 +-- imgui.h | 2 +- 8 files changed, 67 insertions(+), 72 deletions(-) diff --git a/backends/imgui_impl_vulkan.cpp b/backends/imgui_impl_vulkan.cpp index ecd8b98d2..60554368e 100644 --- a/backends/imgui_impl_vulkan.cpp +++ b/backends/imgui_impl_vulkan.cpp @@ -27,6 +27,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2025-09-26: *BREAKING CHANGE*: moved some fields in ImGui_ImplVulkan_InitInfo: init_info.RenderPass --> init_info.PipelineInfoMain.RenderPass, init_info.Subpass --> init_info.PipelineInfoMain.Subpass, init_info.MSAASamples --> init_info.PipelineInfoMain.MSAASamples, init_info.PipelineRenderingCreateInfo --> init_info.PipelineInfoMain.PipelineRenderingCreateInfo. // 2025-09-26: *BREAKING CHANGE*: renamed ImGui_ImplVulkan_MainPipelineCreateInfo to ImGui_ImplVulkan_PipelineInfo. Introduced very recently so shouldn't affect many users. // 2025-09-26: *BREAKING CHANGE*: helper ImGui_ImplVulkanH_CreateOrResizeWindow() added a VkImageUsageFlags image_usage` argument, default to VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT if 0. // 2025-09-26: Vulkan: Added a way to customize shaders by filling ImGui_ImplVulkan_InitInfo::CustomShaderVertCreateInfo/CustomShaderFragCreateInfo. (#8585) @@ -918,7 +919,7 @@ static void ImGui_ImplVulkan_CreateShaderModules(VkDevice device, const VkAlloca typedef void VkPipelineRenderingCreateInfoKHR; #endif -static VkPipeline ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationCallbacks* allocator, VkPipelineCache pipelineCache, VkRenderPass renderPass, VkSampleCountFlagBits MSAASamples, uint32_t subpass, const VkPipelineRenderingCreateInfoKHR* pipeline_rendering_create_info) +static VkPipeline ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAllocationCallbacks* allocator, VkPipelineCache pipelineCache, const ImGui_ImplVulkan_PipelineInfo* info) { ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); ImGui_ImplVulkan_CreateShaderModules(device, allocator); @@ -976,7 +977,7 @@ static VkPipeline ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAlloc VkPipelineMultisampleStateCreateInfo ms_info = {}; ms_info.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - ms_info.rasterizationSamples = (MSAASamples != 0) ? MSAASamples : VK_SAMPLE_COUNT_1_BIT; + ms_info.rasterizationSamples = (info->MSAASamples != 0) ? info->MSAASamples : VK_SAMPLE_COUNT_1_BIT; VkPipelineColorBlendAttachmentState color_attachment[1] = {}; color_attachment[0].blendEnable = VK_TRUE; @@ -1016,20 +1017,17 @@ static VkPipeline ImGui_ImplVulkan_CreatePipeline(VkDevice device, const VkAlloc create_info.pColorBlendState = &blend_info; create_info.pDynamicState = &dynamic_state; create_info.layout = bd->PipelineLayout; - create_info.renderPass = renderPass; - create_info.subpass = subpass; + create_info.renderPass = info->RenderPass; + create_info.subpass = info->Subpass; #ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING if (bd->VulkanInitInfo.UseDynamicRendering) { - IM_ASSERT(pipeline_rendering_create_info && "PipelineRenderingCreateInfo must not be nullptr when using dynamic rendering"); - IM_ASSERT(pipeline_rendering_create_info->sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR && "PipelineRenderingCreateInfo::sType must be VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR"); - IM_ASSERT(pipeline_rendering_create_info->pNext == nullptr && "PipelineRenderingCreateInfo::pNext must be nullptr"); - create_info.pNext = pipeline_rendering_create_info; + IM_ASSERT(info->PipelineRenderingCreateInfo.sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR && "PipelineRenderingCreateInfo::sType must be VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR"); + IM_ASSERT(info->PipelineRenderingCreateInfo.pNext == nullptr && "PipelineRenderingCreateInfo::pNext must be nullptr"); + create_info.pNext = &info->PipelineRenderingCreateInfo; create_info.renderPass = VK_NULL_HANDLE; // Just make sure it's actually nullptr. } -#else - IM_ASSERT(pipeline_rendering_create_info == nullptr); #endif VkPipeline pipeline; VkResult err = vkCreateGraphicsPipelines(device, pipelineCache, 1, &create_info, allocator, &pipeline); @@ -1109,21 +1107,12 @@ bool ImGui_ImplVulkan_CreateDeviceObjects() } // Create pipeline - bool create_main_pipeline = (v->RenderPass != VK_NULL_HANDLE); + bool create_main_pipeline = (v->PipelineInfoMain.RenderPass != VK_NULL_HANDLE); #ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING - create_main_pipeline |= (v->UseDynamicRendering && v->PipelineRenderingCreateInfo.sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR); + create_main_pipeline |= (v->UseDynamicRendering && v->PipelineInfoMain.PipelineRenderingCreateInfo.sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR); #endif if (create_main_pipeline) - { - ImGui_ImplVulkan_PipelineInfo mp_info = {}; - mp_info.RenderPass = v->RenderPass; - mp_info.Subpass = v->Subpass; - mp_info.MSAASamples = v->MSAASamples; -#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING - mp_info.PipelineRenderingCreateInfo = v->PipelineRenderingCreateInfo; -#endif - ImGui_ImplVulkan_CreateMainPipeline(mp_info); - } + ImGui_ImplVulkan_CreateMainPipeline(&v->PipelineInfoMain); // Create command pool/buffer for texture upload if (!bd->TexCommandPool) @@ -1148,7 +1137,7 @@ bool ImGui_ImplVulkan_CreateDeviceObjects() return true; } -void ImGui_ImplVulkan_CreateMainPipeline(const ImGui_ImplVulkan_PipelineInfo& info) +void ImGui_ImplVulkan_CreateMainPipeline(const ImGui_ImplVulkan_PipelineInfo* pipeline_info_in) { ImGui_ImplVulkan_Data* bd = ImGui_ImplVulkan_GetBackendData(); ImGui_ImplVulkan_InitInfo* v = &bd->VulkanInitInfo; @@ -1157,28 +1146,23 @@ void ImGui_ImplVulkan_CreateMainPipeline(const ImGui_ImplVulkan_PipelineInfo& in vkDestroyPipeline(v->Device, bd->Pipeline, v->Allocator); bd->Pipeline = VK_NULL_HANDLE; } - v->RenderPass = info.RenderPass; - v->MSAASamples = info.MSAASamples; - v->Subpass = info.Subpass; + ImGui_ImplVulkan_PipelineInfo* pipeline_info = &v->PipelineInfoMain; + if (pipeline_info != pipeline_info_in) + *pipeline_info = *pipeline_info_in; - const VkPipelineRenderingCreateInfoKHR* pipeline_rendering_create_info = nullptr; #ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING - if (v->UseDynamicRendering) + VkPipelineRenderingCreateInfoKHR* pipeline_rendering_create_info = &pipeline_info->PipelineRenderingCreateInfo; + if (v->UseDynamicRendering && pipeline_rendering_create_info->pColorAttachmentFormats != NULL) { - v->PipelineRenderingCreateInfo = info.PipelineRenderingCreateInfo; - pipeline_rendering_create_info = &v->PipelineRenderingCreateInfo; - if (v->PipelineRenderingCreateInfo.pColorAttachmentFormats != NULL) - { - // Deep copy buffer to reduce error-rate for end user (#8282) - ImVector formats; - formats.resize((int)v->PipelineRenderingCreateInfo.colorAttachmentCount); - memcpy(formats.Data, v->PipelineRenderingCreateInfo.pColorAttachmentFormats, (size_t)formats.size_in_bytes()); - formats.swap(bd->PipelineRenderingCreateInfoColorAttachmentFormats); - v->PipelineRenderingCreateInfo.pColorAttachmentFormats = bd->PipelineRenderingCreateInfoColorAttachmentFormats.Data; - } + // Deep copy buffer to reduce error-rate for end user (#8282) + ImVector formats; + formats.resize((int)pipeline_rendering_create_info->colorAttachmentCount); + memcpy(formats.Data, pipeline_rendering_create_info->pColorAttachmentFormats, (size_t)formats.size_in_bytes()); + formats.swap(bd->PipelineRenderingCreateInfoColorAttachmentFormats); + pipeline_rendering_create_info->pColorAttachmentFormats = bd->PipelineRenderingCreateInfoColorAttachmentFormats.Data; } #endif - bd->Pipeline = ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, v->PipelineCache, v->RenderPass, v->MSAASamples, v->Subpass, pipeline_rendering_create_info); + bd->Pipeline = ImGui_ImplVulkan_CreatePipeline(v->Device, v->Allocator, v->PipelineCache, pipeline_info); } void ImGui_ImplVulkan_DestroyDeviceObjects() @@ -1298,12 +1282,14 @@ bool ImGui_ImplVulkan_Init(ImGui_ImplVulkan_InitInfo* info) IM_ASSERT(info->PhysicalDevice != VK_NULL_HANDLE); IM_ASSERT(info->Device != VK_NULL_HANDLE); IM_ASSERT(info->Queue != VK_NULL_HANDLE); + IM_ASSERT(info->MinImageCount >= 2); + IM_ASSERT(info->ImageCount >= info->MinImageCount); if (info->DescriptorPool != VK_NULL_HANDLE) // Either DescriptorPool or DescriptorPoolSize must be set, not both! IM_ASSERT(info->DescriptorPoolSize == 0); else IM_ASSERT(info->DescriptorPoolSize > 0); - IM_ASSERT(info->MinImageCount >= 2); - IM_ASSERT(info->ImageCount >= info->MinImageCount); + if (info->UseDynamicRendering) + IM_ASSERT(info->PipelineInfoMain.RenderPass == VK_NULL_HANDLE); bd->VulkanInitInfo = *info; diff --git a/backends/imgui_impl_vulkan.h b/backends/imgui_impl_vulkan.h index a174e72d5..afc698701 100644 --- a/backends/imgui_impl_vulkan.h +++ b/backends/imgui_impl_vulkan.h @@ -65,6 +65,18 @@ // Backend uses a small number of descriptors per font atlas + as many as additional calls done to ImGui_ImplVulkan_AddTexture(). #define IMGUI_IMPL_VULKAN_MINIMUM_IMAGE_SAMPLER_POOL_SIZE (8) // Minimum per atlas +// Specify settings to create pipeline and swapchain +struct ImGui_ImplVulkan_PipelineInfo +{ + // For Main and Secondary viewports + VkRenderPass RenderPass; // Ignored if using dynamic rendering + uint32_t Subpass; // + VkSampleCountFlagBits MSAASamples = {}; // 0 defaults to VK_SAMPLE_COUNT_1_BIT +#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING + VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo; // Optional, valid if .sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR +#endif +}; + // Initialization data, for ImGui_ImplVulkan_Init() // [Please zero-clear before use!] // - About descriptor pool: @@ -88,16 +100,15 @@ struct ImGui_ImplVulkan_InitInfo VkPipelineCache PipelineCache; // Optional // Pipeline - VkRenderPass RenderPass; // Ignored if using dynamic rendering - uint32_t Subpass; - VkSampleCountFlagBits MSAASamples; // 0 defaults to VK_SAMPLE_COUNT_1_BIT + ImGui_ImplVulkan_PipelineInfo PipelineInfoMain; // Infos for Main Viewport (created by app/user) + //VkRenderPass RenderPass; // --> Since 2025/09/26: set 'PipelineInfoMain.RenderPass' instead + //uint32_t Subpass; // --> Since 2025/09/26: set 'PipelineInfoMain.Subpass' instead + //VkSampleCountFlagBits MSAASamples; // --> Since 2025/09/26: set 'PipelineInfoMain.MSAASamples' instead + //VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo; // Since 2025/09/26: set 'PipelineInfoMain.PipelineRenderingCreateInfo' instead // (Optional) Dynamic Rendering - // Need to explicitly enable VK_KHR_dynamic_rendering extension to use this, even for Vulkan 1.3 + setup PipelineRenderingCreateInfo. + // Need to explicitly enable VK_KHR_dynamic_rendering extension to use this, even for Vulkan 1.3 + setup PipelineInfoMain.PipelineRenderingCreateInfo. bool UseDynamicRendering; -#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING - VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo; // Optional, valid if .sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR -#endif // (Optional) Allocation, Debugging const VkAllocationCallbacks* Allocator; @@ -121,16 +132,7 @@ IMGUI_IMPL_API void ImGui_ImplVulkan_SetMinImageCount(uint32_t min_i // (Advanced) Use e.g. if you need to recreate pipeline without reinitializing the backend (see #8110, #8111) // The main window pipeline will be created by ImGui_ImplVulkan_Init() if possible (== RenderPass xor (UseDynamicRendering && PipelineRenderingCreateInfo->sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR)) // Else, the pipeline can be created, or re-created, using ImGui_ImplVulkan_CreateMainPipeline() before rendering. -struct ImGui_ImplVulkan_PipelineInfo -{ - VkRenderPass RenderPass = VK_NULL_HANDLE; - uint32_t Subpass = 0; - VkSampleCountFlagBits MSAASamples = {}; -#ifdef IMGUI_IMPL_VULKAN_HAS_DYNAMIC_RENDERING - VkPipelineRenderingCreateInfoKHR PipelineRenderingCreateInfo; // Optional, valid if .sType == VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR -#endif -}; -IMGUI_IMPL_API void ImGui_ImplVulkan_CreateMainPipeline(const ImGui_ImplVulkan_PipelineInfo& info); // (render_pass xor (p_dynamic_rendering && p_dynamic_rendering is correct (sType and pNext))) +IMGUI_IMPL_API void ImGui_ImplVulkan_CreateMainPipeline(const ImGui_ImplVulkan_PipelineInfo* info); // (Advanced) Use e.g. if you need to precisely control the timing of texture updates (e.g. for staged rendering), by setting ImDrawData::Textures = NULL to handle this manually. IMGUI_IMPL_API void ImGui_ImplVulkan_UpdateTexture(ImTextureData* tex); diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 912527734..08337ee5c 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -41,6 +41,13 @@ HOW TO UPDATE? Breaking Changes: +- Backends: Vulkan: moved some fields in ImGui_ImplVulkan_InitInfo: + init_info.RenderPass --> init_info.PipelineInfoMain.RenderPass + init_info.Subpass --> init_info.PipelineInfoMain.Subpass + init_info.MSAASamples --> init_info.PipelineInfoMain.MSAASamples + init_info.PipelineRenderingCreateInfo --> init_info.PipelineInfoMain.PipelineRenderingCreateInfo + It makes things more consistent and was desirable to introduce new settings for + secondary viewports. (#8946, #8110, #8111, #8686) [@ocornut, @SuperRonan, @sylmroz] - Backends: Vulkan: renamed ImGui_ImplVulkan_MainPipelineCreateInfo --> ImGui_ImplVulkan_PipelineInfo (introduced very recently and only used by `ImGui_ImplVulkan_CreateMainPipeline()` so it should not affect many users). (#8110, #8111) diff --git a/examples/example_glfw_vulkan/main.cpp b/examples/example_glfw_vulkan/main.cpp index 176c8c4d3..d9cbfb787 100644 --- a/examples/example_glfw_vulkan/main.cpp +++ b/examples/example_glfw_vulkan/main.cpp @@ -411,12 +411,12 @@ int main(int, char**) init_info.Queue = g_Queue; init_info.PipelineCache = g_PipelineCache; init_info.DescriptorPool = g_DescriptorPool; - init_info.RenderPass = wd->RenderPass; - init_info.Subpass = 0; init_info.MinImageCount = g_MinImageCount; init_info.ImageCount = wd->ImageCount; - init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; init_info.Allocator = g_Allocator; + init_info.PipelineInfoMain.RenderPass = wd->RenderPass; + init_info.PipelineInfoMain.Subpass = 0; + init_info.PipelineInfoMain.MSAASamples = VK_SAMPLE_COUNT_1_BIT; init_info.CheckVkResultFn = check_vk_result; ImGui_ImplVulkan_Init(&init_info); diff --git a/examples/example_sdl2_vulkan/main.cpp b/examples/example_sdl2_vulkan/main.cpp index 21e892779..fd845373d 100644 --- a/examples/example_sdl2_vulkan/main.cpp +++ b/examples/example_sdl2_vulkan/main.cpp @@ -417,12 +417,12 @@ int main(int, char**) init_info.Queue = g_Queue; init_info.PipelineCache = g_PipelineCache; init_info.DescriptorPool = g_DescriptorPool; - init_info.RenderPass = wd->RenderPass; - init_info.Subpass = 0; init_info.MinImageCount = g_MinImageCount; init_info.ImageCount = wd->ImageCount; - init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; init_info.Allocator = g_Allocator; + init_info.PipelineInfoMain.RenderPass = wd->RenderPass; + init_info.PipelineInfoMain.Subpass = 0; + init_info.PipelineInfoMain.MSAASamples = VK_SAMPLE_COUNT_1_BIT; init_info.CheckVkResultFn = check_vk_result; ImGui_ImplVulkan_Init(&init_info); diff --git a/examples/example_sdl3_vulkan/main.cpp b/examples/example_sdl3_vulkan/main.cpp index e4cecf210..6f67e990d 100644 --- a/examples/example_sdl3_vulkan/main.cpp +++ b/examples/example_sdl3_vulkan/main.cpp @@ -416,12 +416,12 @@ int main(int, char**) init_info.Queue = g_Queue; init_info.PipelineCache = g_PipelineCache; init_info.DescriptorPool = g_DescriptorPool; - init_info.RenderPass = wd->RenderPass; - init_info.Subpass = 0; init_info.MinImageCount = g_MinImageCount; init_info.ImageCount = wd->ImageCount; - init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; init_info.Allocator = g_Allocator; + init_info.PipelineInfoMain.RenderPass = wd->RenderPass; + init_info.PipelineInfoMain.Subpass = 0; + init_info.PipelineInfoMain.MSAASamples = VK_SAMPLE_COUNT_1_BIT; init_info.CheckVkResultFn = check_vk_result; ImGui_ImplVulkan_Init(&init_info); diff --git a/examples/example_win32_vulkan/main.cpp b/examples/example_win32_vulkan/main.cpp index 7a68ccbdd..cdf4a247e 100644 --- a/examples/example_win32_vulkan/main.cpp +++ b/examples/example_win32_vulkan/main.cpp @@ -404,12 +404,12 @@ int main(int, char**) init_info.Queue = g_Queue; init_info.PipelineCache = g_PipelineCache; init_info.DescriptorPool = g_DescriptorPool; - init_info.RenderPass = wd->RenderPass; - init_info.Subpass = 0; init_info.MinImageCount = g_MinImageCount; init_info.ImageCount = wd->ImageCount; - init_info.MSAASamples = VK_SAMPLE_COUNT_1_BIT; init_info.Allocator = g_Allocator; + init_info.PipelineInfoMain.RenderPass = wd->RenderPass; + init_info.PipelineInfoMain.Subpass = 0; + init_info.PipelineInfoMain.MSAASamples = VK_SAMPLE_COUNT_1_BIT; init_info.CheckVkResultFn = check_vk_result; ImGui_ImplVulkan_Init(&init_info); diff --git a/imgui.h b/imgui.h index f04e8c0e4..7d71480b8 100644 --- a/imgui.h +++ b/imgui.h @@ -29,7 +29,7 @@ // Library Version // (Integer encoded as XYYZZ for use in #if preprocessor conditionals, e.g. '#if IMGUI_VERSION_NUM >= 12345') #define IMGUI_VERSION "1.92.4 WIP" -#define IMGUI_VERSION_NUM 19232 +#define IMGUI_VERSION_NUM 19233 #define IMGUI_HAS_TABLE // Added BeginTable() - from IMGUI_VERSION_NUM >= 18000 #define IMGUI_HAS_TEXTURES // Added ImGuiBackendFlags_RendererHasTextures - from IMGUI_VERSION_NUM >= 19198