From d7c1ced08d5d78fcb239550404db4e67d4357a19 Mon Sep 17 00:00:00 2001 From: hachem Date: Tue, 22 Sep 2026 06:57:16 +0200 Subject: fix: windows support --- src/core/application.cpp | 56 +++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 5 deletions(-) (limited to 'src/core/application.cpp') diff --git a/src/core/application.cpp b/src/core/application.cpp index e53e420..de318fb 100644 --- a/src/core/application.cpp +++ b/src/core/application.cpp @@ -4,10 +4,13 @@ #include "settings_manager.h" #include "platform/opengl/opengl_device.h" -#include "platform/vulkan/vulkan_device.h" +#ifndef DONUT_NO_VULKAN + #include "platform/vulkan/vulkan_device.h" +#endif #include #include +#include // ImGui_ImplGlfw_GetContentScaleForWindow #include #include #include @@ -29,6 +32,7 @@ namespace Donut } Application::Application(const std::string& name, int width, int height) + : m_title(name), m_init_w(width), m_init_h(height) { s_instance = this; @@ -42,11 +46,31 @@ namespace Donut ? RendererAPI::API::Vulkan : RendererAPI::API::OpenGL); } +#ifdef DONUT_NO_VULKAN + // generated without a Vulkan SDK, so the backend isn't in this binary at all + if (RendererAPI::get_api() == RendererAPI::API::Vulkan) + { + DONUT_WARN("built without the Vulkan backend, falling back to OpenGL"); + RendererAPI::set_api(RendererAPI::API::OpenGL); + } +#else + if (RendererAPI::get_api() == RendererAPI::API::Vulkan && !RHI::vulkan_runtime_available()) + { + DONUT_WARN("no Vulkan runtime on this machine (vulkan-1.dll), falling back to OpenGL"); + RendererAPI::set_api(RendererAPI::API::OpenGL); + } if (RendererAPI::get_api() == RendererAPI::API::Vulkan) RHI::vulkan_prepare_glfw(); // must precede glfwInit() inside the Window ctor +#endif m_window = create_scope(name, width, height); m_window->set_event_callback([this](Event& event) { on_event(event); }); + if (!m_window->get_native_window()) + { + DONUT_ERROR("no window, no app (GLFW said why above)"); + m_running = false; + return; + } on_init(); } @@ -62,15 +86,33 @@ namespace Donut int w = 0, h = 0; glfwGetFramebufferSize((GLFWwindow*)m_window->get_native_window(), &w, &h); +#ifndef DONUT_NO_VULKAN if (RendererAPI::get_api() == RendererAPI::API::Vulkan) m_device = RHI::create_vulkan_device(); else +#endif m_device = RHI::create_opengl_device(); RHI::NativeWindow native{ m_window->get_native_window(), w, h }; if (!m_device->init(native)) { + m_device->shutdown(); + m_device.reset(); +#ifndef DONUT_NO_VULKAN + // a Vulkan window can't host a GL context (GLFW_NO_API), so rebuild it + // and try once more on OpenGL. the saved setting stays as the user left it. + if (RendererAPI::get_api() == RendererAPI::API::Vulkan) + { + DONUT_WARN("Vulkan device init failed (see above), falling back to OpenGL"); + RendererAPI::set_api(RendererAPI::API::OpenGL); + m_window.reset(); + m_window = create_scope(m_title, m_init_w, m_init_h); + m_window->set_event_callback([this](Event& event) { on_event(event); }); + if (m_window->get_native_window()) { on_init(); return; } + } +#endif DONUT_ERROR("RHI device initialization failed"); + m_running = false; // nothing to draw with; run() just returns return; } @@ -80,9 +122,13 @@ namespace Donut m_ui = create_scope(); m_device->init_imgui(); + // windows hands out physical pixels with no scaling, so a 4k desktop at 200% + // would get a half-size ui. the glfw backend reports 1.0 on macos (retina + // scaling lives in the framebuffer there), so the mac is untouched. + const float dpi = ImGui_ImplGlfw_GetContentScaleForWindow((GLFWwindow*)m_window->get_native_window()); // the UI layer owns its typography and its imgui.ini section; both go into // the device-created ImGui context before its first NewFrame reads the ini. - m_ui->init(); + m_ui->init(dpi); g_prev_scroll = glfwSetScrollCallback((GLFWwindow*)m_window->get_native_window(), donut_scroll_callback); @@ -99,8 +145,8 @@ namespace Donut { double frame_start = glfwGetTime(); glfwPollEvents(); - if (!m_minimized && m_device) - render_frame(); + if (m_minimized) { glfwWaitEventsTimeout(0.1); continue; } // nothing to draw, so don't spin a core + if (m_device) render_frame(); // with vsync off, cap to the target FPS (vsync itself paces otherwise). if (!SettingsManager::get_v_sync_enabled()) @@ -179,7 +225,7 @@ namespace Donut { ExportConfig cfg; cfg.width = 1280; cfg.height = 720; - int written = export_frame(cfg); + [[maybe_unused]] const int written = export_frame(cfg); // only the debug log reads it DONUT_INFO("autoexport wrote {} file(s)", written); close(); } -- cgit v1.3