@@ -88,7 +88,10 @@ struct DeviceDelegateOculusVR::State {
8888 vrb::FBOPtr previousFBO;
8989 vrb::CameraEyePtr cameras[2 ];
9090 uint32_t frameIndex = 0 ;
91+ FramePrediction framePrediction = FramePrediction::NO_FRAME_AHEAD;
92+ double prevPredictedDisplayTime = 0 ;
9193 double predictedDisplayTime = 0 ;
94+ ovrTracking2 prevPredictedTracking = {};
9295 ovrTracking2 predictedTracking = {};
9396 ovrTracking2 discardPredictedTracking = {};
9497 uint32_t discardedFrameIndex = 0 ;
@@ -818,15 +821,28 @@ DeviceDelegateOculusVR::ProcessEvents() {
818821 }
819822}
820823
824+ bool
825+ DeviceDelegateOculusVR::SupportsFramePrediction (FramePrediction aPrediction) const {
826+ return true ;
827+ }
828+
821829void
822- DeviceDelegateOculusVR::StartFrame () {
830+ DeviceDelegateOculusVR::StartFrame (const FramePrediction aPrediction ) {
823831 if (!m.ovr ) {
824832 VRB_LOG (" StartFrame called while not in VR mode" );
825833 return ;
826834 }
827835
836+ m.framePrediction = aPrediction;
828837 m.frameIndex ++;
829- m.predictedDisplayTime = vrapi_GetPredictedDisplayTime (m.ovr , m.frameIndex );
838+ if (aPrediction == FramePrediction::ONE_FRAME_AHEAD) {
839+ m.prevPredictedDisplayTime = m.predictedDisplayTime ;
840+ m.prevPredictedTracking = m.predictedTracking ;
841+ m.predictedDisplayTime = vrapi_GetPredictedDisplayTime (m.ovr , m.frameIndex + 1 );
842+ } else {
843+ m.predictedDisplayTime = vrapi_GetPredictedDisplayTime (m.ovr , m.frameIndex );
844+ }
845+
830846 m.predictedTracking = vrapi_GetPredictedTracking2 (m.ovr , m.predictedDisplayTime );
831847
832848 float ipd = vrapi_GetInterpupillaryDistance (&m.predictedTracking );
@@ -908,7 +924,7 @@ DeviceDelegateOculusVR::BindEye(const device::Eye aWhich) {
908924}
909925
910926void
911- DeviceDelegateOculusVR::EndFrame (const bool aDiscard ) {
927+ DeviceDelegateOculusVR::EndFrame (const FrameEndMode aEndMode ) {
912928 if (!m.ovr ) {
913929 VRB_LOG (" EndFrame called while not in VR mode" );
914930 return ;
@@ -918,11 +934,15 @@ DeviceDelegateOculusVR::EndFrame(const bool aDiscard) {
918934 m.currentFBO .reset ();
919935 }
920936
921- if (aDiscard) {
937+ const bool frameAhead = m.framePrediction == FramePrediction::ONE_FRAME_AHEAD;
938+ const ovrTracking2& tracking = frameAhead ? m.prevPredictedTracking : m.predictedTracking ;
939+ const double displayTime = frameAhead ? m.prevPredictedDisplayTime : m.predictedDisplayTime ;
940+
941+ if (aEndMode == FrameEndMode::DISCARD) {
922942 // Reuse the last frame when a frame is discarded.
923943 // The last frame is timewarped by the VR compositor.
924944 if (m.discardCount == 0 ) {
925- m.discardPredictedTracking = m. predictedTracking ;
945+ m.discardPredictedTracking = tracking ;
926946 m.discardedFrameIndex = m.frameIndex ;
927947 }
928948 m.discardCount ++;
@@ -936,13 +956,13 @@ DeviceDelegateOculusVR::EndFrame(const bool aDiscard) {
936956 const ovrLayerHeader2* layers[ovrMaxLayerCount] = {};
937957
938958 if (m.cubeLayer && m.cubeLayer ->IsLoaded () && m.cubeLayer ->IsDrawRequested ()) {
939- m.cubeLayer ->Update (m. predictedTracking , m.clearColorSwapChain );
959+ m.cubeLayer ->Update (tracking , m.clearColorSwapChain );
940960 layers[layerCount++] = m.cubeLayer ->Header ();
941961 m.cubeLayer ->ClearRequestDraw ();
942962 }
943963
944964 if (m.equirectLayer && m.equirectLayer ->IsDrawRequested ()) {
945- m.equirectLayer ->Update (m. predictedTracking , m.clearColorSwapChain );
965+ m.equirectLayer ->Update (tracking , m.clearColorSwapChain );
946966 layers[layerCount++] = m.equirectLayer ->Header ();
947967 m.equirectLayer ->ClearRequestDraw ();
948968 }
@@ -955,7 +975,7 @@ DeviceDelegateOculusVR::EndFrame(const bool aDiscard) {
955975 // Draw back layers
956976 for (const OculusLayerPtr& layer: m.uiLayers ) {
957977 if (!layer->GetDrawInFront () && layer->IsDrawRequested () && (layerCount < ovrMaxLayerCount - 1 )) {
958- layer->Update (m. predictedTracking , m.clearColorSwapChain );
978+ layer->Update (tracking , m.clearColorSwapChain );
959979 layers[layerCount++] = layer->Header ();
960980 layer->ClearRequestDraw ();
961981 }
@@ -967,7 +987,7 @@ DeviceDelegateOculusVR::EndFrame(const bool aDiscard) {
967987 const ovrMatrix4f projectionMatrix = ovrMatrix4f_CreateProjectionFov (fovX, fovY, 0 .0f , 0 .0f , VRAPI_ZNEAR, 0 .0f );
968988
969989 ovrLayerProjection2 projection = vrapi_DefaultLayerProjection2 ();
970- projection.HeadPose = m. predictedTracking .HeadPose ;
990+ projection.HeadPose = tracking .HeadPose ;
971991 projection.Header .SrcBlend = VRAPI_FRAME_LAYER_BLEND_ONE;
972992 projection.Header .DstBlend = VRAPI_FRAME_LAYER_BLEND_ONE_MINUS_SRC_ALPHA;
973993 for (int i = 0 ; i < VRAPI_FRAME_LAYER_EYE_MAX; ++i) {
@@ -983,7 +1003,7 @@ DeviceDelegateOculusVR::EndFrame(const bool aDiscard) {
9831003 // Draw front layers
9841004 for (const OculusLayerPtr& layer: m.uiLayers ) {
9851005 if (layer->GetDrawInFront () && layer->IsDrawRequested () && layerCount < ovrMaxLayerCount) {
986- layer->Update (m. predictedTracking , m.clearColorSwapChain );
1006+ layer->Update (tracking , m.clearColorSwapChain );
9871007 layers[layerCount++] = layer->Header ();
9881008 layer->ClearRequestDraw ();
9891009 }
@@ -998,7 +1018,7 @@ DeviceDelegateOculusVR::EndFrame(const bool aDiscard) {
9981018 }
9991019 frameDesc.SwapInterval = 1 ;
10001020 frameDesc.FrameIndex = m.frameIndex ;
1001- frameDesc.DisplayTime = m. predictedDisplayTime ;
1021+ frameDesc.DisplayTime = displayTime ;
10021022
10031023 frameDesc.LayerCount = layerCount;
10041024 frameDesc.Layers = layers;
0 commit comments