@@ -330,18 +330,26 @@ namespace virtualdesktop_openxr {
330330
331331 // Debug option to test reprojection.
332332 if (m_jiggleViewRotations) {
333- static std::mt19937_64 randGen (0 );
334-
335- // Scale jitter by FOV.
336- const float randMax = (views[i].fov .angleRight - views[i].fov .angleLeft ) * 0 .06f ;
337- std::uniform_real_distribution<float > dist (-randMax, randMax);
338- const auto randomQuatJiggle =
339- DirectX::XMVectorSet (dist (randGen), dist (randGen), dist (randGen), dist (randGen));
340- const auto originalPoseOrientation = xr::math::LoadXrQuaternion (views[i].pose .orientation );
341- const auto poseOrientationWithJiggle =
342- DirectX::XMVectorAdd (originalPoseOrientation, randomQuatJiggle);
343- xr::math::StoreXrQuaternion (&views[i].pose .orientation ,
344- DirectX::XMVector4Normalize (poseOrientationWithJiggle));
333+ // To investigate cross-frame or within-frame issues.
334+ const bool useSameJiggleForEachDisplayTime = false ;
335+ if (!useSameJiggleForEachDisplayTime ||
336+ m_lastRequestedViewDisplayTime != viewLocateInfo->displayTime ) {
337+ static std::mt19937_64 randGen (0 );
338+
339+ // Scale jitter by FOV.
340+ const float randMax = (views[i].fov .angleRight - views[i].fov .angleLeft ) * 0 .06f ;
341+ std::uniform_real_distribution<float > dist (-randMax, randMax);
342+ const auto randomQuatJiggle =
343+ DirectX::XMVectorSet (dist (randGen), dist (randGen), dist (randGen), dist (randGen));
344+ const auto originalPoseOrientation = xr::math::LoadXrQuaternion (views[i].pose .orientation );
345+ const auto poseOrientationWithJiggle =
346+ DirectX::XMVectorAdd (originalPoseOrientation, randomQuatJiggle);
347+ xr::math::StoreXrQuaternion (&views[i].pose .orientation ,
348+ DirectX::XMVector4Normalize (poseOrientationWithJiggle));
349+ } else if (m_lastValidViews) {
350+ *views = m_lastValidViews.value ();
351+ }
352+ m_lastValidViews = *views;
345353 }
346354
347355 TraceLoggingWrite (g_traceProvider,
@@ -359,14 +367,15 @@ namespace virtualdesktop_openxr {
359367 } else {
360368 m_lastSeenIpd.reset ();
361369 }
362-
363370 } else {
364371 // All or nothing.
365372 viewState->viewStateFlags = 0 ;
366373 TraceLoggingWrite (g_traceProvider, " xrLocateViews" , TLArg (viewState->viewStateFlags , " ViewStateFlags" ));
367374 }
368375 }
369376
377+ m_lastRequestedViewDisplayTime = viewLocateInfo->displayTime ;
378+
370379 return XR_SUCCESS;
371380 }
372381
@@ -599,6 +608,13 @@ namespace virtualdesktop_openxr {
599608 XrSpaceLocationFlags locationFlags = 0 ;
600609 ovrPoseStatef state{};
601610 ovrTrackedDeviceType hmd = ovrTrackedDevice_HMD;
611+
612+ // OVRPlugin assumes that xrLocateViews() with the same displayTime returns the same value across calls, which
613+ // violates OpenXR spec 1.0 per 10.2. View and Projection State: "Repeatedly calling xrLocateViews with the same
614+ // time may not necessarily return the same result. Instead the prediction gets increasingly accurate as the
615+ // function is called closer to the given time for which a prediction is made.".
616+ const bool enablePredictionRefinement = !(m_isUnity && m_isOculusXrPlugin);
617+
602618 const auto result = ovr_GetDevicePoses (m_ovrSession, &hmd, 1 , xrTimeToOvrTime (time), &state);
603619 if (result == ovrError_LostTracking) {
604620 TraceLoggingWrite (g_traceProvider, " OVR_HmdPoseNotTracking" );
@@ -615,7 +631,15 @@ namespace virtualdesktop_openxr {
615631 if (isTracked) {
616632 locationFlags |= (XR_SPACE_LOCATION_ORIENTATION_VALID_BIT | XR_SPACE_LOCATION_ORIENTATION_TRACKED_BIT |
617633 XR_SPACE_LOCATION_POSITION_VALID_BIT | XR_SPACE_LOCATION_POSITION_TRACKED_BIT);
618- pose = ovrPoseToXrPose (state.ThePose );
634+ if (enablePredictionRefinement || time != m_lastRequestedViewDisplayTime) {
635+ pose = ovrPoseToXrPose (state.ThePose );
636+ } else if (m_lastValidHmdPose) {
637+ // Return the same pose for the same timestamp.
638+ pose = m_lastValidHmdPose.value ();
639+ } else {
640+ locationFlags = 0 ;
641+ pose = Pose::Identity ();
642+ }
619643 } else {
620644 if (m_lastValidHmdPose) {
621645 locationFlags |= XR_SPACE_LOCATION_ORIENTATION_VALID_BIT | XR_SPACE_LOCATION_POSITION_VALID_BIT;
0 commit comments