diff --git a/README.md b/README.md index c02301dab..adbe8d7d7 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 3621. +This is the source code for early-access 3622. ## Legal Notice diff --git a/src/common/wall_clock.cpp b/src/common/wall_clock.cpp index b7bb3e2c4..a511a82bf 100755 --- a/src/common/wall_clock.cpp +++ b/src/common/wall_clock.cpp @@ -32,6 +32,10 @@ public: return GetHostTicksElapsed() * NsToCNTPCTRatio::num / NsToCNTPCTRatio::den; } + u64 GetGPUTick() const override { + return GetHostTicksElapsed() * NsToGPUTickRatio::num / NsToGPUTickRatio::den; + } + u64 GetHostTicksNow() const override { return static_cast(SteadyClock::Now().time_since_epoch().count()); } @@ -52,12 +56,12 @@ std::unique_ptr CreateOptimalClock() { #ifdef ARCHITECTURE_x86_64 const auto& caps = GetCPUCaps(); - if (caps.invariant_tsc && caps.tsc_frequency >= WallClock::CNTFRQ) { + if (caps.invariant_tsc && caps.tsc_frequency >= WallClock::GPUTickFreq) { return std::make_unique(caps.tsc_frequency); } else { // Fallback to StandardWallClock if the hardware TSC // - Is not invariant - // - Is not more precise than CNTFRQ + // - Is not more precise than GPUTickFreq return std::make_unique(); } #else diff --git a/src/common/wall_clock.h b/src/common/wall_clock.h index 6ed085f4d..8395ea231 100755 --- a/src/common/wall_clock.h +++ b/src/common/wall_clock.h @@ -13,7 +13,8 @@ namespace Common { class WallClock { public: - static constexpr u64 CNTFRQ = 19'200'000; // CNTPCT_EL0 Frequency = 19.2 MHz + static constexpr u64 CNTFRQ = 19'200'000; // CNTPCT_EL0 Frequency = 19.2 MHz + static constexpr u64 GPUTickFreq = 614'400'000; // GM20B GPU Tick Frequency = 614.4 MHz virtual ~WallClock() = default; @@ -29,6 +30,9 @@ public: /// @returns The guest CNTPCT ticks since the construction of this clock. virtual u64 GetCNTPCT() const = 0; + /// @returns The guest GPU ticks since the construction of this clock. + virtual u64 GetGPUTick() const = 0; + /// @returns The raw host timer ticks since an indeterminate epoch. virtual u64 GetHostTicksNow() const = 0; @@ -46,6 +50,10 @@ public: return us * UsToCNTPCTRatio::num / UsToCNTPCTRatio::den; } + static inline u64 NSToGPUTick(u64 ns) { + return ns * NsToGPUTickRatio::num / NsToGPUTickRatio::den; + } + static inline u64 CNTPCTToNS(u64 cntpct) { return cntpct * NsToCNTPCTRatio::den / NsToCNTPCTRatio::num; } @@ -54,6 +62,14 @@ public: return cntpct * UsToCNTPCTRatio::den / UsToCNTPCTRatio::num; } + static inline u64 GPUTickToNS(u64 gpu_tick) { + return gpu_tick * NsToGPUTickRatio::den / NsToGPUTickRatio::num; + } + + static inline u64 CNTPCTToGPUTick(u64 cntpct) { + return cntpct * CNTPCTToGPUTickRatio::num / CNTPCTToGPUTickRatio::den; + } + protected: using NsRatio = std::nano; using UsRatio = std::micro; @@ -63,6 +79,8 @@ protected: using NsToMsRatio = std::ratio_divide; using NsToCNTPCTRatio = std::ratio; using UsToCNTPCTRatio = std::ratio; + using NsToGPUTickRatio = std::ratio; + using CNTPCTToGPUTickRatio = std::ratio; }; std::unique_ptr CreateOptimalClock(); diff --git a/src/common/x64/native_clock.cpp b/src/common/x64/native_clock.cpp index a90a1faed..9fbe75bd1 100755 --- a/src/common/x64/native_clock.cpp +++ b/src/common/x64/native_clock.cpp @@ -12,7 +12,8 @@ NativeClock::NativeClock(u64 rdtsc_frequency_) ns_rdtsc_factor{GetFixedPoint64Factor(NsRatio::den, rdtsc_frequency)}, us_rdtsc_factor{GetFixedPoint64Factor(UsRatio::den, rdtsc_frequency)}, ms_rdtsc_factor{GetFixedPoint64Factor(MsRatio::den, rdtsc_frequency)}, - cntpct_rdtsc_factor{GetFixedPoint64Factor(CNTFRQ, rdtsc_frequency)} {} + cntpct_rdtsc_factor{GetFixedPoint64Factor(CNTFRQ, rdtsc_frequency)}, + gputick_rdtsc_factor{GetFixedPoint64Factor(GPUTickFreq, rdtsc_frequency)} {} std::chrono::nanoseconds NativeClock::GetTimeNS() const { return std::chrono::nanoseconds{MultiplyHigh(GetHostTicksElapsed(), ns_rdtsc_factor)}; @@ -30,6 +31,10 @@ u64 NativeClock::GetCNTPCT() const { return MultiplyHigh(GetHostTicksElapsed(), cntpct_rdtsc_factor); } +u64 NativeClock::GetGPUTick() const { + return MultiplyHigh(GetHostTicksElapsed(), gputick_rdtsc_factor); +} + u64 NativeClock::GetHostTicksNow() const { return FencedRDTSC(); } diff --git a/src/common/x64/native_clock.h b/src/common/x64/native_clock.h index 3b487d442..925d3928c 100755 --- a/src/common/x64/native_clock.h +++ b/src/common/x64/native_clock.h @@ -19,6 +19,8 @@ public: u64 GetCNTPCT() const override; + u64 GetGPUTick() const override; + u64 GetHostTicksNow() const override; u64 GetHostTicksElapsed() const override; @@ -33,6 +35,7 @@ private: u64 us_rdtsc_factor; u64 ms_rdtsc_factor; u64 cntpct_rdtsc_factor; + u64 gputick_rdtsc_factor; }; } // namespace Common::X64 diff --git a/src/core/core_timing.cpp b/src/core/core_timing.cpp index b65f52f93..3c0dd9348 100755 --- a/src/core/core_timing.cpp +++ b/src/core/core_timing.cpp @@ -197,6 +197,13 @@ u64 CoreTiming::GetClockTicks() const { return ticks; } +u64 CoreTiming::GetGPUTicks() const { + if (is_multicore) [[likely]] { + return clock->GetGPUTick(); + } + return Common::WallClock::CNTPCTToGPUTick(ticks); +} + std::optional CoreTiming::Advance() { std::scoped_lock lock{advance_lock, basic_lock}; global_timer = GetGlobalTimeNs().count(); diff --git a/src/core/core_timing.h b/src/core/core_timing.h index 5ce1f0ff1..ae9b858fd 100755 --- a/src/core/core_timing.h +++ b/src/core/core_timing.h @@ -119,6 +119,9 @@ public: /// Returns the current CNTPCT tick value. u64 GetClockTicks() const; + /// Returns the current GPU tick value. + u64 GetGPUTicks() const; + /// Returns current time in microseconds. std::chrono::microseconds GetGlobalTimeUs() const; diff --git a/src/input_common/helpers/joycon_protocol/nfc.cpp b/src/input_common/helpers/joycon_protocol/nfc.cpp index 3b7a628e5..f7058c4a7 100755 --- a/src/input_common/helpers/joycon_protocol/nfc.cpp +++ b/src/input_common/helpers/joycon_protocol/nfc.cpp @@ -528,9 +528,9 @@ NFCWritePackage NfcProtocol::MakeAmiiboWritePackage(const TagUUID& tag_uuid, } NFCDataChunk NfcProtocol::MakeAmiiboChunk(u8 page, u8 size, std::span data) const { - constexpr u8 PAGE_SIZE = 4; + constexpr u8 NFC_PAGE_SIZE = 4; - if (static_cast(page * PAGE_SIZE) + size >= data.size()) { + if (static_cast(page * NFC_PAGE_SIZE) + size >= data.size()) { return {}; } @@ -539,7 +539,7 @@ NFCDataChunk NfcProtocol::MakeAmiiboChunk(u8 page, u8 size, std::span .data_size = size, .data = {}, }; - std::memcpy(chunk.data.data(), data.data() + (page * PAGE_SIZE), size); + std::memcpy(chunk.data.data(), data.data() + (page * NFC_PAGE_SIZE), size); return chunk; } diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 3ab20e4d2..d59917463 100755 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp @@ -192,18 +192,13 @@ struct GPU::Impl { } [[nodiscard]] u64 GetTicks() const { - // This values were reversed engineered by fincs from NVN - // The GPU clock is 614.4 MHz - using NsToGPUTickRatio = std::ratio<614'400'000, std::nano::den>; - static_assert(NsToGPUTickRatio::num == 384 && NsToGPUTickRatio::den == 625); - - u64 nanoseconds = system.CoreTiming().GetGlobalTimeNs().count(); + u64 gpu_tick = system.CoreTiming().GetGPUTicks(); if (Settings::values.use_fast_gpu_time.GetValue()) { - nanoseconds /= 256; + gpu_tick /= 256; } - return nanoseconds * NsToGPUTickRatio::num / NsToGPUTickRatio::den; + return gpu_tick; } [[nodiscard]] bool IsAsync() const {