[Mesa-dev] [PATCH] u_vbuf: Simplify the format fallback translation.

Eric Anholt eric at anholt.net
Sat Aug 23 16:38:13 PDT 2014


Individual caps made supporting new fallbacks more complicated than it
needed to be.  Instead, just make a table of fallbacks at context init
time.

v2: Fix inverted "do we need to install vbuf?" flagging caught by Marek.
---

Sorry for the crap patch, hopefully this has the fixees from your review.

 src/gallium/auxiliary/cso_cache/cso_context.c |  12 +-
 src/gallium/auxiliary/util/u_vbuf.c           | 181 ++++++++++++--------------
 src/gallium/auxiliary/util/u_vbuf.h           |  11 +-
 3 files changed, 87 insertions(+), 117 deletions(-)

diff --git a/src/gallium/auxiliary/cso_cache/cso_context.c b/src/gallium/auxiliary/cso_cache/cso_context.c
index ca91b67..3d8860f 100644
--- a/src/gallium/auxiliary/cso_cache/cso_context.c
+++ b/src/gallium/auxiliary/cso_cache/cso_context.c
@@ -239,18 +239,8 @@ static void cso_init_vbuf(struct cso_context *cso)
 {
    struct u_vbuf_caps caps;
 
-   u_vbuf_get_caps(cso->pipe->screen, &caps);
-
    /* Install u_vbuf if there is anything unsupported. */
-   if (!caps.buffer_offset_unaligned ||
-       !caps.buffer_stride_unaligned ||
-       !caps.velem_src_offset_unaligned ||
-       !caps.format_fixed32 ||
-       !caps.format_float16 ||
-       !caps.format_float64 ||
-       !caps.format_norm32 ||
-       !caps.format_scaled32 ||
-       !caps.user_vertex_buffers) {
+   if (u_vbuf_get_caps(cso->pipe->screen, &caps)) {
       cso->vbuf = u_vbuf_create(cso->pipe, &caps,
                                 cso->aux_vertex_buffer_index);
    }
diff --git a/src/gallium/auxiliary/util/u_vbuf.c b/src/gallium/auxiliary/util/u_vbuf.c
index c475ee1..26017fa 100644
--- a/src/gallium/auxiliary/util/u_vbuf.c
+++ b/src/gallium/auxiliary/util/u_vbuf.c
@@ -191,47 +191,90 @@ u_vbuf_create_vertex_elements(struct u_vbuf *mgr, unsigned count,
                               const struct pipe_vertex_element *attribs);
 static void u_vbuf_delete_vertex_elements(struct u_vbuf *mgr, void *cso);
 
+static const struct {
+   enum pipe_format from, to;
+} vbuf_format_fallbacks[] = {
+   { PIPE_FORMAT_R32_FIXED,            PIPE_FORMAT_R32_FLOAT },
+   { PIPE_FORMAT_R32G32_FIXED,         PIPE_FORMAT_R32G32_FLOAT },
+   { PIPE_FORMAT_R32G32B32_FIXED,      PIPE_FORMAT_R32G32B32_FLOAT },
+   { PIPE_FORMAT_R32G32B32A32_FIXED,   PIPE_FORMAT_R32G32B32A32_FLOAT },
+   { PIPE_FORMAT_R16_FLOAT,            PIPE_FORMAT_R32_FLOAT },
+   { PIPE_FORMAT_R16G16_FLOAT,         PIPE_FORMAT_R32G32_FLOAT },
+   { PIPE_FORMAT_R16G16B16_FLOAT,      PIPE_FORMAT_R32G32B32_FLOAT },
+   { PIPE_FORMAT_R16G16B16A16_FLOAT,   PIPE_FORMAT_R32G32B32A32_FLOAT },
+   { PIPE_FORMAT_R64_FLOAT,            PIPE_FORMAT_R32_FLOAT },
+   { PIPE_FORMAT_R64G64_FLOAT,         PIPE_FORMAT_R32G32_FLOAT },
+   { PIPE_FORMAT_R64G64B64_FLOAT,      PIPE_FORMAT_R32G32B32_FLOAT },
+   { PIPE_FORMAT_R64G64B64A64_FLOAT,   PIPE_FORMAT_R32G32B32A32_FLOAT },
+   { PIPE_FORMAT_R32_UNORM,            PIPE_FORMAT_R32_FLOAT },
+   { PIPE_FORMAT_R32G32_UNORM,         PIPE_FORMAT_R32G32_FLOAT },
+   { PIPE_FORMAT_R32G32B32_UNORM,      PIPE_FORMAT_R32G32B32_FLOAT },
+   { PIPE_FORMAT_R32G32B32A32_UNORM,   PIPE_FORMAT_R32G32B32A32_FLOAT },
+   { PIPE_FORMAT_R32_SNORM,            PIPE_FORMAT_R32_FLOAT },
+   { PIPE_FORMAT_R32G32_SNORM,         PIPE_FORMAT_R32G32_FLOAT },
+   { PIPE_FORMAT_R32G32B32_SNORM,      PIPE_FORMAT_R32G32B32_FLOAT },
+   { PIPE_FORMAT_R32G32B32A32_SNORM,   PIPE_FORMAT_R32G32B32A32_FLOAT },
+   { PIPE_FORMAT_R32_USCALED,          PIPE_FORMAT_R32_FLOAT },
+   { PIPE_FORMAT_R32G32_USCALED,       PIPE_FORMAT_R32G32_FLOAT },
+   { PIPE_FORMAT_R32G32B32_USCALED,    PIPE_FORMAT_R32G32B32_FLOAT },
+   { PIPE_FORMAT_R32G32B32A32_USCALED, PIPE_FORMAT_R32G32B32A32_FLOAT },
+   { PIPE_FORMAT_R32_SSCALED,          PIPE_FORMAT_R32_FLOAT },
+   { PIPE_FORMAT_R32G32_SSCALED,       PIPE_FORMAT_R32G32_FLOAT },
+   { PIPE_FORMAT_R32G32B32_SSCALED,    PIPE_FORMAT_R32G32B32_FLOAT },
+   { PIPE_FORMAT_R32G32B32A32_SSCALED, PIPE_FORMAT_R32G32B32A32_FLOAT },
+};
 
-void u_vbuf_get_caps(struct pipe_screen *screen, struct u_vbuf_caps *caps)
+boolean u_vbuf_get_caps(struct pipe_screen *screen, struct u_vbuf_caps *caps)
 {
-   caps->format_fixed32 =
-      screen->is_format_supported(screen, PIPE_FORMAT_R32_FIXED, PIPE_BUFFER,
-                                  0, PIPE_BIND_VERTEX_BUFFER);
-
-   caps->format_float16 =
-      screen->is_format_supported(screen, PIPE_FORMAT_R16_FLOAT, PIPE_BUFFER,
-                                  0, PIPE_BIND_VERTEX_BUFFER);
-
-   caps->format_float64 =
-      screen->is_format_supported(screen, PIPE_FORMAT_R64_FLOAT, PIPE_BUFFER,
-                                  0, PIPE_BIND_VERTEX_BUFFER);
-
-   caps->format_norm32 =
-      screen->is_format_supported(screen, PIPE_FORMAT_R32_UNORM, PIPE_BUFFER,
-                                  0, PIPE_BIND_VERTEX_BUFFER) &&
-      screen->is_format_supported(screen, PIPE_FORMAT_R32_SNORM, PIPE_BUFFER,
-                                  0, PIPE_BIND_VERTEX_BUFFER);
-
-   caps->format_scaled32 =
-      screen->is_format_supported(screen, PIPE_FORMAT_R32_USCALED, PIPE_BUFFER,
-                                  0, PIPE_BIND_VERTEX_BUFFER) &&
-      screen->is_format_supported(screen, PIPE_FORMAT_R32_SSCALED, PIPE_BUFFER,
-                                  0, PIPE_BIND_VERTEX_BUFFER);
-
-   caps->buffer_offset_unaligned =
-      !screen->get_param(screen,
-                        PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY);
-
-   caps->buffer_stride_unaligned =
-      !screen->get_param(screen,
-                        PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY);
-
-   caps->velem_src_offset_unaligned =
-      !screen->get_param(screen,
-                        PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY);
-
-   caps->user_vertex_buffers =
-      screen->get_param(screen, PIPE_CAP_USER_VERTEX_BUFFERS);
+   unsigned i;
+   boolean fallback = FALSE;
+
+   /* I'd rather have a bitfield of which formats are supported and a static
+    * table of the translations indexed by format, but since we don't have C99
+    * we can't easily make a sparsely-populated table indexed by format.  So,
+    * we construct the sparse table here.
+    */
+   for (i = 0; i < PIPE_FORMAT_COUNT; i++)
+      caps->format_translation[i] = i;
+
+   for (i = 0; i < Elements(vbuf_format_fallbacks); i++) {
+      enum pipe_format format = vbuf_format_fallbacks[i].from;
+
+      if (!screen->is_format_supported(screen, format, PIPE_BUFFER, 0,
+                                       PIPE_BIND_VERTEX_BUFFER)) {
+         caps->format_translation[format] = vbuf_format_fallbacks[i].to;
+         fallback = TRUE;
+      }
+   }
+
+   if (!screen->get_param(screen,
+                          PIPE_CAP_VERTEX_BUFFER_OFFSET_4BYTE_ALIGNED_ONLY)) {
+      caps->buffer_offset_unaligned = TRUE;
+   } else {
+      fallback = TRUE;
+   }
+
+   if (!screen->get_param(screen,
+                          PIPE_CAP_VERTEX_BUFFER_STRIDE_4BYTE_ALIGNED_ONLY)) {
+      caps->buffer_stride_unaligned = TRUE;
+   } else {
+      fallback = TRUE;
+   }
+
+   if (!screen->get_param(screen,
+                          PIPE_CAP_VERTEX_ELEMENT_SRC_OFFSET_4BYTE_ALIGNED_ONLY)) {
+      caps->velem_src_offset_unaligned = TRUE;
+   } else {
+      fallback = TRUE;
+   }
+
+   if (screen->get_param(screen, PIPE_CAP_USER_VERTEX_BUFFERS)) {
+      caps->user_vertex_buffers = TRUE;
+   } else {
+      fallback = TRUE;
+   }
+
+   return fallback;
 }
 
 struct u_vbuf *
@@ -664,9 +707,6 @@ static void u_vbuf_translate_end(struct u_vbuf *mgr)
    }
 }
 
-#define FORMAT_REPLACE(what, withwhat) \
-    case PIPE_FORMAT_##what: format = PIPE_FORMAT_##withwhat; break
-
 static void *
 u_vbuf_create_vertex_elements(struct u_vbuf *mgr, unsigned count,
                               const struct pipe_vertex_element *attribs)
@@ -695,62 +735,7 @@ u_vbuf_create_vertex_elements(struct u_vbuf *mgr, unsigned count,
          ve->noninstance_vb_mask_any |= 1 << ve->ve[i].vertex_buffer_index;
       }
 
-      /* Choose a native format.
-       * For now we don't care about the alignment, that's going to
-       * be sorted out later. */
-      if (!mgr->caps.format_fixed32) {
-         switch (format) {
-            FORMAT_REPLACE(R32_FIXED,           R32_FLOAT);
-            FORMAT_REPLACE(R32G32_FIXED,        R32G32_FLOAT);
-            FORMAT_REPLACE(R32G32B32_FIXED,     R32G32B32_FLOAT);
-            FORMAT_REPLACE(R32G32B32A32_FIXED,  R32G32B32A32_FLOAT);
-            default:;
-         }
-      }
-      if (!mgr->caps.format_float16) {
-         switch (format) {
-            FORMAT_REPLACE(R16_FLOAT,           R32_FLOAT);
-            FORMAT_REPLACE(R16G16_FLOAT,        R32G32_FLOAT);
-            FORMAT_REPLACE(R16G16B16_FLOAT,     R32G32B32_FLOAT);
-            FORMAT_REPLACE(R16G16B16A16_FLOAT,  R32G32B32A32_FLOAT);
-            default:;
-         }
-      }
-      if (!mgr->caps.format_float64) {
-         switch (format) {
-            FORMAT_REPLACE(R64_FLOAT,           R32_FLOAT);
-            FORMAT_REPLACE(R64G64_FLOAT,        R32G32_FLOAT);
-            FORMAT_REPLACE(R64G64B64_FLOAT,     R32G32B32_FLOAT);
-            FORMAT_REPLACE(R64G64B64A64_FLOAT,  R32G32B32A32_FLOAT);
-            default:;
-         }
-      }
-      if (!mgr->caps.format_norm32) {
-         switch (format) {
-            FORMAT_REPLACE(R32_UNORM,           R32_FLOAT);
-            FORMAT_REPLACE(R32G32_UNORM,        R32G32_FLOAT);
-            FORMAT_REPLACE(R32G32B32_UNORM,     R32G32B32_FLOAT);
-            FORMAT_REPLACE(R32G32B32A32_UNORM,  R32G32B32A32_FLOAT);
-            FORMAT_REPLACE(R32_SNORM,           R32_FLOAT);
-            FORMAT_REPLACE(R32G32_SNORM,        R32G32_FLOAT);
-            FORMAT_REPLACE(R32G32B32_SNORM,     R32G32B32_FLOAT);
-            FORMAT_REPLACE(R32G32B32A32_SNORM,  R32G32B32A32_FLOAT);
-            default:;
-         }
-      }
-      if (!mgr->caps.format_scaled32) {
-         switch (format) {
-            FORMAT_REPLACE(R32_USCALED,         R32_FLOAT);
-            FORMAT_REPLACE(R32G32_USCALED,      R32G32_FLOAT);
-            FORMAT_REPLACE(R32G32B32_USCALED,   R32G32B32_FLOAT);
-            FORMAT_REPLACE(R32G32B32A32_USCALED,R32G32B32A32_FLOAT);
-            FORMAT_REPLACE(R32_SSCALED,         R32_FLOAT);
-            FORMAT_REPLACE(R32G32_SSCALED,      R32G32_FLOAT);
-            FORMAT_REPLACE(R32G32B32_SSCALED,   R32G32B32_FLOAT);
-            FORMAT_REPLACE(R32G32B32A32_SSCALED,R32G32B32A32_FLOAT);
-            default:;
-         }
-      }
+      format = mgr->caps.format_translation[format];
 
       driver_attribs[i].src_format = format;
       ve->native_format[i] = format;
diff --git a/src/gallium/auxiliary/util/u_vbuf.h b/src/gallium/auxiliary/util/u_vbuf.h
index a608184..9e8b135 100644
--- a/src/gallium/auxiliary/util/u_vbuf.h
+++ b/src/gallium/auxiliary/util/u_vbuf.h
@@ -35,19 +35,14 @@
 
 #include "pipe/p_context.h"
 #include "pipe/p_state.h"
+#include "pipe/p_format.h"
 
 struct cso_context;
 struct u_vbuf;
 
 /* Hardware vertex fetcher limitations can be described by this structure. */
 struct u_vbuf_caps {
-   /* Vertex format CAPs. */
-   /* TRUE if hardware supports it. */
-   unsigned format_fixed32:1;    /* PIPE_FORMAT_*32*_FIXED */
-   unsigned format_float16:1;    /* PIPE_FORMAT_*16*_FLOAT */
-   unsigned format_float64:1;    /* PIPE_FORMAT_*64*_FLOAT */
-   unsigned format_norm32:1;     /* PIPE_FORMAT_*32*NORM */
-   unsigned format_scaled32:1;   /* PIPE_FORMAT_*32*SCALED */
+   enum pipe_format format_translation[PIPE_FORMAT_COUNT];
 
    /* Whether vertex fetches don't have to be 4-byte-aligned. */
    /* TRUE if hardware supports it. */
@@ -60,7 +55,7 @@ struct u_vbuf_caps {
 };
 
 
-void u_vbuf_get_caps(struct pipe_screen *screen, struct u_vbuf_caps *caps);
+boolean u_vbuf_get_caps(struct pipe_screen *screen, struct u_vbuf_caps *caps);
 
 struct u_vbuf *
 u_vbuf_create(struct pipe_context *pipe,
-- 
2.1.0



More information about the mesa-dev mailing list