diff options
author | Yuri Kunde Schlesner <yuriks@yuriks.net> | 2015-02-15 18:49:27 +0100 |
---|---|---|
committer | Yuri Kunde Schlesner <yuriks@yuriks.net> | 2015-03-02 01:47:14 +0100 |
commit | dc8a3f8bc842df1b3eeeb5a283556ac644ab3183 (patch) | |
tree | 82bc4d610bd0b77ba6f2ac4e514e68d1c251b251 | |
parent | Add profiling infrastructure and widget (diff) | |
download | yuzu-dc8a3f8bc842df1b3eeeb5a283556ac644ab3183.tar yuzu-dc8a3f8bc842df1b3eeeb5a283556ac644ab3183.tar.gz yuzu-dc8a3f8bc842df1b3eeeb5a283556ac644ab3183.tar.bz2 yuzu-dc8a3f8bc842df1b3eeeb5a283556ac644ab3183.tar.lz yuzu-dc8a3f8bc842df1b3eeeb5a283556ac644ab3183.tar.xz yuzu-dc8a3f8bc842df1b3eeeb5a283556ac644ab3183.tar.zst yuzu-dc8a3f8bc842df1b3eeeb5a283556ac644ab3183.zip |
-rw-r--r-- | src/common/profiler.cpp | 23 | ||||
-rw-r--r-- | src/common/profiler.h | 20 |
2 files changed, 42 insertions, 1 deletions
diff --git a/src/common/profiler.cpp b/src/common/profiler.cpp index c37546af0..65c3df167 100644 --- a/src/common/profiler.cpp +++ b/src/common/profiler.cpp @@ -6,6 +6,12 @@ #include "common/profiler_reporting.h" #include "common/assert.h" +#if defined(_MSC_VER) && _MSC_VER <= 1800 // MSVC 2013. +#define NOMINMAX +#define WIN32_LEAN_AND_MEAN +#include <Windows.h> // For QueryPerformanceCounter/Frequency +#endif + namespace Common { namespace Profiling { @@ -13,6 +19,23 @@ namespace Profiling { thread_local Timer* Timer::current_timer = nullptr; #endif +#if defined(_MSC_VER) && _MSC_VER <= 1800 // MSVC 2013 +QPCClock::time_point QPCClock::now() { + static LARGE_INTEGER freq; + // Use this dummy local static to ensure this gets initialized once. + static BOOL dummy = QueryPerformanceFrequency(&freq); + + LARGE_INTEGER ticks; + QueryPerformanceCounter(&ticks); + + // This is prone to overflow when multiplying, which is why I'm using micro instead of nano. The + // correct way to approach this would be to just return ticks as a time_point and then subtract + // and do this conversion when creating a duration from two time_points, however, as far as I + // could tell the C++ requirements for these types are incompatible with this approach. + return time_point(duration(ticks.QuadPart * std::micro::den / freq.QuadPart)); +} +#endif + TimingCategory::TimingCategory(const char* name, TimingCategory* parent) : accumulated_duration(0) { diff --git a/src/common/profiler.h b/src/common/profiler.h index 53c4f6eaf..3e967b4bc 100644 --- a/src/common/profiler.h +++ b/src/common/profiler.h @@ -18,8 +18,26 @@ namespace Profiling { #define ENABLE_PROFILING 1 #endif -using Duration = std::chrono::nanoseconds; +#if defined(_MSC_VER) && _MSC_VER <= 1800 // MSVC 2013 +// MSVC up to 2013 doesn't use QueryPerformanceCounter for high_resolution_clock, so it has bad +// precision. We manually implement a clock based on QPC to get good results. + +struct QPCClock { + using duration = std::chrono::microseconds; + using time_point = std::chrono::time_point<QPCClock>; + using rep = duration::rep; + using period = duration::period; + static const bool is_steady = false; + + static time_point now(); +}; + +using Clock = QPCClock; +#else using Clock = std::chrono::high_resolution_clock; +#endif + +using Duration = Clock::duration; /** * Represents a timing category that measured time can be accounted towards. Should be declared as a |