mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-08-28 13:16:41 +00:00
CoreTiming: Add support for secondary event type that does not affect timing.
This commit is contained in:
parent
f284bfca45
commit
1ce5e2425d
2 changed files with 54 additions and 0 deletions
|
@ -212,6 +212,9 @@ void CoreTimingManager::DoState(PointerWrap& p)
|
|||
// The stave state has changed the time, so our previous Throttle targets are invalid.
|
||||
// Especially when global_time goes down; So we create a fake throttle update.
|
||||
ResetThrottle(m_globals.global_timer);
|
||||
|
||||
// Throw away pending external events when loading state, they no longer apply.
|
||||
m_external_event_queue.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -282,6 +285,24 @@ void CoreTimingManager::ScheduleEvent(s64 cycles_into_future, EventType* event_t
|
|||
}
|
||||
}
|
||||
|
||||
void CoreTimingManager::ScheduleExternalEvent(u64 timepoint, EventType* event_type, u64 userdata,
|
||||
u64 unique_id)
|
||||
{
|
||||
if (Core::IsCPUThread())
|
||||
{
|
||||
m_external_event_queue.emplace_back(
|
||||
Event{static_cast<s64>(timepoint), unique_id, userdata, event_type});
|
||||
std::push_heap(m_external_event_queue.begin(), m_external_event_queue.end(),
|
||||
std::greater<Event>());
|
||||
}
|
||||
else
|
||||
{
|
||||
std::lock_guard lk(m_ts_write_lock);
|
||||
m_external_pending_queue.Push(
|
||||
Event{static_cast<s64>(timepoint), unique_id, userdata, event_type});
|
||||
}
|
||||
}
|
||||
|
||||
void CoreTimingManager::RemoveEvent(EventType* event_type)
|
||||
{
|
||||
auto itr = std::remove_if(m_event_queue.begin(), m_event_queue.end(),
|
||||
|
@ -322,6 +343,13 @@ void CoreTimingManager::MoveEvents()
|
|||
m_event_queue.emplace_back(std::move(ev));
|
||||
std::push_heap(m_event_queue.begin(), m_event_queue.end(), std::greater<Event>());
|
||||
}
|
||||
|
||||
for (Event ev; m_external_pending_queue.Pop(ev);)
|
||||
{
|
||||
m_external_event_queue.emplace_back(std::move(ev));
|
||||
std::push_heap(m_external_event_queue.begin(), m_external_event_queue.end(),
|
||||
std::greater<Event>());
|
||||
}
|
||||
}
|
||||
|
||||
void CoreTimingManager::Advance()
|
||||
|
@ -351,6 +379,16 @@ void CoreTimingManager::Advance()
|
|||
evt.type->callback(m_system, evt.userdata, m_globals.global_timer - evt.time);
|
||||
}
|
||||
|
||||
while (!m_external_event_queue.empty() &&
|
||||
m_external_event_queue.front().time <= m_globals.global_timer)
|
||||
{
|
||||
Event evt = std::move(m_external_event_queue.front());
|
||||
std::pop_heap(m_external_event_queue.begin(), m_external_event_queue.end(),
|
||||
std::greater<Event>());
|
||||
m_external_event_queue.pop_back();
|
||||
evt.type->callback(m_system, evt.userdata, m_globals.global_timer - evt.time);
|
||||
}
|
||||
|
||||
m_is_global_timer_sane = false;
|
||||
|
||||
// Still events left (scheduled in the future)
|
||||
|
|
|
@ -104,6 +104,13 @@ public:
|
|||
void ScheduleEvent(s64 cycles_into_future, EventType* event_type, u64 userdata = 0,
|
||||
FromThread from = FromThread::CPU);
|
||||
|
||||
// Similar to ScheduleEvent, but enqueues an event in the secondary event queue that does not
|
||||
// affect timing logic and isn't savestated. Used primarily for handling events in a deterministic
|
||||
// manner during netplay. Note that 'timepoint' is absolute (instead of ScheduleEvent's relative)
|
||||
// and that the user should try to provide a 'unique_id' for consistent event ordering if they
|
||||
// happen to be at the same timepoint.
|
||||
void ScheduleExternalEvent(u64 timepoint, EventType* event_type, u64 userdata, u64 unique_id);
|
||||
|
||||
// We only permit one event of each type in the queue at a time.
|
||||
void RemoveEvent(EventType* event_type);
|
||||
void RemoveAllEvents(EventType* event_type);
|
||||
|
@ -172,6 +179,15 @@ private:
|
|||
std::mutex m_ts_write_lock;
|
||||
Common::SPSCQueue<Event, false> m_ts_queue;
|
||||
|
||||
// A second event queue that is used for timing 'external' events that are sent by the emulator
|
||||
// rather than by the emulated game. Netplay uses these for syncing non-controller-button events
|
||||
// sent by a single client, such as a press of the physical Reset button on the console, or an
|
||||
// unplugging of a controller. These don't affect timing logic (and thus will not run at a precise
|
||||
// time, but instead at the first opportunity given by the regular events) and do not get written
|
||||
// to savestates.
|
||||
std::vector<Event> m_external_event_queue;
|
||||
Common::SPSCQueue<Event, false> m_external_pending_queue;
|
||||
|
||||
float m_last_oc_factor = 0.0f;
|
||||
|
||||
s64 m_idled_cycles = 0;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue