blob: 9601dc96f784f3379cb969e38ea96309afcd8050 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
#pragma once
#include "thread.h"
#include "util_time.h"
namespace dxvk {
/**
* \brief Frame rate limiter
*
* Provides functionality to stall an application
* thread in order to maintain a given frame rate.
*/
class FpsLimiter {
public:
/**
* \brief Creates frame rate limiter
*/
FpsLimiter();
~FpsLimiter();
/**
* \brief Sets target frame rate
* \param [in] frameRate Target frame rate
*/
void setTargetFrameRate(double frameRate);
/**
* \brief Sets display refresh rate
*
* This information is used to decide whether or not
* the limiter should be active in the first place in
* case vertical synchronization is enabled.
* \param [in] refreshRate Current refresh rate
*/
void setDisplayRefreshRate(double refreshRate);
/**
* \brief Stalls calling thread as necessary
*
* Blocks the calling thread if the limiter is enabled
* and the time since the last call to \ref delay is
* shorter than the target interval.
* \param [in] vsyncEnabled \c true if vsync is enabled
*/
void delay(bool vsyncEnabled);
/**
* \brief Checks whether the frame rate limiter is enabled
* \returns \c true if the target frame rate is non-zero.
*/
bool isEnabled() const {
return m_targetInterval != NtTimerDuration::zero();
}
private:
using TimePoint = dxvk::high_resolution_clock::time_point;
using NtTimerDuration = std::chrono::duration<int64_t, std::ratio<1, 10000000>>;
using NtQueryTimerResolutionProc = UINT (WINAPI *) (ULONG*, ULONG*, ULONG*);
using NtSetTimerResolutionProc = UINT (WINAPI *) (ULONG, BOOL, ULONG*);
using NtDelayExecutionProc = UINT (WINAPI *) (BOOL, LARGE_INTEGER*);
dxvk::mutex m_mutex;
NtTimerDuration m_targetInterval = NtTimerDuration::zero();
NtTimerDuration m_refreshInterval = NtTimerDuration::zero();
NtTimerDuration m_deviation = NtTimerDuration::zero();
TimePoint m_lastFrame;
bool m_initialized = false;
bool m_envOverride = false;
NtTimerDuration m_sleepGranularity = NtTimerDuration::zero();
NtTimerDuration m_sleepThreshold = NtTimerDuration::zero();
NtDelayExecutionProc NtDelayExecution = nullptr;
TimePoint sleep(TimePoint t0, NtTimerDuration duration);
void initialize();
};
}
|