[Bf-blender-cvs] [4d7fba508d3] tmp-drw-callbatching: DRW: Put DRWCalls into DRWCallChunks

Clément Foucault noreply at git.blender.org
Sat Aug 17 14:49:52 CEST 2019


Commit: 4d7fba508d3a2434a0c03df14924703f1198685d
Author: Clément Foucault
Date:   Sun Jun 2 20:02:35 2019 +0200
Branches: tmp-drw-callbatching
https://developer.blender.org/rB4d7fba508d3a2434a0c03df14924703f1198685d

DRW: Put DRWCalls into DRWCallChunks

This is in order to improve cache coherence and make it possible
to sort and merge drawcalls in the future.

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

M	source/blender/draw/intern/draw_manager.c
M	source/blender/draw/intern/draw_manager.h
M	source/blender/draw/intern/draw_manager_data.c
M	source/blender/draw/intern/draw_manager_exec.c

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

diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index eb75abaa8af..8a43ddbc4d5 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -636,7 +636,7 @@ static void drw_viewport_var_init(void)
     DST.vmempool = GPU_viewport_mempool_get(DST.viewport);
 
     if (DST.vmempool->calls == NULL) {
-      DST.vmempool->calls = BLI_memblock_create(sizeof(DRWCall));
+      DST.vmempool->calls = BLI_memblock_create(sizeof(DRWCallChunk));
     }
     if (DST.vmempool->obmats == NULL) {
       uint chunk_len = sizeof(DRWObjectMatrix) * DRW_RESOURCE_CHUNK_LEN;
@@ -2202,7 +2202,7 @@ void DRW_draw_select_loop(struct Depsgraph *depsgraph,
   Object *obact = OBACT(view_layer);
   Object *obedit = OBEDIT_FROM_OBACT(obact);
 #ifndef USE_GPU_SELECT
-  UNUSED_VARS(vc, scene, view_layer, v3d, ar, rect);
+  UNUSED_VARS(scene, view_layer, v3d, ar, rect);
 #else
   RegionView3D *rv3d = ar->regiondata;
 
diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h
index b150cb3cbc3..712fa712ec6 100644
--- a/source/blender/draw/intern/draw_manager.h
+++ b/source/blender/draw/intern/draw_manager.h
@@ -150,8 +150,6 @@ BLI_STATIC_ASSERT_ALIGN(DRWObjectMatrix, 16)
 BLI_STATIC_ASSERT_ALIGN(DRWObjectInfos, 16)
 
 typedef struct DRWCall {
-  struct DRWCall *next;
-
   GPUBatch *batch;
   uint vert_first;
   uint vert_count;
@@ -203,11 +201,11 @@ struct DRWShadingGroup {
 
   GPUShader *shader;                /* Shader to bind */
   struct DRWUniformChunk *uniforms; /* Uniforms pointers */
-
-  uint32_t uniform_count;
+  uint32_t uniform_count;           /* Index of next uniform inside DRWUniformChunk. */
 
   struct {
-    DRWCall *first, *last; /* Linked list of DRWCall */
+    /* Chunks of draw calls. */
+    struct DRWCallChunk *first, *last;
   } calls;
 
   /** TODO Maybe remove from here */
@@ -305,6 +303,22 @@ typedef struct DRWUniformChunk {
   DRWUniform uniforms[5];
 } DRWUniformChunk;
 
+typedef struct DRWCallChunk {
+  struct DRWCallChunk *next; /* single-linked list */
+  uchar chunk_len;
+  uchar call_used;
+  DRWCall calls[63];
+} DRWCallChunk;
+
+typedef struct DRWCallSmallChunk {
+  struct DRWCallChunk *next; /* single-linked list */
+  uchar chunk_len;
+  uchar call_used;
+  /* Small chunk to avoid wasting too much memory
+   * on small shading groups. */
+  DRWCall calls[5];
+} DRWCallSmallChunk;
+
 /* ------------- DRAW DEBUG ------------ */
 
 typedef struct DRWDebugLine {
diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c
index 8262937ea58..e918c395e17 100644
--- a/source/blender/draw/intern/draw_manager_data.c
+++ b/source/blender/draw/intern/draw_manager_data.c
@@ -518,6 +518,28 @@ static DRWResourceHandle drw_call_handle_object(DRWShadingGroup *shgroup,
   }
 }
 
+static DRWCall *drw_call_create(DRWShadingGroup *shgroup)
+{
+  DRWCallChunk *chunk = shgroup->calls.last;
+
+  if (chunk == NULL) {
+    /* TODO Create another pool to reduce memory usage of the first chunk. */
+    DRWCallSmallChunk *smallchunk = BLI_memblock_alloc(DST.vmempool->calls);
+    smallchunk->chunk_len = ARRAY_SIZE(smallchunk->calls);
+    smallchunk->call_used = 0;
+    chunk = (DRWCallChunk *)smallchunk;
+    BLI_LINKS_APPEND(&shgroup->calls, chunk);
+  }
+  else if (chunk->call_used == chunk->chunk_len) {
+    chunk = BLI_memblock_alloc(DST.vmempool->calls);
+    chunk->chunk_len = ARRAY_SIZE(chunk->calls);
+    chunk->call_used = 0;
+    BLI_LINKS_APPEND(&shgroup->calls, chunk);
+  }
+
+  return chunk->calls + chunk->call_used++;
+}
+
 void DRW_shgroup_call_ex(DRWShadingGroup *shgroup,
                          Object *ob,
                          float (*obmat)[4],
@@ -529,9 +551,7 @@ void DRW_shgroup_call_ex(DRWShadingGroup *shgroup,
 {
   BLI_assert(geom != NULL);
 
-  DRWCall *call = BLI_memblock_alloc(DST.vmempool->calls);
-  BLI_LINKS_APPEND(&shgroup->calls, call);
-
+  DRWCall *call = drw_call_create(shgroup);
   call->handle = drw_call_handle_object(shgroup, ob ? ob->obmat : obmat, ob);
   call->batch = geom;
   call->vert_first = v_sta;
@@ -562,9 +582,7 @@ static void drw_shgroup_call_procedural_add_ex(DRWShadingGroup *shgroup,
                                                uint vert_count)
 {
 
-  DRWCall *call = BLI_memblock_alloc(DST.vmempool->calls);
-  BLI_LINKS_APPEND(&shgroup->calls, call);
-
+  DRWCall *call = drw_call_create(shgroup);
   call->handle = drw_call_handle_object(shgroup, ob ? ob->obmat : NULL, ob);
   call->batch = geom;
   call->vert_first = 0;
@@ -601,9 +619,7 @@ void DRW_shgroup_call_instances(DRWShadingGroup *shgroup,
 {
   BLI_assert(geom != NULL);
 
-  DRWCall *call = BLI_memblock_alloc(DST.vmempool->calls);
-  BLI_LINKS_APPEND(&shgroup->calls, call);
-
+  DRWCall *call = drw_call_create(shgroup);
   call->handle = drw_call_handle_object(shgroup, ob ? ob->obmat : NULL, ob);
   call->batch = geom;
   call->vert_first = 0;
@@ -625,9 +641,7 @@ void DRW_shgroup_call_instances_with_attribs(DRWShadingGroup *shgroup,
 
   GPUVertBuf *buf_inst = inst_attributes->verts[0];
 
-  DRWCall *call = BLI_memblock_alloc(DST.vmempool->calls);
-  BLI_LINKS_APPEND(&shgroup->calls, call);
-
+  DRWCall *call = drw_call_create(shgroup);
   call->handle = drw_call_handle_object(shgroup, ob ? ob->obmat : NULL, ob);
   call->batch = DRW_temp_batch_instance_request(DST.idatalist, buf_inst, geom);
   call->vert_first = 0;
@@ -789,9 +803,7 @@ DRWCallBuffer *DRW_shgroup_call_buffer(DRWShadingGroup *shgroup,
   BLI_assert(ELEM(prim_type, GPU_PRIM_POINTS, GPU_PRIM_LINES, GPU_PRIM_TRI_FAN));
   BLI_assert(format != NULL);
 
-  DRWCall *call = BLI_memblock_alloc(DST.vmempool->calls);
-  BLI_LINKS_APPEND(&shgroup->calls, call);
-
+  DRWCall *call = drw_call_create(shgroup);
   call->handle = drw_call_handle_object(shgroup, NULL, NULL);
   GPUVertBuf *buf = DRW_temp_buffer_request(DST.idatalist, format, &call->vert_count);
   call->batch = DRW_temp_batch_request(DST.idatalist, buf, prim_type);
@@ -819,9 +831,7 @@ DRWCallBuffer *DRW_shgroup_call_buffer_instance(DRWShadingGroup *shgroup,
   BLI_assert(geom != NULL);
   BLI_assert(format != NULL);
 
-  DRWCall *call = BLI_memblock_alloc(DST.vmempool->calls);
-  BLI_LINKS_APPEND(&shgroup->calls, call);
-
+  DRWCall *call = drw_call_create(shgroup);
   call->handle = drw_call_handle_object(shgroup, NULL, NULL);
   GPUVertBuf *buf = DRW_temp_buffer_request(DST.idatalist, format, &call->inst_count);
   call->batch = DRW_temp_batch_instance_request(DST.idatalist, buf, geom);
@@ -1653,8 +1663,8 @@ static int pass_shgroup_dist_sort(void *thunk, const void *a, const void *b)
   const DRWShadingGroup *shgrp_a = (const DRWShadingGroup *)a;
   const DRWShadingGroup *shgrp_b = (const DRWShadingGroup *)b;
 
-  const DRWCall *call_a = (DRWCall *)shgrp_a->calls.first;
-  const DRWCall *call_b = (DRWCall *)shgrp_b->calls.first;
+  const DRWCall *call_a = &((DRWCallChunk *)shgrp_a->calls.first)->calls[0];
+  const DRWCall *call_b = &((DRWCallChunk *)shgrp_b->calls.first)->calls[0];
 
   if (call_a == NULL) {
     return -1;
diff --git a/source/blender/draw/intern/draw_manager_exec.c b/source/blender/draw/intern/draw_manager_exec.c
index 51562df2268..09de805cfc5 100644
--- a/source/blender/draw/intern/draw_manager_exec.c
+++ b/source/blender/draw/intern/draw_manager_exec.c
@@ -37,13 +37,13 @@
 #  include "GPU_select.h"
 #endif
 
-#ifdef USE_GPU_SELECT
 void DRW_select_load_id(uint id)
 {
+#ifdef USE_GPU_SELECT
   BLI_assert(G.f & G_FLAG_PICKSEL);
   DST.select_id = id;
-}
 #endif
+}
 
 #define DEBUG_UBO_BINDING
 
@@ -931,6 +931,33 @@ BLI_INLINE bool draw_select_do_call(DRWShadingGroup *shgroup, DRWCall *call, uin
 #endif
 }
 
+typedef struct DRWCallIterator {
+  int call_index;
+  DRWCallChunk *curr_chunk;
+} DRWCallIterator;
+
+static void draw_call_iter_begin(DRWCallIterator *iter, DRWShadingGroup *shgroup)
+{
+  iter->curr_chunk = shgroup->calls.first;
+  iter->call_index = 0;
+}
+
+static DRWCall *draw_call_iter_step(DRWCallIterator *iter)
+{
+  if (iter->curr_chunk) {
+    if (iter->call_index == iter->curr_chunk->chunk_len) {
+      iter->curr_chunk = iter->curr_chunk->next;
+      iter->call_index = 0;
+    }
+    if (iter->curr_chunk) {
+      if (iter->call_index < iter->curr_chunk->call_used) {
+        return iter->curr_chunk->calls + iter->call_index++;
+      }
+    }
+  }
+  return NULL;
+}
+
 static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
 {
   BLI_assert(shgroup->shader);
@@ -969,7 +996,12 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
     uint resource_chunk = 0;
     uint base_inst = 0;
     int callid = 0;
-    for (DRWCall *call = shgroup->calls.first; call; call = call->next) {
+
+    DRWCallIterator iter;
+    draw_call_iter_begin(&iter, shgroup);
+    DRWCall *call;
+
+    while ((call = draw_call_iter_step(&iter))) {
       DRWResourceHandle handle = call->handle;
 
       if (draw_call_is_culled(call, DST.view_active)) {
@@ -996,7 +1028,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
         }
         if (obinfos_loc != -1) {
           GPU_uniformbuffer_unbind(DST.vmempool->obinfos_ubo[resource_chunk]);
-          GPU_uniformbuffer_bind(DST.vmempool->obinfos_ubo[handle.chunk], 0);
+          GPU_uniformbuffer_bind(DST.vmempool->obinfos_ubo[handle.chunk], 1);
         }
         resource_chunk = handle.chunk;
       }



More information about the Bf-blender-cvs mailing list