mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-27 00:05:34 +01:00
CoreTiming: Move the 'Globals' instance into Core::System.
This commit is contained in:
parent
70f353fb37
commit
86f17511fc
@ -74,8 +74,6 @@ static u64 s_fake_dec_start_ticks;
|
|||||||
// Are we in a function that has been called from Advance()
|
// Are we in a function that has been called from Advance()
|
||||||
static bool s_is_global_timer_sane;
|
static bool s_is_global_timer_sane;
|
||||||
|
|
||||||
Globals g;
|
|
||||||
|
|
||||||
static EventType* s_ev_lost = nullptr;
|
static EventType* s_ev_lost = nullptr;
|
||||||
|
|
||||||
static size_t s_registered_config_callback_id;
|
static size_t s_registered_config_callback_id;
|
||||||
@ -94,7 +92,7 @@ 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,
|
// Technically it might be more accurate to call this changing the IPC instead of the CPU speed,
|
||||||
// but the effect is largely the same.
|
// but the effect is largely the same.
|
||||||
static int DowncountToCycles(int downcount)
|
static int DowncountToCycles(CoreTiming::Globals& g, int downcount)
|
||||||
{
|
{
|
||||||
return static_cast<int>(downcount * g.last_OC_factor_inverted);
|
return static_cast<int>(downcount * g.last_OC_factor_inverted);
|
||||||
}
|
}
|
||||||
@ -127,6 +125,8 @@ void UnregisterAllEvents()
|
|||||||
|
|
||||||
void Init()
|
void Init()
|
||||||
{
|
{
|
||||||
|
auto& g = Core::System::GetInstance().GetCoreTimingGlobals();
|
||||||
|
|
||||||
s_registered_config_callback_id =
|
s_registered_config_callback_id =
|
||||||
Config::AddConfigChangedCallback([]() { Core::RunAsCPUThread([]() { RefreshConfig(); }); });
|
Config::AddConfigChangedCallback([]() { Core::RunAsCPUThread([]() { RefreshConfig(); }); });
|
||||||
RefreshConfig();
|
RefreshConfig();
|
||||||
@ -167,6 +167,8 @@ void RefreshConfig()
|
|||||||
|
|
||||||
void DoState(PointerWrap& p)
|
void DoState(PointerWrap& p)
|
||||||
{
|
{
|
||||||
|
auto& g = Core::System::GetInstance().GetCoreTimingGlobals();
|
||||||
|
|
||||||
std::lock_guard lk(s_ts_write_lock);
|
std::lock_guard lk(s_ts_write_lock);
|
||||||
p.Do(g.slice_length);
|
p.Do(g.slice_length);
|
||||||
p.Do(g.global_timer);
|
p.Do(g.global_timer);
|
||||||
@ -226,10 +228,12 @@ void DoState(PointerWrap& p)
|
|||||||
// it from any other thread, you are doing something evil
|
// it from any other thread, you are doing something evil
|
||||||
u64 GetTicks()
|
u64 GetTicks()
|
||||||
{
|
{
|
||||||
|
auto& g = Core::System::GetInstance().GetCoreTimingGlobals();
|
||||||
|
|
||||||
u64 ticks = static_cast<u64>(g.global_timer);
|
u64 ticks = static_cast<u64>(g.global_timer);
|
||||||
if (!s_is_global_timer_sane)
|
if (!s_is_global_timer_sane)
|
||||||
{
|
{
|
||||||
int downcount = DowncountToCycles(PowerPC::ppcState.downcount);
|
int downcount = DowncountToCycles(g, PowerPC::ppcState.downcount);
|
||||||
ticks += g.slice_length - downcount;
|
ticks += g.slice_length - downcount;
|
||||||
}
|
}
|
||||||
return ticks;
|
return ticks;
|
||||||
@ -249,6 +253,8 @@ void ScheduleEvent(s64 cycles_into_future, EventType* event_type, u64 userdata,
|
|||||||
{
|
{
|
||||||
ASSERT_MSG(POWERPC, event_type, "Event type is nullptr, will crash now.");
|
ASSERT_MSG(POWERPC, event_type, "Event type is nullptr, will crash now.");
|
||||||
|
|
||||||
|
auto& g = Core::System::GetInstance().GetCoreTimingGlobals();
|
||||||
|
|
||||||
bool from_cpu_thread;
|
bool from_cpu_thread;
|
||||||
if (from == FromThread::ANY)
|
if (from == FromThread::ANY)
|
||||||
{
|
{
|
||||||
@ -309,12 +315,14 @@ void RemoveAllEvents(EventType* event_type)
|
|||||||
|
|
||||||
void ForceExceptionCheck(s64 cycles)
|
void ForceExceptionCheck(s64 cycles)
|
||||||
{
|
{
|
||||||
|
auto& g = Core::System::GetInstance().GetCoreTimingGlobals();
|
||||||
|
|
||||||
cycles = std::max<s64>(0, cycles);
|
cycles = std::max<s64>(0, cycles);
|
||||||
if (DowncountToCycles(PowerPC::ppcState.downcount) > cycles)
|
if (DowncountToCycles(g, PowerPC::ppcState.downcount) > cycles)
|
||||||
{
|
{
|
||||||
// downcount is always (much) smaller than MAX_INT so we can safely cast cycles to an int here.
|
// 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
|
// Account for cycles already executed by adjusting the g.slice_length
|
||||||
g.slice_length -= DowncountToCycles(PowerPC::ppcState.downcount) - static_cast<int>(cycles);
|
g.slice_length -= DowncountToCycles(g, PowerPC::ppcState.downcount) - static_cast<int>(cycles);
|
||||||
PowerPC::ppcState.downcount = CyclesToDowncount(static_cast<int>(cycles));
|
PowerPC::ppcState.downcount = CyclesToDowncount(static_cast<int>(cycles));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -331,9 +339,11 @@ void MoveEvents()
|
|||||||
|
|
||||||
void Advance()
|
void Advance()
|
||||||
{
|
{
|
||||||
|
auto& g = Core::System::GetInstance().GetCoreTimingGlobals();
|
||||||
|
|
||||||
MoveEvents();
|
MoveEvents();
|
||||||
|
|
||||||
int cyclesExecuted = g.slice_length - DowncountToCycles(PowerPC::ppcState.downcount);
|
int cyclesExecuted = g.slice_length - DowncountToCycles(g, PowerPC::ppcState.downcount);
|
||||||
g.global_timer += cyclesExecuted;
|
g.global_timer += cyclesExecuted;
|
||||||
s_last_OC_factor = s_config_OC_factor;
|
s_last_OC_factor = s_config_OC_factor;
|
||||||
g.last_OC_factor_inverted = s_config_OC_inv_factor;
|
g.last_OC_factor_inverted = s_config_OC_inv_factor;
|
||||||
@ -369,6 +379,8 @@ void Advance()
|
|||||||
|
|
||||||
void LogPendingEvents()
|
void LogPendingEvents()
|
||||||
{
|
{
|
||||||
|
auto& g = Core::System::GetInstance().GetCoreTimingGlobals();
|
||||||
|
|
||||||
auto clone = s_event_queue;
|
auto clone = s_event_queue;
|
||||||
std::sort(clone.begin(), clone.end());
|
std::sort(clone.begin(), clone.end());
|
||||||
for (const Event& ev : clone)
|
for (const Event& ev : clone)
|
||||||
@ -381,6 +393,8 @@ void LogPendingEvents()
|
|||||||
// Should only be called from the CPU thread after the PPC clock has changed
|
// Should only be called from the CPU thread after the PPC clock has changed
|
||||||
void AdjustEventQueueTimes(u32 new_ppc_clock, u32 old_ppc_clock)
|
void AdjustEventQueueTimes(u32 new_ppc_clock, u32 old_ppc_clock)
|
||||||
{
|
{
|
||||||
|
auto& g = Core::System::GetInstance().GetCoreTimingGlobals();
|
||||||
|
|
||||||
for (Event& ev : s_event_queue)
|
for (Event& ev : s_event_queue)
|
||||||
{
|
{
|
||||||
const s64 ticks = (ev.time - g.global_timer) * new_ppc_clock / old_ppc_clock;
|
const s64 ticks = (ev.time - g.global_timer) * new_ppc_clock / old_ppc_clock;
|
||||||
@ -390,6 +404,8 @@ void AdjustEventQueueTimes(u32 new_ppc_clock, u32 old_ppc_clock)
|
|||||||
|
|
||||||
void Idle()
|
void Idle()
|
||||||
{
|
{
|
||||||
|
auto& g = Core::System::GetInstance().GetCoreTimingGlobals();
|
||||||
|
|
||||||
if (s_config_sync_on_skip_idle)
|
if (s_config_sync_on_skip_idle)
|
||||||
{
|
{
|
||||||
// When the FIFO is processing data we must not advance because in this way
|
// When the FIFO is processing data we must not advance because in this way
|
||||||
@ -399,7 +415,7 @@ void Idle()
|
|||||||
}
|
}
|
||||||
|
|
||||||
PowerPC::UpdatePerformanceMonitor(PowerPC::ppcState.downcount, 0, 0);
|
PowerPC::UpdatePerformanceMonitor(PowerPC::ppcState.downcount, 0, 0);
|
||||||
s_idled_cycles += DowncountToCycles(PowerPC::ppcState.downcount);
|
s_idled_cycles += DowncountToCycles(g, PowerPC::ppcState.downcount);
|
||||||
PowerPC::ppcState.downcount = 0;
|
PowerPC::ppcState.downcount = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -439,21 +455,25 @@ void SetFakeDecStartTicks(u64 val)
|
|||||||
|
|
||||||
u64 GetFakeTBStartValue()
|
u64 GetFakeTBStartValue()
|
||||||
{
|
{
|
||||||
|
auto& g = Core::System::GetInstance().GetCoreTimingGlobals();
|
||||||
return g.fake_TB_start_value;
|
return g.fake_TB_start_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetFakeTBStartValue(u64 val)
|
void SetFakeTBStartValue(u64 val)
|
||||||
{
|
{
|
||||||
|
auto& g = Core::System::GetInstance().GetCoreTimingGlobals();
|
||||||
g.fake_TB_start_value = val;
|
g.fake_TB_start_value = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 GetFakeTBStartTicks()
|
u64 GetFakeTBStartTicks()
|
||||||
{
|
{
|
||||||
|
auto& g = Core::System::GetInstance().GetCoreTimingGlobals();
|
||||||
return g.fake_TB_start_ticks;
|
return g.fake_TB_start_ticks;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetFakeTBStartTicks(u64 val)
|
void SetFakeTBStartTicks(u64 val)
|
||||||
{
|
{
|
||||||
|
auto& g = Core::System::GetInstance().GetCoreTimingGlobals();
|
||||||
g.fake_TB_start_ticks = val;
|
g.fake_TB_start_ticks = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,6 @@ struct Globals
|
|||||||
u64 fake_TB_start_ticks;
|
u64 fake_TB_start_ticks;
|
||||||
float last_OC_factor_inverted;
|
float last_OC_factor_inverted;
|
||||||
};
|
};
|
||||||
extern Globals g;
|
|
||||||
|
|
||||||
// CoreTiming begins at the boundary of timing slice -1. An initial call to Advance() is
|
// CoreTiming begins at the boundary of timing slice -1. An initial call to Advance() is
|
||||||
// required to end slice -1 and start slice 0 before the first cycle of code is executed.
|
// required to end slice -1 and start slice 0 before the first cycle of code is executed.
|
||||||
|
@ -212,13 +212,15 @@ int Interpreter::SingleStepInner()
|
|||||||
|
|
||||||
void Interpreter::SingleStep()
|
void Interpreter::SingleStep()
|
||||||
{
|
{
|
||||||
|
auto& core_timing_globals = Core::System::GetInstance().GetCoreTimingGlobals();
|
||||||
|
|
||||||
// Declare start of new slice
|
// Declare start of new slice
|
||||||
CoreTiming::Advance();
|
CoreTiming::Advance();
|
||||||
|
|
||||||
SingleStepInner();
|
SingleStepInner();
|
||||||
|
|
||||||
// The interpreter ignores instruction timing information outside the 'fast runloop'.
|
// The interpreter ignores instruction timing information outside the 'fast runloop'.
|
||||||
CoreTiming::g.slice_length = 1;
|
core_timing_globals.slice_length = 1;
|
||||||
PowerPC::ppcState.downcount = 0;
|
PowerPC::ppcState.downcount = 0;
|
||||||
|
|
||||||
if (PowerPC::ppcState.Exceptions != 0)
|
if (PowerPC::ppcState.Exceptions != 0)
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "Core/PowerPC/Jit64/RegCache/JitRegCache.h"
|
#include "Core/PowerPC/Jit64/RegCache/JitRegCache.h"
|
||||||
#include "Core/PowerPC/Jit64Common/Jit64PowerPCState.h"
|
#include "Core/PowerPC/Jit64Common/Jit64PowerPCState.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
|
#include "Core/System.h"
|
||||||
|
|
||||||
using namespace Gen;
|
using namespace Gen;
|
||||||
|
|
||||||
@ -322,7 +323,8 @@ void Jit64::mfspr(UGeckoInstruction inst)
|
|||||||
RCX64Reg rax = gpr.Scratch(RAX);
|
RCX64Reg rax = gpr.Scratch(RAX);
|
||||||
RCX64Reg rcx = gpr.Scratch(RCX);
|
RCX64Reg rcx = gpr.Scratch(RCX);
|
||||||
|
|
||||||
MOV(64, rcx, ImmPtr(&CoreTiming::g));
|
auto& core_timing_globals = Core::System::GetInstance().GetCoreTimingGlobals();
|
||||||
|
MOV(64, rcx, ImmPtr(&core_timing_globals));
|
||||||
|
|
||||||
// An inline implementation of CoreTiming::GetFakeTimeBase, since in timer-heavy games the
|
// An inline implementation of CoreTiming::GetFakeTimeBase, since in timer-heavy games the
|
||||||
// cost of calling out to C for this is actually significant.
|
// cost of calling out to C for this is actually significant.
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "Core/PowerPC/Interpreter/ExceptionUtils.h"
|
#include "Core/PowerPC/Interpreter/ExceptionUtils.h"
|
||||||
#include "Core/PowerPC/PPCTables.h"
|
#include "Core/PowerPC/PPCTables.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
|
#include "Core/System.h"
|
||||||
|
|
||||||
using namespace Arm64Gen;
|
using namespace Arm64Gen;
|
||||||
|
|
||||||
@ -306,7 +307,8 @@ void JitArm64::mfspr(UGeckoInstruction inst)
|
|||||||
// An inline implementation of CoreTiming::GetFakeTimeBase, since in timer-heavy games the
|
// An inline implementation of CoreTiming::GetFakeTimeBase, since in timer-heavy games the
|
||||||
// cost of calling out to C for this is actually significant.
|
// cost of calling out to C for this is actually significant.
|
||||||
|
|
||||||
MOVP2R(Xg, &CoreTiming::g);
|
auto& core_timing_globals = Core::System::GetInstance().GetCoreTimingGlobals();
|
||||||
|
MOVP2R(Xg, &core_timing_globals);
|
||||||
|
|
||||||
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(downcount));
|
LDR(IndexType::Unsigned, WA, PPC_REG, PPCSTATE_OFF(downcount));
|
||||||
m_float_emit.SCVTF(SC, WA);
|
m_float_emit.SCVTF(SC, WA);
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
|
|
||||||
#include "AudioCommon/SoundStream.h"
|
#include "AudioCommon/SoundStream.h"
|
||||||
#include "Core/Config/MainSettings.h"
|
#include "Core/Config/MainSettings.h"
|
||||||
|
#include "Core/CoreTiming.h"
|
||||||
#include "Core/HW/AudioInterface.h"
|
#include "Core/HW/AudioInterface.h"
|
||||||
#include "Core/HW/DSP.h"
|
#include "Core/HW/DSP.h"
|
||||||
#include "Core/HW/DVD/DVDInterface.h"
|
#include "Core/HW/DVD/DVDInterface.h"
|
||||||
@ -26,6 +27,7 @@ struct System::Impl
|
|||||||
bool m_audio_dump_started = false;
|
bool m_audio_dump_started = false;
|
||||||
|
|
||||||
AudioInterface::AudioInterfaceState m_audio_interface_state;
|
AudioInterface::AudioInterfaceState m_audio_interface_state;
|
||||||
|
CoreTiming::Globals m_core_timing_globals;
|
||||||
DSP::DSPState m_dsp_state;
|
DSP::DSPState m_dsp_state;
|
||||||
DVDInterface::DVDInterfaceState m_dvd_interface_state;
|
DVDInterface::DVDInterfaceState m_dvd_interface_state;
|
||||||
DVDThread::DVDThreadState m_dvd_thread_state;
|
DVDThread::DVDThreadState m_dvd_thread_state;
|
||||||
@ -84,6 +86,11 @@ AudioInterface::AudioInterfaceState& System::GetAudioInterfaceState() const
|
|||||||
return m_impl->m_audio_interface_state;
|
return m_impl->m_audio_interface_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CoreTiming::Globals& System::GetCoreTimingGlobals() const
|
||||||
|
{
|
||||||
|
return m_impl->m_core_timing_globals;
|
||||||
|
}
|
||||||
|
|
||||||
DSP::DSPState& System::GetDSPState() const
|
DSP::DSPState& System::GetDSPState() const
|
||||||
{
|
{
|
||||||
return m_impl->m_dsp_state;
|
return m_impl->m_dsp_state;
|
||||||
|
@ -12,6 +12,10 @@ namespace AudioInterface
|
|||||||
{
|
{
|
||||||
class AudioInterfaceState;
|
class AudioInterfaceState;
|
||||||
};
|
};
|
||||||
|
namespace CoreTiming
|
||||||
|
{
|
||||||
|
struct Globals;
|
||||||
|
}
|
||||||
namespace DSP
|
namespace DSP
|
||||||
{
|
{
|
||||||
class DSPState;
|
class DSPState;
|
||||||
@ -76,6 +80,7 @@ public:
|
|||||||
void SetAudioDumpStarted(bool started);
|
void SetAudioDumpStarted(bool started);
|
||||||
|
|
||||||
AudioInterface::AudioInterfaceState& GetAudioInterfaceState() const;
|
AudioInterface::AudioInterfaceState& GetAudioInterfaceState() const;
|
||||||
|
CoreTiming::Globals& GetCoreTimingGlobals() const;
|
||||||
DSP::DSPState& GetDSPState() const;
|
DSP::DSPState& GetDSPState() const;
|
||||||
DVDInterface::DVDInterfaceState& GetDVDInterfaceState() const;
|
DVDInterface::DVDInterfaceState& GetDVDInterfaceState() const;
|
||||||
DVDThread::DVDThreadState& GetDVDThreadState() const;
|
DVDThread::DVDThreadState& GetDVDThreadState() const;
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "Core/Core.h"
|
#include "Core/Core.h"
|
||||||
#include "Core/CoreTiming.h"
|
#include "Core/CoreTiming.h"
|
||||||
#include "Core/PowerPC/PowerPC.h"
|
#include "Core/PowerPC/PowerPC.h"
|
||||||
|
#include "Core/System.h"
|
||||||
#include "UICommon/UICommon.h"
|
#include "UICommon/UICommon.h"
|
||||||
|
|
||||||
// Numbers are chosen randomly to make sure the correct one is given.
|
// Numbers are chosen randomly to make sure the correct one is given.
|
||||||
@ -279,9 +280,10 @@ TEST(CoreTiming, ScheduleIntoPast)
|
|||||||
// the stale value, i.e. effectively half-way through the previous slice.
|
// 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.
|
// NOTE: We're only testing that the scheduler doesn't break, not whether this makes sense.
|
||||||
Core::UndeclareAsCPUThread();
|
Core::UndeclareAsCPUThread();
|
||||||
CoreTiming::g.global_timer -= 1000;
|
auto& core_timing_globals = Core::System::GetInstance().GetCoreTimingGlobals();
|
||||||
|
core_timing_globals.global_timer -= 1000;
|
||||||
CoreTiming::ScheduleEvent(0, cb_b, CB_IDS[1], CoreTiming::FromThread::NON_CPU);
|
CoreTiming::ScheduleEvent(0, cb_b, CB_IDS[1], CoreTiming::FromThread::NON_CPU);
|
||||||
CoreTiming::g.global_timer += 1000;
|
core_timing_globals.global_timer += 1000;
|
||||||
Core::DeclareAsCPUThread();
|
Core::DeclareAsCPUThread();
|
||||||
AdvanceAndCheck(1, MAX_SLICE_LENGTH, MAX_SLICE_LENGTH + 1000);
|
AdvanceAndCheck(1, MAX_SLICE_LENGTH, MAX_SLICE_LENGTH + 1000);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user