[Bf-blender-cvs] [7d515f8c90c] tmp-batch-cache-cleanup: GPU: Add GPUIndexBuf subrange

Clément Foucault noreply at git.blender.org
Mon Jul 22 12:52:39 CEST 2019


Commit: 7d515f8c90c44d1bbadee255eb0f82508898c35a
Author: Clément Foucault
Date:   Sun Jul 14 16:49:44 2019 +0200
Branches: tmp-batch-cache-cleanup
https://developer.blender.org/rB7d515f8c90c44d1bbadee255eb0f82508898c35a

GPU: Add GPUIndexBuf subrange

This allows to render only a subset of an index buffer.
This is nice as we can render each material surfaces individually and the
whole mesh with the same index buffer.

===================================================================

M	source/blender/gpu/GPU_batch.h
M	source/blender/gpu/GPU_element.h
M	source/blender/gpu/intern/gpu_batch.c
M	source/blender/gpu/intern/gpu_element.c

===================================================================

diff --git a/source/blender/gpu/GPU_batch.h b/source/blender/gpu/GPU_batch.h
index 5b0cab220c0..68496e82936 100644
--- a/source/blender/gpu/GPU_batch.h
+++ b/source/blender/gpu/GPU_batch.h
@@ -40,7 +40,7 @@ typedef enum {
   GPU_BATCH_READY_TO_DRAW,
 } GPUBatchPhase;
 
-#define GPU_BATCH_VBO_MAX_LEN 4
+#define GPU_BATCH_VBO_MAX_LEN 5
 #define GPU_BATCH_VAO_STATIC_LEN 3
 #define GPU_BATCH_VAO_DYN_ALLOC_COUNT 16
 
@@ -114,6 +114,7 @@ void GPU_batch_vao_cache_clear(GPUBatch *);
 void GPU_batch_callback_free_set(GPUBatch *, void (*callback)(GPUBatch *, void *), void *);
 
 void GPU_batch_instbuf_set(GPUBatch *, GPUVertBuf *, bool own_vbo); /* Instancing */
+void GPU_batch_elembuf_set(GPUBatch *batch, GPUIndexBuf *elem, bool own_ibo);
 
 int GPU_batch_vertbuf_add_ex(GPUBatch *, GPUVertBuf *, bool own_vbo);
 
diff --git a/source/blender/gpu/GPU_element.h b/source/blender/gpu/GPU_element.h
index 4ac89d2658b..5f6c422096e 100644
--- a/source/blender/gpu/GPU_element.h
+++ b/source/blender/gpu/GPU_element.h
@@ -36,14 +36,19 @@ typedef enum {
 } GPUIndexBufType;
 
 typedef struct GPUIndexBuf {
+  uint index_start;
   uint index_len;
+  bool is_subrange;
 #if GPU_TRACK_INDEX_RANGE
   GPUIndexBufType index_type;
   uint32_t gl_index_type;
   uint base_index;
 #endif
   uint32_t ibo_id; /* 0 indicates not yet sent to VRAM */
-  void *data;      /* non-NULL indicates not yet sent to VRAM */
+  union {
+    void *data;              /* non-NULL indicates not yet sent to VRAM */
+    struct GPUIndexBuf *src; /* if is_subrange is true, this is the source buffer. */
+  };
 } GPUIndexBuf;
 
 void GPU_indexbuf_use(GPUIndexBuf *);
@@ -74,6 +79,9 @@ void GPU_indexbuf_add_line_adj_verts(GPUIndexBufBuilder *, uint v1, uint v2, uin
 GPUIndexBuf *GPU_indexbuf_build(GPUIndexBufBuilder *);
 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_discard(GPUIndexBuf *);
 
 int GPU_indexbuf_primitive_len(GPUPrimType prim_type);
diff --git a/source/blender/gpu/intern/gpu_batch.c b/source/blender/gpu/intern/gpu_batch.c
index ba3c7f68518..8d6e0aadb61 100644
--- a/source/blender/gpu/intern/gpu_batch.c
+++ b/source/blender/gpu/intern/gpu_batch.c
@@ -181,6 +181,25 @@ void GPU_batch_instbuf_set(GPUBatch *batch, GPUVertBuf *inst, bool own_vbo)
   }
 }
 
+void GPU_batch_elembuf_set(GPUBatch *batch, GPUIndexBuf *elem, bool own_ibo)
+{
+  BLI_assert(elem != NULL);
+  /* redo the bindings */
+  GPU_batch_vao_cache_clear(batch);
+
+  if (batch->elem != NULL && (batch->owns_flag & GPU_BATCH_OWNS_INDEX)) {
+    GPU_indexbuf_discard(batch->elem);
+  }
+  batch->elem = elem;
+
+  if (own_ibo) {
+    batch->owns_flag |= GPU_BATCH_OWNS_INDEX;
+  }
+  else {
+    batch->owns_flag &= ~GPU_BATCH_OWNS_INDEX;
+  }
+}
+
 /* Returns the index of verts in the batch. */
 int GPU_batch_vertbuf_add_ex(GPUBatch *batch, GPUVertBuf *verts, bool own_vbo)
 {
@@ -549,10 +568,10 @@ static void *elem_offset(const GPUIndexBuf *el, int v_first)
 {
 #if GPU_TRACK_INDEX_RANGE
   if (el->index_type == GPU_INDEX_U16) {
-    return (GLushort *)0 + v_first;
+    return (GLushort *)0 + v_first + el->index_start;
   }
 #endif
-  return (GLuint *)0 + v_first;
+  return (GLuint *)0 + v_first + el->index_start;
 }
 
 /* Use when drawing with GPU_batch_draw_advanced */
diff --git a/source/blender/gpu/intern/gpu_element.c b/source/blender/gpu/intern/gpu_element.c
index 50e7df96503..9b8deac094b 100644
--- a/source/blender/gpu/intern/gpu_element.c
+++ b/source/blender/gpu/intern/gpu_element.c
@@ -162,6 +162,23 @@ void GPU_indexbuf_add_line_adj_verts(
   GPU_indexbuf_add_generic_vert(builder, v4);
 }
 
+GPUIndexBuf *GPU_indexbuf_create_subrange(GPUIndexBuf *elem_src, uint start, uint length)
+{
+  GPUIndexBuf *elem = MEM_callocN(sizeof(GPUIndexBuf), "GPUIndexBuf");
+  BLI_assert(elem_src && !elem_src->is_subrange);
+  BLI_assert(start + length <= elem_src->index_len);
+#if GPU_TRACK_INDEX_RANGE
+  elem->index_type = elem_src->index_type;
+  elem->gl_index_type = elem_src->gl_index_type;
+  elem->base_index = elem_src->base_index;
+#endif
+  elem->is_subrange = true;
+  elem->src = elem_src;
+  elem->index_start = start;
+  elem->index_len = length;
+  return elem;
+}
+
 #if GPU_TRACK_INDEX_RANGE
 /* Everything remains 32 bit while building to keep things simple.
  * Find min/max after, then convert to smallest index type possible. */
@@ -271,6 +288,10 @@ static void indexbuf_upload_data(GPUIndexBuf *elem)
 
 void GPU_indexbuf_use(GPUIndexBuf *elem)
 {
+  if (elem->is_subrange) {
+    GPU_indexbuf_use(elem->src);
+    return;
+  }
   if (elem->ibo_id == 0) {
     elem->ibo_id = GPU_buf_alloc();
   }
@@ -285,7 +306,7 @@ void GPU_indexbuf_discard(GPUIndexBuf *elem)
   if (elem->ibo_id) {
     GPU_buf_free(elem->ibo_id);
   }
-  if (elem->data) {
+  if (!elem->is_subrange && elem->data) {
     MEM_freeN(elem->data);
   }
   MEM_freeN(elem);



More information about the Bf-blender-cvs mailing list