mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu.git
				synced 2025-05-12 00:45:25 +00:00 
			
		
		
		
	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.
This commit is contained in:
		
							parent
							
								
									cd1fbfcf1b
								
							
						
					
					
						commit
						dc8a3f8bc8
					
				@ -6,6 +6,12 @@
 | 
				
			|||||||
#include "common/profiler_reporting.h"
 | 
					#include "common/profiler_reporting.h"
 | 
				
			||||||
#include "common/assert.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 Common {
 | 
				
			||||||
namespace Profiling {
 | 
					namespace Profiling {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -13,6 +19,23 @@ namespace Profiling {
 | 
				
			|||||||
thread_local Timer* Timer::current_timer = nullptr;
 | 
					thread_local Timer* Timer::current_timer = nullptr;
 | 
				
			||||||
#endif
 | 
					#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)
 | 
					TimingCategory::TimingCategory(const char* name, TimingCategory* parent)
 | 
				
			||||||
        : accumulated_duration(0) {
 | 
					        : accumulated_duration(0) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -18,8 +18,26 @@ namespace Profiling {
 | 
				
			|||||||
#define ENABLE_PROFILING 1
 | 
					#define ENABLE_PROFILING 1
 | 
				
			||||||
#endif
 | 
					#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;
 | 
					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
 | 
					 * Represents a timing category that measured time can be accounted towards. Should be declared as a
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user