Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix OpenXR hmd detection #26

Merged
merged 1 commit into from
Dec 17, 2023
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 43 additions & 34 deletions ScoreSaber/Core/Utils/OpenXRManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,14 @@

namespace ScoreSaber.Core.Utils {
internal static unsafe class OpenXRManager {

[DllImport("kernel32", CharSet = CharSet.Auto)]
private static extern IntPtr GetModuleHandle(
string lpModuleName);
private static extern IntPtr GetModuleHandle(string lpModuleName);

[DllImport("openxr_loader", EntryPoint = "xrGetSystemProperties", CallingConvention = CallingConvention.Cdecl)]
private static extern ulong GetSystemProperties(long* instance, ulong systemId, XrSystemProperties* properties);

[DllImport("openxr_loader", EntryPoint = "xrGetSystem", CallingConvention = CallingConvention.Cdecl)]
private static extern ulong GetSystem(long* instance, XrSystemGetInfo* getInfo, ulong* systemId);

// delegate for xrGetInstanceProcAddr() https://registry.khronos.org/OpenXR/specs/1.0/man/html/xrGetInstanceProcAddr.html
private delegate ulong xrGetInstanceProcAddrDelegate(ulong instance, StringBuilder name, IntPtr* function);
Expand All @@ -24,13 +28,13 @@ private static extern IntPtr GetModuleHandle(

// XrSystemProperties structure https://registry.khronos.org/OpenXR/specs/1.0/man/html/XrSystemProperties.html
private struct XrSystemProperties {
public ulong type; // 64 bit
public void* next; // 64 bit
public ulong systemId; // 64 bit
public int vendorId; // 32 bit
public fixed byte systemName[XR_MAX_SYSTEM_NAME_SIZE];
public XrSystemGraphicsProperties graphicsProperties;
public XrSystemTrackingProperties trackingProperties;
public ulong type; // 64 bit
public void* next; // 64 bit
public ulong systemId; // 64 bit
public int vendorId; // 32 bit
public fixed byte systemName[XR_MAX_SYSTEM_NAME_SIZE];
public XrSystemGraphicsProperties graphicsProperties;
public XrSystemTrackingProperties trackingProperties;
};

// XrSystemGraphicsProperties structure https://registry.khronos.org/OpenXR/specs/1.0/man/html/XrSystemGraphicsProperties.html
Expand All @@ -48,18 +52,18 @@ private struct XrSystemTrackingProperties {

// XrSystemGetInfo structure https://registry.khronos.org/OpenXR/specs/1.0/man/html/XrSystemGetInfo.html
private struct XrSystemGetInfo {
public ulong type; // 64 bit
public void* next; // 64 bit
public ulong formFactor;// 64 bit
public ulong type; // 64 bit
public void* next; // 64 bit
public ulong formFactor; // 64 bit
}

// https://registry.khronos.org/OpenXR/specs/1.0/man/html/XrFormFactor.html
private const int XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY = 1;

// https://registry.khronos.org/OpenXR/specs/1.0/man/html/XrStructureType.html
private const int XR_TYPE_SYSTEM_GET_INFO = 4;
private const int XR_TYPE_SYSTEM_GET_INFO = 4;
private const int XR_TYPE_SYSTEM_PROPERTIES = 5;
private const int XR_MAX_SYSTEM_NAME_SIZE = 256;
private const int XR_MAX_SYSTEM_NAME_SIZE = 256;

internal static string hmdName = null;

Expand All @@ -68,7 +72,6 @@ internal static void Initialize() {
}

private static string AttemptGetHmd() {

try {
var openXRLoaderBaseAddress = GetModuleHandle("openxr_loader");

Expand All @@ -77,43 +80,49 @@ private static string AttemptGetHmd() {
}

// Get our xrInstance
var xrGetCurrentInstance = Marshal.GetDelegateForFunctionPointer<xrGetCurrentInstanceDelegate>(openXRLoaderBaseAddress + 0x38980);
var xrCurrentInstance = new IntPtr(*(long*)xrGetCurrentInstance());
var xrInstance = *(ulong*)new IntPtr((byte*)xrCurrentInstance.ToPointer() + 8);
var xrGetCurrentInstance = Marshal.GetDelegateForFunctionPointer<xrGetCurrentInstanceDelegate>(openXRLoaderBaseAddress + 0x39480);
var xrCurrentInstance = new IntPtr(*(long*)xrGetCurrentInstance());
var xrInstance = (long*)*(ulong*)new IntPtr((byte*)xrCurrentInstance.ToPointer() + 8);

// Get our systemId
var info = new XrSystemGetInfo {
type = XR_TYPE_SYSTEM_GET_INFO,
type = XR_TYPE_SYSTEM_GET_INFO,
formFactor = XR_FORM_FACTOR_HEAD_MOUNTED_DISPLAY
};

ulong systemId = 0;
var xrGetSystem = Marshal.GetDelegateForFunctionPointer<xrGetSystemDelegate>(openXRLoaderBaseAddress + 0x2D0B);
var getSystemResult = xrGetSystem(xrInstance, &info, &systemId);
ulong systemId = 0;
var getSystemResult = GetSystem(xrInstance, &info, &systemId);

// Get our system properties
var xrGetInstanceProcAddr = Marshal.GetDelegateForFunctionPointer<xrGetInstanceProcAddrDelegate>(openXRLoaderBaseAddress + 0x5AE2);
IntPtr xrGetSystemPropertiesAddr;
ulong result = xrGetInstanceProcAddr(xrInstance, new StringBuilder("xrGetSystemProperties"), &xrGetSystemPropertiesAddr);
var getSystemPropertiesAddr = Marshal.GetDelegateForFunctionPointer<xrGetSystemPropertiesDelegate>(xrGetSystemPropertiesAddr);
if (getSystemResult != 0) {
Plugin.Log.Info($"Failed to get system from OpenXR {getSystemResult}");
return null;
}

// Get our system properties
XrSystemProperties properties;
properties.type = XR_TYPE_SYSTEM_PROPERTIES;
result = getSystemPropertiesAddr(xrInstance, systemId, &properties);
var result = GetSystemProperties(xrInstance, systemId, &properties);

if (result != 0) {
Plugin.Log.Info($"Failed to get system properties from OpenXR {result}");
return null;
}

var systemNameStrBuilder = new StringBuilder();

var systemName = "";
for (int charIndex = 0; charIndex < XR_MAX_SYSTEM_NAME_SIZE; charIndex++) {
if (properties.systemName[charIndex] == 0) {
break;
}
systemName += ((char)properties.systemName[charIndex]);

systemNameStrBuilder.Append(((char)properties.systemName[charIndex]));
}
return systemName;

return systemNameStrBuilder.ToString();
} catch (Exception ex) {
Plugin.Log.Info($"Failed to get hmd from OpenXR {ex}");
return null;
}

}
}
}
}