-
Notifications
You must be signed in to change notification settings - Fork 4
Expand file tree
/
Copy pathOpenXRDiagnostics.cs
More file actions
127 lines (101 loc) · 5.52 KB
/
OpenXRDiagnostics.cs
File metadata and controls
127 lines (101 loc) · 5.52 KB
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
using Microsoft.Win32;
using Newtonsoft.Json;
namespace SLZ.XRDoctor;
public static class OpenXRDiagnostics {
private static readonly Serilog.ILogger Log = Serilog.Log.ForContext(typeof(OpenXRDiagnostics));
private const string LogTag = "OpenXR";
public static void FindActiveRuntime(out string XR_RUNTIME_JSON) {
Log.Information("[{LogTag}] Finding active runtime according to {ActiveRuntimeRegistryKey}",
LogTag, @"HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\OpenXR\1");
// I.e.
// C:\Program Files (x86)\Steam\steamapps\common\SteamVR\steamxr_win64.json
// or
// C:\Program Files\Oculus\Support\oculus-runtime\oculus_openxr_64.json
XR_RUNTIME_JSON = null;
using var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Khronos\OpenXR\1");
var o = key?.GetValue("ActiveRuntime");
if (o is string activeRuntimeStr && !string.IsNullOrWhiteSpace(activeRuntimeStr)) {
XR_RUNTIME_JSON = activeRuntimeStr;
}
}
public static void FindRegisteredRuntimes(out Dictionary<string, RuntimeManifest> runtimes) {
Log.Information("[{LogTag}] Listing available runtimes according to {AvailableRuntimesRegistryKey}",
LogTag, @"HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\OpenXR\1\AvailableRuntimes");
runtimes = new Dictionary<string, RuntimeManifest>();
using var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Khronos\OpenXR\1\AvailableRuntimes");
if (key == null) { return; }
foreach (var runtimeName in key.GetValueNames()) {
if (key.GetValue(runtimeName) is not (int and 0)) { continue; }
if (!File.Exists(runtimeName)) {
Log.Error("[{LogTag}] Runtime \"{apiLayer}\" is registered but was not found.", LogTag, runtimeName);
continue;
}
var runtimeJsonStr = File.ReadAllText(runtimeName);
if (string.IsNullOrWhiteSpace(runtimeJsonStr)) {
Log.Error("[{LogTag}] Runtime \"{apiLayer}\" is registered but its JSON was empty.", LogTag, runtimeName);
continue;
}
RuntimeManifest manifest;
try { manifest = JsonConvert.DeserializeObject<RuntimeManifest>(runtimeJsonStr); } catch (JsonException e) {
Log.Error(e, "[{LogTag}] Runtime \"{apiLayer}\" is registered but its JSON did not parse correctly.",
LogTag, runtimeName);
continue;
}
runtimes[runtimeName] = manifest;
}
}
public static void FindImplicitApiLayers(out Dictionary<string, ApiLayerManifest> layers) {
Log.Information("[{LogTag}] Listing implicit OpenXR API layers according to {ImplicitApiLayersRegistryKey}",
LogTag, @"HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\OpenXR\1\ApiLayers\Implicit");
layers = new Dictionary<string, ApiLayerManifest>();
using var key = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Khronos\OpenXR\1\ApiLayers\Implicit");
if (key == null) {
Log.Information("[{LogTag}] No implicit API layers (This isn't unusual).", LogTag);
return;
}
foreach (var layerJsonPath in key.GetValueNames()) {
if (key.GetValue(layerJsonPath) is not (int and 0)) { continue; }
if (!File.Exists(layerJsonPath)) {
Log.Error("[{LogTag}] API Layer \"{apiLayer}\" is registered but was not found.", LogTag, layerJsonPath);
continue;
}
var layerJson = File.ReadAllText(layerJsonPath);
if (string.IsNullOrWhiteSpace(layerJson)) {
Log.Error("[{LogTag}] API Layer \"{apiLayer}\" is registered but was empty.", LogTag, layerJsonPath);
continue;
}
ApiLayerManifest manifest;
try { manifest = JsonConvert.DeserializeObject<ApiLayerManifest>(layerJson); } catch (JsonException e) {
Log.Error(e, "[{LogTag}] API Layer \"{apiLayer}\" is registered but did not parse correctly.",
LogTag, layerJsonPath);
continue;
}
layers[layerJsonPath] = manifest;
}
foreach (var (path, layerManifest) in layers) {
var isDisabled = false;
var disableVar = layerManifest.ApiLayer.DisableEnvironment;
if (!string.IsNullOrWhiteSpace(disableVar)) {
isDisabled = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable(disableVar));
}
var isEnabled = false;
var enableVar = layerManifest.ApiLayer.EnableEnvironment;
if (!string.IsNullOrWhiteSpace(enableVar)) {
isEnabled = !string.IsNullOrEmpty(Environment.GetEnvironmentVariable(enableVar));
}
bool actuallyEnabled;
// ReSharper disable once ConvertIfStatementToSwitchStatement
// Overly pedantic for avoidance of confusion
if (isDisabled && isEnabled) {
actuallyEnabled = false;
} else if (isDisabled) {
actuallyEnabled = false;
} else if (isEnabled) {
actuallyEnabled = true;
} else {
actuallyEnabled = true;
}
Log.Information("[{LogTag}] API Layer \"{apiLayer}\" (Enabled: {enabled} DisableEnvironment = {disableEnvironment}, EnableEnvironment = {enableEnvironment}) {pathToManifest}", LogTag, layerManifest.ApiLayer.Name, actuallyEnabled, isDisabled, isEnabled, path);
}
}
}