Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBrecht Van Lommel <brechtvanlommel@gmail.com>2019-10-02 19:02:41 +0300
committerBrecht Van Lommel <brechtvanlommel@gmail.com>2019-10-02 19:28:26 +0300
commitde4ebcbe4368e2e71dc14effaf2733a4a0138570 (patch)
treee3de16ef7ee68a449acef38bba0ff09b35ca35a4 /source/blender/gpu/intern/gpu_buffers.c
parenta1f16ba67fc2decb3fdb755531aafa9043c046a7 (diff)
Fix T70390: dyntopo smooth shading broken after recent changes
Made the code fully thread safe now.
Diffstat (limited to 'source/blender/gpu/intern/gpu_buffers.c')
-rw-r--r--source/blender/gpu/intern/gpu_buffers.c257
1 files changed, 115 insertions, 142 deletions
diff --git a/source/blender/gpu/intern/gpu_buffers.c b/source/blender/gpu/intern/gpu_buffers.c
index ed606ccb8c6..78202158852 100644
--- a/source/blender/gpu/intern/gpu_buffers.c
+++ b/source/blender/gpu/intern/gpu_buffers.c
@@ -729,47 +729,36 @@ GPU_PBVH_Buffers *GPU_pbvh_grid_buffers_build(int totgrid, BLI_bitmap **grid_hid
/** \name BMesh PBVH
* \{ */
-/* Output a BMVert into a VertexBufferFormat array
- *
- * The vertex is skipped if hidden, otherwise the output goes into
- * index '*v_index' in the 'vert_data' array and '*v_index' is
- * incremented.
- */
-static void gpu_bmesh_vert_to_buffer_copy__gwn(BMVert *v,
- GPUVertBuf *vert_buf,
- int *v_index,
- const float fno[3],
- const float *fmask,
- const int cd_vert_mask_offset,
- const bool show_mask,
- const bool show_vcol,
- bool *empty_mask)
+/* Output a BMVert into a VertexBufferFormat array at v_index. */
+static void gpu_bmesh_vert_to_buffer_copy(BMVert *v,
+ GPUVertBuf *vert_buf,
+ int v_index,
+ const float fno[3],
+ const float *fmask,
+ const int cd_vert_mask_offset,
+ const bool show_mask,
+ const bool show_vcol,
+ bool *empty_mask)
{
- if (!BM_elem_flag_test(v, BM_ELEM_HIDDEN)) {
-
- /* Set coord, normal, and mask */
- GPU_vertbuf_attr_set(vert_buf, g_vbo_id.pos, *v_index, v->co);
+ /* Vertex should always be visible if it's used by a visible face. */
+ BLI_assert(!BM_elem_flag_test(v, BM_ELEM_HIDDEN));
- short no_short[3];
- normal_float_to_short_v3(no_short, fno ? fno : v->no);
- GPU_vertbuf_attr_set(vert_buf, g_vbo_id.nor, *v_index, no_short);
+ /* Set coord, normal, and mask */
+ GPU_vertbuf_attr_set(vert_buf, g_vbo_id.pos, v_index, v->co);
- if (show_mask) {
- float effective_mask = fmask ? *fmask : BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset);
- GPU_vertbuf_attr_set(vert_buf, g_vbo_id.msk, *v_index, &effective_mask);
- *empty_mask = *empty_mask && (effective_mask == 0.0f);
- }
-
- if (show_vcol) {
- static char vcol[4] = {255, 255, 255, 255};
- GPU_vertbuf_attr_set(vert_buf, g_vbo_id.col, *v_index, &vcol);
- }
+ short no_short[3];
+ normal_float_to_short_v3(no_short, fno ? fno : v->no);
+ GPU_vertbuf_attr_set(vert_buf, g_vbo_id.nor, v_index, no_short);
- /* Assign index for use in the triangle index buffer */
- /* note: caller must set: bm->elem_index_dirty |= BM_VERT; */
- BM_elem_index_set(v, (*v_index)); /* set_dirty! */
+ if (show_mask) {
+ float effective_mask = fmask ? *fmask : BM_ELEM_CD_GET_FLOAT(v, cd_vert_mask_offset);
+ GPU_vertbuf_attr_set(vert_buf, g_vbo_id.msk, v_index, &effective_mask);
+ *empty_mask = *empty_mask && (effective_mask == 0.0f);
+ }
- (*v_index)++;
+ if (show_vcol) {
+ static char vcol[4] = {255, 255, 255, 255};
+ GPU_vertbuf_attr_set(vert_buf, g_vbo_id.col, v_index, &vcol);
}
}
@@ -839,7 +828,7 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
{
const bool show_mask = (update_flags & GPU_PBVH_BUFFERS_SHOW_MASK) != 0;
const bool show_vcol = (update_flags & GPU_PBVH_BUFFERS_SHOW_VCOL) != 0;
- int tottri, totvert, maxvert = 0;
+ int tottri, totvert;
bool empty_mask = true;
BMFace *f = NULL;
@@ -869,135 +858,118 @@ void GPU_pbvh_bmesh_buffers_update(GPU_PBVH_Buffers *buffers,
const int cd_vert_mask_offset = CustomData_get_offset(&bm->vdata, CD_PAINT_MASK);
/* Fill vertex buffer */
- if (gpu_pbvh_vert_buf_data_set(buffers, totvert)) {
- int v_index = 0;
-
- if (buffers->smooth) {
- GSetIterator gs_iter;
-
- /* Vertices get an index assigned for use in the triangle
- * index buffer */
- bm->elem_index_dirty |= BM_VERT;
-
- GSET_ITER (gs_iter, bm_unique_verts) {
- gpu_bmesh_vert_to_buffer_copy__gwn(BLI_gsetIterator_getKey(&gs_iter),
- buffers->vert_buf,
- &v_index,
- NULL,
- NULL,
- cd_vert_mask_offset,
- show_mask,
- show_vcol,
- &empty_mask);
- }
-
- GSET_ITER (gs_iter, bm_other_verts) {
- gpu_bmesh_vert_to_buffer_copy__gwn(BLI_gsetIterator_getKey(&gs_iter),
- buffers->vert_buf,
- &v_index,
- NULL,
- NULL,
- cd_vert_mask_offset,
- show_mask,
- show_vcol,
- &empty_mask);
- }
+ if (!gpu_pbvh_vert_buf_data_set(buffers, totvert)) {
+ /* Memory map failed */
+ return;
+ }
- maxvert = v_index;
- }
- else {
- GSetIterator gs_iter;
+ int v_index = 0;
- GPUIndexBufBuilder elb_lines;
- GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, totvert);
+ if (buffers->smooth) {
+ /* Fill the vertex and triangle buffer in one pass over faces. */
+ GPUIndexBufBuilder elb, elb_lines;
+ GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tottri, totvert);
+ GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, totvert);
- GSET_ITER (gs_iter, bm_faces) {
- f = BLI_gsetIterator_getKey(&gs_iter);
+ GHash *bm_vert_to_index = BLI_ghash_int_new_ex("bm_vert_to_index", totvert);
- BLI_assert(f->len == 3);
+ GSetIterator gs_iter;
+ GSET_ITER (gs_iter, bm_faces) {
+ f = BLI_gsetIterator_getKey(&gs_iter);
- if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
- BMVert *v[3];
- float fmask = 0.0f;
- int i;
+ if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ BMVert *v[3];
+ BM_face_as_array_vert_tri(f, v);
- BM_face_as_array_vert_tri(f, v);
+ uint idx[3];
+ for (int i = 0; i < 3; i++) {
+ void **idx_p;
+ if (!BLI_ghash_ensure_p(bm_vert_to_index, v[i], &idx_p)) {
+ /* Add vertex to the vertex buffer each time a new one is encountered */
+ *idx_p = POINTER_FROM_UINT(v_index);
- /* Average mask value */
- for (i = 0; i < 3; i++) {
- fmask += BM_ELEM_CD_GET_FLOAT(v[i], cd_vert_mask_offset);
+ gpu_bmesh_vert_to_buffer_copy(v[i],
+ buffers->vert_buf,
+ v_index,
+ NULL,
+ NULL,
+ cd_vert_mask_offset,
+ show_mask,
+ show_vcol,
+ &empty_mask);
+
+ idx[i] = v_index;
+ v_index++;
}
- fmask /= 3.0f;
-
- GPU_indexbuf_add_line_verts(&elb_lines, v_index + 0, v_index + 1);
- GPU_indexbuf_add_line_verts(&elb_lines, v_index + 1, v_index + 2);
- GPU_indexbuf_add_line_verts(&elb_lines, v_index + 2, v_index + 0);
-
- for (i = 0; i < 3; i++) {
- gpu_bmesh_vert_to_buffer_copy__gwn(v[i],
- buffers->vert_buf,
- &v_index,
- f->no,
- &fmask,
- cd_vert_mask_offset,
- show_mask,
- show_vcol,
- &empty_mask);
+ else {
+ /* Vertex already in the vertex buffer, just get the index. */
+ idx[i] = POINTER_AS_UINT(*idx_p);
}
}
- }
- buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines);
- buffers->tot_tri = tottri;
+ GPU_indexbuf_add_tri_verts(&elb, idx[0], idx[1], idx[2]);
+
+ GPU_indexbuf_add_line_verts(&elb_lines, idx[0], idx[1]);
+ GPU_indexbuf_add_line_verts(&elb_lines, idx[1], idx[2]);
+ GPU_indexbuf_add_line_verts(&elb_lines, idx[2], idx[0]);
+ }
}
- /* gpu_bmesh_vert_to_buffer_copy sets dirty index values */
- bm->elem_index_dirty |= BM_VERT;
+ BLI_ghash_free(bm_vert_to_index, NULL, NULL);
+
+ buffers->tot_tri = tottri;
+ if (buffers->index_buf == NULL) {
+ buffers->index_buf = GPU_indexbuf_build(&elb);
+ }
+ else {
+ GPU_indexbuf_build_in_place(&elb, buffers->index_buf);
+ }
+ buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines);
}
else {
- /* Memory map failed */
- return;
- }
-
- if (buffers->smooth) {
- /* Fill the triangle buffer */
- GPUIndexBufBuilder elb, elb_lines;
- GPU_indexbuf_init(&elb, GPU_PRIM_TRIS, tottri, maxvert);
- GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, maxvert);
+ GSetIterator gs_iter;
- /* Fill triangle index buffer */
- {
- GSetIterator gs_iter;
+ GPUIndexBufBuilder elb_lines;
+ GPU_indexbuf_init(&elb_lines, GPU_PRIM_LINES, tottri * 3, tottri * 3);
- GSET_ITER (gs_iter, bm_faces) {
- f = BLI_gsetIterator_getKey(&gs_iter);
+ GSET_ITER (gs_iter, bm_faces) {
+ f = BLI_gsetIterator_getKey(&gs_iter);
- if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
- BMVert *v[3];
+ BLI_assert(f->len == 3);
- BM_face_as_array_vert_tri(f, v);
+ if (!BM_elem_flag_test(f, BM_ELEM_HIDDEN)) {
+ BMVert *v[3];
+ float fmask = 0.0f;
+ int i;
- const uint idx[3] = {
- BM_elem_index_get(v[0]), BM_elem_index_get(v[1]), BM_elem_index_get(v[2])};
- GPU_indexbuf_add_tri_verts(&elb, idx[0], idx[1], idx[2]);
+ BM_face_as_array_vert_tri(f, v);
- GPU_indexbuf_add_line_verts(&elb_lines, idx[0], idx[1]);
- GPU_indexbuf_add_line_verts(&elb_lines, idx[1], idx[2]);
- GPU_indexbuf_add_line_verts(&elb_lines, idx[2], idx[0]);
+ /* Average mask value */
+ for (i = 0; i < 3; i++) {
+ fmask += BM_ELEM_CD_GET_FLOAT(v[i], cd_vert_mask_offset);
+ }
+ fmask /= 3.0f;
+
+ GPU_indexbuf_add_line_verts(&elb_lines, v_index + 0, v_index + 1);
+ GPU_indexbuf_add_line_verts(&elb_lines, v_index + 1, v_index + 2);
+ GPU_indexbuf_add_line_verts(&elb_lines, v_index + 2, v_index + 0);
+
+ for (i = 0; i < 3; i++) {
+ gpu_bmesh_vert_to_buffer_copy(v[i],
+ buffers->vert_buf,
+ v_index++,
+ f->no,
+ &fmask,
+ cd_vert_mask_offset,
+ show_mask,
+ show_vcol,
+ &empty_mask);
}
}
-
- buffers->tot_tri = tottri;
-
- if (buffers->index_buf == NULL) {
- buffers->index_buf = GPU_indexbuf_build(&elb);
- }
- else {
- GPU_indexbuf_build_in_place(&elb, buffers->index_buf);
- }
-
- buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines);
}
+
+ buffers->index_lines_buf = GPU_indexbuf_build(&elb_lines);
+ buffers->tot_tri = tottri;
}
/* Get material index from the last face we iterated on. */
@@ -1054,6 +1026,7 @@ void GPU_pbvh_buffers_update_flush(GPU_PBVH_Buffers *buffers)
GPU_BATCH_DISCARD_SAFE(buffers->triangles);
GPU_INDEXBUF_DISCARD_SAFE(buffers->index_buf);
GPU_VERTBUF_DISCARD_SAFE(buffers->vert_buf);
+ buffers->clear_bmesh_on_flush = false;
}
/* Force flushing to the GPU. */