imgui icon indicating copy to clipboard operation
imgui copied to clipboard

GLFW Vulkan crash on selecting rows

Open cursedastronaut opened this issue 9 months ago • 3 comments

Version/Branch of Dear ImGui:

Version 1.91.9b, Branch: master AS OF cdb5cbe6f8786ced227624a71bc8a677618e5327

Back-ends:

imgui_impl_glfw.cpp + imgui_impl_vulkan.cpp

Compiler, OS:

GCC + Linux

Full config/build information:

Dear ImGui 1.92.0 WIP (19196)
--------------------------------
sizeof(size_t): 8, sizeof(ImDrawIdx): 2, sizeof(ImDrawVert): 20
define: __cplusplus=201103
define: __linux__
define: __GNUC__=15
--------------------------------
io.BackendPlatformName: imgui_impl_glfw (3400)
io.BackendRendererName: imgui_impl_vulkan
io.ConfigFlags: 0x00000003
 NavEnableKeyboard
 NavEnableGamepad
io.ConfigNavCaptureKeyboard
io.ConfigInputTextCursorBlink
io.ConfigWindowsResizeFromEdges
io.ConfigMemoryCompactTimer = 60.0
io.BackendFlags: 0x0000000E
 HasMouseCursors
 HasSetMousePos
 RendererHasVtxOffset
--------------------------------
io.Fonts: 1 fonts, Flags: 0x00000000, TexSize: 512,64
io.DisplaySize: 1269.00,1551.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

Details:

My Issue/Question: I have a table with multiple columns, and multiple rows that are based on imported filenames. When I select a row, the function FrameRender in main.cpp segfaults. It segfaults on line

VkResult err = vkAcquireNextImageKHR(g_Device, wd->Swapchain, UINT64_MAX, image_acquired_semaphore, VK_NULL_HANDLE, &wd->FrameIndex);

My table implementation (I put a more reproduceable one beneath):

void UserInterface::drawFileTable() {
	bool temp = true;
	ImGui::Begin("File Table", &temp, ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove);
	ImGui::SetWindowPos(ImVec2(informationBayWidth, mainMenuBarHeight));
	ImGui::SetWindowSize(
		ImVec2(
			ImGui::GetIO().DisplaySize.x - informationBayWidth,
			ImGui::GetIO().DisplaySize.y - mainMenuBarHeight
		)
	);
	ImGui::BeginTable("##file_table", 12,
		ImGuiTableFlags_NoSavedSettings |
		ImGuiTableFlags_BordersH |
		ImGuiTableFlags_RowBg |                     // alternating row colors
		ImGuiTableFlags_Resizable |
		ImGuiTableFlags_ScrollY);                   // if you want scroll
	
	// Header
	ImGui::TableNextRow();
	ImGui::TableNextColumn(); ImGui::Text("Filename");
	ImGui::TableNextColumn(); ImGui::Text("Path");
	ImGui::TableNextColumn(); ImGui::Text("Title");
	ImGui::TableNextColumn(); ImGui::Text("Artist");
	ImGui::TableNextColumn(); ImGui::Text("Album Artist");
	ImGui::TableNextColumn(); ImGui::Text("Album");
	ImGui::TableNextColumn(); ImGui::Text("Track");
	ImGui::TableNextColumn(); ImGui::Text("Discnumber");
	ImGui::TableNextColumn(); ImGui::Text("Year");
	ImGui::TableNextColumn(); ImGui::Text("Genre");
	ImGui::TableNextColumn(); ImGui::Text("Comment");
	ImGui::TableNextColumn(); ImGui::Text("Codec");
	
	// Body
	for (size_t i = 0; i < tracks.size(); ++i) {
		ImGui::TableNextRow();
		ImGui::TableNextColumn();
	
		std::string filename = tracks[i].getPath().filename().string();
		std::string parent = tracks[i].getPath().parent_path().string();
		std::string title = tracks[i].getTitle();
		std::string artist = tracks[i].getArtist();
		std::string albumArtist = tracks[i].getAlbumArtist();
		std::string album = tracks[i].getAlbum();
		std::string genre = tracks[i].getGenre();
		std::string comment = tracks[i].getComment();
	
		std::string label = "##row_select_" + std::to_string(i);
//selectedRows is an std::set<size_t>
		bool isSelected = selectedRows.count(i) > 0;
	
		if (ImGui::Selectable(label.c_str(), isSelected, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowDoubleClick)) {
			if (ImGui::GetIO().KeyCtrl) {
				if (isSelected)
					selectedRows.erase(i);
				else
					selectedRows.insert(i);
			} else {
				selectedRows.clear();
				selectedRows.insert(i);
			}
		}
	
		ImGui::SameLine();
		ImGui::TextUnformatted(filename.c_str());
	
		ImGui::TableNextColumn(); ImGui::TextUnformatted(parent.c_str());
		ImGui::TableNextColumn(); ImGui::TextUnformatted(title.c_str());
		ImGui::TableNextColumn(); ImGui::TextUnformatted(artist.c_str());
		ImGui::TableNextColumn(); ImGui::TextUnformatted(albumArtist.c_str());
		ImGui::TableNextColumn(); ImGui::TextUnformatted(album.c_str());
		ImGui::TableNextColumn(); ImGui::Text("%u", tracks[i].getNumber());
		ImGui::TableNextColumn(); ImGui::Text("%u", tracks[i].getDiscNumber());
		ImGui::TableNextColumn(); ImGui::Text("%u", tracks[i].getYear());
		ImGui::TableNextColumn(); ImGui::TextUnformatted(genre.c_str());
		ImGui::TableNextColumn(); ImGui::TextUnformatted(comment.c_str());
		ImGui::TableNextColumn(); ImGui::Text("TO_IMPLEMENT");
	}
	
	ImGui::EndTable();
	ImGui::End();
}

I am unable to pinpoint what exactly causes this. I do not know if it is an error on my part or a bug within ImGui.

XXX (please provide as much context as possible)

Screenshots/Video:

https://github.com/user-attachments/assets/aa85a502-f7f9-424c-8322-20e1d93a7aba

Minimal, Complete and Verifiable Example code:

std::set<size_t> selectedRows;
bool temp = true;
ImGui::Begin("File Table", &temp, ImGuiWindowFlags_AlwaysUseWindowPadding | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoSavedSettings | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoMove);
ImGui::SetWindowPos(ImVec2(0, 0));
ImGui::SetWindowSize(
ImVec2(
	ImGui::GetIO().DisplaySize.x - informationBayWidth,
	ImGui::GetIO().DisplaySize.y - mainMenuBarHeight
)
);
ImGui::BeginTable("##file_table", 12,
ImGuiTableFlags_NoSavedSettings |
ImGuiTableFlags_BordersH |
ImGuiTableFlags_RowBg | 
ImGuiTableFlags_Resizable |
ImGuiTableFlags_ScrollY);

// Header
ImGui::TableNextRow();
ImGui::TableNextColumn(); ImGui::Text("Filename");
ImGui::TableNextColumn(); ImGui::Text("Path");
ImGui::TableNextColumn(); ImGui::Text("Title");
ImGui::TableNextColumn(); ImGui::Text("Artist");
ImGui::TableNextColumn(); ImGui::Text("Album Artist");
ImGui::TableNextColumn(); ImGui::Text("Album");
ImGui::TableNextColumn(); ImGui::Text("Track");
ImGui::TableNextColumn(); ImGui::Text("Discnumber");
ImGui::TableNextColumn(); ImGui::Text("Year");
ImGui::TableNextColumn(); ImGui::Text("Genre");
ImGui::TableNextColumn(); ImGui::Text("Comment");
ImGui::TableNextColumn(); ImGui::Text("Codec");

// Body
for (size_t i = 0; i < 2; ++i) {
ImGui::TableNextRow();
ImGui::TableNextColumn();

std::string label = "##row_select_" + std::to_string(i);
//selectedRows is an std::set<size_t>
bool isSelected = selectedRows.count(i) > 0;

if (ImGui::Selectable(label.c_str(), isSelected, ImGuiSelectableFlags_SpanAllColumns | ImGuiSelectableFlags_AllowDoubleClick)) {
	if (ImGui::GetIO().KeyCtrl) {
		if (isSelected)
			selectedRows.erase(i);
		else
			selectedRows.insert(i);
	} else {
		selectedRows.clear();
		selectedRows.insert(i);
	}
}

ImGui::SameLine();
ImGui::TextUnformatted(filename.c_str());

ImGui::TableNextColumn(); ImGui::TextUnformatted("filename");
ImGui::TableNextColumn(); ImGui::TextUnformatted("title");
ImGui::TableNextColumn(); ImGui::TextUnformatted("artist");
ImGui::TableNextColumn(); ImGui::TextUnformatted("album artist");
ImGui::TableNextColumn(); ImGui::TextUnformatted("album");
ImGui::TableNextColumn(); ImGui::Text("%u", 0);
ImGui::TableNextColumn(); ImGui::Text("%u", 0);
ImGui::TableNextColumn(); ImGui::Text("%u", 0);
ImGui::TableNextColumn(); ImGui::TextUnformatted("genre");
ImGui::TableNextColumn(); ImGui::TextUnformatted("comment");
ImGui::TableNextColumn(); ImGui::Text("TO_IMPLEMENT");
}

ImGui::EndTable();
ImGui::End();

cursedastronaut avatar May 18 '25 10:05 cursedastronaut

It seems to only crash with _DEBUG defined. I commented earlier APP_USE_VULKAN_DEBUG_REPORT when using _DEBUG as it segfaulted and I wasn't trying to debug Vulkan.

cursedastronaut avatar May 18 '25 10:05 cursedastronaut

Interesting to note: If I uncomment

#ifdef _DEBUG
#define APP_USE_VULKAN_DEBUG_REPORT
static VkDebugReportCallbackEXT g_DebugReport = VK_NULL_HANDLE;
#endif

The program segfaults at

static void check_vk_result(VkResult err)
{
    if (err == VK_SUCCESS)
        return;
    fprintf(stderr, "[vulkan] Error: VkResult = %d\n", err);
    if (err < 0)
        abort(); //<---------- HERE
}

and the output is

libdecor-gtk-WARNING: Failed to initialize GTK
Failed to load plugin 'libdecor-gtk.so': failed to init
[vulkan] Error: VkResult = -6

libdecor-gtk seems unrelated as it also happens when compiling without _DEBUG defined.

cursedastronaut avatar May 18 '25 10:05 cursedastronaut

My made-up solution was to compile my source files with _DEBUG but not ImGui's source files.

cursedastronaut avatar May 18 '25 10:05 cursedastronaut

This seems particularly fishy. The high-level selection stuff seems wildly unrelated to Vulkan rendering and to that libdecor-gtk library. My guess is that you omitted code/logic that may have an effect on those things, but the code you published seems rather harmless at first glance.

You should try to narrow your repro to the minimum amount of code, remove anything extraneous until you find what's causing it, but my bet is that the issue is not part of the code that you shared here.

I'm closing as this is missing information. But if you still need help with this we'd be happy to help if you amend with extra infos and research.

ocornut avatar Jun 17 '25 15:06 ocornut