Mesa (master): r300g: skip rendering for unsupported vertex formats instead of aborting

Marek Olšák mareko at kemper.freedesktop.org
Tue Jun 8 15:01:27 PDT 2010


Module: Mesa
Branch: master
Commit: fccfb7b16512a36424370dc1942cdedd3d1c208a
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=fccfb7b16512a36424370dc1942cdedd3d1c208a

Author: Marek Olšák <maraeo at gmail.com>
Date:   Tue Jun  8 23:45:11 2010 +0200

r300g: skip rendering for unsupported vertex formats instead of aborting

The next step is to replace skipping by an actual fallback.

---

 src/gallium/drivers/r300/r300_context.h |   13 +++
 src/gallium/drivers/r300/r300_emit.c    |   16 +---
 src/gallium/drivers/r300/r300_render.c  |   12 +++-
 src/gallium/drivers/r300/r300_state.c   |  146 ++++++++++++++-----------------
 4 files changed, 93 insertions(+), 94 deletions(-)

diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h
index 48ec52d..cca11f8 100644
--- a/src/gallium/drivers/r300/r300_context.h
+++ b/src/gallium/drivers/r300/r300_context.h
@@ -326,6 +326,17 @@ struct r300_vertex_element_state {
     unsigned count;
     struct pipe_vertex_element velem[PIPE_MAX_ATTRIBS];
 
+    /* If (velem[i].src_format != hw_format[i]), the vertex buffer
+     * referenced by this vertex element cannot be used for rendering and
+     * its vertex data must be translated to hw_format[i]. */
+    enum pipe_format hw_format[PIPE_MAX_ATTRIBS];
+    unsigned hw_format_size[PIPE_MAX_ATTRIBS];
+
+    /* This might mean two things:
+     * - src_format != hw_format, as discussed above.
+     * - src_offset % 4 != 0. */
+    boolean incompatible_layout;
+
     struct r300_vertex_stream_state vertex_stream;
 };
 
@@ -434,6 +445,8 @@ struct r300_context {
     int sprite_coord_enable;
     /* Whether two-sided color selection is enabled (AKA light_twoside). */
     boolean two_sided_color;
+    /* Incompatible vertex buffer layout? (misaligned stride or buffer_offset) */
+    boolean incompatible_vb_layout;
 
     /* upload managers */
     struct u_upload_mgr *upload_vb;
diff --git a/src/gallium/drivers/r300/r300_emit.c b/src/gallium/drivers/r300/r300_emit.c
index c329c0f..dd9bca8 100644
--- a/src/gallium/drivers/r300/r300_emit.c
+++ b/src/gallium/drivers/r300/r300_emit.c
@@ -821,19 +821,11 @@ void r300_emit_aos(struct r300_context* r300, int offset, boolean indexed)
     struct pipe_vertex_element *velem = r300->velems->velem;
     struct r300_buffer *buf;
     int i;
+    unsigned *hw_format_size = r300->velems->hw_format_size;
     unsigned size1, size2, aos_count = r300->velems->count;
     unsigned packet_size = (aos_count * 3 + 1) / 2;
     CS_LOCALS(r300);
 
-    for (i = 0; i < aos_count; i++) {
-        if ((vbuf[velem[i].vertex_buffer_index].buffer_offset + velem[i].src_offset) % 4 != 0) {
-            /* XXX We must align the buffer. */
-            assert(0);
-            fprintf(stderr, "r300: Unaligned vertex buffer offsets aren't supported, aborting..\n");
-            abort();
-        }
-    }
-
     BEGIN_CS(2 + packet_size + aos_count * 2);
     OUT_CS_PKT3(R300_PACKET3_3D_LOAD_VBPNTR, packet_size);
     OUT_CS(aos_count | (!indexed ? R300_VC_FORCE_PREFETCH : 0));
@@ -841,8 +833,8 @@ void r300_emit_aos(struct r300_context* r300, int offset, boolean indexed)
     for (i = 0; i < aos_count - 1; i += 2) {
         vb1 = &vbuf[velem[i].vertex_buffer_index];
         vb2 = &vbuf[velem[i+1].vertex_buffer_index];
-        size1 = util_format_get_blocksize(velem[i].src_format);
-        size2 = util_format_get_blocksize(velem[i+1].src_format);
+        size1 = hw_format_size[i];
+        size2 = hw_format_size[i+1];
 
         OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride) |
                R300_VBPNTR_SIZE1(size2) | R300_VBPNTR_STRIDE1(vb2->stride));
@@ -852,7 +844,7 @@ void r300_emit_aos(struct r300_context* r300, int offset, boolean indexed)
 
     if (aos_count & 1) {
         vb1 = &vbuf[velem[i].vertex_buffer_index];
-        size1 = util_format_get_blocksize(velem[i].src_format);
+        size1 = hw_format_size[i];
 
         OUT_CS(R300_VBPNTR_SIZE0(size1) | R300_VBPNTR_STRIDE0(vb1->stride));
         OUT_CS(vb1->buffer_offset + velem[i].src_offset + offset * vb1->stride);
diff --git a/src/gallium/drivers/r300/r300_render.c b/src/gallium/drivers/r300/r300_render.c
index 23caaa5..80dea8b 100644
--- a/src/gallium/drivers/r300/r300_render.c
+++ b/src/gallium/drivers/r300/r300_render.c
@@ -333,7 +333,7 @@ static void r300_emit_draw_arrays_immediate(struct r300_context *r300,
     for (i = 0; i < vertex_element_count; i++) {
         velem = &r300->velems->velem[i];
         offset[i] = velem->src_offset / 4;
-        size[i] = util_format_get_blocksize(velem->src_format) / 4;
+        size[i] = r300->velems->hw_format_size[i] / 4;
         vertex_size += size[i];
         vbi = velem->vertex_buffer_index;
 
@@ -610,6 +610,11 @@ static void r300_draw_range_elements(struct pipe_context* pipe,
         return;
     }
 
+    if (r300->incompatible_vb_layout ||
+        r300->velems->incompatible_layout) {
+        return;
+    }
+
     if (!u_trim_pipe_prim(mode, &count)) {
         return;
     }
@@ -704,6 +709,11 @@ static void r300_draw_arrays(struct pipe_context* pipe, unsigned mode,
         return;
     }
 
+    if (r300->incompatible_vb_layout ||
+        r300->velems->incompatible_layout) {
+        return;
+    }
+
     if (!u_trim_pipe_prim(mode, &count)) {
         return;
     }
diff --git a/src/gallium/drivers/r300/r300_state.c b/src/gallium/drivers/r300/r300_state.c
index cfec8ac..d19563c 100644
--- a/src/gallium/drivers/r300/r300_state.c
+++ b/src/gallium/drivers/r300/r300_state.c
@@ -1167,15 +1167,15 @@ static void r300_set_vertex_buffers(struct pipe_context* pipe,
 
     if (r300->screen->caps.has_tcl) {
         /* HW TCL. */
-        /* Check if the stride is aligned to the size of DWORD. */
+        r300->incompatible_vb_layout = FALSE;
+
+        /* Check if the strides and offsets are aligned to the size of DWORD. */
         for (i = 0; i < count; i++) {
             if (buffers[i].buffer) {
-                if (buffers[i].stride % 4 != 0) {
-                    // XXX Shouldn't we align the buffer?
-                    fprintf(stderr, "r300: set_vertex_buffers: "
-                            "Unaligned buffer stride %i isn't supported.\n",
-                            buffers[i].stride);
-                    abort();
+                if (buffers[i].stride % 4 != 0 ||
+                    buffers[i].buffer_offset % 4 != 0) {
+                    r300->incompatible_vb_layout = TRUE;
+                    break;
                 }
             }
         }
@@ -1248,7 +1248,7 @@ static void r300_vertex_psc(struct r300_vertex_element_state *velems)
      * so PSC should just route stuff based on the vertex elements,
      * and not on attrib information. */
     for (i = 0; i < velems->count; i++) {
-        format = velems->velem[i].src_format;
+        format = velems->hw_format[i];
 
         type = r300_translate_vertex_data_type(format);
         if (type == R300_INVALID_FORMAT) {
@@ -1280,12 +1280,15 @@ static void r300_vertex_psc(struct r300_vertex_element_state *velems)
     vstream->count = (i >> 1) + 1;
 }
 
+#define FORMAT_REPLACE(what, withwhat) \
+    case PIPE_FORMAT_##what: *format = PIPE_FORMAT_##withwhat; break
+
 static void* r300_create_vertex_elements_state(struct pipe_context* pipe,
                                                unsigned count,
                                                const struct pipe_vertex_element* attribs)
 {
     struct r300_vertex_element_state *velems;
-    unsigned i, size;
+    unsigned i;
     enum pipe_format *format;
 
     assert(count <= PIPE_MAX_ATTRIBS);
@@ -1293,88 +1296,69 @@ static void* r300_create_vertex_elements_state(struct pipe_context* pipe,
     if (velems != NULL) {
         velems->count = count;
         memcpy(velems->velem, attribs, sizeof(struct pipe_vertex_element) * count);
+        velems->incompatible_layout = FALSE;
 
         if (r300_screen(pipe->screen)->caps.has_tcl) {
-            r300_vertex_psc(velems);
-
-            /* Check if the format is aligned to the size of DWORD.
-             * We only care about the blocksizes of the formats since
-             * swizzles are already set up. */
+            /* Set the best hw format in case the original format is not
+             * supported by hw. */
             for (i = 0; i < count; i++) {
-                format = &velems->velem[i].src_format;
+                velems->hw_format[i] = velems->velem[i].src_format;
+                format = &velems->hw_format[i];
 
-                /* Replace some formats with their aligned counterparts,
-                 * this is OK because we check for aligned strides too. */
+                /* This is basically the list of unsupported formats.
+                 * For now we don't care about the alignment, that's going to
+                 * be sorted out after the PSC setup. */
                 switch (*format) {
-                    /* Align to RGBA8. */
-                    case PIPE_FORMAT_R8_UNORM:
-                    case PIPE_FORMAT_R8G8_UNORM:
-                    case PIPE_FORMAT_R8G8B8_UNORM:
-                        *format = PIPE_FORMAT_R8G8B8A8_UNORM;
-                        continue;
-                    case PIPE_FORMAT_R8_SNORM:
-                    case PIPE_FORMAT_R8G8_SNORM:
-                    case PIPE_FORMAT_R8G8B8_SNORM:
-                        *format = PIPE_FORMAT_R8G8B8A8_SNORM;
-                        continue;
-                    case PIPE_FORMAT_R8_USCALED:
-                    case PIPE_FORMAT_R8G8_USCALED:
-                    case PIPE_FORMAT_R8G8B8_USCALED:
-                        *format = PIPE_FORMAT_R8G8B8A8_USCALED;
-                        continue;
-                    case PIPE_FORMAT_R8_SSCALED:
-                    case PIPE_FORMAT_R8G8_SSCALED:
-                    case PIPE_FORMAT_R8G8B8_SSCALED:
-                        *format = PIPE_FORMAT_R8G8B8A8_SSCALED;
-                        continue;
-
-                    /* Align to RG16. */
-                    case PIPE_FORMAT_R16_UNORM:
-                        *format = PIPE_FORMAT_R16G16_UNORM;
-                        continue;
-                    case PIPE_FORMAT_R16_SNORM:
-                        *format = PIPE_FORMAT_R16G16_SNORM;
-                        continue;
-                    case PIPE_FORMAT_R16_USCALED:
-                        *format = PIPE_FORMAT_R16G16_USCALED;
-                        continue;
-                    case PIPE_FORMAT_R16_SSCALED:
-                        *format = PIPE_FORMAT_R16G16_SSCALED;
-                        continue;
-                    case PIPE_FORMAT_R16_FLOAT:
-                        *format = PIPE_FORMAT_R16G16_FLOAT;
-                        continue;
-
-                    /* Align to RGBA16. */
-                    case PIPE_FORMAT_R16G16B16_UNORM:
-                        *format = PIPE_FORMAT_R16G16B16A16_UNORM;
-                        continue;
-                    case PIPE_FORMAT_R16G16B16_SNORM:
-                        *format = PIPE_FORMAT_R16G16B16A16_SNORM;
-                        continue;
-                    case PIPE_FORMAT_R16G16B16_USCALED:
-                        *format = PIPE_FORMAT_R16G16B16A16_USCALED;
-                        continue;
-                    case PIPE_FORMAT_R16G16B16_SSCALED:
-                        *format = PIPE_FORMAT_R16G16B16A16_SSCALED;
-                        continue;
-                    case PIPE_FORMAT_R16G16B16_FLOAT:
-                        *format = PIPE_FORMAT_R16G16B16A16_FLOAT;
-                        continue;
+                    FORMAT_REPLACE(R64_FLOAT,           R32_FLOAT);
+                    FORMAT_REPLACE(R64G64_FLOAT,        R32G32_FLOAT);
+                    FORMAT_REPLACE(R64G64B64_FLOAT,     R32G32B32_FLOAT);
+                    FORMAT_REPLACE(R64G64B64A64_FLOAT,  R32G32B32A32_FLOAT);
+
+                    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_USCALED,         R32_FLOAT);
+                    FORMAT_REPLACE(R32G32_USCALED,      R32G32_FLOAT);
+                    FORMAT_REPLACE(R32G32B32_USCALED,   R32G32B32_FLOAT);
+                    FORMAT_REPLACE(R32G32B32A32_USCALED,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);
+
+                    FORMAT_REPLACE(R32_SSCALED,         R32_FLOAT);
+                    FORMAT_REPLACE(R32G32_SSCALED,      R32G32_FLOAT);
+                    FORMAT_REPLACE(R32G32B32_SSCALED,   R32G32B32_FLOAT);
+                    FORMAT_REPLACE(R32G32B32A32_SSCALED,R32G32B32A32_FLOAT);
+
+                    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:;
                 }
 
-                size = util_format_get_blocksize(*format);
+                velems->incompatible_layout =
+                        velems->incompatible_layout ||
+                        velems->velem[i].src_format != velems->hw_format[i] ||
+                        velems->velem[i].src_offset % 4 != 0;
+            }
 
-                if (size % 4 != 0) {
-                    /* XXX Shouldn't we align the format? */
-                    fprintf(stderr, "r300_create_vertex_elements_state: "
-                            "Unaligned format %s:%i isn't supported\n",
-                            util_format_short_name(*format), size);
-                    assert(0);
-                    abort();
-                }
+            /* Now setup PSC.
+             * The unused components will be replaced by (..., 0, 1). */
+            r300_vertex_psc(velems);
+
+            /* Align the formats to the size of DWORD.
+             * We only care about the blocksizes of the formats since
+             * swizzles are already set up. */
+            for (i = 0; i < count; i++) {
+                /* This is OK because we check for aligned strides too. */
+                velems->hw_format_size[i] =
+                    align(util_format_get_blocksize(velems->hw_format[i]), 4);
             }
         }
     }



More information about the mesa-commit mailing list