DRW: Change Procedural function to use a GPUBatch
authorClément Foucault <foucault.clem@gmail.com>
Sat, 11 May 2019 15:45:20 +0000 (17:45 +0200)
committerClément Foucault <foucault.clem@gmail.com>
Tue, 14 May 2019 08:57:03 +0000 (10:57 +0200)
This is in order to have VAO handled by thoses batches instead of using a
common VAO. Even if the VAO has no importance in these case using a batch
will help when transitioning to Vulkan.

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

index e9896261004ac6c57379aa616c0a6d904feba432..c40e977234082f6f8fbf2d04197ec5ce86f6c8f3 100644 (file)
@@ -46,6 +46,9 @@
 
 /* Batch's only (free'd as an array) */
 static struct DRWShapeCache {
+  GPUBatch *drw_procedural_verts;
+  GPUBatch *drw_procedural_lines;
+  GPUBatch *drw_procedural_tris;
   GPUBatch *drw_single_vertice;
   GPUBatch *drw_cursor;
   GPUBatch *drw_cursor_only_circle;
@@ -137,6 +140,54 @@ void DRW_shape_cache_reset(void)
   }
 }
 
+/* -------------------------------------------------------------------- */
+/** \name Procedural Batches
+ * \{ */
+
+GPUBatch *drw_cache_procedural_points_get(void)
+{
+  if (!SHC.drw_procedural_verts) {
+    /* TODO(fclem) get rid of this dummy VBO. */
+    GPUVertFormat format = {0};
+    GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+    GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+    GPU_vertbuf_data_alloc(vbo, 1);
+
+    SHC.drw_procedural_verts = GPU_batch_create_ex(GPU_PRIM_POINTS, vbo, NULL, GPU_BATCH_OWNS_VBO);
+  }
+  return SHC.drw_procedural_verts;
+}
+
+GPUBatch *drw_cache_procedural_lines_get(void)
+{
+  if (!SHC.drw_procedural_lines) {
+    /* TODO(fclem) get rid of this dummy VBO. */
+    GPUVertFormat format = {0};
+    GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+    GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+    GPU_vertbuf_data_alloc(vbo, 1);
+
+    SHC.drw_procedural_lines = GPU_batch_create_ex(GPU_PRIM_LINES, vbo, NULL, GPU_BATCH_OWNS_VBO);
+  }
+  return SHC.drw_procedural_lines;
+}
+
+GPUBatch *drw_cache_procedural_triangles_get(void)
+{
+  if (!SHC.drw_procedural_tris) {
+    /* TODO(fclem) get rid of this dummy VBO. */
+    GPUVertFormat format = {0};
+    GPU_vertformat_attr_add(&format, "dummy", GPU_COMP_F32, 1, GPU_FETCH_FLOAT);
+    GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format);
+    GPU_vertbuf_data_alloc(vbo, 1);
+
+    SHC.drw_procedural_tris = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, NULL, GPU_BATCH_OWNS_VBO);
+  }
+  return SHC.drw_procedural_tris;
+}
+
+/** \} */
+
 /* -------------------------------------------------------------------- */
 /** \name Helper functions
  * \{ */
index ae765775929fd0f95e02baae7c20a7c79c59c4b5..8dff65175ecddb1febda7e5cb25ad3b5e2e06197 100644 (file)
@@ -152,8 +152,8 @@ typedef struct DRWCall {
       uint count;
     } instances;
     struct { /* type == DRW_CALL_PROCEDURAL */
+      GPUBatch *geometry;
       uint vert_count;
-      GPUPrimType prim_type;
     } procedural;
   };
 
@@ -438,6 +438,11 @@ void drw_debug_init(void);
 void drw_batch_cache_validate(Object *ob);
 void drw_batch_cache_generate_requested(struct Object *ob);
 
+/* Procedural Drawing */
+GPUBatch *drw_cache_procedural_points_get(void);
+GPUBatch *drw_cache_procedural_lines_get(void);
+GPUBatch *drw_cache_procedural_triangles_get(void);
+
 extern struct GPUVertFormat *g_pos_format;
 
 #endif /* __DRAW_MANAGER_H__ */
index 75dcf6e779698a296ef859a471da26011745f060..3a6a7300ceab94cdef496c9cd83e41bf7d09beb1 100644 (file)
@@ -487,19 +487,18 @@ void DRW_shgroup_call_range_add(
 }
 
 static void drw_shgroup_call_procedural_add_ex(DRWShadingGroup *shgroup,
-                                               GPUPrimType prim_type,
+                                               GPUBatch *geom,
                                                uint vert_count,
-                                               float (*obmat)[4],
-                                               Object *ob)
+                                               float (*obmat)[4])
 {
   BLI_assert(ELEM(shgroup->type, DRW_SHG_NORMAL, DRW_SHG_FEEDBACK_TRANSFORM));
 
   DRWCall *call = BLI_memblock_alloc(DST.vmempool->calls);
   BLI_LINKS_APPEND(&shgroup->calls, call);
 
-  call->state = drw_call_state_object(shgroup, ob ? ob->obmat : obmat, ob);
+  call->state = drw_call_state_object(shgroup, obmat, NULL);
   call->type = DRW_CALL_PROCEDURAL;
-  call->procedural.prim_type = prim_type;
+  call->procedural.geometry = geom;
   call->procedural.vert_count = vert_count;
 #ifdef USE_GPU_SELECT
   call->select_id = DST.select_id;
@@ -510,21 +509,24 @@ void DRW_shgroup_call_procedural_points_add(DRWShadingGroup *shgroup,
                                             uint point_len,
                                             float (*obmat)[4])
 {
-  drw_shgroup_call_procedural_add_ex(shgroup, GPU_PRIM_POINTS, point_len, obmat, NULL);
+  struct GPUBatch *geom = drw_cache_procedural_points_get();
+  drw_shgroup_call_procedural_add_ex(shgroup, geom, point_len, obmat);
 }
 
 void DRW_shgroup_call_procedural_lines_add(DRWShadingGroup *shgroup,
                                            uint line_count,
                                            float (*obmat)[4])
 {
-  drw_shgroup_call_procedural_add_ex(shgroup, GPU_PRIM_LINES, line_count * 2, obmat, NULL);
+  struct GPUBatch *geom = drw_cache_procedural_lines_get();
+  drw_shgroup_call_procedural_add_ex(shgroup, geom, line_count * 2, obmat);
 }
 
 void DRW_shgroup_call_procedural_triangles_add(DRWShadingGroup *shgroup,
                                                uint tria_count,
                                                float (*obmat)[4])
 {
-  drw_shgroup_call_procedural_add_ex(shgroup, GPU_PRIM_TRIS, tria_count * 3, obmat, NULL);
+  struct GPUBatch *geom = drw_cache_procedural_triangles_get();
+  drw_shgroup_call_procedural_add_ex(shgroup, geom, tria_count * 3, obmat);
 }
 
 /* These calls can be culled and are optimized for redraw */
index ef50e9d59101b08081d66475d0e733922eb60a80..b9d49df794759ec9f63d03b311bd86c9faccbe3b 100644 (file)
@@ -858,18 +858,9 @@ static void draw_geometry_prepare(DRWShadingGroup *shgroup, DRWCall *call)
   }
 }
 
-static void draw_geometry_execute_ex(
+static void draw_geometry_execute(
     DRWShadingGroup *shgroup, GPUBatch *geom, uint start, uint count, bool draw_instance)
 {
-  /* Special case: empty drawcall, placement is done via shader, don't bind anything. */
-  /* TODO use DRW_CALL_PROCEDURAL instead */
-  if (geom == NULL) {
-    BLI_assert(shgroup->type == DRW_SHG_TRIANGLE_BATCH); /* Add other type if needed. */
-    /* Shader is already bound. */
-    GPU_draw_primitive(GPU_PRIM_TRIS, count);
-    return;
-  }
-
   /* step 2 : bind vertex array & draw */
   GPU_batch_program_set_no_use(
       geom, GPU_shader_get_program(shgroup->shader), GPU_shader_get_interface(shgroup->shader));
@@ -881,11 +872,6 @@ static void draw_geometry_execute_ex(
   geom->program_in_use = false; /* XXX hacking gawain */
 }
 
-static void draw_geometry_execute(DRWShadingGroup *shgroup, GPUBatch *geom)
-{
-  draw_geometry_execute_ex(shgroup, geom, 0, 0, false);
-}
-
 enum {
   BIND_NONE = 0,
   BIND_TEMP = 1,    /* Release slot after this shading group. */
@@ -1223,7 +1209,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
         if (shgroup->instance_geom != NULL) {
           GPU_SELECT_LOAD_IF_PICKSEL(shgroup->override_selectid);
           draw_geometry_prepare(shgroup, NULL);
-          draw_geometry_execute_ex(shgroup, shgroup->instance_geom, 0, 0, true);
+          draw_geometry_execute(shgroup, shgroup->instance_geom, 0, 0, true);
         }
       }
       else {
@@ -1231,7 +1217,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
           uint count, start;
           draw_geometry_prepare(shgroup, NULL);
           GPU_SELECT_LOAD_IF_PICKSEL_LIST (shgroup, start, count) {
-            draw_geometry_execute_ex(shgroup, shgroup->instance_geom, start, count, true);
+            draw_geometry_execute(shgroup, shgroup->instance_geom, start, count, true);
           }
           GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(start, count);
         }
@@ -1243,7 +1229,7 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
         uint count, start;
         draw_geometry_prepare(shgroup, NULL);
         GPU_SELECT_LOAD_IF_PICKSEL_LIST (shgroup, start, count) {
-          draw_geometry_execute_ex(shgroup, shgroup->batch_geom, start, count, false);
+          draw_geometry_execute(shgroup, shgroup->batch_geom, start, count, false);
         }
         GPU_SELECT_LOAD_IF_PICKSEL_LIST_END(start, count);
       }
@@ -1281,18 +1267,18 @@ static void draw_shgroup(DRWShadingGroup *shgroup, DRWState pass_state)
 
       switch (call->type) {
         case DRW_CALL_SINGLE:
-          draw_geometry_execute(shgroup, call->single.geometry);
+          draw_geometry_execute(shgroup, call->single.geometry, 0, 0, false);
           break;
         case DRW_CALL_RANGE:
-          draw_geometry_execute_ex(
+          draw_geometry_execute(
               shgroup, call->range.geometry, call->range.start, call->range.count, false);
           break;
         case DRW_CALL_INSTANCES:
-          draw_geometry_execute_ex(
-              shgroup, call->instances.geometry, 0, call->instances.count, true);
+          draw_geometry_execute(shgroup, call->instances.geometry, 0, call->instances.count, true);
           break;
         case DRW_CALL_PROCEDURAL:
-          GPU_draw_primitive(call->procedural.prim_type, call->procedural.vert_count);
+          draw_geometry_execute(
+              shgroup, call->procedural.geometry, 0, call->procedural.vert_count, false);
           break;
         default:
           BLI_assert(0);