[Bf-blender-cvs] [9b6ce439bbb] temp-vr-draw-thread: Fix race condition in state changes + related cleanup + add assert

Julian Eisel noreply at git.blender.org
Fri Aug 2 02:42:46 CEST 2019


Commit: 9b6ce439bbbf5ce2a06f772d6168164bc87e5e3f
Author: Julian Eisel
Date:   Fri Aug 2 00:38:22 2019 +0200
Branches: temp-vr-draw-thread
https://developer.blender.org/rB9b6ce439bbbf5ce2a06f772d6168164bc87e5e3f

Fix race condition in state changes + related cleanup + add assert

===================================================================

M	intern/ghost/GHOST_C-api.h
M	intern/ghost/GHOST_IXrContext.h
M	intern/ghost/intern/GHOST_C-api.cpp
M	intern/ghost/intern/GHOST_XrContext.cpp
M	intern/ghost/intern/GHOST_XrContext.h
M	intern/ghost/intern/GHOST_XrSession.cpp
M	intern/ghost/intern/GHOST_XrSession.h
M	source/blender/windowmanager/intern/wm_xr.c

===================================================================

diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
index e9fb3373a4b..557503783e5 100644
--- a/intern/ghost/GHOST_C-api.h
+++ b/intern/ghost/GHOST_C-api.h
@@ -1002,7 +1002,7 @@ void GHOST_XrSessionStart(GHOST_XrContextHandle xr_context,
                           const GHOST_XrSessionBeginInfo *begin_info);
 void GHOST_XrSessionEnd(GHOST_XrContextHandle xr_context);
 int GHOST_XrHasSession(const GHOST_XrContextHandle xr_contexthandle);
-int GHOST_XrSessionIsRunning(const GHOST_XrContextHandle xr_context);
+int GHOST_XrSessionShouldRunDrawLoop(const GHOST_XrContextHandle xr_context);
 void GHOST_XrSessionDrawViews(GHOST_XrContextHandle xr_context, void *customdata);
 
 /* events */
diff --git a/intern/ghost/GHOST_IXrContext.h b/intern/ghost/GHOST_IXrContext.h
index 3b8455e6e86..968c98ad42e 100644
--- a/intern/ghost/GHOST_IXrContext.h
+++ b/intern/ghost/GHOST_IXrContext.h
@@ -30,7 +30,7 @@ class GHOST_IXrContext {
   virtual void startSession(const GHOST_XrSessionBeginInfo *begin_info) = 0;
   virtual void endSession() = 0;
   virtual bool hasSession() const = 0;
-  virtual bool isSessionRunning() const = 0;
+  virtual bool shouldRunSessionDrawLoop() const = 0;
   virtual void drawSessionViews(void *draw_customdata) = 0;
 
   virtual void dispatchErrorMessage(const class GHOST_XrException *) const = 0;
diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp
index c188cc8e819..98579985693 100644
--- a/intern/ghost/intern/GHOST_C-api.cpp
+++ b/intern/ghost/intern/GHOST_C-api.cpp
@@ -944,10 +944,10 @@ int GHOST_XrHasSession(const GHOST_XrContextHandle xr_contexthandle)
   return 0;  // Only reached if exception is thrown.
 }
 
-int GHOST_XrSessionIsRunning(const GHOST_XrContextHandle xr_contexthandle)
+int GHOST_XrSessionShouldRunDrawLoop(const GHOST_XrContextHandle xr_contexthandle)
 {
   const GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle;
-  GHOST_XR_CAPI_CALL_RET(xr_context->isSessionRunning(), xr_context);
+  GHOST_XR_CAPI_CALL_RET(xr_context->shouldRunSessionDrawLoop(), xr_context);
   return 0;  // Only reached if exception is thrown.
 }
 
diff --git a/intern/ghost/intern/GHOST_XrContext.cpp b/intern/ghost/intern/GHOST_XrContext.cpp
index 51b39bcc193..813fdf19f5a 100644
--- a/intern/ghost/intern/GHOST_XrContext.cpp
+++ b/intern/ghost/intern/GHOST_XrContext.cpp
@@ -446,9 +446,9 @@ bool GHOST_XrContext::hasSession() const
   return m_session != nullptr;
 }
 
-bool GHOST_XrContext::isSessionRunning() const
+bool GHOST_XrContext::shouldRunSessionDrawLoop() const
 {
-  return m_session && m_session->isRunning();
+  return m_session && m_session->shouldRunDrawLoop();
 }
 
 void GHOST_XrContext::drawSessionViews(void *draw_customdata)
diff --git a/intern/ghost/intern/GHOST_XrContext.h b/intern/ghost/intern/GHOST_XrContext.h
index bd189f39491..3cf33fb6950 100644
--- a/intern/ghost/intern/GHOST_XrContext.h
+++ b/intern/ghost/intern/GHOST_XrContext.h
@@ -51,7 +51,7 @@ class GHOST_XrContext : public GHOST_IXrContext {
   void startSession(const GHOST_XrSessionBeginInfo *begin_info) override;
   void endSession() override;
   bool hasSession() const override;
-  bool isSessionRunning() const override;
+  bool shouldRunSessionDrawLoop() const override;
   void drawSessionViews(void *draw_customdata) override;
 
   static void setErrorHandler(GHOST_XrErrorHandlerFn handler_fn, void *customdata);
diff --git a/intern/ghost/intern/GHOST_XrSession.cpp b/intern/ghost/intern/GHOST_XrSession.cpp
index dee175632b5..a5eb7a891d7 100644
--- a/intern/ghost/intern/GHOST_XrSession.cpp
+++ b/intern/ghost/intern/GHOST_XrSession.cpp
@@ -193,16 +193,13 @@ void GHOST_XrSession::end()
 GHOST_XrSession::eLifeExpectancy GHOST_XrSession::handleStateChangeEvent(
     const XrEventDataSessionStateChanged *lifecycle)
 {
-  m_oxr->session_state = lifecycle->state;
-
   /* Runtime may send events for apparently destroyed session. Our handle should be NULL then. */
   assert((m_oxr->session == XR_NULL_HANDLE) || (m_oxr->session == lifecycle->session));
 
   switch (lifecycle->state) {
     case XR_SESSION_STATE_READY: {
-      XrSessionBeginInfo begin_info{};
+      XrSessionBeginInfo begin_info{XR_TYPE_SESSION_BEGIN_INFO};
 
-      begin_info.type = XR_TYPE_SESSION_BEGIN_INFO;
       begin_info.primaryViewConfigurationType = m_oxr->view_type;
       CHECK_XR(xrBeginSession(m_oxr->session, &begin_info),
                "Failed to cleanly begin the VR session.");
@@ -218,6 +215,10 @@ GHOST_XrSession::eLifeExpectancy GHOST_XrSession::handleStateChangeEvent(
       break;
   }
 
+  /* GHOST session state is managed through this. Set last so on parallel execution of GHOST_Xr
+   * calls, state changes only take effect once previous operations in this functions are done. */
+  m_oxr->session_state = lifecycle->state;
+
   return SESSION_KEEP_ALIVE;
 }
 /** \} */ /* State Management */
@@ -320,7 +321,6 @@ void GHOST_XrSession::beginFrameDrawing()
   XrFrameBeginInfo begin_info{XR_TYPE_FRAME_BEGIN_INFO};
   XrFrameState frame_state{XR_TYPE_FRAME_STATE};
 
-  // TODO Blocking call. Does this intefer with other drawing?
   CHECK_XR(xrWaitFrame(m_oxr->session, &wait_info, &frame_state),
            "Failed to synchronize frame rates between Blender and the device.");
 
@@ -381,6 +381,8 @@ void GHOST_XrSession::draw(void *draw_customdata)
   XrCompositionLayerProjection proj_layer;
   std::vector<XrCompositionLayerBaseHeader *> layers;
 
+  assert(shouldRunDrawLoop());
+
   beginFrameDrawing();
 
   if (m_draw_info->frame_state.shouldRender) {
@@ -505,7 +507,7 @@ XrCompositionLayerProjection GHOST_XrSession::drawLayer(
  *
  * \{ */
 
-bool GHOST_XrSession::isRunning() const
+bool GHOST_XrSession::shouldRunDrawLoop() const
 {
   if (m_oxr->session == XR_NULL_HANDLE) {
     return false;
diff --git a/intern/ghost/intern/GHOST_XrSession.h b/intern/ghost/intern/GHOST_XrSession.h
index 7b75bdbae56..56bba7130b0 100644
--- a/intern/ghost/intern/GHOST_XrSession.h
+++ b/intern/ghost/intern/GHOST_XrSession.h
@@ -39,7 +39,7 @@ class GHOST_XrSession {
 
   eLifeExpectancy handleStateChangeEvent(const struct XrEventDataSessionStateChanged *lifecycle);
 
-  bool isRunning() const;
+  bool shouldRunDrawLoop() const;
 
   void unbindGraphicsContext(); /* public so context can ensure it's unbound as needed. */
 
diff --git a/source/blender/windowmanager/intern/wm_xr.c b/source/blender/windowmanager/intern/wm_xr.c
index 486a9b8e0f5..646b44eeb52 100644
--- a/source/blender/windowmanager/intern/wm_xr.c
+++ b/source/blender/windowmanager/intern/wm_xr.c
@@ -440,7 +440,7 @@ static void *wm_xr_session_drawthread_main(void *data)
 
   /* Sort of the session's main loop. */
   while (GHOST_XrHasSession(wm->xr_context)) {
-    if (!GHOST_XrSessionIsRunning(wm->xr_context)) {
+    if (!GHOST_XrSessionShouldRunDrawLoop(wm->xr_context)) {
       continue;
     }
 
@@ -474,7 +474,7 @@ void wm_xr_session_toggle(bContext *C, void *xr_context_ptr)
 {
   GHOST_XrContextHandle xr_context = xr_context_ptr;
 
-  if (xr_context && GHOST_XrSessionIsRunning(xr_context)) {
+  if (xr_context && GHOST_XrHasSession(xr_context)) {
     GHOST_XrSessionEnd(xr_context);
   }
   else {



More information about the Bf-blender-cvs mailing list