diff --git a/ultramodern/events.cpp b/ultramodern/events.cpp index 1597f76..4f0c4a2 100644 --- a/ultramodern/events.cpp +++ b/ultramodern/events.cpp @@ -10,7 +10,7 @@ #include #include "blockingconcurrentqueue.h" - +#include "utils.hpp" #include "ultra64.h" #include "ultramodern.hpp" #include "config.hpp" @@ -328,41 +328,44 @@ void gfx_thread_func(uint8_t* rdram, moodycamel::LightweightSemaphore* thread_re // Try to pull an action from the queue Action action; if (events_context.action_queue.wait_dequeue_timed(action, 1ms)) { - // Determine the action type and act on it - if (const auto* task_action = std::get_if(&action)) { - // Turn on instant present if the game has been started and it hasn't been turned on yet. - if (ultramodern::is_game_started() && !enabled_instant_present) { - rt64.enable_instant_present(); - enabled_instant_present = true; - } - // Tell the game that the RSP completed instantly. This will allow it to queue other task types, but it won't - // start another graphics task until the RDP is also complete. Games usually preserve the RSP inputs until the RDP - // is finished as well, so sending this early shouldn't be an issue in most cases. - // If this causes issues then the logic can be replaced with responding to yield requests. - sp_complete(); - ultramodern::measure_input_latency(); + match(action, + [&](const SpTaskAction& action){ + // Turn on instant present if the game has been started and it hasn't been turned on yet. + if (ultramodern::is_game_started() && !enabled_instant_present) { + rt64.enable_instant_present(); + enabled_instant_present = true; + } + // Tell the game that the RSP completed instantly. This will allow it to queue other task types, but it won't + // start another graphics task until the RDP is also complete. Games usually preserve the RSP inputs until the RDP + // is finished as well, so sending this early shouldn't be an issue in most cases. + // If this causes issues then the logic can be replaced with responding to yield requests. + sp_complete(); + ultramodern::measure_input_latency(); + + auto rt64_start = std::chrono::high_resolution_clock::now(); + rt64.send_dl(&task_action->task); + auto rt64_end = std::chrono::high_resolution_clock::now(); + dp_complete(); + }, + [&](const SwapBuffersAction &action) + { + events_context.vi.current_buffer = events_context.vi.next_buffer; + rt64.update_screen(swap_action->origin); + display_refresh_rate = rt64.get_display_framerate(); + }, + [&](const UpdateConfigAction &action) + { + ultramodern::GraphicsConfig new_config = cur_config; + if (old_config == new_config) return; - auto rt64_start = std::chrono::high_resolution_clock::now(); - rt64.send_dl(&task_action->task); - auto rt64_end = std::chrono::high_resolution_clock::now(); - dp_complete(); - // printf("RT64 ProcessDList time: %d us\n", static_cast(std::chrono::duration_cast(rt64_end - rt64_start).count())); - } - else if (const auto* swap_action = std::get_if(&action)) { - events_context.vi.current_buffer = events_context.vi.next_buffer; - rt64.update_screen(swap_action->origin); - display_refresh_rate = rt64.get_display_framerate(); - } - else if (const auto* config_action = std::get_if(&action)) { - ultramodern::GraphicsConfig new_config = cur_config; - if (old_config != new_config) { rt64.update_config(old_config, new_config); old_config = new_config; + }, + [&](const LoadShaderCacheAction &action) + { + rt64.load_shader_cache(load_shader_cache_action->data); } - } - else if (const auto* load_shader_cache_action = std::get_if(&action)) { - rt64.load_shader_cache(load_shader_cache_action->data); - } + ); } } // TODO move recomp code out of ultramodern. diff --git a/ultramodern/timer.cpp b/ultramodern/timer.cpp index b278ff3..af87e47 100644 --- a/ultramodern/timer.cpp +++ b/ultramodern/timer.cpp @@ -3,6 +3,7 @@ #include #include "blockingconcurrentqueue.h" +#include "utils.hpp" #include "ultra64.h" #include "ultramodern.hpp" @@ -87,12 +88,16 @@ void timer_thread(RDRAM_ARG1) { // Lambda to process a timer action to handle adding and removing timers auto process_timer_action = [&](const Action& action) { - // Determine the action type and act on it - if (const auto* add_action = std::get_if(&action)) { - active_timers.insert(add_action->timer); - } else if (const auto* remove_action = std::get_if(&action)) { - active_timers.erase(remove_action->timer); - } + match(action, + [&active_timers](const AddTimerAction& action) + { + active_timers.insert(action->timer); + }, + [&active_timers](const RemoveTimerAction& action) + { + active_timers.erase(action->timer); + } + ); }; while (true) { diff --git a/ultramodern/utils.hpp b/ultramodern/utils.hpp new file mode 100644 index 0000000..d921b68 --- /dev/null +++ b/ultramodern/utils.hpp @@ -0,0 +1,12 @@ +#include + +template +struct overloaded : Ts... +{ + using Ts::operator()...; +}; + +template +auto match(const T& event, Ts&&... args){ + return std::visit(overloaded{std::forward(args)...}, event); +} \ No newline at end of file