diff options
| author | 2015-02-15 15:49:27 -0200 | |
|---|---|---|
| committer | 2015-03-01 21:47:14 -0300 | |
| commit | dc8a3f8bc842df1b3eeeb5a283556ac644ab3183 (patch) | |
| tree | 82bc4d610bd0b77ba6f2ac4e514e68d1c251b251 /src/common/profiler.cpp | |
| parent | Add profiling infrastructure and widget (diff) | |
| download | yuzu-dc8a3f8bc842df1b3eeeb5a283556ac644ab3183.tar.gz yuzu-dc8a3f8bc842df1b3eeeb5a283556ac644ab3183.tar.xz yuzu-dc8a3f8bc842df1b3eeeb5a283556ac644ab3183.zip | |
Profiler: Implement QPCClock to get better precision on Win32
MSVC 2013 (at least) doesn't use QueryPerformanceCounter to implement
std::chrono::high_resolution_clock, so it has bad precision. Manually
implementing our own clock type using it works around this for now.
Diffstat (limited to 'src/common/profiler.cpp')
| -rw-r--r-- | src/common/profiler.cpp | 23 |
1 files changed, 23 insertions, 0 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 @@ | |||
| 6 | #include "common/profiler_reporting.h" | 6 | #include "common/profiler_reporting.h" |
| 7 | #include "common/assert.h" | 7 | #include "common/assert.h" |
| 8 | 8 | ||
| 9 | #if defined(_MSC_VER) && _MSC_VER <= 1800 // MSVC 2013. | ||
| 10 | #define NOMINMAX | ||
| 11 | #define WIN32_LEAN_AND_MEAN | ||
| 12 | #include <Windows.h> // For QueryPerformanceCounter/Frequency | ||
| 13 | #endif | ||
| 14 | |||
| 9 | namespace Common { | 15 | namespace Common { |
| 10 | namespace Profiling { | 16 | namespace Profiling { |
| 11 | 17 | ||
| @@ -13,6 +19,23 @@ namespace Profiling { | |||
| 13 | thread_local Timer* Timer::current_timer = nullptr; | 19 | thread_local Timer* Timer::current_timer = nullptr; |
| 14 | #endif | 20 | #endif |
| 15 | 21 | ||
| 22 | #if defined(_MSC_VER) && _MSC_VER <= 1800 // MSVC 2013 | ||
| 23 | QPCClock::time_point QPCClock::now() { | ||
| 24 | static LARGE_INTEGER freq; | ||
| 25 | // Use this dummy local static to ensure this gets initialized once. | ||
| 26 | static BOOL dummy = QueryPerformanceFrequency(&freq); | ||
| 27 | |||
| 28 | LARGE_INTEGER ticks; | ||
| 29 | QueryPerformanceCounter(&ticks); | ||
| 30 | |||
| 31 | // This is prone to overflow when multiplying, which is why I'm using micro instead of nano. The | ||
| 32 | // correct way to approach this would be to just return ticks as a time_point and then subtract | ||
| 33 | // and do this conversion when creating a duration from two time_points, however, as far as I | ||
| 34 | // could tell the C++ requirements for these types are incompatible with this approach. | ||
| 35 | return time_point(duration(ticks.QuadPart * std::micro::den / freq.QuadPart)); | ||
| 36 | } | ||
| 37 | #endif | ||
| 38 | |||
| 16 | TimingCategory::TimingCategory(const char* name, TimingCategory* parent) | 39 | TimingCategory::TimingCategory(const char* name, TimingCategory* parent) |
| 17 | : accumulated_duration(0) { | 40 | : accumulated_duration(0) { |
| 18 | 41 | ||