mirror of
https://gitlab.com/suyu-emu/suyu.git
synced 2024-03-15 23:15:44 +00:00
core_timing: Use CNTPCT as the guest CPU tick
Previously, we were mixing the raw CPU frequency and CNTFRQ. The raw CPU frequency (1020 MHz) should've never been used as CNTPCT (whose frequency is CNTFRQ) is the only counter available.
This commit is contained in:
parent
bbd502f67a
commit
8e56a84566
|
@ -7,7 +7,6 @@
|
||||||
#include "common/logging/log.h"
|
#include "common/logging/log.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
#include "core/core_timing_util.h"
|
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
|
|
||||||
namespace AudioCore::AudioRenderer::ADSP {
|
namespace AudioCore::AudioRenderer::ADSP {
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
#include "common/thread.h"
|
#include "common/thread.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
#include "core/core_timing_util.h"
|
|
||||||
|
|
||||||
MICROPROFILE_DEFINE(Audio_Renderer, "Audio", "DSP", MP_RGB(60, 19, 97));
|
MICROPROFILE_DEFINE(Audio_Renderer, "Audio", "DSP", MP_RGB(60, 19, 97));
|
||||||
|
|
||||||
|
@ -144,6 +143,7 @@ void AudioRenderer::ThreadFunc(std::stop_token stop_token) {
|
||||||
|
|
||||||
mailbox->ADSPSendMessage(RenderMessage::AudioRenderer_InitializeOK);
|
mailbox->ADSPSendMessage(RenderMessage::AudioRenderer_InitializeOK);
|
||||||
|
|
||||||
|
// 0.12 seconds (2304000 / 19200000)
|
||||||
constexpr u64 max_process_time{2'304'000ULL};
|
constexpr u64 max_process_time{2'304'000ULL};
|
||||||
|
|
||||||
while (!stop_token.stop_requested()) {
|
while (!stop_token.stop_requested()) {
|
||||||
|
@ -184,8 +184,7 @@ void AudioRenderer::ThreadFunc(std::stop_token stop_token) {
|
||||||
u64 max_time{max_process_time};
|
u64 max_time{max_process_time};
|
||||||
if (index == 1 && command_buffer.applet_resource_user_id ==
|
if (index == 1 && command_buffer.applet_resource_user_id ==
|
||||||
mailbox->GetCommandBuffer(0).applet_resource_user_id) {
|
mailbox->GetCommandBuffer(0).applet_resource_user_id) {
|
||||||
max_time = max_process_time -
|
max_time = max_process_time - render_times_taken[0];
|
||||||
Core::Timing::CyclesToNs(render_times_taken[0]).count();
|
|
||||||
if (render_times_taken[0] > max_process_time) {
|
if (render_times_taken[0] > max_process_time) {
|
||||||
max_time = 0;
|
max_time = 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
#include "core/core_timing_util.h"
|
|
||||||
#include "core/memory.h"
|
#include "core/memory.h"
|
||||||
|
|
||||||
namespace AudioCore::AudioRenderer::ADSP {
|
namespace AudioCore::AudioRenderer::ADSP {
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include "audio_core/renderer/command/performance/performance.h"
|
#include "audio_core/renderer/command/performance/performance.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
#include "core/core_timing_util.h"
|
|
||||||
|
|
||||||
namespace AudioCore::AudioRenderer {
|
namespace AudioCore::AudioRenderer {
|
||||||
|
|
||||||
|
@ -18,20 +17,18 @@ void PerformanceCommand::Process(const ADSP::CommandListProcessor& processor) {
|
||||||
auto base{entry_address.translated_address};
|
auto base{entry_address.translated_address};
|
||||||
if (state == PerformanceState::Start) {
|
if (state == PerformanceState::Start) {
|
||||||
auto start_time_ptr{reinterpret_cast<u32*>(base + entry_address.entry_start_time_offset)};
|
auto start_time_ptr{reinterpret_cast<u32*>(base + entry_address.entry_start_time_offset)};
|
||||||
*start_time_ptr = static_cast<u32>(
|
*start_time_ptr =
|
||||||
Core::Timing::CyclesToUs(processor.system->CoreTiming().GetClockTicks() -
|
static_cast<u32>(processor.system->CoreTiming().GetClockTicks() - processor.start_time -
|
||||||
processor.start_time - processor.current_processing_time)
|
processor.current_processing_time);
|
||||||
.count());
|
|
||||||
} else if (state == PerformanceState::Stop) {
|
} else if (state == PerformanceState::Stop) {
|
||||||
auto processed_time_ptr{
|
auto processed_time_ptr{
|
||||||
reinterpret_cast<u32*>(base + entry_address.entry_processed_time_offset)};
|
reinterpret_cast<u32*>(base + entry_address.entry_processed_time_offset)};
|
||||||
auto entry_count_ptr{
|
auto entry_count_ptr{
|
||||||
reinterpret_cast<u32*>(base + entry_address.header_entry_count_offset)};
|
reinterpret_cast<u32*>(base + entry_address.header_entry_count_offset)};
|
||||||
|
|
||||||
*processed_time_ptr = static_cast<u32>(
|
*processed_time_ptr =
|
||||||
Core::Timing::CyclesToUs(processor.system->CoreTiming().GetClockTicks() -
|
static_cast<u32>(processor.system->CoreTiming().GetClockTicks() - processor.start_time -
|
||||||
processor.start_time - processor.current_processing_time)
|
processor.current_processing_time);
|
||||||
.count());
|
|
||||||
(*entry_count_ptr)++;
|
(*entry_count_ptr)++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,6 @@
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
#include "core/core_timing_util.h"
|
|
||||||
|
|
||||||
namespace AudioCore::Sink {
|
namespace AudioCore::Sink {
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,22 @@ public:
|
||||||
/// @returns Whether the clock directly uses the host's hardware clock.
|
/// @returns Whether the clock directly uses the host's hardware clock.
|
||||||
virtual bool IsNative() const = 0;
|
virtual bool IsNative() const = 0;
|
||||||
|
|
||||||
|
static inline u64 NSToCNTPCT(u64 ns) {
|
||||||
|
return ns * NsToCNTPCTRatio::num / NsToCNTPCTRatio::den;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u64 USToCNTPCT(u64 us) {
|
||||||
|
return us * UsToCNTPCTRatio::num / UsToCNTPCTRatio::den;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u64 CNTPCTToNS(u64 cntpct) {
|
||||||
|
return cntpct * NsToCNTPCTRatio::den / NsToCNTPCTRatio::num;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u64 CNTPCTToUS(u64 cntpct) {
|
||||||
|
return cntpct * UsToCNTPCTRatio::den / UsToCNTPCTRatio::num;
|
||||||
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
using NsRatio = std::nano;
|
using NsRatio = std::nano;
|
||||||
using UsRatio = std::micro;
|
using UsRatio = std::micro;
|
||||||
|
@ -46,6 +62,7 @@ protected:
|
||||||
using NsToUsRatio = std::ratio_divide<std::nano, std::micro>;
|
using NsToUsRatio = std::ratio_divide<std::nano, std::micro>;
|
||||||
using NsToMsRatio = std::ratio_divide<std::nano, std::milli>;
|
using NsToMsRatio = std::ratio_divide<std::nano, std::milli>;
|
||||||
using NsToCNTPCTRatio = std::ratio<CNTFRQ, std::nano::den>;
|
using NsToCNTPCTRatio = std::ratio<CNTFRQ, std::nano::den>;
|
||||||
|
using UsToCNTPCTRatio = std::ratio<CNTFRQ, std::micro::den>;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<WallClock> CreateOptimalClock();
|
std::unique_ptr<WallClock> CreateOptimalClock();
|
||||||
|
|
|
@ -16,7 +16,6 @@ add_library(core STATIC
|
||||||
core.h
|
core.h
|
||||||
core_timing.cpp
|
core_timing.cpp
|
||||||
core_timing.h
|
core_timing.h
|
||||||
core_timing_util.h
|
|
||||||
cpu_manager.cpp
|
cpu_manager.cpp
|
||||||
cpu_manager.h
|
cpu_manager.h
|
||||||
crypto/aes_util.cpp
|
crypto/aes_util.cpp
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
|
|
||||||
#include "common/microprofile.h"
|
#include "common/microprofile.h"
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
#include "core/core_timing_util.h"
|
|
||||||
#include "core/hardware_properties.h"
|
#include "core/hardware_properties.h"
|
||||||
|
|
||||||
namespace Core::Timing {
|
namespace Core::Timing {
|
||||||
|
@ -45,9 +44,7 @@ struct CoreTiming::Event {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
CoreTiming::CoreTiming()
|
CoreTiming::CoreTiming() : clock{Common::CreateOptimalClock()} {}
|
||||||
: cpu_clock{Common::CreateBestMatchingClock(Hardware::BASE_CLOCK_RATE, Hardware::CNTFREQ)},
|
|
||||||
event_clock{Common::CreateStandardWallClock(Hardware::BASE_CLOCK_RATE, Hardware::CNTFREQ)} {}
|
|
||||||
|
|
||||||
CoreTiming::~CoreTiming() {
|
CoreTiming::~CoreTiming() {
|
||||||
Reset();
|
Reset();
|
||||||
|
@ -180,7 +177,7 @@ void CoreTiming::AddTicks(u64 ticks_to_add) {
|
||||||
void CoreTiming::Idle() {
|
void CoreTiming::Idle() {
|
||||||
if (!event_queue.empty()) {
|
if (!event_queue.empty()) {
|
||||||
const u64 next_event_time = event_queue.front().time;
|
const u64 next_event_time = event_queue.front().time;
|
||||||
const u64 next_ticks = nsToCycles(std::chrono::nanoseconds(next_event_time)) + 10U;
|
const u64 next_ticks = Common::WallClock::NSToCNTPCT(next_event_time) + 10U;
|
||||||
if (next_ticks > ticks) {
|
if (next_ticks > ticks) {
|
||||||
ticks = next_ticks;
|
ticks = next_ticks;
|
||||||
}
|
}
|
||||||
|
@ -193,18 +190,11 @@ void CoreTiming::ResetTicks() {
|
||||||
downcount = MAX_SLICE_LENGTH;
|
downcount = MAX_SLICE_LENGTH;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 CoreTiming::GetCPUTicks() const {
|
|
||||||
if (is_multicore) [[likely]] {
|
|
||||||
return cpu_clock->GetCPUCycles();
|
|
||||||
}
|
|
||||||
return ticks;
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 CoreTiming::GetClockTicks() const {
|
u64 CoreTiming::GetClockTicks() const {
|
||||||
if (is_multicore) [[likely]] {
|
if (is_multicore) [[likely]] {
|
||||||
return cpu_clock->GetClockCycles();
|
return clock->GetCNTPCT();
|
||||||
}
|
}
|
||||||
return CpuCyclesToClockCycles(ticks);
|
return ticks;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<s64> CoreTiming::Advance() {
|
std::optional<s64> CoreTiming::Advance() {
|
||||||
|
@ -297,9 +287,7 @@ void CoreTiming::ThreadLoop() {
|
||||||
}
|
}
|
||||||
|
|
||||||
paused_set = true;
|
paused_set = true;
|
||||||
event_clock->Pause(true);
|
|
||||||
pause_event.Wait();
|
pause_event.Wait();
|
||||||
event_clock->Pause(false);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -315,25 +303,18 @@ void CoreTiming::Reset() {
|
||||||
has_started = false;
|
has_started = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::chrono::nanoseconds CoreTiming::GetCPUTimeNs() const {
|
|
||||||
if (is_multicore) [[likely]] {
|
|
||||||
return cpu_clock->GetTimeNS();
|
|
||||||
}
|
|
||||||
return CyclesToNs(ticks);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::chrono::nanoseconds CoreTiming::GetGlobalTimeNs() const {
|
std::chrono::nanoseconds CoreTiming::GetGlobalTimeNs() const {
|
||||||
if (is_multicore) [[likely]] {
|
if (is_multicore) [[likely]] {
|
||||||
return event_clock->GetTimeNS();
|
return clock->GetTimeNS();
|
||||||
}
|
}
|
||||||
return CyclesToNs(ticks);
|
return std::chrono::nanoseconds{Common::WallClock::CNTPCTToNS(ticks)};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const {
|
std::chrono::microseconds CoreTiming::GetGlobalTimeUs() const {
|
||||||
if (is_multicore) [[likely]] {
|
if (is_multicore) [[likely]] {
|
||||||
return event_clock->GetTimeUS();
|
return clock->GetTimeUS();
|
||||||
}
|
}
|
||||||
return CyclesToUs(ticks);
|
return std::chrono::microseconds{Common::WallClock::CNTPCTToUS(ticks)};
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Core::Timing
|
} // namespace Core::Timing
|
||||||
|
|
|
@ -116,15 +116,9 @@ public:
|
||||||
return downcount;
|
return downcount;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns current time in emulated CPU cycles
|
/// Returns the current CNTPCT tick value.
|
||||||
u64 GetCPUTicks() const;
|
|
||||||
|
|
||||||
/// Returns current time in emulated in Clock cycles
|
|
||||||
u64 GetClockTicks() const;
|
u64 GetClockTicks() const;
|
||||||
|
|
||||||
/// Returns current time in nanoseconds.
|
|
||||||
std::chrono::nanoseconds GetCPUTimeNs() const;
|
|
||||||
|
|
||||||
/// Returns current time in microseconds.
|
/// Returns current time in microseconds.
|
||||||
std::chrono::microseconds GetGlobalTimeUs() const;
|
std::chrono::microseconds GetGlobalTimeUs() const;
|
||||||
|
|
||||||
|
@ -142,8 +136,7 @@ private:
|
||||||
|
|
||||||
void Reset();
|
void Reset();
|
||||||
|
|
||||||
std::unique_ptr<Common::WallClock> cpu_clock;
|
std::unique_ptr<Common::WallClock> clock;
|
||||||
std::unique_ptr<Common::WallClock> event_clock;
|
|
||||||
|
|
||||||
s64 global_timer = 0;
|
s64 global_timer = 0;
|
||||||
|
|
||||||
|
|
|
@ -1,58 +0,0 @@
|
||||||
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
|
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <chrono>
|
|
||||||
|
|
||||||
#include "common/common_types.h"
|
|
||||||
#include "core/hardware_properties.h"
|
|
||||||
|
|
||||||
namespace Core::Timing {
|
|
||||||
|
|
||||||
namespace detail {
|
|
||||||
constexpr u64 CNTFREQ_ADJUSTED = Hardware::CNTFREQ / 1000;
|
|
||||||
constexpr u64 BASE_CLOCK_RATE_ADJUSTED = Hardware::BASE_CLOCK_RATE / 1000;
|
|
||||||
} // namespace detail
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr s64 msToCycles(std::chrono::milliseconds ms) {
|
|
||||||
return ms.count() * detail::BASE_CLOCK_RATE_ADJUSTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr s64 usToCycles(std::chrono::microseconds us) {
|
|
||||||
return us.count() * detail::BASE_CLOCK_RATE_ADJUSTED / 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr s64 nsToCycles(std::chrono::nanoseconds ns) {
|
|
||||||
return ns.count() * detail::BASE_CLOCK_RATE_ADJUSTED / 1000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr u64 msToClockCycles(std::chrono::milliseconds ms) {
|
|
||||||
return static_cast<u64>(ms.count()) * detail::CNTFREQ_ADJUSTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr u64 usToClockCycles(std::chrono::microseconds us) {
|
|
||||||
return us.count() * detail::CNTFREQ_ADJUSTED / 1000;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr u64 nsToClockCycles(std::chrono::nanoseconds ns) {
|
|
||||||
return ns.count() * detail::CNTFREQ_ADJUSTED / 1000000;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr u64 CpuCyclesToClockCycles(u64 ticks) {
|
|
||||||
return ticks * detail::CNTFREQ_ADJUSTED / detail::BASE_CLOCK_RATE_ADJUSTED;
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr std::chrono::milliseconds CyclesToMs(s64 cycles) {
|
|
||||||
return std::chrono::milliseconds(cycles / detail::BASE_CLOCK_RATE_ADJUSTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr std::chrono::nanoseconds CyclesToNs(s64 cycles) {
|
|
||||||
return std::chrono::nanoseconds(cycles * 1000000 / detail::BASE_CLOCK_RATE_ADJUSTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] constexpr std::chrono::microseconds CyclesToUs(s64 cycles) {
|
|
||||||
return std::chrono::microseconds(cycles * 1000 / detail::BASE_CLOCK_RATE_ADJUSTED);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Core::Timing
|
|
|
@ -184,7 +184,8 @@ u64 KScheduler::UpdateHighestPriorityThread(KThread* highest_thread) {
|
||||||
prev_highest_thread != highest_thread) [[likely]] {
|
prev_highest_thread != highest_thread) [[likely]] {
|
||||||
if (prev_highest_thread != nullptr) [[likely]] {
|
if (prev_highest_thread != nullptr) [[likely]] {
|
||||||
IncrementScheduledCount(prev_highest_thread);
|
IncrementScheduledCount(prev_highest_thread);
|
||||||
prev_highest_thread->SetLastScheduledTick(m_kernel.System().CoreTiming().GetCPUTicks());
|
prev_highest_thread->SetLastScheduledTick(
|
||||||
|
m_kernel.System().CoreTiming().GetClockTicks());
|
||||||
}
|
}
|
||||||
if (m_state.should_count_idle) {
|
if (m_state.should_count_idle) {
|
||||||
if (highest_thread != nullptr) [[likely]] {
|
if (highest_thread != nullptr) [[likely]] {
|
||||||
|
@ -351,7 +352,7 @@ void KScheduler::SwitchThread(KThread* next_thread) {
|
||||||
|
|
||||||
// Update the CPU time tracking variables.
|
// Update the CPU time tracking variables.
|
||||||
const s64 prev_tick = m_last_context_switch_time;
|
const s64 prev_tick = m_last_context_switch_time;
|
||||||
const s64 cur_tick = m_kernel.System().CoreTiming().GetCPUTicks();
|
const s64 cur_tick = m_kernel.System().CoreTiming().GetClockTicks();
|
||||||
const s64 tick_diff = cur_tick - prev_tick;
|
const s64 tick_diff = cur_tick - prev_tick;
|
||||||
cur_thread->AddCpuTime(m_core_id, tick_diff);
|
cur_thread->AddCpuTime(m_core_id, tick_diff);
|
||||||
if (cur_process != nullptr) {
|
if (cur_process != nullptr) {
|
||||||
|
|
|
@ -199,9 +199,9 @@ Result GetInfo(Core::System& system, u64* result, InfoType info_id_type, Handle
|
||||||
if (same_thread && info_sub_id == 0xFFFFFFFFFFFFFFFF) {
|
if (same_thread && info_sub_id == 0xFFFFFFFFFFFFFFFF) {
|
||||||
const u64 thread_ticks = current_thread->GetCpuTime();
|
const u64 thread_ticks = current_thread->GetCpuTime();
|
||||||
|
|
||||||
out_ticks = thread_ticks + (core_timing.GetCPUTicks() - prev_ctx_ticks);
|
out_ticks = thread_ticks + (core_timing.GetClockTicks() - prev_ctx_ticks);
|
||||||
} else if (same_thread && info_sub_id == system.Kernel().CurrentPhysicalCoreIndex()) {
|
} else if (same_thread && info_sub_id == system.Kernel().CurrentPhysicalCoreIndex()) {
|
||||||
out_ticks = core_timing.GetCPUTicks() - prev_ctx_ticks;
|
out_ticks = core_timing.GetClockTicks() - prev_ctx_ticks;
|
||||||
}
|
}
|
||||||
|
|
||||||
*result = out_ticks;
|
*result = out_ticks;
|
||||||
|
|
|
@ -5,7 +5,6 @@
|
||||||
#include "common/settings.h"
|
#include "common/settings.h"
|
||||||
#include "core/core.h"
|
#include "core/core.h"
|
||||||
#include "core/core_timing.h"
|
#include "core/core_timing.h"
|
||||||
#include "core/core_timing_util.h"
|
|
||||||
#include "core/hid/hid_types.h"
|
#include "core/hid/hid_types.h"
|
||||||
#include "core/hle/kernel/k_event.h"
|
#include "core/hle/kernel/k_event.h"
|
||||||
#include "core/hle/kernel/k_readable_event.h"
|
#include "core/hle/kernel/k_readable_event.h"
|
||||||
|
|
|
@ -194,17 +194,17 @@ struct GPU::Impl {
|
||||||
|
|
||||||
[[nodiscard]] u64 GetTicks() const {
|
[[nodiscard]] u64 GetTicks() const {
|
||||||
// This values were reversed engineered by fincs from NVN
|
// This values were reversed engineered by fincs from NVN
|
||||||
// The gpu clock is reported in units of 385/625 nanoseconds
|
// The GPU clock is 614.4 MHz
|
||||||
constexpr u64 gpu_ticks_num = 384;
|
using NsToGPUTickRatio = std::ratio<614'400'000, std::nano::den>;
|
||||||
constexpr u64 gpu_ticks_den = 625;
|
static_assert(NsToGPUTickRatio::num == 384 && NsToGPUTickRatio::den == 625);
|
||||||
|
|
||||||
|
u64 nanoseconds = system.CoreTiming().GetGlobalTimeNs().count();
|
||||||
|
|
||||||
u64 nanoseconds = system.CoreTiming().GetCPUTimeNs().count();
|
|
||||||
if (Settings::values.use_fast_gpu_time.GetValue()) {
|
if (Settings::values.use_fast_gpu_time.GetValue()) {
|
||||||
nanoseconds /= 256;
|
nanoseconds /= 256;
|
||||||
}
|
}
|
||||||
const u64 nanoseconds_num = nanoseconds / gpu_ticks_den;
|
|
||||||
const u64 nanoseconds_rem = nanoseconds % gpu_ticks_den;
|
return nanoseconds * NsToGPUTickRatio::num / NsToGPUTickRatio::den;
|
||||||
return nanoseconds_num * gpu_ticks_num + (nanoseconds_rem * gpu_ticks_num) / gpu_ticks_den;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[[nodiscard]] bool IsAsync() const {
|
[[nodiscard]] bool IsAsync() const {
|
||||||
|
|
Loading…
Reference in a new issue