2022-02-16 05:21:24 +00:00
|
|
|
#include <aurora/aurora.hpp>
|
2022-06-08 17:58:38 +00:00
|
|
|
|
2022-02-19 05:33:56 +00:00
|
|
|
#include "gfx/common.hpp"
|
2022-03-06 07:46:42 +00:00
|
|
|
#include "gfx/gx.hpp"
|
2022-02-19 05:33:56 +00:00
|
|
|
#include "gpu.hpp"
|
2022-02-19 14:36:03 +00:00
|
|
|
#include "input.hpp"
|
2022-02-19 05:33:56 +00:00
|
|
|
#include "imgui.hpp"
|
|
|
|
|
2022-06-08 17:58:38 +00:00
|
|
|
#include <algorithm>
|
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-05-27 19:52:16 +00:00
|
|
|
std::string g_configPath;
|
2022-02-16 23:13:40 +00:00
|
|
|
|
2022-02-16 07:05:42 +00:00
|
|
|
// SDL
|
2022-02-26 20:38:08 +00:00
|
|
|
static SDL_Window* g_window;
|
2022-03-08 23:35:40 +00:00
|
|
|
WindowSize g_windowSize;
|
2022-02-16 07:05:42 +00:00
|
|
|
|
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());
|
2022-02-19 06:41:21 +00:00
|
|
|
unreachable();
|
2022-02-16 07:05:42 +00:00
|
|
|
}
|
2022-02-26 20:38:08 +00:00
|
|
|
SDL_SetWindowIcon(g_window, iconSurface);
|
2022-02-16 07:05:42 +00:00
|
|
|
SDL_FreeSurface(iconSurface);
|
|
|
|
}
|
|
|
|
|
2022-06-12 21:09:47 +00:00
|
|
|
static bool g_paused = false;
|
|
|
|
|
|
|
|
static void resize_swapchain(bool force) noexcept {
|
|
|
|
const auto size = get_window_size();
|
|
|
|
if (!force && size == g_windowSize) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (size.scale != g_windowSize.scale) {
|
|
|
|
if (g_windowSize.scale > 0.f) {
|
|
|
|
Log.report(logvisor::Info, FMT_STRING("Display scale changed to {}"), size.scale);
|
|
|
|
}
|
|
|
|
g_AppDelegate->onAppDisplayScaleChanged(size.scale);
|
|
|
|
}
|
|
|
|
g_windowSize = size;
|
|
|
|
gpu::resize_swapchain(size.fb_width, size.fb_height);
|
|
|
|
g_AppDelegate->onAppWindowResized(size);
|
|
|
|
}
|
|
|
|
|
2022-02-16 07:05:42 +00:00
|
|
|
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) {
|
2022-06-12 21:09:47 +00:00
|
|
|
case SDL_WINDOWEVENT_MINIMIZED: {
|
|
|
|
// Android/iOS: Application backgrounded
|
|
|
|
g_paused = true;
|
2022-02-16 09:23:39 +00:00
|
|
|
break;
|
|
|
|
}
|
2022-06-12 21:09:47 +00:00
|
|
|
case SDL_WINDOWEVENT_RESTORED: {
|
|
|
|
// Android/iOS: Application focused
|
|
|
|
g_paused = false;
|
2022-02-16 09:23:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_WINDOWEVENT_MOVED: {
|
|
|
|
g_AppDelegate->onAppWindowMoved(event.window.data1, event.window.data2);
|
|
|
|
break;
|
|
|
|
}
|
2022-06-12 21:09:47 +00:00
|
|
|
case SDL_WINDOWEVENT_SIZE_CHANGED: {
|
|
|
|
resize_swapchain(false);
|
2022-02-16 09:23:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_CONTROLLERDEVICEADDED: {
|
2022-02-19 14:36:03 +00:00
|
|
|
auto instance = input::add_controller(event.cdevice.which);
|
|
|
|
if (instance != -1) {
|
|
|
|
g_AppDelegate->onControllerAdded(instance);
|
|
|
|
}
|
2022-02-16 09:23:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_CONTROLLERDEVICEREMOVED: {
|
2022-02-19 14:36:03 +00:00
|
|
|
input::remove_controller(event.cdevice.which);
|
2022-02-16 09:23:39 +00:00
|
|
|
break;
|
|
|
|
}
|
2022-02-19 14:36:03 +00:00
|
|
|
case SDL_CONTROLLERBUTTONUP:
|
2022-02-16 09:23:39 +00:00
|
|
|
case SDL_CONTROLLERBUTTONDOWN: {
|
2022-02-19 14:36:03 +00:00
|
|
|
g_AppDelegate->onControllerButton(
|
2022-02-20 03:22:03 +00:00
|
|
|
event.cbutton.which,
|
|
|
|
input::translate_controller_button(static_cast<SDL_GameControllerButton>(event.cbutton.button)),
|
2022-02-19 14:36:03 +00:00
|
|
|
event.cbutton.state == SDL_PRESSED);
|
2022-02-16 09:23:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_CONTROLLERAXISMOTION: {
|
2022-03-04 09:46:33 +00:00
|
|
|
if (event.caxis.value > 8000 || event.caxis.value < -8000) {
|
|
|
|
g_AppDelegate->onControllerAxis(
|
|
|
|
event.caxis.which, input::translate_controller_axis(static_cast<SDL_GameControllerAxis>(event.caxis.axis)),
|
|
|
|
event.caxis.value);
|
|
|
|
} else {
|
|
|
|
g_AppDelegate->onControllerAxis(
|
|
|
|
event.caxis.which, input::translate_controller_axis(static_cast<SDL_GameControllerAxis>(event.caxis.axis)),
|
|
|
|
0);
|
|
|
|
}
|
2022-02-16 09:23:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_KEYDOWN: {
|
2022-06-12 21:09:47 +00:00
|
|
|
// ALT+ENTER for fullscreen toggle
|
|
|
|
if (event.key.repeat == 0u && event.key.keysym.scancode == SDL_SCANCODE_RETURN &&
|
|
|
|
(event.key.keysym.mod & (KMOD_RALT | KMOD_LALT)) != 0u) {
|
|
|
|
set_fullscreen(!is_fullscreen());
|
|
|
|
break;
|
|
|
|
}
|
2022-02-17 06:03:00 +00:00
|
|
|
if (!ImGui::GetIO().WantCaptureKeyboard) {
|
2022-02-20 03:22:03 +00:00
|
|
|
SpecialKey specialKey{};
|
|
|
|
ModifierKey modifierKey{};
|
|
|
|
char chr = input::translate_key(event.key.keysym, specialKey, modifierKey);
|
|
|
|
if (chr != 0) {
|
|
|
|
modifierKey = input::translate_modifiers(event.key.keysym.mod);
|
|
|
|
g_AppDelegate->onCharKeyDown(chr, modifierKey, event.key.repeat != 0u);
|
|
|
|
} else if (specialKey != SpecialKey::None) {
|
|
|
|
modifierKey = input::translate_modifiers(event.key.keysym.mod);
|
|
|
|
g_AppDelegate->onSpecialKeyDown(specialKey, modifierKey, event.key.repeat != 0u);
|
|
|
|
} else if (modifierKey != ModifierKey::None) {
|
|
|
|
g_AppDelegate->onModifierKeyDown(modifierKey, event.key.repeat != 0u);
|
|
|
|
}
|
2022-02-17 06:03:00 +00:00
|
|
|
}
|
2022-02-16 09:23:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_KEYUP: {
|
2022-02-17 06:03:00 +00:00
|
|
|
if (!ImGui::GetIO().WantCaptureKeyboard) {
|
2022-02-20 03:22:03 +00:00
|
|
|
SpecialKey specialKey{};
|
|
|
|
ModifierKey modifierKey{};
|
|
|
|
char chr = input::translate_key(event.key.keysym, specialKey, modifierKey);
|
|
|
|
if (chr != 0) {
|
|
|
|
modifierKey = input::translate_modifiers(event.key.keysym.mod);
|
|
|
|
g_AppDelegate->onCharKeyUp(chr, modifierKey);
|
|
|
|
} else if (specialKey != SpecialKey::None) {
|
|
|
|
modifierKey = input::translate_modifiers(event.key.keysym.mod);
|
|
|
|
g_AppDelegate->onSpecialKeyUp(specialKey, modifierKey);
|
|
|
|
} else if (modifierKey != ModifierKey::None) {
|
|
|
|
g_AppDelegate->onModifierKeyUp(modifierKey);
|
|
|
|
}
|
2022-02-17 06:03:00 +00:00
|
|
|
}
|
2022-02-16 09:23:39 +00:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_TEXTINPUT: {
|
2022-02-17 06:03:00 +00:00
|
|
|
if (!ImGui::GetIO().WantCaptureKeyboard) {
|
2022-02-20 03:22:03 +00:00
|
|
|
std::string str;
|
|
|
|
str.assign(&event.text.text[0], SDL_TEXTINPUTEVENT_TEXT_SIZE);
|
|
|
|
g_AppDelegate->onTextInput(str);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_MOUSEBUTTONDOWN: {
|
|
|
|
if (!ImGui::GetIO().WantCaptureMouse) {
|
|
|
|
g_AppDelegate->onMouseButtonDown(event.button.x, event.button.y,
|
|
|
|
input::translate_mouse_button(event.button.button), event.button.clicks);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_MOUSEBUTTONUP: {
|
|
|
|
if (!ImGui::GetIO().WantCaptureMouse) {
|
|
|
|
g_AppDelegate->onMouseButtonUp(event.button.x, event.button.y,
|
|
|
|
input::translate_mouse_button(event.button.button));
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
case SDL_MOUSEMOTION: {
|
|
|
|
if (!ImGui::GetIO().WantCaptureMouse) {
|
|
|
|
g_AppDelegate->onMouseMove(event.motion.x, event.motion.y, event.motion.xrel, event.motion.yrel,
|
|
|
|
input::translate_mouse_button_state(event.motion.state));
|
2022-02-17 06:03:00 +00:00
|
|
|
}
|
2022-02-16 09:23:39 +00:00
|
|
|
break;
|
|
|
|
}
|
2022-02-16 07:05:42 +00:00
|
|
|
case SDL_QUIT:
|
|
|
|
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-06-12 21:09:47 +00:00
|
|
|
static SDL_Window* create_window(wgpu::BackendType type, bool fullscreen) {
|
2022-05-27 19:52:16 +00:00
|
|
|
Uint32 flags = SDL_WINDOW_ALLOW_HIGHDPI;
|
2022-06-12 21:09:47 +00:00
|
|
|
#if TARGET_OS_IOS || TARGET_OS_TV
|
2022-05-27 19:52:16 +00:00
|
|
|
flags |= SDL_WINDOW_FULLSCREEN;
|
|
|
|
#else
|
|
|
|
flags |= SDL_WINDOW_HIDDEN | SDL_WINDOW_RESIZABLE;
|
2022-06-12 21:09:47 +00:00
|
|
|
if (fullscreen) {
|
|
|
|
flags |= SDL_WINDOW_FULLSCREEN;
|
|
|
|
}
|
2022-05-27 19:52:16 +00:00
|
|
|
#endif
|
2022-05-24 00:26:35 +00:00
|
|
|
switch (type) {
|
|
|
|
#ifdef DAWN_ENABLE_BACKEND_VULKAN
|
|
|
|
case wgpu::BackendType::Vulkan:
|
|
|
|
flags |= SDL_WINDOW_VULKAN;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#ifdef DAWN_ENABLE_BACKEND_METAL
|
|
|
|
case wgpu::BackendType::Metal:
|
|
|
|
flags |= SDL_WINDOW_METAL;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
#ifdef DAWN_ENABLE_BACKEND_OPENGL
|
|
|
|
case wgpu::BackendType::OpenGL:
|
|
|
|
flags |= SDL_WINDOW_OPENGL;
|
|
|
|
break;
|
|
|
|
#endif
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
2022-06-12 21:09:47 +00:00
|
|
|
return SDL_CreateWindow("Metaforce", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1280,
|
|
|
|
#ifdef __SWITCH__
|
|
|
|
720,
|
|
|
|
#else
|
|
|
|
960,
|
|
|
|
#endif
|
|
|
|
flags);
|
2022-05-24 00:26:35 +00:00
|
|
|
}
|
|
|
|
|
2022-06-08 17:58:38 +00:00
|
|
|
wgpu::BackendType to_wgpu_backend(Backend backend) {
|
|
|
|
switch (backend) {
|
|
|
|
case Backend::WebGPU:
|
|
|
|
return wgpu::BackendType::WebGPU;
|
|
|
|
case Backend::D3D11:
|
|
|
|
return wgpu::BackendType::D3D11;
|
|
|
|
case Backend::D3D12:
|
|
|
|
return wgpu::BackendType::D3D12;
|
|
|
|
case Backend::Metal:
|
|
|
|
return wgpu::BackendType::Metal;
|
|
|
|
case Backend::Vulkan:
|
|
|
|
return wgpu::BackendType::Vulkan;
|
|
|
|
case Backend::OpenGL:
|
|
|
|
return wgpu::BackendType::OpenGL;
|
|
|
|
case Backend::OpenGLES:
|
|
|
|
return wgpu::BackendType::OpenGLES;
|
|
|
|
default:
|
|
|
|
return wgpu::BackendType::Null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
void app_run(std::unique_ptr<AppDelegate> app, Icon icon, int argc, char** argv, std::string_view configPath,
|
2022-06-12 21:09:47 +00:00
|
|
|
Backend desiredBackend, uint32_t msaa, uint16_t aniso, bool fullscreen) noexcept {
|
2022-02-16 09:23:39 +00:00
|
|
|
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-05-27 19:52:16 +00:00
|
|
|
g_configPath = configPath;
|
2022-02-23 06:39:48 +00:00
|
|
|
|
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-19 06:41:21 +00:00
|
|
|
unreachable();
|
2022-02-16 07:05:42 +00:00
|
|
|
}
|
|
|
|
|
2022-02-23 06:39:48 +00:00
|
|
|
#if !defined(_WIN32) && !defined(__APPLE__)
|
|
|
|
SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0");
|
|
|
|
#endif
|
2022-06-01 00:40:46 +00:00
|
|
|
#if SDL_VERSION_ATLEAST(2, 0, 18)
|
2022-04-04 00:22:07 +00:00
|
|
|
SDL_SetHint(SDL_HINT_SCREENSAVER_INHIBIT_ACTIVITY_NAME, "Metaforce");
|
2022-06-01 00:40:46 +00:00
|
|
|
#endif
|
|
|
|
#ifdef SDL_HINT_JOYSTICK_GAMECUBE_RUMBLE_BRAKE
|
|
|
|
SDL_SetHint(SDL_HINT_JOYSTICK_GAMECUBE_RUMBLE_BRAKE, "1");
|
|
|
|
#endif
|
2022-04-04 00:22:07 +00:00
|
|
|
|
|
|
|
SDL_DisableScreenSaver();
|
2022-04-04 00:17:11 +00:00
|
|
|
/* TODO: Make this an option rather than hard coding it */
|
2022-05-02 23:42:59 +00:00
|
|
|
SDL_SetHint(SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS, "1");
|
2022-02-23 06:39:48 +00:00
|
|
|
|
2022-06-08 17:58:38 +00:00
|
|
|
/* Attempt to create a window using the calling application's desired backend */
|
|
|
|
if (desiredBackend != Backend::Invalid) {
|
|
|
|
auto wgpuBackend = to_wgpu_backend(desiredBackend);
|
2022-06-12 21:09:47 +00:00
|
|
|
g_window = create_window(wgpuBackend, fullscreen);
|
2022-06-08 17:58:38 +00:00
|
|
|
if (g_window != nullptr && !gpu::initialize(g_window, wgpuBackend, msaa, aniso)) {
|
|
|
|
g_window = nullptr;
|
|
|
|
SDL_DestroyWindow(g_window);
|
2022-05-24 00:26:35 +00:00
|
|
|
}
|
2022-06-08 17:58:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
if (g_window == nullptr) {
|
|
|
|
for (const auto backendType : gpu::PreferredBackendOrder) {
|
2022-06-12 21:09:47 +00:00
|
|
|
auto* window = create_window(backendType, fullscreen);
|
2022-06-08 17:58:38 +00:00
|
|
|
if (window == nullptr) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
g_window = window;
|
|
|
|
if (gpu::initialize(window, backendType, msaa, aniso)) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
g_window = nullptr;
|
|
|
|
SDL_DestroyWindow(window);
|
2022-05-24 00:26:35 +00:00
|
|
|
}
|
2022-02-16 07:05:42 +00:00
|
|
|
}
|
2022-06-08 17:58:38 +00:00
|
|
|
|
2022-02-26 20:38:08 +00:00
|
|
|
if (g_window == nullptr) {
|
2022-02-16 07:05:42 +00:00
|
|
|
Log.report(logvisor::Fatal, FMT_STRING("Error creating window: {}"), SDL_GetError());
|
2022-02-19 06:41:21 +00:00
|
|
|
unreachable();
|
2022-02-16 07:05:42 +00:00
|
|
|
}
|
|
|
|
set_window_icon(std::move(icon));
|
|
|
|
|
2022-06-01 00:40:46 +00:00
|
|
|
// Initialize SDL_Renderer for ImGui when we can't use a Dawn backend
|
|
|
|
SDL_Renderer* renderer = nullptr;
|
|
|
|
if (gpu::g_backendType == wgpu::BackendType::Null) {
|
|
|
|
const auto flags = SDL_RENDERER_PRESENTVSYNC;
|
|
|
|
renderer = SDL_CreateRenderer(g_window, -1, flags | SDL_RENDERER_ACCELERATED);
|
|
|
|
if (renderer == nullptr) {
|
|
|
|
// Attempt fallback to SW renderer
|
|
|
|
renderer = SDL_CreateRenderer(g_window, -1, flags);
|
|
|
|
}
|
|
|
|
if (renderer == nullptr) {
|
|
|
|
Log.report(logvisor::Fatal, FMT_STRING("Failed to initialize SDL renderer: {}"), SDL_GetError());
|
|
|
|
unreachable();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
SDL_ShowWindow(g_window);
|
2022-02-19 06:41:21 +00:00
|
|
|
gfx::initialize();
|
2022-02-16 23:13:40 +00:00
|
|
|
|
2022-02-19 05:33:56 +00:00
|
|
|
imgui::create_context();
|
2022-02-26 20:38:08 +00:00
|
|
|
const auto size = get_window_size();
|
|
|
|
Log.report(logvisor::Info, FMT_STRING("Using framebuffer size {}x{} scale {}"), size.fb_width, size.fb_height,
|
|
|
|
size.scale);
|
|
|
|
g_AppDelegate->onImGuiInit(size.scale);
|
2022-06-01 00:40:46 +00:00
|
|
|
imgui::initialize(g_window, renderer);
|
2022-02-17 06:03:00 +00:00
|
|
|
g_AppDelegate->onImGuiAddTextures();
|
|
|
|
|
2022-02-16 09:23:39 +00:00
|
|
|
g_AppDelegate->onAppLaunched();
|
2022-02-26 20:38:08 +00:00
|
|
|
g_AppDelegate->onAppWindowResized(size);
|
2022-02-17 06:03:00 +00:00
|
|
|
|
2022-02-16 23:13:40 +00:00
|
|
|
while (poll_events()) {
|
2022-06-12 21:09:47 +00:00
|
|
|
if (g_paused) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2022-02-26 20:38:08 +00:00
|
|
|
imgui::new_frame(g_windowSize);
|
2022-02-19 05:33:56 +00:00
|
|
|
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-06-12 21:09:47 +00:00
|
|
|
if (!view) {
|
|
|
|
ImGui::EndFrame();
|
|
|
|
// Force swapchain recreation
|
|
|
|
resize_swapchain(true);
|
|
|
|
continue;
|
|
|
|
}
|
2022-03-16 02:38:55 +00:00
|
|
|
gfx::begin_frame();
|
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-03-16 03:04:43 +00:00
|
|
|
gfx::end_frame(encoder);
|
2022-05-09 21:13:38 +00:00
|
|
|
gfx::render(encoder);
|
2022-02-16 23:13:40 +00:00
|
|
|
{
|
2022-02-19 05:33:56 +00:00
|
|
|
const std::array attachments{
|
|
|
|
wgpu::RenderPassColorAttachment{
|
|
|
|
.view = view,
|
|
|
|
.loadOp = wgpu::LoadOp::Clear,
|
|
|
|
.storeOp = wgpu::StoreOp::Store,
|
|
|
|
},
|
|
|
|
};
|
|
|
|
auto renderPassDescriptor = wgpu::RenderPassDescriptor{
|
2022-05-09 21:13:38 +00:00
|
|
|
.label = "Post render pass",
|
2022-02-19 05:33:56 +00:00
|
|
|
.colorAttachmentCount = attachments.size(),
|
|
|
|
.colorAttachments = attachments.data(),
|
|
|
|
};
|
|
|
|
auto pass = encoder.BeginRenderPass(&renderPassDescriptor);
|
2022-05-09 21:13:38 +00:00
|
|
|
// Copy EFB -> XFB (swapchain)
|
|
|
|
pass.SetPipeline(gpu::g_CopyPipeline);
|
|
|
|
pass.SetBindGroup(0, gpu::g_CopyBindGroup);
|
|
|
|
pass.Draw(3);
|
|
|
|
// Render ImGui
|
2022-02-19 05:33:56 +00:00
|
|
|
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-23 08:19:19 +00:00
|
|
|
Log.report(logvisor::Info, FMT_STRING("Application exiting"));
|
2022-02-17 06:03:00 +00:00
|
|
|
g_AppDelegate->onAppExiting();
|
|
|
|
|
2022-02-19 05:33:56 +00:00
|
|
|
imgui::shutdown();
|
2022-02-19 06:41:21 +00:00
|
|
|
gfx::shutdown();
|
2022-02-19 05:33:56 +00:00
|
|
|
gpu::shutdown();
|
2022-06-01 00:40:46 +00:00
|
|
|
if (renderer != nullptr) {
|
|
|
|
SDL_DestroyRenderer(renderer);
|
|
|
|
}
|
2022-02-26 20:38:08 +00:00
|
|
|
SDL_DestroyWindow(g_window);
|
2022-06-12 21:09:47 +00:00
|
|
|
g_window = nullptr;
|
2022-04-04 00:22:07 +00:00
|
|
|
SDL_EnableScreenSaver();
|
2022-02-16 07:05:42 +00:00
|
|
|
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-26 20:38:08 +00:00
|
|
|
int width, height, fb_w, fb_h;
|
|
|
|
SDL_GetWindowSize(g_window, &width, &height);
|
2022-05-27 19:52:16 +00:00
|
|
|
#if DAWN_ENABLE_BACKEND_METAL
|
|
|
|
SDL_Metal_GetDrawableSize(g_window, &fb_w, &fb_h);
|
|
|
|
#else
|
2022-02-26 20:38:08 +00:00
|
|
|
SDL_GL_GetDrawableSize(g_window, &fb_w, &fb_h);
|
2022-05-27 19:52:16 +00:00
|
|
|
#endif
|
2022-02-26 21:28:58 +00:00
|
|
|
float scale = static_cast<float>(fb_w) / static_cast<float>(width);
|
2022-02-26 21:28:21 +00:00
|
|
|
#ifndef __APPLE__
|
|
|
|
if (SDL_GetDisplayDPI(SDL_GetWindowDisplayIndex(g_window), nullptr, &scale, nullptr) == 0) {
|
|
|
|
scale /= 96.f;
|
|
|
|
}
|
|
|
|
#endif
|
2022-02-26 20:38:08 +00:00
|
|
|
return {
|
|
|
|
.width = static_cast<uint32_t>(width),
|
|
|
|
.height = static_cast<uint32_t>(height),
|
|
|
|
.fb_width = static_cast<uint32_t>(fb_w),
|
|
|
|
.fb_height = static_cast<uint32_t>(fb_h),
|
2022-02-26 21:28:21 +00:00
|
|
|
.scale = scale,
|
2022-02-26 20:38:08 +00:00
|
|
|
};
|
2022-02-16 05:21:24 +00:00
|
|
|
}
|
2022-02-19 05:33:56 +00:00
|
|
|
|
2022-02-26 20:38:08 +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-06-12 21:09:47 +00:00
|
|
|
case wgpu::BackendType::Null:
|
|
|
|
return Backend::Null;
|
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
|
|
|
|
2022-06-12 21:09:47 +00:00
|
|
|
std::vector<Backend> get_available_backends() noexcept {
|
|
|
|
return {
|
|
|
|
#ifdef DAWN_ENABLE_BACKEND_D3D12
|
|
|
|
Backend::D3D12,
|
|
|
|
#endif
|
|
|
|
#ifdef DAWN_ENABLE_BACKEND_METAL
|
|
|
|
Backend::Metal,
|
|
|
|
#endif
|
|
|
|
#ifdef DAWN_ENABLE_BACKEND_VULKAN
|
|
|
|
Backend::Vulkan,
|
|
|
|
#endif
|
|
|
|
#ifdef DAWN_ENABLE_BACKEND_DESKTOP_GL
|
|
|
|
Backend::OpenGL,
|
|
|
|
#endif
|
|
|
|
#ifdef DAWN_ENABLE_BACKEND_OPENGLES
|
|
|
|
Backend::OpenGLES,
|
|
|
|
#endif
|
|
|
|
#ifdef DAWN_ENABLE_BACKEND_NULL
|
|
|
|
Backend::Null,
|
|
|
|
#endif
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2022-02-19 05:33:56 +00:00
|
|
|
std::string_view get_backend_string() noexcept { return magic_enum::enum_name(gpu::g_backendType); }
|
|
|
|
|
2022-06-12 21:09:47 +00:00
|
|
|
Backend backend_from_string(std::string_view backend) {
|
2022-06-08 17:58:38 +00:00
|
|
|
if (backend.empty()) {
|
|
|
|
return Backend::Invalid;
|
|
|
|
}
|
|
|
|
std::string tmp = backend.data();
|
|
|
|
std::transform(tmp.begin(), tmp.end(), tmp.begin(), [](unsigned char c) { return std::tolower(c); });
|
|
|
|
#if DAWN_ENABLE_BACKEND_WEBGPU
|
|
|
|
if (tmp == "webgpu" || tmp == "wgpu") {
|
|
|
|
return Backend::WebGPU;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#if DAWN_ENABLE_BACKEND_D3D11
|
|
|
|
if (tmp == "d3d11") {
|
|
|
|
return Backend::D3D11;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#if DAWN_ENABLE_BACKEND_D3D12
|
|
|
|
if (tmp == "d3d12") {
|
|
|
|
return Backend::D3D12;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#if DAWN_ENABLE_BACKEND_METAL
|
|
|
|
if (tmp == "metal") {
|
|
|
|
return Backend::Metal;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#if DAWN_ENABLE_BACKEND_DESKTOP_GL || DAWN_ENABLE_BACKEND_OPENGL
|
|
|
|
if (tmp == "gl" || tmp == "opengl") {
|
|
|
|
return Backend::OpenGL;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#if DAWN_ENABLE_BACKEND_OPENGLES
|
|
|
|
if (tmp == "gles" || tmp == "opengles") {
|
|
|
|
return Backend::OpenGLES;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#if DAWN_ENABLE_BACKEND_VULKAN
|
|
|
|
if (tmp == "vulkan") {
|
|
|
|
return Backend::Vulkan;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
#if DAWN_ENABLE_BACKEND_NULL
|
|
|
|
if (tmp == "null") {
|
|
|
|
return Backend::Null;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
return Backend::Invalid;
|
|
|
|
}
|
|
|
|
|
2022-06-12 21:09:47 +00:00
|
|
|
std::string_view backend_to_string(Backend backend) {
|
|
|
|
switch (backend) {
|
|
|
|
case Backend::Null:
|
|
|
|
return "null"sv;
|
|
|
|
case Backend::WebGPU:
|
|
|
|
return "webgpu"sv;
|
|
|
|
case Backend::D3D11:
|
|
|
|
return "d3d11"sv;
|
|
|
|
case Backend::D3D12:
|
|
|
|
return "d3d12"sv;
|
|
|
|
case Backend::Metal:
|
|
|
|
return "metal"sv;
|
|
|
|
case Backend::Vulkan:
|
|
|
|
return "vulkan"sv;
|
|
|
|
case Backend::OpenGL:
|
|
|
|
return "opengl"sv;
|
|
|
|
case Backend::OpenGLES:
|
|
|
|
return "opengles"sv;
|
|
|
|
case Backend::Invalid:
|
|
|
|
return "auto";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-16 05:21:24 +00:00
|
|
|
void set_fullscreen(bool fullscreen) noexcept {
|
2022-02-26 20:38:08 +00:00
|
|
|
SDL_SetWindowFullscreen(g_window, fullscreen ? SDL_WINDOW_FULLSCREEN : 0);
|
2022-02-16 05:21:24 +00:00
|
|
|
}
|
2022-02-16 09:23:39 +00:00
|
|
|
|
2022-06-12 21:09:47 +00:00
|
|
|
bool is_fullscreen() noexcept { return (SDL_GetWindowFlags(g_window) & SDL_WINDOW_FULLSCREEN) != 0u; }
|
|
|
|
|
2022-05-02 23:42:59 +00:00
|
|
|
uint32_t get_which_controller_for_player(int32_t index) noexcept { return input::get_instance_for_player(index); }
|
2022-02-22 09:12:15 +00:00
|
|
|
int32_t get_controller_player_index(uint32_t instance) noexcept { return input::player_index(instance); }
|
|
|
|
|
|
|
|
void set_controller_player_index(uint32_t instance, int32_t index) noexcept {
|
|
|
|
input::set_player_index(instance, index);
|
2022-02-16 05:21:24 +00:00
|
|
|
}
|
2022-02-19 05:33:56 +00:00
|
|
|
|
2022-02-22 09:12:15 +00:00
|
|
|
bool is_controller_gamecube(uint32_t instance) noexcept { return input::is_gamecube(instance); }
|
2022-02-19 05:33:56 +00:00
|
|
|
|
2022-02-22 09:12:15 +00:00
|
|
|
bool controller_has_rumble(uint32_t instance) noexcept { return input::controller_has_rumble(instance); }
|
2022-02-19 05:33:56 +00:00
|
|
|
|
2022-02-22 09:12:15 +00:00
|
|
|
void controller_rumble(uint32_t instance, uint16_t low_freq_intensity, uint16_t high_freq_intensity,
|
|
|
|
uint32_t duration_ms) noexcept {
|
|
|
|
input::controller_rumble(instance, low_freq_intensity, high_freq_intensity, duration_ms);
|
2022-02-16 05:21:24 +00:00
|
|
|
}
|
2022-02-26 20:38:08 +00:00
|
|
|
|
2022-05-08 04:20:52 +00:00
|
|
|
uint32_t get_controller_count() noexcept { return input::controller_count(); }
|
2022-02-22 09:12:15 +00:00
|
|
|
std::string get_controller_name(uint32_t instance) noexcept { return input::controller_name(instance); }
|
2022-02-16 05:21:24 +00:00
|
|
|
} // namespace aurora
|