From 013c162cf14749f71d85a295eb1aca688732ade0 Mon Sep 17 00:00:00 2001 From: Dentomologist Date: Sun, 24 Jan 2021 19:42:53 -0800 Subject: [PATCH 01/13] DolphinAnalytics: Remove redundant #include STL header was included from both Analytics.h and Analytics.cpp on Android. --- Source/Core/Core/DolphinAnalytics.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/Core/Core/DolphinAnalytics.cpp b/Source/Core/Core/DolphinAnalytics.cpp index 3551321e6f..9dd8508e16 100644 --- a/Source/Core/Core/DolphinAnalytics.cpp +++ b/Source/Core/Core/DolphinAnalytics.cpp @@ -17,7 +17,6 @@ #elif defined(__APPLE__) #include #elif defined(ANDROID) -#include #include "Common/AndroidAnalytics.h" #endif From ca10f2fdf1288fcae66ec326bbbe7a2f2ead5e77 Mon Sep 17 00:00:00 2001 From: Dentomologist Date: Mon, 25 Jan 2021 09:25:02 -0800 Subject: [PATCH 02/13] DolphinAnalytics: Refactor variable declaration Move endpoint declaration from anonymous namespace to the only function it's used in. --- Source/Core/Core/DolphinAnalytics.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Core/Core/DolphinAnalytics.cpp b/Source/Core/Core/DolphinAnalytics.cpp index 9dd8508e16..8cd45520c1 100644 --- a/Source/Core/Core/DolphinAnalytics.cpp +++ b/Source/Core/Core/DolphinAnalytics.cpp @@ -42,7 +42,6 @@ namespace { -constexpr char ANALYTICS_ENDPOINT[] = "https://analytics.dolphin-emu.org/report"; } // namespace #if defined(ANDROID) @@ -73,10 +72,11 @@ void DolphinAnalytics::ReloadConfig() std::unique_ptr new_backend; if (Config::Get(Config::MAIN_ANALYTICS_ENABLED)) { + constexpr char analytics_endpoint[] = "https://analytics.dolphin-emu.org/report"; #if defined(ANDROID) - new_backend = std::make_unique(ANALYTICS_ENDPOINT); + new_backend = std::make_unique(analytics_endpoint); #else - new_backend = std::make_unique(ANALYTICS_ENDPOINT); + new_backend = std::make_unique(analytics_endpoint); #endif } m_reporter.SetBackend(std::move(new_backend)); From 7208b64a942f2e7ede9c6c986d5a6f49d6151d86 Mon Sep 17 00:00:00 2001 From: Dentomologist Date: Mon, 25 Jan 2021 11:36:21 -0800 Subject: [PATCH 03/13] DolphinAnalytics: Extract ReportBuilder functions --- Source/Core/Core/DolphinAnalytics.cpp | 173 +++++++++++++++----------- 1 file changed, 99 insertions(+), 74 deletions(-) diff --git a/Source/Core/Core/DolphinAnalytics.cpp b/Source/Core/Core/DolphinAnalytics.cpp index 8cd45520c1..f72e498980 100644 --- a/Source/Core/Core/DolphinAnalytics.cpp +++ b/Source/Core/Core/DolphinAnalytics.cpp @@ -40,10 +40,6 @@ #include "VideoCommon/VideoBackendBase.h" #include "VideoCommon/VideoConfig.h" -namespace -{ -} // namespace - #if defined(ANDROID) static std::function s_get_val_func; void DolphinAnalytics::AndroidSetGetValFunc(std::function func) @@ -52,6 +48,100 @@ void DolphinAnalytics::AndroidSetGetValFunc(std::functionAddData("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(winver.dwMajorVersion)); + builder->AddData("win-ver-minor", static_cast(winver.dwMinorVersion)); + builder->AddData("win-ver-build", static_cast(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) +{ + // id processInfo = [NSProcessInfo processInfo] + id processInfo = reinterpret_cast(objc_msgSend)( + objc_getClass("NSProcessInfo"), sel_getUid("processInfo")); + if (processInfo) + { + struct OSVersion // NSOperatingSystemVersion + { + s64 major_version; // NSInteger majorVersion + s64 minor_version; // NSInteger minorVersion + s64 patch_version; // NSInteger patchVersion + }; + // On x86_64, we need to explicitly call objc_msgSend_stret for a struct. +#ifdef _M_ARM_64 +#define msgSend objc_msgSend +#else +#define msgSend objc_msgSend_stret +#endif + // NSOperatingSystemVersion version = [processInfo operatingSystemVersion] + OSVersion version = reinterpret_cast(msgSend)( + processInfo, sel_getUid("operatingSystemVersion")); +#undef msgSend + builder->AddData("osx-ver-major", version.major_version); + builder->AddData("osx-ver-minor", version.minor_version); + builder->AddData("osx-ver-bugfix", version.patch_version); + } +} +#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() { ReloadConfig(); @@ -255,77 +345,12 @@ bool DolphinAnalytics::ShouldStartPerformanceSampling() 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(winver.dwMajorVersion)); - builder.AddData("win-ver-minor", static_cast(winver.dwMinorVersion)); - builder.AddData("win-ver-build", static_cast(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"); - - // id processInfo = [NSProcessInfo processInfo] - id processInfo = reinterpret_cast(objc_msgSend)( - objc_getClass("NSProcessInfo"), sel_getUid("processInfo")); - if (processInfo) - { - struct OSVersion // NSOperatingSystemVersion - { - s64 major_version; // NSInteger majorVersion - s64 minor_version; // NSInteger minorVersion - s64 patch_version; // NSInteger patchVersion - }; - // Under arm64, we need to call objc_msgSend to receive a struct. - // On x86_64, we need to explicitly call objc_msgSend_stret for a struct. -#ifdef _M_ARM_64 -#define msgSend objc_msgSend -#else -#define msgSend objc_msgSend_stret -#endif - // NSOperatingSystemVersion version = [processInfo operatingSystemVersion] - OSVersion version = reinterpret_cast(msgSend)( - processInfo, sel_getUid("operatingSystemVersion")); -#undef msgSend - builder.AddData("osx-ver-major", version.major_version); - builder.AddData("osx-ver-minor", version.minor_version); - builder.AddData("osx-ver-bugfix", version.patch_version); - } -#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(const VideoConfig& video_config) From e3de3ada0502f72616a0af84db7931fc3dd7ce61 Mon Sep 17 00:00:00 2001 From: Dentomologist Date: Mon, 25 Jan 2021 12:03:04 -0800 Subject: [PATCH 04/13] DolphinAnalytics: Make assorted variables const --- Source/Core/Core/DolphinAnalytics.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/Core/Core/DolphinAnalytics.cpp b/Source/Core/Core/DolphinAnalytics.cpp index f72e498980..3f0f097a06 100644 --- a/Source/Core/Core/DolphinAnalytics.cpp +++ b/Source/Core/Core/DolphinAnalytics.cpp @@ -156,7 +156,7 @@ 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 new_backend; @@ -267,7 +267,7 @@ static_assert(GAME_QUIRKS_NAMES.size() == static_cast(GameQuirk::COUNT), void DolphinAnalytics::ReportGameQuirk(GameQuirk quirk) { - u32 quirk_idx = static_cast(quirk); + const u32 quirk_idx = static_cast(quirk); // Only report once per run. if (m_reported_quirks[quirk_idx]) @@ -325,7 +325,7 @@ void DolphinAnalytics::InitializePerformanceSampling() m_performance_samples.clear(); m_sampling_performance_info = false; - u64 wait_us = + const u64 wait_us = PERFORMANCE_SAMPLING_INITIAL_WAIT_TIME_SECS * 1000000 + Common::Random::GenerateValue() % (PERFORMANCE_SAMPLING_WAIT_TIME_JITTER_SECS * 1000000); m_sampling_next_start_us = Common::Timer::NowUs() + wait_us; @@ -336,7 +336,7 @@ bool DolphinAnalytics::ShouldStartPerformanceSampling() if (Common::Timer::NowUs() < m_sampling_next_start_us) return false; - u64 wait_us = + const u64 wait_us = PERFORMANCE_SAMPLING_INTERVAL_SECS * 1000000 + Common::Random::GenerateValue() % (PERFORMANCE_SAMPLING_WAIT_TIME_JITTER_SECS * 1000000); m_sampling_next_start_us = Common::Timer::NowUs() + wait_us; From d3fc0c89e4e448252ef875c66cba2c4092b82127 Mon Sep 17 00:00:00 2001 From: Dentomologist Date: Mon, 25 Jan 2021 12:09:28 -0800 Subject: [PATCH 05/13] DolphinAnalytics: Refactor redundant data accesses --- Source/Core/Core/DolphinAnalytics.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Source/Core/Core/DolphinAnalytics.cpp b/Source/Core/Core/DolphinAnalytics.cpp index 3f0f097a06..8b5f9e8695 100644 --- a/Source/Core/Core/DolphinAnalytics.cpp +++ b/Source/Core/Core/DolphinAnalytics.cpp @@ -372,12 +372,13 @@ static const char* GetShaderCompilationMode(const VideoConfig& video_config) 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)); From 6b8533d012e45e44a8422523e9e7934cb4f1781c Mon Sep 17 00:00:00 2001 From: Dentomologist Date: Mon, 25 Jan 2021 12:11:56 -0800 Subject: [PATCH 06/13] DolphinAnalytics: Reformat comments --- Source/Core/Core/DolphinAnalytics.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Core/Core/DolphinAnalytics.h b/Source/Core/Core/DolphinAnalytics.h index 8fc23161a8..b7d0439406 100644 --- a/Source/Core/Core/DolphinAnalytics.h +++ b/Source/Core/Core/DolphinAnalytics.h @@ -181,7 +181,7 @@ private: // 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. + 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 m_performance_samples; From b4eee80103c753a61c1e7a5e03eaa55120f49e3f Mon Sep 17 00:00:00 2001 From: Dentomologist Date: Tue, 26 Jan 2021 23:16:07 -0800 Subject: [PATCH 07/13] DolphinAnalytics: Make GameQuirk members TitleCase # Conflicts: # Source/Core/Core/DolphinAnalytics.cpp --- Source/Core/Core/DolphinAnalytics.cpp | 4 +- Source/Core/Core/DolphinAnalytics.h | 70 +++++++++---------- Source/Core/Core/HW/DSPHLE/UCodes/AX.cpp | 2 +- Source/Core/Core/HW/DSPHLE/UCodes/AXVoice.h | 6 +- Source/Core/Core/HW/DVD/DVDInterface.cpp | 12 ++-- Source/Core/Core/IOS/DI/DI.cpp | 32 ++++----- Source/Core/Core/IOS/Network/WD/Command.cpp | 4 +- Source/Core/VideoCommon/BPStructs.cpp | 2 +- Source/Core/VideoCommon/CPMemory.cpp | 18 ++--- .../Core/VideoCommon/VertexLoaderManager.cpp | 19 +++-- Source/Core/VideoCommon/VertexManagerBase.cpp | 6 +- Source/Core/VideoCommon/VideoBackendBase.cpp | 2 +- Source/Core/VideoCommon/XFStructs.cpp | 10 +-- 13 files changed, 91 insertions(+), 96 deletions(-) diff --git a/Source/Core/Core/DolphinAnalytics.cpp b/Source/Core/Core/DolphinAnalytics.cpp index 8b5f9e8695..a857a074c1 100644 --- a/Source/Core/Core/DolphinAnalytics.cpp +++ b/Source/Core/Core/DolphinAnalytics.cpp @@ -141,7 +141,7 @@ void AddPlatformInformationToReportBuilder(Common::AnalyticsReportBuilder* build } } // namespace - // Under arm64, we need to call objc_msgSend to receive a struct. +// Under arm64, we need to call objc_msgSend to receive a struct. DolphinAnalytics::DolphinAnalytics() { ReloadConfig(); @@ -262,7 +262,7 @@ constexpr std::array GAME_QUIRKS_NAMES{ "invalid-texture-coordinate-component-format", "invalid-color-component-format", }; -static_assert(GAME_QUIRKS_NAMES.size() == static_cast(GameQuirk::COUNT), +static_assert(GAME_QUIRKS_NAMES.size() == static_cast(GameQuirk::Count), "Game quirks names and enum definition are out of sync."); void DolphinAnalytics::ReportGameQuirk(GameQuirk quirk) diff --git a/Source/Core/Core/DolphinAnalytics.h b/Source/Core/Core/DolphinAnalytics.h index b7d0439406..75bd8d9f88 100644 --- a/Source/Core/Core/DolphinAnalytics.h +++ b/Source/Core/Core/DolphinAnalytics.h @@ -21,86 +21,86 @@ enum class GameQuirk { // Several Wii DI commands that are rarely/never used and not implemented by Dolphin - USES_DVD_LOW_STOP_LASER, - USES_DVD_LOW_OFFSET, - USES_DVD_LOW_READ_DISK_BCA, // NSMBW known to use this - USES_DVD_LOW_REQUEST_DISC_STATUS, - USES_DVD_LOW_REQUEST_RETRY_NUMBER, - USES_DVD_LOW_SER_MEAS_CONTROL, + UsesDVDLowStopLaser, + UsesDVDLowOffset, + UsesDVDLowReadDiskBCA, // NSMBW known to use this + UsesDVDLowRequestDiscStatus, + UsesDVDLowRequestRetryNumber, + UsesDVDLowSerMeasControl, // Dolphin only implements the simple DVDLowOpenPartition, not any of the variants where some // already-read data is provided - USES_DIFFERENT_PARTITION_COMMAND, + UsesDifferentPartitionCommand, // IOS has implementations for ioctls 0x85 and 0x89 and a stub for 0x87, but // DVDLowMaskCoverInterrupt/DVDLowUnmaskCoverInterrupt/DVDLowUnmaskStatusInterrupts // are all stubbed on the PPC side so they presumably will never be used. // (DVDLowClearCoverInterrupt is used, though) - USES_DI_INTERRUPT_MASK_COMMAND, + UsesDIInterruptMaskCommand, // Some games configure a mismatched number of texture coordinates or colors between the transform // and TEV/BP stages of the rendering pipeline. Currently, Dolphin just skips over these objects // as the hardware renderers are not equipped to handle the case where the registers between // stages are mismatched. - MISMATCHED_GPU_TEXGENS_BETWEEN_XF_AND_BP, - MISMATCHED_GPU_COLORS_BETWEEN_XF_AND_BP, + MismatchedGPUTexgensBetweenXFAndBP, + MismatchedGPUColorsBetweenXFAndBP, // The WD module can be configured to operate in six different modes. // In practice, only mode 1 (DS communications) and mode 3 (AOSS access point scanning) // are used by games and the system menu respectively. - USES_UNCOMMON_WD_MODE, + UsesUncommonWDMode, - USES_WD_UNIMPLEMENTED_IOCTL, + UsesWDUnimplementedIoctl, // Some games use invalid/unknown graphics commands (see e.g. bug 10931). // These are different from unknown opcodes: it is known that a BP/CP/XF command is being used, // but the command itself is not understood. - USES_UNKNOWN_BP_COMMAND, - USES_UNKNOWN_CP_COMMAND, - USES_UNKNOWN_XF_COMMAND, + UsesUnknownBPCommand, + UsesUnknownCPCommand, + UsesUnknownXFCommand, // YAGCD and Dolphin's implementation disagree about what is valid in some cases - USES_MAYBE_INVALID_CP_COMMAND, + UsesMaybeInvalidCPCommand, // These commands are used by a few games (e.g. bug 12461), and seem to relate to perf queries. // Track them separately. - USES_CP_PERF_COMMAND, + UsesCPPerfCommand, // We don't implement all AX features yet. - USES_UNIMPLEMENTED_AX_COMMAND, - USES_AX_INITIAL_TIME_DELAY, - USES_AX_WIIMOTE_LOWPASS, - USES_AX_WIIMOTE_BIQUAD, + UsesUnimplementedAXCommand, + UsesAXInitialTimeDelay, + UsesAXWiimoteLowpass, + UsesAXWiimoteBiquad, // We don't implement XFMEM_CLIPDISABLE yet. - SETS_XF_CLIPDISABLE_BIT_0, - SETS_XF_CLIPDISABLE_BIT_1, - SETS_XF_CLIPDISABLE_BIT_2, + SetsXFClipdisableBit0, + SetsXFClipdisableBit1, + SetsXFClipdisableBit2, // Similar to the XF-BP mismatch, CP and XF might be configured with different vertex formats. // Real hardware seems to hang in this case, so games probably don't do this, but it would // be good to know if anything does it. - MISMATCHED_GPU_COLORS_BETWEEN_CP_AND_XF, - MISMATCHED_GPU_NORMALS_BETWEEN_CP_AND_XF, - MISMATCHED_GPU_TEX_COORDS_BETWEEN_CP_AND_XF, + MismatchedGPUColorsBetweenCPAndXF, + MismatchedGPUNormalsBetweenCPAndXF, + MismatchedGPUTexCoordsBetweenCPAndXF, // Both CP and XF have normally-identical matrix index information. We currently always // use the CP one in the hardware renderers and the XF one in the software renderer, // but testing is needed to find out which of these is actually used for what. - MISMATCHED_GPU_MATRIX_INDICES_BETWEEN_CP_AND_XF, + MismatchedGPUMatrixIndicesBetweenCPAndXF, // Only a few games use the Bounding Box feature. Note that every game initializes the bounding // box registers (using BPMEM_CLEARBBOX1/BPMEM_CLEARBBOX2) on startup, as part of the SDK, but // only a few read them (from PE_BBOX_LEFT etc.) - READS_BOUNDING_BOX, + ReadsBoundingBox, // A few games use invalid vertex component formats, but the two known cases (Fifa Street and // Def Jam: Fight for New York, see https://bugs.dolphin-emu.org/issues/12719) only use invalid // normal formats and lighting is disabled in those cases, so it doesn't end up mattering. // It's possible other games use invalid formats, possibly on other vertex components. - INVALID_POSITION_COMPONENT_FORMAT, - INVALID_NORMAL_COMPONENT_FORMAT, - INVALID_TEXTURE_COORDINATE_COMPONENT_FORMAT, - INVALID_COLOR_COMPONENT_FORMAT, + InvalidPositionComponentFormat, + InvalidNormalComponentFormat, + InvalidTextureCoordinateComponentFormat, + InvalidColorComponentFormat, - COUNT, + Count, }; class DolphinAnalytics @@ -186,7 +186,7 @@ private: std::vector m_performance_samples; // What quirks have already been reported about the current game. - std::array(GameQuirk::COUNT)> m_reported_quirks; + std::array(GameQuirk::Count)> m_reported_quirks; // Builder that contains all non variable data that should be sent with all // reports. diff --git a/Source/Core/Core/HW/DSPHLE/UCodes/AX.cpp b/Source/Core/Core/HW/DSPHLE/UCodes/AX.cpp index f82abf5d23..6beeace583 100644 --- a/Source/Core/Core/HW/DSPHLE/UCodes/AX.cpp +++ b/Source/Core/Core/HW/DSPHLE/UCodes/AX.cpp @@ -180,7 +180,7 @@ void AXUCode::HandleCommandList() break; case CMD_UNK_08: - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_UNIMPLEMENTED_AX_COMMAND); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesUnimplementedAXCommand); curr_idx += 10; break; // TODO: check diff --git a/Source/Core/Core/HW/DSPHLE/UCodes/AXVoice.h b/Source/Core/Core/HW/DSPHLE/UCodes/AXVoice.h index 502ab657ed..0b79c11ed1 100644 --- a/Source/Core/Core/HW/DSPHLE/UCodes/AXVoice.h +++ b/Source/Core/Core/HW/DSPHLE/UCodes/AXVoice.h @@ -536,7 +536,7 @@ void ProcessVoice(HLEAccelerator* accelerator, PB_TYPE& pb, const AXBuffers& buf if (pb.initial_time_delay.on) { // TODO - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_AX_INITIAL_TIME_DELAY); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesAXInitialTimeDelay); } #ifdef AX_WII @@ -548,12 +548,12 @@ void ProcessVoice(HLEAccelerator* accelerator, PB_TYPE& pb, const AXBuffers& buf // Only one filter at most for Wiimotes. if (pb.remote_iir.on == 2) { - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_AX_WIIMOTE_BIQUAD); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesAXWiimoteBiquad); BiquadFilter(samples, count, pb.remote_iir.biquad); } else { - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_AX_WIIMOTE_LOWPASS); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesAXWiimoteLowpass); LowPassFilter(samples, count, pb.remote_iir.lpf); } } diff --git a/Source/Core/Core/HW/DVD/DVDInterface.cpp b/Source/Core/Core/HW/DVD/DVDInterface.cpp index 1c6ea07aa0..410f5763a5 100644 --- a/Source/Core/Core/HW/DVD/DVDInterface.cpp +++ b/Source/Core/Core/HW/DVD/DVDInterface.cpp @@ -885,14 +885,14 @@ void DVDInterface::ExecuteCommand(ReplyType reply_type) // Wii-exclusive case DICommand::StopLaser: ERROR_LOG_FMT(DVDINTERFACE, "DVDLowStopLaser"); - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DVD_LOW_STOP_LASER); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDVDLowStopLaser); SetDriveError(DriveError::InvalidCommand); interrupt_type = DIInterruptType::DEINT; break; // Wii-exclusive case DICommand::Offset: ERROR_LOG_FMT(DVDINTERFACE, "DVDLowOffset"); - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DVD_LOW_OFFSET); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDVDLowOffset); SetDriveError(DriveError::InvalidCommand); interrupt_type = DIInterruptType::DEINT; break; @@ -900,7 +900,7 @@ void DVDInterface::ExecuteCommand(ReplyType reply_type) case DICommand::ReadBCA: { WARN_LOG_FMT(DVDINTERFACE, "DVDLowReadDiskBca - supplying dummy data to appease NSMBW"); - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DVD_LOW_READ_DISK_BCA); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDVDLowReadDiskBCA); // NSMBW checks that the first 0x33 bytes of the BCA are 0, then it expects a 1. // Most (all?) other games have 0x34 0's at the start of the BCA, but don't actually // read it. NSMBW doesn't care about the other 12 bytes (which contain manufacturing data?) @@ -915,14 +915,14 @@ void DVDInterface::ExecuteCommand(ReplyType reply_type) // Wii-exclusive case DICommand::RequestDiscStatus: ERROR_LOG_FMT(DVDINTERFACE, "DVDLowRequestDiscStatus"); - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DVD_LOW_REQUEST_DISC_STATUS); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDVDLowRequestDiscStatus); SetDriveError(DriveError::InvalidCommand); interrupt_type = DIInterruptType::DEINT; break; // Wii-exclusive case DICommand::RequestRetryNumber: ERROR_LOG_FMT(DVDINTERFACE, "DVDLowRequestRetryNumber"); - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DVD_LOW_REQUEST_RETRY_NUMBER); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDVDLowRequestRetryNumber); SetDriveError(DriveError::InvalidCommand); interrupt_type = DIInterruptType::DEINT; break; @@ -935,7 +935,7 @@ void DVDInterface::ExecuteCommand(ReplyType reply_type) // Wii-exclusive case DICommand::SerMeasControl: ERROR_LOG_FMT(DVDINTERFACE, "DVDLowSerMeasControl"); - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DVD_LOW_SER_MEAS_CONTROL); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDVDLowSerMeasControl); SetDriveError(DriveError::InvalidCommand); interrupt_type = DIInterruptType::DEINT; break; diff --git a/Source/Core/Core/IOS/DI/DI.cpp b/Source/Core/Core/IOS/DI/DI.cpp index 0f1413229f..6f4ea1f8e6 100644 --- a/Source/Core/Core/IOS/DI/DI.cpp +++ b/Source/Core/Core/IOS/DI/DI.cpp @@ -261,7 +261,7 @@ std::optional DIDevice::StartIOCtl(const IOCtlRequest& reque case DIIoctl::DVDLowMaskCoverInterrupt: INFO_LOG_FMT(IOS_DI, "DVDLowMaskCoverInterrupt"); system.GetDVDInterface().SetInterruptEnabled(DVD::DIInterruptType::CVRINT, false); - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DI_INTERRUPT_MASK_COMMAND); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDIInterruptMaskCommand); return DIResult::Success; case DIIoctl::DVDLowClearCoverInterrupt: DEBUG_LOG_FMT(IOS_DI, "DVDLowClearCoverInterrupt"); @@ -269,7 +269,7 @@ std::optional DIDevice::StartIOCtl(const IOCtlRequest& reque return DIResult::Success; case DIIoctl::DVDLowUnmaskStatusInterrupts: INFO_LOG_FMT(IOS_DI, "DVDLowUnmaskStatusInterrupts"); - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DI_INTERRUPT_MASK_COMMAND); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDIInterruptMaskCommand); // Dummied out return DIResult::Success; case DIIoctl::DVDLowGetCoverStatus: @@ -282,7 +282,7 @@ std::optional DIDevice::StartIOCtl(const IOCtlRequest& reque case DIIoctl::DVDLowUnmaskCoverInterrupt: INFO_LOG_FMT(IOS_DI, "DVDLowUnmaskCoverInterrupt"); system.GetDVDInterface().SetInterruptEnabled(DVD::DIInterruptType::CVRINT, true); - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DI_INTERRUPT_MASK_COMMAND); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDIInterruptMaskCommand); return DIResult::Success; case DIIoctl::DVDLowReset: { @@ -319,7 +319,7 @@ std::optional DIDevice::StartIOCtl(const IOCtlRequest& reque } case DIIoctl::DVDLowOpenPartition: ERROR_LOG_FMT(IOS_DI, "DVDLowOpenPartition as an ioctl - rejecting"); - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DIFFERENT_PARTITION_COMMAND); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDifferentPartitionCommand); return DIResult::SecurityError; case DIIoctl::DVDLowClosePartition: INFO_LOG_FMT(IOS_DI, "DVDLowClosePartition"); @@ -372,23 +372,23 @@ std::optional DIDevice::StartIOCtl(const IOCtlRequest& reque // Dolphin as games are unlikely to use them. case DIIoctl::DVDLowGetNoDiscOpenPartitionParams: ERROR_LOG_FMT(IOS_DI, "DVDLowGetNoDiscOpenPartitionParams as an ioctl - rejecting"); - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DIFFERENT_PARTITION_COMMAND); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDifferentPartitionCommand); return DIResult::SecurityError; case DIIoctl::DVDLowNoDiscOpenPartition: ERROR_LOG_FMT(IOS_DI, "DVDLowNoDiscOpenPartition as an ioctl - rejecting"); - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DIFFERENT_PARTITION_COMMAND); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDifferentPartitionCommand); return DIResult::SecurityError; case DIIoctl::DVDLowGetNoDiscBufferSizes: ERROR_LOG_FMT(IOS_DI, "DVDLowGetNoDiscBufferSizes as an ioctl - rejecting"); - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DIFFERENT_PARTITION_COMMAND); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDifferentPartitionCommand); return DIResult::SecurityError; case DIIoctl::DVDLowOpenPartitionWithTmdAndTicket: ERROR_LOG_FMT(IOS_DI, "DVDLowOpenPartitionWithTmdAndTicket as an ioctl - rejecting"); - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DIFFERENT_PARTITION_COMMAND); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDifferentPartitionCommand); return DIResult::SecurityError; case DIIoctl::DVDLowOpenPartitionWithTmdAndTicketView: ERROR_LOG_FMT(IOS_DI, "DVDLowOpenPartitionWithTmdAndTicketView as an ioctl - rejecting"); - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DIFFERENT_PARTITION_COMMAND); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDifferentPartitionCommand); return DIResult::SecurityError; case DIIoctl::DVDLowGetStatusRegister: { @@ -721,14 +721,14 @@ std::optional DIDevice::IOCtlV(const IOCtlVRequest& request) { ERROR_LOG_FMT(IOS_DI, "DVDLowOpenPartition with ticket - not implemented, ignoring ticket parameter"); - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DIFFERENT_PARTITION_COMMAND); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDifferentPartitionCommand); } if (request.in_vectors[2].address != 0) { ERROR_LOG_FMT( IOS_DI, "DVDLowOpenPartition with cert chain - not implemented, ignoring certs parameter"); - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DIFFERENT_PARTITION_COMMAND); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDifferentPartitionCommand); } const u64 partition_offset = @@ -752,26 +752,26 @@ std::optional DIDevice::IOCtlV(const IOCtlVRequest& request) } case DIIoctl::DVDLowGetNoDiscOpenPartitionParams: ERROR_LOG_FMT(IOS_DI, "DVDLowGetNoDiscOpenPartitionParams - dummied out"); - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DIFFERENT_PARTITION_COMMAND); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDifferentPartitionCommand); request.DumpUnknown(system, GetDeviceName(), Common::Log::LogType::IOS_DI); break; case DIIoctl::DVDLowNoDiscOpenPartition: ERROR_LOG_FMT(IOS_DI, "DVDLowNoDiscOpenPartition - dummied out"); - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DIFFERENT_PARTITION_COMMAND); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDifferentPartitionCommand); request.DumpUnknown(system, GetDeviceName(), Common::Log::LogType::IOS_DI); break; case DIIoctl::DVDLowGetNoDiscBufferSizes: ERROR_LOG_FMT(IOS_DI, "DVDLowGetNoDiscBufferSizes - dummied out"); - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DIFFERENT_PARTITION_COMMAND); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDifferentPartitionCommand); request.DumpUnknown(system, GetDeviceName(), Common::Log::LogType::IOS_DI); break; case DIIoctl::DVDLowOpenPartitionWithTmdAndTicket: ERROR_LOG_FMT(IOS_DI, "DVDLowOpenPartitionWithTmdAndTicket - not implemented"); - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DIFFERENT_PARTITION_COMMAND); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDifferentPartitionCommand); break; case DIIoctl::DVDLowOpenPartitionWithTmdAndTicketView: ERROR_LOG_FMT(IOS_DI, "DVDLowOpenPartitionWithTmdAndTicketView - not implemented"); - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_DIFFERENT_PARTITION_COMMAND); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesDifferentPartitionCommand); break; default: ERROR_LOG_FMT(IOS_DI, "Unknown ioctlv {:#04x}", request.request); diff --git a/Source/Core/Core/IOS/Network/WD/Command.cpp b/Source/Core/Core/IOS/Network/WD/Command.cpp index d86ee5f39f..6da09c948b 100644 --- a/Source/Core/Core/IOS/Network/WD/Command.cpp +++ b/Source/Core/Core/IOS/Network/WD/Command.cpp @@ -198,7 +198,7 @@ std::optional NetWDCommandDevice::Open(const OpenRequest& request) if (mode != WD::Mode::DSCommunications && mode != WD::Mode::AOSSAccessPointScan) { ERROR_LOG_FMT(IOS_NET, "Unsupported WD operating mode: {}", mode); - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_UNCOMMON_WD_MODE); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesUncommonWDMode); return IPCReply(s32(ResultCode::UnavailableCommand)); } @@ -390,7 +390,7 @@ std::optional NetWDCommandDevice::IOCtlV(const IOCtlVRequest& request) case IOCTLV_WD_CHANGE_GAMEINFO: case IOCTLV_WD_CHANGE_VTSF: default: - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_WD_UNIMPLEMENTED_IOCTL); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesWDUnimplementedIoctl); request.Dump(GetSystem(), GetDeviceName(), Common::Log::LogType::IOS_NET, Common::Log::LogLevel::LWARNING); } diff --git a/Source/Core/VideoCommon/BPStructs.cpp b/Source/Core/VideoCommon/BPStructs.cpp index bb910e653e..a15a9d3e88 100644 --- a/Source/Core/VideoCommon/BPStructs.cpp +++ b/Source/Core/VideoCommon/BPStructs.cpp @@ -783,7 +783,7 @@ static void BPWritten(PixelShaderManager& pixel_shader_manager, XFStateManager& break; } - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_UNKNOWN_BP_COMMAND); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesUnknownBPCommand); WARN_LOG_FMT(VIDEO, "Unknown BP opcode: address = {:#010x} value = {:#010x}", bp.address, bp.newvalue); } diff --git a/Source/Core/VideoCommon/CPMemory.cpp b/Source/Core/VideoCommon/CPMemory.cpp index b3761ddf52..9b47a13da0 100644 --- a/Source/Core/VideoCommon/CPMemory.cpp +++ b/Source/Core/VideoCommon/CPMemory.cpp @@ -99,7 +99,7 @@ void CPState::LoadCPReg(u8 sub_cmd, u32 value) if (!(sub_cmd == UNKNOWN_20 && value == 0)) { // All titles using libogc or the official SDK issue 0x20 with value=0 on startup - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_CP_PERF_COMMAND); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesCPPerfCommand); DEBUG_LOG_FMT(VIDEO, "Unknown CP command possibly relating to perf queries used: {:02x}", sub_cmd); } @@ -108,7 +108,7 @@ void CPState::LoadCPReg(u8 sub_cmd, u32 value) case MATINDEX_A: if (sub_cmd != MATINDEX_A) { - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_MAYBE_INVALID_CP_COMMAND); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesMaybeInvalidCPCommand); WARN_LOG_FMT(VIDEO, "CP MATINDEX_A: an exact value of {:02x} was expected " "but instead a value of {:02x} was seen", @@ -121,7 +121,7 @@ void CPState::LoadCPReg(u8 sub_cmd, u32 value) case MATINDEX_B: if (sub_cmd != MATINDEX_B) { - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_MAYBE_INVALID_CP_COMMAND); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesMaybeInvalidCPCommand); WARN_LOG_FMT(VIDEO, "CP MATINDEX_B: an exact value of {:02x} was expected " "but instead a value of {:02x} was seen", @@ -134,7 +134,7 @@ void CPState::LoadCPReg(u8 sub_cmd, u32 value) case VCD_LO: if (sub_cmd != VCD_LO) // Stricter than YAGCD { - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_MAYBE_INVALID_CP_COMMAND); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesMaybeInvalidCPCommand); WARN_LOG_FMT(VIDEO, "CP VCD_LO: an exact value of {:02x} was expected " "but instead a value of {:02x} was seen", @@ -147,7 +147,7 @@ void CPState::LoadCPReg(u8 sub_cmd, u32 value) case VCD_HI: if (sub_cmd != VCD_HI) // Stricter than YAGCD { - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_MAYBE_INVALID_CP_COMMAND); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesMaybeInvalidCPCommand); WARN_LOG_FMT(VIDEO, "CP VCD_HI: an exact value of {:02x} was expected " "but instead a value of {:02x} was seen", @@ -160,7 +160,7 @@ void CPState::LoadCPReg(u8 sub_cmd, u32 value) case CP_VAT_REG_A: if ((sub_cmd - CP_VAT_REG_A) >= CP_NUM_VAT_REG) { - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_MAYBE_INVALID_CP_COMMAND); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesMaybeInvalidCPCommand); WARN_LOG_FMT(VIDEO, "CP_VAT_REG_A: Invalid VAT {}", sub_cmd - CP_VAT_REG_A); } vtx_attr[sub_cmd & CP_VAT_MASK].g0.Hex = value; @@ -169,7 +169,7 @@ void CPState::LoadCPReg(u8 sub_cmd, u32 value) case CP_VAT_REG_B: if ((sub_cmd - CP_VAT_REG_B) >= CP_NUM_VAT_REG) { - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_MAYBE_INVALID_CP_COMMAND); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesMaybeInvalidCPCommand); WARN_LOG_FMT(VIDEO, "CP_VAT_REG_B: Invalid VAT {}", sub_cmd - CP_VAT_REG_B); } vtx_attr[sub_cmd & CP_VAT_MASK].g1.Hex = value; @@ -178,7 +178,7 @@ void CPState::LoadCPReg(u8 sub_cmd, u32 value) case CP_VAT_REG_C: if ((sub_cmd - CP_VAT_REG_C) >= CP_NUM_VAT_REG) { - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_MAYBE_INVALID_CP_COMMAND); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesMaybeInvalidCPCommand); WARN_LOG_FMT(VIDEO, "CP_VAT_REG_C: Invalid VAT {}", sub_cmd - CP_VAT_REG_C); } vtx_attr[sub_cmd & CP_VAT_MASK].g2.Hex = value; @@ -195,7 +195,7 @@ void CPState::LoadCPReg(u8 sub_cmd, u32 value) break; default: - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_UNKNOWN_CP_COMMAND); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesUnknownCPCommand); WARN_LOG_FMT(VIDEO, "Unknown CP register {:02x} set to {:08x}", sub_cmd, value); } } diff --git a/Source/Core/VideoCommon/VertexLoaderManager.cpp b/Source/Core/VideoCommon/VertexLoaderManager.cpp index 0f44d16023..e7b2cb5df2 100644 --- a/Source/Core/VideoCommon/VertexLoaderManager.cpp +++ b/Source/Core/VideoCommon/VertexLoaderManager.cpp @@ -300,18 +300,15 @@ static void CheckCPConfiguration(int vtx_attr_group) // eventually simulate the behavior we have test cases for it. if (num_cp_colors != xfmem.invtxspec.numcolors) [[unlikely]] { - DolphinAnalytics::Instance().ReportGameQuirk( - GameQuirk::MISMATCHED_GPU_COLORS_BETWEEN_CP_AND_XF); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::MismatchedGPUColorsBetweenCPAndXF); } if (num_cp_normals != num_xf_normals) [[unlikely]] { - DolphinAnalytics::Instance().ReportGameQuirk( - GameQuirk::MISMATCHED_GPU_NORMALS_BETWEEN_CP_AND_XF); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::MismatchedGPUNormalsBetweenCPAndXF); } if (num_cp_tex_coords != xfmem.invtxspec.numtextures) [[unlikely]] { - DolphinAnalytics::Instance().ReportGameQuirk( - GameQuirk::MISMATCHED_GPU_TEX_COORDS_BETWEEN_CP_AND_XF); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::MismatchedGPUTexCoordsBetweenCPAndXF); } // Don't bail out, though; we can still render something successfully @@ -327,7 +324,7 @@ static void CheckCPConfiguration(int vtx_attr_group) g_main_cp_state.matrix_index_a.Hex, xfmem.MatrixIndexA.Hex, g_main_cp_state.matrix_index_b.Hex, xfmem.MatrixIndexB.Hex); DolphinAnalytics::Instance().ReportGameQuirk( - GameQuirk::MISMATCHED_GPU_MATRIX_INDICES_BETWEEN_CP_AND_XF); + GameQuirk::MismatchedGPUMatrixIndicesBetweenCPAndXF); } if (g_main_cp_state.vtx_attr[vtx_attr_group].g0.PosFormat >= ComponentFormat::InvalidFloat5) @@ -337,7 +334,7 @@ static void CheckCPConfiguration(int vtx_attr_group) g_main_cp_state.vtx_attr[vtx_attr_group].g0.Hex, g_main_cp_state.vtx_attr[vtx_attr_group].g1.Hex, g_main_cp_state.vtx_attr[vtx_attr_group].g2.Hex); - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::INVALID_POSITION_COMPONENT_FORMAT); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::InvalidPositionComponentFormat); } if (g_main_cp_state.vtx_attr[vtx_attr_group].g0.NormalFormat >= ComponentFormat::InvalidFloat5) { @@ -346,7 +343,7 @@ static void CheckCPConfiguration(int vtx_attr_group) g_main_cp_state.vtx_attr[vtx_attr_group].g0.Hex, g_main_cp_state.vtx_attr[vtx_attr_group].g1.Hex, g_main_cp_state.vtx_attr[vtx_attr_group].g2.Hex); - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::INVALID_NORMAL_COMPONENT_FORMAT); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::InvalidNormalComponentFormat); } for (size_t i = 0; i < 8; i++) { @@ -359,7 +356,7 @@ static void CheckCPConfiguration(int vtx_attr_group) g_main_cp_state.vtx_attr[vtx_attr_group].g1.Hex, g_main_cp_state.vtx_attr[vtx_attr_group].g2.Hex); DolphinAnalytics::Instance().ReportGameQuirk( - GameQuirk::INVALID_TEXTURE_COORDINATE_COMPONENT_FORMAT); + GameQuirk::InvalidTextureCoordinateComponentFormat); } } for (size_t i = 0; i < 2; i++) @@ -371,7 +368,7 @@ static void CheckCPConfiguration(int vtx_attr_group) g_main_cp_state.vtx_attr[vtx_attr_group].g0.Hex, g_main_cp_state.vtx_attr[vtx_attr_group].g1.Hex, g_main_cp_state.vtx_attr[vtx_attr_group].g2.Hex); - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::INVALID_COLOR_COMPONENT_FORMAT); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::InvalidColorComponentFormat); } } } diff --git a/Source/Core/VideoCommon/VertexManagerBase.cpp b/Source/Core/VideoCommon/VertexManagerBase.cpp index 64246df904..706ee571f8 100644 --- a/Source/Core/VideoCommon/VertexManagerBase.cpp +++ b/Source/Core/VideoCommon/VertexManagerBase.cpp @@ -459,13 +459,11 @@ void VertexManagerBase::Flush() // eventually simulate the behavior we have test cases for it. if (xfmem.numTexGen.numTexGens != bpmem.genMode.numtexgens) { - DolphinAnalytics::Instance().ReportGameQuirk( - GameQuirk::MISMATCHED_GPU_TEXGENS_BETWEEN_XF_AND_BP); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::MismatchedGPUTexgensBetweenXFAndBP); } if (xfmem.numChan.numColorChans != bpmem.genMode.numcolchans) { - DolphinAnalytics::Instance().ReportGameQuirk( - GameQuirk::MISMATCHED_GPU_COLORS_BETWEEN_XF_AND_BP); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::MismatchedGPUColorsBetweenXFAndBP); } return; diff --git a/Source/Core/VideoCommon/VideoBackendBase.cpp b/Source/Core/VideoCommon/VideoBackendBase.cpp index 73035e0e1b..88c0cf9122 100644 --- a/Source/Core/VideoCommon/VideoBackendBase.cpp +++ b/Source/Core/VideoCommon/VideoBackendBase.cpp @@ -124,7 +124,7 @@ u32 VideoBackendBase::Video_GetQueryResult(PerfQueryType type) u16 VideoBackendBase::Video_GetBoundingBox(int index) { - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::READS_BOUNDING_BOX); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::ReadsBoundingBox); if (!g_ActiveConfig.bBBoxEnable) { diff --git a/Source/Core/VideoCommon/XFStructs.cpp b/Source/Core/VideoCommon/XFStructs.cpp index 54adb0e4d3..ad6e59906b 100644 --- a/Source/Core/VideoCommon/XFStructs.cpp +++ b/Source/Core/VideoCommon/XFStructs.cpp @@ -48,11 +48,11 @@ static void XFRegWritten(Core::System& system, XFStateManager& xf_state_manager, { ClipDisable setting{.hex = value}; if (setting.disable_clipping_detection) - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::SETS_XF_CLIPDISABLE_BIT_0); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::SetsXFClipdisableBit0); if (setting.disable_trivial_rejection) - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::SETS_XF_CLIPDISABLE_BIT_1); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::SetsXFClipdisableBit1); if (setting.disable_cpoly_clipping_acceleration) - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::SETS_XF_CLIPDISABLE_BIT_2); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::SetsXFClipdisableBit2); break; } @@ -180,7 +180,7 @@ static void XFRegWritten(Core::System& system, XFStateManager& xf_state_manager, case 0x104d: case 0x104e: case 0x104f: - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_UNKNOWN_XF_COMMAND); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesUnknownXFCommand); DEBUG_LOG_FMT(VIDEO, "Possible Normal Mtx XF reg?: {:x}={:x}", address, value); break; @@ -191,7 +191,7 @@ static void XFRegWritten(Core::System& system, XFStateManager& xf_state_manager, case 0x1017: default: - DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::USES_UNKNOWN_XF_COMMAND); + DolphinAnalytics::Instance().ReportGameQuirk(GameQuirk::UsesUnknownXFCommand); WARN_LOG_FMT(VIDEO, "Unknown XF Reg: {:x}={:x}", address, value); break; } From 41b0c09486ee8b39d102e15d830702acaba0ebac Mon Sep 17 00:00:00 2001 From: Dentomologist Date: Thu, 28 Jan 2021 09:22:40 -0800 Subject: [PATCH 08/13] DolphinAnalytics: Move PerformanceSample to header Avoid circular dependencies or forward declarations in upcoming commits. --- Source/Core/Core/CMakeLists.txt | 1 + Source/Core/Core/DolphinAnalytics.h | 8 ++------ Source/Core/Core/PerformanceSample.h | 12 ++++++++++++ Source/Core/DolphinLib.props | 1 + 4 files changed, 16 insertions(+), 6 deletions(-) create mode 100644 Source/Core/Core/PerformanceSample.h diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index f7b43c463e..7dad798fc7 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -483,6 +483,7 @@ add_library(core NetworkCaptureLogger.h PatchEngine.cpp PatchEngine.h + PerformanceSample.h PowerPC/BreakPoints.cpp PowerPC/BreakPoints.h PowerPC/CachedInterpreter/CachedInterpreter_Disassembler.cpp diff --git a/Source/Core/Core/DolphinAnalytics.h b/Source/Core/Core/DolphinAnalytics.h index 75bd8d9f88..400e73e6ed 100644 --- a/Source/Core/Core/DolphinAnalytics.h +++ b/Source/Core/Core/DolphinAnalytics.h @@ -12,6 +12,8 @@ #include "Common/Analytics.h" #include "Common/CommonTypes.h" +#include "Core/PerformanceSample.h" + #if defined(ANDROID) #include #endif @@ -134,12 +136,6 @@ 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. // diff --git a/Source/Core/Core/PerformanceSample.h b/Source/Core/Core/PerformanceSample.h new file mode 100644 index 0000000000..34e289408a --- /dev/null +++ b/Source/Core/Core/PerformanceSample.h @@ -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; +}; diff --git a/Source/Core/DolphinLib.props b/Source/Core/DolphinLib.props index d7bb245d29..09c7726310 100644 --- a/Source/Core/DolphinLib.props +++ b/Source/Core/DolphinLib.props @@ -437,6 +437,7 @@ + From d78e6fe165f9b3b35465256c48c67b6fe9ec5346 Mon Sep 17 00:00:00 2001 From: Dentomologist Date: Thu, 28 Jan 2021 09:36:37 -0800 Subject: [PATCH 09/13] Create PerformanceSampleAggregator --- Source/Core/Core/CMakeLists.txt | 2 ++ Source/Core/Core/DolphinAnalytics.cpp | 4 ++++ Source/Core/Core/PerformanceSampleAggregator.cpp | 5 +++++ Source/Core/Core/PerformanceSampleAggregator.h | 11 +++++++++++ Source/Core/DolphinLib.props | 2 ++ 5 files changed, 24 insertions(+) create mode 100644 Source/Core/Core/PerformanceSampleAggregator.cpp create mode 100644 Source/Core/Core/PerformanceSampleAggregator.h diff --git a/Source/Core/Core/CMakeLists.txt b/Source/Core/Core/CMakeLists.txt index 7dad798fc7..7b9e2b3d85 100644 --- a/Source/Core/Core/CMakeLists.txt +++ b/Source/Core/Core/CMakeLists.txt @@ -484,6 +484,8 @@ add_library(core PatchEngine.cpp PatchEngine.h PerformanceSample.h + PerformanceSampleAggregator.cpp + PerformanceSampleAggregator.h PowerPC/BreakPoints.cpp PowerPC/BreakPoints.h PowerPC/CachedInterpreter/CachedInterpreter_Disassembler.cpp diff --git a/Source/Core/Core/DolphinAnalytics.cpp b/Source/Core/Core/DolphinAnalytics.cpp index a857a074c1..03b07d27b2 100644 --- a/Source/Core/Core/DolphinAnalytics.cpp +++ b/Source/Core/Core/DolphinAnalytics.cpp @@ -29,14 +29,18 @@ #include "Common/Random.h" #include "Common/Timer.h" #include "Common/Version.h" + #include "Core/Config/MainSettings.h" #include "Core/ConfigManager.h" #include "Core/HW/GCPad.h" #include "Core/Movie.h" #include "Core/NetPlayProto.h" +#include "Core/PerformanceSampleAggregator.h" + #include "Core/System.h" #include "InputCommon/GCAdapter.h" #include "InputCommon/InputConfig.h" + #include "VideoCommon/VideoBackendBase.h" #include "VideoCommon/VideoConfig.h" diff --git a/Source/Core/Core/PerformanceSampleAggregator.cpp b/Source/Core/Core/PerformanceSampleAggregator.cpp new file mode 100644 index 0000000000..1e0b8ddf4b --- /dev/null +++ b/Source/Core/Core/PerformanceSampleAggregator.cpp @@ -0,0 +1,5 @@ +// Copyright 2021 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "Core/PerformanceSampleAggregator.h" diff --git a/Source/Core/Core/PerformanceSampleAggregator.h b/Source/Core/Core/PerformanceSampleAggregator.h new file mode 100644 index 0000000000..59f5c86484 --- /dev/null +++ b/Source/Core/Core/PerformanceSampleAggregator.h @@ -0,0 +1,11 @@ +// Copyright 2021 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +class PerformanceSampleAggregator +{ +public: + PerformanceSampleAggregator() = default; +}; diff --git a/Source/Core/DolphinLib.props b/Source/Core/DolphinLib.props index 09c7726310..ee4d3bb4ba 100644 --- a/Source/Core/DolphinLib.props +++ b/Source/Core/DolphinLib.props @@ -438,6 +438,7 @@ + @@ -1106,6 +1107,7 @@ + From d9b0fd2805f1f24dc2907ca3d9d55a75416bdd5e Mon Sep 17 00:00:00 2001 From: Dentomologist Date: Tue, 26 Jan 2021 16:36:12 -0800 Subject: [PATCH 10/13] DolphinAnalytics: Extract timestamp functions Moves functions that generate starting timestamps for performance sampling to PerformanceSampleAggregator. --- Source/Core/Core/DolphinAnalytics.cpp | 18 ++------- Source/Core/Core/DolphinAnalytics.h | 14 +++---- .../Core/Core/PerformanceSampleAggregator.cpp | 39 +++++++++++++++++++ .../Core/Core/PerformanceSampleAggregator.h | 6 +++ 4 files changed, 56 insertions(+), 21 deletions(-) diff --git a/Source/Core/Core/DolphinAnalytics.cpp b/Source/Core/Core/DolphinAnalytics.cpp index 03b07d27b2..54e3f5f7fc 100644 --- a/Source/Core/Core/DolphinAnalytics.cpp +++ b/Source/Core/Core/DolphinAnalytics.cpp @@ -27,7 +27,6 @@ #include "Common/Crypto/SHA1.h" #include "Common/EnumUtils.h" #include "Common/Random.h" -#include "Common/Timer.h" #include "Common/Version.h" #include "Core/Config/MainSettings.h" @@ -35,7 +34,6 @@ #include "Core/HW/GCPad.h" #include "Core/Movie.h" #include "Core/NetPlayProto.h" -#include "Core/PerformanceSampleAggregator.h" #include "Core/System.h" #include "InputCommon/GCAdapter.h" @@ -321,6 +319,7 @@ void DolphinAnalytics::ReportPerformanceInfo(PerformanceSample&& sample) // Clear up and stop sampling until next time ShouldStartPerformanceSampling() says so. m_performance_samples.clear(); m_sampling_performance_info = false; + m_sampling_next_start_us = m_sample_aggregator.GetRepeatSamplingStartTimestamp().count(); } } @@ -329,22 +328,13 @@ void DolphinAnalytics::InitializePerformanceSampling() m_performance_samples.clear(); m_sampling_performance_info = false; - const u64 wait_us = - PERFORMANCE_SAMPLING_INITIAL_WAIT_TIME_SECS * 1000000 + - Common::Random::GenerateValue() % (PERFORMANCE_SAMPLING_WAIT_TIME_JITTER_SECS * 1000000); - m_sampling_next_start_us = Common::Timer::NowUs() + wait_us; + m_sampling_next_start_us = m_sample_aggregator.GetInitialSamplingStartTimestamp().count(); } bool DolphinAnalytics::ShouldStartPerformanceSampling() { - if (Common::Timer::NowUs() < m_sampling_next_start_us) - return false; - - const u64 wait_us = - PERFORMANCE_SAMPLING_INTERVAL_SECS * 1000000 + - Common::Random::GenerateValue() % (PERFORMANCE_SAMPLING_WAIT_TIME_JITTER_SECS * 1000000); - m_sampling_next_start_us = Common::Timer::NowUs() + wait_us; - return true; + return static_cast(m_sample_aggregator.GetCurrentMicroseconds().count()) >= + m_sampling_next_start_us; } void DolphinAnalytics::MakeBaseBuilder() diff --git a/Source/Core/Core/DolphinAnalytics.h b/Source/Core/Core/DolphinAnalytics.h index 400e73e6ed..76180aaba1 100644 --- a/Source/Core/Core/DolphinAnalytics.h +++ b/Source/Core/Core/DolphinAnalytics.h @@ -13,6 +13,7 @@ #include "Common/CommonTypes.h" #include "Core/PerformanceSample.h" +#include "Core/PerformanceSampleAggregator.h" #if defined(ANDROID) #include @@ -138,6 +139,10 @@ public: // 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); @@ -165,21 +170,16 @@ 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 m_performance_samples; + PerformanceSampleAggregator m_sample_aggregator; // What quirks have already been reported about the current game. std::array(GameQuirk::Count)> m_reported_quirks; diff --git a/Source/Core/Core/PerformanceSampleAggregator.cpp b/Source/Core/Core/PerformanceSampleAggregator.cpp index 1e0b8ddf4b..f4ec11924a 100644 --- a/Source/Core/Core/PerformanceSampleAggregator.cpp +++ b/Source/Core/Core/PerformanceSampleAggregator.cpp @@ -3,3 +3,42 @@ // Refer to the license.txt file included. #include "Core/PerformanceSampleAggregator.h" + +#include "Common/Random.h" + +namespace +{ +std::chrono::microseconds GetSamplingStartTimeJitter() +{ + constexpr long long max_delay = std::chrono::microseconds(std::chrono::minutes(3)).count(); + return std::chrono::microseconds(Common::Random::GenerateValue() % max_delay); +} + +std::chrono::microseconds +GetSamplingStartTimestampUsingBaseDelay(const std::chrono::microseconds base_delay) +{ + const std::chrono::microseconds now = PerformanceSampleAggregator::GetCurrentMicroseconds(); + const std::chrono::microseconds jitter = GetSamplingStartTimeJitter(); + const std::chrono::microseconds sampling_start_timestamp = now + base_delay + jitter; + return sampling_start_timestamp; +} +} // namespace + +std::chrono::microseconds PerformanceSampleAggregator::GetInitialSamplingStartTimestamp() +{ + constexpr std::chrono::microseconds base_initial_delay = std::chrono::minutes(5); + return GetSamplingStartTimestampUsingBaseDelay(base_initial_delay); +} + +std::chrono::microseconds PerformanceSampleAggregator::GetRepeatSamplingStartTimestamp() +{ + constexpr std::chrono::microseconds base_repeat_delay = std::chrono::minutes(30); + return GetSamplingStartTimestampUsingBaseDelay(base_repeat_delay); +} + +std::chrono::microseconds PerformanceSampleAggregator::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(time_since_epoch); +} diff --git a/Source/Core/Core/PerformanceSampleAggregator.h b/Source/Core/Core/PerformanceSampleAggregator.h index 59f5c86484..a3a8bc4e4a 100644 --- a/Source/Core/Core/PerformanceSampleAggregator.h +++ b/Source/Core/Core/PerformanceSampleAggregator.h @@ -4,8 +4,14 @@ #pragma once +#include + class PerformanceSampleAggregator { public: PerformanceSampleAggregator() = default; + + static std::chrono::microseconds GetInitialSamplingStartTimestamp(); + static std::chrono::microseconds GetRepeatSamplingStartTimestamp(); + static std::chrono::microseconds GetCurrentMicroseconds(); }; From 4138d691ae00740559c264d89dc516173fdb1c72 Mon Sep 17 00:00:00 2001 From: Dentomologist Date: Sat, 30 Jan 2021 10:55:25 -0800 Subject: [PATCH 11/13] DolphinAnalytics: Extract report generation Move generation of completed performance sample report to PerformanceSampleAggregator. --- Source/Core/Core/DolphinAnalytics.cpp | 17 +++++------------ .../Core/Core/PerformanceSampleAggregator.cpp | 19 +++++++++++++++++++ .../Core/Core/PerformanceSampleAggregator.h | 14 ++++++++++++++ 3 files changed, 38 insertions(+), 12 deletions(-) diff --git a/Source/Core/Core/DolphinAnalytics.cpp b/Source/Core/Core/DolphinAnalytics.cpp index 54e3f5f7fc..18e6261671 100644 --- a/Source/Core/Core/DolphinAnalytics.cpp +++ b/Source/Core/Core/DolphinAnalytics.cpp @@ -296,23 +296,16 @@ void DolphinAnalytics::ReportPerformanceInfo(PerformanceSample&& sample) if (m_performance_samples.size() >= NUM_PERFORMANCE_SAMPLES_PER_REPORT) { - std::vector speed_times_1000(m_performance_samples.size()); - std::vector num_prims(m_performance_samples.size()); - std::vector num_draw_calls(m_performance_samples.size()); - for (size_t i = 0; i < m_performance_samples.size(); ++i) - { - speed_times_1000[i] = static_cast(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; - } + PerformanceSampleAggregator::CompletedReport report = + PerformanceSampleAggregator::GetReportFromSamples(m_performance_samples); // 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); + builder.AddData("speed", report.speed); + builder.AddData("prims", report.primitives); + builder.AddData("draw-calls", report.draw_calls); Send(builder); diff --git a/Source/Core/Core/PerformanceSampleAggregator.cpp b/Source/Core/Core/PerformanceSampleAggregator.cpp index f4ec11924a..7d59a2cd75 100644 --- a/Source/Core/Core/PerformanceSampleAggregator.cpp +++ b/Source/Core/Core/PerformanceSampleAggregator.cpp @@ -42,3 +42,22 @@ std::chrono::microseconds PerformanceSampleAggregator::GetCurrentMicroseconds() std::chrono::high_resolution_clock::now().time_since_epoch(); return std::chrono::duration_cast(time_since_epoch); } + +PerformanceSampleAggregator::CompletedReport +PerformanceSampleAggregator::GetReportFromSamples(const std::vector& samples) +{ + 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(sample.speed_ratio * 1'000); + report.primitives[i] = sample.num_prims; + report.draw_calls[i] = sample.num_draw_calls; + } + return report; +} diff --git a/Source/Core/Core/PerformanceSampleAggregator.h b/Source/Core/Core/PerformanceSampleAggregator.h index a3a8bc4e4a..7b50d6e171 100644 --- a/Source/Core/Core/PerformanceSampleAggregator.h +++ b/Source/Core/Core/PerformanceSampleAggregator.h @@ -5,6 +5,11 @@ #pragma once #include +#include + +#include "Common/CommonTypes.h" + +#include "Core/PerformanceSample.h" class PerformanceSampleAggregator { @@ -14,4 +19,13 @@ public: static std::chrono::microseconds GetInitialSamplingStartTimestamp(); static std::chrono::microseconds GetRepeatSamplingStartTimestamp(); static std::chrono::microseconds GetCurrentMicroseconds(); + + struct CompletedReport + { + std::vector speed; + std::vector primitives; + std::vector draw_calls; + }; + + static CompletedReport GetReportFromSamples(const std::vector& samples); }; From 1d0d1234474cb8ac960dea38825216431418ba48 Mon Sep 17 00:00:00 2001 From: Dentomologist Date: Sat, 30 Jan 2021 12:19:09 -0800 Subject: [PATCH 12/13] DolphinAnalytics: Extract sample aggregation Moves remaining sample aggregation logic to PerformanceSampleAggregation. --- Source/Core/Core/DolphinAnalytics.cpp | 56 ++++----------- Source/Core/Core/DolphinAnalytics.h | 9 --- .../Core/Core/PerformanceSampleAggregator.cpp | 68 +++++++++++++++---- .../Core/Core/PerformanceSampleAggregator.h | 19 ++++-- 4 files changed, 83 insertions(+), 69 deletions(-) diff --git a/Source/Core/Core/DolphinAnalytics.cpp b/Source/Core/Core/DolphinAnalytics.cpp index 18e6261671..c047b97e2f 100644 --- a/Source/Core/Core/DolphinAnalytics.cpp +++ b/Source/Core/Core/DolphinAnalytics.cpp @@ -225,7 +225,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. @@ -284,50 +284,24 @@ void DolphinAnalytics::ReportGameQuirk(GameQuirk quirk) void DolphinAnalytics::ReportPerformanceInfo(PerformanceSample&& sample) { - if (ShouldStartPerformanceSampling()) + m_sample_aggregator.AddSampleIfSamplingInProgress(std::move(sample)); + const std::optional 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(std::move(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) - { - PerformanceSampleAggregator::CompletedReport report = - PerformanceSampleAggregator::GetReportFromSamples(m_performance_samples); - - // 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); - - Send(builder); - - // Clear up and stop sampling until next time ShouldStartPerformanceSampling() says so. - m_performance_samples.clear(); - m_sampling_performance_info = false; - m_sampling_next_start_us = m_sample_aggregator.GetRepeatSamplingStartTimestamp().count(); - } -} - -void DolphinAnalytics::InitializePerformanceSampling() -{ - m_performance_samples.clear(); - m_sampling_performance_info = false; - - m_sampling_next_start_us = m_sample_aggregator.GetInitialSamplingStartTimestamp().count(); -} - -bool DolphinAnalytics::ShouldStartPerformanceSampling() -{ - return static_cast(m_sample_aggregator.GetCurrentMicroseconds().count()) >= - m_sampling_next_start_us; + Send(builder); } void DolphinAnalytics::MakeBaseBuilder() diff --git a/Source/Core/Core/DolphinAnalytics.h b/Source/Core/Core/DolphinAnalytics.h index 76180aaba1..21fa24104c 100644 --- a/Source/Core/Core/DolphinAnalytics.h +++ b/Source/Core/Core/DolphinAnalytics.h @@ -170,15 +170,6 @@ private: // values created by MakeUniqueId. std::string m_unique_id; - static constexpr int NUM_PERFORMANCE_SAMPLES_PER_REPORT = 100; - - // 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 m_performance_samples; PerformanceSampleAggregator m_sample_aggregator; // What quirks have already been reported about the current game. diff --git a/Source/Core/Core/PerformanceSampleAggregator.cpp b/Source/Core/Core/PerformanceSampleAggregator.cpp index 7d59a2cd75..4328f066e4 100644 --- a/Source/Core/Core/PerformanceSampleAggregator.cpp +++ b/Source/Core/Core/PerformanceSampleAggregator.cpp @@ -4,10 +4,21 @@ #include "Core/PerformanceSampleAggregator.h" +#include + #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(time_since_epoch); +} + std::chrono::microseconds GetSamplingStartTimeJitter() { constexpr long long max_delay = std::chrono::microseconds(std::chrono::minutes(3)).count(); @@ -17,36 +28,28 @@ std::chrono::microseconds GetSamplingStartTimeJitter() std::chrono::microseconds GetSamplingStartTimestampUsingBaseDelay(const std::chrono::microseconds base_delay) { - const std::chrono::microseconds now = PerformanceSampleAggregator::GetCurrentMicroseconds(); + 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; } -} // namespace -std::chrono::microseconds PerformanceSampleAggregator::GetInitialSamplingStartTimestamp() +std::chrono::microseconds GetInitialSamplingStartTimestamp() { constexpr std::chrono::microseconds base_initial_delay = std::chrono::minutes(5); return GetSamplingStartTimestampUsingBaseDelay(base_initial_delay); } -std::chrono::microseconds PerformanceSampleAggregator::GetRepeatSamplingStartTimestamp() +std::chrono::microseconds GetRepeatSamplingStartTimestamp() { constexpr std::chrono::microseconds base_repeat_delay = std::chrono::minutes(30); return GetSamplingStartTimestampUsingBaseDelay(base_repeat_delay); } -std::chrono::microseconds PerformanceSampleAggregator::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(time_since_epoch); -} - PerformanceSampleAggregator::CompletedReport -PerformanceSampleAggregator::GetReportFromSamples(const std::vector& samples) +GetCompletedReport(const std::vector& samples) { - CompletedReport report; + PerformanceSampleAggregator::CompletedReport report; const size_t num_samples = samples.size(); report.speed.resize(num_samples); report.primitives.resize(num_samples); @@ -61,3 +64,42 @@ PerformanceSampleAggregator::GetReportFromSamples(const std::vector(s_samples_per_report)), + m_next_starting_timestamp(std::numeric_limits::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::PopReportIfComplete() +{ + if (m_samples.size() < s_samples_per_report) + { + return std::nullopt; + } + const CompletedReport report = GetCompletedReport(m_samples); + ResetPerformanceSampling(); + return report; +} diff --git a/Source/Core/Core/PerformanceSampleAggregator.h b/Source/Core/Core/PerformanceSampleAggregator.h index 7b50d6e171..27354ff2c6 100644 --- a/Source/Core/Core/PerformanceSampleAggregator.h +++ b/Source/Core/Core/PerformanceSampleAggregator.h @@ -5,6 +5,7 @@ #pragma once #include +#include #include #include "Common/CommonTypes.h" @@ -14,11 +15,7 @@ class PerformanceSampleAggregator { public: - PerformanceSampleAggregator() = default; - - static std::chrono::microseconds GetInitialSamplingStartTimestamp(); - static std::chrono::microseconds GetRepeatSamplingStartTimestamp(); - static std::chrono::microseconds GetCurrentMicroseconds(); + PerformanceSampleAggregator(); struct CompletedReport { @@ -27,5 +24,15 @@ public: std::vector draw_calls; }; - static CompletedReport GetReportFromSamples(const std::vector& samples); + // Called on game start / title switch. + void InitializePerformanceSampling(); + void AddSampleIfSamplingInProgress(PerformanceSample&& sample); + std::optional PopReportIfComplete(); + +private: + // Called after sampling report is completed + void ResetPerformanceSampling(); + + std::vector m_samples; + std::chrono::microseconds m_next_starting_timestamp; }; From e3aa5f0763e9f5a2acaa127aaf238b9e5b1cf3c8 Mon Sep 17 00:00:00 2001 From: Dentomologist Date: Sun, 31 Jan 2021 10:41:09 -0800 Subject: [PATCH 13/13] DolphinAnalytics: Remove unused headers --- Source/Core/Core/DolphinAnalytics.cpp | 1 - Source/Core/Core/DolphinAnalytics.h | 2 -- 2 files changed, 3 deletions(-) diff --git a/Source/Core/Core/DolphinAnalytics.cpp b/Source/Core/Core/DolphinAnalytics.cpp index c047b97e2f..15c502060f 100644 --- a/Source/Core/Core/DolphinAnalytics.cpp +++ b/Source/Core/Core/DolphinAnalytics.cpp @@ -7,7 +7,6 @@ #include #include #include -#include #include diff --git a/Source/Core/Core/DolphinAnalytics.h b/Source/Core/Core/DolphinAnalytics.h index 21fa24104c..587bb1eb34 100644 --- a/Source/Core/Core/DolphinAnalytics.h +++ b/Source/Core/Core/DolphinAnalytics.h @@ -7,10 +7,8 @@ #include #include #include -#include #include "Common/Analytics.h" -#include "Common/CommonTypes.h" #include "Core/PerformanceSample.h" #include "Core/PerformanceSampleAggregator.h"