[Bf-blender-cvs] [58ee4852b6e] blender-v3.0-release: Fix T93649: Blender freezes when saving with active VR session

Julian Eisel noreply at git.blender.org
Tue Jan 11 09:32:58 CET 2022


Commit: 58ee4852b6e2d745965f34ef347d5bd6d6e03fbb
Author: Julian Eisel
Date:   Tue Dec 14 15:12:23 2021 +0100
Branches: blender-v3.0-release
https://developer.blender.org/rB58ee4852b6e2d745965f34ef347d5bd6d6e03fbb

Fix T93649: Blender freezes when saving with active VR session

Dead-lock when VR viewport drawing and depsgraph updates would fight for
the draw-manager GL lock. This didn't usually cause issues because the
depsgraph would be evaluated at this point already, except in rare
exceptions like after file writing.

Fix this by ensuring the XR surface gets its depsgraph updated after
handling notifiers, which is where regular windows also do the depsgraph
updating.

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

M	source/blender/windowmanager/intern/wm_event_system.c
M	source/blender/windowmanager/intern/wm_surface.c
M	source/blender/windowmanager/wm_surface.h
M	source/blender/windowmanager/xr/intern/wm_xr_session.c

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

diff --git a/source/blender/windowmanager/intern/wm_event_system.c b/source/blender/windowmanager/intern/wm_event_system.c
index c5efb239a88..f61030e315c 100644
--- a/source/blender/windowmanager/intern/wm_event_system.c
+++ b/source/blender/windowmanager/intern/wm_event_system.c
@@ -84,6 +84,7 @@
 #include "wm.h"
 #include "wm_event_system.h"
 #include "wm_event_types.h"
+#include "wm_surface.h"
 #include "wm_window.h"
 
 #include "DEG_depsgraph.h"
@@ -385,6 +386,8 @@ void wm_event_do_depsgraph(bContext *C, bool is_after_open_file)
     DEG_make_active(depsgraph);
     BKE_scene_graph_update_tagged(depsgraph, bmain);
   }
+
+  wm_surfaces_do_depsgraph(C);
 }
 
 /**
diff --git a/source/blender/windowmanager/intern/wm_surface.c b/source/blender/windowmanager/intern/wm_surface.c
index 715f72d70cf..72b68788e79 100644
--- a/source/blender/windowmanager/intern/wm_surface.c
+++ b/source/blender/windowmanager/intern/wm_surface.c
@@ -50,6 +50,18 @@ void wm_surfaces_iter(bContext *C, void (*cb)(bContext *C, wmSurface *))
   }
 }
 
+static void wm_surface_do_depsgraph_fn(bContext *C, wmSurface *surface)
+{
+  if (surface->do_depsgraph) {
+    surface->do_depsgraph(C);
+  }
+}
+
+void wm_surfaces_do_depsgraph(bContext *C)
+{
+  wm_surfaces_iter(C, wm_surface_do_depsgraph_fn);
+}
+
 void wm_surface_clear_drawable(void)
 {
   if (g_drawable) {
diff --git a/source/blender/windowmanager/wm_surface.h b/source/blender/windowmanager/wm_surface.h
index a2483d38154..e924b1e47ad 100644
--- a/source/blender/windowmanager/wm_surface.h
+++ b/source/blender/windowmanager/wm_surface.h
@@ -39,6 +39,8 @@ typedef struct wmSurface {
   void *customdata;
 
   void (*draw)(struct bContext *);
+  /* To evaluate the surface's depsgraph. Called as part of the main loop. */
+  void (*do_depsgraph)(struct bContext *C);
   /** Free customdata, not the surface itself (done by wm_surface API) */
   void (*free_data)(struct wmSurface *);
 
@@ -56,6 +58,9 @@ void wm_surfaces_free(void);
 /* Utils */
 void wm_surfaces_iter(struct bContext *C, void (*cb)(struct bContext *, wmSurface *));
 
+/* Evaluation. */
+void wm_surfaces_do_depsgraph(struct bContext *C);
+
 /* Drawing */
 void wm_surface_make_drawable(wmSurface *surface);
 void wm_surface_clear_drawable(void);
diff --git a/source/blender/windowmanager/xr/intern/wm_xr_session.c b/source/blender/windowmanager/xr/intern/wm_xr_session.c
index 3224869b04a..6f9ead7879a 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_session.c
+++ b/source/blender/windowmanager/xr/intern/wm_xr_session.c
@@ -30,6 +30,7 @@
 #include "BLI_math.h"
 
 #include "DEG_depsgraph.h"
+#include "DEG_depsgraph_query.h"
 
 #include "DNA_camera_types.h"
 #include "DNA_space_types.h"
@@ -250,10 +251,9 @@ wmWindow *wm_xr_session_root_window_or_fallback_get(const wmWindowManager *wm,
  * 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)
+static void wm_xr_session_scene_and_depsgraph_get(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);
 
@@ -263,7 +263,6 @@ static void wm_xr_session_scene_and_evaluated_depsgraph_get(Main *bmain,
 
   Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer);
   BLI_assert(scene && view_layer && depsgraph);
-  BKE_scene_graph_evaluated_ensure(depsgraph, bmain);
   *r_scene = scene;
   *r_depsgraph = depsgraph;
 }
@@ -1314,7 +1313,6 @@ void wm_xr_session_controller_data_clear(wmXrSessionState *state)
 static void wm_xr_session_surface_draw(bContext *C)
 {
   wmWindowManager *wm = CTX_wm_manager(C);
-  Main *bmain = CTX_data_main(C);
   wmXrDrawData draw_data;
 
   if (!WM_xr_session_is_ready(&wm->xr)) {
@@ -1323,7 +1321,10 @@ static void wm_xr_session_surface_draw(bContext *C)
 
   Scene *scene;
   Depsgraph *depsgraph;
-  wm_xr_session_scene_and_evaluated_depsgraph_get(bmain, wm, &scene, &depsgraph);
+  wm_xr_session_scene_and_depsgraph_get(wm, &scene, &depsgraph);
+  /* Might fail when force-redrawing windows with #WM_redraw_windows(), which is done on file
+   * writing for example. */
+  // BLI_assert(DEG_is_fully_evaluated(depsgraph));
   wm_xr_session_draw_data_populate(&wm->xr, scene, depsgraph, &draw_data);
 
   GHOST_XrSessionDrawViews(wm->xr.runtime->context, &draw_data);
@@ -1331,6 +1332,20 @@ static void wm_xr_session_surface_draw(bContext *C)
   GPU_framebuffer_restore();
 }
 
+static void wm_xr_session_do_depsgraph(bContext *C)
+{
+  wmWindowManager *wm = CTX_wm_manager(C);
+
+  if (!WM_xr_session_is_ready(&wm->xr)) {
+    return;
+  }
+
+  Scene *scene;
+  Depsgraph *depsgraph;
+  wm_xr_session_scene_and_depsgraph_get(wm, &scene, &depsgraph);
+  BKE_scene_graph_evaluated_ensure(depsgraph, CTX_data_main(C));
+}
+
 bool wm_xr_session_surface_offscreen_ensure(wmXrSurfaceData *surface_data,
                                             const GHOST_XrDrawViewInfo *draw_view)
 {
@@ -1439,6 +1454,7 @@ static wmSurface *wm_xr_session_surface_create(void)
   data->controller_art = MEM_callocN(sizeof(*(data->controller_art)), "XrControllerRegionType");
 
   surface->draw = wm_xr_session_surface_draw;
+  surface->do_depsgraph = wm_xr_session_do_depsgraph;
   surface->free_data = wm_xr_session_surface_free_data;
   surface->activate = DRW_xr_drawing_begin;
   surface->deactivate = DRW_xr_drawing_end;



More information about the Bf-blender-cvs mailing list