From 03a9d57dc2ea52a93ce5391a29370ec08e133d54 Mon Sep 17 00:00:00 2001 From: 0forks <114709761+0forks@users.noreply.github.com> Date: Fri, 24 Feb 2023 16:59:17 +0300 Subject: [PATCH] server: Fix frame drops in SteamVR/Windows --- .../windows/WindowsNamedPipeBridge.java | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/server/src/main/java/dev/slimevr/platform/windows/WindowsNamedPipeBridge.java b/server/src/main/java/dev/slimevr/platform/windows/WindowsNamedPipeBridge.java index 2b097deae3..af89778282 100644 --- a/server/src/main/java/dev/slimevr/platform/windows/WindowsNamedPipeBridge.java +++ b/server/src/main/java/dev/slimevr/platform/windows/WindowsNamedPipeBridge.java @@ -4,6 +4,7 @@ import com.sun.jna.platform.win32.Kernel32; import com.sun.jna.platform.win32.WinBase; import com.sun.jna.platform.win32.WinError; +import com.sun.jna.platform.win32.WinNT; import com.sun.jna.ptr.IntByReference; import dev.slimevr.Main; import dev.slimevr.VRServer; @@ -23,6 +24,8 @@ public class WindowsNamedPipeBridge extends SteamVRBridge { protected final String pipeName; private final byte[] buffArray = new byte[2048]; protected WindowsPipe pipe; + protected WinNT.HANDLE dataEvent = Kernel32.INSTANCE.CreateEvent(null, false, false, null); + protected WinBase.OVERLAPPED overlapped = new WinBase.OVERLAPPED(); public WindowsNamedPipeBridge( VRServer server, @@ -34,6 +37,7 @@ public WindowsNamedPipeBridge( ) { super(server, hmd, "Named pipe thread", bridgeName, bridgeSettingsKey, shareableTrackers); this.pipeName = pipeName; + overlapped.hEvent = dataEvent; } @Override @@ -54,10 +58,14 @@ public void run() { resetPipe(); } if (!pipesUpdated) { - try { - Thread.sleep(5); // Up to 200Hz - } catch (InterruptedException e) { - e.printStackTrace(); + if (pipe.state == PipeState.OPEN) { + waitForData(); + } else { + try { + Thread.sleep(20); + } catch (InterruptedException e) { + e.printStackTrace(); + } } } } @@ -93,6 +101,14 @@ protected boolean sendMessageReal(ProtobufMessage message) { return false; } + private void waitForData() { + if (pipe.state != PipeState.OPEN) + return; + // async request for data, overlapped contains the event handle + Kernel32.INSTANCE.ReadFile(pipe.pipeHandle, null, 0, null, overlapped); + Kernel32.INSTANCE.WaitForSingleObject(dataEvent, 20); + } + private boolean updatePipe() throws IOException { if (pipe.state == PipeState.OPEN) { boolean readAnything = false;