AronaCore/core/application/application.cpp
2024-02-02 00:37:22 +08:00

246 lines
6.8 KiB
C++

#include "application.h"
#include <assert.h>
#include <iostream>
#include "command_line.h"
#include "imgui_impl_sdl3.h"
#include "imgui_internal.h"
#include "filesystem/stb_image.h"
#include "rhi/texture.h"
#include "rhi/opengl/renderer_opengl.h"
#include "spdlog/async.h"
#include "spdlog/spdlog.h"
#include "spdlog/sinks/basic_file_sink.h"
#if WIN32
#include "rhi/windows/dx11/renderer_dx11.h"
#endif
bool g_is_running = true;
bool g_exit_requested = false;
slang::IGlobalSession* g_slang_global_session = nullptr;
application* g_app_instance = nullptr;
application::~application()
{
application::shutdown();
}
void application::init(window_params in_window_params, int argc, char** argv)
{
slang::createGlobalSession(&g_slang_global_session);
try
{
auto async_file = spdlog::basic_logger_mt<spdlog::async_factory>("async_file_logger", "logs/log.txt");
}
catch (const spdlog::spdlog_ex &ex)
{
std::cout << "Log init failed: " << ex.what() << std::endl;
}
command_line::instance().init(argc, argv);
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
// Setup Dear ImGui context
IMGUI_CHECKVERSION();
init_imgui(ImGui::CreateContext());
ImGuiIO& io = ImGui::GetIO();
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
ImGui::StyleColorsDark();
//ImGui::StyleColorsLight();
unsigned int window_flags = 0;
#if WIN32
bool use_dx11 = false;
bool use_dx12 = false;
bool use_vulkan = false;
bool use_opengl = false;
#elif __APPLE__
bool use_vulkan = true;
bool use_opengl = false;
bool use_metal = false;
#else
bool use_vulkan = true;
bool use_opengl = false;
#endif
#if WIN32
command_line::instance().get_arg("dx11", use_dx11);
command_line::instance().get_arg("dx12", use_dx12);
command_line::instance().get_arg("vulkan", use_vulkan);
command_line::instance().get_arg("opengl", use_opengl);
// only one renderer can be used at a time
const int renderer_count = use_dx11 + use_dx12 + use_vulkan + use_opengl;
assert(renderer_count <= 1);
// if no renderer is specified, use dx11
if (!(use_dx11 || use_dx12 || use_vulkan || use_opengl))
{
use_dx11 = true;
}
if (use_dx11)
{
renderer_ = new renderer_dx11();
}
else if (use_opengl)
{
renderer_ = new renderer_opengl();
window_flags |= SDL_WINDOW_OPENGL;
}
// if (use_dx12)
// {
// renderer_ = new renderer_dx12();
// }
// if (use_vulkan)
// {
// renderer_ = new renderer_vulkan();
// window_flags |= SDL_WINDOW_VULKAN;
// }
#elif __APPLE__
const int renderer_count = use_metal || use_vulkan || use_opengl;
assert(renderer_count <= 1);
if (!(use_metal || use_vulkan || use_opengl))
{
use_metal = true;
}
if (use_metal)
{
renderer_ = new renderer_metal();
window_flags |= SDL_WINDOW_METAL;
}
else if (use_vulkan)
{
renderer_ = new renderer_vulkan();
window_flags |= SDL_WINDOW_VULKAN;
}
else if (use_opengl)
{
renderer_ = new renderer_opengl();
window_flags |= SDL_WINDOW_OPENGL;
}
#else
const int renderer_count = use_vulkan || use_opengl;
assert(renderer_count <= 1);
if (!(use_vulkan || use_opengl))
{
use_vulkan = true;
}
if (use_vulkan)
{
renderer_ = new renderer_vulkan();
window_flags |= SDL_WINDOW_VULKAN;
}
else if (use_opengl)
{
renderer_ = new renderer_opengl();
window_flags |= SDL_WINDOW_OPENGL;
}
#endif
// if (!renderer_)
// renderer_ = new renderer_null();
renderer_->pre_init();
if (in_window_params.fullscreen)
window_flags |= SDL_WINDOW_FULLSCREEN;
if (in_window_params.borderless)
window_flags |= SDL_WINDOW_BORDERLESS;
if (in_window_params.resizable)
window_flags |= SDL_WINDOW_RESIZABLE;
if (in_window_params.minimized)
window_flags |= SDL_WINDOW_MINIMIZED;
if (in_window_params.maximized)
window_flags |= SDL_WINDOW_MAXIMIZED;
if (in_window_params.hi_dpi)
window_flags |= SDL_WINDOW_HIGH_PIXEL_DENSITY;
if (in_window_params.always_on_top)
window_flags |= SDL_WINDOW_ALWAYS_ON_TOP;
// new SDL window
window_ = SDL_CreateWindow(in_window_params.title.c_str(), in_window_params.width, in_window_params.height, window_flags);
if (!window_)
{
spdlog::error("Failed to create SDL window: {}", SDL_GetError());
return;
}
SDL_SetWindowPosition(window_, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED);
SDL_ShowWindow(window_);
renderer_->init(window_);
renderer_->init_slang(R"(E:\Projects\AronaStudio\Arona\shaders\)");
renderer_->resize(in_window_params.width, in_window_params.height);
g_is_running = true;
}
int application::run()
{
while (!g_exit_requested)
{
SDL_Event event;
while (SDL_PollEvent(&event))
{
ImGui_ImplSDL3_ProcessEvent(&event);
if (event.type == SDL_EVENT_QUIT)
g_exit_requested = true;
if (event.type == SDL_EVENT_WINDOW_CLOSE_REQUESTED && event.window.windowID == SDL_GetWindowID(window_))
g_exit_requested = true;
if (event.type == SDL_EVENT_WINDOW_RESIZED)
{
const int width = event.window.data1;
const int height = event.window.data2;
renderer_->resize(width, height);
}
}
if (g_exit_requested)
break;
renderer_->new_frame(window_);
draw_gui();
renderer_->end_frame(window_);
}
return 0;
}
void application::shutdown()
{
renderer_->shutdown();
ImGui::DestroyContext();
delete renderer_;
}
std::shared_ptr<texture> application::load_texture(const std::string& path) const
{
int width = 0;
int height = 0;
unsigned char* image_data = stbi_load(path.c_str(), &width, &height, nullptr, 4);
if (!image_data)
{
spdlog::error("Failed to load texture: {}", path.c_str());
return nullptr;
}
const auto texture = renderer_->create_texture(image_data, width, height);
stbi_image_free(image_data);
return texture;
}
std::shared_ptr<texture> application::create_texture(const unsigned char* data, const int width, const int height) const
{
return renderer_->create_texture(data, width, height);
}
std::shared_ptr<render_target> application::create_render_target(const int width, const int height, texture_format format) const
{
return renderer_->create_render_target(width, height, format);
}