diff --git a/CMakeLists.txt b/CMakeLists.txt index ed7834f..446d88d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -19,7 +19,7 @@ set(AURORA_SDL3_VERSION "3.4.4" CACHE STRING "SDL3 version tag (https://github.c set(AURORA_NOD_VERSION "v2.0.0-alpha.8" CACHE STRING "nod version tag (https://github.com/encounter/nod/releases)") # Platform-specific defaults -if (CMAKE_CROSSCOMPILING OR EMSCRIPTEN) +if (CMAKE_CROSSCOMPILING) # Cross-compiling: vendor everything, don't use system packages set(_default_provider "vendor") set(_default_linkage "static") diff --git a/cmake/aurora_core.cmake b/cmake/aurora_core.cmake index 5e8d03b..e6514a9 100644 --- a/cmake/aurora_core.cmake +++ b/cmake/aurora_core.cmake @@ -37,16 +37,9 @@ if(AURORA_ENABLE_RMLUI) endif () if (AURORA_ENABLE_GX) - target_compile_definitions(aurora_core PUBLIC AURORA_ENABLE_GX) - target_sources(aurora_core PRIVATE lib/webgpu/gpu.cpp lib/webgpu/gpu_cache.cpp) - if (EMSCRIPTEN) - target_link_options(aurora_core PUBLIC -sUSE_WEBGPU=1 -sASYNCIFY -sEXIT_RUNTIME) - target_compile_definitions(aurora_core PRIVATE ENABLE_BACKEND_WEBGPU) - else () - target_link_libraries(aurora_core PRIVATE dawn::webgpu_dawn) - target_sources(aurora_core PRIVATE lib/dawn/BackendBinding.cpp) - target_compile_definitions(aurora_core PRIVATE WEBGPU_DAWN) - endif () + target_compile_definitions(aurora_core PUBLIC AURORA_ENABLE_GX WEBGPU_DAWN) + target_sources(aurora_core PRIVATE lib/webgpu/gpu.cpp lib/webgpu/gpu_cache.cpp lib/dawn/BackendBinding.cpp) + target_link_libraries(aurora_core PRIVATE dawn::webgpu_dawn) if (DAWN_ENABLE_VULKAN) target_compile_definitions(aurora_core PRIVATE DAWN_ENABLE_BACKEND_VULKAN) endif () diff --git a/cmake/aurora_gx.cmake b/cmake/aurora_gx.cmake index f59423f..dbaf5f3 100644 --- a/cmake/aurora_gx.cmake +++ b/cmake/aurora_gx.cmake @@ -39,11 +39,5 @@ add_library(aurora::gx ALIAS aurora_gx) set_target_properties(aurora_gx PROPERTIES FOLDER "aurora") target_link_libraries(aurora_gx PUBLIC aurora::core xxhash) -target_link_libraries(aurora_gx PRIVATE absl::btree absl::flat_hash_map sqlite3 TracyClient) -if (EMSCRIPTEN) - target_link_options(aurora_gx PUBLIC -sUSE_WEBGPU=1 -sASYNCIFY -sEXIT_RUNTIME) - target_compile_definitions(aurora_gx PRIVATE ENABLE_BACKEND_WEBGPU) -else () - target_link_libraries(aurora_gx PRIVATE dawn::webgpu_dawn) - target_compile_definitions(aurora_gx PRIVATE WEBGPU_DAWN) -endif () +target_link_libraries(aurora_gx PRIVATE absl::btree absl::flat_hash_map dawn::webgpu_dawn sqlite3 TracyClient) +target_compile_definitions(aurora_gx PRIVATE WEBGPU_DAWN) diff --git a/extern/CMakeLists.txt b/extern/CMakeLists.txt index a72e857..51cb538 100644 --- a/extern/CMakeLists.txt +++ b/extern/CMakeLists.txt @@ -3,45 +3,39 @@ include(FetchContent) # Don't build tests for third party dependencies set(BUILD_TESTING OFF CACHE INTERNAL "Build tests") -if (NOT EMSCRIPTEN) - if (AURORA_ENABLE_GX) - include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/AuroraDawnProvider.cmake) - endif () - - # Abseil is needed for core libraries. It normally comes via Dawn's vendor build. - # Otherwise prefer a system package and only fetch it as a last resort. - if (NOT TARGET absl::flat_hash_map OR NOT TARGET absl::btree) - find_package(absl CONFIG QUIET GLOBAL) - endif () - - if (TARGET absl::flat_hash_map AND TARGET absl::btree) - message(STATUS "aurora: Using system/existing abseil") - else () - message(STATUS "aurora: Fetching abseil-cpp (standalone)") - if(NOT DEFINED CMAKE_MSVC_RUNTIME_LIBRARY OR CMAKE_MSVC_RUNTIME_LIBRARY MATCHES "DLL$") - set(ABSL_MSVC_STATIC_RUNTIME OFF CACHE INTERNAL "Link static runtime libraries") - else() - set(ABSL_MSVC_STATIC_RUNTIME ON CACHE INTERNAL "Link static runtime libraries") - endif() - set(ABSL_PROPAGATE_CXX_STD ON) - FetchContent_Declare(abseil-cpp - URL https://github.com/abseil/abseil-cpp/archive/refs/tags/20240722.0.tar.gz - DOWNLOAD_EXTRACT_TIMESTAMP TRUE - EXCLUDE_FROM_ALL - ) - FetchContent_MakeAvailable(abseil-cpp) - if (NOT TARGET absl::flat_hash_map OR NOT TARGET absl::btree) - message(FATAL_ERROR "Failed to make abseil-cpp available") - endif () - endif () - - include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/AuroraSDL3Provider.cmake) -else () - set(ABSL_PROPAGATE_CXX_STD ON) - add_subdirectory(dawn/third_party/abseil-cpp EXCLUDE_FROM_ALL) - set(AURORA_SDL3_TARGET SDL3::SDL3-static CACHE INTERNAL "SDL3 target for emscripten") +if (AURORA_ENABLE_GX) + include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/AuroraDawnProvider.cmake) endif () +# Abseil is needed for core libraries. It normally comes via Dawn's vendor build. +# Otherwise prefer a system package and only fetch it as a last resort. +if (NOT TARGET absl::flat_hash_map OR NOT TARGET absl::btree) + find_package(absl CONFIG QUIET GLOBAL) +endif () + +if (TARGET absl::flat_hash_map AND TARGET absl::btree) + message(STATUS "aurora: Using system/existing abseil") +else () + message(STATUS "aurora: Fetching abseil-cpp (standalone)") + if(NOT DEFINED CMAKE_MSVC_RUNTIME_LIBRARY OR CMAKE_MSVC_RUNTIME_LIBRARY MATCHES "DLL$") + set(ABSL_MSVC_STATIC_RUNTIME OFF CACHE INTERNAL "Link static runtime libraries") + else() + set(ABSL_MSVC_STATIC_RUNTIME ON CACHE INTERNAL "Link static runtime libraries") + endif() + set(ABSL_PROPAGATE_CXX_STD ON) + FetchContent_Declare(abseil-cpp + URL https://github.com/abseil/abseil-cpp/archive/refs/tags/20240722.0.tar.gz + DOWNLOAD_EXTRACT_TIMESTAMP TRUE + EXCLUDE_FROM_ALL + ) + FetchContent_MakeAvailable(abseil-cpp) + if (NOT TARGET absl::flat_hash_map OR NOT TARGET absl::btree) + message(FATAL_ERROR "Failed to make abseil-cpp available") + endif () +endif () + +include(${CMAKE_CURRENT_SOURCE_DIR}/../cmake/AuroraSDL3Provider.cmake) + if (NOT TARGET xxhash) message(STATUS "aurora: Fetching xxhash") FetchContent_Declare(xxhash diff --git a/lib/imgui.cpp b/lib/imgui.cpp index c7077be..2956e39 100644 --- a/lib/imgui.cpp +++ b/lib/imgui.cpp @@ -146,8 +146,7 @@ void render(const wgpu::RenderPassEncoder& pass) noexcept { } ImTextureID add_texture(uint32_t width, uint32_t height, const uint8_t* data) noexcept { - if (g_useSdlRenderer) { - SDL_Renderer* renderer = window::get_sdl_renderer(); + if (SDL_Renderer* renderer = window::get_sdl_renderer()) { SDL_Texture* texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_STATIC, width, height); SDL_UpdateTexture(texture, nullptr, data, width * 4); SDL_SetTextureScaleMode(texture, SDL_SCALEMODE_LINEAR); diff --git a/lib/webgpu/gpu.cpp b/lib/webgpu/gpu.cpp index df4f8b1..a286570 100644 --- a/lib/webgpu/gpu.cpp +++ b/lib/webgpu/gpu.cpp @@ -49,7 +49,9 @@ wgpu::Instance g_instance; static wgpu::AdapterInfo g_adapterInfo; static wgpu::SurfaceCapabilities g_surfaceCapabilities; -static wgpu::PresentMode best_present_mode(bool vsync) { +namespace { + +wgpu::PresentMode best_present_mode(bool vsync) { const auto supports = [](const wgpu::PresentMode candidate) { for (size_t i = 0; i < g_surfaceCapabilities.presentModeCount; ++i) { if (g_surfaceCapabilities.presentModes[i] == candidate) { @@ -74,6 +76,31 @@ static wgpu::PresentMode best_present_mode(bool vsync) { return wgpu::PresentMode::Fifo; } +wgpu::TextureFormat to_linear(wgpu::TextureFormat format) { + if (format == wgpu::TextureFormat::RGBA8UnormSrgb) { + return wgpu::TextureFormat::RGBA8Unorm; + } + if (format == wgpu::TextureFormat::BGRA8UnormSrgb) { + return wgpu::TextureFormat::BGRA8Unorm; + } + return format; +} + +wgpu::TextureFormat best_surface_format() { + if (g_surfaceCapabilities.formatCount == 0) { + return wgpu::TextureFormat::Undefined; + } + for (size_t i = 0; i < g_surfaceCapabilities.formatCount; ++i) { + const auto format = to_linear(g_surfaceCapabilities.formats[i]); + if (format == wgpu::TextureFormat::RGBA8Unorm || format == wgpu::TextureFormat::BGRA8Unorm) { + return format; + } + } + return g_surfaceCapabilities.formats[0]; +} + +} // namespace + TextureWithSampler create_render_texture(uint32_t width, uint32_t height, bool multisampled) { const wgpu::Extent3D size{ .width = width, @@ -349,16 +376,6 @@ static wgpu::BackendType to_wgpu_backend(AuroraBackend backend) { } static bool create_surface() { -#ifdef EMSCRIPTEN - const WGPUSurfaceDescriptorFromCanvasHTMLSelector canvasDescriptor{ - .chain = {.sType = WGPUSType_SurfaceDescriptorFromCanvasHTMLSelector}, - .selector = "#canvas", - }; - const wgpu::SurfaceDescriptor surfaceDescriptor{ - .nextInChain = reinterpret_cast(&canvasDescriptor.chain), - .label = "Surface", - }; -#else SDL_Window* window = window::get_sdl_window(); if (window == nullptr) { Log.error("Failed to create surface: no window"); @@ -373,7 +390,6 @@ static bool create_surface() { .nextInChain = chainedDescriptor.get(), .label = "Surface", }; -#endif g_surface = g_instance.CreateSurface(&surfaceDescriptor); if (!g_surface) { Log.error("Failed to create surface"); @@ -384,10 +400,7 @@ static bool create_surface() { bool initialize(AuroraBackend auroraBackend) { if (!g_instance) { -#ifdef WEBGPU_DAWN - Log.info("Initializing Dawn"); -#endif - Log.info("Creating WGPU instance"); + Log.info("Creating WebGPU instance"); const std::array requiredInstanceFeatures{ wgpu::InstanceFeatureName::TimedWaitAny, }; @@ -402,17 +415,11 @@ bool initialize(AuroraBackend auroraBackend) { #endif g_instance = wgpu::CreateInstance(&instanceDescriptor); if (!g_instance) { - Log.error("Failed to create WGPU instance"); + Log.error("Failed to create WebGPU instance"); return false; } } const wgpu::BackendType backend = to_wgpu_backend(auroraBackend); -#ifdef EMSCRIPTEN - if (backend != wgpu::BackendType::WebGPU) { - Log.warn("Backend type {} unsupported", magic_enum::enum_name(backend)); - return false; - } -#endif Log.info("Attempting to initialize {}", magic_enum::enum_name(backend)); #if 0 // D3D12's debug layer is very slow @@ -609,13 +616,8 @@ bool initialize(AuroraBackend auroraBackend) { Log.error("Surface has no present modes"); return false; } - auto surfaceFormat = g_surfaceCapabilities.formats[0]; + auto surfaceFormat = best_surface_format(); auto presentMode = best_present_mode(g_config.vsync); - if (surfaceFormat == wgpu::TextureFormat::RGBA8UnormSrgb) { - surfaceFormat = wgpu::TextureFormat::RGBA8Unorm; - } else if (surfaceFormat == wgpu::TextureFormat::BGRA8UnormSrgb) { - surfaceFormat = wgpu::TextureFormat::BGRA8Unorm; - } Log.info("Using surface format {}, present mode {}", magic_enum::enum_name(surfaceFormat), magic_enum::enum_name(presentMode)); const auto size = window::get_window_size(); diff --git a/lib/webgpu/wgpu.hpp b/lib/webgpu/wgpu.hpp index a449fb7..ba7ebea 100644 --- a/lib/webgpu/wgpu.hpp +++ b/lib/webgpu/wgpu.hpp @@ -1,9 +1,6 @@ #pragma once #include -#ifdef EMSCRIPTEN -#include -#endif #include diff --git a/lib/window.cpp b/lib/window.cpp index 63e4af8..b5374ca 100644 --- a/lib/window.cpp +++ b/lib/window.cpp @@ -38,50 +38,32 @@ bool g_frameBufferAspectFit = false; AuroraWindowSize g_windowSize; std::vector g_events; -inline bool operator==(const AuroraWindowSize& lhs, const AuroraWindowSize& rhs) { +bool operator==(const AuroraWindowSize& lhs, const AuroraWindowSize& rhs) { return lhs.width == rhs.width && lhs.height == rhs.height && lhs.fb_width == rhs.fb_width && lhs.fb_height == rhs.fb_height && lhs.native_fb_height == rhs.native_fb_height && lhs.native_fb_width == rhs.native_fb_width && lhs.scale == rhs.scale; } -Vec2 scale_frame_buffer_to_aspect(int base_width, int base_height, float scale, float aspect) { - if (base_width <= 0 || base_height <= 0 || scale <= 0.f || aspect <= 0.f) { - return {std::max(base_width, 1), std::max(base_height, 1)}; +Vec2 scale_frame_buffer_to_aspect(int w, int h, float scale, float aspect) { + if (w <= 0 || h <= 0 || scale <= 0.f || aspect <= 0.f) { + return {std::max(w, 1), std::max(h, 1)}; } - - const int scaled_base_width = std::max(1, static_cast(std::lround(static_cast(base_width) * scale))); - const int scaled_base_height = std::max(1, static_cast(std::lround(static_cast(base_height) * scale))); - const float base_aspect = static_cast(base_width) / static_cast(base_height); - if (aspect >= base_aspect) { - return { - std::max(1, static_cast(std::lround(static_cast(scaled_base_height) * aspect))), - scaled_base_height, - }; + const int baseW = std::max(1, static_cast(std::lround(static_cast(w) * scale))); + const int baseH = std::max(1, static_cast(std::lround(static_cast(h) * scale))); + if (aspect >= static_cast(w) / static_cast(h)) { + return {std::max(1, static_cast(std::lround(static_cast(baseH) * aspect))), baseH}; } - - return { - scaled_base_width, - std::max(1, static_cast(std::lround(static_cast(scaled_base_width) / aspect))), - }; + return {baseW, std::max(1, static_cast(std::lround(static_cast(baseW) / aspect)))}; } Vec2 fit_frame_buffer_to_aspect(int width, int height, float aspect) { if (width <= 0 || height <= 0 || aspect <= 0.f) { return {std::max(width, 1), std::max(height, 1)}; } - - const float targetAspect = static_cast(width) / static_cast(height); - if (targetAspect > aspect) { - return { - std::max(1, static_cast(std::lround(static_cast(height) * aspect))), - height, - }; + if (static_cast(width) / static_cast(height) > aspect) { + return {std::max(1, static_cast(std::lround(static_cast(height) * aspect))), height}; } - - return { - width, - std::max(1, static_cast(std::lround(static_cast(width) / aspect))), - }; + return {width, std::max(1, static_cast(std::lround(static_cast(width) / aspect)))}; } void resize_swapchain() noexcept { @@ -95,6 +77,11 @@ void resize_swapchain() noexcept { } } g_windowSize = size; + if (g_renderer != nullptr) { + SDL_SetRenderLogicalPresentation(g_renderer, static_cast(size.native_fb_width), + static_cast(size.native_fb_height), SDL_LOGICAL_PRESENTATION_DISABLED); + SDL_SetRenderScale(g_renderer, size.scale, size.scale); + } #ifdef AURORA_ENABLE_GX webgpu::resize_swapchain(size.fb_width, size.fb_height, size.native_fb_width, size.native_fb_height); #endif @@ -124,7 +111,6 @@ const AuroraEvent* poll_events() { #ifdef AURORA_ENABLE_GX imgui::process_event(event); #endif - #ifdef AURORA_ENABLE_RMLUI rmlui::handle_event(event); #endif @@ -271,10 +257,6 @@ bool create_window(AuroraBackend backend) { default: break; } -#ifdef __SWITCH__ - Sint32 width = 1280; - Sint32 height = 720; -#else auto width = static_cast(g_config.windowWidth); auto height = static_cast(g_config.windowHeight); if (width == 0 || height == 0) { @@ -295,7 +277,6 @@ bool create_window(AuroraBackend backend) { posY = SDL_WINDOWPOS_UNDEFINED; } -#endif const auto props = SDL_CreateProperties(); TRY(SDL_SetStringProperty(props, SDL_PROP_WINDOW_CREATE_TITLE_STRING, g_config.appName), "Failed to set {}: {}", SDL_PROP_WINDOW_CREATE_TITLE_STRING, SDL_GetError());