Changeset View
Changeset View
Standalone View
Standalone View
source/blender/draw/intern/draw_cache_impl_mesh.c
| Show First 20 Lines • Show All 1,116 Lines • ▼ Show 20 Lines | void DRW_mesh_batch_cache_free_old(Mesh *me, int ctime) | ||||
| if (ctime - cache->lastmatch > U.vbotimeout) { | if (ctime - cache->lastmatch > U.vbotimeout) { | ||||
| mesh_batch_cache_discard_shaded_tri(cache); | mesh_batch_cache_discard_shaded_tri(cache); | ||||
| } | } | ||||
| mesh_cd_layers_type_clear(&cache->cd_used_over_time); | mesh_cd_layers_type_clear(&cache->cd_used_over_time); | ||||
| } | } | ||||
| #ifdef DEBUG | |||||
| /* Sanity check function to test if all requested batches are available. */ | |||||
| static void drw_mesh_batch_cache_check_available(struct TaskGraph *task_graph, Mesh *me) | |||||
| { | |||||
| # if 0 | |||||
| MeshBatchCache *cache = mesh_batch_cache_get(me); | |||||
| /* Make sure all requested batches have been setup. */ | |||||
| /* Note: The next line creates a different scheduling than during release builds what can lead to | |||||
| * some issues (See T77867 where we needed to disable this function in order to debug what was | |||||
| * happening in release builds). */ | |||||
| BLI_task_graph_work_and_wait(task_graph); | |||||
| for (int i = 0; i < sizeof(cache->batch) / sizeof(void *); i++) { | |||||
| BLI_assert(!DRW_batch_requested(((GPUBatch **)&cache->batch)[i], 0)); | |||||
| } | |||||
| for (int i = 0; i < sizeof(cache->final.vbo) / sizeof(void *); i++) { | |||||
| BLI_assert(!DRW_vbo_requested(((GPUVertBuf **)&cache->final.vbo)[i])); | |||||
| } | |||||
| for (int i = 0; i < sizeof(cache->final.ibo) / sizeof(void *); i++) { | |||||
| BLI_assert(!DRW_ibo_requested(((GPUIndexBuf **)&cache->final.ibo)[i])); | |||||
| } | |||||
| for (int i = 0; i < sizeof(cache->cage.vbo) / sizeof(void *); i++) { | |||||
| BLI_assert(!DRW_vbo_requested(((GPUVertBuf **)&cache->cage.vbo)[i])); | |||||
| } | |||||
| for (int i = 0; i < sizeof(cache->cage.ibo) / sizeof(void *); i++) { | |||||
| BLI_assert(!DRW_ibo_requested(((GPUIndexBuf **)&cache->cage.ibo)[i])); | |||||
| } | |||||
| for (int i = 0; i < sizeof(cache->uv_cage.vbo) / sizeof(void *); i++) { | |||||
| BLI_assert(!DRW_vbo_requested(((GPUVertBuf **)&cache->uv_cage.vbo)[i])); | |||||
| } | |||||
| for (int i = 0; i < sizeof(cache->uv_cage.ibo) / sizeof(void *); i++) { | |||||
| BLI_assert(!DRW_ibo_requested(((GPUIndexBuf **)&cache->uv_cage.ibo)[i])); | |||||
| } | |||||
| # endif | |||||
| } | |||||
| #endif | |||||
| /* Can be called for any surface type. Mesh *me is the final mesh. */ | /* Can be called for any surface type. Mesh *me is the final mesh. */ | ||||
| void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, | void DRW_mesh_batch_cache_prepare_requested(struct TaskGraph *task_graph, | ||||
| Object *ob, | Object *ob, | ||||
| Mesh *me, | Mesh *me, | ||||
| const Scene *scene, | const Scene *scene, | ||||
| const bool is_paint_mode, | const bool is_paint_mode, | ||||
| const bool use_hide) | const bool UNUSED(use_hide)) | ||||
| { | { | ||||
| BLI_assert(task_graph); | BLI_assert(task_graph); | ||||
| GPUIndexBuf **saved_elem_ranges = NULL; | GPUIndexBuf **saved_elem_ranges = NULL; | ||||
| const ToolSettings *ts = NULL; | const ToolSettings *ts = NULL; | ||||
| if (scene) { | if (scene) { | ||||
| ts = scene->toolsettings; | ts = scene->toolsettings; | ||||
| } | } | ||||
| MeshBatchCache *cache = mesh_batch_cache_get(me); | MeshBatchCache *cache = mesh_batch_cache_get(me); | ||||
| bool cd_uv_update = false; | bool cd_uv_update = false; | ||||
| /* Early out */ | /* Early out */ | ||||
| if (cache->batch_requested == 0) { | if (cache->batch_requested == 0) { | ||||
| #ifdef DEBUG | |||||
| goto check; | |||||
| #else | |||||
| return; | return; | ||||
| #endif | |||||
| } | } | ||||
| /* Sanity check. */ | /* Sanity check. */ | ||||
| if ((me->edit_mesh != NULL) && (ob->mode & OB_MODE_EDIT)) { | if ((me->edit_mesh != NULL) && (ob->mode & OB_MODE_EDIT)) { | ||||
| BLI_assert(me->edit_mesh->mesh_eval_final != NULL); | BLI_assert(me->edit_mesh->mesh_eval_final != NULL); | ||||
| } | } | ||||
| const bool is_editmode = (me->edit_mesh != NULL) && DRW_object_is_in_edit_mode(ob); | const bool is_editmode = (me->edit_mesh != NULL) && DRW_object_is_in_edit_mode(ob); | ||||
| Show All 11 Lines | if ((cache->batch.surface_weights != NULL) && (ts != NULL)) { | ||||
| drw_mesh_weight_state_copy(&cache->weight_state, &wstate); | drw_mesh_weight_state_copy(&cache->weight_state, &wstate); | ||||
| drw_mesh_weight_state_clear(&wstate); | drw_mesh_weight_state_clear(&wstate); | ||||
| } | } | ||||
| } | } | ||||
| /* HACK: if MBC_SURF_PER_MAT is requested and ibo.tris is already available, it won't have it's | /* HACK: if MBC_SURF_PER_MAT is requested and ibo.tris is already available, it won't have it's | ||||
| * index ranges initialized. So discard ibo.tris in order to recreate it. | * index ranges initialized. So discard ibo.tris in order to recreate it. | ||||
| * This needs to happen before saved_elem_ranges is populated. */ | * This needs to happen before saved_elem_ranges is populated. */ | ||||
| if ((batch_requested & MBC_SURF_PER_MAT) != 0 && (cache->batch_ready & MBC_SURF_PER_MAT) == 0) { | if ((batch_requested & MBC_SURF_PER_MAT) != 0 && | ||||
| ((cache->batch_prepared | cache->batch_ready) & MBC_SURF_PER_MAT) == 0) { | |||||
| FOREACH_MESH_BUFFER_CACHE (cache, mbuffercache) { | FOREACH_MESH_BUFFER_CACHE (cache, mbuffercache) { | ||||
| GPU_INDEXBUF_DISCARD_SAFE(mbuffercache->ibo.tris); | GPU_INDEXBUF_DISCARD_SAFE(mbuffercache->ibo.tris); | ||||
| } | } | ||||
| /* Clear all batches that reference ibo.tris. */ | /* Clear all batches that reference ibo.tris. */ | ||||
| GPU_BATCH_CLEAR_SAFE(cache->batch.surface); | GPU_BATCH_CLEAR_SAFE(cache->batch.surface); | ||||
| GPU_BATCH_CLEAR_SAFE(cache->batch.surface_weights); | GPU_BATCH_CLEAR_SAFE(cache->batch.surface_weights); | ||||
| GPU_BATCH_CLEAR_SAFE(cache->batch.edit_mesh_analysis); | GPU_BATCH_CLEAR_SAFE(cache->batch.edit_mesh_analysis); | ||||
| GPU_BATCH_CLEAR_SAFE(cache->batch.edit_triangles); | GPU_BATCH_CLEAR_SAFE(cache->batch.edit_triangles); | ||||
| GPU_BATCH_CLEAR_SAFE(cache->batch.edit_lnor); | GPU_BATCH_CLEAR_SAFE(cache->batch.edit_lnor); | ||||
| GPU_BATCH_CLEAR_SAFE(cache->batch.edit_selection_faces); | GPU_BATCH_CLEAR_SAFE(cache->batch.edit_selection_faces); | ||||
| for (int i = 0; i < cache->mat_len; i++) { | for (int i = 0; i < cache->mat_len; i++) { | ||||
| GPU_BATCH_CLEAR_SAFE(cache->surface_per_mat[i]); | GPU_BATCH_CLEAR_SAFE(cache->surface_per_mat[i]); | ||||
| } | } | ||||
| cache->batch_ready &= ~(MBC_SURFACE | MBC_SURFACE_WEIGHTS | MBC_EDIT_MESH_ANALYSIS | | cache->batch_ready &= ~(MBC_SURFACE | MBC_SURFACE_WEIGHTS | MBC_EDIT_MESH_ANALYSIS | | ||||
| MBC_EDIT_TRIANGLES | MBC_EDIT_LNOR | MBC_EDIT_SELECTION_FACES); | MBC_EDIT_TRIANGLES | MBC_EDIT_LNOR | MBC_EDIT_SELECTION_FACES); | ||||
| /* Note: We don't reset `cache->batch_prepared` as it will still be needed. */ | |||||
| } | } | ||||
| if (batch_requested & | if (batch_requested & | ||||
| (MBC_SURFACE | MBC_SURF_PER_MAT | MBC_WIRE_LOOPS_UVS | MBC_EDITUV_FACES_STRETCH_AREA | | (MBC_SURFACE | MBC_SURF_PER_MAT | MBC_WIRE_LOOPS_UVS | MBC_EDITUV_FACES_STRETCH_AREA | | ||||
| MBC_EDITUV_FACES_STRETCH_ANGLE | MBC_EDITUV_FACES | MBC_EDITUV_EDGES | MBC_EDITUV_VERTS)) { | MBC_EDITUV_FACES_STRETCH_ANGLE | MBC_EDITUV_FACES | MBC_EDITUV_EDGES | MBC_EDITUV_VERTS)) { | ||||
| /* Modifiers will only generate an orco layer if the mesh is deformed. */ | /* Modifiers will only generate an orco layer if the mesh is deformed. */ | ||||
| if (cache->cd_needed.orco != 0) { | if (cache->cd_needed.orco != 0) { | ||||
| /* Orco is always extracted from final mesh. */ | /* Orco is always extracted from final mesh. */ | ||||
| ▲ Show 20 Lines • Show All 70 Lines • ▼ Show 20 Lines | if (cd_uv_update || (cache->is_uvsyncsel != is_uvsyncsel)) { | ||||
| GPU_BATCH_CLEAR_SAFE(cache->batch.wire_loops_uvs); | GPU_BATCH_CLEAR_SAFE(cache->batch.wire_loops_uvs); | ||||
| GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces_stretch_area); | GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces_stretch_area); | ||||
| GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces_stretch_angle); | GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces_stretch_angle); | ||||
| GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces); | GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_faces); | ||||
| GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_edges); | GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_edges); | ||||
| GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_verts); | GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_verts); | ||||
| GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_fdots); | GPU_BATCH_CLEAR_SAFE(cache->batch.edituv_fdots); | ||||
| cache->batch_ready &= ~MBC_EDITUV; | cache->batch_ready &= ~MBC_EDITUV; | ||||
| /* Note: We don't reset `cache->batch_prepared` as they will still be needed. */ | |||||
| } | } | ||||
| } | } | ||||
| /* Second chance to early out */ | /* Second chance to early out */ | ||||
| if ((batch_requested & ~cache->batch_ready) == 0) { | if ((batch_requested & ~(cache->batch_ready | cache->batch_prepared)) == 0) { | ||||
| #ifdef DEBUG | |||||
| goto check; | |||||
| #else | |||||
| return; | return; | ||||
| #endif | |||||
| } | } | ||||
| cache->batch_prepared |= batch_requested; | |||||
| cache->batch_ready |= batch_requested; | |||||
| const bool do_cage = (is_editmode && | const bool do_cage = (is_editmode && | ||||
| (me->edit_mesh->mesh_eval_final != me->edit_mesh->mesh_eval_cage)); | (me->edit_mesh->mesh_eval_final != me->edit_mesh->mesh_eval_cage)); | ||||
| const bool do_uvcage = is_editmode && !me->edit_mesh->mesh_eval_final->runtime.is_original; | const bool do_uvcage = is_editmode && !me->edit_mesh->mesh_eval_final->runtime.is_original; | ||||
| MeshBufferCache *mbufcache = &cache->final; | MeshBufferCache *mbufcache = &cache->final; | ||||
| ▲ Show 20 Lines • Show All 178 Lines • ▼ Show 20 Lines | if (DRW_batch_requested(cache->batch.edituv_verts, GPU_PRIM_POINTS)) { | ||||
| DRW_vbo_request(cache->batch.edituv_verts, &mbufcache->vbo.uv); | DRW_vbo_request(cache->batch.edituv_verts, &mbufcache->vbo.uv); | ||||
| DRW_vbo_request(cache->batch.edituv_verts, &mbufcache->vbo.edituv_data); | DRW_vbo_request(cache->batch.edituv_verts, &mbufcache->vbo.edituv_data); | ||||
| } | } | ||||
| if (DRW_batch_requested(cache->batch.edituv_fdots, GPU_PRIM_POINTS)) { | if (DRW_batch_requested(cache->batch.edituv_fdots, GPU_PRIM_POINTS)) { | ||||
| DRW_ibo_request(cache->batch.edituv_fdots, &mbufcache->ibo.edituv_fdots); | DRW_ibo_request(cache->batch.edituv_fdots, &mbufcache->ibo.edituv_fdots); | ||||
| DRW_vbo_request(cache->batch.edituv_fdots, &mbufcache->vbo.fdots_uv); | DRW_vbo_request(cache->batch.edituv_fdots, &mbufcache->vbo.fdots_uv); | ||||
| DRW_vbo_request(cache->batch.edituv_fdots, &mbufcache->vbo.fdots_edituv_data); | DRW_vbo_request(cache->batch.edituv_fdots, &mbufcache->vbo.fdots_edituv_data); | ||||
| } | } | ||||
| } | |||||
| void DRW_mesh_batch_cache_create_requested(struct TaskGraph *task_graph, | |||||
| Object *ob, | |||||
| Mesh *me, | |||||
| const Scene *scene, | |||||
| const bool is_paint_mode, | |||||
| const bool use_hide) | |||||
| { | |||||
| MeshBatchCache *cache = mesh_batch_cache_get(me); | |||||
| const ToolSettings *ts = NULL; | |||||
| if (scene) { | |||||
| ts = scene->toolsettings; | |||||
| } | |||||
| const bool is_editmode = (me->edit_mesh != NULL) && DRW_object_is_in_edit_mode(ob); | |||||
| const bool do_cage = (is_editmode && | |||||
| (me->edit_mesh->mesh_eval_final != me->edit_mesh->mesh_eval_cage)); | |||||
| const bool do_uvcage = is_editmode && !me->edit_mesh->mesh_eval_final->runtime.is_original; | |||||
| /* Meh loose Scene const correctness here. */ | /* Meh loose Scene const correctness here. */ | ||||
| const bool use_subsurf_fdots = scene ? BKE_modifiers_uses_subsurf_facedots((Scene *)scene, ob) : | const bool use_subsurf_fdots = scene ? BKE_modifiers_uses_subsurf_facedots((Scene *)scene, ob) : | ||||
| false; | false; | ||||
| /* Check if there is still work to be done. Linked meshes could already be scheduled | |||||
| * in the same loop. */ | |||||
| if ((cache->batch_prepared & ~cache->batch_ready) == 0) { | |||||
| #ifdef DEBUG | |||||
| drw_mesh_batch_cache_check_available(task_graph, me); | |||||
| #endif | |||||
| return; | |||||
| } | |||||
| cache->batch_ready |= cache->batch_prepared; | |||||
| cache->batch_prepared = 0; | |||||
| if (do_uvcage) { | if (do_uvcage) { | ||||
| mesh_buffer_cache_create_requested(task_graph, | mesh_buffer_cache_create_requested(task_graph, | ||||
| cache, | cache, | ||||
| cache->uv_cage, | cache->uv_cage, | ||||
| me, | me, | ||||
| is_editmode, | is_editmode, | ||||
| is_paint_mode, | is_paint_mode, | ||||
| ob->obmat, | ob->obmat, | ||||
| Show All 33 Lines | mesh_buffer_cache_create_requested(task_graph, | ||||
| true, | true, | ||||
| false, | false, | ||||
| use_subsurf_fdots, | use_subsurf_fdots, | ||||
| &cache->cd_used, | &cache->cd_used, | ||||
| scene, | scene, | ||||
| ts, | ts, | ||||
| use_hide); | use_hide); | ||||
| #ifdef DEBUG | #ifdef DEBUG | ||||
| check: | drw_mesh_batch_cache_check_available(task_graph, me); | ||||
| /* Make sure all requested batches have been setup. */ | |||||
| /* TODO(jbakker): we should move this to the draw_manager but that needs refactoring and | |||||
| * additional looping.*/ | |||||
| BLI_task_graph_work_and_wait(task_graph); | |||||
| for (int i = 0; i < sizeof(cache->batch) / sizeof(void *); i++) { | |||||
| BLI_assert(!DRW_batch_requested(((GPUBatch **)&cache->batch)[i], 0)); | |||||
| } | |||||
| for (int i = 0; i < sizeof(cache->final.vbo) / sizeof(void *); i++) { | |||||
| BLI_assert(!DRW_vbo_requested(((GPUVertBuf **)&cache->final.vbo)[i])); | |||||
| } | |||||
| for (int i = 0; i < sizeof(cache->final.ibo) / sizeof(void *); i++) { | |||||
| BLI_assert(!DRW_ibo_requested(((GPUIndexBuf **)&cache->final.ibo)[i])); | |||||
| } | |||||
| for (int i = 0; i < sizeof(cache->cage.vbo) / sizeof(void *); i++) { | |||||
| BLI_assert(!DRW_vbo_requested(((GPUVertBuf **)&cache->cage.vbo)[i])); | |||||
| } | |||||
| for (int i = 0; i < sizeof(cache->cage.ibo) / sizeof(void *); i++) { | |||||
| BLI_assert(!DRW_ibo_requested(((GPUIndexBuf **)&cache->cage.ibo)[i])); | |||||
| } | |||||
| for (int i = 0; i < sizeof(cache->uv_cage.vbo) / sizeof(void *); i++) { | |||||
| BLI_assert(!DRW_vbo_requested(((GPUVertBuf **)&cache->uv_cage.vbo)[i])); | |||||
| } | |||||
| for (int i = 0; i < sizeof(cache->uv_cage.ibo) / sizeof(void *); i++) { | |||||
| BLI_assert(!DRW_ibo_requested(((GPUIndexBuf **)&cache->uv_cage.ibo)[i])); | |||||
| } | |||||
| #endif | #endif | ||||
| } | } | ||||
| /** \} */ | /** \} */ | ||||