Add performance statistics to status bar
This commit is contained in:
		
							parent
							
								
									21f4f49c7a
								
							
						
					
					
						commit
						c75ae6c585
					
				@ -253,6 +253,8 @@ void GMainWindow::ConnectWidgetEvents() {
 | 
			
		||||
    connect(this, SIGNAL(EmulationStarting(EmuThread*)), render_window,
 | 
			
		||||
            SLOT(OnEmulationStarting(EmuThread*)));
 | 
			
		||||
    connect(this, SIGNAL(EmulationStopping()), render_window, SLOT(OnEmulationStopping()));
 | 
			
		||||
 | 
			
		||||
    connect(&status_bar_update_timer, &QTimer::timeout, this, &GMainWindow::UpdateStatusBar);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GMainWindow::ConnectMenuEvents() {
 | 
			
		||||
@ -401,6 +403,8 @@ void GMainWindow::BootGame(const QString& filename) {
 | 
			
		||||
    if (ui.action_Single_Window_Mode->isChecked()) {
 | 
			
		||||
        game_list->hide();
 | 
			
		||||
    }
 | 
			
		||||
    status_bar_update_timer.start(1000);
 | 
			
		||||
 | 
			
		||||
    render_window->show();
 | 
			
		||||
    render_window->setFocus();
 | 
			
		||||
 | 
			
		||||
@ -435,6 +439,12 @@ void GMainWindow::ShutdownGame() {
 | 
			
		||||
    render_window->hide();
 | 
			
		||||
    game_list->show();
 | 
			
		||||
 | 
			
		||||
    // Disable status bar updates
 | 
			
		||||
    status_bar_update_timer.stop();
 | 
			
		||||
    emu_speed_label->setVisible(false);
 | 
			
		||||
    game_fps_label->setVisible(false);
 | 
			
		||||
    emu_frametime_label->setVisible(false);
 | 
			
		||||
 | 
			
		||||
    emulation_running = false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -614,6 +624,23 @@ void GMainWindow::OnCreateGraphicsSurfaceViewer() {
 | 
			
		||||
    graphicsSurfaceViewerWidget->show();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void GMainWindow::UpdateStatusBar() {
 | 
			
		||||
    if (emu_thread == nullptr) {
 | 
			
		||||
        status_bar_update_timer.stop();
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto results = Core::System::GetInstance().GetAndResetPerfStats();
 | 
			
		||||
 | 
			
		||||
    emu_speed_label->setText(tr("Speed: %1%").arg(results.emulation_speed * 100.0, 0, 'f', 2));
 | 
			
		||||
    game_fps_label->setText(tr("Game: %1 FPS").arg(results.game_fps, 0, 'f', 1));
 | 
			
		||||
    emu_frametime_label->setText(tr("Frame: %1 ms").arg(results.frametime * 1000.0, 0, 'f', 2));
 | 
			
		||||
 | 
			
		||||
    emu_speed_label->setVisible(true);
 | 
			
		||||
    game_fps_label->setVisible(true);
 | 
			
		||||
    emu_frametime_label->setVisible(true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool GMainWindow::ConfirmClose() {
 | 
			
		||||
    if (emu_thread == nullptr || !UISettings::values.confirm_before_closing)
 | 
			
		||||
        return true;
 | 
			
		||||
 | 
			
		||||
@ -127,6 +127,8 @@ private slots:
 | 
			
		||||
    void OnCreateGraphicsSurfaceViewer();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void UpdateStatusBar();
 | 
			
		||||
 | 
			
		||||
    Ui::MainWindow ui;
 | 
			
		||||
 | 
			
		||||
    GRenderWindow* render_window;
 | 
			
		||||
@ -136,6 +138,7 @@ private:
 | 
			
		||||
    QLabel* emu_speed_label = nullptr;
 | 
			
		||||
    QLabel* game_fps_label = nullptr;
 | 
			
		||||
    QLabel* emu_frametime_label = nullptr;
 | 
			
		||||
    QTimer status_bar_update_timer;
 | 
			
		||||
 | 
			
		||||
    std::unique_ptr<Config> config;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
            )
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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.
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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])).
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										53
									
								
								src/core/perf_stats.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/core/perf_stats.cpp
									
									
									
									
									
										Normal file
									
								
							@ -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
 | 
			
		||||
							
								
								
									
										43
									
								
								src/core/perf_stats.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/core/perf_stats.h
									
									
									
									
									
										Normal file
									
								
							@ -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
 | 
			
		||||
@ -12,6 +12,7 @@
 | 
			
		||||
#include "common/logging/log.h"
 | 
			
		||||
#include "common/profiler_reporting.h"
 | 
			
		||||
#include "common/synchronized_wrapper.h"
 | 
			
		||||
#include "core/core.h"
 | 
			
		||||
#include "core/frontend/emu_window.h"
 | 
			
		||||
#include "core/hw/gpu.h"
 | 
			
		||||
#include "core/hw/hw.h"
 | 
			
		||||
@ -151,6 +152,10 @@ void RendererOpenGL::SwapBuffers() {
 | 
			
		||||
        auto aggregator = Common::Profiling::GetTimingResultsAggregator();
 | 
			
		||||
        aggregator->AddFrame(profiler.GetPreviousFrameResults());
 | 
			
		||||
    }
 | 
			
		||||
    {
 | 
			
		||||
        auto perf_stats = Core::System::GetInstance().perf_stats.Lock();
 | 
			
		||||
        perf_stats->EndSystemFrame();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Swap buffers
 | 
			
		||||
    render_window->PollEvents();
 | 
			
		||||
@ -159,6 +164,10 @@ void RendererOpenGL::SwapBuffers() {
 | 
			
		||||
    prev_state.Apply();
 | 
			
		||||
 | 
			
		||||
    profiler.BeginFrame();
 | 
			
		||||
    {
 | 
			
		||||
        auto perf_stats = Core::System::GetInstance().perf_stats.Lock();
 | 
			
		||||
        perf_stats->BeginSystemFrame();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    RefreshRasterizerSetting();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user