diff options
-rw-r--r-- | source/blender/draw/DRW_engine.h | 3 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache.c | 21 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl.h | 5 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_cache_impl_mesh.c | 26 | ||||
-rw-r--r-- | source/blender/draw/intern/draw_manager.c | 42 | ||||
-rw-r--r-- | source/blender/editors/space_view3d/view3d_draw.c | 1 |
6 files changed, 95 insertions, 3 deletions
diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h index 161e28db2d3..8ff4fbbe5a5 100644 --- a/source/blender/draw/DRW_engine.h +++ b/source/blender/draw/DRW_engine.h @@ -152,6 +152,9 @@ void DRW_opengl_context_destroy(void); void DRW_opengl_context_enable(void); void DRW_opengl_context_disable(void); +/* For garbage collection */ +void DRW_cache_free_old_batches(struct Main *bmain); + /* Never use this. Only for closing blender. */ void DRW_opengl_context_enable_ex(bool restore); void DRW_opengl_context_disable_ex(bool restore); diff --git a/source/blender/draw/intern/draw_cache.c b/source/blender/draw/intern/draw_cache.c index 6b6a79bfb60..8a13d8be622 100644 --- a/source/blender/draw/intern/draw_cache.c +++ b/source/blender/draw/intern/draw_cache.c @@ -4031,4 +4031,25 @@ void drw_batch_cache_generate_requested(Object *ob) } } +void DRW_batch_cache_free_old(Object *ob, int ctime) +{ + struct Mesh *mesh_eval = ob->runtime.mesh_eval; + + switch (ob->type) { + case OB_MESH: + DRW_mesh_batch_cache_free_old((Mesh *)ob->data, ctime); + break; + case OB_CURVE: + case OB_FONT: + case OB_SURF: + if (mesh_eval) { + DRW_mesh_batch_cache_free_old(mesh_eval, ctime); + } + break; + /* TODO all cases */ + default: + break; + } +} + /** \} */ diff --git a/source/blender/draw/intern/draw_cache_impl.h b/source/blender/draw/intern/draw_cache_impl.h index 94d8a82f2e4..e4ce3ed9d49 100644 --- a/source/blender/draw/intern/draw_cache_impl.h +++ b/source/blender/draw/intern/draw_cache_impl.h @@ -61,6 +61,11 @@ void DRW_particle_batch_cache_free(struct ParticleSystem *psys); void DRW_gpencil_batch_cache_dirty_tag(struct bGPdata *gpd); void DRW_gpencil_batch_cache_free(struct bGPdata *gpd); +/* Garbage collection */ +void DRW_batch_cache_free_old(struct Object *ob, int ctime); + +void DRW_mesh_batch_cache_free_old(struct Mesh *me, int ctime); + /* Curve */ void DRW_curve_batch_cache_create_requested(struct Object *ob); diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c index 6b43fbed49f..41de51fde96 100644 --- a/source/blender/draw/intern/draw_cache_impl_mesh.c +++ b/source/blender/draw/intern/draw_cache_impl_mesh.c @@ -364,6 +364,11 @@ BLI_INLINE bool mesh_cd_layers_type_overlap(DRW_MeshCDMask a, DRW_MeshCDMask b) return (*((uint32_t *)&a) & *((uint32_t *)&b)) == *((uint32_t *)&b); } +BLI_INLINE bool mesh_cd_layers_type_equal(DRW_MeshCDMask a, DRW_MeshCDMask b) +{ + return *((uint32_t *)&a) == *((uint32_t *)&b); +} + BLI_INLINE void mesh_cd_layers_type_merge(DRW_MeshCDMask *a, DRW_MeshCDMask b) { atomic_fetch_and_or_uint32((uint32_t *)a, *(uint32_t *)&b); @@ -1997,7 +2002,7 @@ typedef struct MeshBatchCache { struct DRW_MeshWeightState weight_state; - DRW_MeshCDMask cd_used, cd_needed; + DRW_MeshCDMask cd_used, cd_needed, cd_used_over_time; /* XXX, only keep for as long as sculpt mode uses shaded drawing. */ bool is_sculpt_points_tag; @@ -2121,6 +2126,8 @@ static void mesh_batch_cache_discard_shaded_tri(MeshBatchCache *cache) MEM_SAFE_FREE(cache->auto_layer_names); MEM_SAFE_FREE(cache->auto_layer_is_srgb); + mesh_cd_layers_type_clear(&cache->cd_used); + cache->mat_len = 0; } @@ -4717,6 +4724,22 @@ static void mesh_create_uvedit_buffers(MeshRenderData *rdata, /** \name Grouped batch generation * \{ */ +/* Thread safety need to be assured by caller. Don't call this during drawing. + * Note: For now this only free the shading batches / vbo if any cd layers is + * not needed anymore. */ +void DRW_mesh_batch_cache_free_old(Mesh *me, int UNUSED(ctime)) +{ + MeshBatchCache *cache = me->runtime.batch_cache; + + if (cache == NULL) + return; + + if (mesh_cd_layers_type_equal(cache->cd_used_over_time, cache->cd_used) == false) { + mesh_batch_cache_discard_shaded_tri(cache); + } + mesh_cd_layers_type_clear(&cache->cd_used_over_time); +} + /* Can be called for any surface type. Mesh *me is the final mesh. */ void DRW_mesh_batch_cache_create_requested( Object *ob, Mesh *me, const ToolSettings *ts, const bool is_paint_mode, const bool use_hide) @@ -4769,6 +4792,7 @@ void DRW_mesh_batch_cache_create_requested( mesh_cd_layers_type_merge(&cache->cd_used, cache->cd_needed); } + mesh_cd_layers_type_merge(&cache->cd_used_over_time, cache->cd_needed); mesh_cd_layers_type_clear(&cache->cd_needed); /* Discard UV batches if sync_selection changes */ diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c index 9e078fd2774..b3546092667 100644 --- a/source/blender/draw/intern/draw_manager.c +++ b/source/blender/draw/intern/draw_manager.c @@ -35,6 +35,7 @@ #include "BKE_global.h" #include "BKE_gpencil.h" #include "BKE_lattice.h" +#include "BKE_main.h" #include "BKE_mball.h" #include "BKE_mesh.h" #include "BKE_object.h" @@ -404,7 +405,7 @@ void DRW_multisamples_resolve(GPUTexture *src_depth, GPUTexture *src_color, bool builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_16_DEPTH_TEST; break; default: - BLI_assert("Mulisample count unsupported by blit shader."); + BLI_assert(!"Mulisample count unsupported by blit shader."); builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_2_DEPTH_TEST; break; } @@ -424,7 +425,7 @@ void DRW_multisamples_resolve(GPUTexture *src_depth, GPUTexture *src_color, bool builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_16; break; default: - BLI_assert("Mulisample count unsupported by blit shader."); + BLI_assert(!"Mulisample count unsupported by blit shader."); builtin = GPU_SHADER_2D_IMAGE_MULTISAMPLE_2; break; } @@ -969,6 +970,43 @@ static void drw_drawdata_unlink_dupli(ID *id) /** \name Rendering (DRW_engines) * \{ */ +#define DRW_BATCH_COLLECTION_RATE 60 /* in sec */ + +void DRW_cache_free_old_batches(Main *bmain) +{ + Scene *scene; + ViewLayer *view_layer; + static int lasttime = 0; + int ctime = (int)PIL_check_seconds_timer(); + + if (ctime % DRW_BATCH_COLLECTION_RATE || ctime == lasttime) + return; + + lasttime = ctime; + + for (scene = bmain->scenes.first; scene; scene = scene->id.next) { + for (view_layer = scene->view_layers.first; view_layer; view_layer = view_layer->next) { + Depsgraph *depsgraph = BKE_scene_get_depsgraph(scene, view_layer, false); + + /* TODO(fclem): This is not optimal since it iter over all dupli instances. + * In this case only the source object should be tagged. */ + int iter_flags = DEG_ITER_OBJECT_FLAG_LINKED_DIRECTLY | DEG_ITER_OBJECT_FLAG_LINKED_VIA_SET | + DEG_ITER_OBJECT_FLAG_VISIBLE | DEG_ITER_OBJECT_FLAG_DUPLI; + + DEG_OBJECT_ITER_BEGIN (depsgraph, ob, iter_flags) { + DRW_batch_cache_free_old(ob, ctime); + } + DEG_OBJECT_ITER_END; + } + } +} + +/** \} */ + +/* -------------------------------------------------------------------- */ +/** \name Rendering (DRW_engines) + * \{ */ + static void drw_engines_init(void) { for (LinkData *link = DST.enabled_engines.first; link; link = link->next) { diff --git a/source/blender/editors/space_view3d/view3d_draw.c b/source/blender/editors/space_view3d/view3d_draw.c index 2c831c0877c..a298e668f44 100644 --- a/source/blender/editors/space_view3d/view3d_draw.c +++ b/source/blender/editors/space_view3d/view3d_draw.c @@ -1450,6 +1450,7 @@ void view3d_main_region_draw(const bContext *C, ARegion *ar) view3d_draw_view(C, ar); + DRW_cache_free_old_batches(bmain); GPU_free_images_old(bmain); GPU_pass_cache_garbage_collect(); |