aboutsummaryrefslogtreecommitdiff
path: root/src/Core
diff options
context:
space:
mode:
Diffstat (limited to 'src/Core')
-rw-r--r--src/Core/Application.cpp124
-rw-r--r--src/Core/Application.h4
-rw-r--r--src/Core/Window.cpp33
3 files changed, 118 insertions, 43 deletions
diff --git a/src/Core/Application.cpp b/src/Core/Application.cpp
index df42877..c73dc6d 100644
--- a/src/Core/Application.cpp
+++ b/src/Core/Application.cpp
@@ -8,10 +8,14 @@
#include "States/WorldBuilderState.h"
#include <GLFW/glfw3.h>
+#include <imgui.h>
#include <ImGuizmo.h>
+#include "Platform/Vulkan/VulkanRenderer.h"
+
#ifdef __APPLE__
#include "Platform/Metal/MetalContext.h"
+#include "Platform/Vulkan/VulkanContext.h"
#endif
namespace Donut
@@ -23,8 +27,21 @@ namespace Donut
{
s_Instance = this;
+ // Select the render API before the window is created: the window is
+ // built differently for Vulkan (GLFW_NO_API) than for OpenGL.
+ Logger::Init();
+ SettingsManager::Initialize();
+ {
+ const auto& settings = SettingsManager::GetSettingsConst();
+ RendererAPI::SetAPI(settings.graphics.renderAPI == "Vulkan"
+ ? RendererAPI::API::Vulkan : RendererAPI::API::OpenGL);
+ }
+
+ if (RendererAPI::GetAPI() == RendererAPI::API::Vulkan)
+ VulkanPrepareGLFW(); // must precede glfwInit() inside the Window ctor
+
m_Window = CreateScope<Window>(name, width, height);
- m_Window->SetEventCallback([this](Event& event)
+ m_Window->SetEventCallback([this](Event& event)
{
OnEvent(event);
});
@@ -42,16 +59,39 @@ namespace Donut
{
while (m_Running)
{
- if (!m_Minimized)
+ if (m_VulkanRenderer)
{
- OnUpdate();
- OnRender();
+ glfwPollEvents(); // before the ImGui frame so input is current
+ if (!m_Minimized)
+ m_VulkanRenderer->DrawFrame(glm::vec4(0.05f, 0.06f, 0.10f, 1.0f),
+ [this] { BuildVulkanUI(); });
+ }
+ else
+ {
+ if (!m_Minimized)
+ {
+ OnUpdate();
+ OnRender();
+ }
+ m_Window->OnUpdate(); // polls events + swaps buffers (OpenGL)
}
-
- m_Window->OnUpdate();
}
}
+ void Application::BuildVulkanUI()
+ {
+ // Placeholder UI proving the ImGui Vulkan backend renders. The real
+ // application UI (states' OnImUIRender) moves here once the scene is
+ // ported to Vulkan (B-3).
+ ImGui::Begin("Donut - Vulkan backend");
+ ImGui::Text("Geodesic black hole through Vulkan (MoltenVK).");
+ ImGui::Text("%.1f FPS", ImGui::GetIO().Framerate);
+ ImGui::Separator();
+ ImGui::TextWrapped("Drag to orbit, scroll to zoom. HDRI starfield is live; "
+ "next is porting the simulation UI to Vulkan.");
+ ImGui::End();
+ }
+
void Application::Close()
{
m_Running = false;
@@ -73,15 +113,24 @@ namespace Donut
m_Minimized = true;
else
m_Minimized = false;
-
- Renderer::OnWindowResize(e.GetWidth(), e.GetHeight());
- m_Engine->SetWindowDimensions(e.GetWidth(), e.GetHeight());
+
+ if (m_VulkanRenderer)
+ {
+ m_VulkanRenderer->OnResize(e.GetWidth(), e.GetHeight());
+ }
+ else
+ {
+ Renderer::OnWindowResize(e.GetWidth(), e.GetHeight());
+ if (m_Engine) m_Engine->SetWindowDimensions(e.GetWidth(), e.GetHeight());
+ }
event.Handled = true;
return true;
});
- dispatcher.Dispatch<KeyPressedEvent>([this, &event](KeyPressedEvent& e)
+ dispatcher.Dispatch<KeyPressedEvent>([this, &event](KeyPressedEvent& e)
{
+ if (!m_StateManager)
+ return true;
if (e.GetKeyCode() == GLFW_KEY_1)
{
m_StateManager->SwitchToState("Config");
@@ -103,34 +152,38 @@ namespace Donut
return true;
});
-
- m_StateManager->OnEvent(event);
+
+ if (m_StateManager)
+ m_StateManager->OnEvent(event);
}
void Application::OnInit()
{
- Logger::Init();
+ // (Logger, settings and API selection happen in the constructor.)
+
+ if (RendererAPI::GetAPI() == RendererAPI::API::Vulkan)
+ {
+ int w = 0, h = 0;
+ glfwGetFramebufferSize((GLFWwindow*)m_Window->GetNativeWindow(), &w, &h);
+ m_VulkanRenderer = CreateScope<VulkanRenderer>();
+ if (!m_VulkanRenderer->Init(m_Window->GetNativeWindow(), w, h))
+ DONUT_ERROR("Vulkan renderer initialization failed");
+ else
+ m_VulkanRenderer->InitImGui();
+ // Scene rendering hooks in here in the B-3 phase; the Vulkan path now
+ // clears, presents, and draws the ImGui UI.
+ return;
+ }
-#ifdef __APPLE__
- MetalProbe(); // Phase 1: native Metal device available?
- MetalComputeSelfTest(); // Phase 1: full compute dispatch + read-back works?
-#endif
-
- SettingsManager::Initialize();
-
- const auto& settings = SettingsManager::GetSettingsConst();
- RendererAPI::API api = (settings.graphics.renderAPI == "Vulkan") ? RendererAPI::API::Vulkan : RendererAPI::API::OpenGL;
- RendererAPI::SetAPI(api);
-
Renderer::Init();
m_Window->InitImGui();
-
+
Renderer::OnWindowResize(1280, 720);
RenderCommand::SetFaceCulling(false);
m_Engine = CreateScope<Engine>();
m_Engine->SetWindowDimensions(1280, 720);
-
+
m_StateManager = CreateScope<StateManager>();
m_StateManager->RegisterState("Config", CreateScope<ConfigState>());
m_StateManager->RegisterState("Simulation", CreateScope<SimulationState>());
@@ -138,12 +191,19 @@ namespace Donut
m_StateManager->SwitchToState("Config");
}
- void Application::OnShutdown()
- {
- if (m_StateManager)
- m_StateManager->Shutdown();
-
- Renderer::Shutdown();
+ void Application::OnShutdown()
+ {
+ if (m_VulkanRenderer)
+ {
+ m_VulkanRenderer->Shutdown();
+ m_VulkanRenderer.reset();
+ }
+ else
+ {
+ if (m_StateManager)
+ m_StateManager->Shutdown();
+ Renderer::Shutdown();
+ }
SettingsManager::Shutdown();
Logger::Shutdown();
}
diff --git a/src/Core/Application.h b/src/Core/Application.h
index c16b6d9..b715170 100644
--- a/src/Core/Application.h
+++ b/src/Core/Application.h
@@ -10,6 +10,8 @@
namespace Donut
{
+ class VulkanRenderer; // live-window Vulkan backend (Platform/Vulkan)
+
class Application
{
public:
@@ -31,10 +33,12 @@ namespace Donut
void OnRender();
void OnEvent(Event& event);
void SetupDockingLayout();
+ void BuildVulkanUI(); // ImGui UI built each frame on the Vulkan path
private:
Scope<StateManager> m_StateManager;
Scope<Window> m_Window;
Scope<Engine> m_Engine;
+ Scope<VulkanRenderer> m_VulkanRenderer; // non-null only when the Vulkan API is selected
bool m_Running;
bool m_Minimized;
diff --git a/src/Core/Window.cpp b/src/Core/Window.cpp
index c890979..ade0c26 100644
--- a/src/Core/Window.cpp
+++ b/src/Core/Window.cpp
@@ -1,6 +1,7 @@
#include <glad/glad.h>
#include "Window.h"
#include "ThemeManager.h"
+#include "Rendering/Renderer.h" // RendererAPI::GetAPI()
#include <cstdint>
@@ -42,16 +43,24 @@ namespace Donut
DONUT_INFO("GLFW initialized successfully");
}
+ if (RendererAPI::GetAPI() == RendererAPI::API::Vulkan)
+ {
+ // Vulkan manages presentation itself; GLFW must not create a GL context.
+ glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
+ }
+ else
+ {
#ifdef __APPLE__
- // macOS only exposes OpenGL up to 4.1 Core Profile, and requires a
- // forward-compatible core-profile context for any modern (>= 3.3)
- // shader to compile. Without these hints GLFW hands back a legacy
- // 2.1 context and every GLSL shader in the project fails to build.
- glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
- glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
- glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
- glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
+ // macOS only exposes OpenGL up to 4.1 Core Profile, and requires a
+ // forward-compatible core-profile context for any modern (>= 3.3)
+ // shader to compile. Without these hints GLFW hands back a legacy
+ // 2.1 context and every GLSL shader in the project fails to build.
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 4);
+ glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
+ glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
+ glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GLFW_TRUE);
#endif
+ }
m_Window = glfwCreateWindow(m_Width, m_Height, m_Title.c_str(), nullptr, nullptr);
if (!m_Window)
@@ -63,7 +72,8 @@ namespace Donut
DONUT_INFO("GLFW window created successfully");
- glfwMakeContextCurrent(m_Window);
+ if (RendererAPI::GetAPI() != RendererAPI::API::Vulkan)
+ glfwMakeContextCurrent(m_Window);
glfwSetWindowUserPointer(m_Window, this);
glfwSetErrorCallback(GLFWErrorCallback);
@@ -100,7 +110,8 @@ namespace Donut
void Window::OnUpdate() const
{
glfwPollEvents();
- glfwSwapBuffers(m_Window);
+ if (RendererAPI::GetAPI() != RendererAPI::API::Vulkan)
+ glfwSwapBuffers(m_Window); // Vulkan presents via the swapchain instead
}
bool Window::ShouldClose() const
@@ -219,7 +230,7 @@ namespace Donut
void Window::GLFWErrorCallback(int error, const char* description)
{
- DONUT_ERROR("GLFW Error (", error, "): ", description);
+ DONUT_ERROR("GLFW Error ({}): {}", error, description ? description : "");
}
void Window::GLFWWindowCloseCallback(GLFWwindow* window)