mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2026-05-09 04:13:28 -05:00
Merge fff0a19e08 into d19952cc11
This commit is contained in:
commit
1ede0bab78
|
|
@ -512,6 +512,9 @@ add_library(core
|
|||
NetworkCaptureLogger.h
|
||||
PatchEngine.cpp
|
||||
PatchEngine.h
|
||||
PerformanceSample.h
|
||||
PerformanceSampleAggregator.cpp
|
||||
PerformanceSampleAggregator.h
|
||||
PowerPC/BreakPoints.cpp
|
||||
PowerPC/BreakPoints.h
|
||||
PowerPC/CachedInterpreter/CachedInterpreter_Disassembler.cpp
|
||||
|
|
|
|||
|
|
@ -8,7 +8,6 @@
|
|||
#include <mutex>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
|
|
@ -17,10 +16,6 @@
|
|||
#include "Common/WindowsRegistry.h"
|
||||
#endif
|
||||
|
||||
#if defined(ANDROID)
|
||||
#include <functional>
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
#include "Common/CommonFuncs.h"
|
||||
#endif
|
||||
|
|
@ -31,7 +26,6 @@
|
|||
#include "Common/Config/Config.h"
|
||||
#include "Common/Crypto/SHA1.h"
|
||||
#include "Common/Random.h"
|
||||
#include "Common/Timer.h"
|
||||
#include "Common/Version.h"
|
||||
#include "Core/Config/GraphicsSettings.h"
|
||||
#include "Core/Config/MainSettings.h"
|
||||
|
|
@ -39,17 +33,14 @@
|
|||
#include "Core/HW/GCPad.h"
|
||||
#include "Core/Movie.h"
|
||||
#include "Core/NetPlayProto.h"
|
||||
|
||||
#include "Core/System.h"
|
||||
#include "InputCommon/GCAdapter.h"
|
||||
#include "InputCommon/InputConfig.h"
|
||||
|
||||
#include "VideoCommon/VideoBackendBase.h"
|
||||
#include "VideoCommon/VideoConfig.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr char ANALYTICS_ENDPOINT[] = "https://analytics.dolphin-emu.org/report";
|
||||
} // namespace
|
||||
|
||||
#if defined(ANDROID)
|
||||
static std::function<std::string(std::string)> s_get_val_func;
|
||||
void DolphinAnalytics::AndroidSetGetValFunc(std::function<std::string(std::string)> func)
|
||||
|
|
@ -58,6 +49,79 @@ void DolphinAnalytics::AndroidSetGetValFunc(std::function<std::string(std::strin
|
|||
}
|
||||
#endif
|
||||
|
||||
namespace
|
||||
{
|
||||
void AddVersionInformationToReportBuilder(Common::AnalyticsReportBuilder* builder)
|
||||
{
|
||||
builder->AddData("version-desc", Common::GetScmDescStr());
|
||||
builder->AddData("version-hash", Common::GetScmRevGitStr());
|
||||
builder->AddData("version-branch", Common::GetScmBranchStr());
|
||||
builder->AddData("version-dist", Common::GetScmDistributorStr());
|
||||
}
|
||||
|
||||
void AddAutoUpdateInformationToReportBuilder(Common::AnalyticsReportBuilder* builder)
|
||||
{
|
||||
builder->AddData("update-track", Config::Get(Config::MAIN_AUTOUPDATE_UPDATE_TRACK));
|
||||
}
|
||||
|
||||
void AddCPUInformationToReportBuilder(Common::AnalyticsReportBuilder* builder)
|
||||
{
|
||||
builder->AddData("cpu-summary", cpu_info.Summarize());
|
||||
}
|
||||
|
||||
#if defined(_WIN32)
|
||||
void AddWindowsInformationToReportBuilder(Common::AnalyticsReportBuilder* builder)
|
||||
{
|
||||
const auto winver = WindowsRegistry::GetOSVersion();
|
||||
builder->AddData("win-ver-major", static_cast<u32>(winver.dwMajorVersion));
|
||||
builder->AddData("win-ver-minor", static_cast<u32>(winver.dwMinorVersion));
|
||||
builder->AddData("win-ver-build", static_cast<u32>(winver.dwBuildNumber));
|
||||
}
|
||||
#elif defined(ANDROID)
|
||||
void AddAndroidInformationToReportBuilder(Common::AnalyticsReportBuilder* builder)
|
||||
{
|
||||
builder->AddData("android-manufacturer", s_get_val_func("DEVICE_MANUFACTURER"));
|
||||
builder->AddData("android-model", s_get_val_func("DEVICE_MODEL"));
|
||||
builder->AddData("android-version", s_get_val_func("DEVICE_OS"));
|
||||
}
|
||||
#elif defined(__APPLE__)
|
||||
void AddMacOSInformationToReportBuilder(Common::AnalyticsReportBuilder* builder)
|
||||
{
|
||||
Common::MacOSVersion version = Common::GetMacOSVersion();
|
||||
builder->AddData("osx-ver-major", version.major);
|
||||
builder->AddData("osx-ver-minor", version.minor);
|
||||
builder->AddData("osx-ver-bugfix", version.patch);
|
||||
}
|
||||
#endif
|
||||
|
||||
void AddPlatformInformationToReportBuilder(Common::AnalyticsReportBuilder* builder)
|
||||
{
|
||||
#if defined(_WIN32)
|
||||
builder->AddData("os-type", "windows");
|
||||
AddWindowsInformationToReportBuilder(builder);
|
||||
#elif defined(ANDROID)
|
||||
builder->AddData("os-type", "android");
|
||||
AddAndroidInformationToReportBuilder(builder);
|
||||
#elif defined(__APPLE__)
|
||||
builder->AddData("os-type", "osx");
|
||||
AddMacOSInformationToReportBuilder(builder);
|
||||
#elif defined(__linux__)
|
||||
builder->AddData("os-type", "linux");
|
||||
#elif defined(__FreeBSD__)
|
||||
builder->AddData("os-type", "freebsd");
|
||||
#elif defined(__OpenBSD__)
|
||||
builder->AddData("os-type", "openbsd");
|
||||
#elif defined(__NetBSD__)
|
||||
builder->AddData("os-type", "netbsd");
|
||||
#elif defined(__HAIKU__)
|
||||
builder->AddData("os-type", "haiku");
|
||||
#else
|
||||
builder->AddData("os-type", "unknown");
|
||||
#endif
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// Under arm64, we need to call objc_msgSend to receive a struct.
|
||||
DolphinAnalytics::DolphinAnalytics()
|
||||
{
|
||||
m_last_analytics_enabled = Config::Get(Config::MAIN_ANALYTICS_ENABLED);
|
||||
|
|
@ -88,13 +152,14 @@ DolphinAnalytics& DolphinAnalytics::Instance()
|
|||
|
||||
void DolphinAnalytics::ReloadConfig()
|
||||
{
|
||||
std::lock_guard lk{m_reporter_mutex};
|
||||
const std::lock_guard lk{m_reporter_mutex};
|
||||
|
||||
// Install the HTTP backend if analytics support is enabled.
|
||||
std::unique_ptr<Common::AnalyticsReportingBackend> new_backend;
|
||||
if (m_last_analytics_enabled)
|
||||
{
|
||||
new_backend = std::make_unique<Common::HttpAnalyticsBackend>(ANALYTICS_ENDPOINT);
|
||||
constexpr char analytics_endpoint[] = "https://analytics.dolphin-emu.org/report";
|
||||
new_backend = std::make_unique<Common::HttpAnalyticsBackend>(analytics_endpoint);
|
||||
}
|
||||
m_reporter.SetBackend(std::move(new_backend));
|
||||
|
||||
|
|
@ -150,7 +215,7 @@ void DolphinAnalytics::ReportGameStart()
|
|||
|
||||
// Reset per-game state.
|
||||
m_reported_quirks.fill(false);
|
||||
InitializePerformanceSampling();
|
||||
m_sample_aggregator.InitializePerformanceSampling();
|
||||
}
|
||||
|
||||
// Keep in sync with enum class GameQuirk definition.
|
||||
|
|
@ -194,7 +259,7 @@ static_assert(GAME_QUIRKS_NAMES.size() == static_cast<u32>(GameQuirk::Count),
|
|||
|
||||
void DolphinAnalytics::ReportGameQuirk(GameQuirk quirk)
|
||||
{
|
||||
u32 quirk_idx = static_cast<u32>(quirk);
|
||||
const u32 quirk_idx = static_cast<u32>(quirk);
|
||||
|
||||
// Only report once per run.
|
||||
if (m_reported_quirks[quirk_idx])
|
||||
|
|
@ -209,118 +274,34 @@ void DolphinAnalytics::ReportGameQuirk(GameQuirk quirk)
|
|||
|
||||
void DolphinAnalytics::ReportPerformanceInfo(PerformanceSample sample)
|
||||
{
|
||||
if (ShouldStartPerformanceSampling())
|
||||
m_sample_aggregator.AddSampleIfSamplingInProgress(sample);
|
||||
const std::optional<PerformanceSampleAggregator::CompletedReport> report_optional =
|
||||
m_sample_aggregator.PopReportIfComplete();
|
||||
if (!report_optional)
|
||||
{
|
||||
m_sampling_performance_info = true;
|
||||
return;
|
||||
}
|
||||
const PerformanceSampleAggregator::CompletedReport& report = *report_optional;
|
||||
|
||||
if (m_sampling_performance_info)
|
||||
{
|
||||
m_performance_samples.emplace_back(sample);
|
||||
}
|
||||
// The per game builder should already exist -- there is no way we can be reporting performance
|
||||
// info without a game start event having been generated.
|
||||
Common::AnalyticsReportBuilder builder(m_per_game_builder);
|
||||
builder.AddData("type", "performance");
|
||||
builder.AddData("speed", report.speed);
|
||||
builder.AddData("prims", report.primitives);
|
||||
builder.AddData("draw-calls", report.draw_calls);
|
||||
|
||||
if (m_performance_samples.size() >= NUM_PERFORMANCE_SAMPLES_PER_REPORT)
|
||||
{
|
||||
std::vector<u32> speed_times_1000(m_performance_samples.size());
|
||||
std::vector<u32> num_prims(m_performance_samples.size());
|
||||
std::vector<u32> num_draw_calls(m_performance_samples.size());
|
||||
for (size_t i = 0; i < m_performance_samples.size(); ++i)
|
||||
{
|
||||
speed_times_1000[i] = static_cast<u32>(m_performance_samples[i].speed_ratio * 1000);
|
||||
num_prims[i] = m_performance_samples[i].num_prims;
|
||||
num_draw_calls[i] = m_performance_samples[i].num_draw_calls;
|
||||
}
|
||||
|
||||
// The per game builder should already exist -- there is no way we can be reporting performance
|
||||
// info without a game start event having been generated.
|
||||
Common::AnalyticsReportBuilder builder(m_per_game_builder);
|
||||
builder.AddData("type", "performance");
|
||||
builder.AddData("speed", speed_times_1000);
|
||||
builder.AddData("prims", num_prims);
|
||||
builder.AddData("draw-calls", num_draw_calls);
|
||||
|
||||
Send(builder);
|
||||
|
||||
// Clear up and stop sampling until next time ShouldStartPerformanceSampling() says so.
|
||||
m_performance_samples.clear();
|
||||
m_sampling_performance_info = false;
|
||||
}
|
||||
}
|
||||
|
||||
void DolphinAnalytics::InitializePerformanceSampling()
|
||||
{
|
||||
m_performance_samples.clear();
|
||||
m_sampling_performance_info = false;
|
||||
|
||||
u64 wait_us =
|
||||
PERFORMANCE_SAMPLING_INITIAL_WAIT_TIME_SECS * 1000000 +
|
||||
Common::Random::GenerateValue<u64>() % (PERFORMANCE_SAMPLING_WAIT_TIME_JITTER_SECS * 1000000);
|
||||
m_sampling_next_start_us = Common::Timer::NowUs() + wait_us;
|
||||
}
|
||||
|
||||
bool DolphinAnalytics::ShouldStartPerformanceSampling()
|
||||
{
|
||||
if (Common::Timer::NowUs() < m_sampling_next_start_us)
|
||||
return false;
|
||||
|
||||
u64 wait_us =
|
||||
PERFORMANCE_SAMPLING_INTERVAL_SECS * 1000000 +
|
||||
Common::Random::GenerateValue<u64>() % (PERFORMANCE_SAMPLING_WAIT_TIME_JITTER_SECS * 1000000);
|
||||
m_sampling_next_start_us = Common::Timer::NowUs() + wait_us;
|
||||
return true;
|
||||
Send(builder);
|
||||
}
|
||||
|
||||
void DolphinAnalytics::MakeBaseBuilder()
|
||||
{
|
||||
Common::AnalyticsReportBuilder builder;
|
||||
m_base_builder = Common::AnalyticsReportBuilder();
|
||||
|
||||
// Version information.
|
||||
builder.AddData("version-desc", Common::GetScmDescStr());
|
||||
builder.AddData("version-hash", Common::GetScmRevGitStr());
|
||||
builder.AddData("version-branch", Common::GetScmBranchStr());
|
||||
builder.AddData("version-dist", Common::GetScmDistributorStr());
|
||||
|
||||
// Auto-Update information.
|
||||
builder.AddData("update-track", Config::Get(Config::MAIN_AUTOUPDATE_UPDATE_TRACK));
|
||||
|
||||
// CPU information.
|
||||
builder.AddData("cpu-summary", cpu_info.Summarize());
|
||||
|
||||
// OS information.
|
||||
#if defined(_WIN32)
|
||||
builder.AddData("os-type", "windows");
|
||||
|
||||
const auto winver = WindowsRegistry::GetOSVersion();
|
||||
builder.AddData("win-ver-major", static_cast<u32>(winver.dwMajorVersion));
|
||||
builder.AddData("win-ver-minor", static_cast<u32>(winver.dwMinorVersion));
|
||||
builder.AddData("win-ver-build", static_cast<u32>(winver.dwBuildNumber));
|
||||
#elif defined(ANDROID)
|
||||
builder.AddData("os-type", "android");
|
||||
builder.AddData("android-manufacturer", s_get_val_func("DEVICE_MANUFACTURER"));
|
||||
builder.AddData("android-model", s_get_val_func("DEVICE_MODEL"));
|
||||
builder.AddData("android-version", s_get_val_func("DEVICE_OS"));
|
||||
#elif defined(__APPLE__)
|
||||
builder.AddData("os-type", "osx");
|
||||
|
||||
Common::MacOSVersion version = Common::GetMacOSVersion();
|
||||
builder.AddData("osx-ver-major", version.major);
|
||||
builder.AddData("osx-ver-minor", version.minor);
|
||||
builder.AddData("osx-ver-bugfix", version.patch);
|
||||
#elif defined(__linux__)
|
||||
builder.AddData("os-type", "linux");
|
||||
#elif defined(__FreeBSD__)
|
||||
builder.AddData("os-type", "freebsd");
|
||||
#elif defined(__OpenBSD__)
|
||||
builder.AddData("os-type", "openbsd");
|
||||
#elif defined(__NetBSD__)
|
||||
builder.AddData("os-type", "netbsd");
|
||||
#elif defined(__HAIKU__)
|
||||
builder.AddData("os-type", "haiku");
|
||||
#else
|
||||
builder.AddData("os-type", "unknown");
|
||||
#endif
|
||||
|
||||
m_base_builder = builder;
|
||||
AddVersionInformationToReportBuilder(&m_base_builder);
|
||||
AddAutoUpdateInformationToReportBuilder(&m_base_builder);
|
||||
AddCPUInformationToReportBuilder(&m_base_builder);
|
||||
AddPlatformInformationToReportBuilder(&m_base_builder);
|
||||
}
|
||||
|
||||
static const char* GetShaderCompilationMode()
|
||||
|
|
@ -347,12 +328,13 @@ static bool UseVertexRounding()
|
|||
void DolphinAnalytics::MakePerGameBuilder()
|
||||
{
|
||||
Common::AnalyticsReportBuilder builder(m_base_builder);
|
||||
const SConfig& config = SConfig::GetInstance();
|
||||
|
||||
// Gameid.
|
||||
builder.AddData("gameid", SConfig::GetInstance().GetGameID());
|
||||
builder.AddData("gameid", config.GetGameID());
|
||||
|
||||
// Unique id bound to the gameid.
|
||||
builder.AddData("id", MakeUniqueId(SConfig::GetInstance().GetGameID()));
|
||||
builder.AddData("id", MakeUniqueId(config.GetGameID()));
|
||||
|
||||
// Configuration.
|
||||
builder.AddData("cfg-dsp-hle", Config::Get(Config::MAIN_DSP_HLE));
|
||||
|
|
|
|||
|
|
@ -7,12 +7,13 @@
|
|||
#include <mutex>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <vector>
|
||||
|
||||
#include "Common/Analytics.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/Config/Config.h"
|
||||
|
||||
#include "Core/PerformanceSample.h"
|
||||
#include "Core/PerformanceSampleAggregator.h"
|
||||
|
||||
#if defined(ANDROID)
|
||||
#include <functional>
|
||||
#endif
|
||||
|
|
@ -138,14 +139,12 @@ public:
|
|||
// Get the base builder for building a report
|
||||
const Common::AnalyticsReportBuilder& BaseBuilder() const { return m_base_builder; }
|
||||
|
||||
struct PerformanceSample
|
||||
{
|
||||
double speed_ratio; // See SystemTimers::GetEstimatedEmulationPerformance().
|
||||
int num_prims;
|
||||
int num_draw_calls;
|
||||
};
|
||||
// Reports performance information. This method performs its own throttling / aggregation --
|
||||
// calling it does not guarantee when a report will actually be sent.
|
||||
// Performance reports are generated using data from 100 consecutive frames.
|
||||
// Report starting times are randomized to obtain a wider range of sample data.
|
||||
// The first report begins 5-8 minutes after a game is launched.
|
||||
// Successive reports begin 30-33 minutes after the previous report finishes.
|
||||
//
|
||||
// This method is NOT thread-safe.
|
||||
void ReportPerformanceInfo(PerformanceSample sample);
|
||||
|
|
@ -173,21 +172,7 @@ private:
|
|||
// values created by MakeUniqueId.
|
||||
std::string m_unique_id;
|
||||
|
||||
// Performance sampling configuration constants.
|
||||
//
|
||||
// 5min after startup + rand(0, 3min) jitter time, collect performance for 100 frames in a row.
|
||||
// Repeat collection after 30min + rand(0, 3min).
|
||||
static constexpr int NUM_PERFORMANCE_SAMPLES_PER_REPORT = 100;
|
||||
static constexpr int PERFORMANCE_SAMPLING_INITIAL_WAIT_TIME_SECS = 300;
|
||||
static constexpr int PERFORMANCE_SAMPLING_WAIT_TIME_JITTER_SECS = 180;
|
||||
static constexpr int PERFORMANCE_SAMPLING_INTERVAL_SECS = 1800;
|
||||
|
||||
// Performance sampling state & internal helpers.
|
||||
void InitializePerformanceSampling(); // Called on game start / title switch.
|
||||
bool ShouldStartPerformanceSampling();
|
||||
u64 m_sampling_next_start_us; // Next timestamp (in us) at which to trigger sampling.
|
||||
bool m_sampling_performance_info = false; // Whether we are currently collecting samples.
|
||||
std::vector<PerformanceSample> m_performance_samples;
|
||||
PerformanceSampleAggregator m_sample_aggregator;
|
||||
|
||||
// What quirks have already been reported about the current game.
|
||||
std::array<bool, static_cast<size_t>(GameQuirk::Count)> m_reported_quirks;
|
||||
|
|
|
|||
12
Source/Core/Core/PerformanceSample.h
Normal file
12
Source/Core/Core/PerformanceSample.h
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
// Copyright 2021 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
struct PerformanceSample
|
||||
{
|
||||
double speed_ratio; // See SystemTimers::GetEstimatedEmulationPerformance().
|
||||
int num_prims;
|
||||
int num_draw_calls;
|
||||
};
|
||||
105
Source/Core/Core/PerformanceSampleAggregator.cpp
Normal file
105
Source/Core/Core/PerformanceSampleAggregator.cpp
Normal file
|
|
@ -0,0 +1,105 @@
|
|||
// Copyright 2021 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "Core/PerformanceSampleAggregator.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include "Common/Random.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr size_t s_samples_per_report = 100;
|
||||
|
||||
std::chrono::microseconds GetCurrentMicroseconds()
|
||||
{
|
||||
const std::chrono::high_resolution_clock::duration time_since_epoch =
|
||||
std::chrono::high_resolution_clock::now().time_since_epoch();
|
||||
return std::chrono::duration_cast<std::chrono::microseconds>(time_since_epoch);
|
||||
}
|
||||
|
||||
std::chrono::microseconds GetSamplingStartTimeJitter()
|
||||
{
|
||||
constexpr long long max_delay = std::chrono::microseconds(std::chrono::minutes(3)).count();
|
||||
return std::chrono::microseconds(Common::Random::GenerateValue<u64>() % max_delay);
|
||||
}
|
||||
|
||||
std::chrono::microseconds
|
||||
GetSamplingStartTimestampUsingBaseDelay(const std::chrono::microseconds base_delay)
|
||||
{
|
||||
const std::chrono::microseconds now = GetCurrentMicroseconds();
|
||||
const std::chrono::microseconds jitter = GetSamplingStartTimeJitter();
|
||||
const std::chrono::microseconds sampling_start_timestamp = now + base_delay + jitter;
|
||||
return sampling_start_timestamp;
|
||||
}
|
||||
|
||||
std::chrono::microseconds GetInitialSamplingStartTimestamp()
|
||||
{
|
||||
constexpr std::chrono::microseconds base_initial_delay = std::chrono::minutes(5);
|
||||
return GetSamplingStartTimestampUsingBaseDelay(base_initial_delay);
|
||||
}
|
||||
|
||||
std::chrono::microseconds GetRepeatSamplingStartTimestamp()
|
||||
{
|
||||
constexpr std::chrono::microseconds base_repeat_delay = std::chrono::minutes(30);
|
||||
return GetSamplingStartTimestampUsingBaseDelay(base_repeat_delay);
|
||||
}
|
||||
|
||||
PerformanceSampleAggregator::CompletedReport
|
||||
GetCompletedReport(const std::vector<PerformanceSample>& samples)
|
||||
{
|
||||
PerformanceSampleAggregator::CompletedReport report;
|
||||
const size_t num_samples = samples.size();
|
||||
report.speed.resize(num_samples);
|
||||
report.primitives.resize(num_samples);
|
||||
report.draw_calls.resize(num_samples);
|
||||
|
||||
for (size_t i = 0; i < num_samples; ++i)
|
||||
{
|
||||
const PerformanceSample& sample = samples[i];
|
||||
report.speed[i] = static_cast<u32>(sample.speed_ratio * 1'000);
|
||||
report.primitives[i] = sample.num_prims;
|
||||
report.draw_calls[i] = sample.num_draw_calls;
|
||||
}
|
||||
return report;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
PerformanceSampleAggregator::PerformanceSampleAggregator()
|
||||
: m_samples(std::vector<PerformanceSample>(s_samples_per_report)),
|
||||
m_next_starting_timestamp(std::numeric_limits<std::chrono::microseconds>::max())
|
||||
{
|
||||
}
|
||||
|
||||
void PerformanceSampleAggregator::InitializePerformanceSampling()
|
||||
{
|
||||
m_samples.clear();
|
||||
m_next_starting_timestamp = GetInitialSamplingStartTimestamp();
|
||||
}
|
||||
|
||||
void PerformanceSampleAggregator::ResetPerformanceSampling()
|
||||
{
|
||||
m_samples.clear();
|
||||
m_next_starting_timestamp = GetRepeatSamplingStartTimestamp();
|
||||
}
|
||||
|
||||
void PerformanceSampleAggregator::AddSampleIfSamplingInProgress(PerformanceSample&& sample)
|
||||
{
|
||||
if (GetCurrentMicroseconds() >= m_next_starting_timestamp)
|
||||
{
|
||||
m_samples.push_back(sample);
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<PerformanceSampleAggregator::CompletedReport>
|
||||
PerformanceSampleAggregator::PopReportIfComplete()
|
||||
{
|
||||
if (m_samples.size() < s_samples_per_report)
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
const CompletedReport report = GetCompletedReport(m_samples);
|
||||
ResetPerformanceSampling();
|
||||
return report;
|
||||
}
|
||||
38
Source/Core/Core/PerformanceSampleAggregator.h
Normal file
38
Source/Core/Core/PerformanceSampleAggregator.h
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
// Copyright 2021 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <chrono>
|
||||
#include <optional>
|
||||
#include <vector>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
#include "Core/PerformanceSample.h"
|
||||
|
||||
class PerformanceSampleAggregator
|
||||
{
|
||||
public:
|
||||
PerformanceSampleAggregator();
|
||||
|
||||
struct CompletedReport
|
||||
{
|
||||
std::vector<u32> speed;
|
||||
std::vector<u32> primitives;
|
||||
std::vector<u32> draw_calls;
|
||||
};
|
||||
|
||||
// Called on game start / title switch.
|
||||
void InitializePerformanceSampling();
|
||||
void AddSampleIfSamplingInProgress(PerformanceSample&& sample);
|
||||
std::optional<CompletedReport> PopReportIfComplete();
|
||||
|
||||
private:
|
||||
// Called after sampling report is completed
|
||||
void ResetPerformanceSampling();
|
||||
|
||||
std::vector<PerformanceSample> m_samples;
|
||||
std::chrono::microseconds m_next_starting_timestamp;
|
||||
};
|
||||
|
|
@ -459,6 +459,8 @@
|
|||
<ClInclude Include="Core\NetPlayServer.h" />
|
||||
<ClInclude Include="Core\NetworkCaptureLogger.h" />
|
||||
<ClInclude Include="Core\PatchEngine.h" />
|
||||
<ClInclude Include="Core\PerformanceSample.h" />
|
||||
<ClInclude Include="Core\PerformanceSampleAggregator.h" />
|
||||
<ClInclude Include="Core\PowerPC\BreakPoints.h" />
|
||||
<ClInclude Include="Core\PowerPC\CachedInterpreter\CachedInterpreter.h" />
|
||||
<ClInclude Include="Core\PowerPC\CachedInterpreter\CachedInterpreterBlockCache.h" />
|
||||
|
|
@ -1164,6 +1166,7 @@
|
|||
<ClCompile Include="Core\NetPlayServer.cpp" />
|
||||
<ClCompile Include="Core\NetworkCaptureLogger.cpp" />
|
||||
<ClCompile Include="Core\PatchEngine.cpp" />
|
||||
<ClCompile Include="Core\PerformanceSampleAggregator.cpp" />
|
||||
<ClCompile Include="Core\PowerPC\BreakPoints.cpp" />
|
||||
<ClCompile Include="Core\PowerPC\CachedInterpreter\CachedInterpreter_Disassembler.cpp" />
|
||||
<ClCompile Include="Core\PowerPC\CachedInterpreter\CachedInterpreter.cpp" />
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user