2022-02-16 05:21:24 +00:00
|
|
|
#include <aurora/aurora.hpp>
|
2022-02-16 23:13:40 +00:00
|
|
|
|
2022-02-19 05:33:56 +00:00
|
|
|
#include "gfx/common.hpp"
|
|
|
|
#include "gpu.hpp"
|
|
|
|
#include "imgui.hpp"
|
|
|
|
|
2022-02-16 23:13:40 +00:00
|
|
|
#include <SDL.h>
|
2022-02-19 05:33:56 +00:00
|
|
|
#include <imgui.h>
|
2022-02-16 23:13:40 +00:00
|
|
|
#include <logvisor/logvisor.hpp>
|
|
|
|
#include <magic_enum.hpp>
|
|
|
|
|
2022-02-16 05:21:24 +00:00
|
|
|
namespace aurora {
|
2022-02-16 07:05:42 +00:00
|
|
|
static logvisor::Module Log("aurora");
|
2022-02-16 23:13:40 +00:00
|
|
|
|
2022-02-19 05:33:56 +00:00
|
|
|
// TODO: Move global state to a class/struct?
|
2022-02-16 09:23:39 +00:00
|
|
|
static std::unique_ptr<AppDelegate> g_AppDelegate;
|
2022-02-16 23:13:40 +00:00
|
|
|
static std::vector<std::string> g_Args;
|
|
|
|
|
2022-02-16 07:05:42 +00:00
|
|
|
// SDL
|
|
|
|
static SDL_Window* g_Window;
|
|
|
|
|
2022-02-19 05:33:56 +00:00
|
|
|
// GPU
|
|
|
|
using gpu::g_depthBuffer;
|
|
|
|
using gpu::g_device;
|
|
|
|
using gpu::g_frameBuffer;
|
|
|
|
using gpu::g_frameBufferResolved;
|
|
|
|
using gpu::g_queue;
|
|
|
|
using gpu::g_swapChain;
|
2022-02-16 07:05:42 +00:00
|
|
|
|
|
|
|
static void set_window_icon(Icon icon) noexcept {
|
|
|
|
SDL_Surface* iconSurface = SDL_CreateRGBSurfaceFrom(icon.data.get(), icon.width, icon.height, 32, 4 * icon.width,
|
|
|
|
#if SDL_BYTEORDER == SDL_BIG_ENDIAN
|
|
|
|
0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff
|
|
|
|
#else
|
|
|
|
0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000
|
|
|
|
#endif
|
|
|
|
);
|
|
|
|
if (iconSurface == nullptr) {
|
|
|
|
Log.report(logvisor::Fatal, FMT_STRING("Failed to create icon surface: {}"), SDL_GetError());
|
|
|
|
}
|
|
|
|
SDL_SetWindowIcon(g_Window, iconSurface);
|
|
|
|
SDL_FreeSurface(iconSurface);
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool poll_events() noexcept {
|
|
|
|
SDL_Event event;
|
|
|
|
while (SDL_PollEvent(&event) != 0) {
|
2022-02-19 05:33:56 +00:00
|
|
|
imgui::process_event(event);
|
2022-02-17 06:03:00 +00:00
|
|
|
|
2022-02-16 07:05:42 +00:00
|
|
|
switch (event.type) {
|
2022-02-16 09:23:39 +00:00
|
|
|
case SDL_WINDOWEVENT: {
|
|
|
|
switch (event.window.event) {
|
|
|
|
case SDL_WINDOWEVENT_SHOWN: {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_WINDOWEVENT_HIDDEN: {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_WINDOWEVENT_EXPOSED: {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_WINDOWEVENT_MOVED: {
|
|
|
|
g_AppDelegate->onAppWindowMoved(event.window.data1, event.window.data2);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_WINDOWEVENT_RESIZED: {
|
2022-02-19 05:33:56 +00:00
|
|
|
gpu::resize_swapchain(event.window.data1, event.window.data2);
|
2022-02-16 09:23:39 +00:00
|
|
|
g_AppDelegate->onAppWindowResized(
|
|
|
|
{static_cast<uint32_t>(event.window.data1), static_cast<uint32_t>(event.window.data2)});
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_WINDOWEVENT_SIZE_CHANGED: {
|
|
|
|
// TODO: handle size changed event
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_WINDOWEVENT_MINIMIZED: {
|
|
|
|
// TODO: handle minimized event
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_WINDOWEVENT_MAXIMIZED: {
|
|
|
|
// TODO: handle maximized event
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_WINDOWEVENT_RESTORED: {
|
|
|
|
// TODO: handle restored event
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_WINDOWEVENT_ENTER: {
|
|
|
|
// TODO: handle enter event (mouse focus)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_WINDOWEVENT_LEAVE: {
|
|
|
|
// TODO: handle leave event (mouse focus)
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_WINDOWEVENT_FOCUS_GAINED: {
|
|
|
|
// TODO: handle focus gained event
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_WINDOWEVENT_FOCUS_LOST: {
|
|
|
|
// TODO: handle focus lost event
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_WINDOWEVENT_CLOSE: {
|
|
|
|
// TODO: handle window close event
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_WINDOWEVENT_TAKE_FOCUS: {
|
|
|
|
// TODO: handle take focus event
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_WINDOWEVENT_HIT_TEST: {
|
|
|
|
// TODO: handle hit test?
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_WINDOWEVENT_DISPLAY_CHANGED: {
|
|
|
|
// TODO: handle display chaaged event
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/* TODO: More window events */
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_CONTROLLERDEVICEADDED: {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_CONTROLLERDEVICEREMOVED: {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_CONTROLLERBUTTONDOWN: {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_CONTROLLERBUTTONUP: {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_CONTROLLERAXISMOTION: {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_KEYDOWN: {
|
2022-02-17 06:03:00 +00:00
|
|
|
if (!ImGui::GetIO().WantCaptureKeyboard) {
|
|
|
|
// TODO
|
|
|
|
}
|
2022-02-16 09:23:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_KEYUP: {
|
2022-02-17 06:03:00 +00:00
|
|
|
if (!ImGui::GetIO().WantCaptureKeyboard) {
|
|
|
|
// TODO
|
|
|
|
}
|
2022-02-16 09:23:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_TEXTINPUT: {
|
2022-02-17 06:03:00 +00:00
|
|
|
if (!ImGui::GetIO().WantCaptureKeyboard) {
|
|
|
|
// TODO
|
|
|
|
}
|
2022-02-16 09:23:39 +00:00
|
|
|
break;
|
|
|
|
}
|
2022-02-16 07:05:42 +00:00
|
|
|
case SDL_QUIT:
|
2022-02-16 09:23:39 +00:00
|
|
|
g_AppDelegate->onAppExiting();
|
2022-02-16 07:05:42 +00:00
|
|
|
Log.report(logvisor::Info, FMT_STRING("Received quit request"));
|
|
|
|
return false;
|
|
|
|
}
|
2022-02-18 00:38:31 +00:00
|
|
|
// Log.report(logvisor::Info, FMT_STRING("Received SDL event: {}"), event.type);
|
2022-02-16 07:05:42 +00:00
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2022-02-16 09:23:39 +00:00
|
|
|
void app_run(std::unique_ptr<AppDelegate> app, Icon icon, int argc, char** argv) noexcept {
|
|
|
|
g_AppDelegate = std::move(app);
|
|
|
|
/* Lets gather arguments skipping the program filename */
|
|
|
|
for (size_t i = 1; i < argc; ++i) {
|
|
|
|
g_Args.emplace_back(argv[i]);
|
|
|
|
}
|
|
|
|
|
2022-02-16 07:05:42 +00:00
|
|
|
if (SDL_Init(SDL_INIT_EVERYTHING) < 0) {
|
|
|
|
Log.report(logvisor::Fatal, FMT_STRING("Error initializing SDL: {}"), SDL_GetError());
|
|
|
|
}
|
|
|
|
|
2022-02-16 23:13:40 +00:00
|
|
|
Uint32 flags = SDL_WINDOW_SHOWN | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_RESIZABLE;
|
2022-02-19 05:33:56 +00:00
|
|
|
switch (gpu::preferredBackendType) {
|
2022-02-16 23:13:40 +00:00
|
|
|
#ifdef DAWN_ENABLE_BACKEND_VULKAN
|
2022-02-16 07:05:42 +00:00
|
|
|
case wgpu::BackendType::Vulkan:
|
|
|
|
flags |= SDL_WINDOW_VULKAN;
|
|
|
|
break;
|
|
|
|
#endif
|
2022-02-16 23:13:40 +00:00
|
|
|
#ifdef DAWN_ENABLE_BACKEND_METAL
|
2022-02-16 07:05:42 +00:00
|
|
|
case wgpu::BackendType::Metal:
|
|
|
|
flags |= SDL_WINDOW_METAL;
|
|
|
|
break;
|
|
|
|
#endif
|
2022-02-16 23:13:40 +00:00
|
|
|
#ifdef DAWN_ENABLE_BACKEND_OPENGL
|
2022-02-16 07:05:42 +00:00
|
|
|
case wgpu::BackendType::OpenGL:
|
|
|
|
flags |= SDL_WINDOW_OPENGL;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
g_Window = SDL_CreateWindow("Metaforce", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1280, 720, flags);
|
|
|
|
if (g_Window == nullptr) {
|
|
|
|
Log.report(logvisor::Fatal, FMT_STRING("Error creating window: {}"), SDL_GetError());
|
|
|
|
}
|
|
|
|
set_window_icon(std::move(icon));
|
|
|
|
|
2022-02-19 05:33:56 +00:00
|
|
|
gpu::initialize(g_Window);
|
|
|
|
gfx::construct_state();
|
2022-02-16 23:13:40 +00:00
|
|
|
|
2022-02-19 05:33:56 +00:00
|
|
|
imgui::create_context();
|
2022-02-17 06:03:00 +00:00
|
|
|
g_AppDelegate->onImGuiInit(1.f); // TODO scale
|
2022-02-19 05:33:56 +00:00
|
|
|
imgui::initialize(g_Window);
|
2022-02-17 06:03:00 +00:00
|
|
|
g_AppDelegate->onImGuiAddTextures();
|
|
|
|
|
2022-02-16 09:23:39 +00:00
|
|
|
g_AppDelegate->onAppLaunched();
|
|
|
|
g_AppDelegate->onAppWindowResized(get_window_size());
|
2022-02-17 06:03:00 +00:00
|
|
|
|
2022-02-16 23:13:40 +00:00
|
|
|
while (poll_events()) {
|
2022-02-19 05:33:56 +00:00
|
|
|
imgui::new_frame();
|
|
|
|
if (!g_AppDelegate->onAppIdle(ImGui::GetIO().DeltaTime)) {
|
|
|
|
break;
|
|
|
|
}
|
2022-02-17 06:03:00 +00:00
|
|
|
|
2022-02-19 05:33:56 +00:00
|
|
|
const wgpu::TextureView view = g_swapChain.GetCurrentTextureView();
|
2022-02-17 06:03:00 +00:00
|
|
|
g_AppDelegate->onAppDraw();
|
|
|
|
|
2022-02-19 05:33:56 +00:00
|
|
|
const auto encoderDescriptor = wgpu::CommandEncoderDescriptor{
|
|
|
|
.label = "Redraw encoder",
|
|
|
|
};
|
|
|
|
auto encoder = g_device.CreateCommandEncoder(&encoderDescriptor);
|
2022-02-16 23:13:40 +00:00
|
|
|
{
|
2022-02-19 05:33:56 +00:00
|
|
|
const std::array attachments{
|
|
|
|
wgpu::RenderPassColorAttachment{
|
|
|
|
.view = view,
|
|
|
|
// .resolveTarget = g_frameBufferResolved.view,
|
|
|
|
.loadOp = wgpu::LoadOp::Clear,
|
|
|
|
.storeOp = wgpu::StoreOp::Store,
|
|
|
|
.clearColor = {0.f, 0.f, 0.f, 0.f},
|
|
|
|
},
|
|
|
|
};
|
|
|
|
const auto depthStencilAttachment = wgpu::RenderPassDepthStencilAttachment{
|
|
|
|
.view = g_depthBuffer.view,
|
|
|
|
.depthLoadOp = wgpu::LoadOp::Clear,
|
|
|
|
.depthStoreOp = wgpu::StoreOp::Discard,
|
|
|
|
.clearDepth = 1.f,
|
|
|
|
.stencilLoadOp = wgpu::LoadOp::Clear,
|
|
|
|
.stencilStoreOp = wgpu::StoreOp::Discard,
|
|
|
|
};
|
2022-02-16 23:13:40 +00:00
|
|
|
auto renderPassDescriptor = wgpu::RenderPassDescriptor{
|
2022-02-19 05:33:56 +00:00
|
|
|
.label = "Main render pass",
|
2022-02-16 23:13:40 +00:00
|
|
|
.colorAttachmentCount = attachments.size(),
|
|
|
|
.colorAttachments = attachments.data(),
|
2022-02-19 05:33:56 +00:00
|
|
|
.depthStencilAttachment = &depthStencilAttachment,
|
2022-02-16 23:13:40 +00:00
|
|
|
};
|
|
|
|
auto pass = encoder.BeginRenderPass(&renderPassDescriptor);
|
2022-02-19 05:33:56 +00:00
|
|
|
gfx::render(pass);
|
|
|
|
pass.End();
|
|
|
|
}
|
|
|
|
{
|
|
|
|
const std::array attachments{
|
|
|
|
wgpu::RenderPassColorAttachment{
|
|
|
|
.view = view,
|
|
|
|
.loadOp = wgpu::LoadOp::Load,
|
|
|
|
.storeOp = wgpu::StoreOp::Store,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
auto renderPassDescriptor = wgpu::RenderPassDescriptor{
|
|
|
|
.label = "ImGui render pass",
|
|
|
|
.colorAttachmentCount = attachments.size(),
|
|
|
|
.colorAttachments = attachments.data(),
|
|
|
|
};
|
|
|
|
auto pass = encoder.BeginRenderPass(&renderPassDescriptor);
|
|
|
|
imgui::render(pass);
|
2022-02-16 23:13:40 +00:00
|
|
|
pass.End();
|
|
|
|
}
|
|
|
|
const auto buffer = encoder.Finish();
|
2022-02-19 05:33:56 +00:00
|
|
|
g_queue.Submit(1, &buffer);
|
|
|
|
g_swapChain.Present();
|
2022-02-17 06:03:00 +00:00
|
|
|
|
|
|
|
g_AppDelegate->onAppPostDraw();
|
2022-02-19 05:33:56 +00:00
|
|
|
|
|
|
|
ImGui::EndFrame();
|
2022-02-16 23:13:40 +00:00
|
|
|
}
|
2022-02-16 07:05:42 +00:00
|
|
|
|
2022-02-17 06:03:00 +00:00
|
|
|
g_AppDelegate->onAppExiting();
|
|
|
|
|
2022-02-19 05:33:56 +00:00
|
|
|
imgui::shutdown();
|
|
|
|
gpu::shutdown();
|
2022-02-16 07:05:42 +00:00
|
|
|
SDL_DestroyWindow(g_Window);
|
|
|
|
SDL_Quit();
|
|
|
|
}
|
|
|
|
|
2022-02-16 09:23:39 +00:00
|
|
|
std::vector<std::string> get_args() noexcept { return g_Args; }
|
2022-02-19 05:33:56 +00:00
|
|
|
|
2022-02-16 05:21:24 +00:00
|
|
|
WindowSize get_window_size() noexcept {
|
2022-02-16 09:23:39 +00:00
|
|
|
int width, height;
|
|
|
|
SDL_GetWindowSize(g_Window, &width, &height);
|
|
|
|
return {static_cast<uint32_t>(width), static_cast<uint32_t>(height)};
|
2022-02-16 05:21:24 +00:00
|
|
|
}
|
2022-02-19 05:33:56 +00:00
|
|
|
|
2022-02-16 07:05:42 +00:00
|
|
|
void set_window_title(zstring_view title) noexcept { SDL_SetWindowTitle(g_Window, title.c_str()); }
|
2022-02-19 05:33:56 +00:00
|
|
|
|
2022-02-16 05:21:24 +00:00
|
|
|
Backend get_backend() noexcept {
|
2022-02-19 05:33:56 +00:00
|
|
|
switch (gpu::g_backendType) {
|
2022-02-16 09:23:39 +00:00
|
|
|
case wgpu::BackendType::WebGPU:
|
|
|
|
return Backend::WebGPU;
|
|
|
|
case wgpu::BackendType::D3D11:
|
|
|
|
return Backend::D3D11;
|
|
|
|
case wgpu::BackendType::D3D12:
|
|
|
|
return Backend::D3D12;
|
|
|
|
case wgpu::BackendType::Metal:
|
|
|
|
return Backend::Metal;
|
|
|
|
case wgpu::BackendType::Vulkan:
|
|
|
|
return Backend::Vulkan;
|
|
|
|
case wgpu::BackendType::OpenGL:
|
|
|
|
return Backend::OpenGL;
|
2022-02-16 23:13:40 +00:00
|
|
|
case wgpu::BackendType::OpenGLES:
|
|
|
|
return Backend::OpenGLES;
|
2022-02-16 09:23:39 +00:00
|
|
|
default:
|
|
|
|
return Backend::Invalid;
|
|
|
|
}
|
2022-02-16 05:21:24 +00:00
|
|
|
}
|
2022-02-19 05:33:56 +00:00
|
|
|
|
|
|
|
std::string_view get_backend_string() noexcept { return magic_enum::enum_name(gpu::g_backendType); }
|
|
|
|
|
2022-02-16 05:21:24 +00:00
|
|
|
void set_fullscreen(bool fullscreen) noexcept {
|
2022-02-16 09:23:39 +00:00
|
|
|
auto flags = SDL_GetWindowFlags(g_Window);
|
|
|
|
if (fullscreen) {
|
|
|
|
flags |= SDL_WINDOW_FULLSCREEN;
|
|
|
|
} else {
|
|
|
|
flags &= ~SDL_WINDOW_FULLSCREEN;
|
|
|
|
}
|
|
|
|
SDL_SetWindowFullscreen(g_Window, flags);
|
2022-02-16 05:21:24 +00:00
|
|
|
}
|
2022-02-16 09:23:39 +00:00
|
|
|
|
2022-02-16 05:21:24 +00:00
|
|
|
int32_t get_controller_player_index(uint32_t which) noexcept {
|
|
|
|
return -1; // TODO
|
|
|
|
}
|
2022-02-19 05:33:56 +00:00
|
|
|
|
2022-02-16 05:21:24 +00:00
|
|
|
void set_controller_player_index(uint32_t which, int32_t index) noexcept {
|
|
|
|
// TODO
|
|
|
|
}
|
2022-02-19 05:33:56 +00:00
|
|
|
|
2022-02-16 05:21:24 +00:00
|
|
|
bool is_controller_gamecube(uint32_t which) noexcept {
|
|
|
|
return true; // TODO
|
|
|
|
}
|
2022-02-19 05:33:56 +00:00
|
|
|
|
2022-02-16 05:21:24 +00:00
|
|
|
std::string get_controller_name(uint32_t which) noexcept {
|
|
|
|
return ""; // TODO
|
|
|
|
}
|
|
|
|
} // namespace aurora
|