[Bf-blender-cvs] [a0ec3b7fd76] tmp-batch-cache-cleanup: Mesh Batch Cache: Fix some threadsafety issue with indices buffers
Clément Foucault
noreply at git.blender.org
Tue Jul 23 00:10:55 CEST 2019
Commit: a0ec3b7fd761155b5f82b3cfb0f305d6a04d6127
Author: Clément Foucault
Date: Tue Jul 23 00:05:15 2019 +0200
Branches: tmp-batch-cache-cleanup
https://developer.blender.org/rBa0ec3b7fd761155b5f82b3cfb0f305d6a04d6127
Mesh Batch Cache: Fix some threadsafety issue with indices buffers
===================================================================
M source/blender/draw/intern/draw_cache_impl_mesh.c
M source/blender/gpu/intern/gpu_element.c
===================================================================
diff --git a/source/blender/draw/intern/draw_cache_impl_mesh.c b/source/blender/draw/intern/draw_cache_impl_mesh.c
index 094cff77ea5..d9edbdc4511 100644
--- a/source/blender/draw/intern/draw_cache_impl_mesh.c
+++ b/source/blender/draw/intern/draw_cache_impl_mesh.c
@@ -233,6 +233,21 @@ BLI_INLINE void mesh_cd_layers_type_clear(DRW_MeshCDMask *a)
*((uint32_t *)a) = 0;
}
+BLI_INLINE BMFace *bm_original_face_get(BMesh *bm, int idx)
+{
+ return ((idx != ORIGINDEX_NONE) ? BM_face_at_index(bm, idx) : NULL);
+}
+
+BLI_INLINE BMEdge *bm_original_edge_get(BMesh *bm, int idx)
+{
+ return ((idx != ORIGINDEX_NONE) ? BM_edge_at_index(bm, idx) : NULL);
+}
+
+BLI_INLINE BMVert *bm_original_vert_get(BMesh *bm, int idx)
+{
+ return ((idx != ORIGINDEX_NONE) ? BM_vert_at_index(bm, idx) : NULL);
+}
+
static void mesh_cd_calc_active_uv_layer(const Mesh *me, DRW_MeshCDMask *cd_used)
{
const CustomData *cd_ldata = (me->edit_mesh) ? &me->edit_mesh->bm->ldata : &me->ldata;
@@ -1201,7 +1216,7 @@ typedef struct MeshExtractIterData {
int v1, v2, v3;
bool use_hide;
- MeshRenderData *mr;
+ const MeshRenderData *mr;
/** iter function list */
void *itr_fn;
} MeshExtractIterData;
@@ -1224,93 +1239,132 @@ typedef struct MeshExtract {
/** \name Extract Triangles Indices
* \{ */
-typedef struct MeshExtract_Tri_Data {
- GPUIndexBufBuilder elb;
- uint32_t mat_tri_idx[0];
-} MeshExtract_Tri_Data;
-
static void *mesh_tri_init(const MeshRenderData *mr, void *UNUSED(ibo))
{
- size_t mat_tri_idx_size = sizeof(uint32_t) * mr->mat_len;
- MeshExtract_Tri_Data *data = MEM_callocN(sizeof(*data) + mat_tri_idx_size, __func__);
- GPU_indexbuf_init(&data->elb, GPU_PRIM_TRIS, mr->tri_len, mr->loop_len);
- /* Set all indices to primitive restart. We do this to bypass hidden elements. */
- /* NOTE: This is not the best method as it leave holes in the index buffer.
- * TODO(fclem): Better approach would be to remove the holes by moving all the indices block to
- * have a continuous buffer. The issue is that we need to randomly set indices in the buffer
- * for multithreading. */
- // memset(data->elb.data, 0xFF, sizeof(uint) * mr->tri_len * 3);
- /* Count how many triangle for each material. */
- if (mr->mat_len > 1) {
- if (mr->extract_type == MR_EXTRACT_BMESH) {
- BMIter iter;
- BMFace *efa;
- BM_ITER_MESH (efa, &iter, mr->bm, BM_FACES_OF_MESH) {
- BLI_assert(efa->len > 2);
- data->mat_tri_idx[efa->mat_nr] += efa->len - 2;
- }
- }
- else {
- const MPoly *mpoly = mr->mpoly;
- for (int p = 0; p < mr->poly_len; p++, mpoly++) {
- BLI_assert(mpoly->totloop > 2);
- data->mat_tri_idx[mpoly->mat_nr] += mpoly->totloop - 2;
- }
- }
- }
- /* Accumulate tri len per mat to have correct offsets. */
- int ofs = data->mat_tri_idx[0];
- data->mat_tri_idx[0] = 0;
- for (int i = 1; i < mr->mat_len; i++) {
- int tmp = data->mat_tri_idx[i];
- data->mat_tri_idx[i] = ofs;
- ofs += tmp;
- }
- /* HACK pass per mat triangle start and end outside the extract loop. */
- MEM_SAFE_FREE(mr->cache->tri_mat_end);
- MEM_SAFE_FREE(mr->cache->tri_mat_start);
- mr->cache->tri_mat_end = MEM_mallocN(mat_tri_idx_size, __func__);
- mr->cache->tri_mat_start = MEM_mallocN(mat_tri_idx_size, __func__);
- memcpy(mr->cache->tri_mat_start, data->mat_tri_idx, mat_tri_idx_size);
+ GPUIndexBufBuilder *elb = MEM_callocN(sizeof(*elb), __func__);
+ GPU_indexbuf_init(elb, GPU_PRIM_TRIS, mr->tri_len, mr->loop_len);
- return data;
+ return elb;
}
-static void mesh_tri_iter(const MeshExtractIterData *iter, void *UNUSED(buf), void *user_data)
+static void mesh_tri_iter(const MeshExtractIterData *iter, void *UNUSED(buf), void *elb)
{
if (!(iter->use_hide && (iter->mpoly->flag & ME_HIDE))) {
- MeshExtract_Tri_Data *data = user_data;
- uint32_t tri_idx = atomic_fetch_and_add_uint32(&data->mat_tri_idx[iter->mpoly->mat_nr], 1u);
- GPU_indexbuf_set_tri_verts(&data->elb, tri_idx, iter->v1, iter->v2, iter->v3);
+ GPU_indexbuf_set_tri_verts(elb, iter->tri_idx, iter->v1, iter->v2, iter->v3);
+ }
+ else {
+ GPU_indexbuf_set_tri_restart(elb, iter->tri_idx);
}
}
-static void mesh_tri_iter_edit(const MeshExtractIterData *iter, void *UNUSED(buf), void *user_data)
+static void mesh_tri_iter_edit(const MeshExtractIterData *iter, void *UNUSED(buf), void *elb)
{
if (!iter->efa) {
- mesh_tri_iter(iter, NULL, user_data);
+ mesh_tri_iter(iter, NULL, elb);
}
else if (!BM_elem_flag_test(iter->efa, BM_ELEM_HIDDEN)) {
- MeshExtract_Tri_Data *data = user_data;
- uint32_t tri_idx = atomic_fetch_and_add_uint32(&data->mat_tri_idx[iter->efa->mat_nr], 1u);
- GPU_indexbuf_set_tri_verts(&data->elb, tri_idx, iter->v1, iter->v2, iter->v3);
+ GPU_indexbuf_set_tri_verts(elb, iter->tri_idx, iter->v1, iter->v2, iter->v3);
+ }
+ else {
+ GPU_indexbuf_set_tri_restart(elb, iter->tri_idx);
}
}
-static void mesh_tri_finish(const MeshRenderData *mr, void *ibo, void *user_data)
+static void mesh_tri_finish(const MeshRenderData *mr, void *ibo, void *elb)
{
- MeshExtract_Tri_Data *data = user_data;
- GPU_indexbuf_build_in_place(&data->elb, ibo);
+ MEM_SAFE_FREE(mr->cache->tri_mat_end);
+ MEM_SAFE_FREE(mr->cache->tri_mat_start);
/* HACK pass per mat triangle start and end outside the extract loop. */
- memcpy(mr->cache->tri_mat_end, data->mat_tri_idx, sizeof(uint32_t) * mr->mat_len);
+ size_t mat_tri_idx_size = sizeof(int) * mr->mat_len;
+ mr->cache->tri_mat_start = MEM_callocN(mat_tri_idx_size, __func__);
+ mr->cache->tri_mat_end = MEM_callocN(mat_tri_idx_size, __func__);
- for (int mat = 0; mat < mr->mat_len; mat++) {
- if (mr->cache->tri_mat_end[mat] < mr->cache->tri_mat_start[mat]) {
- /* Fill the rest of the buffer with restart index. */
- for (int tri = mr->cache->tri_mat_end[mat]; tri < mr->cache->tri_mat_start[mat]; tri++) {
- GPU_indexbuf_set_tri_restart(&data->elb, tri);
+ if (mr->mat_len > 1) {
+ int *mat_tri_ofs = mr->cache->tri_mat_start;
+ int *mat_tri_len = mr->cache->tri_mat_end;
+ /* Count how many triangle for each material. */
+ if (mr->extract_type == MR_EXTRACT_BMESH) {
+ BMIter iter;
+ BMFace *efa;
+ BM_ITER_MESH (efa, &iter, mr->bm, BM_FACES_OF_MESH) {
+ int poly_tri_len = efa->len - 2;
+ mat_tri_ofs[efa->mat_nr] += poly_tri_len;
+ }
+ }
+ else {
+ const MPoly *mpoly = mr->mpoly;
+ for (int p = 0; p < mr->poly_len; p++, mpoly++) {
+ int poly_tri_len = mpoly->totloop - 2;
+ mat_tri_ofs[mpoly->mat_nr] += poly_tri_len;
}
}
+ // memcpy(mat_tri_len, mat_tri_ofs, sizeof(*mat_tri_len) * mr->mat_len);
+ /* Accumulate tri len per mat to have correct offsets. */
+ int ofs = mat_tri_ofs[0];
+ mat_tri_ofs[0] = 0;
+ for (int i = 1; i < mr->mat_len; i++) {
+ int tmp = mat_tri_ofs[i];
+ mat_tri_ofs[i] = ofs;
+ ofs += tmp;
+ }
+ /* Now sort triangles per materials. */
+ uint(*tri_sorted)[3] = MEM_mallocN(sizeof(*tri_sorted) * mr->tri_len, __func__);
+ uint(*tri_source)[3] = (uint(*)[3])((GPUIndexBufBuilder *)elb)->data;
+ if (mr->extract_type == MR_EXTRACT_BMESH) {
+ int tri_idx = 0;
+ BMIter iter;
+ BMFace *efa;
+ BM_ITER_MESH (efa, &iter, mr->bm, BM_FACES_OF_MESH) {
+ int poly_tri_len = efa->len - 2;
+ uint(*src)[3] = tri_source + tri_idx;
+ uint(*dst)[3] = tri_sorted + mat_tri_ofs[efa->mat_nr] + mat_tri_len[efa->mat_nr];
+ memcpy(dst, src, sizeof(*dst) * poly_tri_len);
+ mat_tri_len[efa->mat_nr] += poly_tri_len;
+ tri_idx += poly_tri_len;
+ }
+ }
+ else {
+ const MPoly *mpoly = mr->mpoly;
+ int mat_curr = mpoly->mat_nr;
+ int cpy_sta = 0, cpy_end = 0, cpy_len;
+ int tri_idx = 0;
+ for (int p = 0; p < mr->poly_len; p++, mpoly++) {
+ if ((mat_curr != mpoly->mat_nr) || (p == mr->poly_len - 1)) {
+ cpy_end = (p == mr->poly_len - 1) ? tri_idx + mpoly->totloop - 2 : tri_idx;
+ cpy_len = cpy_end - cpy_sta;
+ int dst_sta = mat_tri_ofs[mat_curr] + mat_tri_len[mat_curr];
+ uint(*src)[3] = tri_source + cpy_sta;
+ uint(*dst)[3] = tri_sorted + dst_sta;
+ printf("copy mat[%d] %d-%d to %d-%d\n",
+ mat_curr,
+ cpy_sta,
+ cpy_sta + cpy_len,
+ dst_sta,
+ dst_sta + cpy_len);
+ memcpy(dst, src, sizeof(*dst) * cpy_len);
+
+ mat_tri_len[mat_curr] += cpy_len;
+ cpy_sta = tri_idx;
+ mat_curr = mpoly->mat_nr;
+ }
+ tri_idx += mpoly->totloop - 2;
+ }
+ }
+
+ /* Replace old (unsorted) data and free it. */
+ ((GPUIndexBufBuilder *)elb)->data = (uint *)tri_sorted;
+ MEM_freeN(tri_source);
+ /* Set material indices end. */
+ for (int i = 1; i < mr->mat_len; i++) {
+ mr->cache->tri_mat_end[i] = mat_tri_ofs[i] + mat_tri_len[i];
+ }
}
+ else {
+ mr->cache->tri_mat_start[0] = 0;
+ mr->cache->tri_mat_end[0] = mr->tri_len;
+ }
+ /* XXX overriding here in case multithread hazard happened. */
+ ((GPUIndexBufBuilder *)elb)->index_len = mr->tri_len * 3;
+ GPU_indexbuf_build_in_place(elb, ibo);
- MEM_freeN(user_data);
+ MEM_freeN(elb);
}
MeshExtract extract_tris = {
@@ -1380,7 +1434,8 @@ static void mesh_edge_finish(const MeshRenderData *mr, void *ibo, void *elb)
mr->cache->edge_loose_start = 0;
mr->cache->edge_loose_end = 0;
}
-
+ /* XXX overriding here in case multithread hazard happened. */
+ ((GPUIndexBufBuilder *)elb)->index_len = (mr->edge_len + mr->edge_loose_len) * 2;
GPU_indexbuf_build_in_place(elb, ibo);
MEM_freeN(elb);
}
@@ -1428,8 +1483,10 @@ static void mesh_vert_iter_edit(const MeshExtractIterData *iter, void *UNUSED(bu
GPU_indexbuf_set_point_restart(elb, iter->vert_idx);
}
}
-static void mesh_vert_finish(const MeshRenderData *UNUSED(mr), void *ibo, void *elb)
+static void mesh_vert_finish(const MeshRenderData *mr, void *ibo, void *elb)
{
+ /* XXX overriding here in case multithread hazard happened. */
+ ((GPUIndexBufBuilder *)elb)->index_len = mr->vert_len;
GPU_indexbu
@@ Diff output truncated at 10240 characters. @@
More information about the Bf-blender-cvs
mailing list