[Bf-blender-cvs] [4e78a7360e4] blender-v3.1-release: Fix T93784: text and curve objects have no motion blur

Jacques Lucke noreply at git.blender.org
Tue Feb 22 13:52:25 CET 2022


Commit: 4e78a7360e451b4e2c99e8fb88d6701bc8f13618
Author: Jacques Lucke
Date:   Tue Feb 22 13:52:15 2022 +0100
Branches: blender-v3.1-release
https://developer.blender.org/rB4e78a7360e451b4e2c99e8fb88d6701bc8f13618

Fix T93784: text and curve objects have no motion blur

Previously, objects and geometries were mapped between frames
using different hash tables in a way that is incompatible with
geometry instances. That is because the geometry mapping happened
without looking at the `persistent_id` of instances, which is not possible
anymore. Now, there is just one mapping that identifies the same
object at multiple points in time.

There are also two new caches for duplicated vbos and textures used for
motion blur. This data has to be duplicated, otherwise it would be freed
when another time step is evaluated. This caching existed before, but is
now a bit more explicit and works for geometry instances as well.

Differential Revision: https://developer.blender.org/D13497

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

M	source/blender/draw/engines/eevee/eevee_data.c
M	source/blender/draw/engines/eevee/eevee_motion_blur.c
M	source/blender/draw/engines/eevee/eevee_private.h
M	source/blender/gpu/GPU_batch.h
M	source/blender/gpu/intern/gpu_batch.cc

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

diff --git a/source/blender/draw/engines/eevee/eevee_data.c b/source/blender/draw/engines/eevee/eevee_data.c
index b453df284ed..58ea682c060 100644
--- a/source/blender/draw/engines/eevee/eevee_data.c
+++ b/source/blender/draw/engines/eevee/eevee_data.c
@@ -42,25 +42,12 @@
 
 static void eevee_motion_blur_mesh_data_free(void *val)
 {
-  EEVEE_GeometryMotionData *geom_mb = (EEVEE_GeometryMotionData *)val;
-  EEVEE_HairMotionData *hair_mb = (EEVEE_HairMotionData *)val;
-  switch (geom_mb->type) {
-    case EEVEE_MOTION_DATA_HAIR:
-      for (int j = 0; j < hair_mb->psys_len; j++) {
-        for (int i = 0; i < ARRAY_SIZE(hair_mb->psys[0].hair_pos); i++) {
-          GPU_VERTBUF_DISCARD_SAFE(hair_mb->psys[j].hair_pos[i]);
-        }
-        for (int i = 0; i < ARRAY_SIZE(hair_mb->psys[0].hair_pos); i++) {
-          DRW_TEXTURE_FREE_SAFE(hair_mb->psys[j].hair_pos_tx[i]);
-        }
-      }
-      break;
-
-    case EEVEE_MOTION_DATA_MESH:
-      for (int i = 0; i < ARRAY_SIZE(geom_mb->vbo); i++) {
-        GPU_VERTBUF_DISCARD_SAFE(geom_mb->vbo[i]);
-      }
-      break;
+  EEVEE_ObjectMotionData *mb_data = (EEVEE_ObjectMotionData *)val;
+  if (mb_data->hair_data != NULL) {
+    MEM_freeN(mb_data->hair_data);
+  }
+  if (mb_data->geometry_data != NULL) {
+    MEM_freeN(mb_data->geometry_data);
   }
   MEM_freeN(val);
 }
@@ -99,39 +86,57 @@ static bool eevee_object_key_cmp(const void *a, const void *b)
   return false;
 }
 
+void EEVEE_motion_hair_step_free(EEVEE_HairMotionStepData *step_data)
+{
+  GPU_vertbuf_discard(step_data->hair_pos);
+  DRW_texture_free(step_data->hair_pos_tx);
+  MEM_freeN(step_data);
+}
+
 void EEVEE_motion_blur_data_init(EEVEE_MotionBlurData *mb)
 {
   if (mb->object == NULL) {
     mb->object = BLI_ghash_new(eevee_object_key_hash, eevee_object_key_cmp, "EEVEE Object Motion");
   }
-  if (mb->geom == NULL) {
-    mb->geom = BLI_ghash_new(BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "EEVEE Mesh Motion");
+  for (int i = 0; i < 2; i++) {
+    if (mb->position_vbo_cache[i] == NULL) {
+      mb->position_vbo_cache[i] = BLI_ghash_new(
+          BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "EEVEE duplicate vbo cache");
+    }
+    if (mb->hair_motion_step_cache[i] == NULL) {
+      mb->hair_motion_step_cache[i] = BLI_ghash_new(
+          BLI_ghashutil_ptrhash, BLI_ghashutil_ptrcmp, "EEVEE hair motion step cache");
+    }
   }
 }
 
 void EEVEE_motion_blur_data_free(EEVEE_MotionBlurData *mb)
 {
   if (mb->object) {
-    BLI_ghash_free(mb->object, MEM_freeN, MEM_freeN);
+    BLI_ghash_free(mb->object, MEM_freeN, eevee_motion_blur_mesh_data_free);
     mb->object = NULL;
   }
-  if (mb->geom) {
-    BLI_ghash_free(mb->geom, NULL, eevee_motion_blur_mesh_data_free);
-    mb->geom = NULL;
+  for (int i = 0; i < 2; i++) {
+    if (mb->position_vbo_cache[i]) {
+      BLI_ghash_free(mb->position_vbo_cache[i], NULL, (GHashValFreeFP)GPU_vertbuf_discard);
+    }
+    if (mb->hair_motion_step_cache[i]) {
+      BLI_ghash_free(
+          mb->hair_motion_step_cache[i], NULL, (GHashValFreeFP)EEVEE_motion_hair_step_free);
+    }
   }
 }
 
-EEVEE_ObjectMotionData *EEVEE_motion_blur_object_data_get(EEVEE_MotionBlurData *mb,
-                                                          Object *ob,
-                                                          bool hair)
+EEVEE_ObjectMotionData *EEVEE_motion_blur_object_data_get(EEVEE_MotionBlurData *mb, Object *ob)
 {
   if (mb->object == NULL) {
     return NULL;
   }
 
   EEVEE_ObjectKey key, *key_p;
-  /* Small hack to avoid another comparison. */
-  key.ob = (Object *)((char *)ob + hair);
+  /* Assumes that all instances have the same object pointer. This is currently the case because
+   * instance objects are temporary objects on the stack. */
+  key.ob = ob;
   DupliObject *dup = DRW_object_get_dupli(ob);
   if (dup) {
     key.parent = DRW_object_get_dupli_parent(ob);
@@ -154,53 +159,28 @@ EEVEE_ObjectMotionData *EEVEE_motion_blur_object_data_get(EEVEE_MotionBlurData *
   return ob_step;
 }
 
-static void *motion_blur_deform_data_get(EEVEE_MotionBlurData *mb, Object *ob, bool hair)
+EEVEE_GeometryMotionData *EEVEE_motion_blur_geometry_data_get(EEVEE_ObjectMotionData *mb_data)
 {
-  if (mb->geom == NULL) {
-    return NULL;
+  if (mb_data->geometry_data == NULL) {
+    EEVEE_GeometryMotionData *geom_step = MEM_callocN(sizeof(EEVEE_GeometryMotionData), __func__);
+    geom_step->type = EEVEE_MOTION_DATA_MESH;
+    mb_data->geometry_data = geom_step;
   }
-  DupliObject *dup = DRW_object_get_dupli(ob);
-  void *key;
-  if (dup) {
-    key = dup->ob;
-  }
-  else {
-    key = ob;
-  }
-  /* Only use data for object that have no modifiers. */
-  if (!BKE_object_is_modified(DRW_context_state_get()->scene, ob)) {
-    key = ob->data;
-  }
-  key = (char *)key + (int)hair;
-  EEVEE_GeometryMotionData *geom_step = BLI_ghash_lookup(mb->geom, key);
-  if (geom_step == NULL) {
-    if (hair) {
-      EEVEE_HairMotionData *hair_step;
-      /* Ugly, we allocate for each modifiers and just fill based on modifier index in the list. */
-      int psys_len = (ob->type != OB_HAIR) ? BLI_listbase_count(&ob->modifiers) : 1;
-      hair_step = MEM_callocN(sizeof(EEVEE_HairMotionData) + sizeof(hair_step->psys[0]) * psys_len,
-                              __func__);
-      hair_step->psys_len = psys_len;
-      geom_step = (EEVEE_GeometryMotionData *)hair_step;
-      geom_step->type = EEVEE_MOTION_DATA_HAIR;
-    }
-    else {
-      geom_step = MEM_callocN(sizeof(EEVEE_GeometryMotionData), __func__);
-      geom_step->type = EEVEE_MOTION_DATA_MESH;
-    }
-    BLI_ghash_insert(mb->geom, key, geom_step);
-  }
-  return geom_step;
+  return mb_data->geometry_data;
 }
 
-EEVEE_GeometryMotionData *EEVEE_motion_blur_geometry_data_get(EEVEE_MotionBlurData *mb, Object *ob)
+EEVEE_HairMotionData *EEVEE_motion_blur_hair_data_get(EEVEE_ObjectMotionData *mb_data, Object *ob)
 {
-  return motion_blur_deform_data_get(mb, ob, false);
-}
-
-EEVEE_HairMotionData *EEVEE_motion_blur_hair_data_get(EEVEE_MotionBlurData *mb, Object *ob)
-{
-  return motion_blur_deform_data_get(mb, ob, true);
+  if (mb_data->hair_data == NULL) {
+    /* Ugly, we allocate for each modifiers and just fill based on modifier index in the list. */
+    int psys_len = (ob->type != OB_HAIR) ? BLI_listbase_count(&ob->modifiers) : 1;
+    EEVEE_HairMotionData *hair_step = MEM_callocN(
+        sizeof(EEVEE_HairMotionData) + sizeof(hair_step->psys[0]) * psys_len, __func__);
+    hair_step->psys_len = psys_len;
+    hair_step->type = EEVEE_MOTION_DATA_HAIR;
+    mb_data->hair_data = hair_step;
+  }
+  return mb_data->hair_data;
 }
 
 /* View Layer data. */
diff --git a/source/blender/draw/engines/eevee/eevee_motion_blur.c b/source/blender/draw/engines/eevee/eevee_motion_blur.c
index 703518a32ec..dd6b4b2c17a 100644
--- a/source/blender/draw/engines/eevee/eevee_motion_blur.c
+++ b/source/blender/draw/engines/eevee/eevee_motion_blur.c
@@ -241,15 +241,14 @@ void EEVEE_motion_blur_hair_cache_populate(EEVEE_ViewLayerData *UNUSED(sldata),
   }
 
   /* For now we assume hair objects are always moving. */
-  EEVEE_ObjectMotionData *mb_data = EEVEE_motion_blur_object_data_get(
-      &effects->motion_blur, ob, true);
+  EEVEE_ObjectMotionData *mb_data = EEVEE_motion_blur_object_data_get(&effects->motion_blur, ob);
 
   if (mb_data) {
     int mb_step = effects->motion_blur_step;
     /* Store transform. */
     DRW_hair_duplimat_get(ob, psys, md, mb_data->obmat[mb_step]);
 
-    EEVEE_HairMotionData *mb_hair = EEVEE_motion_blur_hair_data_get(&effects->motion_blur, ob);
+    EEVEE_HairMotionData *mb_hair = EEVEE_motion_blur_hair_data_get(mb_data, ob);
     int psys_id = (md != NULL) ? BLI_findindex(&ob->modifiers, md) : 0;
 
     if (psys_id >= mb_hair->psys_len) {
@@ -267,8 +266,8 @@ void EEVEE_motion_blur_hair_cache_populate(EEVEE_ViewLayerData *UNUSED(sldata),
         copy_m4_m4(mb_data->obmat[MB_NEXT], mb_data->obmat[MB_CURR]);
       }
 
-      GPUTexture *tex_prev = mb_hair->psys[psys_id].hair_pos_tx[MB_PREV];
-      GPUTexture *tex_next = mb_hair->psys[psys_id].hair_pos_tx[MB_NEXT];
+      GPUTexture *tex_prev = mb_hair->psys[psys_id].step_data[MB_PREV].hair_pos_tx;
+      GPUTexture *tex_next = mb_hair->psys[psys_id].step_data[MB_NEXT].hair_pos_tx;
 
       grp = DRW_shgroup_hair_create_sub(ob, psys, md, effects->motion_blur.hair_grp, NULL);
       DRW_shgroup_uniform_mat4(grp, "prevModelMatrix", mb_data->obmat[MB_PREV]);
@@ -280,7 +279,7 @@ void EEVEE_motion_blur_hair_cache_populate(EEVEE_ViewLayerData *UNUSED(sldata),
     }
     else {
       /* Store vertex position buffer. */
-      mb_hair->psys[psys_id].hair_pos[mb_step] = DRW_hair_pos_buffer_get(ob, psys, md);
+      mb_hair->psys[psys_id].step_data[mb_step].hair_pos = DRW_hair_pos_buffer_get(ob, psys, md);
       mb_hair->use_deform = true;
     }
   }
@@ -319,24 +318,14 @@ void EEVEE_motion_blur_cache_populate(EEVEE_ViewLayerData *UNUSED(sldata),
     return;
   }
 
-  const DupliObject *dup = DRW_object_get_dupli(ob);
-  if (dup != NULL && dup->ob->data != dup->ob_data) {
-    /* Geometry instances do not support motion blur correctly yet. The #key used in
-     * #motion_blur_deform_data_get has to take ids of instances (#DupliObject.persistent_id) into
-     * account. Otherwise it can't find matching geometry instances at different points in time. */
-    return;
-  }
-
-  EEVEE_ObjectMotionData *mb_data = EEVEE_motion_blur_object_data_get(
-      &effects->motion_blur, ob, false);
+  EEVEE_ObjectMotionData *mb_data = EEVEE_motion_blur_object_data_get(&effects->motion_blur, ob);
 
   if (mb_data) {
     int mb_step = effects->motion_blur_step;
     /* Store transform. */
     copy_m4_m4(mb_data->obmat[mb_step], ob->obmat);
 
-    EEVEE_GeometryMotionData *mb_geom = EEVEE_motion_blur_geometry_data_get(&effects->motion_blur,
-                                                                            ob);
+    EEVEE_GeometryMotionData *mb_geom = EEVEE_motion_blur_geometry_data_get(mb_data);
 
     if (mb_step == MB_CURR) {
       GPUBatch *batch = DRW_cache_object_surface_get(ob);
@@ -422,86 +411,93 @@ void EEVEE_motion_blur_cache_finish(EEVEE_Data *vedata)
     DRW_cache_restart();
   }
 
-  for (BLI_

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list