Mesa (main): gallium: lower raw 64-bit vertex formats in cso/vbuf instead of st/mesa

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Mon Aug 2 20:35:19 UTC 2021


Module: Mesa
Branch: main
Commit: 8b6fd3f786d3cf1d9b1ee1dc5be1c8cb885ed77a
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=8b6fd3f786d3cf1d9b1ee1dc5be1c8cb885ed77a

Author: Marek Olšák <marek.olsak at amd.com>
Date:   Wed May 26 23:45:45 2021 -0400

gallium: lower raw 64-bit vertex formats in cso/vbuf instead of st/mesa

This lower each 64-bit vertex element into 1 or 2 32-bit vertex elements.
The motivation is to simplify st/mesa, which uses a lot more complicated
code to do the same thing, and do the lowering only on a cso_cache miss.

Reviewed-by: Alyssa Rosenzweig <alyssa at collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/11370>

---

 src/gallium/auxiliary/cso_cache/cso_context.c | 13 ++++-
 src/gallium/auxiliary/util/u_helpers.c        | 84 +++++++++++++++++++++++++++
 src/gallium/auxiliary/util/u_helpers.h        |  5 ++
 src/gallium/auxiliary/util/u_vbuf.c           |  4 ++
 4 files changed, 103 insertions(+), 3 deletions(-)

diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c
index d49b5161c04..0bb5c1a50ee 100644
--- a/src/gallium/auxiliary/cso_cache/cso_context.c
+++ b/src/gallium/auxiliary/cso_cache/cso_context.c
@@ -38,6 +38,7 @@
 #include "pipe/p_state.h"
 #include "util/u_draw.h"
 #include "util/u_framebuffer.h"
+#include "util/u_helpers.h"
 #include "util/u_inlines.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
@@ -1026,9 +1027,15 @@ cso_set_vertex_elements_direct(struct cso_context *ctx,
          return;
 
       memcpy(&cso->state, velems, key_size);
-      cso->data = ctx->pipe->create_vertex_elements_state(ctx->pipe,
-                                                          velems->count,
-                                                      &cso->state.velems[0]);
+
+      /* Lower 64-bit vertex attributes. */
+      unsigned new_count = velems->count;
+      const struct pipe_vertex_element *new_elems = velems->velems;
+      struct pipe_vertex_element tmp[PIPE_MAX_ATTRIBS];
+      util_lower_uint64_vertex_elements(&new_elems, &new_count, tmp);
+
+      cso->data = ctx->pipe->create_vertex_elements_state(ctx->pipe, new_count,
+                                                          new_elems);
 
       iter = cso_insert_state(&ctx->cache, hash_key, CSO_VELEMENTS, cso);
       if (cso_hash_iter_is_null(iter)) {
diff --git a/src/gallium/auxiliary/util/u_helpers.c b/src/gallium/auxiliary/util/u_helpers.c
index d7db32d124b..0c358a06b21 100644
--- a/src/gallium/auxiliary/util/u_helpers.c
+++ b/src/gallium/auxiliary/util/u_helpers.c
@@ -166,6 +166,90 @@ util_upload_index_buffer(struct pipe_context *pipe,
    return *out_buffer != NULL;
 }
 
+/**
+ * Lower each UINT64 vertex element to 1 or 2 UINT32 vertex elements.
+ * 3 and 4 component formats are expanded into 2 slots.
+ *
+ * @param velems        Original vertex elements, will be updated to contain
+ *                      the lowered vertex elements.
+ * @param velem_count   Original count, will be updated to contain the count
+ *                      after lowering.
+ * @param tmp           Temporary array of PIPE_MAX_ATTRIBS vertex elements.
+ */
+void
+util_lower_uint64_vertex_elements(const struct pipe_vertex_element **velems,
+                                  unsigned *velem_count,
+                                  struct pipe_vertex_element tmp[PIPE_MAX_ATTRIBS])
+{
+   const struct pipe_vertex_element *input = *velems;
+   unsigned count = *velem_count;
+   bool has_64bit = false;
+
+   for (unsigned i = 0; i < count; i++) {
+      has_64bit |= input[i].src_format >= PIPE_FORMAT_R64_UINT &&
+                   input[i].src_format <= PIPE_FORMAT_R64G64B64A64_UINT;
+   }
+
+   /* Return the original vertex elements if there is nothing to do. */
+   if (!has_64bit)
+      return;
+
+   /* Lower 64_UINT to 32_UINT. */
+   unsigned new_count = 0;
+
+   for (unsigned i = 0; i < count; i++) {
+      enum pipe_format format = input[i].src_format;
+
+      /* If the shader input is dvec2 or smaller, reduce the number of
+       * components to 2 at most. If the shader input is dvec3 or larger,
+       * expand the number of components to 3 at least. If the 3rd component
+       * is out of bounds, the hardware shouldn't skip loading the first
+       * 2 components.
+       */
+      if (format >= PIPE_FORMAT_R64_UINT &&
+          format <= PIPE_FORMAT_R64G64B64A64_UINT) {
+         if (input[i].dual_slot)
+            format = MAX2(format, PIPE_FORMAT_R64G64B64_UINT);
+         else
+            format = MIN2(format, PIPE_FORMAT_R64G64_UINT);
+      }
+
+      switch (format) {
+      case PIPE_FORMAT_R64_UINT:
+         tmp[new_count] = input[i];
+         tmp[new_count].src_format = PIPE_FORMAT_R32G32_UINT;
+         new_count++;
+         break;
+
+      case PIPE_FORMAT_R64G64_UINT:
+         tmp[new_count] = input[i];
+         tmp[new_count].src_format = PIPE_FORMAT_R32G32B32A32_UINT;
+         new_count++;
+         break;
+
+      case PIPE_FORMAT_R64G64B64_UINT:
+      case PIPE_FORMAT_R64G64B64A64_UINT:
+         assert(new_count + 2 <= PIPE_MAX_ATTRIBS);
+         tmp[new_count] = tmp[new_count + 1] = input[i];
+         tmp[new_count].src_format = PIPE_FORMAT_R32G32B32A32_UINT;
+         tmp[new_count + 1].src_format =
+            format == PIPE_FORMAT_R64G64B64_UINT ?
+                  PIPE_FORMAT_R32G32_UINT :
+                  PIPE_FORMAT_R32G32B32A32_UINT;
+         tmp[new_count + 1].src_offset += 16;
+         new_count += 2;
+         break;
+
+      default:
+         tmp[new_count++] = input[i];
+         break;
+      }
+   }
+
+   *velem_count = new_count;
+   *velems = tmp;
+}
+
 /* This is a helper for hardware bring-up. Don't remove. */
 struct pipe_query *
 util_begin_pipestat_query(struct pipe_context *ctx)
diff --git a/src/gallium/auxiliary/util/u_helpers.h b/src/gallium/auxiliary/util/u_helpers.h
index 0bfc91700c1..f08f44dad99 100644
--- a/src/gallium/auxiliary/util/u_helpers.h
+++ b/src/gallium/auxiliary/util/u_helpers.h
@@ -62,6 +62,11 @@ bool util_upload_index_buffer(struct pipe_context *pipe,
                               struct pipe_resource **out_buffer,
                               unsigned *out_offset, unsigned alignment);
 
+void
+util_lower_uint64_vertex_elements(const struct pipe_vertex_element **velems,
+                                  unsigned *velem_count,
+                                  struct pipe_vertex_element tmp[PIPE_MAX_ATTRIBS]);
+
 /* Helper function to determine if the varying should contain the point
  * coordinates, given the sprite_coord_enable mask.  Requires
  * PIPE_CAP_TGSI_TEXCOORD to be enabled.
diff --git a/src/gallium/auxiliary/util/u_vbuf.c b/src/gallium/auxiliary/util/u_vbuf.c
index e6dc72c6bce..ef28c628da9 100644
--- a/src/gallium/auxiliary/util/u_vbuf.c
+++ b/src/gallium/auxiliary/util/u_vbuf.c
@@ -89,6 +89,7 @@
 
 #include "util/u_dump.h"
 #include "util/format/u_format.h"
+#include "util/u_helpers.h"
 #include "util/u_inlines.h"
 #include "util/u_memory.h"
 #include "indices/u_primconvert.h"
@@ -841,6 +842,9 @@ static void *
 u_vbuf_create_vertex_elements(struct u_vbuf *mgr, unsigned count,
                               const struct pipe_vertex_element *attribs)
 {
+   struct pipe_vertex_element tmp[PIPE_MAX_ATTRIBS];
+   util_lower_uint64_vertex_elements(&attribs, &count, tmp);
+
    struct pipe_context *pipe = mgr->pipe;
    unsigned i;
    struct pipe_vertex_element driver_attribs[PIPE_MAX_ATTRIBS];



More information about the mesa-commit mailing list