[Bf-blender-cvs] [184b01c5099] tmp-drw-callbatching: DRW: Upload model matrices via UBO

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


Commit: 184b01c50998ed757b735008bcb585069c43e674
Author: Clément Foucault
Date:   Fri May 31 19:42:03 2019 +0200
Branches: tmp-drw-callbatching
https://developer.blender.org/rB184b01c50998ed757b735008bcb585069c43e674

DRW: Upload model matrices via UBO

The UBO is still not used so nothing should fail for now.

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

M	source/blender/blenlib/BLI_memblock.h
M	source/blender/blenlib/intern/BLI_memblock.c
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/editors/mesh/editmesh_intersect.c
M	source/blender/gpu/GPU_viewport.h
M	source/blender/gpu/intern/gpu_viewport.c

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

diff --git a/source/blender/blenlib/BLI_memblock.h b/source/blender/blenlib/BLI_memblock.h
index c5ef26ffb91..a4d665a4cfd 100644
--- a/source/blender/blenlib/BLI_memblock.h
+++ b/source/blender/blenlib/BLI_memblock.h
@@ -30,16 +30,21 @@ extern "C" {
 
 #include "BLI_compiler_attrs.h"
 
+#define BLI_MEM_BLOCK_CHUNK_SIZE (1 << 15) /* 32KiB */
+
 struct BLI_memblock;
 
 typedef struct BLI_memblock BLI_memblock;
 typedef void (*MemblockValFreeFP)(void *val);
 
-BLI_memblock *BLI_memblock_create(uint elem_size) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
+BLI_memblock *BLI_memblock_create_ex(uint elem_size,
+                                     uint chunk_size) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT;
 void *BLI_memblock_alloc(BLI_memblock *mblk) ATTR_MALLOC ATTR_WARN_UNUSED_RESULT ATTR_NONNULL(1);
 void BLI_memblock_clear(BLI_memblock *mblk, MemblockValFreeFP valfreefp) ATTR_NONNULL(1);
 void BLI_memblock_destroy(BLI_memblock *mblk, MemblockValFreeFP free_callback) ATTR_NONNULL(1);
 
+#define BLI_memblock_create(elem_size) BLI_memblock_create_ex(elem_size, BLI_MEM_BLOCK_CHUNK_SIZE)
+
 typedef struct BLI_memblock_iter {
   void **chunk_list;
   int cur_index;
@@ -53,6 +58,9 @@ typedef struct BLI_memblock_iter {
 void BLI_memblock_iternew(BLI_memblock *pool, BLI_memblock_iter *iter) ATTR_NONNULL();
 void *BLI_memblock_iterstep(BLI_memblock_iter *iter) ATTR_WARN_UNUSED_RESULT ATTR_NONNULL();
 
+void *BLI_memblock_elem_get(BLI_memblock *mblk, int chunk, int elem) ATTR_WARN_UNUSED_RESULT
+    ATTR_NONNULL();
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/source/blender/blenlib/intern/BLI_memblock.c b/source/blender/blenlib/intern/BLI_memblock.c
index f26860afe77..b357c5ed4eb 100644
--- a/source/blender/blenlib/intern/BLI_memblock.c
+++ b/source/blender/blenlib/intern/BLI_memblock.c
@@ -37,7 +37,6 @@
 
 #include "BLI_strict_flags.h" /* keep last */
 
-#define BLI_MEM_BLOCK_CHUNK_SIZE (1 << 15) /* 32KiB */
 #define CHUNK_LIST_SIZE 16
 
 struct BLI_memblock {
@@ -61,15 +60,15 @@ struct BLI_memblock {
   int chunk_len;
 };
 
-BLI_memblock *BLI_memblock_create(uint elem_size)
+BLI_memblock *BLI_memblock_create_ex(uint elem_size, uint chunk_size)
 {
-  BLI_assert(elem_size < BLI_MEM_BLOCK_CHUNK_SIZE);
+  BLI_assert(elem_size < chunk_size);
 
   BLI_memblock *mblk = MEM_mallocN(sizeof(BLI_memblock), "BLI_memblock");
   mblk->elem_size = (int)elem_size;
   mblk->elem_next = 0;
   mblk->elem_last = -1;
-  mblk->chunk_size = BLI_MEM_BLOCK_CHUNK_SIZE;
+  mblk->chunk_size = (int)chunk_size;
   mblk->chunk_len = CHUNK_LIST_SIZE;
   mblk->chunk_list = MEM_callocN(sizeof(void *) * (uint)mblk->chunk_len, "chunk list");
   mblk->chunk_list[0] = MEM_callocN((uint)mblk->chunk_size, "BLI_memblock chunk");
@@ -180,3 +179,11 @@ void *BLI_memblock_iterstep(BLI_memblock_iter *iter)
   }
   return ptr;
 }
+
+/* Direct access. elem is element index inside the chosen chunk. */
+void *BLI_memblock_elem_get(BLI_memblock *mblk, int chunk, int elem)
+{
+  BLI_assert(chunk < mblk->chunk_len);
+  BLI_assert(elem < (mblk->chunk_size / mblk->elem_size));
+  return (char *)(mblk->chunk_list[chunk]) + mblk->elem_size * elem;
+}
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index b0cea94e1ed..db492404584 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -613,6 +613,8 @@ static DRWCallState *draw_unit_state_create(void)
   culling->bsphere.radius = -1.0f;
   culling->user_data = NULL;
 
+  DRW_NEXT_RESOURCE_HANDLE(DST.resource_handle);
+
   return state;
 }
 
@@ -645,10 +647,12 @@ static void drw_viewport_var_init(void)
       DST.vmempool->states = BLI_memblock_create(sizeof(DRWCallState));
     }
     if (DST.vmempool->obmats == NULL) {
-      DST.vmempool->obmats = BLI_memblock_create(sizeof(DRWObjectMatrix));
+      uint chunk_len = sizeof(DRWObjectMatrix) * DRW_RESOURCE_CHUNK_LEN;
+      DST.vmempool->obmats = BLI_memblock_create_ex(sizeof(DRWObjectMatrix), chunk_len);
     }
     if (DST.vmempool->obinfos == NULL) {
-      DST.vmempool->obinfos = BLI_memblock_create(sizeof(DRWObjectInfos));
+      uint chunk_len = sizeof(DRWObjectInfos) * DRW_RESOURCE_CHUNK_LEN;
+      DST.vmempool->obinfos = BLI_memblock_create_ex(sizeof(DRWObjectInfos), chunk_len);
     }
     if (DST.vmempool->cullstates == NULL) {
       DST.vmempool->cullstates = BLI_memblock_create(sizeof(DRWCullingState));
@@ -669,7 +673,9 @@ static void drw_viewport_var_init(void)
       DST.vmempool->images = BLI_memblock_create(sizeof(GPUTexture *));
     }
 
-    /* Alloc default unit state */
+    DST.resource_handle.id = 0;
+    DST.resource_handle.chunk = 0;
+
     DST.unit_state = draw_unit_state_create();
 
     DST.idatalist = GPU_viewport_instance_data_list_get(DST.viewport);
@@ -2182,6 +2188,7 @@ void DRW_render_instance_buffer_finish(void)
   BLI_assert(!DST.buffer_finish_called && "DRW_render_instance_buffer_finish called twice!");
   DST.buffer_finish_called = true;
   DRW_instance_buffer_finish(DST.idatalist);
+  drw_resource_buffer_finish(DST.vmempool);
 }
 
 /**
diff --git a/source/blender/draw/intern/draw_manager.h b/source/blender/draw/intern/draw_manager.h
index bd8137b2ef7..e8ca365a480 100644
--- a/source/blender/draw/intern/draw_manager.h
+++ b/source/blender/draw/intern/draw_manager.h
@@ -105,6 +105,23 @@ typedef struct DRWCullingState {
   void *user_data;
 } DRWCullingState;
 
+/* We count on the fact that unsigned integers wrap around whe overflowing. */
+#define DRW_NEXT_RESOURCE_HANDLE(handle) \
+  do { \
+    if ((handle).id++ == 511) { \
+      (handle).chunk++; \
+    } \
+  } while (0)
+
+/* Minimum max UBO size is 64KiB. We take the largest
+ * UBO struct and alloc the max number. */
+#define DRW_RESOURCE_CHUNK_LEN ((1 << 16) / sizeof(DRWObjectMatrix))
+
+typedef struct DRWResourceHandle {
+  uint32_t id : 9;
+  uint32_t chunk : 23;
+} DRWResourceHandle;
+
 typedef struct DRWObjectMatrix {
   float model[4][4];
   float modelinverse[4][4];
@@ -287,16 +304,23 @@ typedef struct DRWManager {
   /* Cache generation */
   ViewportMemoryPool *vmempool;
   DRWInstanceDataList *idatalist;
-  DRWInstanceData *object_instance_data[MAX_INSTANCE_DATA_SIZE];
   /* Default Unit model matrix state without culling. */
   DRWCallState *unit_state;
   /* State of the object being evaluated if already allocated. */
   DRWCallState *ob_state;
+  /** Handle of current object resource in object resource arrays (DRWObjectMatrices/Infos). */
+  DRWResourceHandle resource_handle;
+
+  /** Dupli state. NULL if not dupli. */
   struct DupliObject *dupli_source;
   struct Object *dupli_parent;
   struct Object *dupli_origin;
+  /** Ghash containing original objects. */
   struct GHash *dupli_ghash;
-  void **dupli_datas; /* Array of dupli_data (one for each enabled engine) to handle duplis. */
+  /** TODO(fclem) try to remove usage of this. */
+  DRWInstanceData *object_instance_data[MAX_INSTANCE_DATA_SIZE];
+  /* Array of dupli_data (one for each enabled engine) to handle duplis. */
+  void **dupli_datas;
 
   /* Rendering state */
   GPUShader *shader;
@@ -402,6 +426,8 @@ void drw_debug_init(void);
 void drw_batch_cache_validate(Object *ob);
 void drw_batch_cache_generate_requested(struct Object *ob);
 
+void drw_resource_buffer_finish(ViewportMemoryPool *vmempool);
+
 /* Procedural Drawing */
 GPUBatch *drw_cache_procedural_points_get(void);
 GPUBatch *drw_cache_procedural_lines_get(void);
diff --git a/source/blender/draw/intern/draw_manager_data.c b/source/blender/draw/intern/draw_manager_data.c
index 5b956fbdf7d..bad6971f208 100644
--- a/source/blender/draw/intern/draw_manager_data.c
+++ b/source/blender/draw/intern/draw_manager_data.c
@@ -66,6 +66,49 @@ void DRW_uniformbuffer_free(GPUUniformBuffer *ubo)
   GPU_uniformbuffer_free(ubo);
 }
 
+void drw_resource_buffer_finish(ViewportMemoryPool *vmempool)
+{
+  int ubo_len = 1 + DST.resource_handle.chunk - ((DST.resource_handle.id == 0) ? 1 : 0);
+  size_t list_size = sizeof(GPUUniformBuffer *) * ubo_len;
+
+  /* TODO find a better system. currently a lot of obinfos UBO are going to be unused
+   * if not rendering with Eevee. */
+
+  if (vmempool->matrices_ubo == NULL) {
+    vmempool->matrices_ubo = MEM_callocN(list_size, __func__);
+    vmempool->obinfos_ubo = MEM_callocN(list_size, __func__);
+    vmempool->ubo_len = ubo_len;
+  }
+
+  /* Remove unecessary buffers */
+  for (int i = ubo_len; i < vmempool->ubo_len; i++) {
+    GPU_uniformbuffer_free(vmempool->matrices_ubo[i]);
+    GPU_uniformbuffer_free(vmempool->obinfos_ubo[i]);
+  }
+
+  if (ubo_len != vmempool->ubo_len) {
+    vmempool->matrices_ubo = MEM_recallocN(vmempool->matrices_ubo, list_size);
+    vmempool->obinfos_ubo = MEM_recallocN(vmempool->obinfos_ubo, list_size);
+    vmempool->ubo_len = ubo_len;
+  }
+
+  /* Create/Update buffers. */
+  for (int i = 0; i < ubo_len; i++) {
+    void *data_obmat = BLI_memblock_elem_get(vmempool->obmats, i, 0);
+    void *data_infos = BLI_memblock_elem_get(vmempool->obinfos, i, 0);
+    if (vmempool->matrices_ubo[i] == NULL) {
+      vmempool->matrices_ubo[i] = GPU_uniformbuffer_create(
+          sizeof(DRWObjectMatrix) * DRW_RESOURCE_CHUNK_LEN, data_obmat, NULL);
+      vmempool->obinfos_ubo[i] = GPU_uniformbuffer_create(
+          sizeof(DRWObjectInfos) * DRW_RESOURCE_CHUNK_LEN, data_infos, NULL);
+    }
+    else {
+      GPU_uniformbuffer_update(vmempool->matrices_ubo[i], data_obmat);
+      GPU_uniformbuffer_update(vmempool->obinfos_ubo[i], data_infos);
+    }
+  }
+}
+
 /** \} */
 
 /* -------------------------------------------------------------------- */
@@ -354,7 +397,7 @@ static void drw_call_calc_orco(Object *ob, float (*r_orcofacs)[4])
 static void drw_call_obinfos_create(DRWCallState *state, Object *ob)
 {
   BLI_assert(ob);
-  DRWObjectInfos *ob_infos = state->ob_infos = BLI_memblock_alloc(DST.vmempool->obinfos);
+  DRWObjectInfos *ob_infos = state->ob_infos;
   /* Index. */
   ob_infos->ob_index = ob->index;
   /* Orco factors. */
@@ -372,7 +415,7 @@ static void drw_call_obinfos_create(DRWCallState *state, Object *ob)
 
 static void drw_call_culling_create(DRWCallState *state, Object *ob)
 {
-  DRWCullingState *cull = state->culling = BLI_memblock_alloc(DST

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list