From 5fee2ac628d342e86d14ae4e1c46b7fba0c1a897 Mon Sep 17 00:00:00 2001 From: qwertyquerty Date: Sun, 12 Apr 2026 18:40:21 -0700 Subject: [PATCH] better bp caching, xf cache, optimize fifo with realloc and remove double lookups (#110) * optimize fifo with realloc and remove double lookups * bp cache, xf cache, and last pipeline ref cache * remove double lookup from find/try_emplace * change name * Move xfRegCache * Update gx_test_stubs.cpp --------- Co-authored-by: Luke Street --- lib/gx/command_processor.cpp | 6 +++++- lib/gx/fifo.cpp | 19 ++++++------------- lib/gx/gx.hpp | 1 + lib/input.cpp | 32 +++++++++++++++----------------- tests/gx_test_stubs.cpp | 5 +---- 5 files changed, 28 insertions(+), 35 deletions(-) diff --git a/lib/gx/command_processor.cpp b/lib/gx/command_processor.cpp index 5ddcb46..1ad1b86 100644 --- a/lib/gx/command_processor.cpp +++ b/lib/gx/command_processor.cpp @@ -504,6 +504,7 @@ static void handle_bp(u32 value, bool bigEndian) { g_gxState.bpRegCache[0xFE] = 0x00FFFFFF; const u32 merged = (g_gxState.bpRegCache[regId] & ~ssMask) | (value & ssMask); value = (regId << 24) | (merged & 0x00FFFFFF); + if (g_gxState.bpRegCache[regId] == value) return; g_gxState.bpRegCache[regId] = value; } @@ -1275,7 +1276,10 @@ static void handle_xf(const u8* data, u32& pos, u32 size, bool bigEndian) { for (u32 i = 0; i < count; i++) { u32 reg = xfAddr + i; u32 val = read_u32(xfData + i * 4, bigEndian); - f32 fval = read_f32(xfData + i * 4, bigEndian); + + // Skip scalar register writes that haven't changed (viewport/projection handled below) + if (reg <= 0x19 && val == g_gxState.xfRegCache[reg]) continue; + if (reg <= 0x19) g_gxState.xfRegCache[reg] = val; switch (reg) { case 0x08: diff --git a/lib/gx/fifo.cpp b/lib/gx/fifo.cpp index bd7734b..23bd0a9 100644 --- a/lib/gx/fifo.cpp +++ b/lib/gx/fifo.cpp @@ -2,6 +2,7 @@ #include "command_processor.hpp" #include "../internal.hpp" +#include #include namespace aurora::gx::fifo { @@ -19,8 +20,8 @@ uint32_t sDlWritePos = 0; void init() { constexpr uint32_t initialCapacity = 64 * 1024; - delete[] detail::sBufferData; - detail::sBufferData = new uint8_t[initialCapacity]; + free(detail::sBufferData); + detail::sBufferData = static_cast(malloc(initialCapacity)); detail::sBufferSize = 0; detail::sBufferCapacity = initialCapacity; detail::sInDisplayList = false; @@ -31,17 +32,9 @@ void init() { void write_data_grow(const void* data, uint32_t length) { uint32_t needed = detail::sBufferSize + length; - uint32_t newCap = detail::sBufferCapacity * 2; - if (newCap < needed) { - newCap = needed; - } - auto* newBuf = new uint8_t[newCap]; - if (detail::sBufferSize > 0) { - std::memcpy(newBuf, detail::sBufferData, detail::sBufferSize); - } - std::memcpy(newBuf + detail::sBufferSize, data, length); - delete[] detail::sBufferData; - detail::sBufferData = newBuf; + uint32_t newCap = std::max(detail::sBufferCapacity * 2, needed); + detail::sBufferData = static_cast(realloc(detail::sBufferData, newCap)); + std::memcpy(detail::sBufferData + detail::sBufferSize, data, length); detail::sBufferSize = needed; detail::sBufferCapacity = newCap; } diff --git a/lib/gx/gx.hpp b/lib/gx/gx.hpp index 63ce74f..ded46a6 100644 --- a/lib/gx/gx.hpp +++ b/lib/gx/gx.hpp @@ -373,6 +373,7 @@ struct GXState { regs[0xFE] = 0x00FFFFFF; return regs; }(); + std::array xfRegCache; void clearVtxSizeCache() { lastVtxFmt = GX_MAX_VTXFMT; } }; diff --git a/lib/input.cpp b/lib/input.cpp index 2310151..ae57268 100644 --- a/lib/input.cpp +++ b/lib/input.cpp @@ -80,35 +80,35 @@ SDL_JoystickID add_controller(SDL_JoystickID which) noexcept { } void remove_controller(Uint32 instance) noexcept { - if (g_GameControllers.find(instance) != g_GameControllers.end()) { - SDL_CloseGamepad(g_GameControllers[instance].m_controller); - g_GameControllers.erase(instance); + if (auto it = g_GameControllers.find(instance); it != g_GameControllers.end()) { + SDL_CloseGamepad(it->second.m_controller); + g_GameControllers.erase(it); } } bool is_gamecube(Uint32 instance) noexcept { - if (g_GameControllers.find(instance) != g_GameControllers.end()) { - return g_GameControllers[instance].m_isGameCube; + if (auto it = g_GameControllers.find(instance); it != g_GameControllers.end()) { + return it->second.m_isGameCube; } return false; } int32_t player_index(Uint32 instance) noexcept { - if (g_GameControllers.find(instance) != g_GameControllers.end()) { - return SDL_GetGamepadPlayerIndex(g_GameControllers[instance].m_controller); + if (auto it = g_GameControllers.find(instance); it != g_GameControllers.end()) { + return SDL_GetGamepadPlayerIndex(it->second.m_controller); } return -1; } void set_player_index(Uint32 instance, Sint32 index) noexcept { - if (g_GameControllers.find(instance) != g_GameControllers.end()) { - SDL_SetGamepadPlayerIndex(g_GameControllers[instance].m_controller, index); + if (auto it = g_GameControllers.find(instance); it != g_GameControllers.end()) { + SDL_SetGamepadPlayerIndex(it->second.m_controller, index); } } std::string controller_name(Uint32 instance) noexcept { - if (g_GameControllers.find(instance) != g_GameControllers.end()) { - const auto* name = SDL_GetGamepadName(g_GameControllers[instance].m_controller); + if (auto it = g_GameControllers.find(instance); it != g_GameControllers.end()) { + const auto* name = SDL_GetGamepadName(it->second.m_controller); if (name != nullptr) { return {name}; } @@ -117,18 +117,16 @@ std::string controller_name(Uint32 instance) noexcept { } bool controller_has_rumble(Uint32 instance) noexcept { - if (g_GameControllers.find(instance) != g_GameControllers.end()) { - return g_GameControllers[instance].m_hasRumble; + if (auto it = g_GameControllers.find(instance); it != g_GameControllers.end()) { + return it->second.m_hasRumble; } - return false; } void controller_rumble(uint32_t instance, uint16_t low_freq_intensity, uint16_t high_freq_intensity, uint16_t duration_ms) noexcept { - - if (g_GameControllers.find(instance) != g_GameControllers.end()) { - SDL_RumbleGamepad(g_GameControllers[instance].m_controller, low_freq_intensity, high_freq_intensity, duration_ms); + if (auto it = g_GameControllers.find(instance); it != g_GameControllers.end()) { + SDL_RumbleGamepad(it->second.m_controller, low_freq_intensity, high_freq_intensity, duration_ms); } } diff --git a/tests/gx_test_stubs.cpp b/tests/gx_test_stubs.cpp index 0484b34..c13bdd7 100644 --- a/tests/gx_test_stubs.cpp +++ b/tests/gx_test_stubs.cpp @@ -70,10 +70,7 @@ namespace aurora::gx { void populate_pipeline_config(PipelineConfig& config, GXPrimitive primitive, GXVtxFmt fmt) noexcept { // No-op for tests } -GXBindGroups build_bind_groups(const ShaderInfo& info, const ShaderConfig& config, - const BindGroupRanges& ranges) noexcept { - return {}; -} +GXBindGroups build_bind_groups(const ShaderInfo& info) noexcept { return {}; } ShaderInfo build_shader_info(const ShaderConfig& config) noexcept { return {}; } gfx::Range build_uniform(const ShaderInfo& info, uint32_t vtxStart, const BindGroupRanges& ranges) noexcept { return {};