Skip to content

Commit 05c506c

Browse files
committed
fix(gui): prevent crash during file dialog and resolve D3D11 resize jitter
- Add reentrant guard to event_watch callback; file dialogs (NFD) run a Win32 modal loop that pumps messages → SDL fires EXPOSED events → callback calls NewFrame() while main loop is mid-frame → ImGui assert - Wrap main loop render in same guard so callback detects mid-frame state - D3D11 on_resize: remove Flush() stall, use event pixel dimensions directly, skip vsync on resize frames to beat DWM composition deadline - Only handle SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED (drop WINDOW_RESIZED)
1 parent b3b9c3e commit 05c506c

1 file changed

Lines changed: 9 additions & 0 deletions

File tree

src/gui/gui_app.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,14 +376,19 @@ int run(int argc, char** argv) {
376376
IRenderBackend* backend;
377377
MainWindow* main_window;
378378
SDL_Window* window;
379+
bool rendering{false}; // Reentrant guard
379380
};
380381

381382
RenderContext render_ctx{backend.get(), &main_window, window};
382383

383384
// Event watch callback - called during Windows modal resize loop
385+
// Also fires during file dialog modal loops (EXPOSED events), so
386+
// a reentrant guard is needed to avoid calling NewFrame() while
387+
// the main loop is mid-frame.
384388
auto event_watch = [](void* userdata, SDL_Event* event) -> bool {
385389
auto* ctx = static_cast<RenderContext*>(userdata);
386390

391+
if (ctx->rendering) return true; // Already mid-frame — skip
387392
if (event->type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED ||
388393
event->type == SDL_EVENT_WINDOW_EXPOSED) {
389394

@@ -393,6 +398,7 @@ int run(int argc, char** argv) {
393398
}
394399

395400
// Render frame immediately
401+
ctx->rendering = true;
396402
ctx->backend->begin_frame();
397403
ctx->backend->imgui_new_frame();
398404
ImGui::NewFrame();
@@ -401,6 +407,7 @@ int run(int argc, char** argv) {
401407
ctx->backend->imgui_render();
402408
ctx->backend->end_frame();
403409
ctx->backend->present();
410+
ctx->rendering = false;
404411
}
405412

406413
return true; // Allow event to be added to queue
@@ -455,6 +462,7 @@ int run(int argc, char** argv) {
455462
}
456463

457464
// Render frame
465+
render_ctx.rendering = true;
458466
backend->begin_frame();
459467
backend->imgui_new_frame();
460468
ImGui::NewFrame();
@@ -463,6 +471,7 @@ int run(int argc, char** argv) {
463471
backend->imgui_render();
464472
backend->end_frame();
465473
backend->present();
474+
render_ctx.rendering = false;
466475
}
467476

468477
// Remove event watch before cleanup

0 commit comments

Comments
 (0)