Merge pull request #260 from OpenVR-Advanced-Settings/vsync-options
Add disable vsync and custom tickrate options
This commit is contained in:
+128
-22
@@ -313,6 +313,32 @@ OverlayController::OverlayController( bool desktopMode,
|
|||||||
appSettings()->setValue( "keyboardThree", defaultDiscordMuteBindings );
|
appSettings()->setValue( "keyboardThree", defaultDiscordMuteBindings );
|
||||||
}
|
}
|
||||||
appSettings()->endGroup();
|
appSettings()->endGroup();
|
||||||
|
|
||||||
|
// Keep the settings for vsyncDisabled here in main overlaycontroller
|
||||||
|
appSettings()->beginGroup( "applicationSettings" );
|
||||||
|
auto value = appSettings()->value( "vsyncDisabled", m_vsyncDisabled );
|
||||||
|
if ( value.isValid() && !value.isNull() )
|
||||||
|
{
|
||||||
|
m_vsyncDisabled = value.toBool();
|
||||||
|
}
|
||||||
|
value = appSettings()->value( "customTickRateMs", m_customTickRateMs );
|
||||||
|
if ( value.isValid() && !value.isNull() )
|
||||||
|
{
|
||||||
|
// keep sane tickrate (between 1~k_maxCustomTickRate)
|
||||||
|
if ( value.toInt() < 1 )
|
||||||
|
{
|
||||||
|
m_customTickRateMs = 1;
|
||||||
|
}
|
||||||
|
else if ( value.toInt() > k_maxCustomTickRate )
|
||||||
|
{
|
||||||
|
m_customTickRateMs = k_maxCustomTickRate;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_customTickRateMs = value.toInt();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
appSettings()->endGroup();
|
||||||
}
|
}
|
||||||
|
|
||||||
OverlayController::~OverlayController()
|
OverlayController::~OverlayController()
|
||||||
@@ -706,35 +732,115 @@ void OverlayController::processInputBindings()
|
|||||||
processKeyboardBindings();
|
processKeyboardBindings();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool OverlayController::vsyncDisabled() const
|
||||||
|
{
|
||||||
|
return m_vsyncDisabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OverlayController::setVsyncDisabled( bool value, bool notify )
|
||||||
|
{
|
||||||
|
if ( m_vsyncDisabled == value )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
m_vsyncDisabled = value;
|
||||||
|
appSettings()->beginGroup( "applicationSettings" );
|
||||||
|
appSettings()->setValue( "vsyncDisabled", m_vsyncDisabled );
|
||||||
|
appSettings()->endGroup();
|
||||||
|
appSettings()->sync();
|
||||||
|
if ( notify )
|
||||||
|
{
|
||||||
|
emit vsyncDisabledChanged( m_vsyncDisabled );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int OverlayController::customTickRateMs() const
|
||||||
|
{
|
||||||
|
return m_customTickRateMs;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OverlayController::setCustomTickRateMs( int value, bool notify )
|
||||||
|
{
|
||||||
|
if ( m_customTickRateMs == value )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// keep m_customTickRateMs sane (between 1~k_maxCustomTickRate)
|
||||||
|
if ( value < 1 )
|
||||||
|
{
|
||||||
|
m_customTickRateMs = 1;
|
||||||
|
}
|
||||||
|
else if ( value > k_maxCustomTickRate )
|
||||||
|
{
|
||||||
|
m_customTickRateMs = k_maxCustomTickRate;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_customTickRateMs = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
appSettings()->beginGroup( "applicationSettings" );
|
||||||
|
appSettings()->setValue( "customTickRateMs", m_customTickRateMs );
|
||||||
|
appSettings()->endGroup();
|
||||||
|
appSettings()->sync();
|
||||||
|
if ( notify )
|
||||||
|
{
|
||||||
|
emit customTickRateMsChanged( m_customTickRateMs );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// vsync implementation:
|
// vsync implementation:
|
||||||
// (this function triggers every 1ms)
|
// this function triggers every 1ms
|
||||||
|
// this function should remain lightweight and only check if it's time to run
|
||||||
|
// mainEventLoop() or not.
|
||||||
void OverlayController::OnTimeoutPumpEvents()
|
void OverlayController::OnTimeoutPumpEvents()
|
||||||
{
|
{
|
||||||
// get the current frame number from the VRSystem frame counter
|
if ( m_vsyncDisabled )
|
||||||
vr::VRSystem()->GetTimeSinceLastVsync( nullptr, &m_currentFrame );
|
|
||||||
|
|
||||||
// Check if we are in the next frame yet
|
|
||||||
if ( m_currentFrame > m_lastFrame )
|
|
||||||
{
|
{
|
||||||
// If the frame has advanced since last check, it's time for our main
|
// check if it's time for a custom tick rate tick
|
||||||
// event loop. (this function should trigger about every 11ms assuming
|
if ( m_customTickRateCounter > m_customTickRateMs )
|
||||||
// 90fps compositor)
|
{
|
||||||
mainEventLoop();
|
mainEventLoop();
|
||||||
|
m_customTickRateCounter = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_customTickRateCounter++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// wait for the next frame after executing our main event loop once.
|
// vsync is enabled
|
||||||
m_lastFrame = m_currentFrame;
|
else
|
||||||
m_vsyncTooLateCounter = 0;
|
|
||||||
}
|
|
||||||
else if ( m_vsyncTooLateCounter >= k_nonVsyncTickRate )
|
|
||||||
{
|
{
|
||||||
mainEventLoop();
|
// get the current frame number from the VRSystem frame counter
|
||||||
// m_lastFrame = m_currentFrame + 1 skips the next vsync frame in case
|
vr::VRSystem()->GetTimeSinceLastVsync( nullptr, &m_currentFrame );
|
||||||
// it was just about to trigger, to prevent double updates faster than
|
|
||||||
// 11ms.
|
// Check if we are in the next frame yet
|
||||||
m_lastFrame = m_currentFrame + 1;
|
if ( m_currentFrame > m_lastFrame )
|
||||||
m_vsyncTooLateCounter = 0;
|
{
|
||||||
|
// If the frame has advanced since last check, it's time for our
|
||||||
|
// main event loop. (this function should trigger about every 11ms
|
||||||
|
// assuming 90fps compositor)
|
||||||
|
mainEventLoop();
|
||||||
|
|
||||||
|
// wait for the next frame after executing our main event loop once.
|
||||||
|
m_lastFrame = m_currentFrame;
|
||||||
|
m_vsyncTooLateCounter = 0;
|
||||||
|
}
|
||||||
|
else if ( m_vsyncTooLateCounter >= k_nonVsyncTickRate )
|
||||||
|
{
|
||||||
|
mainEventLoop();
|
||||||
|
// m_lastFrame = m_currentFrame + 1 skips the next vsync frame in
|
||||||
|
// case it was just about to trigger, to prevent double updates
|
||||||
|
// faster than 11ms.
|
||||||
|
m_lastFrame = m_currentFrame + 1;
|
||||||
|
m_vsyncTooLateCounter = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_vsyncTooLateCounter++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
m_vsyncTooLateCounter++;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OverlayController::mainEventLoop()
|
void OverlayController::mainEventLoop()
|
||||||
|
|||||||
@@ -72,12 +72,17 @@ constexpr int k_utilitiesSettingsUpdateCounter = 19;
|
|||||||
// k_nonVsyncTickRate determines number of ms we wait to force the next event
|
// k_nonVsyncTickRate determines number of ms we wait to force the next event
|
||||||
// loop tick when vsync is too late due to dropped frames.
|
// loop tick when vsync is too late due to dropped frames.
|
||||||
constexpr int k_nonVsyncTickRate = 20;
|
constexpr int k_nonVsyncTickRate = 20;
|
||||||
|
constexpr int k_maxCustomTickRate = 999;
|
||||||
constexpr int k_hmdRotationCounterUpdateRate = 7;
|
constexpr int k_hmdRotationCounterUpdateRate = 7;
|
||||||
|
|
||||||
class OverlayController : public QObject
|
class OverlayController : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY( bool m_desktopMode READ isDesktopMode )
|
Q_PROPERTY( bool m_desktopMode READ isDesktopMode )
|
||||||
|
Q_PROPERTY( bool vsyncDisabled READ vsyncDisabled WRITE setVsyncDisabled
|
||||||
|
NOTIFY vsyncDisabledChanged )
|
||||||
|
Q_PROPERTY( int customTickRateMs READ customTickRateMs WRITE
|
||||||
|
setCustomTickRateMs NOTIFY customTickRateMsChanged )
|
||||||
|
|
||||||
private:
|
private:
|
||||||
vr::VROverlayHandle_t m_ulOverlayHandle = vr::k_ulOverlayHandleInvalid;
|
vr::VROverlayHandle_t m_ulOverlayHandle = vr::k_ulOverlayHandleInvalid;
|
||||||
@@ -99,6 +104,8 @@ private:
|
|||||||
|
|
||||||
bool m_desktopMode;
|
bool m_desktopMode;
|
||||||
bool m_noSound;
|
bool m_noSound;
|
||||||
|
bool m_vsyncDisabled = false;
|
||||||
|
int m_customTickRateMs = 20;
|
||||||
|
|
||||||
QUrl m_runtimePathUrl;
|
QUrl m_runtimePathUrl;
|
||||||
|
|
||||||
@@ -111,6 +118,7 @@ private:
|
|||||||
uint64_t m_currentFrame = 0;
|
uint64_t m_currentFrame = 0;
|
||||||
uint64_t m_lastFrame = 0;
|
uint64_t m_lastFrame = 0;
|
||||||
int m_vsyncTooLateCounter = 0;
|
int m_vsyncTooLateCounter = 0;
|
||||||
|
int m_customTickRateCounter = 0;
|
||||||
|
|
||||||
input::SteamIVRInput m_actions;
|
input::SteamIVRInput m_actions;
|
||||||
|
|
||||||
@@ -194,6 +202,9 @@ public:
|
|||||||
vr::VREvent_t* pEvent );
|
vr::VREvent_t* pEvent );
|
||||||
void mainEventLoop();
|
void mainEventLoop();
|
||||||
|
|
||||||
|
bool vsyncDisabled() const;
|
||||||
|
int customTickRateMs() const;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
void renderOverlay();
|
void renderOverlay();
|
||||||
void OnRenderRequest();
|
void OnRenderRequest();
|
||||||
@@ -207,8 +218,13 @@ public slots:
|
|||||||
void setAlarm01SoundVolume( float vol );
|
void setAlarm01SoundVolume( float vol );
|
||||||
void cancelAlarm01Sound();
|
void cancelAlarm01Sound();
|
||||||
|
|
||||||
|
void setVsyncDisabled( bool value, bool notify = true );
|
||||||
|
void setCustomTickRateMs( int value, bool notify = true );
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void keyBoardInputSignal( QString input, unsigned long userValue = 0 );
|
void keyBoardInputSignal( QString input, unsigned long userValue = 0 );
|
||||||
|
void vsyncDisabledChanged( bool value );
|
||||||
|
void customTickRateMsChanged( int value );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static QSettings* _appSettings;
|
static QSettings* _appSettings;
|
||||||
|
|||||||
@@ -50,16 +50,78 @@ MyStackViewPage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
RowLayout {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
|
||||||
|
MyToggleButton {
|
||||||
|
id: vsyncDisabledToggle
|
||||||
|
text: "Disable App Vsync"
|
||||||
|
onCheckedChanged: {
|
||||||
|
OverlayController.setVsyncDisabled(checked, true)
|
||||||
|
customTickRateText.visible = checked
|
||||||
|
customTickRateLabel.visible = checked
|
||||||
|
customTickRateMsLabel.visible = checked
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MyText {
|
||||||
|
id: customTickRateLabel
|
||||||
|
text: "Custom Tick Rate: "
|
||||||
|
horizontalAlignment: Text.AlignRight
|
||||||
|
Layout.leftMargin: 20
|
||||||
|
Layout.rightMargin: 2
|
||||||
|
}
|
||||||
|
|
||||||
|
MyTextField {
|
||||||
|
id: customTickRateText
|
||||||
|
text: "20"
|
||||||
|
keyBoardUID: 1001
|
||||||
|
Layout.preferredWidth: 140
|
||||||
|
Layout.leftMargin: 10
|
||||||
|
Layout.rightMargin: 1
|
||||||
|
horizontalAlignment: Text.AlignHCenter
|
||||||
|
function onInputEvent(input) {
|
||||||
|
var val = parseInt(input, 10)
|
||||||
|
if (!isNaN(val)) {
|
||||||
|
OverlayController.customTickRateMs = val
|
||||||
|
text = OverlayController.customTickRateMs
|
||||||
|
} else {
|
||||||
|
text = OverlayController.customTickRateMs
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
MyText {
|
||||||
|
id: customTickRateMsLabel
|
||||||
|
text: "ms"
|
||||||
|
horizontalAlignment: Text.AlignLeft
|
||||||
|
Layout.leftMargin: 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Item {
|
||||||
|
Layout.fillWidth: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Item {
|
Item {
|
||||||
Layout.fillHeight: true
|
Layout.fillHeight: true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
settingsAutoStartToggle.checked = SettingsTabController.autoStartEnabled
|
settingsAutoStartToggle.checked = SettingsTabController.autoStartEnabled
|
||||||
forceReviveToggle.checked = SettingsTabController.forceRevivePage
|
forceReviveToggle.checked = SettingsTabController.forceRevivePage
|
||||||
|
|
||||||
allowExternalEditsToggle.checked = MoveCenterTabController.allowExternalEdits
|
allowExternalEditsToggle.checked = MoveCenterTabController.allowExternalEdits
|
||||||
oldStyleMotionToggle.checked = MoveCenterTabController.oldStyleMotion
|
oldStyleMotionToggle.checked = MoveCenterTabController.oldStyleMotion
|
||||||
universeCenteredRotationToggle.checked = MoveCenterTabController.universeCenteredRotation
|
universeCenteredRotationToggle.checked = MoveCenterTabController.universeCenteredRotation
|
||||||
|
|
||||||
|
customTickRateText.text = OverlayController.customTickRateMs
|
||||||
|
vsyncDisabledToggle.checked = OverlayController.vsyncDisabled
|
||||||
|
customTickRateText.visible = vsyncDisabledToggle.checked
|
||||||
|
customTickRateLabel.visible = vsyncDisabledToggle.checked
|
||||||
|
customTickRateMsLabel.visible = vsyncDisabledToggle.checked
|
||||||
}
|
}
|
||||||
|
|
||||||
Connections {
|
Connections {
|
||||||
@@ -84,5 +146,18 @@ MyStackViewPage {
|
|||||||
universeCenteredRotationToggle.checked = MoveCenterTabController.universeCenteredRotation
|
universeCenteredRotationToggle.checked = MoveCenterTabController.universeCenteredRotation
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Connections {
|
||||||
|
target: OverlayController
|
||||||
|
onVsyncDisabledChanged: {
|
||||||
|
vsyncDisabledToggle.checked = OverlayController.vsyncDisabled
|
||||||
|
customTickRateText.visible = vsyncDisabledToggle.checked
|
||||||
|
customTickRateLabel.visible = vsyncDisabledToggle.checked
|
||||||
|
customTickRateMsLabel.visible = vsyncDisabledToggle.checked
|
||||||
|
}
|
||||||
|
onCustomTickRateMsChanged: {
|
||||||
|
customTickRateText.text = OverlayController.customTickRateMs
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ MyDialogOkCancelPopup {
|
|||||||
}
|
}
|
||||||
MyTextField {
|
MyTextField {
|
||||||
id: pttNewProfileName
|
id: pttNewProfileName
|
||||||
keyBoardUID: 590
|
keyBoardUID: 591
|
||||||
color: "#cccccc"
|
color: "#cccccc"
|
||||||
text: ""
|
text: ""
|
||||||
Layout.fillWidth: true
|
Layout.fillWidth: true
|
||||||
|
|||||||
Reference in New Issue
Block a user