Skip to content

Commit 83827df

Browse files
committed
Implement UNIX timestamp conversion extention to make OVRPlugin happy.
1 parent 7f4e2ce commit 83827df

File tree

10 files changed

+144
-7
lines changed

10 files changed

+144
-7
lines changed

virtualdesktop-openxr/framework/dispatch.gen.cpp

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1319,6 +1319,48 @@ namespace RUNTIME_NAMESPACE {
13191319
return result;
13201320
}
13211321

1322+
XrResult XRAPI_CALL xrConvertTimespecTimeToTimeKHR(XrInstance instance, const struct timespec* timespecTime, XrTime* time) {
1323+
TraceLocalActivity(local);
1324+
TraceLoggingWriteStart(local, "xrConvertTimespecTimeToTimeKHR");
1325+
1326+
XrResult result;
1327+
try {
1328+
result = RUNTIME_NAMESPACE::GetInstance()->xrConvertTimespecTimeToTimeKHR(instance, timespecTime, time);
1329+
} catch (std::exception& exc) {
1330+
TraceLoggingWriteTagged(local, "xrConvertTimespecTimeToTimeKHR_Error", TLArg(exc.what(), "Error"));
1331+
ErrorLog("xrConvertTimespecTimeToTimeKHR: %s\n", exc.what());
1332+
result = XR_ERROR_RUNTIME_FAILURE;
1333+
}
1334+
1335+
TraceLoggingWriteStop(local, "xrConvertTimespecTimeToTimeKHR", TLArg(xr::ToCString(result), "Result"));
1336+
if (XR_FAILED(result)) {
1337+
ErrorLog("xrConvertTimespecTimeToTimeKHR failed with %s\n", xr::ToCString(result));
1338+
}
1339+
1340+
return result;
1341+
}
1342+
1343+
XrResult XRAPI_CALL xrConvertTimeToTimespecTimeKHR(XrInstance instance, XrTime time, struct timespec* timespecTime) {
1344+
TraceLocalActivity(local);
1345+
TraceLoggingWriteStart(local, "xrConvertTimeToTimespecTimeKHR");
1346+
1347+
XrResult result;
1348+
try {
1349+
result = RUNTIME_NAMESPACE::GetInstance()->xrConvertTimeToTimespecTimeKHR(instance, time, timespecTime);
1350+
} catch (std::exception& exc) {
1351+
TraceLoggingWriteTagged(local, "xrConvertTimeToTimespecTimeKHR_Error", TLArg(exc.what(), "Error"));
1352+
ErrorLog("xrConvertTimeToTimespecTimeKHR: %s\n", exc.what());
1353+
result = XR_ERROR_RUNTIME_FAILURE;
1354+
}
1355+
1356+
TraceLoggingWriteStop(local, "xrConvertTimeToTimespecTimeKHR", TLArg(xr::ToCString(result), "Result"));
1357+
if (XR_FAILED(result)) {
1358+
ErrorLog("xrConvertTimeToTimespecTimeKHR failed with %s\n", xr::ToCString(result));
1359+
}
1360+
1361+
return result;
1362+
}
1363+
13221364
XrResult XRAPI_CALL xrCreateVulkanInstanceKHR(XrInstance instance, const XrVulkanInstanceCreateInfoKHR* createInfo, VkInstance* vulkanInstance, VkResult* vulkanResult) {
13231365
TraceLocalActivity(local);
13241366
TraceLoggingWriteStart(local, "xrCreateVulkanInstanceKHR");
@@ -2062,6 +2104,12 @@ namespace RUNTIME_NAMESPACE {
20622104
else if (has_XR_KHR_win32_convert_performance_counter_time && apiName == "xrConvertTimeToWin32PerformanceCounterKHR") {
20632105
*function = reinterpret_cast<PFN_xrVoidFunction>(RUNTIME_NAMESPACE::xrConvertTimeToWin32PerformanceCounterKHR);
20642106
}
2107+
else if (has_XR_KHR_convert_timespec_time && apiName == "xrConvertTimespecTimeToTimeKHR") {
2108+
*function = reinterpret_cast<PFN_xrVoidFunction>(RUNTIME_NAMESPACE::xrConvertTimespecTimeToTimeKHR);
2109+
}
2110+
else if (has_XR_KHR_convert_timespec_time && apiName == "xrConvertTimeToTimespecTimeKHR") {
2111+
*function = reinterpret_cast<PFN_xrVoidFunction>(RUNTIME_NAMESPACE::xrConvertTimeToTimespecTimeKHR);
2112+
}
20652113
else if (has_XR_KHR_vulkan_enable2 && apiName == "xrCreateVulkanInstanceKHR") {
20662114
*function = reinterpret_cast<PFN_xrVoidFunction>(RUNTIME_NAMESPACE::xrCreateVulkanInstanceKHR);
20672115
}
@@ -2181,6 +2229,9 @@ namespace RUNTIME_NAMESPACE {
21812229
else if (extensionName == "XR_KHR_win32_convert_performance_counter_time") {
21822230
has_XR_KHR_win32_convert_performance_counter_time = true;
21832231
}
2232+
else if (extensionName == "XR_KHR_convert_timespec_time") {
2233+
has_XR_KHR_convert_timespec_time = true;
2234+
}
21842235
else if (extensionName == "XR_FB_display_refresh_rate") {
21852236
has_XR_FB_display_refresh_rate = true;
21862237
}

virtualdesktop-openxr/framework/dispatch.gen.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,8 @@ namespace RUNTIME_NAMESPACE {
104104
virtual XrResult xrGetVisibilityMaskKHR(XrSession session, XrViewConfigurationType viewConfigurationType, uint32_t viewIndex, XrVisibilityMaskTypeKHR visibilityMaskType, XrVisibilityMaskKHR* visibilityMask) = 0;
105105
virtual XrResult xrConvertWin32PerformanceCounterToTimeKHR(XrInstance instance, const LARGE_INTEGER* performanceCounter, XrTime* time) = 0;
106106
virtual XrResult xrConvertTimeToWin32PerformanceCounterKHR(XrInstance instance, XrTime time, LARGE_INTEGER* performanceCounter) = 0;
107+
virtual XrResult xrConvertTimespecTimeToTimeKHR(XrInstance instance, const struct timespec* timespecTime, XrTime* time) = 0;
108+
virtual XrResult xrConvertTimeToTimespecTimeKHR(XrInstance instance, XrTime time, struct timespec* timespecTime) = 0;
107109
virtual XrResult xrCreateVulkanInstanceKHR(XrInstance instance, const XrVulkanInstanceCreateInfoKHR* createInfo, VkInstance* vulkanInstance, VkResult* vulkanResult) = 0;
108110
virtual XrResult xrCreateVulkanDeviceKHR(XrInstance instance, const XrVulkanDeviceCreateInfoKHR* createInfo, VkDevice* vulkanDevice, VkResult* vulkanResult) = 0;
109111
virtual XrResult xrGetVulkanGraphicsDevice2KHR(XrInstance instance, const XrVulkanGraphicsDeviceGetInfoKHR* getInfo, VkPhysicalDevice* vulkanPhysicalDevice) = 0;
@@ -147,6 +149,7 @@ namespace RUNTIME_NAMESPACE {
147149
bool has_XR_KHR_composition_layer_cube{false};
148150
bool has_XR_KHR_visibility_mask{false};
149151
bool has_XR_KHR_win32_convert_performance_counter_time{false};
152+
bool has_XR_KHR_convert_timespec_time{false};
150153
bool has_XR_FB_display_refresh_rate{false};
151154
bool has_XR_EXT_hand_tracking{false};
152155
bool has_XR_EXT_hand_tracking_data_source{false};

virtualdesktop-openxr/framework/dispatch_generator.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@
4646
VERY_SPECIAL_API = ['xrGetInstanceProperties']
4747
EXTENSIONS = ['XR_KHR_D3D11_enable', 'XR_KHR_D3D12_enable', 'XR_KHR_vulkan_enable', 'XR_KHR_vulkan_enable2', 'XR_KHR_opengl_enable',
4848
'XR_KHR_composition_layer_depth', 'XR_KHR_composition_layer_cylinder', 'XR_KHR_composition_layer_cube', 'XR_KHR_visibility_mask',
49-
'XR_KHR_win32_convert_performance_counter_time', 'XR_FB_display_refresh_rate', 'XR_EXT_hand_tracking', 'XR_EXT_hand_tracking_data_source',
49+
'XR_KHR_win32_convert_performance_counter_time', 'XR_KHR_convert_timespec_time', 'XR_FB_display_refresh_rate', 'XR_EXT_hand_tracking', 'XR_EXT_hand_tracking_data_source',
5050
'XR_EXT_eye_gaze_interaction', 'XR_EXT_uuid', 'XR_META_headset_id', 'XR_OCULUS_audio_device_guid', 'XR_MND_headless',
5151
'XR_FB_eye_tracking_social', 'XR_FB_face_tracking', 'XR_FB_face_tracking2', 'XR_FB_hand_tracking_aim',
5252
'XR_FB_body_tracking', 'XR_META_body_tracking_full_body', 'XR_META_body_tracking_fidelity', 'XR_META_body_tracking_calibration', 'XR_HTCX_vive_tracker_interaction']

virtualdesktop-openxr/hand_tracking.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ namespace virtualdesktop_openxr {
259259
}
260260

261261
if (locateInfo->time <= 0) {
262-
// Workaround: the OculusXR plugin is passing a time of 0
262+
// Workaround: the OculusXR plugin is passing a time of 0 during initialization.
263263
if (!m_isOculusXrPlugin) {
264264
return XR_ERROR_TIME_INVALID;
265265
}

virtualdesktop-openxr/instance.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,9 @@ namespace virtualdesktop_openxr {
574574
m_extensionsTable.push_back( // Qpc timestamp conversion.
575575
{XR_KHR_WIN32_CONVERT_PERFORMANCE_COUNTER_TIME_EXTENSION_NAME,
576576
XR_KHR_win32_convert_performance_counter_time_SPEC_VERSION});
577+
m_extensionsTable.push_back( // Timespec timestamp conversion.
578+
{XR_KHR_CONVERT_TIMESPEC_TIME_EXTENSION_NAME,
579+
XR_KHR_convert_timespec_time_SPEC_VERSION});
577580

578581
m_extensionsTable.push_back( // For UWP apps.
579582
{XR_EXT_WIN32_APPCONTAINER_COMPATIBLE_EXTENSION_NAME, XR_EXT_win32_appcontainer_compatible_SPEC_VERSION});

virtualdesktop-openxr/pch.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ using Microsoft::WRL::ComPtr;
8989
// OpenXR + Windows-specific definitions.
9090
#define XR_NO_PROTOTYPES
9191
#define XR_USE_PLATFORM_WIN32
92+
#define XR_USE_TIMESPEC
9293
#define XR_USE_GRAPHICS_API_D3D11
9394
#define XR_USE_GRAPHICS_API_D3D12
9495
#define XR_USE_GRAPHICS_API_VULKAN

virtualdesktop-openxr/perf_counter.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,4 +98,66 @@ namespace virtualdesktop_openxr {
9898
return XR_SUCCESS;
9999
}
100100

101+
// https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#xrConvertTimespecTimeToTimeKHR
102+
XrResult OpenXrRuntime::xrConvertTimespecTimeToTimeKHR(XrInstance instance,
103+
const struct timespec* timespecTime,
104+
XrTime* time) {
105+
TraceLoggingWrite(g_traceProvider,
106+
"xrConvertTimespecTimeToTimeKHR",
107+
TLXArg(instance, "Instance"),
108+
TLArg(timespecTime->tv_sec, "PerformanceCounterSec"),
109+
TLArg(timespecTime->tv_nsec, "PerformanceCounterNSec"));
110+
111+
if (!has_XR_KHR_convert_timespec_time) {
112+
return XR_ERROR_FUNCTION_UNSUPPORTED;
113+
}
114+
115+
if (!m_instanceCreated || instance != (XrInstance)1) {
116+
return XR_ERROR_HANDLE_INVALID;
117+
}
118+
119+
double ovrTime = (double)timespecTime->tv_sec + (timespecTime->tv_nsec / 1e9f);
120+
ovrTime += m_ovrTimeFromTimeSpecTimeOffset;
121+
122+
*time = ovrTimeToXrTime(ovrTime);
123+
124+
TraceLoggingWrite(g_traceProvider, "xrConvertTimespecTimeToTimeKHR", TLArg(*time, "Time"));
125+
126+
return XR_SUCCESS;
127+
}
128+
129+
// https://www.khronos.org/registry/OpenXR/specs/1.0/html/xrspec.html#xrConvertTimeToTimespecTimeKHR
130+
XrResult OpenXrRuntime::xrConvertTimeToTimespecTimeKHR(XrInstance instance,
131+
XrTime time,
132+
struct timespec* timespecTime) {
133+
TraceLoggingWrite(
134+
g_traceProvider, "xrConvertTimeToTimespecTimeKHR", TLXArg(instance, "Instance"), TLArg(time, "Time"));
135+
136+
if (!has_XR_KHR_convert_timespec_time) {
137+
return XR_ERROR_FUNCTION_UNSUPPORTED;
138+
}
139+
140+
if (!m_instanceCreated || instance != (XrInstance)1) {
141+
return XR_ERROR_HANDLE_INVALID;
142+
}
143+
144+
if (time <= 0) {
145+
return XR_ERROR_TIME_INVALID;
146+
}
147+
148+
double ovrTime = xrTimeToOvrTime(time);
149+
ovrTime -= m_ovrTimeFromTimeSpecTimeOffset;
150+
151+
timespecTime->tv_sec = (time_t)ovrTime;
152+
double integerPart = (double)timespecTime->tv_sec;
153+
timespecTime->tv_nsec = (long)(modf(ovrTime, &integerPart) * 1e9);
154+
155+
TraceLoggingWrite(g_traceProvider,
156+
"xrConvertTimeToTimespecTimeKHR",
157+
TLArg(timespecTime->tv_sec, "PerformanceCounterSec"),
158+
TLArg(timespecTime->tv_nsec, "PerformanceCounterNSec"));
159+
160+
return XR_SUCCESS;
161+
}
162+
101163
} // namespace virtualdesktop_openxr

virtualdesktop-openxr/runtime.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,12 @@ namespace virtualdesktop_openxr {
222222
XrResult xrConvertTimeToWin32PerformanceCounterKHR(XrInstance instance,
223223
XrTime time,
224224
LARGE_INTEGER* performanceCounter) override;
225+
XrResult xrConvertTimespecTimeToTimeKHR(XrInstance instance,
226+
const struct timespec* timespecTime,
227+
XrTime* time) override;
228+
XrResult xrConvertTimeToTimespecTimeKHR(XrInstance instance,
229+
XrTime time,
230+
struct timespec* timespecTime) override;
225231
XrResult xrCreateVulkanInstanceKHR(XrInstance instance,
226232
const XrVulkanInstanceCreateInfoKHR* createInfo,
227233
VkInstance* vulkanInstance,
@@ -615,6 +621,7 @@ namespace virtualdesktop_openxr {
615621
mutable std::optional<float> m_lastKnownFloorHeight;
616622
LARGE_INTEGER m_qpcFrequency{};
617623
double m_ovrTimeFromQpcTimeOffset{0};
624+
double m_ovrTimeFromTimeSpecTimeOffset{0};
618625
XrPath m_stringIndex{0};
619626
using MappingFunction = std::function<bool(const Action&, XrPath, ActionSource&)>;
620627
using CheckValidPathFunction = std::function<bool(const std::string&)>;

virtualdesktop-openxr/space.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ namespace virtualdesktop_openxr {
209209
}
210210

211211
if (time <= 0) {
212-
// Workaround: the OculusXR plugin is passing a time of 0 during early init and will refuse to submit frames
212+
// Workaround: the OculusXR plugin is passing a time of 0 during initialization.
213213
// if we error out.
214214
if (!m_isOculusXrPlugin) {
215215
return XR_ERROR_TIME_INVALID;
@@ -466,10 +466,10 @@ namespace virtualdesktop_openxr {
466466
velocity->velocityFlags = 0;
467467
}
468468

469-
// Workaround for OVRPlugin and REFramework incorrect use of xrLocateViews().
469+
// Workaround for OculusXR and REFramework incorrect use of xrLocateViews().
470470
const bool ignoreFloorHeight = time <= 1;
471471

472-
// OVRPlugin likes to specify random XrTime. Clamp to t-1s.
472+
// OculusXR likes to specify random XrTime. Clamp to t-1s.
473473
if (m_lastPredictedDisplayTime) {
474474
time = std::max(time, m_lastPredictedDisplayTime - 1'000'000'000);
475475
}

virtualdesktop-openxr/system.cpp

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -441,8 +441,18 @@ namespace virtualdesktop_openxr {
441441
const double qpcTime = (double)now.QuadPart / m_qpcFrequency.QuadPart;
442442
m_ovrTimeFromQpcTimeOffset = std::min(m_ovrTimeFromQpcTimeOffset, ovr_GetTimeInSeconds() - qpcTime);
443443
}
444-
TraceLoggingWrite(
445-
g_traceProvider, "ConvertTime", TLArg(m_ovrTimeFromQpcTimeOffset, "OvrTimeFromQpcTimeOffset"));
444+
m_ovrTimeFromTimeSpecTimeOffset = INFINITY;
445+
for (int i = 0; i < 100; i++) {
446+
timespec now{};
447+
timespec_get(&now, TIME_UTC);
448+
const double tsTime = (double)now.tv_sec + (now.tv_nsec / 1e9f);
449+
m_ovrTimeFromTimeSpecTimeOffset =
450+
std::min(m_ovrTimeFromTimeSpecTimeOffset, ovr_GetTimeInSeconds() - tsTime);
451+
}
452+
TraceLoggingWrite(g_traceProvider,
453+
"ConvertTime",
454+
TLArg(m_ovrTimeFromQpcTimeOffset, "OvrTimeFromQpcTimeOffset"),
455+
TLArg(m_ovrTimeFromTimeSpecTimeOffset, "OvrTimeFromTimeSpecTimeOffset"));
446456

447457
m_isLowVideoMemorySystem = false;
448458
{

0 commit comments

Comments
 (0)