core_timing: Make use of std::chrono with ScheduleEvent
This commit is contained in:
parent
263200f982
commit
8b50c660df
13 changed files with 58 additions and 49 deletions
|
@ -59,11 +59,9 @@ Stream::State Stream::GetState() const {
|
|||
return state;
|
||||
}
|
||||
|
||||
s64 Stream::GetBufferReleaseNS(const Buffer& buffer) const {
|
||||
std::chrono::nanoseconds Stream::GetBufferReleaseNS(const Buffer& buffer) const {
|
||||
const std::size_t num_samples{buffer.GetSamples().size() / GetNumChannels()};
|
||||
const auto ns =
|
||||
std::chrono::nanoseconds((static_cast<u64>(num_samples) * 1000000000ULL) / sample_rate);
|
||||
return ns.count();
|
||||
return std::chrono::nanoseconds((static_cast<u64>(num_samples) * 1000000000ULL) / sample_rate);
|
||||
}
|
||||
|
||||
static void VolumeAdjustSamples(std::vector<s16>& samples, float game_volume) {
|
||||
|
@ -105,10 +103,10 @@ void Stream::PlayNextBuffer(s64 cycles_late) {
|
|||
|
||||
sink_stream.EnqueueSamples(GetNumChannels(), active_buffer->GetSamples());
|
||||
|
||||
core_timing.ScheduleEvent(
|
||||
GetBufferReleaseNS(*active_buffer) -
|
||||
(Settings::values.enable_audio_stretching.GetValue() ? 0 : cycles_late),
|
||||
release_event, {});
|
||||
const auto time_stretch_delta = std::chrono::nanoseconds{
|
||||
Settings::values.enable_audio_stretching.GetValue() ? 0 : cycles_late};
|
||||
const auto future_time = GetBufferReleaseNS(*active_buffer) - time_stretch_delta;
|
||||
core_timing.ScheduleEvent(future_time, release_event, {});
|
||||
}
|
||||
|
||||
void Stream::ReleaseActiveBuffer(s64 cycles_late) {
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
@ -96,10 +97,7 @@ private:
|
|||
void ReleaseActiveBuffer(s64 cycles_late = 0);
|
||||
|
||||
/// Gets the number of core cycles when the specified buffer will be released
|
||||
s64 GetBufferReleaseNS(const Buffer& buffer) const;
|
||||
|
||||
/// Gets the number of core cycles when the specified buffer will be released
|
||||
s64 GetBufferReleaseNSHostTiming(const Buffer& buffer) const;
|
||||
std::chrono::nanoseconds GetBufferReleaseNS(const Buffer& buffer) const;
|
||||
|
||||
u32 sample_rate; ///< Sample rate of the stream
|
||||
Format format; ///< Format of the stream
|
||||
|
|
|
@ -53,7 +53,7 @@ void CoreTiming::ThreadEntry(CoreTiming& instance) {
|
|||
instance.ThreadLoop();
|
||||
}
|
||||
|
||||
void CoreTiming::Initialize(std::function<void(void)>&& on_thread_init_) {
|
||||
void CoreTiming::Initialize(std::function<void()>&& on_thread_init_) {
|
||||
on_thread_init = std::move(on_thread_init_);
|
||||
event_fifo_id = 0;
|
||||
shutting_down = false;
|
||||
|
@ -106,11 +106,11 @@ bool CoreTiming::HasPendingEvents() const {
|
|||
return !(wait_set && event_queue.empty());
|
||||
}
|
||||
|
||||
void CoreTiming::ScheduleEvent(s64 ns_into_future, const std::shared_ptr<EventType>& event_type,
|
||||
u64 userdata) {
|
||||
void CoreTiming::ScheduleEvent(std::chrono::nanoseconds ns_into_future,
|
||||
const std::shared_ptr<EventType>& event_type, u64 userdata) {
|
||||
{
|
||||
std::scoped_lock scope{basic_lock};
|
||||
const u64 timeout = static_cast<u64>(GetGlobalTimeNs().count() + ns_into_future);
|
||||
const u64 timeout = static_cast<u64>((GetGlobalTimeNs() + ns_into_future).count());
|
||||
|
||||
event_queue.emplace_back(Event{timeout, event_fifo_id++, userdata, event_type});
|
||||
|
||||
|
|
|
@ -62,7 +62,7 @@ public:
|
|||
|
||||
/// 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.
|
||||
void Initialize(std::function<void(void)>&& on_thread_init_);
|
||||
void Initialize(std::function<void()>&& on_thread_init_);
|
||||
|
||||
/// Tears down all timing related functionality.
|
||||
void Shutdown();
|
||||
|
@ -95,8 +95,8 @@ public:
|
|||
bool HasPendingEvents() const;
|
||||
|
||||
/// Schedules an event in core timing
|
||||
void ScheduleEvent(s64 ns_into_future, const std::shared_ptr<EventType>& event_type,
|
||||
u64 userdata = 0);
|
||||
void ScheduleEvent(std::chrono::nanoseconds ns_into_future,
|
||||
const std::shared_ptr<EventType>& event_type, u64 userdata = 0);
|
||||
|
||||
void UnscheduleEvent(const std::shared_ptr<EventType>& event_type, u64 userdata);
|
||||
|
||||
|
@ -161,7 +161,7 @@ private:
|
|||
std::atomic<bool> wait_set{};
|
||||
std::atomic<bool> shutting_down{};
|
||||
std::atomic<bool> has_started{};
|
||||
std::function<void(void)> on_thread_init{};
|
||||
std::function<void()> on_thread_init{};
|
||||
|
||||
bool is_multicore{};
|
||||
|
||||
|
|
|
@ -23,7 +23,7 @@ InterruptManager::~InterruptManager() = default;
|
|||
|
||||
void InterruptManager::GPUInterruptSyncpt(const u32 syncpoint_id, const u32 value) {
|
||||
const u64 msg = (static_cast<u64>(syncpoint_id) << 32ULL) | value;
|
||||
system.CoreTiming().ScheduleEvent(10, gpu_interrupt_event, msg);
|
||||
system.CoreTiming().ScheduleEvent(std::chrono::nanoseconds{10}, gpu_interrupt_event, msg);
|
||||
}
|
||||
|
||||
} // namespace Core::Hardware
|
||||
|
|
|
@ -149,11 +149,13 @@ struct KernelCore::Impl {
|
|||
SchedulerLock lock(kernel);
|
||||
global_scheduler.PreemptThreads();
|
||||
}
|
||||
s64 time_interval = Core::Timing::msToCycles(std::chrono::milliseconds(10));
|
||||
const auto time_interval = std::chrono::nanoseconds{
|
||||
Core::Timing::msToCycles(std::chrono::milliseconds(10))};
|
||||
system.CoreTiming().ScheduleEvent(time_interval, preemption_event);
|
||||
});
|
||||
|
||||
s64 time_interval = Core::Timing::msToCycles(std::chrono::milliseconds(10));
|
||||
const auto time_interval =
|
||||
std::chrono::nanoseconds{Core::Timing::msToCycles(std::chrono::milliseconds(10))};
|
||||
system.CoreTiming().ScheduleEvent(time_interval, preemption_event);
|
||||
}
|
||||
|
||||
|
|
|
@ -184,8 +184,8 @@ ResultCode ServerSession::CompleteSyncRequest() {
|
|||
|
||||
ResultCode ServerSession::HandleSyncRequest(std::shared_ptr<Thread> thread,
|
||||
Core::Memory::Memory& memory) {
|
||||
ResultCode result = QueueSyncRequest(std::move(thread), memory);
|
||||
const u64 delay = kernel.IsMulticore() ? 0U : 20000U;
|
||||
const ResultCode result = QueueSyncRequest(std::move(thread), memory);
|
||||
const auto delay = std::chrono::nanoseconds{kernel.IsMulticore() ? 0 : 20000};
|
||||
Core::System::GetInstance().CoreTiming().ScheduleEvent(delay, request_event, {});
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -34,7 +34,8 @@ void TimeManager::ScheduleTimeEvent(Handle& event_handle, Thread* timetask, s64
|
|||
ASSERT(timetask);
|
||||
ASSERT(timetask->GetStatus() != ThreadStatus::Ready);
|
||||
ASSERT(timetask->GetStatus() != ThreadStatus::WaitMutex);
|
||||
system.CoreTiming().ScheduleEvent(nanoseconds, time_manager_event_type, event_handle);
|
||||
system.CoreTiming().ScheduleEvent(std::chrono::nanoseconds{nanoseconds},
|
||||
time_manager_event_type, event_handle);
|
||||
} else {
|
||||
event_handle = InvalidHandle;
|
||||
}
|
||||
|
|
|
@ -39,9 +39,10 @@ namespace Service::HID {
|
|||
|
||||
// Updating period for each HID device.
|
||||
// TODO(ogniK): Find actual polling rate of hid
|
||||
constexpr s64 pad_update_ticks = static_cast<s64>(1000000000 / 66);
|
||||
[[maybe_unused]] constexpr s64 accelerometer_update_ticks = static_cast<s64>(1000000000 / 100);
|
||||
[[maybe_unused]] constexpr s64 gyroscope_update_ticks = static_cast<s64>(1000000000 / 100);
|
||||
constexpr auto pad_update_ns = std::chrono::nanoseconds{1000000000 / 66};
|
||||
[[maybe_unused]] constexpr auto accelerometer_update_ns =
|
||||
std::chrono::nanoseconds{1000000000 / 100};
|
||||
[[maybe_unused]] constexpr auto gyroscope_update_ticks = std::chrono::nanoseconds{1000000000 / 100};
|
||||
constexpr std::size_t SHARED_MEMORY_SIZE = 0x40000;
|
||||
|
||||
IAppletResource::IAppletResource(Core::System& system)
|
||||
|
@ -82,7 +83,7 @@ IAppletResource::IAppletResource(Core::System& system)
|
|||
|
||||
// TODO(shinyquagsire23): Other update callbacks? (accel, gyro?)
|
||||
|
||||
system.CoreTiming().ScheduleEvent(pad_update_ticks, pad_update_event);
|
||||
system.CoreTiming().ScheduleEvent(pad_update_ns, pad_update_event);
|
||||
|
||||
ReloadInputDevices();
|
||||
}
|
||||
|
@ -118,7 +119,8 @@ void IAppletResource::UpdateControllers(u64 userdata, s64 ns_late) {
|
|||
controller->OnUpdate(core_timing, shared_mem->GetPointer(), SHARED_MEMORY_SIZE);
|
||||
}
|
||||
|
||||
core_timing.ScheduleEvent(pad_update_ticks - ns_late, pad_update_event);
|
||||
const auto future_ns = pad_update_ns - std::chrono::nanoseconds{ns_late};
|
||||
core_timing.ScheduleEvent(future_ns, pad_update_event);
|
||||
}
|
||||
|
||||
class IActiveVibrationDeviceList final : public ServiceFramework<IActiveVibrationDeviceList> {
|
||||
|
|
|
@ -28,8 +28,7 @@
|
|||
|
||||
namespace Service::NVFlinger {
|
||||
|
||||
constexpr s64 frame_ticks = static_cast<s64>(1000000000 / 60);
|
||||
constexpr s64 frame_ticks_30fps = static_cast<s64>(1000000000 / 30);
|
||||
constexpr auto frame_ns = std::chrono::nanoseconds{1000000000 / 60};
|
||||
|
||||
void NVFlinger::VSyncThread(NVFlinger& nv_flinger) {
|
||||
nv_flinger.SplitVSync();
|
||||
|
@ -71,16 +70,20 @@ NVFlinger::NVFlinger(Core::System& system) : system(system) {
|
|||
Core::Timing::CreateEvent("ScreenComposition", [this](u64 userdata, s64 ns_late) {
|
||||
Lock();
|
||||
Compose();
|
||||
const auto ticks = GetNextTicks();
|
||||
this->system.CoreTiming().ScheduleEvent(std::max<s64>(0LL, ticks - ns_late),
|
||||
composition_event);
|
||||
|
||||
const auto ticks = std::chrono::nanoseconds{GetNextTicks()};
|
||||
const auto ticks_delta = ticks - std::chrono::nanoseconds{ns_late};
|
||||
const auto future_ns = std::max(std::chrono::nanoseconds::zero(), ticks_delta);
|
||||
|
||||
this->system.CoreTiming().ScheduleEvent(future_ns, composition_event);
|
||||
});
|
||||
|
||||
if (system.IsMulticore()) {
|
||||
is_running = true;
|
||||
wait_event = std::make_unique<Common::Event>();
|
||||
vsync_thread = std::make_unique<std::thread>(VSyncThread, std::ref(*this));
|
||||
} else {
|
||||
system.CoreTiming().ScheduleEvent(frame_ticks, composition_event);
|
||||
system.CoreTiming().ScheduleEvent(frame_ns, composition_event);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
namespace Core::Memory {
|
||||
|
||||
constexpr s64 CHEAT_ENGINE_TICKS = static_cast<s64>(1000000000 / 12);
|
||||
constexpr auto CHEAT_ENGINE_NS = std::chrono::nanoseconds{1000000000 / 12};
|
||||
constexpr u32 KEYPAD_BITMASK = 0x3FFFFFF;
|
||||
|
||||
StandardVmCallbacks::StandardVmCallbacks(Core::System& system, const CheatProcessMetadata& metadata)
|
||||
|
@ -191,7 +191,7 @@ void CheatEngine::Initialize() {
|
|||
event = Core::Timing::CreateEvent(
|
||||
"CheatEngine::FrameCallback::" + Common::HexToString(metadata.main_nso_build_id),
|
||||
[this](u64 userdata, s64 ns_late) { FrameCallback(userdata, ns_late); });
|
||||
core_timing.ScheduleEvent(CHEAT_ENGINE_TICKS, event);
|
||||
core_timing.ScheduleEvent(CHEAT_ENGINE_NS, event);
|
||||
|
||||
metadata.process_id = system.CurrentProcess()->GetProcessID();
|
||||
metadata.title_id = system.CurrentProcess()->GetTitleID();
|
||||
|
@ -230,7 +230,8 @@ void CheatEngine::FrameCallback(u64 userdata, s64 ns_late) {
|
|||
|
||||
vm.Execute(metadata);
|
||||
|
||||
core_timing.ScheduleEvent(CHEAT_ENGINE_TICKS - ns_late, event);
|
||||
const auto future_ns = CHEAT_ENGINE_NS - std::chrono::nanoseconds{ns_late};
|
||||
core_timing.ScheduleEvent(future_ns, event);
|
||||
}
|
||||
|
||||
} // namespace Core::Memory
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
namespace Tools {
|
||||
namespace {
|
||||
|
||||
constexpr s64 MEMORY_FREEZER_TICKS = static_cast<s64>(1000000000 / 60);
|
||||
constexpr auto memory_freezer_ns = std::chrono::nanoseconds{1000000000 / 60};
|
||||
|
||||
u64 MemoryReadWidth(Core::Memory::Memory& memory, u32 width, VAddr addr) {
|
||||
switch (width) {
|
||||
|
@ -58,7 +58,7 @@ Freezer::Freezer(Core::Timing::CoreTiming& core_timing_, Core::Memory::Memory& m
|
|||
event = Core::Timing::CreateEvent(
|
||||
"MemoryFreezer::FrameCallback",
|
||||
[this](u64 userdata, s64 ns_late) { FrameCallback(userdata, ns_late); });
|
||||
core_timing.ScheduleEvent(MEMORY_FREEZER_TICKS, event);
|
||||
core_timing.ScheduleEvent(memory_freezer_ns, event);
|
||||
}
|
||||
|
||||
Freezer::~Freezer() {
|
||||
|
@ -68,7 +68,7 @@ Freezer::~Freezer() {
|
|||
void Freezer::SetActive(bool active) {
|
||||
if (!this->active.exchange(active)) {
|
||||
FillEntryReads();
|
||||
core_timing.ScheduleEvent(MEMORY_FREEZER_TICKS, event);
|
||||
core_timing.ScheduleEvent(memory_freezer_ns, event);
|
||||
LOG_DEBUG(Common_Memory, "Memory freezer activated!");
|
||||
} else {
|
||||
LOG_DEBUG(Common_Memory, "Memory freezer deactivated!");
|
||||
|
@ -173,7 +173,8 @@ void Freezer::FrameCallback(u64 userdata, s64 ns_late) {
|
|||
MemoryWriteWidth(memory, entry.width, entry.address, entry.value);
|
||||
}
|
||||
|
||||
core_timing.ScheduleEvent(MEMORY_FREEZER_TICKS - ns_late, event);
|
||||
const auto future_ns = memory_freezer_ns - std::chrono::nanoseconds{ns_late};
|
||||
core_timing.ScheduleEvent(future_ns, event);
|
||||
}
|
||||
|
||||
void Freezer::FillEntryReads() {
|
||||
|
|
|
@ -116,13 +116,16 @@ TEST_CASE("CoreTiming[BasicOrderNoPausing]", "[core]") {
|
|||
|
||||
expected_callback = 0;
|
||||
|
||||
u64 start = core_timing.GetGlobalTimeNs().count();
|
||||
u64 one_micro = 1000U;
|
||||
const u64 start = core_timing.GetGlobalTimeNs().count();
|
||||
const u64 one_micro = 1000U;
|
||||
|
||||
for (std::size_t i = 0; i < events.size(); i++) {
|
||||
u64 order = calls_order[i];
|
||||
core_timing.ScheduleEvent(i * one_micro + 100U, events[order], CB_IDS[order]);
|
||||
const u64 order = calls_order[i];
|
||||
const auto future_ns = std::chrono::nanoseconds{static_cast<s64>(i * one_micro + 100)};
|
||||
core_timing.ScheduleEvent(future_ns, events[order], CB_IDS[order]);
|
||||
}
|
||||
u64 end = core_timing.GetGlobalTimeNs().count();
|
||||
|
||||
const u64 end = core_timing.GetGlobalTimeNs().count();
|
||||
const double scheduling_time = static_cast<double>(end - start);
|
||||
const double timer_time = static_cast<double>(TestTimerSpeed(core_timing));
|
||||
|
||||
|
|
Loading…
Reference in a new issue