ImGui about:
Dear ImGui 1.70 WIP (16990)
--------------------------------
sizeof(size_t): 4, sizeof(ImDrawIdx): 2, sizeof(ImDrawVert): 20
define: __cplusplus=199711
define: _WIN32
define: _MSC_VER=1916
define: IMGUI_HAS_VIEWPORT
define: IMGUI_HAS_DOCK
--------------------------------
io.BackendPlatformName: imgui_impl_sdl
io.BackendRendererName: imgui_impl_vulkan
io.ConfigFlags: 0x00000441
NavEnableKeyboard
DockingEnable
ViewportsEnable
io.ConfigViewportsNoDecoration
io.ConfigInputTextCursorBlink
io.ConfigWindowsResizeFromEdges
io.BackendFlags: 0x00001402
HasMouseCursors
PlatformHasViewports
RendererHasViewports
--------------------------------
io.Fonts: 1 fonts, Flags: 0x00000000, TexSize: 512,64
io.DisplaySize: 1280.00,720.00
io.DisplayFramebufferScale: 1.00,1.00
--------------------------------
style.WindowPadding: 8.00,8.00
style.WindowBorderSize: 1.00
style.FramePadding: 4.00,3.00
style.FrameRounding: 0.00
style.FrameBorderSize: 0.00
style.ItemSpacing: 8.00,4.00
style.ItemInnerSpacing: 4.00,4.00
Compiler: Visual Studio 2017
Operating System: Windows 10
My Issue/Question:
The vulkan renderer is
XXX _(please provide as much context as possible)_
Screenshots/Video
XXX _(you can drag files here)_
Standalone, minimal, complete and verifiable example:
Run the example_sdk_vulkan sample after having set the imgui.ini to this:
[Window][Debug##Default]
Pos=60,60
Size=400,400
Collapsed=0
[Window][ImGui Demo]
ViewportPos=32,381
ViewportId=0x080FC883
Size=550,680
Collapsed=0
[Window][Hello, world!]
ViewportPos=2062,443
ViewportId=0xEBE6C6E6
Size=345,180
Collapsed=0
[Docking][Data]
Place a breakpoint on the fprintf , (or change to an assert; that's how I found it):
#ifdef IMGUI_VULKAN_DEBUG_REPORT
static VKAPI_ATTR VkBool32 VKAPI_CALL debug_report(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData)
{
(void)flags; (void)object; (void)location; (void)messageCode; (void)pUserData; (void)pLayerPrefix; // Unused arguments
fprintf(stderr, "[vulkan] ObjectType: %i\nMessage: %s\n\n", objectType, pMessage);
return VK_FALSE;
}
Select the "Hello World" window that's off the right side of the main window, and drag it back into the main window.
You'll get an the following debug error:
[ VUID-vkDestroyBuffer-buffer-00922 ] Object: 0x46 (Type = 9) | Cannot free buffer 0x46 that is in use by a command buffer. The Vulkan spec states: All submitted commands that refer to buffer, either directly or via a VkBufferView, must have completed execution (https://www.khronos.org/registry/vulkan/specs/1.1-extensions/html/vkspec.html#VUID-vkDestroyBuffer-buffer-00922)
This is a known issue, those buffers need to be moved into a per-viewport structure, or the number of g_FramesDataBuffers in imgui_impl_vulkan.cpp needs to be number of max inflight backbuffer X number of viewports.
Will address it soonish.
Hello @eddieparker
I think those issues are fixed in this branch:
https://github.com/ocornut/imgui/tree/vulkan_fix_docking
Would you mind giving it a test?
In particular, maybe try to go back and forth between docking and vulkan_fix_docking to make sure you can reliably repro in one and not in the other.
Thank you!
Hello @ocornut:
Looks like that fixes that error. But now if I resize a window that's floating outside of the main window I get:
[ UNASSIGNED-GeneralParameterError-RequiredParameter ] Object: VK_NULL_HANDLE (Type = 0) | vkWaitForFences: required parameter pFences[0] specified as VK_NULL_HANDLE.
It looks as though the resize event causes a DestroyFrame() (UpdatePlatformWindows->CreateWindowSwapChain->DestroyFrame) which nullifies the fence. Then a bunch of other code tries to use the fence and it breaks. Null guarding the other places seems to eventually lead to an exception in SwapBuffers; so I'm assuming that's not the right answer either. :)
@eddieparker : Thanks for testing. I've pushed a handful of new changes, if you want to try again!
That seems to fix the Vulkan crashes! Thanks!
Here's a couple of other things I've noticed that probably aren't Vulkan related: I can file different bugs if you prefer though:
If I drag the ImGui demo window out of the main pane and try to close the main windows GUI window, it fails until I close the ImGui Demo window.
If you apply this code to main [1] and:
Anyhow; thanks for the Vulkan fixes!
[1] Replacement for the main function to show the issue
int main(int, char**)
{
// Setup SDL
if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) != 0)
{
printf("Error: %s\n", SDL_GetError());
return 1;
}
// Setup window
SDL_DisplayMode current;
SDL_GetCurrentDisplayMode(0, ¤t);
SDL_WindowFlags window_flags = (SDL_WindowFlags)(SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI);
SDL_Window* window = SDL_CreateWindow("Dear ImGui SDL2+Vulkan example", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 1280, 720, window_flags);
// Setup Vulkan
uint32_t extensions_count = 0;
SDL_Vulkan_GetInstanceExtensions(window, &extensions_count, NULL);
const char** extensions = new const char*[extensions_count];
SDL_Vulkan_GetInstanceExtensions(window, &extensions_count, extensions);
SetupVulkan(extensions, extensions_count);
delete[] extensions;
// Create Window Surface
VkSurfaceKHR surface;
VkResult err;
if (SDL_Vulkan_CreateSurface(window, g_Instance, &surface) == 0)
{
printf("Failed to create Vulkan surface.\n");
return 1;
}
// Create Framebuffers
int w, h;
SDL_GetWindowSize(window, &w, &h);
ImGui_ImplVulkanH_Window* wd = &g_WindowData;
SetupVulkanWindow(wd, surface, w, h);
// Setup Dear ImGui context
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
//io.ConfigFlags |= ImGuiConfigFlags_ViewportsNoTaskBarIcons;
//io.ConfigFlags |= ImGuiConfigFlags_ViewportsNoMerge;
// Setup Dear ImGui style
ImGui::StyleColorsDark();
//ImGui::StyleColorsClassic();
// When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones.
ImGuiStyle& style = ImGui::GetStyle();
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
style.WindowRounding = 0.0f;
style.Colors[ImGuiCol_WindowBg].w = 1.0f;
}
// Setup Platform/Renderer bindings
ImGui_ImplSDL2_InitForVulkan(window);
ImGui_ImplVulkan_InitInfo init_info = {};
init_info.Instance = g_Instance;
init_info.PhysicalDevice = g_PhysicalDevice;
init_info.Device = g_Device;
init_info.QueueFamily = g_QueueFamily;
init_info.Queue = g_Queue;
init_info.PipelineCache = g_PipelineCache;
init_info.DescriptorPool = g_DescriptorPool;
init_info.Allocator = g_Allocator;
init_info.MinImageCount = g_MinImageCount;
init_info.ImageCount = wd->ImageCount;
init_info.CheckVkResultFn = check_vk_result;
ImGui_ImplVulkan_Init(&init_info, wd->RenderPass);
// Load Fonts
// - If no fonts are loaded, dear imgui will use the default font. You can also load multiple fonts and use ImGui::PushFont()/PopFont() to select them.
// - AddFontFromFileTTF() will return the ImFont* so you can store it if you need to select the font among multiple.
// - If the file cannot be loaded, the function will return NULL. Please handle those errors in your application (e.g. use an assertion, or display an error and quit).
// - The fonts will be rasterized at a given size (w/ oversampling) and stored into a texture when calling ImFontAtlas::Build()/GetTexDataAsXXXX(), which ImGui_ImplXXXX_NewFrame below will call.
// - Read 'misc/fonts/README.txt' for more instructions and details.
// - Remember that in C/C++ if you want to include a backslash \ in a string literal you need to write a double backslash \\ !
//io.Fonts->AddFontDefault();
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Roboto-Medium.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/Cousine-Regular.ttf", 15.0f);
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/DroidSans.ttf", 16.0f);
//io.Fonts->AddFontFromFileTTF("../../misc/fonts/ProggyTiny.ttf", 10.0f);
//ImFont* font = io.Fonts->AddFontFromFileTTF("c:\\Windows\\Fonts\\ArialUni.ttf", 18.0f, NULL, io.Fonts->GetGlyphRangesJapanese());
//IM_ASSERT(font != NULL);
// Upload Fonts
{
// Use any command queue
VkCommandPool command_pool = wd->Frames[wd->FrameIndex].CommandPool;
VkCommandBuffer command_buffer = wd->Frames[wd->FrameIndex].CommandBuffer;
err = vkResetCommandPool(g_Device, command_pool, 0);
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);
ImGui_ImplVulkan_CreateFontsTexture(command_buffer);
VkSubmitInfo end_info = {};
end_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
end_info.commandBufferCount = 1;
end_info.pCommandBuffers = &command_buffer;
err = vkEndCommandBuffer(command_buffer);
check_vk_result(err);
err = vkQueueSubmit(g_Queue, 1, &end_info, VK_NULL_HANDLE);
check_vk_result(err);
err = vkDeviceWaitIdle(g_Device);
check_vk_result(err);
ImGui_ImplVulkan_DestroyFontUploadObjects();
}
bool show_demo_window = true;
bool show_another_window = false;
ImVec4 clear_color = ImVec4(0.45f, 0.55f, 0.60f, 1.00f);
bool m_bShowDemoWindow = false;
// Main loop
bool done = false;
while (!done)
{
// Poll and handle events (inputs, window resize, etc.)
// You can read the io.WantCaptureMouse, io.WantCaptureKeyboard flags to tell if dear imgui wants to use your inputs.
// - When io.WantCaptureMouse is true, do not dispatch mouse input data to your main application.
// - When io.WantCaptureKeyboard is true, do not dispatch keyboard input data to your main application.
// Generally you may always pass all inputs to dear imgui, and hide them from your application based on those two flags.
SDL_Event event;
while (SDL_PollEvent(&event))
{
ImGui_ImplSDL2_ProcessEvent(&event);
if (event.type == SDL_QUIT)
done = true;
if (event.type == SDL_WINDOWEVENT && event.window.event == SDL_WINDOWEVENT_RESIZED && event.window.windowID == SDL_GetWindowID(window))
{
g_SwapChainResizeWidth = (int)event.window.data1;
g_SwapChainResizeHeight = (int)event.window.data2;
g_SwapChainRebuild = true;
}
}
if (g_SwapChainRebuild)
{
g_SwapChainRebuild = false;
ImGui_ImplVulkan_SetMinImageCount(g_MinImageCount);
ImGui_ImplVulkanH_CreateWindow(g_Instance, g_PhysicalDevice, g_Device, &g_WindowData, g_QueueFamily, g_Allocator, g_SwapChainResizeWidth, g_SwapChainResizeHeight, g_MinImageCount);
g_WindowData.FrameIndex = 0;
}
// Start the Dear ImGui frame
ImGui_ImplVulkan_NewFrame();
ImGui_ImplSDL2_NewFrame(window);
ImGui::NewFrame();
{
int nX, nY;
SDL_GetWindowPosition( window, &nX, &nY );
int nWidth, nHeight;
SDL_GetWindowSize( window, &nWidth, &nHeight );
//IntVector2D vPos0 = pRenderer->GetMainWindow()->GetPosition();
ImGui::SetNextWindowPos( ImVec2( (float)nX, (float)nY ), ImGuiCond_Always );
ImGui::SetNextWindowSize( ImVec2( (float)nWidth, (float)nHeight ), ImGuiSetCond_Always );
if ( ImGui::Begin(
"Editor",
/*p_open=*/nullptr,
ImGuiWindowFlags_MenuBar |
ImGuiWindowFlags_NoResize |
ImGuiWindowFlags_NoMove |
ImGuiWindowFlags_NoCollapse
)
)
{
if ( ImGui::BeginMenuBar() )
{
if ( ImGui::BeginMenu( "File" ) )
{
if ( ImGui::MenuItem( "New map" ) )
{
}
if ( ImGui::MenuItem( "Load map..." ) )
{
}
if ( ImGui::MenuItem( "Save map" ) )
{
}
if ( ImGui::MenuItem( "Save map as..." ) )
{
}
if ( ImGui::MenuItem( "Exit" ) )
{
}
ImGui::EndMenu();
}
if ( ImGui::BeginMenu( "Windows" ) )
{
ImGui::Checkbox( "ImGui Demo Window", &m_bShowDemoWindow );
ImGui::EndMenu();
}
}
ImGui::EndMenuBar();
if ( m_bShowDemoWindow )
{
ImGui::ShowDemoWindow();
}
}
ImGui::End();
}
// Rendering
ImGui::Render();
memcpy(&wd->ClearValue.color.float32[0], &clear_color, 4 * sizeof(float));
FrameRender(wd);
// Update and Render additional Platform Windows
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
ImGui::UpdatePlatformWindows();
ImGui::RenderPlatformWindowsDefault();
}
FramePresent(wd);
}
// Cleanup
err = vkDeviceWaitIdle(g_Device);
check_vk_result(err);
ImGui_ImplVulkan_Shutdown();
ImGui_ImplSDL2_Shutdown();
ImGui::DestroyContext();
CleanupVulkanWindow();
CleanupVulkan();
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
I can file different bugs if you prefer though:
Please do!
If I drag the ImGui demo window out of the main pane and try to close the main windows GUI window, it fails until I close the ImGui Demo window.
I think it may be an issue with SDL event handling.
Replacement for the main function to show the issue
Is the whole thing needed and has been changed? Or just the inner block? If only the inner block is new/changed please paste only this section so I don't have to consider the whole main.cpp file. Thanks!
OK, I'll write them up as separate bugs.
As for your second question: no, the whole thing isn't needed, I just assumed it'd be easier to overwrite the whole main function to repro. All that I added was a bool called m_bShowDemoWindow and this code:
{
int nX, nY;
SDL_GetWindowPosition( window, &nX, &nY );
int nWidth, nHeight;
SDL_GetWindowSize( window, &nWidth, &nHeight );
//IntVector2D vPos0 = pRenderer->GetMainWindow()->GetPosition();
ImGui::SetNextWindowPos( ImVec2( (float)nX, (float)nY ), ImGuiCond_Always );
ImGui::SetNextWindowSize( ImVec2( (float)nWidth, (float)nHeight ), ImGuiSetCond_Always );
if ( ImGui::Begin(
"Editor",
/*p_open=*/nullptr,
ImGuiWindowFlags_MenuBar |
ImGuiWindowFlags_NoResize |
ImGuiWindowFlags_NoMove |
ImGuiWindowFlags_NoCollapse
)
)
{
if ( ImGui::BeginMenuBar() )
{
if ( ImGui::BeginMenu( "File" ) )
{
if ( ImGui::MenuItem( "New map" ) )
{
}
if ( ImGui::MenuItem( "Load map..." ) )
{
}
if ( ImGui::MenuItem( "Save map" ) )
{
}
if ( ImGui::MenuItem( "Save map as..." ) )
{
}
if ( ImGui::MenuItem( "Exit" ) )
{
}
ImGui::EndMenu();
}
if ( ImGui::BeginMenu( "Windows" ) )
{
ImGui::Checkbox( "ImGui Demo Window", &m_bShowDemoWindow );
ImGui::EndMenu();
}
}
ImGui::EndMenuBar();
if ( m_bShowDemoWindow )
{
ImGui::ShowDemoWindow();
}
}
ImGui::End();
}
Ah.
You want to use the ImGuiWindowFlags_NoBringToFrontOnFocus flag on your fullscreen window.
You should also use ImGuiViewport* viewport = ImGui::GetMainViewport() then viewport->Pos, viewport->Size so your code doesn't have to call more SDL functions.
Fantastic; thanks ocornut! That seems to solve everything. I'm going to close this issue - thanks for your help!
Will close when the Vulkan changes are actually merged in master+docking, at the moment there鈥檚 a few questions still up in the air in the other threads.
Merged now!