From bda441e9d725a9c31a77bc56f30f7ffab86a71b7 Mon Sep 17 00:00:00 2001 From: PJB3005 Date: Fri, 10 Apr 2026 19:19:12 +0200 Subject: [PATCH 1/7] Change star rendering to be more optimal on modern GPUs. Use vertex colors and a single large draw. --- include/global.h | 11 ++++++++ src/d/d_kankyo_rain.cpp | 56 ++++++++++++++++++++++++++++++++++++++--- 2 files changed, 63 insertions(+), 4 deletions(-) diff --git a/include/global.h b/include/global.h index ff2d18427d..d634332797 100644 --- a/include/global.h +++ b/include/global.h @@ -217,4 +217,15 @@ using std::isnan; #define CRASH(msg, ...) OSPanic(__FILE__, __LINE__, "%s", msg, ##__VA_ARGS__) +// Some basic macros that are more convenient than putting down #if blocks for one-line changes. +#if TARGET_PC +#define IF_DUSK(statement) statement +#define IF_NOT_DUSK(statement) +#define DUSK_IF_ELSE(dusk, orig) dusk +#else +#define IF_DUSK(statement) +#define IF_NOT_DUSK(statement) statement +#define DUSK_IF_ELSE(dusk, orig) orig +#endif + #endif diff --git a/src/d/d_kankyo_rain.cpp b/src/d/d_kankyo_rain.cpp index d91e0c03ba..4814576c31 100644 --- a/src/d/d_kankyo_rain.cpp +++ b/src/d/d_kankyo_rain.cpp @@ -4086,6 +4086,8 @@ void dKyr_drawStar(Mtx drawMtx, u8** tex) { #endif if (star_packet->mEffectNum != 0) { + IF_DUSK(GXPushDebugGroup("dKyr_drawStar")); + if (strcmp(dComIfGp_getStartStageName(), "F_SP200") == 0 && dComIfG_play_c::getLayerNo(0) == 0) { gwolf_howl_stage = true; } else if (strcmp(dComIfGp_getStartStageName(), "F_SP127") == 0 || @@ -4128,23 +4130,27 @@ void dKyr_drawStar(Mtx drawMtx, u8** tex) { mDoLib_project(&moon_pos, &moon_proj); #endif + // Dusk optimization: we use vertex color rather than GX_TEVREG0 to set star color. + // This allows us to merge all the stars into a single draw. GXSetNumChans(1); - GXSetChanCtrl(GX_COLOR0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_CLAMP, GX_AF_NONE); + GXSetChanCtrl(GX_COLOR0, GX_DISABLE, GX_SRC_REG, DUSK_IF_ELSE(GX_SRC_VTX, GX_SRC_REG), GX_LIGHT_NULL, GX_DF_CLAMP, GX_AF_NONE); GXSetNumTexGens(0); GXSetNumTevStages(1); GXSetTevColor(GX_TEVREG0, color_reg0); GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0); - GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, GX_CC_C0); + GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_ZERO, GX_CC_ZERO, DUSK_IF_ELSE(GX_CC_RASC, GX_CC_C0)); GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); - GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, GX_CA_A0); + GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_ZERO, GX_CA_ZERO, DUSK_IF_ELSE(GX_CA_RASA, GX_CA_A0)); GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, GX_TRUE, GX_TEVPREV); GXSetZMode(GX_ENABLE, GX_LEQUAL, GX_DISABLE); GXSetBlendMode(GX_BM_BLEND, GX_BL_SRCALPHA, GX_BL_INVSRCALPHA, GX_LO_CLEAR); GXSetAlphaCompare(GX_GREATER, 0, GX_AOP_OR, GX_GREATER, 0); GXSetNumIndStages(0); GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGBA, GX_F32, 0); + IF_DUSK(GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0)); GXClearVtxDesc(); GXSetVtxDesc(GX_VA_POS, GX_DIRECT); + IF_DUSK(GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT)); Mtx rotMtx; MTXRotRad(rotMtx, 'Z', DEG_TO_RAD(rot)); @@ -4204,6 +4210,15 @@ void dKyr_drawStar(Mtx drawMtx, u8** tex) { int sp44 = 0; f32 var_f28 = 0.0f; +#if TARGET_PC + // Dusk optimization: we submit a single large draw call, rather than a thousand. + u32 vertCount = 3 * star_packet->mEffectNum; + if (draw_mirrored) { + vertCount *= 2; + } + GXBegin(GX_TRIANGLES, GX_VTXFMT0, vertCount); +#endif + for (int i = 0; i < star_packet->mEffectNum; i++) { f32 var_f31; cXyz star_pos; @@ -4254,7 +4269,7 @@ void dKyr_drawStar(Mtx drawMtx, u8** tex) { color_reg0.a = 70.0f + ((i & 63) * 2); } - GXSetTevColor(GX_TEVREG0, color_reg0); + IF_NOT_DUSK(GXSetTevColor(GX_TEVREG0, color_reg0)); cXyz sp68; cXyz sp5C; @@ -4295,6 +4310,33 @@ void dKyr_drawStar(Mtx drawMtx, u8** tex) { } // if a star is too close to the moon then avoid drawing +#if TARGET_PC + // Dusk optimization change: since we submit one large draw, we don't know the count of moon-hidden stars in advance. + // So, just set those to have zero alpha. + if (moon_dist_to_star <= moon_threshold) { + color_reg0.a = 0; + } + + GXPosition3f32(sp68.x + (var_f31 * (pos[0].x - spBC.x)), sp68.y + (var_f31 * (pos[0].y - spBC.y)), sp68.z + (var_f31 * (pos[0].z - spBC.z))); + GXColor4u8(color_reg0.r, color_reg0.g, color_reg0.b, color_reg0.a); + GXPosition3f32(sp68.x + (var_f31 * (pos[1].x - spBC.x)), sp68.y + (var_f31 * (pos[1].y - spBC.y)), sp68.z + (var_f31 * (pos[1].z - spBC.z))); + GXColor4u8(color_reg0.r, color_reg0.g, color_reg0.b, color_reg0.a); + GXPosition3f32(sp68.x + (var_f31 * (pos[2].x - spBC.x)), sp68.y + (var_f31 * (pos[2].y - spBC.y)), sp68.z + (var_f31 * (pos[2].z - spBC.z))); + GXColor4u8(color_reg0.r, color_reg0.g, color_reg0.b, color_reg0.a); + + if (draw_mirrored) { + sp5C.x = spBC.x + star_pos.x; + sp5C.y = spBC.y - star_pos.y; + sp5C.z = spBC.z + star_pos.z; + + GXPosition3f32(sp5C.x + (var_f31 * (pos[0].x - spBC.x)), sp5C.y + (var_f31 * (pos[0].y - spBC.y)), sp5C.z + (var_f31 * (pos[0].z - spBC.z))); + GXColor4u8(color_reg0.r, color_reg0.g, color_reg0.b, color_reg0.a); + GXPosition3f32(sp5C.x + (var_f31 * (pos[1].x - spBC.x)), sp5C.y + (var_f31 * (pos[1].y - spBC.y)), sp5C.z + (var_f31 * (pos[1].z - spBC.z))); + GXColor4u8(color_reg0.r, color_reg0.g, color_reg0.b, color_reg0.a); + GXPosition3f32(sp5C.x + (var_f31 * (pos[2].x - spBC.x)), sp5C.y + (var_f31 * (pos[2].y - spBC.y)), sp5C.z + (var_f31 * (pos[2].z - spBC.z))); + GXColor4u8(color_reg0.r, color_reg0.g, color_reg0.b, color_reg0.a); + } +#else if (moon_dist_to_star > moon_threshold) { GXBegin(GX_TRIANGLES, GX_VTXFMT0, 3); GXPosition3f32(sp68.x + (var_f31 * (pos[0].x - spBC.x)), sp68.y + (var_f31 * (pos[0].y - spBC.y)), sp68.z + (var_f31 * (pos[0].z - spBC.z))); @@ -4314,8 +4356,14 @@ void dKyr_drawStar(Mtx drawMtx, u8** tex) { GXEnd(); } } +#endif } +#if TARGET_PC + GXEnd(); + GXPopDebugGroup(); +#endif + J3DShape::resetVcdVatCache(); } } From b255be9b2a49b342093f0f9e3c70ab19f10e8a58 Mon Sep 17 00:00:00 2001 From: MelonSpeedruns Date: Fri, 10 Apr 2026 17:53:28 -0400 Subject: [PATCH 2/7] Show Pipeline Compilation option (#312) * Show Compiling Shaders option. Off by default. * Addressed encounter comments --------- Co-authored-by: MelonSpeedruns --- include/dusk/settings.h | 1 + src/dusk/imgui/ImGuiConsole.cpp | 2 +- src/dusk/imgui/ImGuiMenuGame.cpp | 3 ++- src/dusk/settings.cpp | 4 +++- 4 files changed, 7 insertions(+), 3 deletions(-) diff --git a/include/dusk/settings.h b/include/dusk/settings.h index 5345f4ddde..7724948fd5 100644 --- a/include/dusk/settings.h +++ b/include/dusk/settings.h @@ -75,6 +75,7 @@ struct UserSettings { ConfigVar isoPath; ConfigVar graphicsBackend; ConfigVar skipPreLaunchUI; + ConfigVar showPipelineCompilation; } backend; }; diff --git a/src/dusk/imgui/ImGuiConsole.cpp b/src/dusk/imgui/ImGuiConsole.cpp index 83ce09f35b..51d5db9c60 100644 --- a/src/dusk/imgui/ImGuiConsole.cpp +++ b/src/dusk/imgui/ImGuiConsole.cpp @@ -411,7 +411,7 @@ namespace dusk { void ImGuiConsole::ShowPipelineProgress() { const auto* stats = aurora_get_stats(); const u32 queuedPipelines = stats->queuedPipelines; - if (queuedPipelines == 0) { + if (queuedPipelines == 0 || !getSettings().backend.showPipelineCompilation) { return; } const u32 createdPipelines = stats->createdPipelines; diff --git a/src/dusk/imgui/ImGuiMenuGame.cpp b/src/dusk/imgui/ImGuiMenuGame.cpp index ff51cf5925..494dbe1c22 100644 --- a/src/dusk/imgui/ImGuiMenuGame.cpp +++ b/src/dusk/imgui/ImGuiMenuGame.cpp @@ -103,8 +103,9 @@ namespace dusk { ImGui::EndMenu(); } - if (ImGui::BeginMenu("Misc")) { + if (ImGui::BeginMenu("Interface")) { config::ImGuiCheckbox("Skip Pre-Launch UI", getSettings().backend.skipPreLaunchUI); + config::ImGuiCheckbox("Show Pipeline Compilation", getSettings().backend.showPipelineCompilation); ImGui::EndMenu(); } diff --git a/src/dusk/settings.cpp b/src/dusk/settings.cpp index cde814a867..a8a6c26522 100644 --- a/src/dusk/settings.cpp +++ b/src/dusk/settings.cpp @@ -62,7 +62,8 @@ UserSettings g_userSettings = { .backend = { .isoPath {"backend.isoPath", ""}, .graphicsBackend {"backend.graphicsBackend", "auto"}, - .skipPreLaunchUI {"backend.skipPreLaunchUI", false} + .skipPreLaunchUI {"backend.skipPreLaunchUI", false}, + .showPipelineCompilation{"backend.showPipelineCompilation", false} } }; @@ -113,6 +114,7 @@ void registerSettings() { Register(g_userSettings.backend.isoPath); Register(g_userSettings.backend.graphicsBackend); Register(g_userSettings.backend.skipPreLaunchUI); + Register(g_userSettings.backend.showPipelineCompilation); } // Transient settings From d8a38a03dabd6f29f1ce3e53489fcb157bb8c9fb Mon Sep 17 00:00:00 2001 From: Luke Street Date: Fri, 10 Apr 2026 16:43:56 -0600 Subject: [PATCH 3/7] Enable 120fps and mouse on iOS --- platforms/ios/Info.plist.in | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/platforms/ios/Info.plist.in b/platforms/ios/Info.plist.in index 54dfc5179a..881d5aff35 100644 --- a/platforms/ios/Info.plist.in +++ b/platforms/ios/Info.plist.in @@ -75,5 +75,9 @@ 1 2 + UIApplicationSupportsIndirectInputEvents + + CADisableMinimumFrameDurationOnPhone + From 6deee934b50634cc4939920859c69789f62a3d10 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Fri, 10 Apr 2026 16:45:41 -0600 Subject: [PATCH 4/7] --dvd param skips prelaunch --- src/m_Do/m_Do_main.cpp | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/src/m_Do/m_Do_main.cpp b/src/m_Do/m_Do_main.cpp index 41307b6fd3..e82f6cd8ba 100644 --- a/src/m_Do/m_Do_main.cpp +++ b/src/m_Do/m_Do_main.cpp @@ -381,7 +381,7 @@ int game_main(int argc, char* argv[]) { arg_options.add_options() ("l,log-level", "Log level from " + std::to_string(AuroraLogLevel::LOG_DEBUG) + " to " + std::to_string(AuroraLogLevel::LOG_FATAL), cxxopts::value()->default_value("0")) ("h,help", "Print usage") - ("dvd", "Path to DVD image file", cxxopts::value()->default_value("game.iso")) + ("dvd", "Path to DVD image file", cxxopts::value()) ("backend", "Graphics API backend to use (auto, d3d12, metal, vulkan, null)", cxxopts::value()) ("cvar", "Override configuration variables without modifying config", cxxopts::value>()); @@ -441,25 +441,37 @@ int game_main(int argc, char* argv[]) { dusk::audio::SetMasterVolume(dusk::getSettings().audio.masterVolume / 100.0f); dusk::audio::SetEnableReverb(dusk::getSettings().audio.enableReverb); - // pre game launch ui main loop - if (!launchUILoop()) { - aurora_shutdown(); - return 0; - } - std::string dvd_path; + bool dvd_opened = false; if (parsed_arg_options.count("dvd")) { dvd_path = parsed_arg_options["dvd"].as(); - } else { + DuskLog.info("Loading DVD image from command line: {}", dvd_path); + dvd_opened = aurora_dvd_open(dvd_path.c_str()); + if (!dvd_opened) { + DuskLog.warn("Failed to open DVD image from command line: {}, opening prelaunch UI", dvd_path); + } else { + dusk::getSettings().backend.isoPath.setValue(dvd_path); + dusk::config::Save(); + dusk::IsGameLaunched = true; + } + } + + if (!dvd_opened) { + // pre game launch ui main loop + if (!launchUILoop()) { + aurora_shutdown(); + return 0; + } + dvd_path = dusk::getSettings().backend.isoPath; if (dvd_path.empty()) { DuskLog.fatal("No DVD image specified, unable to boot!"); } - } - DuskLog.info("Loading DVD image: {}", dvd_path); - if (!aurora_dvd_open(dvd_path.c_str())) { - DuskLog.fatal("Failed to open DVD image: {}", dvd_path); + DuskLog.info("Loading DVD image: {}", dvd_path); + if (!aurora_dvd_open(dvd_path.c_str())) { + DuskLog.fatal("Failed to open DVD image: {}", dvd_path); + } } OSInit(); From ce727b71fb326947e1079ca8540e734712693ba1 Mon Sep 17 00:00:00 2001 From: Luke Street Date: Fri, 10 Apr 2026 16:45:51 -0600 Subject: [PATCH 5/7] Avoid re-initializing game_main --- src/dusk/config.cpp | 4 ++-- src/m_Do/m_Do_main.cpp | 9 +++++++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/dusk/config.cpp b/src/dusk/config.cpp index 159706fac8..98f32cf8cd 100644 --- a/src/dusk/config.cpp +++ b/src/dusk/config.cpp @@ -20,7 +20,7 @@ using json = nlohmann::json; aurora::Module DuskConfigLog("dusk::config"); static absl::flat_hash_map RegisteredConfigVars; -static bool RegistrationDone; +static bool RegistrationDone = false; static std::string GetConfigJsonPath() { return fmt::format("{}{}", configPath, ConfigFileName); @@ -219,4 +219,4 @@ ConfigVarBase* dusk::config::GetConfigVar(std::string_view name) { } return nullptr; -} \ No newline at end of file +} diff --git a/src/m_Do/m_Do_main.cpp b/src/m_Do/m_Do_main.cpp index e82f6cd8ba..b5f5e36669 100644 --- a/src/m_Do/m_Do_main.cpp +++ b/src/m_Do/m_Do_main.cpp @@ -366,10 +366,19 @@ static constexpr PADDefaultMapping defaultPadMapping = { }, }; +static bool mainCalled = false; + // ========================================================================= // PC ENTRY POINT // ========================================================================= int game_main(int argc, char* argv[]) { + // On iOS, when connected to an external monitor, SDLUIKitSceneDelegate scene:willConnectToSession: + // can call our main function again. Explicitly guard against this reinitialization. + if (mainCalled) { + return 0; + } + mainCalled = true; + dusk::registerSettings(); dusk::config::FinishRegistration(); From 8487a4151d1f60ab92fa732af2a4cda45e02624e Mon Sep 17 00:00:00 2001 From: Irastris Date: Fri, 10 Apr 2026 21:14:15 -0400 Subject: [PATCH 6/7] Add Aurora config options for enabling texture replacement and dumping (#222) --- src/m_Do/m_Do_main.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/m_Do/m_Do_main.cpp b/src/m_Do/m_Do_main.cpp index b5f5e36669..1fc8cc2128 100644 --- a/src/m_Do/m_Do_main.cpp +++ b/src/m_Do/m_Do_main.cpp @@ -432,6 +432,8 @@ int game_main(int argc, char* argv[]) { config.mem2Size = 24 * 1024 * 1024; config.allowJoystickBackgroundEvents = true; config.imGuiInitCallback = &aurora_imgui_init_callback; + config.allowTextureReplacements = true; + config.allowTextureDumps = false; PADSetDefaultMapping(&defaultPadMapping); From d2400d661f4ee436071fee3db6cc4a6274a91d0d Mon Sep 17 00:00:00 2001 From: Irastris Date: Fri, 10 Apr 2026 21:14:17 -0400 Subject: [PATCH 7/7] Update Aurora --- extern/aurora | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/aurora b/extern/aurora index 2a9a7943f1..aae772abfe 160000 --- a/extern/aurora +++ b/extern/aurora @@ -1 +1 @@ -Subproject commit 2a9a7943f1ddc8cb275d31c99387aa62a338387d +Subproject commit aae772abfe667e24ebe8107073dadd457fe8d70f