[Bf-blender-cvs] [fa2a13bcb95] blender-v2.83-release: Fix T79324: Crash when changing View Layer while VR session runs

Julian Eisel noreply at git.blender.org
Wed Aug 12 09:44:11 CEST 2020


Commit: fa2a13bcb958ee038ab85c4a413282accceedd1f
Author: Julian Eisel
Date:   Mon Aug 10 17:29:35 2020 +0200
Branches: blender-v2.83-release
https://developer.blender.org/rBfa2a13bcb958ee038ab85c4a413282accceedd1f

Fix T79324: Crash when changing View Layer while VR session runs

Proper handling of View Layers for the VR session was never implemented.
Now the View Layer of the VR session follows the window the session was
started in.
Note that if this window is closed, we fallback to another window. This
is done to avoid the overhead it would take to maintain a separate
depsgraph for the VR view. Instead we always share some already visible
View Layer (and hence the depsgraph).

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

M	source/blender/windowmanager/intern/wm_operators.c
M	source/blender/windowmanager/xr/intern/wm_xr_intern.h
M	source/blender/windowmanager/xr/intern/wm_xr_session.c
M	source/blender/windowmanager/xr/wm_xr.h

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

diff --git a/source/blender/windowmanager/intern/wm_operators.c b/source/blender/windowmanager/intern/wm_operators.c
index a7578291a21..e3c7bca0e8c 100644
--- a/source/blender/windowmanager/intern/wm_operators.c
+++ b/source/blender/windowmanager/intern/wm_operators.c
@@ -3734,6 +3734,7 @@ static int wm_xr_session_toggle_exec(bContext *C, wmOperator *UNUSED(op))
 {
   Main *bmain = CTX_data_main(C);
   wmWindowManager *wm = CTX_wm_manager(C);
+  wmWindow *win = CTX_wm_window(C);
   View3D *v3d = CTX_wm_view3d(C);
 
   /* Lazy-create xr context - tries to dynlink to the runtime, reading active_runtime.json. */
@@ -3742,7 +3743,7 @@ static int wm_xr_session_toggle_exec(bContext *C, wmOperator *UNUSED(op))
   }
 
   v3d->runtime.flag |= V3D_RUNTIME_XR_SESSION_ROOT;
-  wm_xr_session_toggle(wm, wm_xr_session_update_screen_on_exit_cb);
+  wm_xr_session_toggle(wm, win, wm_xr_session_update_screen_on_exit_cb);
   wm_xr_session_update_screen(bmain, &wm->xr);
 
   WM_event_add_notifier(C, NC_WM | ND_XR_DATA_CHANGED, NULL);
diff --git a/source/blender/windowmanager/xr/intern/wm_xr_intern.h b/source/blender/windowmanager/xr/intern/wm_xr_intern.h
index b53ae45a29f..8d249f8c55d 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_intern.h
+++ b/source/blender/windowmanager/xr/intern/wm_xr_intern.h
@@ -45,7 +45,11 @@ typedef struct wmXrSessionState {
 typedef struct wmXrRuntimeData {
   GHOST_XrContextHandle context;
 
-  /* Although this struct is internal, RNA gets a handle to this for state information queries. */
+  /** The window the session was started in. Stored to be able to follow its view-layer. This may
+   * be an invalid reference, i.e. the window may have been closed. */
+  wmWindow *session_root_win;
+
+  /** Although this struct is internal, RNA gets a handle to this for state information queries. */
   wmXrSessionState session_state;
   wmXrSessionExitFn exit_fn;
 } wmXrRuntimeData;
diff --git a/source/blender/windowmanager/xr/intern/wm_xr_session.c b/source/blender/windowmanager/xr/intern/wm_xr_session.c
index 4eb0599a609..5c90bd6331a 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_session.c
+++ b/source/blender/windowmanager/xr/intern/wm_xr_session.c
@@ -19,7 +19,10 @@
  */
 
 #include "BKE_context.h"
+#include "BKE_main.h"
+#include "BKE_scene.h"
 
+#include "BLI_listbase.h"
 #include "BLI_math.h"
 
 #include "DEG_depsgraph.h"
@@ -68,7 +71,9 @@ static void wm_xr_session_begin_info_create(wmXrData *xr_data,
   r_begin_info->exit_customdata = xr_data;
 }
 
-void wm_xr_session_toggle(wmWindowManager *wm, wmXrSessionExitFn session_exit_fn)
+void wm_xr_session_toggle(wmWindowManager *wm,
+                          wmWindow *session_root_win,
+                          wmXrSessionExitFn session_exit_fn)
 {
   wmXrData *xr_data = &wm->xr;
 
@@ -78,6 +83,7 @@ void wm_xr_session_toggle(wmWindowManager *wm, wmXrSessionExitFn session_exit_fn
   else {
     GHOST_XrSessionBeginInfo begin_info;
 
+    xr_data->runtime->session_root_win = session_root_win;
     xr_data->runtime->session_state.is_started = true;
     xr_data->runtime->exit_fn = session_exit_fn;
 
@@ -154,6 +160,43 @@ static void wm_xr_session_draw_data_populate(wmXrData *xr_data,
   wm_xr_session_base_pose_calc(r_draw_data->scene, settings, &r_draw_data->base_pose);
 }
 
+static wmWindow *wm_xr_session_root_window_or_fallback_get(const wmWindowManager *wm,
+                                                           const wmXrRuntimeData *runtime_data)
+{
+  if (runtime_data->session_root_win &&
+      BLI_findindex(&wm->windows, runtime_data->session_root_win) != -1) {
+    /* Root window is still valid, use it. */
+    return runtime_data->session_root_win;
+  }
+  /* Otherwise, fallback. */
+  return wm->windows.first;
+}
+
+/**
+ * Get the scene and depsgraph shown in the VR session's root window (the window the session was
+ * started from) if still available. If it's not available, use some fallback window.
+ *
+ * It's important that the VR session follows some existing window, otherwise it would need to have
+ * an own depsgraph, which is an expense we should avoid.
+ */
+static void wm_xr_session_scene_and_evaluated_depsgraph_get(Main *bmain,
+                                                            const wmWindowManager *wm,
+                                                            Scene **r_scene,
+                                                            Depsgraph **r_depsgraph)
+{
+  const wmWindow *root_win = wm_xr_session_root_window_or_fallback_get(wm, wm->xr.runtime);
+
+  /* Follow the scene & view layer shown in the root 3D View. */
+  Scene *scene = WM_window_get_active_scene(root_win);
+  ViewLayer *view_layer = WM_window_get_active_view_layer(root_win);
+
+  Depsgraph *depsgraph = BKE_scene_get_depsgraph(bmain, scene, view_layer, false);
+  BLI_assert(scene && view_layer && depsgraph);
+  BKE_scene_graph_evaluated_ensure(depsgraph, bmain);
+  *r_scene = scene;
+  *r_depsgraph = depsgraph;
+}
+
 void wm_xr_session_draw_data_update(const wmXrSessionState *state,
                                     const XrSessionSettings *settings,
                                     const GHOST_XrDrawViewInfo *draw_view,
@@ -288,13 +331,17 @@ static void wm_xr_session_surface_draw(bContext *C)
 {
   wmXrSurfaceData *surface_data = g_xr_surface->customdata;
   wmWindowManager *wm = CTX_wm_manager(C);
+  Main *bmain = CTX_data_main(C);
   wmXrDrawData draw_data;
 
   if (!GHOST_XrSessionIsRunning(wm->xr.runtime->context)) {
     return;
   }
-  wm_xr_session_draw_data_populate(
-      &wm->xr, CTX_data_scene(C), CTX_data_ensure_evaluated_depsgraph(C), &draw_data);
+
+  Scene *scene;
+  Depsgraph *depsgraph;
+  wm_xr_session_scene_and_evaluated_depsgraph_get(bmain, wm, &scene, &depsgraph);
+  wm_xr_session_draw_data_populate(&wm->xr, scene, depsgraph, &draw_data);
 
   GHOST_XrSessionDrawViews(wm->xr.runtime->context, &draw_data);
 
diff --git a/source/blender/windowmanager/xr/wm_xr.h b/source/blender/windowmanager/xr/wm_xr.h
index 33f79bc75b2..b4c58d3f139 100644
--- a/source/blender/windowmanager/xr/wm_xr.h
+++ b/source/blender/windowmanager/xr/wm_xr.h
@@ -29,7 +29,7 @@ typedef void (*wmXrSessionExitFn)(const wmXrData *xr_data);
 /* wm_xr.c */
 bool wm_xr_init(wmWindowManager *wm);
 void wm_xr_exit(wmWindowManager *wm);
-void wm_xr_session_toggle(wmWindowManager *wm, wmXrSessionExitFn session_exit_fn);
+void wm_xr_session_toggle(wmWindowManager *wm, wmWindow *win, wmXrSessionExitFn session_exit_fn);
 bool wm_xr_events_handle(wmWindowManager *wm);
 
 #endif



More information about the Bf-blender-cvs mailing list