Fix T72130: Wireframe Visible After Disabling
authorJeroen Bakker <jeroen@blender.org>
Tue, 3 Dec 2019 07:27:55 +0000 (08:27 +0100)
committerJeroen Bakker <jeroen@blender.org>
Wed, 4 Dec 2019 14:17:09 +0000 (15:17 +0100)
The lines index buffer can contain all edges (edit mode) or only loose
edges (object mode). When switching between these modes the wrong
content of the index buffer can be used.

This patch will clear the lines index buffer when a `loose_edges` is requested. Making sure it is always up to date.

Note that this is supporting an exising hack where the IBO is truncated
during the creation. We should find a different way how to solve these
kind of issues.

Reviewed By: fclem

Differential Revision: https://developer.blender.org/D6349

source/blender/draw/intern/draw_cache_extract.h
source/blender/draw/intern/draw_cache_extract_mesh.c
source/blender/draw/intern/draw_cache_impl_mesh.c
source/blender/draw/intern/draw_cache_inline.h
source/blender/gpu/GPU_element.h
source/blender/gpu/intern/gpu_element.c

index b1eab3c73aedc6c8f3426de9412247f276555e47..7ee02c3c55627db3a046ab4846f5a932d9ade69e 100644 (file)
@@ -115,8 +115,9 @@ typedef struct MeshBufferCache {
    * Only need to be updated when topology changes. */
   struct {
     /* Indices to vloops. */
-    GPUIndexBuf *tris;  /* Ordered per material. */
-    GPUIndexBuf *lines; /* Loose edges last. */
+    GPUIndexBuf *tris;        /* Ordered per material. */
+    GPUIndexBuf *lines;       /* Loose edges last. */
+    GPUIndexBuf *lines_loose; /* sub buffer of `lines` only containing the loose edges. */
     GPUIndexBuf *points;
     GPUIndexBuf *fdots;
     /* 3D overlays. */
index 2c6eb7e0b1d682bb5058c477d6c16e3b87768538..06c2bfc301a2b428523f8a39825229235029c4ad 100644 (file)
@@ -634,21 +634,10 @@ static void extract_lines_ledge_mesh(const MeshRenderData *mr,
   GPU_indexbuf_set_line_restart(elb, edge_idx);
 }
 
-static void extract_lines_finish(const MeshRenderData *mr, void *ibo, void *elb)
+static void extract_lines_finish(const MeshRenderData *UNUSED(mr), void *ibo, void *elb)
 {
   GPU_indexbuf_build_in_place(elb, ibo);
   MEM_freeN(elb);
-  /* HACK Create ibo subranges and assign them to GPUBatch. */
-  if (mr->use_final_mesh && mr->cache->batch.loose_edges) {
-    BLI_assert(mr->cache->batch.loose_edges->elem == ibo);
-    /* Multiply by 2 because these are edges indices. */
-    int start = mr->edge_len * 2;
-    int len = mr->edge_loose_len * 2;
-    GPUIndexBuf *sub_ibo = GPU_indexbuf_create_subrange(ibo, start, len);
-    /* WARNING: We modify the GPUBatch here! */
-    GPU_batch_elembuf_set(mr->cache->batch.loose_edges, sub_ibo, true);
-    mr->cache->no_loose_wire = (len == 0);
-  }
 }
 
 static const MeshExtract extract_lines = {
@@ -668,6 +657,56 @@ static const MeshExtract extract_lines = {
 
 /** \} */
 
+/* ---------------------------------------------------------------------- */
+/** \name Extract Loose Edges Indices
+ * \{ */
+
+static void *extract_lines_loose_init(const MeshRenderData *UNUSED(mr), void *UNUSED(buf))
+{
+  return NULL;
+}
+
+static void extract_lines_loose_ledge_mesh(const MeshRenderData *UNUSED(mr),
+                                           int UNUSED(e),
+                                           const MEdge *UNUSED(medge),
+                                           void *UNUSED(elb))
+{
+  /* This function is intentionally empty. The existence of this functions ensures that
+   * `iter_type` `MR_ITER_LVERT` is set when initializing the `MeshRenderData` (See
+   * `mesh_extract_iter_type`). This flag ensures that `mr->edge_loose_len` field is filled. This
+   * field we use in the `extract_lines_loose_finish` function to create a subrange from the
+   * `ibo.lines`. */
+}
+
+static void extract_lines_loose_finish(const MeshRenderData *mr,
+                                       void *UNUSED(ibo),
+                                       void *UNUSED(elb))
+{
+  /* Multiply by 2 because these are edges indices. */
+  const int start = mr->edge_len * 2;
+  const int len = mr->edge_loose_len * 2;
+  GPU_indexbuf_create_subrange_in_place(
+      mr->cache->final.ibo.lines_loose, mr->cache->final.ibo.lines, start, len);
+  mr->cache->no_loose_wire = (len == 0);
+}
+
+static const MeshExtract extract_lines_loose = {
+    extract_lines_loose_init,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    NULL,
+    extract_lines_loose_ledge_mesh,
+    NULL,
+    NULL,
+    extract_lines_loose_finish,
+    0,
+    false,
+};
+
+/** \} */
+
 /* ---------------------------------------------------------------------- */
 /** \name Extract Point Indices
  * \{ */
@@ -4370,6 +4409,7 @@ void mesh_buffer_cache_create_requested(MeshBatchCache *cache,
   TEST_ASSIGN(IBO, ibo, fdots);
   TEST_ASSIGN(IBO, ibo, lines_paint_mask);
   TEST_ASSIGN(IBO, ibo, lines_adjacency);
+  TEST_ASSIGN(IBO, ibo, lines_loose);
   TEST_ASSIGN(IBO, ibo, edituv_tris);
   TEST_ASSIGN(IBO, ibo, edituv_lines);
   TEST_ASSIGN(IBO, ibo, edituv_points);
@@ -4451,6 +4491,12 @@ void mesh_buffer_cache_create_requested(MeshBatchCache *cache,
   BLI_task_pool_work_and_wait(task_pool);
   BLI_task_pool_free(task_pool);
 
+  /* The `lines_loose` is a sub buffer from `ibo.lines`.
+   * We don't use the extract mechanism due to potential synchronization issues.*/
+  if (mbc.ibo.lines_loose) {
+    extract_task_create(NULL, mr, &extract_lines_loose, mbc.ibo.lines_loose, task_counters);
+  }
+
   MEM_freeN(task_counters);
 
   mesh_render_data_free(mr);
index dd6749638a79dacda146c410ef1f39fa109a16a3..7c7178eae852722c6ddbe582a3cbb641d9a27a63 100644 (file)
@@ -1228,7 +1228,8 @@ void DRW_mesh_batch_cache_create_requested(
     DRW_vbo_request(cache->batch.all_edges, &mbufcache->vbo.pos_nor);
   }
   if (DRW_batch_requested(cache->batch.loose_edges, GPU_PRIM_LINES)) {
-    DRW_ibo_request(cache->batch.loose_edges, &mbufcache->ibo.lines);
+    DRW_ibo_request(NULL, &mbufcache->ibo.lines);
+    DRW_ibo_request(cache->batch.loose_edges, &mbufcache->ibo.lines_loose);
     DRW_vbo_request(cache->batch.loose_edges, &mbufcache->vbo.pos_nor);
   }
   if (DRW_batch_requested(cache->batch.edge_detection, GPU_PRIM_LINES_ADJ)) {
index 12dc0a47a68cf192ecac6c4a69573ec20e27e0a2..f14d23dafcfba40b3a59b03fe16c128f2fcb731a 100644 (file)
@@ -72,8 +72,10 @@ BLI_INLINE void DRW_ibo_request(GPUBatch *batch, GPUIndexBuf **ibo)
   if (*ibo == NULL) {
     *ibo = MEM_callocN(sizeof(GPUIndexBuf), "GPUIndexBuf");
   }
-  GPU_batch_vao_cache_clear(batch);
-  batch->elem = *ibo;
+  if (batch != NULL) {
+    GPU_batch_vao_cache_clear(batch);
+    batch->elem = *ibo;
+  }
 }
 
 BLI_INLINE bool DRW_ibo_requested(GPUIndexBuf *ibo)
index 75caf4cbd6aed2d902cf30482d87f64b015d82c1..996ade3e0f66326dd6b0124b90e727b33ce8a6f0 100644 (file)
@@ -90,6 +90,10 @@ void GPU_indexbuf_build_in_place(GPUIndexBufBuilder *, GPUIndexBuf *);
 
 /* Create a subrange of an existing indexbuffer. */
 GPUIndexBuf *GPU_indexbuf_create_subrange(GPUIndexBuf *ibo, uint start, uint length);
+void GPU_indexbuf_create_subrange_in_place(GPUIndexBuf *r_ibo,
+                                           GPUIndexBuf *ibo,
+                                           uint start,
+                                           uint length);
 
 void GPU_indexbuf_discard(GPUIndexBuf *);
 
index 518829d1c78e57d1150bed17c5e1d4c78b6b3fa7..036588b4a48924037b09b15535f613d5596b8349 100644 (file)
@@ -242,6 +242,15 @@ void GPU_indexbuf_set_tri_restart(GPUIndexBufBuilder *builder, uint elem)
 GPUIndexBuf *GPU_indexbuf_create_subrange(GPUIndexBuf *elem_src, uint start, uint length)
 {
   GPUIndexBuf *elem = MEM_callocN(sizeof(GPUIndexBuf), "GPUIndexBuf");
+  GPU_indexbuf_create_subrange_in_place(elem, elem_src, start, length);
+  return elem;
+}
+
+void GPU_indexbuf_create_subrange_in_place(GPUIndexBuf *elem,
+                                           GPUIndexBuf *elem_src,
+                                           uint start,
+                                           uint length)
+{
   BLI_assert(elem_src && !elem_src->is_subrange);
   BLI_assert((length == 0) || (start + length <= elem_src->index_len));
 #if GPU_TRACK_INDEX_RANGE
@@ -253,7 +262,6 @@ GPUIndexBuf *GPU_indexbuf_create_subrange(GPUIndexBuf *elem_src, uint start, uin
   elem->src = elem_src;
   elem->index_start = start;
   elem->index_len = length;
-  return elem;
 }
 
 #if GPU_TRACK_INDEX_RANGE