Fix T69809, T69810: sculpt gone or crashing after render
authorBrecht Van Lommel <brechtvanlommel@gmail.com>
Tue, 17 Sep 2019 15:24:44 +0000 (17:24 +0200)
committerBrecht Van Lommel <brechtvanlommel@gmail.com>
Tue, 17 Sep 2019 17:20:08 +0000 (19:20 +0200)
Make a distinction between flush sculpt changes for rendering, and forcing
sculpt data structures to be rebuilt after mesh changes. Also don't use PBVH
for renders.

14 files changed:
source/blender/blenkernel/BKE_multires.h
source/blender/blenkernel/intern/library_remap.c
source/blender/blenkernel/intern/mesh.c
source/blender/blenkernel/intern/multires.c
source/blender/draw/engines/basic/basic_engine.c
source/blender/draw/engines/eevee/eevee_materials.c
source/blender/draw/engines/workbench/workbench_deferred.c
source/blender/draw/engines/workbench/workbench_forward.c
source/blender/draw/modes/overlay_mode.c
source/blender/editors/object/object_bake.c
source/blender/editors/object/object_modifier.c
source/blender/editors/sculpt_paint/sculpt.c
source/blender/editors/util/ed_util.c
source/blender/makesrna/intern/rna_modifier.c

index c5955a9af8d17257f7f0f90bc3ecbf3c74745b7a..7513717df418a893d550102f2f96c94327d3b292 100644 (file)
@@ -53,8 +53,8 @@ void multires_mark_as_modified(struct Depsgraph *depsgraph,
                                struct Object *object,
                                enum MultiresModifiedFlags flags);
 
-void multires_force_update(struct Object *ob);
-void multires_force_render_update(struct Object *ob);
+void multires_flush_sculpt_updates(struct Object *ob);
+void multires_force_sculpt_rebuild(struct Object *ob);
 void multires_force_external_reload(struct Object *ob);
 
 /* internal, only called in subsurf_ccg.c */
index 61f506a8a6c85cae8ef64725f00e4c40547bdda5..7554dad5fb0abc4e2637bbb5fa5c0f5a6b69e894 100644 (file)
@@ -389,7 +389,7 @@ static void libblock_remap_data_postprocess_obdata_relink(Main *bmain, Object *o
   if (ob->data == new_id) {
     switch (GS(new_id->name)) {
       case ID_ME:
-        multires_force_update(ob);
+        multires_force_sculpt_rebuild(ob);
         break;
       case ID_CU:
         BKE_curve_type_test(ob);
index ae9c3400ace33c4270d09ae0bbbdd81364b866e9..c108ff90850fa3da184fb5fe553ee83a221e384d 100644 (file)
@@ -1080,12 +1080,12 @@ void BKE_mesh_assign_object(Main *bmain, Object *ob, Mesh *me)
 {
   Mesh *old = NULL;
 
-  multires_force_update(ob);
-
   if (ob == NULL) {
     return;
   }
 
+  multires_force_sculpt_rebuild(ob);
+
   if (ob->type == OB_MESH) {
     old = ob->data;
     if (old) {
index 8cf960a7f145689d7b6201241175c1d914142c89..82dfe68dbd606706711014302fc7fcc13abb8605 100644 (file)
@@ -406,24 +406,24 @@ void multires_mark_as_modified(Depsgraph *depsgraph, Object *object, MultiresMod
   multires_ccg_mark_as_modified(subdiv_ccg, flags);
 }
 
-void multires_force_update(Object *ob)
+void multires_flush_sculpt_updates(Object *ob)
 {
-  if (ob == NULL) {
-    return;
-  }
-  SculptSession *sculpt_session = ob->sculpt;
-  if (sculpt_session != NULL && sculpt_session->pbvh != NULL) {
-    PBVH *pbvh = sculpt_session->pbvh;
-    if (BKE_pbvh_type(pbvh) == PBVH_GRIDS) {
+  if (ob && ob->sculpt && ob->sculpt->pbvh != NULL) {
+    SculptSession *sculpt_session = ob->sculpt;
+    if (BKE_pbvh_type(sculpt_session->pbvh) == PBVH_GRIDS) {
       Mesh *mesh = ob->data;
       multiresModifier_reshapeFromCCG(
           sculpt_session->multires->totlvl, mesh, sculpt_session->subdiv_ccg);
     }
-    else {
-      /* NOTE: Disabled for until OpenSubdiv is enabled by default. */
-      // BLI_assert(!"multires_force_update is used on non-grids PBVH");
-    }
-    BKE_pbvh_free(pbvh);
+  }
+}
+
+void multires_force_sculpt_rebuild(Object *ob)
+{
+  multires_flush_sculpt_updates(ob);
+
+  if (ob && ob->sculpt && ob->sculpt->pbvh != NULL) {
+    BKE_pbvh_free(ob->sculpt->pbvh);
     ob->sculpt->pbvh = NULL;
   }
 }
@@ -433,14 +433,7 @@ void multires_force_external_reload(Object *ob)
   Mesh *me = BKE_mesh_from_object(ob);
 
   CustomData_external_reload(&me->ldata, &me->id, CD_MASK_MDISPS, me->totloop);
-  multires_force_update(ob);
-}
-
-void multires_force_render_update(Object *ob)
-{
-  if (ob && (ob->mode & OB_MODE_SCULPT) && modifiers_findByType(ob, eModifierType_Multires)) {
-    multires_force_update(ob);
-  }
+  multires_force_sculpt_rebuild(ob);
 }
 
 /* reset the multires levels to match the number of mdisps */
@@ -624,7 +617,7 @@ static void multires_del_higher(MultiresModifierData *mmd, Object *ob, int lvl)
   mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
   gpm = CustomData_get_layer(&me->ldata, CD_GRID_PAINT_MASK);
 
-  multires_force_update(ob);
+  multires_force_sculpt_rebuild(ob);
 
   if (mdisps && levels > 0) {
     if (lvl > 0) {
@@ -689,7 +682,7 @@ void multiresModifier_del_levels(MultiresModifierData *mmd,
   CustomData_external_read(&me->ldata, &me->id, CD_MASK_MDISPS, me->totloop);
   mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
 
-  multires_force_update(ob);
+  multires_force_sculpt_rebuild(ob);
 
   if (mdisps && levels > 0 && direction == 1) {
     multires_del_higher(mmd, ob, lvl);
@@ -781,7 +774,7 @@ void multiresModifier_base_apply(MultiresModifierData *mmd, Scene *scene, Object
   float(*origco)[3];
   int i, j, k, offset, totlvl;
 
-  multires_force_update(ob);
+  multires_force_sculpt_rebuild(ob);
 
   me = BKE_mesh_from_object(ob);
   totlvl = mmd->totlvl;
@@ -928,7 +921,7 @@ static void multires_subdivide(
 
   BLI_assert(totlvl > lvl);
 
-  multires_force_update(ob);
+  multires_force_sculpt_rebuild(ob);
 
   mdisps = CustomData_get_layer(&me->ldata, CD_MDISPS);
   if (!mdisps) {
index f548bd15bf4dc485de340b4b0d76bbcd4eef40e3..188e252a285714dd6d38b111780337312bc53cd6 100644 (file)
@@ -162,7 +162,8 @@ static void basic_cache_populate(void *vedata, Object *ob)
     }
   }
 
-  const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d);
+  const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) &&
+                               !DRW_state_is_image_render();
   const bool do_cull = (draw_ctx->v3d &&
                         (draw_ctx->v3d->shading.flag & V3D_SHADING_BACKFACE_CULLING));
   DRWShadingGroup *shgrp = (do_cull) ? stl->g_data->depth_shgrp_cull : stl->g_data->depth_shgrp;
index 2158d395d8459ba0f859a2a09fa5a9b75463da66..f01c6363ccbb049bf72f5c05bf0b7279af7d5891 100644 (file)
@@ -1454,7 +1454,8 @@ void EEVEE_materials_cache_populate(EEVEE_Data *vedata,
   Scene *scene = draw_ctx->scene;
   GHash *material_hash = stl->g_data->material_hash;
 
-  bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d);
+  bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) &&
+                         !DRW_state_is_image_render();
 
   /* First get materials for this mesh. */
   if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) {
index e41cba1d3bdc8ff43da5b921ebb4c993655a00fb..15522ba0dfb76199e5ee5c97c7d0eb60b24a27b5 100644 (file)
@@ -945,7 +945,8 @@ static void workbench_cache_populate_texture_paint_mode(WORKBENCH_Data *vedata,
   const DRWContextState *draw_ctx = DRW_context_state_get();
 
   Scene *scene = draw_ctx->scene;
-  const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d);
+  const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) &&
+                               !DRW_state_is_image_render();
   WORKBENCH_MaterialData *material;
 
   /* Force workbench to render active object textured when in texture paint mode */
index 890359e8fda5de4c31484dd7346746ac10b2e560..d731b167c06d7fcad6ddafb4ab5048879474f444 100644 (file)
@@ -560,7 +560,8 @@ static void workbench_forward_cache_populate_texture_paint_mode(WORKBENCH_Data *
   const DRWContextState *draw_ctx = DRW_context_state_get();
 
   Scene *scene = draw_ctx->scene;
-  const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d);
+  const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) &&
+                               !DRW_state_is_image_render();
   WORKBENCH_MaterialData *material;
 
   /* Force workbench to render active object textured when in texture paint mode */
@@ -635,7 +636,8 @@ void workbench_forward_cache_populate(WORKBENCH_Data *vedata, Object *ob)
 
   WORKBENCH_MaterialData *material;
   if (ELEM(ob->type, OB_MESH, OB_CURVE, OB_SURF, OB_FONT, OB_MBALL)) {
-    const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d);
+    const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) &&
+                                 !DRW_state_is_image_render();
     const int materials_len = MAX2(1, ob->totcol);
     const Mesh *me = (ob->type == OB_MESH) ? ob->data : NULL;
     const bool use_texture_paint_drawing = !(DRW_state_is_image_render() &&
index 2433f4c1df5182d25ac17d1443fc7d4f53bfc6d8..587046589eea5c234ded0b5be32118915ef98eb4 100644 (file)
@@ -394,7 +394,8 @@ static void overlay_cache_populate(void *vedata, Object *ob)
     if ((!pd->show_overlays) ||
         (((ob != draw_ctx->object_edit) && !is_edit_mode) || has_edit_mesh_cage) ||
         ob->type != OB_MESH) {
-      const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d);
+      const bool use_sculpt_pbvh = BKE_sculptsession_use_pbvh_draw(ob, draw_ctx->v3d) &&
+                                   !DRW_state_is_image_render();
       const bool all_wires = (ob->dtx & OB_DRAW_ALL_EDGES);
       const bool is_wire = (ob->dt < OB_SOLID);
       const bool is_xray = (ob->dtx & OB_DRAWXRAY);
index 70a9870e6aebb46897582095647a40c3f6c551ce..bc79521ee9bb7efb519c1463aac9a19e937f2a6a 100644 (file)
@@ -371,7 +371,7 @@ static int multiresbake_image_exec_locked(bContext *C, wmOperator *op)
 
     ob = base->object;
 
-    multires_force_update(ob);
+    multires_flush_sculpt_updates(ob);
 
     /* copy data stored in job descriptor */
     bkr.scene = scene;
@@ -435,7 +435,7 @@ static void init_multiresbake_job(bContext *C, MultiresBakeJob *bkj)
 
     ob = base->object;
 
-    multires_force_update(ob);
+    multires_flush_sculpt_updates(ob);
 
     data = MEM_callocN(sizeof(MultiresBakerJobData), "multiresBaker derivedMesh_data");
 
index 88d0193688247b27663557dafa103e2a43e77f26..c437f00684d0f0c866ac8f592d5b0e456e5c22f7 100644 (file)
@@ -677,7 +677,7 @@ static int modifier_apply_obdata(
 
     /* Multires: ensure that recent sculpting is applied */
     if (md_eval->type == eModifierType_Multires) {
-      multires_force_update(ob);
+      multires_force_sculpt_rebuild(ob);
     }
 
     if (mmd && mmd->totlvl && mti->type == eModifierTypeType_OnlyDeform) {
index 83b9abe5f3e6bb93b673cea6e766f7b5ba95cb7a..f9a7e59c509a9441ec9c042cfa80aad5ae3d5e7e 100644 (file)
@@ -1099,7 +1099,7 @@ static bool sculpt_brush_test_cyl(SculptBrushTest *test,
 static bool sculpt_automasking_enabled(SculptSession *ss, const Brush *br)
 {
   // REMOVE WITH PBVH_GRIDS
-  if (BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
+  if (ss->pbvh && BKE_pbvh_type(ss->pbvh) == PBVH_GRIDS) {
     return false;
   }
 
@@ -7529,13 +7529,11 @@ void ED_object_sculptmode_exit_ex(Main *bmain, Depsgraph *depsgraph, Scene *scen
   const int mode_flag = OB_MODE_SCULPT;
   Mesh *me = BKE_mesh_from_object(ob);
 
-  MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob);
-  if (mmd) {
-    multires_force_update(ob);
-  }
+  multires_flush_sculpt_updates(ob);
 
   /* Not needed for now. */
 #if 0
+  MultiresModifierData *mmd = BKE_sculpt_multires_active(scene, ob);
   const int flush_recalc = ed_object_sculptmode_flush_recalc_flag(scene, ob, mmd);
 #endif
 
index c2566d111cfcb8a461dbadbbc407de9fa2b1e778..f5548119e0aa4606b8d04a49d3905308f7a715f0 100644 (file)
@@ -245,7 +245,7 @@ bool ED_editors_flush_edits(Main *bmain, bool for_render)
        * may cause a flush on saving: T53986. */
       if ((ob->sculpt && ob->sculpt->cache) == 0) {
         /* flush multires changes (for sculpt) */
-        multires_force_update(ob);
+        multires_flush_sculpt_updates(ob);
         has_edited = true;
 
         if (for_render) {
index 712fe2a9984fe177b6680f346b79846a10239efb..eebb09a2bc338aa07eba020de514ae0161c38078 100644 (file)
@@ -915,7 +915,7 @@ static void rna_MultiresModifier_type_set(PointerRNA *ptr, int value)
   Object *ob = (Object *)ptr->owner_id;
   MultiresModifierData *mmd = (MultiresModifierData *)ptr->data;
 
-  multires_force_update(ob);
+  multires_force_sculpt_rebuild(ob);
   mmd->simple = value;
 }