diff options
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_data.c | 124 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_motion_blur.c | 254 | ||||
-rw-r--r-- | source/blender/draw/engines/eevee/eevee_private.h | 48 | ||||
-rw-r--r-- | source/blender/gpu/GPU_batch.h | 1 | ||||
-rw-r--r-- | source/blender/gpu/intern/gpu_batch.cc | 10 |
5 files changed, 227 insertions, 210 deletions
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_ghashIterator_init(&ghi, effects->motion_blur.geom); + for (BLI_ghashIterator_init(&ghi, effects->motion_blur.object); BLI_ghashIterator_done(&ghi) == false; BLI_ghashIterator_step(&ghi)) { - EEVEE_GeometryMotionData *mb_geom = BLI_ghashIterator_getValue(&ghi); - EEVEE_HairMotionData *mb_hair = (EEVEE_HairMotionData *)mb_geom; - - if (!mb_geom->use_deform) { - continue; - } - - switch (mb_geom->type) { - case EEVEE_MOTION_DATA_HAIR: - if (mb_step == MB_CURR) { - /* TODO(fclem): Check if vertex count mismatch. */ - mb_hair->use_deform = true; - } - else { - for (int i = 0; i < mb_hair->psys_len; i++) { - if (mb_hair->psys[i].hair_pos[mb_step] == NULL) { - continue; - } - mb_hair->psys[i].hair_pos[mb_step] = GPU_vertbuf_duplicate( - mb_hair->psys[i].hair_pos[mb_step]); - + EEVEE_ObjectMotionData *mb_data = BLI_ghashIterator_getValue(&ghi); + EEVEE_HairMotionData *mb_hair = mb_data->hair_data; + EEVEE_GeometryMotionData *mb_geom = mb_data->geometry_data; + if (mb_hair != NULL && mb_hair->use_deform) { + if (mb_step == MB_CURR) { + /* TODO(fclem): Check if vertex count mismatch. */ + mb_hair->use_deform = true; + } + else { + for (int i = 0; i < mb_hair->psys_len; i++) { + GPUVertBuf *vbo = mb_hair->psys[i].step_data[mb_step].hair_pos; + if (vbo == NULL) { + continue; + } + EEVEE_HairMotionStepData **step_data_cache_ptr; + if (!BLI_ghash_ensure_p(effects->motion_blur.hair_motion_step_cache[mb_step], + vbo, + (void ***)&step_data_cache_ptr)) { + EEVEE_HairMotionStepData *new_step_data = MEM_callocN(sizeof(EEVEE_HairMotionStepData), + __func__); + /* Duplicate the vbo, otherwise it would be lost when evaluating another frame. */ + new_step_data->hair_pos = GPU_vertbuf_duplicate(vbo); /* Create vbo immediately to bind to texture buffer. */ - GPU_vertbuf_use(mb_hair->psys[i].hair_pos[mb_step]); - - mb_hair->psys[i].hair_pos_tx[mb_step] = GPU_texture_create_from_vertbuf( - "hair_pos_motion_blur", mb_hair->psys[i].hair_pos[mb_step]); + GPU_vertbuf_use(new_step_data->hair_pos); + new_step_data->hair_pos_tx = GPU_texture_create_from_vertbuf("hair_pos_motion_blur", + new_step_data->hair_pos); + *step_data_cache_ptr = new_step_data; } + mb_hair->psys[i].step_data[mb_step] = **step_data_cache_ptr; } - break; - - case EEVEE_MOTION_DATA_MESH: - if (mb_step == MB_CURR) { - /* Modify batch to have data from adjacent frames. */ - GPUBatch *batch = mb_geom->batch; - for (int i = 0; i < MB_CURR; i++) { - GPUVertBuf *vbo = mb_geom->vbo[i]; - if (vbo && batch) { - if (GPU_vertbuf_get_vertex_len(vbo) != GPU_vertbuf_get_vertex_len(batch->verts[0])) { - /* Vertex count mismatch, disable deform motion blur. */ - mb_geom->use_deform = false; - } - - if (mb_geom->use_deform == false) { - motion_blur_remove_vbo_reference_from_batch( - batch, mb_geom->vbo[MB_PREV], mb_geom->vbo[MB_NEXT]); - - GPU_VERTBUF_DISCARD_SAFE(mb_geom->vbo[MB_PREV]); - GPU_VERTBUF_DISCARD_SAFE(mb_geom->vbo[MB_NEXT]); - break; - } + } + } + if (mb_geom != NULL && mb_geom->use_deform) { + if (mb_step == MB_CURR) { + /* Modify batch to have data from adjacent frames. */ + GPUBatch *batch = mb_geom->batch; + for (int i = 0; i < MB_CURR; i++) { + GPUVertBuf *vbo = mb_geom->vbo[i]; + if (vbo && batch) { + if (GPU_vertbuf_get_vertex_len(vbo) != GPU_vertbuf_get_vertex_len(batch->verts[0])) { + /* Vertex count mismatch, disable deform motion blur. */ + mb_geom->use_deform = false; + } + if (mb_geom->use_deform == false) { + motion_blur_remove_vbo_reference_from_batch( + batch, mb_geom->vbo[MB_PREV], mb_geom->vbo[MB_NEXT]); + break; + } + /* Avoid adding the same vbo more than once when the batch is used by multiple + * instances. */ + if (!GPU_batch_vertbuf_has(batch, vbo)) { + /* Currently, the code assumes that all objects that share the same mesh in the + * current frame also share the same mesh on other frames. */ GPU_batch_vertbuf_add_ex(batch, vbo, false); } } } - else { - GPUVertBuf *vbo = mb_geom->vbo[mb_step]; - if (vbo) { - /* Use the vbo to perform the copy on the GPU. */ - GPU_vertbuf_use(vbo); - /* Perform a copy to avoid losing it after RE_engine_frame_set(). */ - mb_geom->vbo[mb_step] = vbo = GPU_vertbuf_duplicate(vbo); + } + else { + GPUVertBuf *vbo = mb_geom->vbo[mb_step]; + if (vbo) { + /* Use the vbo to perform the copy on the GPU. */ + GPU_vertbuf_use(vbo); + /* Perform a copy to avoid losing it after RE_engine_frame_set(). */ + GPUVertBuf **vbo_cache_ptr; + if (!BLI_ghash_ensure_p(effects->motion_blur.position_vbo_cache[mb_step], + vbo, + (void ***)&vbo_cache_ptr)) { + /* Duplicate the vbo, otherwise it would be lost when evaluating another frame. */ + GPUVertBuf *duplicated_vbo = GPU_vertbuf_duplicate(vbo); + *vbo_cache_ptr = duplicated_vbo; /* Find and replace "pos" attrib name. */ - GPUVertFormat *format = (GPUVertFormat *)GPU_vertbuf_get_format(vbo); + GPUVertFormat *format = (GPUVertFormat *)GPU_vertbuf_get_format(duplicated_vbo); int attrib_id = GPU_vertformat_attr_id_get(format, "pos"); GPU_vertformat_attr_rename(format, attrib_id, (mb_step == MB_PREV) ? "prv" : "nxt"); } - else { - /* This might happen if the object visibility has been animated. */ - mb_geom->use_deform = false; - } + mb_geom->vbo[mb_step] = vbo = *vbo_cache_ptr; } - break; - - default: - BLI_assert(0); - break; + else { + /* This might happen if the object visibility has been animated. */ + mb_geom->use_deform = false; + } + } } } } @@ -518,54 +514,62 @@ void EEVEE_motion_blur_swap_data(EEVEE_Data *vedata) /* Camera Data. */ effects->motion_blur.camera[MB_PREV] = effects->motion_blur.camera[MB_NEXT]; - /* Object Data. */ - for (BLI_ghashIterator_init(&ghi, effects->motion_blur.object); - BLI_ghashIterator_done(&ghi) == false; - BLI_ghashIterator_step(&ghi)) { - EEVEE_ObjectMotionData *mb_data = BLI_ghashIterator_getValue(&ghi); - - copy_m4_m4(mb_data->obmat[MB_PREV], mb_data->obmat[MB_NEXT]); + /* Swap #position_vbo_cache pointers. */ + if (effects->motion_blur.position_vbo_cache[MB_PREV]) { + BLI_ghash_free(effects->motion_blur.position_vbo_cache[MB_PREV], + NULL, + (GHashValFreeFP)GPU_vertbuf_discard); + } + effects->motion_blur.position_vbo_cache[MB_PREV] = + effects->motion_blur.position_vbo_cache[MB_NEXT]; + effects->motion_blur.position_vbo_cache[MB_NEXT] = NULL; + + /* Swap #hair_motion_step_cache pointers. */ + if (effects->motion_blur.hair_motion_step_cache[MB_PREV]) { + BLI_ghash_free(effects->motion_blur.hair_motion_step_cache[MB_PREV], + NULL, + (GHashValFreeFP)EEVEE_motion_hair_step_free); } + effects->motion_blur.hair_motion_step_cache[MB_PREV] = + effects->motion_blur.hair_motion_step_cache[MB_NEXT]; + effects->motion_blur.hair_motion_step_cache[MB_NEXT] = NULL; - /* Deformation Data. */ - for (BLI_ghashIterator_init(&ghi, effects->motion_blur.geom); - BLI_ghashIterator_done(&ghi) == false; + /* Rename attributes in #position_vbo_cache. */ + for (BLI_ghashIterator_init(&ghi, effects->motion_blur.position_vbo_cache[MB_PREV]); + !BLI_ghashIterator_done(&ghi); BLI_ghashIterator_step(&ghi)) { - EEVEE_GeometryMotionData *mb_geom = BLI_ghashIterator_getValue(&ghi); - EEVEE_HairMotionData *mb_hair = (EEVEE_HairMotionData *)mb_geom; + GPUVertBuf *vbo = BLI_ghashIterator_getValue(&ghi); + GPUVertFormat *format = (GPUVertFormat *)GPU_vertbuf_get_format(vbo); + int attrib_id = GPU_vertformat_attr_id_get(format, "nxt"); + GPU_vertformat_attr_rename(format, attrib_id, "prv"); + } - switch (mb_geom->type) { - case EEVEE_MOTION_DATA_HAIR: - for (int i = 0; i < mb_hair->psys_len; i++) { - GPU_VERTBUF_DISCARD_SAFE(mb_hair->psys[i].hair_pos[MB_PREV]); - DRW_TEXTURE_FREE_SAFE(mb_hair->psys[i].hair_pos_tx[MB_PREV]); - mb_hair->psys[i].hair_pos[MB_PREV] = mb_hair->psys[i].hair_pos[MB_NEXT]; - mb_hair->psys[i].hair_pos_tx[MB_PREV] = mb_hair->psys[i].hair_pos_tx[MB_NEXT]; - mb_hair->psys[i].hair_pos[MB_NEXT] = NULL; - mb_hair->psys[i].hair_pos_tx[MB_NEXT] = NULL; - } - break; + /* Object Data. */ + for (BLI_ghashIterator_init(&ghi, effects->motion_blur.object); !BLI_ghashIterator_done(&ghi); + BLI_ghashIterator_step(&ghi)) { + EEVEE_ObjectMotionData *mb_data = BLI_ghashIterator_getValue(&ghi); + EEVEE_GeometryMotionData *mb_geom = mb_data->geometry_data; + EEVEE_HairMotionData *mb_hair = mb_data->hair_data; - case EEVEE_MOTION_DATA_MESH: - if (mb_geom->batch != NULL) { - motion_blur_remove_vbo_reference_from_batch( - mb_geom->batch, mb_geom->vbo[MB_PREV], mb_geom->vbo[MB_NEXT]); - } - GPU_VERTBUF_DISCARD_SAFE(mb_geom->vbo[MB_PREV]); - mb_geom->vbo[MB_PREV] = mb_geom->vbo[MB_NEXT]; - mb_geom->vbo[MB_NEXT] = NULL; - - if (mb_geom->vbo[MB_PREV]) { - GPUVertBuf *vbo = mb_geom->vbo[MB_PREV]; - GPUVertFormat *format = (GPUVertFormat *)GPU_vertbuf_get_format(vbo); - int attrib_id = GPU_vertformat_attr_id_get(format, "nxt"); - GPU_vertformat_attr_rename(format, attrib_id, "prv"); - } - break; + copy_m4_m4(mb_data->obmat[MB_PREV], mb_data->obmat[MB_NEXT]); - default: - BLI_assert(0); - break; + if (mb_hair != NULL) { + for (int i = 0; i < mb_hair->psys_len; i++) { + mb_hair->psys[i].step_data[MB_PREV].hair_pos = + mb_hair->psys[i].step_data[MB_NEXT].hair_pos; + mb_hair->psys[i].step_data[MB_PREV].hair_pos_tx = + mb_hair->psys[i].step_data[MB_NEXT].hair_pos_tx; + mb_hair->psys[i].step_data[MB_NEXT].hair_pos = NULL; + mb_hair->psys[i].step_data[MB_NEXT].hair_pos_tx = NULL; + } + } + if (mb_geom != NULL) { + if (mb_geom->batch != NULL) { + motion_blur_remove_vbo_reference_from_batch( + mb_geom->batch, mb_geom->vbo[MB_PREV], mb_geom->vbo[MB_NEXT]); + } + mb_geom->vbo[MB_PREV] = mb_geom->vbo[MB_NEXT]; + mb_geom->vbo[MB_NEXT] = NULL; } } } diff --git a/source/blender/draw/engines/eevee/eevee_private.h b/source/blender/draw/engines/eevee/eevee_private.h index 766e721b1b8..336b66af393 100644 --- a/source/blender/draw/engines/eevee/eevee_private.h +++ b/source/blender/draw/engines/eevee/eevee_private.h @@ -633,8 +633,23 @@ enum { #define MB_CURR 2 typedef struct EEVEE_MotionBlurData { + /** + * Maps #EEVEE_ObjectKey to #EEVEE_ObjectMotionData. + */ struct GHash *object; - struct GHash *geom; + /** + * Maps original #GPUVertBuf to duplicated #GPUVertBuf. + * There are two maps for #MB_PREV and #MB_NEXT. + * Only the values are owned. + */ + struct GHash *position_vbo_cache[2]; + /** + * Maps original #GPUVertBuf to #EEVEE_HairMotionStepData. + * There are two maps for #MB_PREV and #MB_NEXT. + * Only the values are owned. + */ + struct GHash *hair_motion_step_cache[2]; + struct { float viewmat[4][4]; float persmat[4][4]; @@ -652,15 +667,16 @@ typedef struct EEVEE_ObjectKey { int id[8]; /* MAX_DUPLI_RECUR */ } EEVEE_ObjectKey; -typedef struct EEVEE_ObjectMotionData { - float obmat[3][4][4]; -} EEVEE_ObjectMotionData; - typedef enum eEEVEEMotionData { EEVEE_MOTION_DATA_MESH = 0, EEVEE_MOTION_DATA_HAIR, } eEEVEEMotionData; +typedef struct EEVEE_HairMotionStepData { + struct GPUVertBuf *hair_pos; + struct GPUTexture *hair_pos_tx; +} EEVEE_HairMotionStepData; + typedef struct EEVEE_HairMotionData { /** Needs to be first to ensure casting. */ eEEVEEMotionData type; @@ -668,8 +684,8 @@ typedef struct EEVEE_HairMotionData { /** Allocator will alloc enough slot for all particle systems. Or 1 if it's a hair object. */ int psys_len; struct { - struct GPUVertBuf *hair_pos[2]; /* Position buffer for time = t +/- step. */ - struct GPUTexture *hair_pos_tx[2]; /* Buffer Texture of the corresponding VBO. */ + /* The vbos and textures are not owned. */ + EEVEE_HairMotionStepData step_data[2]; /* Data for time = t +/- step. */ } psys[0]; } EEVEE_HairMotionData; @@ -679,10 +695,18 @@ typedef struct EEVEE_GeometryMotionData { /** To disable deform mb if vertcount mismatch. */ int use_deform; + /* The batch and vbos are not owned. */ struct GPUBatch *batch; /* Batch for time = t. */ struct GPUVertBuf *vbo[2]; /* VBO for time = t +/- step. */ } EEVEE_GeometryMotionData; +typedef struct EEVEE_ObjectMotionData { + float obmat[3][4][4]; + + EEVEE_GeometryMotionData *geometry_data; + EEVEE_HairMotionData *hair_data; +} EEVEE_ObjectMotionData; + /* ************ EFFECTS DATA ************* */ typedef enum EEVEE_EffectsFlag { @@ -1077,17 +1101,15 @@ typedef struct EEVEE_PrivateData { void EEVEE_motion_blur_data_init(EEVEE_MotionBlurData *mb); void EEVEE_motion_blur_data_free(EEVEE_MotionBlurData *mb); void EEVEE_view_layer_data_free(void *storage); +void EEVEE_motion_hair_step_free(EEVEE_HairMotionStepData *step_data); EEVEE_ViewLayerData *EEVEE_view_layer_data_get(void); EEVEE_ViewLayerData *EEVEE_view_layer_data_ensure_ex(struct ViewLayer *view_layer); EEVEE_ViewLayerData *EEVEE_view_layer_data_ensure(void); EEVEE_ObjectEngineData *EEVEE_object_data_get(Object *ob); EEVEE_ObjectEngineData *EEVEE_object_data_ensure(Object *ob); -EEVEE_ObjectMotionData *EEVEE_motion_blur_object_data_get(EEVEE_MotionBlurData *mb, - Object *ob, - bool hair); -EEVEE_GeometryMotionData *EEVEE_motion_blur_geometry_data_get(EEVEE_MotionBlurData *mb, - Object *ob); -EEVEE_HairMotionData *EEVEE_motion_blur_hair_data_get(EEVEE_MotionBlurData *mb, Object *ob); +EEVEE_ObjectMotionData *EEVEE_motion_blur_object_data_get(EEVEE_MotionBlurData *mb, Object *ob); +EEVEE_GeometryMotionData *EEVEE_motion_blur_geometry_data_get(EEVEE_ObjectMotionData *mb_data); +EEVEE_HairMotionData *EEVEE_motion_blur_hair_data_get(EEVEE_ObjectMotionData *mb_data, Object *ob); EEVEE_LightProbeEngineData *EEVEE_lightprobe_data_get(Object *ob); EEVEE_LightProbeEngineData *EEVEE_lightprobe_data_ensure(Object *ob); EEVEE_LightEngineData *EEVEE_light_data_get(Object *ob); diff --git a/source/blender/gpu/GPU_batch.h b/source/blender/gpu/GPU_batch.h index b193b45d65c..4a0411fd9da 100644 --- a/source/blender/gpu/GPU_batch.h +++ b/source/blender/gpu/GPU_batch.h @@ -135,6 +135,7 @@ int GPU_batch_instbuf_add_ex(GPUBatch *, GPUVertBuf *, bool own_vbo); * Returns the index of verts in the batch. */ int GPU_batch_vertbuf_add_ex(GPUBatch *, GPUVertBuf *, bool own_vbo); +bool GPU_batch_vertbuf_has(GPUBatch *, GPUVertBuf *); #define GPU_batch_vertbuf_add(batch, verts) GPU_batch_vertbuf_add_ex(batch, verts, false) diff --git a/source/blender/gpu/intern/gpu_batch.cc b/source/blender/gpu/intern/gpu_batch.cc index 2874dea775f..7ad2786ab22 100644 --- a/source/blender/gpu/intern/gpu_batch.cc +++ b/source/blender/gpu/intern/gpu_batch.cc @@ -207,6 +207,16 @@ int GPU_batch_vertbuf_add_ex(GPUBatch *batch, GPUVertBuf *verts, bool own_vbo) return -1; } +bool GPU_batch_vertbuf_has(GPUBatch *batch, GPUVertBuf *verts) +{ + for (uint v = 0; v < GPU_BATCH_VBO_MAX_LEN; v++) { + if (batch->verts[v] == verts) { + return true; + } + } + return false; +} + /** \} */ /* -------------------------------------------------------------------- */ |