System: Move perf counters to separate namespace
This commit is contained in:
parent
875ccecb90
commit
21d19a6297
|
@ -102,6 +102,8 @@ add_library(core
|
||||||
pad.h
|
pad.h
|
||||||
pcdrv.cpp
|
pcdrv.cpp
|
||||||
pcdrv.h
|
pcdrv.h
|
||||||
|
performance_counters.cpp
|
||||||
|
performance_counters.h
|
||||||
playstation_mouse.cpp
|
playstation_mouse.cpp
|
||||||
playstation_mouse.h
|
playstation_mouse.h
|
||||||
psf_loader.cpp
|
psf_loader.cpp
|
||||||
|
|
|
@ -79,6 +79,7 @@
|
||||||
<PrecompiledHeader>Create</PrecompiledHeader>
|
<PrecompiledHeader>Create</PrecompiledHeader>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="cpu_pgxp.cpp" />
|
<ClCompile Include="cpu_pgxp.cpp" />
|
||||||
|
<ClCompile Include="performance_counters.cpp" />
|
||||||
<ClCompile Include="playstation_mouse.cpp" />
|
<ClCompile Include="playstation_mouse.cpp" />
|
||||||
<ClCompile Include="psf_loader.cpp" />
|
<ClCompile Include="psf_loader.cpp" />
|
||||||
<ClCompile Include="settings.cpp" />
|
<ClCompile Include="settings.cpp" />
|
||||||
|
@ -160,6 +161,7 @@
|
||||||
<ClInclude Include="pcdrv.h" />
|
<ClInclude Include="pcdrv.h" />
|
||||||
<ClInclude Include="pch.h" />
|
<ClInclude Include="pch.h" />
|
||||||
<ClInclude Include="cpu_pgxp.h" />
|
<ClInclude Include="cpu_pgxp.h" />
|
||||||
|
<ClInclude Include="performance_counters.h" />
|
||||||
<ClInclude Include="playstation_mouse.h" />
|
<ClInclude Include="playstation_mouse.h" />
|
||||||
<ClInclude Include="psf_loader.h" />
|
<ClInclude Include="psf_loader.h" />
|
||||||
<ClInclude Include="save_state_version.h" />
|
<ClInclude Include="save_state_version.h" />
|
||||||
|
|
|
@ -70,6 +70,7 @@
|
||||||
<ClCompile Include="memory_scanner.cpp" />
|
<ClCompile Include="memory_scanner.cpp" />
|
||||||
<ClCompile Include="gpu_dump.cpp" />
|
<ClCompile Include="gpu_dump.cpp" />
|
||||||
<ClCompile Include="cdrom_subq_replacement.cpp" />
|
<ClCompile Include="cdrom_subq_replacement.cpp" />
|
||||||
|
<ClCompile Include="performance_counters.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="types.h" />
|
<ClInclude Include="types.h" />
|
||||||
|
@ -146,6 +147,7 @@
|
||||||
<ClInclude Include="memory_scanner.h" />
|
<ClInclude Include="memory_scanner.h" />
|
||||||
<ClInclude Include="gpu_dump.h" />
|
<ClInclude Include="gpu_dump.h" />
|
||||||
<ClInclude Include="cdrom_subq_replacement.h" />
|
<ClInclude Include="cdrom_subq_replacement.h" />
|
||||||
|
<ClInclude Include="performance_counters.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="gpu_sw_rasterizer.inl" />
|
<None Include="gpu_sw_rasterizer.inl" />
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "gpu_sw_rasterizer.h"
|
#include "gpu_sw_rasterizer.h"
|
||||||
#include "host.h"
|
#include "host.h"
|
||||||
#include "interrupt_controller.h"
|
#include "interrupt_controller.h"
|
||||||
|
#include "performance_counters.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
#include "timers.h"
|
#include "timers.h"
|
||||||
|
@ -146,10 +147,10 @@ void GPU::UpdateSettings(const Settings& old_settings)
|
||||||
if (g_settings.display_deinterlacing_mode != old_settings.display_deinterlacing_mode)
|
if (g_settings.display_deinterlacing_mode != old_settings.display_deinterlacing_mode)
|
||||||
DestroyDeinterlaceTextures();
|
DestroyDeinterlaceTextures();
|
||||||
|
|
||||||
if (!CompileDisplayPipelines(g_settings.display_scaling != old_settings.display_scaling,
|
if (!CompileDisplayPipelines(
|
||||||
g_settings.display_deinterlacing_mode != old_settings.display_deinterlacing_mode,
|
g_settings.display_scaling != old_settings.display_scaling,
|
||||||
g_settings.display_24bit_chroma_smoothing !=
|
g_settings.display_deinterlacing_mode != old_settings.display_deinterlacing_mode,
|
||||||
old_settings.display_24bit_chroma_smoothing, nullptr))
|
g_settings.display_24bit_chroma_smoothing != old_settings.display_24bit_chroma_smoothing, nullptr))
|
||||||
{
|
{
|
||||||
Panic("Failed to compile display pipeline on settings change.");
|
Panic("Failed to compile display pipeline on settings change.");
|
||||||
}
|
}
|
||||||
|
@ -707,7 +708,7 @@ void GPU::UpdateCRTCConfig()
|
||||||
|
|
||||||
cs.current_scanline %= cs.vertical_total;
|
cs.current_scanline %= cs.vertical_total;
|
||||||
|
|
||||||
System::SetThrottleFrequency(ComputeVerticalFrequency());
|
System::SetVideoFrameRate(ComputeVerticalFrequency());
|
||||||
|
|
||||||
UpdateCRTCDisplayParameters();
|
UpdateCRTCDisplayParameters();
|
||||||
UpdateCRTCTickEvent();
|
UpdateCRTCTickEvent();
|
||||||
|
@ -2915,8 +2916,9 @@ bool GPU::StartRecordingGPUDump(const char* path, u32 num_frames /* = 1 */)
|
||||||
// +1 because we want to actually see the buffer swap...
|
// +1 because we want to actually see the buffer swap...
|
||||||
if (num_frames != 0)
|
if (num_frames != 0)
|
||||||
{
|
{
|
||||||
num_frames = std::max(num_frames, static_cast<u32>(static_cast<float>(num_frames + 1) *
|
num_frames =
|
||||||
std::ceil(System::GetVPS() / System::GetFPS())));
|
std::max(num_frames, static_cast<u32>(static_cast<float>(num_frames + 1) *
|
||||||
|
std::ceil(PerformanceCounters::GetVPS() / PerformanceCounters::GetFPS())));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure vram is up to date
|
// ensure vram is up to date
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
#include "gpu.h"
|
#include "gpu.h"
|
||||||
#include "host.h"
|
#include "host.h"
|
||||||
#include "mdec.h"
|
#include "mdec.h"
|
||||||
|
#include "performance_counters.h"
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "spu.h"
|
#include "spu.h"
|
||||||
#include "system.h"
|
#include "system.h"
|
||||||
|
@ -346,9 +347,9 @@ void ImGuiManager::DrawPerformanceOverlay(float& position_y, float scale, float
|
||||||
const System::State state = System::GetState();
|
const System::State state = System::GetState();
|
||||||
if (state == System::State::Running)
|
if (state == System::State::Running)
|
||||||
{
|
{
|
||||||
const float speed = System::GetEmulationSpeed();
|
const float speed = PerformanceCounters::GetEmulationSpeed();
|
||||||
if (g_settings.display_show_fps)
|
if (g_settings.display_show_fps)
|
||||||
text.append_format("G: {:.2f} | V: {:.2f}", System::GetFPS(), System::GetVPS());
|
text.append_format("G: {:.2f} | V: {:.2f}", PerformanceCounters::GetFPS(), PerformanceCounters::GetVPS());
|
||||||
if (g_settings.display_show_speed)
|
if (g_settings.display_show_speed)
|
||||||
{
|
{
|
||||||
text.append_format("{}{}%", text.empty() ? "" : " | ", static_cast<u32>(std::round(speed)));
|
text.append_format("{}{}%", text.empty() ? "" : " | ", static_cast<u32>(std::round(speed)));
|
||||||
|
@ -400,8 +401,8 @@ void ImGuiManager::DrawPerformanceOverlay(float& position_y, float scale, float
|
||||||
|
|
||||||
if (g_settings.display_show_cpu_usage)
|
if (g_settings.display_show_cpu_usage)
|
||||||
{
|
{
|
||||||
text.format("{:.2f}ms | {:.2f}ms | {:.2f}ms", System::GetMinimumFrameTime(), System::GetAverageFrameTime(),
|
text.format("{:.2f}ms | {:.2f}ms | {:.2f}ms", PerformanceCounters::GetMinimumFrameTime(),
|
||||||
System::GetMaximumFrameTime());
|
PerformanceCounters::GetAverageFrameTime(), PerformanceCounters::GetMaximumFrameTime());
|
||||||
DRAW_LINE(fixed_font, text, IM_COL32(255, 255, 255, 255));
|
DRAW_LINE(fixed_font, text, IM_COL32(255, 255, 255, 255));
|
||||||
|
|
||||||
if (g_settings.cpu_overclock_active || CPU::g_state.using_interpreter ||
|
if (g_settings.cpu_overclock_active || CPU::g_state.using_interpreter ||
|
||||||
|
@ -450,13 +451,15 @@ void ImGuiManager::DrawPerformanceOverlay(float& position_y, float scale, float
|
||||||
{
|
{
|
||||||
text.assign("CPU: ");
|
text.assign("CPU: ");
|
||||||
}
|
}
|
||||||
FormatProcessorStat(text, System::GetCPUThreadUsage(), System::GetCPUThreadAverageTime());
|
FormatProcessorStat(text, PerformanceCounters::GetCPUThreadUsage(),
|
||||||
|
PerformanceCounters::GetCPUThreadAverageTime());
|
||||||
DRAW_LINE(fixed_font, text, IM_COL32(255, 255, 255, 255));
|
DRAW_LINE(fixed_font, text, IM_COL32(255, 255, 255, 255));
|
||||||
|
|
||||||
if (g_gpu->GetSWThread())
|
if (g_gpu->GetSWThread())
|
||||||
{
|
{
|
||||||
text.assign("SW: ");
|
text.assign("SW: ");
|
||||||
FormatProcessorStat(text, System::GetSWThreadUsage(), System::GetSWThreadAverageTime());
|
FormatProcessorStat(text, PerformanceCounters::GetSWThreadUsage(),
|
||||||
|
PerformanceCounters::GetSWThreadAverageTime());
|
||||||
DRAW_LINE(fixed_font, text, IM_COL32(255, 255, 255, 255));
|
DRAW_LINE(fixed_font, text, IM_COL32(255, 255, 255, 255));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -473,7 +476,7 @@ void ImGuiManager::DrawPerformanceOverlay(float& position_y, float scale, float
|
||||||
if (g_settings.display_show_gpu_usage && g_gpu_device->IsGPUTimingEnabled())
|
if (g_settings.display_show_gpu_usage && g_gpu_device->IsGPUTimingEnabled())
|
||||||
{
|
{
|
||||||
text.assign("GPU: ");
|
text.assign("GPU: ");
|
||||||
FormatProcessorStat(text, System::GetGPUUsage(), System::GetGPUAverageTime());
|
FormatProcessorStat(text, PerformanceCounters::GetGPUUsage(), PerformanceCounters::GetGPUAverageTime());
|
||||||
DRAW_LINE(fixed_font, text, IM_COL32(255, 255, 255, 255));
|
DRAW_LINE(fixed_font, text, IM_COL32(255, 255, 255, 255));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -645,7 +648,7 @@ void ImGuiManager::DrawFrameTimeOverlay(float& position_y, float scale, float ma
|
||||||
{
|
{
|
||||||
ImGui::PushFont(fixed_font);
|
ImGui::PushFont(fixed_font);
|
||||||
|
|
||||||
auto [min, max] = GetMinMax(System::GetFrameTimeHistory());
|
auto [min, max] = GetMinMax(PerformanceCounters::GetFrameTimeHistory());
|
||||||
|
|
||||||
// add a little bit of space either side, so we're not constantly resizing
|
// add a little bit of space either side, so we're not constantly resizing
|
||||||
if ((max - min) < 4.0f)
|
if ((max - min) < 4.0f)
|
||||||
|
@ -659,10 +662,10 @@ void ImGuiManager::DrawFrameTimeOverlay(float& position_y, float scale, float ma
|
||||||
ImGui::PlotEx(
|
ImGui::PlotEx(
|
||||||
ImGuiPlotType_Lines, "##frame_times",
|
ImGuiPlotType_Lines, "##frame_times",
|
||||||
[](void*, int idx) -> float {
|
[](void*, int idx) -> float {
|
||||||
return System::GetFrameTimeHistory()[((System::GetFrameTimeHistoryPos() + idx) %
|
return PerformanceCounters::GetFrameTimeHistory()[((PerformanceCounters::GetFrameTimeHistoryPos() + idx) %
|
||||||
System::NUM_FRAME_TIME_SAMPLES)];
|
PerformanceCounters::NUM_FRAME_TIME_SAMPLES)];
|
||||||
},
|
},
|
||||||
nullptr, System::NUM_FRAME_TIME_SAMPLES, 0, nullptr, min, max, history_size);
|
nullptr, PerformanceCounters::NUM_FRAME_TIME_SAMPLES, 0, nullptr, min, max, history_size);
|
||||||
|
|
||||||
ImDrawList* win_dl = ImGui::GetCurrentWindow()->DrawList;
|
ImDrawList* win_dl = ImGui::GetCurrentWindow()->DrawList;
|
||||||
const ImVec2 wpos(ImGui::GetCurrentWindow()->Pos);
|
const ImVec2 wpos(ImGui::GetCurrentWindow()->Pos);
|
||||||
|
|
|
@ -0,0 +1,243 @@
|
||||||
|
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||||
|
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
|
||||||
|
|
||||||
|
#include "performance_counters.h"
|
||||||
|
#include "gpu.h"
|
||||||
|
#include "system.h"
|
||||||
|
|
||||||
|
#include "util/media_capture.h"
|
||||||
|
|
||||||
|
#include "common/log.h"
|
||||||
|
#include "common/threading.h"
|
||||||
|
#include "common/timer.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
LOG_CHANNEL(PerfMon);
|
||||||
|
|
||||||
|
namespace PerformanceCounters {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
struct State
|
||||||
|
{
|
||||||
|
Common::Timer::Value last_update_time;
|
||||||
|
Common::Timer::Value last_frame_time;
|
||||||
|
|
||||||
|
u32 last_frame_number;
|
||||||
|
u32 last_internal_frame_number;
|
||||||
|
u32 presents_since_last_update;
|
||||||
|
|
||||||
|
float average_frame_time_accumulator;
|
||||||
|
float minimum_frame_time_accumulator;
|
||||||
|
float maximum_frame_time_accumulator;
|
||||||
|
|
||||||
|
float vps;
|
||||||
|
float fps;
|
||||||
|
float speed;
|
||||||
|
|
||||||
|
float minimum_frame_time;
|
||||||
|
float maximum_frame_time;
|
||||||
|
float average_frame_time;
|
||||||
|
|
||||||
|
u64 last_cpu_time;
|
||||||
|
float cpu_thread_usage;
|
||||||
|
float cpu_thread_time;
|
||||||
|
|
||||||
|
u64 last_sw_time;
|
||||||
|
float sw_thread_usage;
|
||||||
|
float sw_thread_time;
|
||||||
|
|
||||||
|
float average_gpu_time;
|
||||||
|
float accumulated_gpu_time;
|
||||||
|
float gpu_usage;
|
||||||
|
|
||||||
|
FrameTimeHistory frame_time_history;
|
||||||
|
u32 frame_time_history_pos;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
static constexpr const float PERFORMANCE_COUNTER_UPDATE_INTERVAL = 1.0f;
|
||||||
|
|
||||||
|
ALIGN_TO_CACHE_LINE State s_state = {};
|
||||||
|
|
||||||
|
} // namespace PerformanceCounters
|
||||||
|
|
||||||
|
float PerformanceCounters::GetFPS()
|
||||||
|
{
|
||||||
|
return s_state.fps;
|
||||||
|
}
|
||||||
|
|
||||||
|
float PerformanceCounters::GetVPS()
|
||||||
|
{
|
||||||
|
return s_state.vps;
|
||||||
|
}
|
||||||
|
|
||||||
|
float PerformanceCounters::GetEmulationSpeed()
|
||||||
|
{
|
||||||
|
return s_state.speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
float PerformanceCounters::GetAverageFrameTime()
|
||||||
|
{
|
||||||
|
return s_state.average_frame_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
float PerformanceCounters::GetMinimumFrameTime()
|
||||||
|
{
|
||||||
|
return s_state.minimum_frame_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
float PerformanceCounters::GetMaximumFrameTime()
|
||||||
|
{
|
||||||
|
return s_state.maximum_frame_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
float PerformanceCounters::GetCPUThreadUsage()
|
||||||
|
{
|
||||||
|
return s_state.cpu_thread_usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
float PerformanceCounters::GetCPUThreadAverageTime()
|
||||||
|
{
|
||||||
|
return s_state.cpu_thread_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
float PerformanceCounters::GetSWThreadUsage()
|
||||||
|
{
|
||||||
|
return s_state.sw_thread_usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
float PerformanceCounters::GetSWThreadAverageTime()
|
||||||
|
{
|
||||||
|
return s_state.sw_thread_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
float PerformanceCounters::GetGPUUsage()
|
||||||
|
{
|
||||||
|
return s_state.gpu_usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
float PerformanceCounters::GetGPUAverageTime()
|
||||||
|
{
|
||||||
|
return s_state.average_gpu_time;
|
||||||
|
}
|
||||||
|
|
||||||
|
const PerformanceCounters::FrameTimeHistory& PerformanceCounters::GetFrameTimeHistory()
|
||||||
|
{
|
||||||
|
return s_state.frame_time_history;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 PerformanceCounters::GetFrameTimeHistoryPos()
|
||||||
|
{
|
||||||
|
return s_state.frame_time_history_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PerformanceCounters::Clear()
|
||||||
|
{
|
||||||
|
s_state = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void PerformanceCounters::Reset()
|
||||||
|
{
|
||||||
|
const Common::Timer::Value now_ticks = Common::Timer::GetCurrentValue();
|
||||||
|
|
||||||
|
s_state.last_frame_time = now_ticks;
|
||||||
|
s_state.last_update_time = now_ticks;
|
||||||
|
|
||||||
|
s_state.last_frame_number = System::GetFrameNumber();
|
||||||
|
s_state.last_internal_frame_number = System::GetInternalFrameNumber();
|
||||||
|
s_state.last_cpu_time = System::Internal::GetCPUThreadHandle().GetCPUTime();
|
||||||
|
if (const Threading::Thread* sw_thread = g_gpu->GetSWThread(); sw_thread)
|
||||||
|
s_state.last_sw_time = sw_thread->GetCPUTime();
|
||||||
|
else
|
||||||
|
s_state.last_sw_time = 0;
|
||||||
|
|
||||||
|
s_state.average_frame_time_accumulator = 0.0f;
|
||||||
|
s_state.minimum_frame_time_accumulator = 0.0f;
|
||||||
|
s_state.maximum_frame_time_accumulator = 0.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PerformanceCounters::Update(u32 frame_number, u32 internal_frame_number)
|
||||||
|
{
|
||||||
|
const Common::Timer::Value now_ticks = Common::Timer::GetCurrentValue();
|
||||||
|
|
||||||
|
const float frame_time = static_cast<float>(
|
||||||
|
Common::Timer::ConvertValueToMilliseconds(now_ticks - std::exchange(s_state.last_frame_time, now_ticks)));
|
||||||
|
s_state.minimum_frame_time_accumulator = (s_state.minimum_frame_time_accumulator == 0.0f) ?
|
||||||
|
frame_time :
|
||||||
|
std::min(s_state.minimum_frame_time_accumulator, frame_time);
|
||||||
|
s_state.average_frame_time_accumulator += frame_time;
|
||||||
|
s_state.maximum_frame_time_accumulator = std::max(s_state.maximum_frame_time_accumulator, frame_time);
|
||||||
|
s_state.frame_time_history[s_state.frame_time_history_pos] = frame_time;
|
||||||
|
s_state.frame_time_history_pos = (s_state.frame_time_history_pos + 1) % NUM_FRAME_TIME_SAMPLES;
|
||||||
|
|
||||||
|
// update fps counter
|
||||||
|
const Common::Timer::Value ticks_diff = now_ticks - s_state.last_update_time;
|
||||||
|
const float time = static_cast<float>(Common::Timer::ConvertValueToSeconds(ticks_diff));
|
||||||
|
if (time < PERFORMANCE_COUNTER_UPDATE_INTERVAL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
s_state.last_update_time = now_ticks;
|
||||||
|
|
||||||
|
const u32 frames_run = frame_number - std::exchange(s_state.last_frame_number, frame_number);
|
||||||
|
const u32 internal_frames_run =
|
||||||
|
internal_frame_number - std::exchange(s_state.last_internal_frame_number, internal_frame_number);
|
||||||
|
const float frames_runf = static_cast<float>(frames_run);
|
||||||
|
|
||||||
|
// TODO: Make the math here less rubbish
|
||||||
|
const double pct_divider =
|
||||||
|
100.0 * (1.0 / ((static_cast<double>(ticks_diff) * static_cast<double>(Threading::GetThreadTicksPerSecond())) /
|
||||||
|
Common::Timer::GetFrequency() / 1000000000.0));
|
||||||
|
const double time_divider = 1000.0 * (1.0 / static_cast<double>(Threading::GetThreadTicksPerSecond())) *
|
||||||
|
(1.0 / static_cast<double>(frames_runf));
|
||||||
|
|
||||||
|
s_state.minimum_frame_time = std::exchange(s_state.minimum_frame_time_accumulator, 0.0f);
|
||||||
|
s_state.average_frame_time = std::exchange(s_state.average_frame_time_accumulator, 0.0f) / frames_runf;
|
||||||
|
s_state.maximum_frame_time = std::exchange(s_state.maximum_frame_time_accumulator, 0.0f);
|
||||||
|
|
||||||
|
s_state.vps = static_cast<float>(frames_runf / time);
|
||||||
|
s_state.fps = static_cast<float>(internal_frames_run) / time;
|
||||||
|
s_state.speed = (s_state.vps / System::GetVideoFrameRate()) * 100.0f;
|
||||||
|
|
||||||
|
const Threading::Thread* sw_thread = g_gpu->GetSWThread();
|
||||||
|
const u64 cpu_time = System::Internal::GetCPUThreadHandle().GetCPUTime();
|
||||||
|
const u64 sw_time = sw_thread ? sw_thread->GetCPUTime() : 0;
|
||||||
|
const u64 cpu_delta = cpu_time - s_state.last_cpu_time;
|
||||||
|
const u64 sw_delta = sw_time - s_state.last_sw_time;
|
||||||
|
s_state.last_cpu_time = cpu_time;
|
||||||
|
s_state.last_sw_time = sw_time;
|
||||||
|
|
||||||
|
s_state.cpu_thread_usage = static_cast<float>(static_cast<double>(cpu_delta) * pct_divider);
|
||||||
|
s_state.cpu_thread_time = static_cast<float>(static_cast<double>(cpu_delta) * time_divider);
|
||||||
|
s_state.sw_thread_usage = static_cast<float>(static_cast<double>(sw_delta) * pct_divider);
|
||||||
|
s_state.sw_thread_time = static_cast<float>(static_cast<double>(sw_delta) * time_divider);
|
||||||
|
|
||||||
|
if (MediaCapture* cap = System::GetMediaCapture())
|
||||||
|
cap->UpdateCaptureThreadUsage(pct_divider, time_divider);
|
||||||
|
|
||||||
|
if (g_gpu_device->IsGPUTimingEnabled())
|
||||||
|
{
|
||||||
|
s_state.average_gpu_time =
|
||||||
|
s_state.accumulated_gpu_time / static_cast<float>(std::max(s_state.presents_since_last_update, 1u));
|
||||||
|
s_state.gpu_usage = s_state.accumulated_gpu_time / (time * 10.0f);
|
||||||
|
}
|
||||||
|
s_state.accumulated_gpu_time = 0.0f;
|
||||||
|
s_state.presents_since_last_update = 0;
|
||||||
|
|
||||||
|
if (g_settings.display_show_gpu_stats)
|
||||||
|
g_gpu->UpdateStatistics(frames_run);
|
||||||
|
|
||||||
|
VERBOSE_LOG("FPS: {:.2f} VPS: {:.2f} CPU: {:.2f} GPU: {:.2f} Avg: {:.2f}ms Min: {:.2f}ms Max: {:.2f}ms",
|
||||||
|
s_state.fps, s_state.vps, s_state.cpu_thread_usage, s_state.gpu_usage, s_state.average_frame_time,
|
||||||
|
s_state.minimum_frame_time, s_state.maximum_frame_time);
|
||||||
|
|
||||||
|
Host::OnPerformanceCountersUpdated();
|
||||||
|
}
|
||||||
|
|
||||||
|
void PerformanceCounters::AccumulateGPUTime()
|
||||||
|
{
|
||||||
|
s_state.accumulated_gpu_time += g_gpu_device->GetAndResetAccumulatedGPUTime();
|
||||||
|
s_state.presents_since_last_update++;
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
// SPDX-FileCopyrightText: 2019-2024 Connor McLaughlin <stenzek@gmail.com>
|
||||||
|
// SPDX-License-Identifier: CC-BY-NC-ND-4.0
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common/types.h"
|
||||||
|
|
||||||
|
namespace PerformanceCounters
|
||||||
|
{
|
||||||
|
static constexpr u32 NUM_FRAME_TIME_SAMPLES = 150;
|
||||||
|
using FrameTimeHistory = std::array<float, NUM_FRAME_TIME_SAMPLES>;
|
||||||
|
|
||||||
|
float GetFPS();
|
||||||
|
float GetVPS();
|
||||||
|
float GetEmulationSpeed();
|
||||||
|
float GetAverageFrameTime();
|
||||||
|
float GetMinimumFrameTime();
|
||||||
|
float GetMaximumFrameTime();
|
||||||
|
float GetCPUThreadUsage();
|
||||||
|
float GetCPUThreadAverageTime();
|
||||||
|
float GetSWThreadUsage();
|
||||||
|
float GetSWThreadAverageTime();
|
||||||
|
float GetGPUUsage();
|
||||||
|
float GetGPUAverageTime();
|
||||||
|
const FrameTimeHistory& GetFrameTimeHistory();
|
||||||
|
u32 GetFrameTimeHistoryPos();
|
||||||
|
|
||||||
|
void Clear();
|
||||||
|
void Reset();
|
||||||
|
void Update(u32 frame_number, u32 internal_frame_number);
|
||||||
|
void AccumulateGPUTime();
|
||||||
|
|
||||||
|
} // namespace Host
|
|
@ -28,6 +28,7 @@
|
||||||
#include "multitap.h"
|
#include "multitap.h"
|
||||||
#include "pad.h"
|
#include "pad.h"
|
||||||
#include "pcdrv.h"
|
#include "pcdrv.h"
|
||||||
|
#include "performance_counters.h"
|
||||||
#include "psf_loader.h"
|
#include "psf_loader.h"
|
||||||
#include "save_state_version.h"
|
#include "save_state_version.h"
|
||||||
#include "sio.h"
|
#include "sio.h"
|
||||||
|
@ -111,8 +112,10 @@ SystemBootParameters::SystemBootParameters(std::string filename_) : filename(std
|
||||||
SystemBootParameters::~SystemBootParameters() = default;
|
SystemBootParameters::~SystemBootParameters() = default;
|
||||||
|
|
||||||
namespace System {
|
namespace System {
|
||||||
|
|
||||||
/// Memory save states - only for internal use.
|
/// Memory save states - only for internal use.
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
struct SaveStateBuffer
|
struct SaveStateBuffer
|
||||||
{
|
{
|
||||||
std::string serial;
|
std::string serial;
|
||||||
|
@ -132,6 +135,7 @@ struct MemorySaveState
|
||||||
size_t state_size;
|
size_t state_size;
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
static void CheckCacheLineSize();
|
static void CheckCacheLineSize();
|
||||||
|
@ -180,11 +184,8 @@ static void ResetThrottler();
|
||||||
|
|
||||||
/// Throttles the system, i.e. sleeps until it's time to execute the next frame.
|
/// Throttles the system, i.e. sleeps until it's time to execute the next frame.
|
||||||
static void Throttle(Common::Timer::Value current_time);
|
static void Throttle(Common::Timer::Value current_time);
|
||||||
static void UpdatePerformanceCounters();
|
static void AccumulatePreFrameSleepTime(Common::Timer::Value current_time);
|
||||||
static void AccumulatePreFrameSleepTime();
|
|
||||||
static void UpdatePreFrameSleepTime();
|
|
||||||
static void UpdateDisplayVSync();
|
static void UpdateDisplayVSync();
|
||||||
static void ResetPerformanceCounters();
|
|
||||||
|
|
||||||
static bool UpdateGameSettingsLayer();
|
static bool UpdateGameSettingsLayer();
|
||||||
static void UpdateRunningGame(const std::string_view path, CDImage* image, bool booting);
|
static void UpdateRunningGame(const std::string_view path, CDImage* image, bool booting);
|
||||||
|
@ -239,7 +240,7 @@ static void PollDiscordPresence();
|
||||||
#endif
|
#endif
|
||||||
} // namespace System
|
} // namespace System
|
||||||
|
|
||||||
static constexpr const float PERFORMANCE_COUNTER_UPDATE_INTERVAL = 1.0f;
|
static constexpr float PRE_FRAME_SLEEP_UPDATE_INTERVAL = 1.0f;
|
||||||
static constexpr const char FALLBACK_EXE_NAME[] = "PSX.EXE";
|
static constexpr const char FALLBACK_EXE_NAME[] = "PSX.EXE";
|
||||||
static constexpr u32 MAX_SKIPPED_DUPLICATE_FRAME_COUNT = 2; // 20fps minimum
|
static constexpr u32 MAX_SKIPPED_DUPLICATE_FRAME_COUNT = 2; // 20fps minimum
|
||||||
static constexpr u32 MAX_SKIPPED_TIMEOUT_FRAME_COUNT = 1; // 30fps minimum
|
static constexpr u32 MAX_SKIPPED_TIMEOUT_FRAME_COUNT = 1; // 30fps minimum
|
||||||
|
@ -285,7 +286,7 @@ static bool s_skip_presenting_duplicate_frames = false;
|
||||||
static u32 s_skipped_frame_count = 0;
|
static u32 s_skipped_frame_count = 0;
|
||||||
static u32 s_last_presented_internal_frame_number = 0;
|
static u32 s_last_presented_internal_frame_number = 0;
|
||||||
|
|
||||||
static float s_throttle_frequency = 0.0f;
|
static float s_video_frame_rate = 0.0f;
|
||||||
static float s_target_speed = 0.0f;
|
static float s_target_speed = 0.0f;
|
||||||
|
|
||||||
static Common::Timer::Value s_frame_period = 0;
|
static Common::Timer::Value s_frame_period = 0;
|
||||||
|
@ -295,33 +296,8 @@ static Common::Timer::Value s_frame_start_time = 0;
|
||||||
static Common::Timer::Value s_last_active_frame_time = 0;
|
static Common::Timer::Value s_last_active_frame_time = 0;
|
||||||
static Common::Timer::Value s_pre_frame_sleep_time = 0;
|
static Common::Timer::Value s_pre_frame_sleep_time = 0;
|
||||||
static Common::Timer::Value s_max_active_frame_time = 0;
|
static Common::Timer::Value s_max_active_frame_time = 0;
|
||||||
|
static Common::Timer::Value s_last_pre_frame_sleep_update_time = 0;
|
||||||
|
|
||||||
static float s_average_frame_time_accumulator = 0.0f;
|
|
||||||
static float s_minimum_frame_time_accumulator = 0.0f;
|
|
||||||
static float s_maximum_frame_time_accumulator = 0.0f;
|
|
||||||
|
|
||||||
static float s_vps = 0.0f;
|
|
||||||
static float s_fps = 0.0f;
|
|
||||||
static float s_speed = 0.0f;
|
|
||||||
static float s_minimum_frame_time = 0.0f;
|
|
||||||
static float s_maximum_frame_time = 0.0f;
|
|
||||||
static float s_average_frame_time = 0.0f;
|
|
||||||
static float s_cpu_thread_usage = 0.0f;
|
|
||||||
static float s_cpu_thread_time = 0.0f;
|
|
||||||
static float s_sw_thread_usage = 0.0f;
|
|
||||||
static float s_sw_thread_time = 0.0f;
|
|
||||||
static float s_average_gpu_time = 0.0f;
|
|
||||||
static float s_accumulated_gpu_time = 0.0f;
|
|
||||||
static float s_gpu_usage = 0.0f;
|
|
||||||
static System::FrameTimeHistory s_frame_time_history;
|
|
||||||
static u32 s_frame_time_history_pos = 0;
|
|
||||||
static u32 s_last_frame_number = 0;
|
|
||||||
static u32 s_last_internal_frame_number = 0;
|
|
||||||
static u64 s_last_cpu_time = 0;
|
|
||||||
static u64 s_last_sw_time = 0;
|
|
||||||
static u32 s_presents_since_last_update = 0;
|
|
||||||
static Common::Timer s_fps_timer;
|
|
||||||
static Common::Timer s_frame_timer;
|
|
||||||
static Threading::ThreadHandle s_cpu_thread_handle;
|
static Threading::ThreadHandle s_cpu_thread_handle;
|
||||||
|
|
||||||
static std::unique_ptr<MediaCapture> s_media_capture;
|
static std::unique_ptr<MediaCapture> s_media_capture;
|
||||||
|
@ -559,6 +535,11 @@ void System::Internal::CPUThreadShutdown()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Threading::ThreadHandle& System::Internal::GetCPUThreadHandle()
|
||||||
|
{
|
||||||
|
return s_cpu_thread_handle;
|
||||||
|
}
|
||||||
|
|
||||||
void System::Internal::IdlePollUpdate()
|
void System::Internal::IdlePollUpdate()
|
||||||
{
|
{
|
||||||
InputManager::PollSources();
|
InputManager::PollSources();
|
||||||
|
@ -795,67 +776,6 @@ const BIOS::ImageInfo* System::GetBIOSImageInfo()
|
||||||
return s_bios_image_info;
|
return s_bios_image_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
float System::GetFPS()
|
|
||||||
{
|
|
||||||
return s_fps;
|
|
||||||
}
|
|
||||||
float System::GetVPS()
|
|
||||||
{
|
|
||||||
return s_vps;
|
|
||||||
}
|
|
||||||
float System::GetEmulationSpeed()
|
|
||||||
{
|
|
||||||
return s_speed;
|
|
||||||
}
|
|
||||||
float System::GetAverageFrameTime()
|
|
||||||
{
|
|
||||||
return s_average_frame_time;
|
|
||||||
}
|
|
||||||
float System::GetMinimumFrameTime()
|
|
||||||
{
|
|
||||||
return s_minimum_frame_time;
|
|
||||||
}
|
|
||||||
float System::GetMaximumFrameTime()
|
|
||||||
{
|
|
||||||
return s_maximum_frame_time;
|
|
||||||
}
|
|
||||||
float System::GetThrottleFrequency()
|
|
||||||
{
|
|
||||||
return s_throttle_frequency;
|
|
||||||
}
|
|
||||||
float System::GetCPUThreadUsage()
|
|
||||||
{
|
|
||||||
return s_cpu_thread_usage;
|
|
||||||
}
|
|
||||||
float System::GetCPUThreadAverageTime()
|
|
||||||
{
|
|
||||||
return s_cpu_thread_time;
|
|
||||||
}
|
|
||||||
float System::GetSWThreadUsage()
|
|
||||||
{
|
|
||||||
return s_sw_thread_usage;
|
|
||||||
}
|
|
||||||
float System::GetSWThreadAverageTime()
|
|
||||||
{
|
|
||||||
return s_sw_thread_time;
|
|
||||||
}
|
|
||||||
float System::GetGPUUsage()
|
|
||||||
{
|
|
||||||
return s_gpu_usage;
|
|
||||||
}
|
|
||||||
float System::GetGPUAverageTime()
|
|
||||||
{
|
|
||||||
return s_average_gpu_time;
|
|
||||||
}
|
|
||||||
const System::FrameTimeHistory& System::GetFrameTimeHistory()
|
|
||||||
{
|
|
||||||
return s_frame_time_history;
|
|
||||||
}
|
|
||||||
u32 System::GetFrameTimeHistoryPos()
|
|
||||||
{
|
|
||||||
return s_frame_time_history_pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool System::IsExePath(std::string_view path)
|
bool System::IsExePath(std::string_view path)
|
||||||
{
|
{
|
||||||
return (StringUtil::EndsWithNoCase(path, ".exe") || StringUtil::EndsWithNoCase(path, ".psexe") ||
|
return (StringUtil::EndsWithNoCase(path, ".exe") || StringUtil::EndsWithNoCase(path, ".psexe") ||
|
||||||
|
@ -1622,7 +1542,8 @@ void System::ResetSystem()
|
||||||
Host::AddIconOSDMessage("SystemReset", ICON_FA_POWER_OFF, TRANSLATE_STR("OSDMessage", "System reset."),
|
Host::AddIconOSDMessage("SystemReset", ICON_FA_POWER_OFF, TRANSLATE_STR("OSDMessage", "System reset."),
|
||||||
Host::OSD_QUICK_DURATION);
|
Host::OSD_QUICK_DURATION);
|
||||||
|
|
||||||
ResetPerformanceCounters();
|
PerformanceCounters::Reset();
|
||||||
|
ResetThrottler();
|
||||||
InterruptExecution();
|
InterruptExecution();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1677,7 +1598,7 @@ void System::PauseSystem(bool paused)
|
||||||
Host::OnIdleStateChanged();
|
Host::OnIdleStateChanged();
|
||||||
|
|
||||||
UpdateDisplayVSync();
|
UpdateDisplayVSync();
|
||||||
ResetPerformanceCounters();
|
PerformanceCounters::Reset();
|
||||||
ResetThrottler();
|
ResetThrottler();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1927,7 +1848,8 @@ bool System::BootSystem(SystemBootParameters parameters, Error* error)
|
||||||
|
|
||||||
UpdateSpeedLimiterState();
|
UpdateSpeedLimiterState();
|
||||||
ImGuiManager::UpdateDebugWindowConfig();
|
ImGuiManager::UpdateDebugWindowConfig();
|
||||||
ResetPerformanceCounters();
|
PerformanceCounters::Reset();
|
||||||
|
ResetThrottler();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1940,7 +1862,7 @@ bool System::Initialize(std::unique_ptr<CDImage> disc, DiscRegion disc_region, b
|
||||||
s_internal_frame_number = 0;
|
s_internal_frame_number = 0;
|
||||||
|
|
||||||
s_target_speed = g_settings.emulation_speed;
|
s_target_speed = g_settings.emulation_speed;
|
||||||
s_throttle_frequency = 60.0f;
|
s_video_frame_rate = 60.0f;
|
||||||
s_frame_period = 0;
|
s_frame_period = 0;
|
||||||
s_next_frame_time = 0;
|
s_next_frame_time = 0;
|
||||||
s_turbo_enabled = false;
|
s_turbo_enabled = false;
|
||||||
|
@ -1950,32 +1872,6 @@ bool System::Initialize(std::unique_ptr<CDImage> disc, DiscRegion disc_region, b
|
||||||
s_rewind_load_counter = -1;
|
s_rewind_load_counter = -1;
|
||||||
s_rewinding_first_save = true;
|
s_rewinding_first_save = true;
|
||||||
|
|
||||||
s_average_frame_time_accumulator = 0.0f;
|
|
||||||
s_minimum_frame_time_accumulator = 0.0f;
|
|
||||||
s_maximum_frame_time_accumulator = 0.0f;
|
|
||||||
|
|
||||||
s_vps = 0.0f;
|
|
||||||
s_fps = 0.0f;
|
|
||||||
s_speed = 0.0f;
|
|
||||||
s_minimum_frame_time = 0.0f;
|
|
||||||
s_maximum_frame_time = 0.0f;
|
|
||||||
s_average_frame_time = 0.0f;
|
|
||||||
s_cpu_thread_usage = 0.0f;
|
|
||||||
s_cpu_thread_time = 0.0f;
|
|
||||||
s_sw_thread_usage = 0.0f;
|
|
||||||
s_sw_thread_time = 0.0f;
|
|
||||||
s_average_gpu_time = 0.0f;
|
|
||||||
s_accumulated_gpu_time = 0.0f;
|
|
||||||
s_gpu_usage = 0.0f;
|
|
||||||
s_last_frame_number = 0;
|
|
||||||
s_last_internal_frame_number = 0;
|
|
||||||
s_presents_since_last_update = 0;
|
|
||||||
s_last_cpu_time = 0;
|
|
||||||
s_fps_timer.Reset();
|
|
||||||
s_frame_timer.Reset();
|
|
||||||
s_frame_time_history.fill(0.0f);
|
|
||||||
s_frame_time_history_pos = 0;
|
|
||||||
|
|
||||||
TimingEvents::Initialize();
|
TimingEvents::Initialize();
|
||||||
|
|
||||||
Bus::Initialize();
|
Bus::Initialize();
|
||||||
|
@ -2014,6 +1910,9 @@ bool System::Initialize(std::unique_ptr<CDImage> disc, DiscRegion disc_region, b
|
||||||
|
|
||||||
UpdateThrottlePeriod();
|
UpdateThrottlePeriod();
|
||||||
UpdateMemorySaveStateSettings();
|
UpdateMemorySaveStateSettings();
|
||||||
|
|
||||||
|
PerformanceCounters::Clear();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2050,8 +1949,6 @@ void System::DestroySystem()
|
||||||
if (g_settings.inhibit_screensaver)
|
if (g_settings.inhibit_screensaver)
|
||||||
PlatformMisc::ResumeScreensaver();
|
PlatformMisc::ResumeScreensaver();
|
||||||
|
|
||||||
s_cpu_thread_usage = {};
|
|
||||||
|
|
||||||
ClearMemorySaveStates();
|
ClearMemorySaveStates();
|
||||||
|
|
||||||
Cheats::UnloadAll();
|
Cheats::UnloadAll();
|
||||||
|
@ -2224,7 +2121,7 @@ void System::FrameDone()
|
||||||
// Kick off media capture early, might take a while.
|
// Kick off media capture early, might take a while.
|
||||||
if (s_media_capture && s_media_capture->IsCapturingVideo()) [[unlikely]]
|
if (s_media_capture && s_media_capture->IsCapturingVideo()) [[unlikely]]
|
||||||
{
|
{
|
||||||
if (s_media_capture->GetVideoFPS() != GetThrottleFrequency()) [[unlikely]]
|
if (s_media_capture->GetVideoFPS() != s_video_frame_rate) [[unlikely]]
|
||||||
{
|
{
|
||||||
const std::string next_capture_path = s_media_capture->GetNextCapturePath();
|
const std::string next_capture_path = s_media_capture->GetNextCapturePath();
|
||||||
INFO_LOG("Video frame rate changed, switching to new capture file {}", Path::GetFileName(next_capture_path));
|
INFO_LOG("Video frame rate changed, switching to new capture file {}", Path::GetFileName(next_capture_path));
|
||||||
|
@ -2250,7 +2147,7 @@ void System::FrameDone()
|
||||||
const Common::Timer::Value pre_frame_sleep_until = s_next_frame_time + s_pre_frame_sleep_time;
|
const Common::Timer::Value pre_frame_sleep_until = s_next_frame_time + s_pre_frame_sleep_time;
|
||||||
s_last_active_frame_time = current_time - s_frame_start_time;
|
s_last_active_frame_time = current_time - s_frame_start_time;
|
||||||
if (s_pre_frame_sleep)
|
if (s_pre_frame_sleep)
|
||||||
AccumulatePreFrameSleepTime();
|
AccumulatePreFrameSleepTime(current_time);
|
||||||
|
|
||||||
// explicit present (frame pacing)
|
// explicit present (frame pacing)
|
||||||
const bool is_unique_frame = (s_last_presented_internal_frame_number != s_internal_frame_number);
|
const bool is_unique_frame = (s_last_presented_internal_frame_number != s_internal_frame_number);
|
||||||
|
@ -2328,15 +2225,20 @@ void System::FrameDone()
|
||||||
// Update perf counters *after* throttling, we want to measure from start-of-frame
|
// Update perf counters *after* throttling, we want to measure from start-of-frame
|
||||||
// to start-of-frame, not end-of-frame to end-of-frame (will be noisy due to different
|
// to start-of-frame, not end-of-frame to end-of-frame (will be noisy due to different
|
||||||
// amounts of computation happening in each frame).
|
// amounts of computation happening in each frame).
|
||||||
System::UpdatePerformanceCounters();
|
PerformanceCounters::Update(s_frame_number, s_internal_frame_number);
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::SetThrottleFrequency(float frequency)
|
float System::GetVideoFrameRate()
|
||||||
{
|
{
|
||||||
if (s_throttle_frequency == frequency)
|
return s_video_frame_rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
void System::SetVideoFrameRate(float frequency)
|
||||||
|
{
|
||||||
|
if (s_video_frame_rate == frequency)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
s_throttle_frequency = frequency;
|
s_video_frame_rate = frequency;
|
||||||
UpdateThrottlePeriod();
|
UpdateThrottlePeriod();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2346,7 +2248,7 @@ void System::UpdateThrottlePeriod()
|
||||||
{
|
{
|
||||||
const double target_speed = std::max(static_cast<double>(s_target_speed), std::numeric_limits<double>::epsilon());
|
const double target_speed = std::max(static_cast<double>(s_target_speed), std::numeric_limits<double>::epsilon());
|
||||||
s_frame_period =
|
s_frame_period =
|
||||||
Common::Timer::ConvertSecondsToValue(1.0 / (static_cast<double>(s_throttle_frequency) * target_speed));
|
Common::Timer::ConvertSecondsToValue(1.0 / (static_cast<double>(s_video_frame_rate) * target_speed));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2790,17 +2692,11 @@ bool System::LoadState(const char* path, Error* error, bool save_undo_state)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResetPerformanceCounters();
|
|
||||||
ResetThrottler();
|
|
||||||
|
|
||||||
if (IsPaused())
|
|
||||||
InvalidateDisplay();
|
|
||||||
|
|
||||||
VERBOSE_LOG("Loading state took {:.2f} msec", load_timer.GetTimeMilliseconds());
|
VERBOSE_LOG("Loading state took {:.2f} msec", load_timer.GetTimeMilliseconds());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool System::LoadStateFromBuffer(const SaveStateBuffer& buffer, Error* error, bool update_display)
|
bool System::LoadStateFromBuffer(const SaveStateBuffer& buffer, Error* error, bool update_display_if_paused)
|
||||||
{
|
{
|
||||||
Assert(IsValid());
|
Assert(IsValid());
|
||||||
|
|
||||||
|
@ -2866,15 +2762,20 @@ bool System::LoadStateFromBuffer(const SaveStateBuffer& buffer, Error* error, bo
|
||||||
Achievements::DisableHardcoreMode();
|
Achievements::DisableHardcoreMode();
|
||||||
|
|
||||||
StateWrapper sw(buffer.state_data.cspan(0, buffer.state_size), StateWrapper::Mode::Read, buffer.version);
|
StateWrapper sw(buffer.state_data.cspan(0, buffer.state_size), StateWrapper::Mode::Read, buffer.version);
|
||||||
if (!DoState(sw, nullptr, update_display, false))
|
if (!DoState(sw, nullptr, update_display_if_paused && IsPaused(), false))
|
||||||
{
|
{
|
||||||
Error::SetStringView(error, "Save state stream is corrupted.");
|
Error::SetStringView(error, "Save state stream is corrupted.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
InterruptExecution();
|
InterruptExecution();
|
||||||
ResetPerformanceCounters();
|
|
||||||
|
PerformanceCounters::Reset();
|
||||||
ResetThrottler();
|
ResetThrottler();
|
||||||
|
|
||||||
|
if (update_display_if_paused && IsPaused())
|
||||||
|
InvalidateDisplay();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3340,100 +3241,7 @@ float System::GetAudioNominalRate()
|
||||||
return (s_throttler_enabled || s_syncing_to_host_with_vsync) ? s_target_speed : 1.0f;
|
return (s_throttler_enabled || s_syncing_to_host_with_vsync) ? s_target_speed : 1.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::UpdatePerformanceCounters()
|
void System::AccumulatePreFrameSleepTime(Common::Timer::Value current_time)
|
||||||
{
|
|
||||||
const float frame_time = static_cast<float>(s_frame_timer.GetTimeMillisecondsAndReset());
|
|
||||||
s_minimum_frame_time_accumulator =
|
|
||||||
(s_minimum_frame_time_accumulator == 0.0f) ? frame_time : std::min(s_minimum_frame_time_accumulator, frame_time);
|
|
||||||
s_average_frame_time_accumulator += frame_time;
|
|
||||||
s_maximum_frame_time_accumulator = std::max(s_maximum_frame_time_accumulator, frame_time);
|
|
||||||
s_frame_time_history[s_frame_time_history_pos] = frame_time;
|
|
||||||
s_frame_time_history_pos = (s_frame_time_history_pos + 1) % NUM_FRAME_TIME_SAMPLES;
|
|
||||||
|
|
||||||
// update fps counter
|
|
||||||
const Common::Timer::Value now_ticks = Common::Timer::GetCurrentValue();
|
|
||||||
const Common::Timer::Value ticks_diff = now_ticks - s_fps_timer.GetStartValue();
|
|
||||||
const float time = static_cast<float>(Common::Timer::ConvertValueToSeconds(ticks_diff));
|
|
||||||
if (time < PERFORMANCE_COUNTER_UPDATE_INTERVAL)
|
|
||||||
return;
|
|
||||||
|
|
||||||
const u32 frames_run = s_frame_number - s_last_frame_number;
|
|
||||||
const float frames_runf = static_cast<float>(frames_run);
|
|
||||||
|
|
||||||
// TODO: Make the math here less rubbish
|
|
||||||
const double pct_divider =
|
|
||||||
100.0 * (1.0 / ((static_cast<double>(ticks_diff) * static_cast<double>(Threading::GetThreadTicksPerSecond())) /
|
|
||||||
Common::Timer::GetFrequency() / 1000000000.0));
|
|
||||||
const double time_divider = 1000.0 * (1.0 / static_cast<double>(Threading::GetThreadTicksPerSecond())) *
|
|
||||||
(1.0 / static_cast<double>(frames_runf));
|
|
||||||
|
|
||||||
s_minimum_frame_time = std::exchange(s_minimum_frame_time_accumulator, 0.0f);
|
|
||||||
s_average_frame_time = std::exchange(s_average_frame_time_accumulator, 0.0f) / frames_runf;
|
|
||||||
s_maximum_frame_time = std::exchange(s_maximum_frame_time_accumulator, 0.0f);
|
|
||||||
|
|
||||||
s_vps = static_cast<float>(frames_runf / time);
|
|
||||||
s_last_frame_number = s_frame_number;
|
|
||||||
s_fps = static_cast<float>(s_internal_frame_number - s_last_internal_frame_number) / time;
|
|
||||||
s_last_internal_frame_number = s_internal_frame_number;
|
|
||||||
s_speed = (s_vps / s_throttle_frequency) * 100.0f;
|
|
||||||
|
|
||||||
const Threading::Thread* sw_thread = g_gpu->GetSWThread();
|
|
||||||
const u64 cpu_time = s_cpu_thread_handle ? s_cpu_thread_handle.GetCPUTime() : 0;
|
|
||||||
const u64 sw_time = sw_thread ? sw_thread->GetCPUTime() : 0;
|
|
||||||
const u64 cpu_delta = cpu_time - s_last_cpu_time;
|
|
||||||
const u64 sw_delta = sw_time - s_last_sw_time;
|
|
||||||
s_last_cpu_time = cpu_time;
|
|
||||||
s_last_sw_time = sw_time;
|
|
||||||
|
|
||||||
s_cpu_thread_usage = static_cast<float>(static_cast<double>(cpu_delta) * pct_divider);
|
|
||||||
s_cpu_thread_time = static_cast<float>(static_cast<double>(cpu_delta) * time_divider);
|
|
||||||
s_sw_thread_usage = static_cast<float>(static_cast<double>(sw_delta) * pct_divider);
|
|
||||||
s_sw_thread_time = static_cast<float>(static_cast<double>(sw_delta) * time_divider);
|
|
||||||
|
|
||||||
if (s_media_capture)
|
|
||||||
s_media_capture->UpdateCaptureThreadUsage(pct_divider, time_divider);
|
|
||||||
|
|
||||||
s_fps_timer.ResetTo(now_ticks);
|
|
||||||
|
|
||||||
if (g_gpu_device->IsGPUTimingEnabled())
|
|
||||||
{
|
|
||||||
s_average_gpu_time = s_accumulated_gpu_time / static_cast<float>(std::max(s_presents_since_last_update, 1u));
|
|
||||||
s_gpu_usage = s_accumulated_gpu_time / (time * 10.0f);
|
|
||||||
}
|
|
||||||
s_accumulated_gpu_time = 0.0f;
|
|
||||||
s_presents_since_last_update = 0;
|
|
||||||
|
|
||||||
if (g_settings.display_show_gpu_stats)
|
|
||||||
g_gpu->UpdateStatistics(frames_run);
|
|
||||||
|
|
||||||
if (s_pre_frame_sleep)
|
|
||||||
UpdatePreFrameSleepTime();
|
|
||||||
|
|
||||||
VERBOSE_LOG("FPS: {:.2f} VPS: {:.2f} CPU: {:.2f} GPU: {:.2f} Average: {:.2f}ms Min: {:.2f}ms Max: {:.2f}ms", s_fps,
|
|
||||||
s_vps, s_cpu_thread_usage, s_gpu_usage, s_average_frame_time, s_minimum_frame_time, s_maximum_frame_time);
|
|
||||||
|
|
||||||
Host::OnPerformanceCountersUpdated();
|
|
||||||
}
|
|
||||||
|
|
||||||
void System::ResetPerformanceCounters()
|
|
||||||
{
|
|
||||||
s_last_frame_number = s_frame_number;
|
|
||||||
s_last_internal_frame_number = s_internal_frame_number;
|
|
||||||
s_last_cpu_time = s_cpu_thread_handle ? s_cpu_thread_handle.GetCPUTime() : 0;
|
|
||||||
if (const Threading::Thread* sw_thread = g_gpu->GetSWThread(); sw_thread)
|
|
||||||
s_last_sw_time = sw_thread->GetCPUTime();
|
|
||||||
else
|
|
||||||
s_last_sw_time = 0;
|
|
||||||
|
|
||||||
s_average_frame_time_accumulator = 0.0f;
|
|
||||||
s_minimum_frame_time_accumulator = 0.0f;
|
|
||||||
s_maximum_frame_time_accumulator = 0.0f;
|
|
||||||
s_frame_timer.Reset();
|
|
||||||
s_fps_timer.Reset();
|
|
||||||
ResetThrottler();
|
|
||||||
}
|
|
||||||
|
|
||||||
void System::AccumulatePreFrameSleepTime()
|
|
||||||
{
|
{
|
||||||
DebugAssert(s_pre_frame_sleep);
|
DebugAssert(s_pre_frame_sleep);
|
||||||
|
|
||||||
|
@ -3450,21 +3258,22 @@ void System::AccumulatePreFrameSleepTime()
|
||||||
Common::Timer::ConvertValueToMilliseconds(s_pre_frame_sleep_time),
|
Common::Timer::ConvertValueToMilliseconds(s_pre_frame_sleep_time),
|
||||||
Common::Timer::ConvertValueToMilliseconds(s_last_active_frame_time));
|
Common::Timer::ConvertValueToMilliseconds(s_last_active_frame_time));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void System::UpdatePreFrameSleepTime()
|
if (Common::Timer::ConvertValueToSeconds(current_time - s_last_pre_frame_sleep_update_time) >=
|
||||||
{
|
PRE_FRAME_SLEEP_UPDATE_INTERVAL)
|
||||||
DebugAssert(s_pre_frame_sleep);
|
{
|
||||||
|
s_last_pre_frame_sleep_update_time = current_time;
|
||||||
|
|
||||||
const Common::Timer::Value expected_frame_time =
|
const Common::Timer::Value expected_frame_time =
|
||||||
s_max_active_frame_time + Common::Timer::ConvertMillisecondsToValue(g_settings.display_pre_frame_sleep_buffer);
|
s_max_active_frame_time + Common::Timer::ConvertMillisecondsToValue(g_settings.display_pre_frame_sleep_buffer);
|
||||||
s_pre_frame_sleep_time = Common::AlignDown(s_frame_period - std::min(expected_frame_time, s_frame_period),
|
s_pre_frame_sleep_time = Common::AlignDown(s_frame_period - std::min(expected_frame_time, s_frame_period),
|
||||||
static_cast<unsigned int>(Common::Timer::ConvertMillisecondsToValue(1)));
|
static_cast<unsigned int>(Common::Timer::ConvertMillisecondsToValue(1)));
|
||||||
DEV_LOG("Set pre-frame time to {} ms (expected frame time of {} ms)",
|
DEV_LOG("Set pre-frame time to {} ms (expected frame time of {} ms)",
|
||||||
Common::Timer::ConvertValueToMilliseconds(s_pre_frame_sleep_time),
|
Common::Timer::ConvertValueToMilliseconds(s_pre_frame_sleep_time),
|
||||||
Common::Timer::ConvertValueToMilliseconds(expected_frame_time));
|
Common::Timer::ConvertValueToMilliseconds(expected_frame_time));
|
||||||
|
|
||||||
s_max_active_frame_time = 0;
|
s_max_active_frame_time = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void System::FormatLatencyStats(SmallStringBase& str)
|
void System::FormatLatencyStats(SmallStringBase& str)
|
||||||
|
@ -3505,10 +3314,10 @@ void System::UpdateSpeedLimiterState()
|
||||||
const float host_refresh_rate = g_gpu_device->GetMainSwapChain()->GetWindowInfo().surface_refresh_rate;
|
const float host_refresh_rate = g_gpu_device->GetMainSwapChain()->GetWindowInfo().surface_refresh_rate;
|
||||||
if (host_refresh_rate > 0.0f)
|
if (host_refresh_rate > 0.0f)
|
||||||
{
|
{
|
||||||
const float ratio = host_refresh_rate / System::GetThrottleFrequency();
|
const float ratio = host_refresh_rate / s_video_frame_rate;
|
||||||
s_can_sync_to_host = (ratio >= 0.95f && ratio <= 1.05f);
|
s_can_sync_to_host = (ratio >= 0.95f && ratio <= 1.05f);
|
||||||
INFO_LOG("Refresh rate: Host={}hz Guest={}hz Ratio={} - {}", host_refresh_rate, System::GetThrottleFrequency(),
|
INFO_LOG("Refresh rate: Host={}hz Guest={}hz Ratio={} - {}", host_refresh_rate, s_video_frame_rate, ratio,
|
||||||
ratio, s_can_sync_to_host ? "can sync" : "can't sync");
|
s_can_sync_to_host ? "can sync" : "can't sync");
|
||||||
|
|
||||||
s_syncing_to_host = (s_can_sync_to_host && g_settings.sync_to_host_refresh_rate && s_target_speed == 1.0f);
|
s_syncing_to_host = (s_can_sync_to_host && g_settings.sync_to_host_refresh_rate && s_target_speed == 1.0f);
|
||||||
if (s_syncing_to_host)
|
if (s_syncing_to_host)
|
||||||
|
@ -4911,7 +4720,7 @@ void System::UpdateMemorySaveStateSettings()
|
||||||
|
|
||||||
if (g_settings.rewind_enable)
|
if (g_settings.rewind_enable)
|
||||||
{
|
{
|
||||||
s_rewind_save_frequency = static_cast<s32>(std::ceil(g_settings.rewind_save_frequency * s_throttle_frequency));
|
s_rewind_save_frequency = static_cast<s32>(std::ceil(g_settings.rewind_save_frequency * s_video_frame_rate));
|
||||||
s_rewind_save_counter = 0;
|
s_rewind_save_counter = 0;
|
||||||
|
|
||||||
u64 ram_usage, vram_usage;
|
u64 ram_usage, vram_usage;
|
||||||
|
@ -5024,6 +4833,9 @@ bool System::LoadRewindState(u32 skip_saves /*= 0*/, bool consume_state /*=true
|
||||||
if (consume_state)
|
if (consume_state)
|
||||||
s_rewind_states.pop_back();
|
s_rewind_states.pop_back();
|
||||||
|
|
||||||
|
// back in time, need to reset perf counters
|
||||||
|
PerformanceCounters::Reset();
|
||||||
|
|
||||||
#ifdef PROFILE_MEMORY_SAVE_STATES
|
#ifdef PROFILE_MEMORY_SAVE_STATES
|
||||||
DEV_LOG("Rewind load took {:.4f} ms", load_timer.GetTimeMilliseconds());
|
DEV_LOG("Rewind load took {:.4f} ms", load_timer.GetTimeMilliseconds());
|
||||||
#endif
|
#endif
|
||||||
|
@ -5044,7 +4856,7 @@ void System::SetRewinding(bool enabled)
|
||||||
|
|
||||||
// Try to rewind at the replay speed, or one per second maximum.
|
// Try to rewind at the replay speed, or one per second maximum.
|
||||||
const float load_frequency = std::min(g_settings.rewind_save_frequency, 1.0f);
|
const float load_frequency = std::min(g_settings.rewind_save_frequency, 1.0f);
|
||||||
s_rewind_load_frequency = static_cast<s32>(std::ceil(load_frequency * s_throttle_frequency));
|
s_rewind_load_frequency = static_cast<s32>(std::ceil(load_frequency * s_video_frame_rate));
|
||||||
s_rewind_load_counter = 0;
|
s_rewind_load_counter = 0;
|
||||||
|
|
||||||
if (!was_enabled && s_system_executing)
|
if (!was_enabled && s_system_executing)
|
||||||
|
@ -5065,7 +4877,6 @@ void System::DoRewind()
|
||||||
const u32 skip_saves = BoolToUInt32(!s_rewinding_first_save);
|
const u32 skip_saves = BoolToUInt32(!s_rewinding_first_save);
|
||||||
s_rewinding_first_save = false;
|
s_rewinding_first_save = false;
|
||||||
LoadRewindState(skip_saves, false);
|
LoadRewindState(skip_saves, false);
|
||||||
ResetPerformanceCounters();
|
|
||||||
s_rewind_load_counter = s_rewind_load_frequency;
|
s_rewind_load_counter = s_rewind_load_frequency;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -5394,7 +5205,6 @@ bool System::StartMediaCapture(std::string path, bool capture_video, bool captur
|
||||||
Host::GetUIntSettingValue("MediaCapture", "VideoHeight", Settings::DEFAULT_MEDIA_CAPTURE_VIDEO_HEIGHT);
|
Host::GetUIntSettingValue("MediaCapture", "VideoHeight", Settings::DEFAULT_MEDIA_CAPTURE_VIDEO_HEIGHT);
|
||||||
const GPUTexture::Format capture_format =
|
const GPUTexture::Format capture_format =
|
||||||
g_gpu_device->HasMainSwapChain() ? g_gpu_device->GetMainSwapChain()->GetFormat() : GPUTexture::Format::RGBA8;
|
g_gpu_device->HasMainSwapChain() ? g_gpu_device->GetMainSwapChain()->GetFormat() : GPUTexture::Format::RGBA8;
|
||||||
const float fps = System::GetThrottleFrequency();
|
|
||||||
if (capture_video)
|
if (capture_video)
|
||||||
{
|
{
|
||||||
// TODO: This will be a mess with GPU thread.
|
// TODO: This will be a mess with GPU thread.
|
||||||
|
@ -5429,8 +5239,8 @@ bool System::StartMediaCapture(std::string path, bool capture_video, bool captur
|
||||||
s_media_capture = MediaCapture::Create(backend, &error);
|
s_media_capture = MediaCapture::Create(backend, &error);
|
||||||
if (!s_media_capture ||
|
if (!s_media_capture ||
|
||||||
!s_media_capture->BeginCapture(
|
!s_media_capture->BeginCapture(
|
||||||
fps, aspect, capture_width, capture_height, capture_format, SPU::SAMPLE_RATE, std::move(path), capture_video,
|
s_video_frame_rate, aspect, capture_width, capture_height, capture_format, SPU::SAMPLE_RATE, std::move(path),
|
||||||
Host::GetSmallStringSettingValue("MediaCapture", "VideoCodec"),
|
capture_video, Host::GetSmallStringSettingValue("MediaCapture", "VideoCodec"),
|
||||||
Host::GetUIntSettingValue("MediaCapture", "VideoBitrate", Settings::DEFAULT_MEDIA_CAPTURE_VIDEO_BITRATE),
|
Host::GetUIntSettingValue("MediaCapture", "VideoBitrate", Settings::DEFAULT_MEDIA_CAPTURE_VIDEO_BITRATE),
|
||||||
Host::GetBoolSettingValue("MediaCapture", "VideoCodecUseArgs", false) ?
|
Host::GetBoolSettingValue("MediaCapture", "VideoCodecUseArgs", false) ?
|
||||||
Host::GetStringSettingValue("MediaCapture", "AudioCodecArgs") :
|
Host::GetStringSettingValue("MediaCapture", "AudioCodecArgs") :
|
||||||
|
@ -5779,11 +5589,8 @@ void System::ToggleSoftwareRendering()
|
||||||
Host::OSD_QUICK_DURATION);
|
Host::OSD_QUICK_DURATION);
|
||||||
RecreateGPU(new_renderer);
|
RecreateGPU(new_renderer);
|
||||||
|
|
||||||
// Might have a thread change.
|
// TODO: GPU-THREAD: Drop this
|
||||||
if (const Threading::Thread* sw_thread = g_gpu->GetSWThread(); sw_thread)
|
PerformanceCounters::Reset();
|
||||||
s_last_sw_time = sw_thread->GetCPUTime();
|
|
||||||
else
|
|
||||||
s_last_sw_time = 0;
|
|
||||||
|
|
||||||
g_gpu->UpdateResolutionScale();
|
g_gpu->UpdateResolutionScale();
|
||||||
}
|
}
|
||||||
|
@ -5852,10 +5659,7 @@ bool System::PresentDisplay(bool explicit_present, u64 present_time)
|
||||||
g_gpu_device->EndPresent(g_gpu_device->GetMainSwapChain(), explicit_present, present_time);
|
g_gpu_device->EndPresent(g_gpu_device->GetMainSwapChain(), explicit_present, present_time);
|
||||||
|
|
||||||
if (g_gpu_device->IsGPUTimingEnabled())
|
if (g_gpu_device->IsGPUTimingEnabled())
|
||||||
{
|
PerformanceCounters::AccumulateGPUTime();
|
||||||
s_accumulated_gpu_time += g_gpu_device->GetAndResetAccumulatedGPUTime();
|
|
||||||
s_presents_since_last_update++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
|
@ -13,7 +13,10 @@
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class ByteStream;
|
namespace Threading {
|
||||||
|
class ThreadHandle;
|
||||||
|
}
|
||||||
|
|
||||||
class CDImage;
|
class CDImage;
|
||||||
class Error;
|
class Error;
|
||||||
class SmallStringBase;
|
class SmallStringBase;
|
||||||
|
@ -231,24 +234,6 @@ u64 GetSessionPlayedTime();
|
||||||
|
|
||||||
const BIOS::ImageInfo* GetBIOSImageInfo();
|
const BIOS::ImageInfo* GetBIOSImageInfo();
|
||||||
|
|
||||||
static constexpr u32 NUM_FRAME_TIME_SAMPLES = 150;
|
|
||||||
using FrameTimeHistory = std::array<float, NUM_FRAME_TIME_SAMPLES>;
|
|
||||||
|
|
||||||
float GetFPS();
|
|
||||||
float GetVPS();
|
|
||||||
float GetEmulationSpeed();
|
|
||||||
float GetAverageFrameTime();
|
|
||||||
float GetMinimumFrameTime();
|
|
||||||
float GetMaximumFrameTime();
|
|
||||||
float GetThrottleFrequency();
|
|
||||||
float GetCPUThreadUsage();
|
|
||||||
float GetCPUThreadAverageTime();
|
|
||||||
float GetSWThreadUsage();
|
|
||||||
float GetSWThreadAverageTime();
|
|
||||||
float GetGPUUsage();
|
|
||||||
float GetGPUAverageTime();
|
|
||||||
const FrameTimeHistory& GetFrameTimeHistory();
|
|
||||||
u32 GetFrameTimeHistoryPos();
|
|
||||||
void FormatLatencyStats(SmallStringBase& str);
|
void FormatLatencyStats(SmallStringBase& str);
|
||||||
|
|
||||||
/// Loads global settings (i.e. EmuConfig).
|
/// Loads global settings (i.e. EmuConfig).
|
||||||
|
@ -292,7 +277,8 @@ float GetAudioNominalRate();
|
||||||
bool IsRunningAtNonStandardSpeed();
|
bool IsRunningAtNonStandardSpeed();
|
||||||
|
|
||||||
/// Adjusts the throttle frequency, i.e. how many times we should sleep per second.
|
/// Adjusts the throttle frequency, i.e. how many times we should sleep per second.
|
||||||
void SetThrottleFrequency(float frequency);
|
float GetVideoFrameRate();
|
||||||
|
void SetVideoFrameRate(float frequency);
|
||||||
|
|
||||||
// Access controllers for simulating input.
|
// Access controllers for simulating input.
|
||||||
Controller* GetController(u32 slot);
|
Controller* GetController(u32 slot);
|
||||||
|
@ -467,6 +453,9 @@ bool CPUThreadInitialize(Error* error);
|
||||||
/// Called on CPU thread shutdown.
|
/// Called on CPU thread shutdown.
|
||||||
void CPUThreadShutdown();
|
void CPUThreadShutdown();
|
||||||
|
|
||||||
|
/// Returns a handle to the CPU thread.
|
||||||
|
const Threading::ThreadHandle& GetCPUThreadHandle();
|
||||||
|
|
||||||
/// Polls input, updates subsystems which are present while paused/inactive.
|
/// Polls input, updates subsystems which are present while paused/inactive.
|
||||||
void IdlePollUpdate();
|
void IdlePollUpdate();
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
#include "core/host.h"
|
#include "core/host.h"
|
||||||
#include "core/imgui_overlays.h"
|
#include "core/imgui_overlays.h"
|
||||||
#include "core/memory_card.h"
|
#include "core/memory_card.h"
|
||||||
|
#include "core/performance_counters.h"
|
||||||
#include "core/spu.h"
|
#include "core/spu.h"
|
||||||
#include "core/system.h"
|
#include "core/system.h"
|
||||||
|
|
||||||
|
@ -2111,7 +2112,7 @@ void EmuThread::updatePerformanceCounters()
|
||||||
m_last_render_height = render_height;
|
m_last_render_height = render_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
const float gfps = System::GetFPS();
|
const float gfps = PerformanceCounters::GetFPS();
|
||||||
if (gfps != m_last_game_fps)
|
if (gfps != m_last_game_fps)
|
||||||
{
|
{
|
||||||
QMetaObject::invokeMethod(g_main_window->getStatusFPSWidget(), "setText", Qt::QueuedConnection,
|
QMetaObject::invokeMethod(g_main_window->getStatusFPSWidget(), "setText", Qt::QueuedConnection,
|
||||||
|
@ -2119,8 +2120,8 @@ void EmuThread::updatePerformanceCounters()
|
||||||
m_last_game_fps = gfps;
|
m_last_game_fps = gfps;
|
||||||
}
|
}
|
||||||
|
|
||||||
const float speed = System::GetEmulationSpeed();
|
const float speed = PerformanceCounters::GetEmulationSpeed();
|
||||||
const float vfps = System::GetVPS();
|
const float vfps = PerformanceCounters::GetVPS();
|
||||||
if (speed != m_last_speed || vfps != m_last_video_fps)
|
if (speed != m_last_speed || vfps != m_last_video_fps)
|
||||||
{
|
{
|
||||||
QMetaObject::invokeMethod(
|
QMetaObject::invokeMethod(
|
||||||
|
|
Loading…
Reference in New Issue