From e7355e84f3c5d99ddc9f548c0abe74f4cbf830f8 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 25 Oct 2016 22:09:00 -0700 Subject: [PATCH 1/5] Disable OpenVR submit thread --- plugins/openvr/src/OpenVrDisplayPlugin.cpp | 1 + plugins/openvr/src/OpenVrDisplayPlugin.h | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index b9a491a8a2..d54cc540a5 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -625,6 +625,7 @@ void OpenVrDisplayPlugin::hmdPresent() { vr::VRCompositor()->Submit(vr::Eye_Left, &vrTexture, &OPENVR_TEXTURE_BOUNDS_LEFT); vr::VRCompositor()->Submit(vr::Eye_Right, &vrTexture, &OPENVR_TEXTURE_BOUNDS_RIGHT); vr::VRCompositor()->PostPresentHandoff(); + _presentRate.increment(); #endif } diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.h b/plugins/openvr/src/OpenVrDisplayPlugin.h index 025f879d84..dd8381b5ee 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.h +++ b/plugins/openvr/src/OpenVrDisplayPlugin.h @@ -15,7 +15,7 @@ const float TARGET_RATE_OpenVr = 90.0f; // FIXME: get from sdk tracked device property? This number is vive-only. -#define OPENVR_THREADED_SUBMIT 1 +#define OPENVR_THREADED_SUBMIT 0 #if OPENVR_THREADED_SUBMIT namespace gl { From 857f5a69d6e35abf6974908296afd4f672873018 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Tue, 25 Oct 2016 22:10:50 -0700 Subject: [PATCH 2/5] Don't reserve additional thread when we're not using one --- plugins/openvr/src/OpenVrDisplayPlugin.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.h b/plugins/openvr/src/OpenVrDisplayPlugin.h index dd8381b5ee..9d7b4fbb19 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.h +++ b/plugins/openvr/src/OpenVrDisplayPlugin.h @@ -58,8 +58,10 @@ public: void unsuppressKeyboard() override; bool isKeyboardVisible() override; +#if OPENVR_THREADED_SUBMIT // Needs an additional thread for VR submission int getRequiredThreadCount() const override { return Parent::getRequiredThreadCount() + 1; } +#endif protected: bool internalActivate() override; From 1c89fa22916422d24d6e47fcd5eb93653af0e26e Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 26 Oct 2016 10:36:17 -0700 Subject: [PATCH 3/5] Make threaded submit in OpenVR controllable from menu --- interface/src/Menu.cpp | 3 + interface/src/Menu.h | 1 + plugins/openvr/src/OpenVrDisplayPlugin.cpp | 161 +++++++++++---------- plugins/openvr/src/OpenVrDisplayPlugin.h | 14 +- 4 files changed, 90 insertions(+), 89 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 68d1065f72..cd8d39b739 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -338,6 +338,9 @@ Menu::Menu() { // Developer > Render > Throttle FPS If Not Focus addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::ThrottleFPSIfNotFocus, 0, true); + // Developer > Render > OpenVR threaded submit + addCheckableActionToQMenuAndActionHash(renderOptionsMenu, MenuOption::OpenVrThreadedSubmit, 0, true); + // Developer > Render > Resolution MenuWrapper* resolutionMenu = renderOptionsMenu->addMenu(MenuOption::RenderResolution); QActionGroup* resolutionGroup = new QActionGroup(resolutionMenu); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index 7cb3c47b43..640a3e05d2 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -136,6 +136,7 @@ namespace MenuOption { const QString OctreeStats = "Entity Statistics"; const QString OnePointCalibration = "1 Point Calibration"; const QString OnlyDisplayTopTen = "Only Display Top Ten"; + const QString OpenVrThreadedSubmit = "OpenVR Threaded Submit"; const QString OutputMenu = "Display"; const QString Overlays = "Overlays"; const QString PackageModel = "Package Model..."; diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index d54cc540a5..646c7fffd4 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -35,6 +35,7 @@ Q_DECLARE_LOGGING_CATEGORY(displayplugins) const QString OpenVrDisplayPlugin::NAME("OpenVR (Vive)"); const QString StandingHMDSensorMode = "Standing HMD Sensor Mode"; // this probably shouldn't be hardcoded here +const QString OpenVrThreadedSubmit = "OpenVR Threaded Submit"; // this probably shouldn't be hardcoded here PoseData _nextRenderPoseData; PoseData _nextSimPoseData; @@ -49,8 +50,6 @@ bool _openVrDisplayActive { false }; static vr::VRTextureBounds_t OPENVR_TEXTURE_BOUNDS_LEFT{ 0, 0, 0.5f, 1 }; static vr::VRTextureBounds_t OPENVR_TEXTURE_BOUNDS_RIGHT{ 0.5f, 0, 1, 1 }; -#if OPENVR_THREADED_SUBMIT - #define REPROJECTION_BINDING 1 static const char* HMD_REPROJECTION_VERT = R"SHADER( @@ -351,8 +350,6 @@ public: OpenVrDisplayPlugin& _plugin; }; -#endif - bool OpenVrDisplayPlugin::isSupported() const { return openVrSupported(); } @@ -394,6 +391,9 @@ bool OpenVrDisplayPlugin::internalActivate() { return false; } + _threadedSubmit = _container->isOptionChecked(OpenVrThreadedSubmit); + qDebug() << "OpenVR Threaded submit enabled: " << _threadedSubmit; + _openVrDisplayActive = true; _container->setIsOptionChecked(StandingHMDSensorMode, true); @@ -434,16 +434,16 @@ bool OpenVrDisplayPlugin::internalActivate() { #endif } -#if OPENVR_THREADED_SUBMIT - _submitThread = std::make_shared(*this); - if (!_submitCanvas) { - withMainThreadContext([&] { - _submitCanvas = std::make_shared(); - _submitCanvas->create(); - _submitCanvas->doneCurrent(); - }); + if (_threadedSubmit) { + _submitThread = std::make_shared(*this); + if (!_submitCanvas) { + withMainThreadContext([&] { + _submitCanvas = std::make_shared(); + _submitCanvas->create(); + _submitCanvas->doneCurrent(); + }); + } } -#endif return Parent::internalActivate(); } @@ -473,27 +473,27 @@ void OpenVrDisplayPlugin::customizeContext() { Parent::customizeContext(); -#if OPENVR_THREADED_SUBMIT - _compositeInfos[0].texture = _compositeFramebuffer->getRenderBuffer(0); - for (size_t i = 0; i < COMPOSITING_BUFFER_SIZE; ++i) { - if (0 != i) { - _compositeInfos[i].texture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, _renderTargetSize.x, _renderTargetSize.y, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT))); + if (_threadedSubmit) { + _compositeInfos[0].texture = _compositeFramebuffer->getRenderBuffer(0); + for (size_t i = 0; i < COMPOSITING_BUFFER_SIZE; ++i) { + if (0 != i) { + _compositeInfos[i].texture = gpu::TexturePointer(gpu::Texture::create2D(gpu::Element::COLOR_RGBA_32, _renderTargetSize.x, _renderTargetSize.y, gpu::Sampler(gpu::Sampler::FILTER_MIN_MAG_POINT))); + } + _compositeInfos[i].textureID = getGLBackend()->getTextureID(_compositeInfos[i].texture, false); } - _compositeInfos[i].textureID = getGLBackend()->getTextureID(_compositeInfos[i].texture, false); + _submitThread->_canvas = _submitCanvas; + _submitThread->start(QThread::HighPriority); } - _submitThread->_canvas = _submitCanvas; - _submitThread->start(QThread::HighPriority); -#endif } void OpenVrDisplayPlugin::uncustomizeContext() { Parent::uncustomizeContext(); -#if OPENVR_THREADED_SUBMIT - _submitThread->_quit = true; - _submitThread->wait(); - _submitThread.reset(); -#endif + if (_threadedSubmit) { + _submitThread->_quit = true; + _submitThread->wait(); + _submitThread.reset(); + } } void OpenVrDisplayPlugin::resetSensors() { @@ -582,76 +582,77 @@ bool OpenVrDisplayPlugin::beginFrameRender(uint32_t frameIndex) { } void OpenVrDisplayPlugin::compositeLayers() { -#if OPENVR_THREADED_SUBMIT - ++_renderingIndex; - _renderingIndex %= COMPOSITING_BUFFER_SIZE; + if (_threadedSubmit) { + ++_renderingIndex; + _renderingIndex %= COMPOSITING_BUFFER_SIZE; - auto& newComposite = _compositeInfos[_renderingIndex]; - newComposite.pose = _currentPresentFrameInfo.presentPose; - _compositeFramebuffer->setRenderBuffer(0, newComposite.texture); -#endif + auto& newComposite = _compositeInfos[_renderingIndex]; + newComposite.pose = _currentPresentFrameInfo.presentPose; + _compositeFramebuffer->setRenderBuffer(0, newComposite.texture); + } Parent::compositeLayers(); -#if OPENVR_THREADED_SUBMIT - newComposite.fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); - // https://www.opengl.org/registry/specs/ARB/sync.txt: - // > The simple flushing behavior defined by - // > SYNC_FLUSH_COMMANDS_BIT will not help when waiting for a fence - // > command issued in another context's command stream to complete. - // > Applications which block on a fence sync object must take - // > additional steps to assure that the context from which the - // > corresponding fence command was issued has flushed that command - // > to the graphics pipeline. - glFlush(); + if (_threadedSubmit) { + auto& newComposite = _compositeInfos[_renderingIndex]; + newComposite.fence = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + // https://www.opengl.org/registry/specs/ARB/sync.txt: + // > The simple flushing behavior defined by + // > SYNC_FLUSH_COMMANDS_BIT will not help when waiting for a fence + // > command issued in another context's command stream to complete. + // > Applications which block on a fence sync object must take + // > additional steps to assure that the context from which the + // > corresponding fence command was issued has flushed that command + // > to the graphics pipeline. + glFlush(); - if (!newComposite.textureID) { - newComposite.textureID = getGLBackend()->getTextureID(newComposite.texture, false); + if (!newComposite.textureID) { + newComposite.textureID = getGLBackend()->getTextureID(newComposite.texture, false); + } + withPresentThreadLock([&] { + _submitThread->update(newComposite); + }); } - withPresentThreadLock([&] { - _submitThread->update(newComposite); - }); -#endif } void OpenVrDisplayPlugin::hmdPresent() { PROFILE_RANGE_EX(__FUNCTION__, 0xff00ff00, (uint64_t)_currentFrame->frameIndex) -#if OPENVR_THREADED_SUBMIT - _submitThread->waitForPresent(); -#else - GLuint glTexId = getGLBackend()->getTextureID(_compositeFramebuffer->getRenderBuffer(0), false); - vr::Texture_t vrTexture{ (void*)glTexId, vr::API_OpenGL, vr::ColorSpace_Auto }; - vr::VRCompositor()->Submit(vr::Eye_Left, &vrTexture, &OPENVR_TEXTURE_BOUNDS_LEFT); - vr::VRCompositor()->Submit(vr::Eye_Right, &vrTexture, &OPENVR_TEXTURE_BOUNDS_RIGHT); - vr::VRCompositor()->PostPresentHandoff(); - _presentRate.increment(); -#endif + if (_threadedSubmit) { + _submitThread->waitForPresent(); + } else { + GLuint glTexId = getGLBackend()->getTextureID(_compositeFramebuffer->getRenderBuffer(0), false); + vr::Texture_t vrTexture { (void*)glTexId, vr::API_OpenGL, vr::ColorSpace_Auto }; + vr::VRCompositor()->Submit(vr::Eye_Left, &vrTexture, &OPENVR_TEXTURE_BOUNDS_LEFT); + vr::VRCompositor()->Submit(vr::Eye_Right, &vrTexture, &OPENVR_TEXTURE_BOUNDS_RIGHT); + vr::VRCompositor()->PostPresentHandoff(); + _presentRate.increment(); + } } void OpenVrDisplayPlugin::postPreview() { PROFILE_RANGE_EX(__FUNCTION__, 0xff00ff00, (uint64_t)_currentFrame->frameIndex) PoseData nextRender, nextSim; nextRender.frameIndex = presentCount(); -#if !OPENVR_THREADED_SUBMIT - vr::VRCompositor()->WaitGetPoses(nextRender.vrPoses, vr::k_unMaxTrackedDeviceCount, nextSim.vrPoses, vr::k_unMaxTrackedDeviceCount); + if (_threadedSubmit) { + _hmdActivityLevel = _system->GetTrackedDeviceActivityLevel(vr::k_unTrackedDeviceIndex_Hmd); + } else { + vr::VRCompositor()->WaitGetPoses(nextRender.vrPoses, vr::k_unMaxTrackedDeviceCount, nextSim.vrPoses, vr::k_unMaxTrackedDeviceCount); - glm::mat4 resetMat; - withPresentThreadLock([&] { - resetMat = _sensorResetMat; - }); - nextRender.update(resetMat); - nextSim.update(resetMat); - withPresentThreadLock([&] { - _nextSimPoseData = nextSim; - }); - _nextRenderPoseData = nextRender; + glm::mat4 resetMat; + withPresentThreadLock([&] { + resetMat = _sensorResetMat; + }); + nextRender.update(resetMat); + nextSim.update(resetMat); + withPresentThreadLock([&] { + _nextSimPoseData = nextSim; + }); + _nextRenderPoseData = nextRender; - // FIXME - this looks wrong! - _hmdActivityLevel = vr::k_EDeviceActivityLevel_UserInteraction; // _system->GetTrackedDeviceActivityLevel(vr::k_unTrackedDeviceIndex_Hmd); -#else - _hmdActivityLevel = _system->GetTrackedDeviceActivityLevel(vr::k_unTrackedDeviceIndex_Hmd); -#endif + // FIXME - this looks wrong! + _hmdActivityLevel = vr::k_EDeviceActivityLevel_UserInteraction; // _system->GetTrackedDeviceActivityLevel(vr::k_unTrackedDeviceIndex_Hmd); + } } bool OpenVrDisplayPlugin::isHmdMounted() const { @@ -685,3 +686,7 @@ void OpenVrDisplayPlugin::unsuppressKeyboard() { bool OpenVrDisplayPlugin::isKeyboardVisible() { return isOpenVrKeyboardShown(); } + +int OpenVrDisplayPlugin::getRequiredThreadCount() const { + return Parent::getRequiredThreadCount() + (_threadedSubmit ? 1 : 0); +} \ No newline at end of file diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.h b/plugins/openvr/src/OpenVrDisplayPlugin.h index 9d7b4fbb19..d867c71cb6 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.h +++ b/plugins/openvr/src/OpenVrDisplayPlugin.h @@ -15,9 +15,6 @@ const float TARGET_RATE_OpenVr = 90.0f; // FIXME: get from sdk tracked device property? This number is vive-only. -#define OPENVR_THREADED_SUBMIT 0 - -#if OPENVR_THREADED_SUBMIT namespace gl { class OffscreenContext; } @@ -34,7 +31,6 @@ struct CompositeInfo { glm::mat4 pose; GLsync fence{ 0 }; }; -#endif class OpenVrDisplayPlugin : public HmdDisplayPlugin { using Parent = HmdDisplayPlugin; @@ -58,10 +54,8 @@ public: void unsuppressKeyboard() override; bool isKeyboardVisible() override; -#if OPENVR_THREADED_SUBMIT - // Needs an additional thread for VR submission - int getRequiredThreadCount() const override { return Parent::getRequiredThreadCount() + 1; } -#endif + // Possibly needs an additional thread for VR submission + int getRequiredThreadCount() const override; protected: bool internalActivate() override; @@ -73,7 +67,6 @@ protected: bool isHmdMounted() const override; void postPreview() override; - private: vr::IVRSystem* _system { nullptr }; std::atomic _hmdActivityLevel { vr::k_EDeviceActivityLevel_Unknown }; @@ -82,12 +75,11 @@ private: vr::HmdMatrix34_t _lastGoodHMDPose; mat4 _sensorResetMat; + bool _threadedSubmit { true }; -#if OPENVR_THREADED_SUBMIT CompositeInfo::Array _compositeInfos; size_t _renderingIndex { 0 }; std::shared_ptr _submitThread; std::shared_ptr _submitCanvas; friend class OpenVrSubmitThread; -#endif }; From f4f1b04cf0509e14c75bc98ab459e780d616c521 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 26 Oct 2016 16:02:06 -0700 Subject: [PATCH 4/5] Use OpenVR to determine if async reprojection is enabled --- cmake/externals/openvr/CMakeLists.txt | 4 ++-- plugins/openvr/src/OpenVrDisplayPlugin.cpp | 11 ++++++++++- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/cmake/externals/openvr/CMakeLists.txt b/cmake/externals/openvr/CMakeLists.txt index 1cd4c071f1..19a9dd1f15 100644 --- a/cmake/externals/openvr/CMakeLists.txt +++ b/cmake/externals/openvr/CMakeLists.txt @@ -7,8 +7,8 @@ string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) ExternalProject_Add( ${EXTERNAL_NAME} - URL https://github.com/ValveSoftware/openvr/archive/v1.0.2.zip - URL_MD5 0d1cf5f579cf092e33f34759967b7046 + URL https://github.com/ValveSoftware/openvr/archive/v1.0.3.zip + URL_MD5 b484b12901917cc739e40389583c8b0d CONFIGURE_COMMAND "" BUILD_COMMAND "" INSTALL_COMMAND "" diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index 646c7fffd4..567d8f513b 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -373,6 +373,9 @@ void OpenVrDisplayPlugin::init() { emit deviceConnected(getName()); } +// FIXME remove once OpenVR header is updated +#define VRCompositor_ReprojectionAsync 0x04 + bool OpenVrDisplayPlugin::internalActivate() { if (!_system) { _system = acquireOpenVrSystem(); @@ -391,7 +394,13 @@ bool OpenVrDisplayPlugin::internalActivate() { return false; } - _threadedSubmit = _container->isOptionChecked(OpenVrThreadedSubmit); + vr::Compositor_FrameTiming timing; + memset(&timing, 0, sizeof(timing)); + timing.m_nSize = sizeof(vr::Compositor_FrameTiming); + vr::VRCompositor()->GetFrameTiming(&timing); + bool asyncReprojectionActive = timing.m_nReprojectionFlags & VRCompositor_ReprojectionAsync; + + _threadedSubmit = !asyncReprojectionActive; qDebug() << "OpenVR Threaded submit enabled: " << _threadedSubmit; _openVrDisplayActive = true; From a53049b18652d6e3c44c3a8a9f002abaefbc2dad Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 26 Oct 2016 17:19:24 -0700 Subject: [PATCH 5/5] Consolidate activity tracking code --- plugins/openvr/src/OpenVrDisplayPlugin.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/plugins/openvr/src/OpenVrDisplayPlugin.cpp b/plugins/openvr/src/OpenVrDisplayPlugin.cpp index 567d8f513b..18a2ce99c3 100644 --- a/plugins/openvr/src/OpenVrDisplayPlugin.cpp +++ b/plugins/openvr/src/OpenVrDisplayPlugin.cpp @@ -643,9 +643,10 @@ void OpenVrDisplayPlugin::postPreview() { PROFILE_RANGE_EX(__FUNCTION__, 0xff00ff00, (uint64_t)_currentFrame->frameIndex) PoseData nextRender, nextSim; nextRender.frameIndex = presentCount(); - if (_threadedSubmit) { - _hmdActivityLevel = _system->GetTrackedDeviceActivityLevel(vr::k_unTrackedDeviceIndex_Hmd); - } else { + + _hmdActivityLevel = _system->GetTrackedDeviceActivityLevel(vr::k_unTrackedDeviceIndex_Hmd); + + if (!_threadedSubmit) { vr::VRCompositor()->WaitGetPoses(nextRender.vrPoses, vr::k_unMaxTrackedDeviceCount, nextSim.vrPoses, vr::k_unMaxTrackedDeviceCount); glm::mat4 resetMat; @@ -659,8 +660,6 @@ void OpenVrDisplayPlugin::postPreview() { }); _nextRenderPoseData = nextRender; - // FIXME - this looks wrong! - _hmdActivityLevel = vr::k_EDeviceActivityLevel_UserInteraction; // _system->GetTrackedDeviceActivityLevel(vr::k_unTrackedDeviceIndex_Hmd); } }