mesa: optimize _mesa_bytes_per_vertex_attrib using a hash-based translation
authorMarek Olšák <marek.olsak@amd.com>
Mon, 12 Dec 2022 04:47:29 +0000 (23:47 -0500)
committerMarek Olšák <marek.olsak@amd.com>
Sun, 18 Dec 2022 19:35:59 +0000 (14:35 -0500)
This reduces time spent in gl*Pointer for viewperf.

Generated by find_hash_func.c.

Reviewed-by: Rob Clark <robclark@freedesktop.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20287>

src/mesa/main/glformats.c
src/mesa/main/glformats.h
src/mesa/main/varray.c
src/mesa/main/varray.h

index 068c018..06c68b4 100644 (file)
@@ -522,55 +522,6 @@ _mesa_bytes_per_pixel(GLenum format, GLenum type)
 
 
 /**
- * Get the number of bytes for a vertex attrib with the given number of
- * components and type.
- *
- * \param comps number of components.
- * \param type data type.
- *
- * \return bytes per attribute, or -1 if a bad comps/type combination was given.
- */
-GLint
-_mesa_bytes_per_vertex_attrib(GLint comps, GLenum type)
-{
-   switch (type) {
-   case GL_BYTE:
-   case GL_UNSIGNED_BYTE:
-      return comps * sizeof(GLubyte);
-   case GL_SHORT:
-   case GL_UNSIGNED_SHORT:
-      return comps * sizeof(GLshort);
-   case GL_INT:
-   case GL_UNSIGNED_INT:
-      return comps * sizeof(GLint);
-   case GL_FLOAT:
-      return comps * sizeof(GLfloat);
-   case GL_HALF_FLOAT_ARB:
-   case GL_HALF_FLOAT_OES:
-      return comps * sizeof(GLhalfARB);
-   case GL_DOUBLE:
-      return comps * sizeof(GLdouble);
-   case GL_FIXED:
-      return comps * sizeof(GLfixed);
-   case GL_INT_2_10_10_10_REV:
-   case GL_UNSIGNED_INT_2_10_10_10_REV:
-      if (comps == 4)
-         return sizeof(GLuint);
-      else
-         return -1;
-   case GL_UNSIGNED_INT_10F_11F_11F_REV:
-      if (comps == 3)
-         return sizeof(GLuint);
-      else
-         return -1;
-   case GL_UNSIGNED_INT64_ARB:
-      return comps * 8;
-   default:
-      return -1;
-   }
-}
-
-/**
  * Test if the given format is unsized.
  */
 GLboolean
index cfca451..a402a83 100644 (file)
@@ -57,9 +57,6 @@ _mesa_components_in_format( GLenum format );
 extern GLint
 _mesa_bytes_per_pixel( GLenum format, GLenum type );
 
-extern GLint
-_mesa_bytes_per_vertex_attrib(GLint comps, GLenum type);
-
 extern GLboolean
 _mesa_is_astc_format(GLenum internalFormat);
 
index 72a71db..4bb289d 100644 (file)
 #include "state_tracker/st_atom.h"
 #include "state_tracker/st_util.h"
 
+/* The values are multiplied by the component count to get the attrib size.
+ * Indexed by PERF_HASH_GL_TYPE(GLenum).
+ * Generated by src/util/tools/find_hash_func.c.
+ */
+const uint8_t _mesa_vertex_type_bytes[16] = {
+   /* These elements are listed out of order. */
+   [/* 7*/ PERF_HASH_GL_VERTEX_TYPE(GL_BYTE)] = 1,
+   [/* 8*/ PERF_HASH_GL_VERTEX_TYPE(GL_UNSIGNED_BYTE)] = 1,
+   [/* 5*/ PERF_HASH_GL_VERTEX_TYPE(GL_INT_2_10_10_10_REV)] = 1, /* count is 4 */
+   [/* 0*/ PERF_HASH_GL_VERTEX_TYPE(GL_UNSIGNED_INT_2_10_10_10_REV)] = 1, /* count is 4 */
+   [/* 9*/ PERF_HASH_GL_VERTEX_TYPE(GL_SHORT)] = 2,
+   [/*10*/ PERF_HASH_GL_VERTEX_TYPE(GL_UNSIGNED_SHORT)] = 2,
+   [/* 2*/ PERF_HASH_GL_VERTEX_TYPE(GL_HALF_FLOAT_ARB)] = 2,
+   [/* 4*/ PERF_HASH_GL_VERTEX_TYPE(GL_HALF_FLOAT_OES)] = 2,
+   [/*11*/ PERF_HASH_GL_VERTEX_TYPE(GL_INT)] = 4,
+   [/*12*/ PERF_HASH_GL_VERTEX_TYPE(GL_UNSIGNED_INT)] = 4,
+   [/*13*/ PERF_HASH_GL_VERTEX_TYPE(GL_FLOAT)] = 4,
+   [/* 3*/ PERF_HASH_GL_VERTEX_TYPE(GL_FIXED)] = 4,
+   [/* 1*/ PERF_HASH_GL_VERTEX_TYPE(GL_DOUBLE)] = 8,
+   [/* 6*/ PERF_HASH_GL_VERTEX_TYPE(GL_UNSIGNED_INT64_ARB)] = 8,
+};
+
+static inline void
+compile_check_uniqueness_of_gl_vertex_type(unsigned x)
+{
+   /* This switch has the same purpose as static_assert.
+    * It should fail compilation if any case is not unique.
+    */
+   switch (x) {
+   case PERF_HASH_GL_VERTEX_TYPE(GL_BYTE):
+   case PERF_HASH_GL_VERTEX_TYPE(GL_UNSIGNED_BYTE):
+   case PERF_HASH_GL_VERTEX_TYPE(GL_INT_2_10_10_10_REV):
+   case PERF_HASH_GL_VERTEX_TYPE(GL_UNSIGNED_INT_2_10_10_10_REV):
+   case PERF_HASH_GL_VERTEX_TYPE(GL_SHORT):
+   case PERF_HASH_GL_VERTEX_TYPE(GL_UNSIGNED_SHORT):
+   case PERF_HASH_GL_VERTEX_TYPE(GL_HALF_FLOAT_ARB):
+   case PERF_HASH_GL_VERTEX_TYPE(GL_HALF_FLOAT_OES):
+   case PERF_HASH_GL_VERTEX_TYPE(GL_INT):
+   case PERF_HASH_GL_VERTEX_TYPE(GL_UNSIGNED_INT):
+   case PERF_HASH_GL_VERTEX_TYPE(GL_FLOAT):
+   case PERF_HASH_GL_VERTEX_TYPE(GL_FIXED):
+   case PERF_HASH_GL_VERTEX_TYPE(GL_DOUBLE):
+   case PERF_HASH_GL_VERTEX_TYPE(GL_UNSIGNED_INT64_ARB):
+      break;
+   }
+}
 
 /** Used to do error checking for GL_EXT_vertex_array_bgra */
 #define BGRA_OR_4  5
index 8c61070..07cfa23 100644 (file)
@@ -175,4 +175,38 @@ _mesa_update_edgeflag_state_explicit(struct gl_context *ctx,
 void
 _mesa_update_edgeflag_state_vao(struct gl_context *ctx);
 
+
+/**
+ * Get the number of bytes for a vertex attrib with the given number of
+ * components and type.
+ *
+ * Note that this function will return some number between 0 and
+ * "8 * comps" if the type is invalid. It's assumed that error checking
+ * was done before this, or was skipped intentionally by mesa_no_error.
+ *
+ * \param comps number of components.
+ * \param type data type.
+ */
+static inline int
+_mesa_bytes_per_vertex_attrib(int comps, GLenum type)
+{
+   /* This has comps = 3, but should return 4, so it's difficult to
+    * incorporate it into the "bytes * comps" formula below.
+    */
+   if (type == GL_UNSIGNED_INT_10F_11F_11F_REV)
+      return 4;
+
+   /* This is a perfect hash for the specific set of GLenums that is valid
+    * here. It injectively maps a small set of GLenums into smaller numbers
+    * that can be used for indexing into small translation tables. It has
+    * hash collisions with enums that are invalid here.
+    */
+   #define PERF_HASH_GL_VERTEX_TYPE(x) ((((x) * 17175) >> 14) & 0xf)
+
+   extern const uint8_t _mesa_vertex_type_bytes[16];
+
+   assert(PERF_HASH_GL_VERTEX_TYPE(type) < ARRAY_SIZE(_mesa_vertex_type_bytes));
+   return _mesa_vertex_type_bytes[PERF_HASH_GL_VERTEX_TYPE(type)] * comps;
+}
+
 #endif