From 13ecfc0a9eaf3161b979f6e9f1b6f66fa075fb51 Mon Sep 17 00:00:00 2001 From: Adam Date: Sun, 14 Nov 2021 13:41:07 -0500 Subject: [PATCH] gpu: add sync mode config This allows the additional OFF mode which has the client manage its own frame rate target without the use of vsync. On lower end systems which have a hard time delivering a frame in the vsync interval this can give a noticible performance improvement since it doesn't stall the cpu waiting for the next vblank when a frame is skipped --- .../main/java/net/runelite/api/Client.java | 1 + .../client/plugins/gpu/GpuPlugin.java | 43 ++++++++++++++----- .../client/plugins/gpu/GpuPluginConfig.java | 33 ++++++++++++++ 3 files changed, 67 insertions(+), 10 deletions(-) diff --git a/runelite-api/src/main/java/net/runelite/api/Client.java b/runelite-api/src/main/java/net/runelite/api/Client.java index 4f38b13c0c..5f1175fcdd 100644 --- a/runelite-api/src/main/java/net/runelite/api/Client.java +++ b/runelite-api/src/main/java/net/runelite/api/Client.java @@ -1953,6 +1953,7 @@ public interface Client extends GameEngine ClanSettings getClanSettings(int clanId); void setUnlockedFps(boolean unlock); + void setUnlockedFpsTarget(int fps); /** * Gets the ambient sound effects diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java index b9900a988e..b275fd7d4e 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPlugin.java @@ -394,9 +394,7 @@ public class GpuPlugin extends Plugin implements DrawCallbacks this.gl = glContext.getGL().getGL4(); - final boolean unlockFps = this.config.unlockFps(); - client.setUnlockedFps(unlockFps); - gl.setSwapInterval(unlockFps ? -1 : 0); + setupSyncMode(); if (log.isDebugEnabled()) { @@ -556,18 +554,43 @@ public class GpuPlugin extends Plugin implements DrawCallbacks { if (configChanged.getGroup().equals(GpuPluginConfig.GROUP)) { - if (configChanged.getKey().equals("unlockFps")) + if (configChanged.getKey().equals("unlockFps") + || configChanged.getKey().equals("vsyncMode") + || configChanged.getKey().equals("fpsTarget")) { - boolean unlockFps = Boolean.parseBoolean(configChanged.getNewValue()); - clientThread.invokeLater(() -> - { - client.setUnlockedFps(unlockFps); - invokeOnMainThread(() -> gl.setSwapInterval(unlockFps ? -1 : 0)); - }); + log.debug("Rebuilding sync mode"); + clientThread.invokeLater(() -> invokeOnMainThread(this::setupSyncMode)); } } } + private void setupSyncMode() + { + final boolean unlockFps = config.unlockFps(); + client.setUnlockedFps(unlockFps); + + // Without unlocked fps, the client manages sync on its 20ms timer + GpuPluginConfig.SyncMode syncMode = unlockFps + ? this.config.syncMode() + : GpuPluginConfig.SyncMode.OFF; + + switch (syncMode) + { + case ON: + gl.setSwapInterval(1); + client.setUnlockedFpsTarget(0); + break; + case OFF: + gl.setSwapInterval(0); + client.setUnlockedFpsTarget(config.fpsTarget()); // has no effect with unlockFps=false + break; + case ADAPTIVE: + gl.setSwapInterval(-1); + client.setUnlockedFpsTarget(0); + break; + } + } + private void initProgram() throws ShaderException { String versionHeader = OSType.getOSType() == OSType.Linux ? LINUX_VERSION_HEADER : WINDOWS_VERSION_HEADER; diff --git a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPluginConfig.java b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPluginConfig.java index ff69cd80e8..3d5f1095ea 100644 --- a/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPluginConfig.java +++ b/runelite-client/src/main/java/net/runelite/client/plugins/gpu/GpuPluginConfig.java @@ -159,4 +159,37 @@ public interface GpuPluginConfig extends Config { return false; } + + enum SyncMode + { + OFF, + ON, + ADAPTIVE + } + + @ConfigItem( + keyName = "vsyncMode", + name = "Vsync Mode", + description = "Method to synchronize frame rate with refresh rate", + position = 11 + ) + default SyncMode syncMode() + { + return SyncMode.ADAPTIVE; + } + + @ConfigItem( + keyName = "fpsTarget", + name = "FPS Target", + description = "Target FPS when unlock FPS is enabled and Vsync mode is OFF", + position = 12 + ) + @Range( + min = 1, + max = 999 + ) + default int fpsTarget() + { + return 60; + } }