GPUVertexFormat: Reduce size of structs
authorClément Foucault <foucault.clem@gmail.com>
Mon, 13 May 2019 21:31:43 +0000 (23:31 +0200)
committerClément Foucault <foucault.clem@gmail.com>
Tue, 14 May 2019 08:57:04 +0000 (10:57 +0200)
With this patch, the size of GPUVertFormat goes from 1240 to 388.

source/blender/draw/intern/draw_cache_impl_displist.c
source/blender/gpu/GPU_vertex_buffer.h
source/blender/gpu/GPU_vertex_format.h
source/blender/gpu/intern/gpu_attr_binding.c
source/blender/gpu/intern/gpu_batch.c
source/blender/gpu/intern/gpu_vertex_format.c

index 6825b52963b27b8cba5deb8f5a9e4c0d2ab5a3a8..d1c214c2aa6c2b4e679fd30c9289e9eab69232e7 100644 (file)
@@ -404,7 +404,6 @@ void DRW_displist_vertbuf_create_loop_pos_and_nor_and_uv(ListBase *lb,
         &format_pos_nor, "pos", GPU_COMP_F32, 3, GPU_FETCH_FLOAT);
     attr_id.nor = GPU_vertformat_attr_add(
         &format_pos_nor, "nor", GPU_COMP_I10, 3, GPU_FETCH_INT_TO_FLOAT_UNIT);
-    GPU_vertformat_triple_load(&format_pos_nor);
     /* UVs are in [0..1] range. We can compress them. */
     attr_id.uv = GPU_vertformat_attr_add(
         &format_uv, "u", GPU_COMP_I16, 2, GPU_FETCH_INT_TO_FLOAT_UNIT);
index a5a5e3d42967013e083008ac69546a1ec29646d1..3e178e193dc2df1035826f8e20af58a5783e7d63 100644 (file)
@@ -48,12 +48,17 @@ typedef enum {
 
 typedef struct GPUVertBuf {
   GPUVertFormat format;
-  uint vertex_len;   /* number of verts we want to draw */
-  uint vertex_alloc; /* number of verts data */
-  bool dirty;
+  /** Number of verts we want to draw. */
+  uint vertex_len;
+  /** Number of verts data. */
+  uint vertex_alloc;
+  /** 0 indicates not yet allocated. */
+  uint32_t vbo_id;
+  /** Usage hint for GL optimisation. */
+  uint usage : 2;
+  /** Data has been touched and need to be reuploaded to GPU. */
+  uint dirty : 1;
   unsigned char *data; /* NULL indicates data in VRAM (unmapped) */
-  uint32_t vbo_id;     /* 0 indicates not yet allocated */
-  GPUUsageType usage;  /* usage hint for GL optimisation */
 } GPUVertBuf;
 
 GPUVertBuf *GPU_vertbuf_create(GPUUsageType);
index 7f1934431cfd3a584d22a4b8e7e5d201f881a271..74fad51f571e381ed36c240dcb0c372ac1ee75e2 100644 (file)
@@ -27,6 +27,7 @@
 #define __GPU_VERTEX_FORMAT_H__
 
 #include "GPU_common.h"
+#include "BLI_compiler_compat.h"
 
 #define GPU_VERT_ATTR_MAX_LEN 16
 #define GPU_VERT_ATTR_MAX_NAMES 4
@@ -54,28 +55,35 @@ typedef enum {
 } GPUVertFetchMode;
 
 typedef struct GPUVertAttr {
-  GPUVertFetchMode fetch_mode;
-  GPUVertCompType comp_type;
+  GPUVertFetchMode fetch_mode : 2;
+  GPUVertCompType comp_type : 3;
+  /* 1 to 4 or 8 or 12 or 16 */
+  uint comp_len : 5;
+  /* size in bytes, 1 to 64 */
+  uint sz : 7;
+  /* from beginning of vertex, in bytes */
+  uint offset : 11;
+  /* up to GPU_VERT_ATTR_MAX_NAMES */
+  uint name_len : 3;
   uint gl_comp_type;
-  uint comp_len; /* 1 to 4 or 8 or 12 or 16 */
-  uint sz;       /* size in bytes, 1 to 64 */
-  uint offset;   /* from beginning of vertex, in bytes */
-  uint name_len; /* up to GPU_VERT_ATTR_MAX_NAMES */
-  const char *name[GPU_VERT_ATTR_MAX_NAMES];
+  /* -- 8 Bytes -- */
+  uchar names[GPU_VERT_ATTR_MAX_NAMES];
 } GPUVertAttr;
 
 typedef struct GPUVertFormat {
   /** 0 to 16 (GPU_VERT_ATTR_MAX_LEN). */
-  uint attr_len;
+  uint attr_len : 5;
   /** Total count of active vertex attribute. */
-  uint name_len;
-  /** Stride in bytes, 1 to 256. */
-  uint stride;
-  uint name_offset;
-  bool packed;
-  char names[GPU_VERT_ATTR_NAMES_BUF_LEN];
-  /** TODO: variable-size array */
+  uint name_len : 5;
+  /** Stride in bytes, 1 to 1024. */
+  uint stride : 11;
+  /** Has the format been packed. */
+  uint packed : 1;
+  /** Current offset in names[]. */
+  uint name_offset : 8;
+
   GPUVertAttr attrs[GPU_VERT_ATTR_MAX_LEN];
+  char names[GPU_VERT_ATTR_NAMES_BUF_LEN];
 } GPUVertFormat;
 
 struct GPUShaderInterface;
@@ -88,18 +96,15 @@ void GPU_vertformat_from_interface(GPUVertFormat *format,
 uint GPU_vertformat_attr_add(
     GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode);
 void GPU_vertformat_alias_add(GPUVertFormat *, const char *alias);
+
 int GPU_vertformat_attr_id_get(const GPUVertFormat *, const char *name);
 
-/**
- * This makes the "virtual" attributes with suffixes "0", "1", "2"
- * to access triangle data in the vertex shader.
- *
- * IMPORTANT:
- * - Call this before creating the vertex buffer and after creating all attributes
- * - Only first vertex out of 3 has the correct information.
- *   Use flat output with #GL_FIRST_VERTEX_CONVENTION.
- */
-void GPU_vertformat_triple_load(GPUVertFormat *format);
+BLI_INLINE const char *GPU_vertformat_attr_name_get(const GPUVertFormat *format,
+                                                    const GPUVertAttr *attr,
+                                                    uint n_idx)
+{
+  return format->names + attr->names[n_idx];
+}
 
 /* format conversion */
 
index e280b77f6614cdd8f4e0969c77ae828a13619061..802b15a0c4eade8d7e58214f3a87cb4adbf14ea2 100644 (file)
@@ -70,7 +70,8 @@ void get_attr_locations(const GPUVertFormat *format,
   for (uint a_idx = 0; a_idx < format->attr_len; ++a_idx) {
     const GPUVertAttr *a = &format->attrs[a_idx];
     for (uint n_idx = 0; n_idx < a->name_len; ++n_idx) {
-      const GPUShaderInput *input = GPU_shaderinterface_attr(shaderface, a->name[n_idx]);
+      const char *name = GPU_vertformat_attr_name_get(format, a, n_idx);
+      const GPUShaderInput *input = GPU_shaderinterface_attr(shaderface, name);
 #if TRUST_NO_ONE
       assert(input != NULL);
       /* TODO: make this a recoverable runtime error?
index 010f57bf5f81bccfdc36c94124f8e6bb28057a33..45697befe509807f9e56e5d6c739bbc98143e90f 100644 (file)
@@ -370,7 +370,8 @@ static void create_bindings(GPUVertBuf *verts,
     const GLvoid *pointer = (const GLubyte *)0 + a->offset + v_first * stride;
 
     for (uint n_idx = 0; n_idx < a->name_len; ++n_idx) {
-      const GPUShaderInput *input = GPU_shaderinterface_attr(interface, a->name[n_idx]);
+      const char *name = GPU_vertformat_attr_name_get(format, a, n_idx);
+      const GPUShaderInput *input = GPU_shaderinterface_attr(interface, name);
 
       if (input == NULL) {
         continue;
index 388773afbbcae5679f7ad38c66cbda0b994e24e0..82ae7dd4021ad460836db650dcfc4ae91980ee9e 100644 (file)
@@ -58,12 +58,6 @@ void GPU_vertformat_copy(GPUVertFormat *dest, const GPUVertFormat *src)
 {
   /* copy regular struct fields */
   memcpy(dest, src, sizeof(GPUVertFormat));
-
-  for (uint i = 0; i < dest->attr_len; i++) {
-    for (uint j = 0; j < dest->attrs[i].name_len; j++) {
-      dest->attrs[i].name[j] = (char *)dest + (src->attrs[i].name[j] - ((char *)src));
-    }
-  }
 }
 
 static GLenum convert_comp_type_to_gl(GPUVertCompType type)
@@ -122,32 +116,20 @@ uint vertex_buffer_size(const GPUVertFormat *format, uint vertex_len)
   return format->stride * vertex_len;
 }
 
-static const char *copy_attr_name(GPUVertFormat *format, const char *name, const char *suffix)
+static const char copy_attr_name(GPUVertFormat *format, const char *name)
 {
   /* strncpy does 110% of what we need; let's do exactly 100% */
-  char *name_copy = format->names + format->name_offset;
-  uint available = GPU_VERT_ATTR_NAMES_BUF_LEN - format->name_offset;
+  uchar name_offset = format->name_offset;
+  char *name_copy = format->names + name_offset;
+  uint available = GPU_VERT_ATTR_NAMES_BUF_LEN - name_offset;
   bool terminated = false;
 
   for (uint i = 0; i < available; ++i) {
     const char c = name[i];
     name_copy[i] = c;
     if (c == '\0') {
-      if (suffix) {
-        for (uint j = 0; j < available; ++j) {
-          const char s = suffix[j];
-          name_copy[i + j] = s;
-          if (s == '\0') {
-            terminated = true;
-            format->name_offset += (i + j + 1);
-            break;
-          }
-        }
-      }
-      else {
-        terminated = true;
-        format->name_offset += (i + 1);
-      }
+      terminated = true;
+      format->name_offset += (i + 1);
       break;
     }
   }
@@ -157,7 +139,7 @@ static const char *copy_attr_name(GPUVertFormat *format, const char *name, const
 #else
   (void)terminated;
 #endif
-  return name_copy;
+  return name_offset;
 }
 
 uint GPU_vertformat_attr_add(GPUVertFormat *format,
@@ -196,7 +178,7 @@ uint GPU_vertformat_attr_add(GPUVertFormat *format,
   const uint attr_id = format->attr_len++;
   GPUVertAttr *attr = &format->attrs[attr_id];
 
-  attr->name[attr->name_len++] = copy_attr_name(format, name, NULL);
+  attr->names[attr->name_len++] = copy_attr_name(format, name);
   attr->comp_type = comp_type;
   attr->gl_comp_type = convert_comp_type_to_gl(comp_type);
   attr->comp_len = (comp_type == GPU_COMP_I10) ?
@@ -217,7 +199,7 @@ void GPU_vertformat_alias_add(GPUVertFormat *format, const char *alias)
   assert(attr->name_len < GPU_VERT_ATTR_MAX_NAMES);
 #endif
   format->name_len++; /* multiname support */
-  attr->name[attr->name_len++] = copy_attr_name(format, alias, NULL);
+  attr->names[attr->name_len++] = copy_attr_name(format, alias);
 }
 
 int GPU_vertformat_attr_id_get(const GPUVertFormat *format, const char *name)
@@ -225,7 +207,8 @@ int GPU_vertformat_attr_id_get(const GPUVertFormat *format, const char *name)
   for (int i = 0; i < format->attr_len; i++) {
     const GPUVertAttr *attr = &format->attrs[i];
     for (int j = 0; j < attr->name_len; j++) {
-      if (STREQ(name, attr->name[j])) {
+      const char *attr_name = GPU_vertformat_attr_name_get(format, attr, j);
+      if (STREQ(name, attr_name)) {
         return i;
       }
     }
@@ -233,41 +216,6 @@ int GPU_vertformat_attr_id_get(const GPUVertFormat *format, const char *name)
   return -1;
 }
 
-void GPU_vertformat_triple_load(GPUVertFormat *format)
-{
-#if TRUST_NO_ONE
-  assert(!format->packed);
-  assert(format->attr_len * 3 < GPU_VERT_ATTR_MAX_LEN);
-  assert(format->name_len + format->attr_len * 3 < GPU_VERT_ATTR_MAX_LEN);
-#endif
-
-  VertexFormat_pack(format);
-
-  uint old_attr_len = format->attr_len;
-  for (uint a_idx = 0; a_idx < old_attr_len; ++a_idx) {
-    GPUVertAttr *attr = &format->attrs[a_idx];
-    /* Duplicate attr twice */
-    for (int i = 1; i < 3; ++i) {
-      GPUVertAttr *dst_attr = &format->attrs[format->attr_len];
-      memcpy(dst_attr, attr, sizeof(GPUVertAttr));
-      /* Increase offset to the next vertex. */
-      dst_attr->offset += format->stride * i;
-      /* Only copy first name for now. */
-      dst_attr->name_len = 0;
-      dst_attr->name[dst_attr->name_len++] = copy_attr_name(
-          format, attr->name[0], (i == 1) ? "1" : "2");
-      format->attr_len++;
-    }
-
-#if TRUST_NO_ONE
-    assert(attr->name_len < GPU_VERT_ATTR_MAX_NAMES);
-#endif
-    /* Add alias to first attr. */
-    format->name_len++;
-    attr->name[attr->name_len++] = copy_attr_name(format, attr->name[0], "0");
-  }
-}
-
 uint padding(uint offset, uint alignment)
 {
   const uint mod = offset % alignment;
@@ -364,7 +312,6 @@ static uint calc_input_component_size(const GPUShaderInput *input)
 
 static void get_fetch_mode_and_comp_type(int gl_type,
                                          GPUVertCompType *r_comp_type,
-                                         uint *r_gl_comp_type,
                                          GPUVertFetchMode *r_fetch_mode)
 {
   switch (gl_type) {
@@ -382,7 +329,6 @@ static void get_fetch_mode_and_comp_type(int gl_type,
     case GL_FLOAT_MAT4x2:
     case GL_FLOAT_MAT4x3:
       *r_comp_type = GPU_COMP_F32;
-      *r_gl_comp_type = GL_FLOAT;
       *r_fetch_mode = GPU_FETCH_FLOAT;
       break;
     case GL_INT:
@@ -390,7 +336,6 @@ static void get_fetch_mode_and_comp_type(int gl_type,
     case GL_INT_VEC3:
     case GL_INT_VEC4:
       *r_comp_type = GPU_COMP_I32;
-      *r_gl_comp_type = GL_INT;
       *r_fetch_mode = GPU_FETCH_INT;
       break;
     case GL_UNSIGNED_INT:
@@ -398,7 +343,6 @@ static void get_fetch_mode_and_comp_type(int gl_type,
     case GL_UNSIGNED_INT_VEC3:
     case GL_UNSIGNED_INT_VEC4:
       *r_comp_type = GPU_COMP_U32;
-      *r_gl_comp_type = GL_UNSIGNED_INT;
       *r_fetch_mode = GPU_FETCH_INT;
       break;
     default:
@@ -424,15 +368,19 @@ void GPU_vertformat_from_interface(GPUVertFormat *format, const GPUShaderInterfa
       format->name_len++; /* multiname support */
       format->attr_len++;
 
+      GPUVertCompType comp_type;
+      GPUVertFetchMode fetch_mode;
+      get_fetch_mode_and_comp_type(input->gl_type, &comp_type, &fetch_mode);
+
       GPUVertAttr *attr = &format->attrs[input->location];
 
-      attr->name[attr->name_len++] = copy_attr_name(
-          format, name_buffer + input->name_offset, NULL);
+      attr->names[attr->name_len++] = copy_attr_name(format, name_buffer + input->name_offset);
       attr->offset = 0; /* offsets & stride are calculated later (during pack) */
       attr->comp_len = calc_input_component_size(input);
       attr->sz = attr->comp_len * 4;
-      get_fetch_mode_and_comp_type(
-          input->gl_type, &attr->comp_type, &attr->gl_comp_type, &attr->fetch_mode);
+      attr->fetch_mode = fetch_mode;
+      attr->comp_type = comp_type;
+      attr->gl_comp_type = convert_comp_type_to_gl(comp_type);
     }
   }
 }