diff --git a/Source/Core/Core/CoreTiming.cpp b/Source/Core/Core/CoreTiming.cpp index 4d28e65f32..4bdd53df31 100644 --- a/Source/Core/Core/CoreTiming.cpp +++ b/Source/Core/Core/CoreTiming.cpp @@ -49,9 +49,9 @@ static void EmptyTimedCallback(Core::System& system, u64 userdata, s64 cyclesLat // // Technically it might be more accurate to call this changing the IPC instead of the CPU speed, // but the effect is largely the same. -static int DowncountToCycles(CoreTiming::Globals& g, int downcount) +int CoreTimingManager::DowncountToCycles(int downcount) const { - return static_cast(downcount * g.last_OC_factor_inverted); + return static_cast(downcount * m_globals.last_OC_factor_inverted); } int CoreTimingManager::CyclesToDowncount(int cycles) const @@ -82,18 +82,15 @@ void CoreTimingManager::UnregisterAllEvents() void CoreTimingManager::Init() { - auto& system = Core::System::GetInstance(); - auto& g = system.GetCoreTimingGlobals(); - m_registered_config_callback_id = Config::AddConfigChangedCallback( [this]() { Core::RunAsCPUThread([this]() { RefreshConfig(); }); }); RefreshConfig(); m_last_oc_factor = m_config_oc_factor; - g.last_OC_factor_inverted = m_config_oc_inv_factor; + m_globals.last_OC_factor_inverted = m_config_oc_inv_factor; PowerPC::ppcState.downcount = CyclesToDowncount(MAX_SLICE_LENGTH); - g.slice_length = MAX_SLICE_LENGTH; - g.global_timer = 0; + m_globals.slice_length = MAX_SLICE_LENGTH; + m_globals.global_timer = 0; m_idled_cycles = 0; // The time between CoreTiming being intialized and the first call to Advance() is considered @@ -125,19 +122,16 @@ void CoreTimingManager::RefreshConfig() void CoreTimingManager::DoState(PointerWrap& p) { - auto& system = Core::System::GetInstance(); - auto& g = system.GetCoreTimingGlobals(); - std::lock_guard lk(m_ts_write_lock); - p.Do(g.slice_length); - p.Do(g.global_timer); + p.Do(m_globals.slice_length); + p.Do(m_globals.global_timer); p.Do(m_idled_cycles); p.Do(m_fake_dec_start_value); p.Do(m_fake_dec_start_ticks); - p.Do(g.fake_TB_start_value); - p.Do(g.fake_TB_start_ticks); + p.Do(m_globals.fake_TB_start_value); + p.Do(m_globals.fake_TB_start_ticks); p.Do(m_last_oc_factor); - g.last_OC_factor_inverted = 1.0f / m_last_oc_factor; + m_globals.last_OC_factor_inverted = 1.0f / m_last_oc_factor; p.Do(m_event_fifo_id); p.DoMarker("CoreTimingData"); @@ -187,14 +181,11 @@ void CoreTimingManager::DoState(PointerWrap& p) // it from any other thread, you are doing something evil u64 CoreTimingManager::GetTicks() const { - auto& system = Core::System::GetInstance(); - auto& g = system.GetCoreTimingGlobals(); - - u64 ticks = static_cast(g.global_timer); + u64 ticks = static_cast(m_globals.global_timer); if (!m_is_global_timer_sane) { - int downcount = DowncountToCycles(g, PowerPC::ppcState.downcount); - ticks += g.slice_length - downcount; + int downcount = DowncountToCycles(PowerPC::ppcState.downcount); + ticks += m_globals.slice_length - downcount; } return ticks; } @@ -214,9 +205,6 @@ void CoreTimingManager::ScheduleEvent(s64 cycles_into_future, EventType* event_t { ASSERT_MSG(POWERPC, event_type, "Event type is nullptr, will crash now."); - auto& system = Core::System::GetInstance(); - auto& g = system.GetCoreTimingGlobals(); - bool from_cpu_thread; if (from == FromThread::ANY) { @@ -252,7 +240,7 @@ void CoreTimingManager::ScheduleEvent(s64 cycles_into_future, EventType* event_t } std::lock_guard lk(m_ts_write_lock); - m_ts_queue.Push(Event{g.global_timer + cycles_into_future, 0, userdata, event_type}); + m_ts_queue.Push(Event{m_globals.global_timer + cycles_into_future, 0, userdata, event_type}); } } @@ -277,15 +265,13 @@ void CoreTimingManager::RemoveAllEvents(EventType* event_type) void CoreTimingManager::ForceExceptionCheck(s64 cycles) { - auto& system = Core::System::GetInstance(); - auto& g = system.GetCoreTimingGlobals(); - cycles = std::max(0, cycles); - if (DowncountToCycles(g, PowerPC::ppcState.downcount) > cycles) + if (DowncountToCycles(PowerPC::ppcState.downcount) > cycles) { // downcount is always (much) smaller than MAX_INT so we can safely cast cycles to an int here. - // Account for cycles already executed by adjusting the g.slice_length - g.slice_length -= DowncountToCycles(g, PowerPC::ppcState.downcount) - static_cast(cycles); + // Account for cycles already executed by adjusting the m_globals.slice_length + m_globals.slice_length -= + DowncountToCycles(PowerPC::ppcState.downcount) - static_cast(cycles); PowerPC::ppcState.downcount = CyclesToDowncount(static_cast(cycles)); } } @@ -303,24 +289,23 @@ void CoreTimingManager::MoveEvents() void CoreTimingManager::Advance() { auto& system = Core::System::GetInstance(); - auto& g = system.GetCoreTimingGlobals(); MoveEvents(); - int cyclesExecuted = g.slice_length - DowncountToCycles(g, PowerPC::ppcState.downcount); - g.global_timer += cyclesExecuted; + int cyclesExecuted = m_globals.slice_length - DowncountToCycles(PowerPC::ppcState.downcount); + m_globals.global_timer += cyclesExecuted; m_last_oc_factor = m_config_oc_factor; - g.last_OC_factor_inverted = m_config_oc_inv_factor; - g.slice_length = MAX_SLICE_LENGTH; + m_globals.last_OC_factor_inverted = m_config_oc_inv_factor; + m_globals.slice_length = MAX_SLICE_LENGTH; m_is_global_timer_sane = true; - while (!m_event_queue.empty() && m_event_queue.front().time <= g.global_timer) + while (!m_event_queue.empty() && m_event_queue.front().time <= m_globals.global_timer) { Event evt = std::move(m_event_queue.front()); std::pop_heap(m_event_queue.begin(), m_event_queue.end(), std::greater()); m_event_queue.pop_back(); - evt.type->callback(system, evt.userdata, g.global_timer - evt.time); + evt.type->callback(system, evt.userdata, m_globals.global_timer - evt.time); } m_is_global_timer_sane = false; @@ -328,11 +313,11 @@ void CoreTimingManager::Advance() // Still events left (scheduled in the future) if (!m_event_queue.empty()) { - g.slice_length = static_cast( - std::min(m_event_queue.front().time - g.global_timer, MAX_SLICE_LENGTH)); + m_globals.slice_length = static_cast( + std::min(m_event_queue.front().time - m_globals.global_timer, MAX_SLICE_LENGTH)); } - PowerPC::ppcState.downcount = CyclesToDowncount(g.slice_length); + PowerPC::ppcState.downcount = CyclesToDowncount(m_globals.slice_length); // Check for any external exceptions. // It's important to do this after processing events otherwise any exceptions will be delayed @@ -343,14 +328,11 @@ void CoreTimingManager::Advance() void CoreTimingManager::LogPendingEvents() const { - auto& system = Core::System::GetInstance(); - auto& g = system.GetCoreTimingGlobals(); - auto clone = m_event_queue; std::sort(clone.begin(), clone.end()); for (const Event& ev : clone) { - INFO_LOG_FMT(POWERPC, "PENDING: Now: {} Pending: {} Type: {}", g.global_timer, ev.time, + INFO_LOG_FMT(POWERPC, "PENDING: Now: {} Pending: {} Type: {}", m_globals.global_timer, ev.time, *ev.type->name); } } @@ -358,21 +340,15 @@ void CoreTimingManager::LogPendingEvents() const // Should only be called from the CPU thread after the PPC clock has changed void CoreTimingManager::AdjustEventQueueTimes(u32 new_ppc_clock, u32 old_ppc_clock) { - auto& system = Core::System::GetInstance(); - auto& g = system.GetCoreTimingGlobals(); - for (Event& ev : m_event_queue) { - const s64 ticks = (ev.time - g.global_timer) * new_ppc_clock / old_ppc_clock; - ev.time = g.global_timer + ticks; + const s64 ticks = (ev.time - m_globals.global_timer) * new_ppc_clock / old_ppc_clock; + ev.time = m_globals.global_timer + ticks; } } void CoreTimingManager::Idle() { - auto& system = Core::System::GetInstance(); - auto& g = system.GetCoreTimingGlobals(); - if (m_config_sync_on_skip_idle) { // When the FIFO is processing data we must not advance because in this way @@ -382,7 +358,7 @@ void CoreTimingManager::Idle() } PowerPC::UpdatePerformanceMonitor(PowerPC::ppcState.downcount, 0, 0); - m_idled_cycles += DowncountToCycles(g, PowerPC::ppcState.downcount); + m_idled_cycles += DowncountToCycles(PowerPC::ppcState.downcount); PowerPC::ppcState.downcount = 0; } @@ -422,26 +398,22 @@ void CoreTimingManager::SetFakeDecStartTicks(u64 val) u64 CoreTimingManager::GetFakeTBStartValue() const { - auto& g = Core::System::GetInstance().GetCoreTimingGlobals(); - return g.fake_TB_start_value; + return m_globals.fake_TB_start_value; } void CoreTimingManager::SetFakeTBStartValue(u64 val) { - auto& g = Core::System::GetInstance().GetCoreTimingGlobals(); - g.fake_TB_start_value = val; + m_globals.fake_TB_start_value = val; } u64 CoreTimingManager::GetFakeTBStartTicks() const { - auto& g = Core::System::GetInstance().GetCoreTimingGlobals(); - return g.fake_TB_start_ticks; + return m_globals.fake_TB_start_ticks; } void CoreTimingManager::SetFakeTBStartTicks(u64 val) { - auto& g = Core::System::GetInstance().GetCoreTimingGlobals(); - g.fake_TB_start_ticks = val; + m_globals.fake_TB_start_ticks = val; } void GlobalAdvance() diff --git a/Source/Core/Core/CoreTiming.h b/Source/Core/Core/CoreTiming.h index c0a4d53056..737f3889b9 100644 --- a/Source/Core/Core/CoreTiming.h +++ b/Source/Core/Core/CoreTiming.h @@ -137,7 +137,12 @@ public: void ForceExceptionCheck(s64 cycles); + // Directly accessed by the JIT. + Globals& GetGlobals() { return m_globals; } + private: + Globals m_globals; + // unordered_map stores each element separately as a linked list node so pointers to elements // remain stable regardless of rehashes/resizing. std::unordered_map m_event_types; @@ -168,6 +173,7 @@ private: float m_config_oc_inv_factor = 0.0f; bool m_config_sync_on_skip_idle = false; + int DowncountToCycles(int downcount) const; int CyclesToDowncount(int cycles) const; }; diff --git a/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp b/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp index 2dade57576..f2d7ceef9c 100644 --- a/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp +++ b/Source/Core/Core/PowerPC/Interpreter/Interpreter.cpp @@ -212,10 +212,11 @@ int Interpreter::SingleStepInner() void Interpreter::SingleStep() { - auto& core_timing_globals = Core::System::GetInstance().GetCoreTimingGlobals(); + auto& core_timing = Core::System::GetInstance().GetCoreTiming(); + auto& core_timing_globals = core_timing.GetGlobals(); // Declare start of new slice - Core::System::GetInstance().GetCoreTiming().Advance(); + core_timing.Advance(); SingleStepInner(); diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp index eb2e938648..3629e2deec 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp @@ -323,7 +323,7 @@ void Jit64::mfspr(UGeckoInstruction inst) RCX64Reg rax = gpr.Scratch(RAX); RCX64Reg rcx = gpr.Scratch(RCX); - auto& core_timing_globals = Core::System::GetInstance().GetCoreTimingGlobals(); + auto& core_timing_globals = Core::System::GetInstance().GetCoreTiming().GetGlobals(); MOV(64, rcx, ImmPtr(&core_timing_globals)); // An inline implementation of CoreTiming::GetFakeTimeBase, since in timer-heavy games the diff --git a/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp b/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp index d93700e742..cc95654b76 100644 --- a/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp +++ b/Source/Core/Core/PowerPC/JitArm64/JitArm64_SystemRegisters.cpp @@ -307,7 +307,7 @@ void JitArm64::mfspr(UGeckoInstruction inst) // An inline implementation of CoreTiming::GetFakeTimeBase, since in timer-heavy games the // cost of calling out to C for this is actually significant. - auto& core_timing_globals = Core::System::GetInstance().GetCoreTimingGlobals(); + auto& core_timing_globals = Core::System::GetInstance().GetCoreTiming().GetGlobals(); MOVP2R(Xg, &core_timing_globals); LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(downcount)); diff --git a/Source/Core/Core/System.cpp b/Source/Core/Core/System.cpp index 16d5086e9f..2b69756d08 100644 --- a/Source/Core/Core/System.cpp +++ b/Source/Core/Core/System.cpp @@ -28,7 +28,6 @@ struct System::Impl AudioInterface::AudioInterfaceState m_audio_interface_state; CoreTiming::CoreTimingManager m_core_timing; - CoreTiming::Globals m_core_timing_globals; DSP::DSPState m_dsp_state; DVDInterface::DVDInterfaceState m_dvd_interface_state; DVDThread::DVDThreadState m_dvd_thread_state; @@ -92,11 +91,6 @@ CoreTiming::CoreTimingManager& System::GetCoreTiming() const return m_impl->m_core_timing; } -CoreTiming::Globals& System::GetCoreTimingGlobals() const -{ - return m_impl->m_core_timing_globals; -} - DSP::DSPState& System::GetDSPState() const { return m_impl->m_dsp_state; diff --git a/Source/Core/Core/System.h b/Source/Core/Core/System.h index bdcd37f75d..1c4c984fed 100644 --- a/Source/Core/Core/System.h +++ b/Source/Core/Core/System.h @@ -15,8 +15,7 @@ class AudioInterfaceState; namespace CoreTiming { class CoreTimingManager; -struct Globals; -} // namespace CoreTiming +} namespace DSP { class DSPState; @@ -82,7 +81,6 @@ public: AudioInterface::AudioInterfaceState& GetAudioInterfaceState() const; CoreTiming::CoreTimingManager& GetCoreTiming() const; - CoreTiming::Globals& GetCoreTimingGlobals() const; DSP::DSPState& GetDSPState() const; DVDInterface::DVDInterfaceState& GetDVDInterfaceState() const; DVDThread::DVDThreadState& GetDVDThreadState() const; diff --git a/Source/UnitTests/Core/CoreTimingTest.cpp b/Source/UnitTests/Core/CoreTimingTest.cpp index 6054fb9381..14731a10e7 100644 --- a/Source/UnitTests/Core/CoreTimingTest.cpp +++ b/Source/UnitTests/Core/CoreTimingTest.cpp @@ -304,7 +304,7 @@ TEST(CoreTiming, ScheduleIntoPast) // the stale value, i.e. effectively half-way through the previous slice. // NOTE: We're only testing that the scheduler doesn't break, not whether this makes sense. Core::UndeclareAsCPUThread(); - auto& core_timing_globals = Core::System::GetInstance().GetCoreTimingGlobals(); + auto& core_timing_globals = core_timing.GetGlobals(); core_timing_globals.global_timer -= 1000; core_timing.ScheduleEvent(0, cb_b, CB_IDS[1], CoreTiming::FromThread::NON_CPU); core_timing_globals.global_timer += 1000;