summaryrefslogtreecommitdiffstats
path: root/src/core
diff options
context:
space:
mode:
authorYuri Kunde Schlesner <yuriks@yuriks.net>2017-02-19 23:34:47 +0100
committerYuri Kunde Schlesner <yuriks@yuriks.net>2017-02-27 02:22:03 +0100
commitc75ae6c585f651a1b7c162c2e1ecccd22a1c587d (patch)
tree30d51f39c6b57244e1ede29820c3f5d98ca38451 /src/core
parentSynchronizedWrapper: Add Lock convenience method (diff)
downloadyuzu-c75ae6c585f651a1b7c162c2e1ecccd22a1c587d.tar
yuzu-c75ae6c585f651a1b7c162c2e1ecccd22a1c587d.tar.gz
yuzu-c75ae6c585f651a1b7c162c2e1ecccd22a1c587d.tar.bz2
yuzu-c75ae6c585f651a1b7c162c2e1ecccd22a1c587d.tar.lz
yuzu-c75ae6c585f651a1b7c162c2e1ecccd22a1c587d.tar.xz
yuzu-c75ae6c585f651a1b7c162c2e1ecccd22a1c587d.tar.zst
yuzu-c75ae6c585f651a1b7c162c2e1ecccd22a1c587d.zip
Diffstat (limited to 'src/core')
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/core.cpp9
-rw-r--r--src/core/core.h7
-rw-r--r--src/core/hle/service/gsp_gpu.cpp3
-rw-r--r--src/core/hw/gpu.cpp4
-rw-r--r--src/core/hw/gpu.h2
-rw-r--r--src/core/perf_stats.cpp53
-rw-r--r--src/core/perf_stats.h43
8 files changed, 120 insertions, 3 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 5332e35a3..1adc78d8d 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -170,6 +170,7 @@ set(SRCS
loader/smdh.cpp
tracer/recorder.cpp
memory.cpp
+ perf_stats.cpp
settings.cpp
)
@@ -357,6 +358,7 @@ set(HEADERS
memory.h
memory_setup.h
mmio.h
+ perf_stats.h
settings.h
)
diff --git a/src/core/core.cpp b/src/core/core.cpp
index c9c9b7615..ca2c28ce4 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -109,6 +109,11 @@ void System::PrepareReschedule() {
reschedule_pending = true;
}
+PerfStats::Results System::GetAndResetPerfStats() {
+ auto perf_stats = this->perf_stats.Lock();
+ return perf_stats->GetAndResetStats(CoreTiming::GetGlobalTimeUs());
+}
+
void System::Reschedule() {
if (!reschedule_pending) {
return;
@@ -140,6 +145,10 @@ System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
LOG_DEBUG(Core, "Initialized OK");
+ // Reset counters and set time origin to current frame
+ GetAndResetPerfStats();
+ perf_stats.Lock()->BeginSystemFrame();
+
return ResultStatus::Success;
}
diff --git a/src/core/core.h b/src/core/core.h
index 17572a74f..3efc20c3d 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -6,9 +6,10 @@
#include <memory>
#include <string>
-
#include "common/common_types.h"
+#include "common/synchronized_wrapper.h"
#include "core/memory.h"
+#include "core/perf_stats.h"
class EmuWindow;
class ARM_Interface;
@@ -83,6 +84,8 @@ public:
/// Prepare the core emulation for a reschedule
void PrepareReschedule();
+ PerfStats::Results GetAndResetPerfStats();
+
/**
* Gets a reference to the emulated CPU.
* @returns A reference to the emulated CPU.
@@ -91,6 +94,8 @@ public:
return *cpu_core;
}
+ Common::SynchronizedWrapper<PerfStats> perf_stats;
+
private:
/**
* Initialize the emulated system.
diff --git a/src/core/hle/service/gsp_gpu.cpp b/src/core/hle/service/gsp_gpu.cpp
index 1457518d4..67bab38da 100644
--- a/src/core/hle/service/gsp_gpu.cpp
+++ b/src/core/hle/service/gsp_gpu.cpp
@@ -4,6 +4,7 @@
#include "common/bit_field.h"
#include "common/microprofile.h"
+#include "core/core.h"
#include "core/hle/kernel/event.h"
#include "core/hle/kernel/shared_memory.h"
#include "core/hle/result.h"
@@ -280,6 +281,8 @@ ResultCode SetBufferSwap(u32 screen_id, const FrameBufferInfo& info) {
if (screen_id == 0) {
MicroProfileFlip();
+ auto perf_stats = Core::System::GetInstance().perf_stats.Lock();
+ perf_stats->EndGameFrame();
}
return RESULT_SUCCESS;
diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp
index fa8c13d36..7cf081aad 100644
--- a/src/core/hw/gpu.cpp
+++ b/src/core/hw/gpu.cpp
@@ -32,7 +32,7 @@ namespace GPU {
Regs g_regs;
/// 268MHz CPU clocks / 60Hz frames per second
-const u64 frame_ticks = BASE_CLOCK_RATE_ARM11 / 60;
+const u64 frame_ticks = BASE_CLOCK_RATE_ARM11 / SCREEN_REFRESH_RATE;
/// Event id for CoreTiming
static int vblank_event;
/// Total number of frames drawn
@@ -41,7 +41,7 @@ static u64 frame_count;
static u32 time_point;
/// Total delay caused by slow frames
static float time_delay;
-constexpr float FIXED_FRAME_TIME = 1000.0f / 60;
+constexpr float FIXED_FRAME_TIME = 1000.0f / SCREEN_REFRESH_RATE;
// Max lag caused by slow frames. Can be adjusted to compensate for too many slow frames. Higher
// values increases time needed to limit frame rate after spikes
constexpr float MAX_LAG_TIME = 18;
diff --git a/src/core/hw/gpu.h b/src/core/hw/gpu.h
index d53381216..bdd997b2a 100644
--- a/src/core/hw/gpu.h
+++ b/src/core/hw/gpu.h
@@ -13,6 +13,8 @@
namespace GPU {
+constexpr float SCREEN_REFRESH_RATE = 60;
+
// Returns index corresponding to the Regs member labeled by field_name
// TODO: Due to Visual studio bug 209229, offsetof does not return constant expressions
// when used with array elements (e.g. GPU_REG_INDEX(memory_fill_config[0])).
diff --git a/src/core/perf_stats.cpp b/src/core/perf_stats.cpp
new file mode 100644
index 000000000..6d9e603e4
--- /dev/null
+++ b/src/core/perf_stats.cpp
@@ -0,0 +1,53 @@
+// Copyright 2017 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <chrono>
+#include "core/hw/gpu.h"
+#include "core/perf_stats.h"
+
+namespace Core {
+
+void PerfStats::BeginSystemFrame() {
+ frame_begin = Clock::now();
+}
+
+void PerfStats::EndSystemFrame() {
+ auto frame_end = Clock::now();
+ accumulated_frametime += frame_end - frame_begin;
+ system_frames += 1;
+}
+
+void PerfStats::EndGameFrame() {
+ game_frames += 1;
+}
+
+PerfStats::Results PerfStats::GetAndResetStats(u64 current_system_time_us) {
+ using DoubleSecs = std::chrono::duration<double, std::chrono::seconds::period>;
+ using std::chrono::duration_cast;
+
+ auto now = Clock::now();
+ // Walltime elapsed since stats were reset
+ auto interval = duration_cast<DoubleSecs>(now - reset_point).count();
+
+ auto system_us_per_second =
+ static_cast<double>(current_system_time_us - reset_point_system_us) / interval;
+
+ Results results{};
+ results.system_fps = static_cast<double>(system_frames) / interval;
+ results.game_fps = static_cast<double>(game_frames) / interval;
+ results.frametime = duration_cast<DoubleSecs>(accumulated_frametime).count() /
+ static_cast<double>(system_frames);
+ results.emulation_speed = system_us_per_second / 1'000'000.0;
+
+ // Reset counters
+ reset_point = now;
+ reset_point_system_us = current_system_time_us;
+ accumulated_frametime = Clock::duration::zero();
+ system_frames = 0;
+ game_frames = 0;
+
+ return results;
+}
+
+} // namespace Core
diff --git a/src/core/perf_stats.h b/src/core/perf_stats.h
new file mode 100644
index 000000000..566a1419a
--- /dev/null
+++ b/src/core/perf_stats.h
@@ -0,0 +1,43 @@
+// Copyright 2017 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include <chrono>
+#include "common/common_types.h"
+
+namespace Core {
+
+class PerfStats {
+public:
+ using Clock = std::chrono::high_resolution_clock;
+
+ struct Results {
+ /// System FPS (LCD VBlanks) in Hz
+ double system_fps;
+ /// Game FPS (GSP frame submissions) in Hz
+ double game_fps;
+ /// Walltime per system frame, in seconds, excluding any waits
+ double frametime;
+ /// Ratio of walltime / emulated time elapsed
+ double emulation_speed;
+ };
+
+ void BeginSystemFrame();
+ void EndSystemFrame();
+ void EndGameFrame();
+
+ Results GetAndResetStats(u64 current_system_time_us);
+
+private:
+ Clock::time_point reset_point = Clock::now();
+
+ Clock::time_point frame_begin;
+ Clock::duration accumulated_frametime = Clock::duration::zero();
+ u64 reset_point_system_us = 0;
+ u32 system_frames = 0;
+ u32 game_frames = 0;
+};
+
+} // namespace Core