[Bf-blender-cvs] [b847861b6cb] greasepencil-refactor: GPencil: Refactor: Reuse GPENCIL_MaterialPool across multiple objects

Clément Foucault noreply at git.blender.org
Sun Jan 19 02:13:04 CET 2020


Commit: b847861b6cb26be89a451ab87e50ccbd4629ea1d
Author: Clément Foucault
Date:   Sun Jan 19 02:12:50 2020 +0100
Branches: greasepencil-refactor
https://developer.blender.org/rBb847861b6cb26be89a451ab87e50ccbd4629ea1d

GPencil: Refactor: Reuse GPENCIL_MaterialPool across multiple objects

This minimize the number of UBO we create and the number of UBO switching
we have to do to render each objects.

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

M	source/blender/draw/engines/gpencil/gpencil_draw_data.c
M	source/blender/draw/engines/gpencil/gpencil_engine.c
M	source/blender/draw/engines/gpencil/gpencil_engine.h
M	source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
M	source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl
M	source/blender/makesdna/DNA_gpencil_types.h

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

diff --git a/source/blender/draw/engines/gpencil/gpencil_draw_data.c b/source/blender/draw/engines/gpencil/gpencil_draw_data.c
index 70404bcbf6d..ef4efc40ecc 100644
--- a/source/blender/draw/engines/gpencil/gpencil_draw_data.c
+++ b/source/blender/draw/engines/gpencil/gpencil_draw_data.c
@@ -53,6 +53,7 @@ static GPENCIL_MaterialPool *gpencil_material_pool_add(GPENCIL_PrivateData *pd)
 {
   GPENCIL_MaterialPool *matpool = BLI_memblock_alloc(pd->gp_material_pool);
   matpool->next = NULL;
+  matpool->used_count = 0;
   if (matpool->ubo == NULL) {
     matpool->ubo = GPU_uniformbuffer_create(sizeof(matpool->mat_data), NULL, NULL);
   }
@@ -232,9 +233,17 @@ GPENCIL_MaterialPool *gpencil_material_pool_create(GPENCIL_PrivateData *pd, Obje
 {
   GPENCIL_MaterialPool *matpool = pd->last_material_pool;
 
-  /* TODO reuse matpool for objects with small material count. */
-  if (true) {
+  int mat_len = max_ii(1, ob->totcol);
+
+  bool reuse_matpool = matpool && ((matpool->used_count + mat_len) <= GP_MATERIAL_BUFFER_LEN);
+
+  if (reuse_matpool) {
+    /* Share the matpool with other objects. Return offset to first material. */
+    *ofs = matpool->used_count;
+  }
+  else {
     matpool = gpencil_material_pool_add(pd);
+    *ofs = 0;
   }
 
   /* Force vertex color in solid mode with vertex paint mode. Same behavior as meshes. */
@@ -244,12 +253,13 @@ GPENCIL_MaterialPool *gpencil_material_pool_create(GPENCIL_PrivateData *pd, Obje
                        pd->v3d_color_type;
 
   GPENCIL_MaterialPool *pool = matpool;
-  for (int i = 0; i < max_ii(1, ob->totcol); i++) {
-    int mat_id = (i % GP_MATERIAL_BUFFER_LEN);
-    if ((i > 0) && (mat_id == 0)) {
+  for (int i = 0; i < mat_len; i++) {
+    if ((i > 0) && (pool->used_count == GP_MATERIAL_BUFFER_LEN)) {
       pool->next = gpencil_material_pool_add(pd);
       pool = pool->next;
     }
+    int mat_id = pool->used_count++;
+
     gpMaterial *mat_data = &pool->mat_data[mat_id];
     MaterialGPencilStyle *gp_style = BKE_material_gpencil_settings_get(ob, i + 1);
 
@@ -337,8 +347,6 @@ GPENCIL_MaterialPool *gpencil_material_pool_create(GPENCIL_PrivateData *pd, Obje
     }
   }
 
-  *ofs = 0;
-
   return matpool;
 }
 
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.c b/source/blender/draw/engines/gpencil/gpencil_engine.c
index f1438e45755..c91c0af002f 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.c
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.c
@@ -452,6 +452,7 @@ static void gp_layer_cache_populate(bGPDlayer *gpl,
   DRW_shgroup_uniform_texture(iter->grp, "gpFillTexture", iter->tex_fill);
   DRW_shgroup_uniform_texture(iter->grp, "gpStrokeTexture", iter->tex_stroke);
   DRW_shgroup_uniform_texture(iter->grp, "gpSceneDepthTexture", iter->pd->scene_depth_tx);
+  DRW_shgroup_uniform_int_copy(iter->grp, "gpMaterialOffset", iter->mat_ofs);
   DRW_shgroup_uniform_bool_copy(iter->grp, "strokeOrder3d", is_stroke_order_3d);
   DRW_shgroup_uniform_vec3_copy(iter->grp, "gpNormal", iter->tgp_ob->plane_normal);
   DRW_shgroup_uniform_vec2_copy(iter->grp, "sizeViewportInv", DRW_viewport_invert_size_get());
diff --git a/source/blender/draw/engines/gpencil/gpencil_engine.h b/source/blender/draw/engines/gpencil/gpencil_engine.h
index 71b91e042d2..558e3c3fbeb 100644
--- a/source/blender/draw/engines/gpencil/gpencil_engine.h
+++ b/source/blender/draw/engines/gpencil/gpencil_engine.h
@@ -111,6 +111,8 @@ typedef struct GPENCIL_MaterialPool {
   /* Texture per material. NULL means none. */
   struct GPUTexture *tex_fill[GP_MATERIAL_BUFFER_LEN];
   struct GPUTexture *tex_stroke[GP_MATERIAL_BUFFER_LEN];
+  /* Number of material used in this pool. */
+  int used_count;
 } GPENCIL_MaterialPool;
 
 typedef struct GPENCIL_LightPool {
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
index 8062c5c26bb..ed44d53140a 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_common_lib.glsl
@@ -180,13 +180,15 @@ float stroke_round_cap_mask(vec2 p1, vec2 p2, float thickness)
 uniform vec2 sizeViewport;
 uniform vec2 sizeViewportInv;
 
-#ifdef GPU_VERTEX_SHADER
-
 /* Per Object */
 uniform bool strokeOrder3d;
+uniform float gpMaterialOffset;
 uniform float thicknessScale;
 uniform float thicknessWorldScale;
-#  define thicknessIsScreenSpace (thicknessWorldScale < 0.0)
+#define thicknessIsScreenSpace (thicknessWorldScale < 0.0)
+#define MATERIAL(m) materials[m]
+
+#ifdef GPU_VERTEX_SHADER
 
 /* Per Layer */
 uniform float thicknessOffset;
@@ -321,8 +323,8 @@ void stroke_vertex()
 
 #  ifdef GP_MATERIAL_BUFFER_LEN
   if (m != -1.0) {
-    is_dot = GP_FLAG_TEST(materials[m].flag, GP_STROKE_ALIGNMENT);
-    is_squares = !GP_FLAG_TEST(materials[m].flag, GP_STROKE_DOTS);
+    is_dot = GP_FLAG_TEST(MATERIAL(m).flag, GP_STROKE_ALIGNMENT);
+    is_squares = !GP_FLAG_TEST(MATERIAL(m).flag, GP_STROKE_DOTS);
   }
 #  endif
 
@@ -367,7 +369,7 @@ void stroke_vertex()
 
   if (is_dot) {
 #  ifdef GP_MATERIAL_BUFFER_LEN
-    int alignement = materials[m].flag & GP_STROKE_ALIGNMENT;
+    int alignement = MATERIAL(m).flag & GP_STROKE_ALIGNMENT;
 #  endif
 
     vec2 x_axis;
@@ -428,19 +430,19 @@ void stroke_vertex()
 
     finalUvs.x = (use_curr) ? uv1.z : uv2.z;
 #  ifdef GP_MATERIAL_BUFFER_LEN
-    finalUvs.x *= materials[m].stroke_u_scale;
+    finalUvs.x *= MATERIAL(m).stroke_u_scale;
 #  endif
   }
 
 #  ifdef GP_MATERIAL_BUFFER_LEN
   vec4 vert_col = (use_curr) ? col1 : col2;
   float vert_strength = abs((use_curr) ? strength1 : strength2);
-  vec4 stroke_col = materials[m].stroke_color;
-  float mix_tex = materials[m].stroke_texture_mix;
+  vec4 stroke_col = MATERIAL(m).stroke_color;
+  float mix_tex = MATERIAL(m).stroke_texture_mix;
 
   color_output(stroke_col, vert_col, vert_strength, mix_tex);
 
-  matFlag = materials[m].flag & ~GP_FILL_FLAGS;
+  matFlag = MATERIAL(m).flag & ~GP_FILL_FLAGS;
 #  endif
 
   if (strokeOrder3d) {
@@ -448,7 +450,7 @@ void stroke_vertex()
     depth = -1.0;
   }
 #  ifdef GP_MATERIAL_BUFFER_LEN
-  else if (GP_FLAG_TEST(materials[m].flag, GP_STROKE_OVERLAP)) {
+  else if (GP_FLAG_TEST(MATERIAL(m).flag, GP_STROKE_OVERLAP)) {
     /* Use the index of the point as depth.
      * This means the stroke can overlap itself. */
     depth = (point_id1 + 1.0) * 0.0000002;
@@ -475,21 +477,21 @@ void fill_vertex()
 #  ifdef GP_MATERIAL_BUFFER_LEN
   int m = int(ma1.x);
 
-  vec4 fill_col = materials[m].fill_color;
-  float mix_tex = materials[m].fill_texture_mix;
+  vec4 fill_col = MATERIAL(m).fill_color;
+  float mix_tex = MATERIAL(m).fill_texture_mix;
 
   /* Special case: We don't modulate alpha in gradient mode. */
-  if (GP_FLAG_TEST(materials[m].flag, GP_FILL_GRADIENT_USE)) {
+  if (GP_FLAG_TEST(MATERIAL(m).flag, GP_FILL_GRADIENT_USE)) {
     fill_col.a = 1.0;
   }
 
   color_output(fill_col, fcol1, 1.0, mix_tex);
 
-  matFlag = materials[m].flag & GP_FILL_FLAGS;
+  matFlag = MATERIAL(m).flag & GP_FILL_FLAGS;
   matFlag |= m << GP_MATID_SHIFT;
 
-  vec2 loc = materials[m].fill_uv_offset.xy;
-  mat2x2 rot_scale = mat2x2(materials[m].fill_uv_rot_scale.xy, materials[m].fill_uv_rot_scale.zw);
+  vec2 loc = MATERIAL(m).fill_uv_offset.xy;
+  mat2x2 rot_scale = mat2x2(MATERIAL(m).fill_uv_rot_scale.xy, MATERIAL(m).fill_uv_rot_scale.zw);
   finalUvs = rot_scale * uv1.xy + loc;
 #  endif
 
diff --git a/source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl b/source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl
index 1d41533fd47..bca922ec018 100644
--- a/source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl
+++ b/source/blender/draw/engines/gpencil/shaders/gpencil_frag.glsl
@@ -72,7 +72,7 @@ void main()
     bool radial = GP_FLAG_TEST(matFlag, GP_FILL_GRADIENT_RADIAL);
     float fac = clamp(radial ? length(finalUvs * 2.0 - 1.0) : finalUvs.x, 0.0, 1.0);
     int matid = matFlag >> GP_MATID_SHIFT;
-    col = mix(materials[matid].fill_color, materials[matid].fill_mix_color, fac);
+    col = mix(MATERIAL(matid).fill_color, MATERIAL(matid).fill_mix_color, fac);
   }
   else /* SOLID */ {
     col = vec4(1.0);
diff --git a/source/blender/makesdna/DNA_gpencil_types.h b/source/blender/makesdna/DNA_gpencil_types.h
index fca7d4bdfd4..dd84e5ca193 100644
--- a/source/blender/makesdna/DNA_gpencil_types.h
+++ b/source/blender/makesdna/DNA_gpencil_types.h
@@ -36,9 +36,7 @@ struct MDeformVert;
 #define GP_DEFAULT_GRID_LINES 4
 #define GP_MAX_INPUT_SAMPLES 10
 
-/* TODO(fclem) grow this number back when grouping different objects' material together
- * is implemented. */
-#define GP_MATERIAL_BUFFER_LEN 16
+#define GP_MATERIAL_BUFFER_LEN 256
 
 /* ***************************************** */
 /* GP Stroke Points */



More information about the Bf-blender-cvs mailing list