Skip to content
This repository was archived by the owner on Jul 22, 2024. It is now read-only.

Commit d1f9444

Browse files
committed
Reduce WebVR idle times
1 parent d50fa7d commit d1f9444

10 files changed

Lines changed: 81 additions & 35 deletions

app/src/main/cpp/BrowserWorld.cpp

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,6 @@ PerformanceObserver::PerformanceRestored(const double& aTargetFrameRate, const d
144144
} // namespace
145145

146146
namespace crow {
147-
148147
struct BrowserWorld::State {
149148
BrowserWorldWeakPtr self;
150149
std::vector<WidgetPtr> widgets;
@@ -934,7 +933,7 @@ BrowserWorld::EndFrame() {
934933
m.frameEndHandler();
935934
m.frameEndHandler = nullptr;
936935
} else {
937-
m.device->EndFrame(false);
936+
m.device->EndFrame();
938937
}
939938
m.drawHandler = nullptr;
940939

@@ -1422,13 +1421,27 @@ BrowserWorld::TickImmersive() {
14221421
m.externalVR->SetCompositorEnabled(false);
14231422
m.device->SetRenderMode(device::RenderMode::Immersive);
14241423

1425-
m.device->StartFrame();
1424+
DeviceDelegate::FramePrediction prediction = DeviceDelegate::FramePrediction::NO_FRAME_AHEAD;
1425+
if (m.device->SupportsFramePrediction(DeviceDelegate::FramePrediction::ONE_FRAME_AHEAD)
1426+
&& m.externalVR->GetVRState() == ExternalVR::VRState::Rendering) {
1427+
prediction = DeviceDelegate::FramePrediction::ONE_FRAME_AHEAD;
1428+
}
1429+
14261430
VRB_GL_CHECK(glDepthMask(GL_FALSE));
1427-
m.externalVR->PushFramePoses(m.device->GetHeadTransform(), m.controllers->GetControllers(), m.context->GetTimestamp());
1431+
if (prediction == DeviceDelegate::FramePrediction::NO_FRAME_AHEAD) {
1432+
m.device->StartFrame(prediction);
1433+
m.externalVR->PushFramePoses(m.device->GetHeadTransform(), m.controllers->GetControllers(),
1434+
m.context->GetTimestamp());
1435+
}
14281436
int32_t surfaceHandle, textureWidth, textureHeight = 0;
14291437
device::EyeRect leftEye, rightEye;
14301438
bool aDiscardFrame = !m.externalVR->WaitFrameResult();
14311439
m.externalVR->GetFrameResult(surfaceHandle, textureWidth, textureHeight, leftEye, rightEye);
1440+
if (prediction == DeviceDelegate::FramePrediction::ONE_FRAME_AHEAD) {
1441+
m.device->StartFrame(prediction);
1442+
m.externalVR->PushFramePoses(m.device->GetHeadTransform(), m.controllers->GetControllers(),
1443+
m.context->GetTimestamp());
1444+
}
14321445
ExternalVR::VRState state = m.externalVR->GetVRState();
14331446
if (state == ExternalVR::VRState::Rendering) {
14341447
if (!aDiscardFrame) {
@@ -1441,7 +1454,7 @@ BrowserWorld::TickImmersive() {
14411454
};
14421455
}
14431456
m.frameEndHandler = [=]() {
1444-
m.device->EndFrame(aDiscardFrame);
1457+
m.device->EndFrame(aDiscardFrame ? DeviceDelegate::FrameEndMode::DISCARD : DeviceDelegate::FrameEndMode::APPLY);
14451458
m.blitter->EndFrame();
14461459
};
14471460
} else {
@@ -1494,7 +1507,7 @@ BrowserWorld::TickSplashAnimation() {
14941507
if (m.fadeAnimation) {
14951508
m.fadeAnimation->FadeIn();
14961509
}
1497-
m.device->EndFrame(false);
1510+
m.device->EndFrame();
14981511
};
14991512
}
15001513
}

app/src/main/cpp/DeviceDelegate.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ class ImmersiveDisplay {
4545

4646
class DeviceDelegate {
4747
public:
48+
enum class FramePrediction {
49+
NO_FRAME_AHEAD,
50+
ONE_FRAME_AHEAD,
51+
};
52+
enum class FrameEndMode {
53+
APPLY,
54+
DISCARD
55+
};
4856
virtual device::DeviceType GetDeviceType() { return device::UnknownType; }
4957
virtual void SetRenderMode(const device::RenderMode aMode) = 0;
5058
virtual device::RenderMode GetRenderMode() = 0;
@@ -63,9 +71,12 @@ class DeviceDelegate {
6371
virtual const std::string GetControllerModelName(const int32_t aModelIndex) const = 0;
6472
virtual void SetCPULevel(const device::CPULevel aLevel) {};
6573
virtual void ProcessEvents() = 0;
66-
virtual void StartFrame() = 0;
74+
virtual bool SupportsFramePrediction(FramePrediction aPrediction) const {
75+
return aPrediction == FramePrediction::NO_FRAME_AHEAD;
76+
}
77+
virtual void StartFrame(const FramePrediction aPrediction = FramePrediction::NO_FRAME_AHEAD) = 0;
6778
virtual void BindEye(const device::Eye aWhich) = 0;
68-
virtual void EndFrame(bool aDiscard = false) = 0;
79+
virtual void EndFrame(const FrameEndMode aMode = FrameEndMode::APPLY) = 0;
6980
virtual bool IsInGazeMode() const { return false; };
7081
virtual int32_t GazeModeIndex() const { return -1; };
7182
virtual VRLayerQuadPtr CreateLayerQuad(int32_t aWidth, int32_t aHeight,

app/src/noapi/cpp/DeviceDelegateNoAPI.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ DeviceDelegateNoAPI::ProcessEvents() {
211211
}
212212

213213
void
214-
DeviceDelegateNoAPI::StartFrame() {
214+
DeviceDelegateNoAPI::StartFrame(const FramePrediction aPrediction) {
215215
VRB_GL_CHECK(glClearColor(m.clearColor.Red(), m.clearColor.Green(), m.clearColor.Blue(), m.clearColor.Alpha()));
216216
VRB_GL_CHECK(glEnable(GL_DEPTH_TEST));
217217
VRB_GL_CHECK(glEnable(GL_CULL_FACE));
@@ -240,7 +240,7 @@ DeviceDelegateNoAPI::BindEye(const device::Eye aEye) {
240240
}
241241

242242
void
243-
DeviceDelegateNoAPI::EndFrame(const bool aDiscard) {
243+
DeviceDelegateNoAPI::EndFrame(const FrameEndMode aMode) {
244244
// noop
245245
}
246246

app/src/noapi/cpp/DeviceDelegateNoAPI.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ class DeviceDelegateNoAPI : public DeviceDelegate {
3737
int32_t GetControllerModelCount() const override;
3838
const std::string GetControllerModelName(const int32_t aModelIndex) const override;
3939
void ProcessEvents() override;
40-
void StartFrame() override;
40+
void StartFrame(const FramePrediction aPrediction) override;
4141
void BindEye(const device::Eye) override;
42-
void EndFrame(const bool aDiscard) override;
42+
void EndFrame(const FrameEndMode aMode) override;
4343
// DeviceDelegateNoAPI interface
4444
void InitializeJava(JNIEnv* aEnv, jobject aActivity);
4545
void ShutdownJava();

app/src/oculusvr/cpp/DeviceDelegateOculusVR.cpp

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -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+
821829
void
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

910926
void
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;

app/src/oculusvr/cpp/DeviceDelegateOculusVR.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,9 +41,10 @@ class DeviceDelegateOculusVR : public DeviceDelegate {
4141
const std::string GetControllerModelName(const int32_t aModelIndex) const override;
4242
void SetCPULevel(const device::CPULevel aLevel) override;
4343
void ProcessEvents() override;
44-
void StartFrame() override;
44+
bool SupportsFramePrediction(FramePrediction aPrediction) const override;
45+
void StartFrame(const FramePrediction aPrediction) override;
4546
void BindEye(const device::Eye aWhich) override;
46-
void EndFrame(const bool aDiscard) override;
47+
void EndFrame(const FrameEndMode aMode) override;
4748
VRLayerQuadPtr CreateLayerQuad(int32_t aWidth, int32_t aHeight,
4849
VRLayerSurface::SurfaceType aSurfaceType) override;
4950
VRLayerQuadPtr CreateLayerQuad(const VRLayerSurfacePtr& aMoveLayer) override;

app/src/picovr/cpp/DeviceDelegatePicoVR.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -385,7 +385,7 @@ DeviceDelegatePicoVR::ProcessEvents() {
385385
}
386386

387387
void
388-
DeviceDelegatePicoVR::StartFrame() {
388+
DeviceDelegatePicoVR::StartFrame(const FramePrediction aPrediction) {
389389
vrb::Matrix head = vrb::Matrix::Rotation(m.orientation);
390390
head.TranslateInPlace(m.position);
391391

@@ -431,7 +431,7 @@ DeviceDelegatePicoVR::BindEye(const device::Eye aWhich) {
431431
}
432432

433433
void
434-
DeviceDelegatePicoVR::EndFrame(const bool aDiscard) {
434+
DeviceDelegatePicoVR::EndFrame(const FrameEndMode aMode) {
435435

436436
}
437437

app/src/picovr/cpp/DeviceDelegatePicoVR.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,9 @@ class DeviceDelegatePicoVR : public DeviceDelegate {
3737
int32_t GetControllerModelCount() const override;
3838
const std::string GetControllerModelName(const int32_t aModelIndex) const override;
3939
void ProcessEvents() override;
40-
void StartFrame() override;
40+
void StartFrame(const FramePrediction aPrediction) override;
4141
void BindEye(const device::Eye aWhich) override;
42-
void EndFrame(const bool aDiscard) override;
42+
void EndFrame(const FrameEndMode aMode) override;
4343
bool IsInGazeMode() const override;
4444
int32_t GazeModeIndex() const override;
4545
// Custom methods

app/src/wavevr/cpp/DeviceDelegateWaveVR.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "vrb/Matrix.h"
1717
#include "vrb/RenderContext.h"
1818
#include "vrb/Vector.h"
19+
#include "../../main/cpp/DeviceDelegate.h"
1920

2021
#include <array>
2122
#include <vector>
@@ -693,7 +694,7 @@ HandToString(ElbowModel::HandEnum hand) {
693694
}
694695

695696
void
696-
DeviceDelegateWaveVR::StartFrame() {
697+
DeviceDelegateWaveVR::StartFrame(const FramePrediction aPrediction) {
697698
VRB_GL_CHECK(glClearColor(m.clearColor.Red(), m.clearColor.Green(), m.clearColor.Blue(), m.clearColor.Alpha()));
698699
if (!m.lastSubmitDiscarded) {
699700
m.leftFBOIndex = WVR_GetAvailableTextureIndex(m.leftTextureQueue);
@@ -801,14 +802,14 @@ DeviceDelegateWaveVR::BindEye(const device::Eye aWhich) {
801802
}
802803

803804
void
804-
DeviceDelegateWaveVR::EndFrame(const bool aDiscard) {
805+
DeviceDelegateWaveVR::EndFrame(const FrameEndMode aMode) {
805806
if (m.currentFBO) {
806807
m.currentFBO->Unbind();
807808
m.currentFBO = nullptr;
808809
}
809810

810-
m.lastSubmitDiscarded = aDiscard;
811-
if (aDiscard) {
811+
m.lastSubmitDiscarded = aMode == DeviceDelegate::FrameEndMode::DISCARD;
812+
if (m.lastSubmitDiscarded) {
812813
return;
813814
}
814815
// Left eye

app/src/wavevr/cpp/DeviceDelegateWaveVR.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@ class DeviceDelegateWaveVR : public DeviceDelegate {
3131
int32_t GetControllerModelCount() const override;
3232
const std::string GetControllerModelName(const int32_t aModelIndex) const override;
3333
void ProcessEvents() override;
34-
void StartFrame() override;
34+
void StartFrame(const FramePrediction aPrediction) override;
3535
void BindEye(const device::Eye aWhich) override;
36-
void EndFrame(const bool aDiscard) override;
36+
void EndFrame(const FrameEndMode aMode) override;
3737
// DeviceDelegateWaveVR interface
3838
bool IsRunning();
3939
protected:

0 commit comments

Comments
 (0)