Mesa (master): vc4: Add support for 8-bit unorm/snorm vertex inputs.

Eric Anholt anholt at kemper.freedesktop.org
Tue Sep 23 21:52:58 UTC 2014


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

Author: Eric Anholt <eric at anholt.net>
Date:   Fri Aug 22 15:02:52 2014 -0700

vc4: Add support for 8-bit unorm/snorm vertex inputs.

---

 src/gallium/drivers/vc4/vc4_program.c           |   42 +++++++++++++++++------
 src/gallium/drivers/vc4/vc4_qir.c               |    4 +++
 src/gallium/drivers/vc4/vc4_qir.h               |   13 +++++++
 src/gallium/drivers/vc4/vc4_qpu_emit.c          |   25 ++++++++++++++
 src/gallium/drivers/vc4/vc4_register_allocate.c |    8 +++++
 src/gallium/drivers/vc4/vc4_screen.c            |   25 ++++++++++----
 6 files changed, 101 insertions(+), 16 deletions(-)

diff --git a/src/gallium/drivers/vc4/vc4_program.c b/src/gallium/drivers/vc4/vc4_program.c
index 60d9ce9..b7b64c0 100644
--- a/src/gallium/drivers/vc4/vc4_program.c
+++ b/src/gallium/drivers/vc4/vc4_program.c
@@ -805,19 +805,41 @@ emit_vertex_input(struct vc4_compile *c, int attr)
 
         for (int i = 0; i < 4; i++) {
                 uint8_t swiz = desc->swizzle[i];
+                struct qreg result;
 
-                if (swiz <= UTIL_FORMAT_SWIZZLE_W &&
-                    !format_warned &&
-                    (desc->channel[swiz].type != UTIL_FORMAT_TYPE_FLOAT ||
-                     desc->channel[swiz].size != 32)) {
-                        fprintf(stderr,
-                                "vtx element %d unsupported type: %s\n",
-                                attr, util_format_name(format));
-                        format_warned = true;
+                if (swiz > UTIL_FORMAT_SWIZZLE_W)
+                        result = get_swizzled_channel(c, vpm_reads, swiz);
+                else if (desc->channel[swiz].size == 32 &&
+                         desc->channel[swiz].type == UTIL_FORMAT_TYPE_FLOAT) {
+                        result = get_swizzled_channel(c, vpm_reads, swiz);
+                } else if (desc->channel[swiz].size == 8 &&
+                           (desc->channel[swiz].type == UTIL_FORMAT_TYPE_UNSIGNED ||
+                            desc->channel[swiz].type == UTIL_FORMAT_TYPE_SIGNED) &&
+                           desc->channel[swiz].normalized) {
+                        struct qreg vpm = vpm_reads[0];
+                        if (desc->channel[swiz].type == UTIL_FORMAT_TYPE_SIGNED)
+                                vpm = qir_XOR(c, vpm, qir_uniform_ui(c, 0x80808080));
+                        result = qir_UNPACK_8(c, vpm, swiz);
+                } else {
+                        if (!format_warned) {
+                                fprintf(stderr,
+                                        "vtx element %d unsupported type: %s\n",
+                                        attr, util_format_name(format));
+                                format_warned = true;
+                        }
+                        result = qir_uniform_f(c, 0.0);
                 }
 
-                c->inputs[attr * 4 + i] =
-                        get_swizzled_channel(c, vpm_reads, swiz);
+                if (desc->channel[swiz].normalized &&
+                    desc->channel[swiz].type == UTIL_FORMAT_TYPE_SIGNED) {
+                        result = qir_FSUB(c,
+                                          qir_FMUL(c,
+                                                   result,
+                                                   qir_uniform_f(c, 2.0)),
+                                          qir_uniform_f(c, 1.0));
+                }
+
+                c->inputs[attr * 4 + i] = result;
         }
 }
 
diff --git a/src/gallium/drivers/vc4/vc4_qir.c b/src/gallium/drivers/vc4/vc4_qir.c
index b4d6812..efba6d3 100644
--- a/src/gallium/drivers/vc4/vc4_qir.c
+++ b/src/gallium/drivers/vc4/vc4_qir.c
@@ -97,6 +97,10 @@ static const struct qir_op_info qir_op_info[] = {
         [QOP_R4_UNPACK_B] = { "r4_unpack_b", 1, 1 },
         [QOP_R4_UNPACK_C] = { "r4_unpack_c", 1, 1 },
         [QOP_R4_UNPACK_D] = { "r4_unpack_d", 1, 1 },
+        [QOP_UNPACK_8A] = { "unpack_8a", 1, 1 },
+        [QOP_UNPACK_8B] = { "unpack_8b", 1, 1 },
+        [QOP_UNPACK_8C] = { "unpack_8c", 1, 1 },
+        [QOP_UNPACK_8D] = { "unpack_8d", 1, 1 },
 };
 
 static const char *
diff --git a/src/gallium/drivers/vc4/vc4_qir.h b/src/gallium/drivers/vc4/vc4_qir.h
index f3e5332..d1bfc77 100644
--- a/src/gallium/drivers/vc4/vc4_qir.h
+++ b/src/gallium/drivers/vc4/vc4_qir.h
@@ -108,6 +108,11 @@ enum qop {
         QOP_FRAG_Z,
         QOP_FRAG_W,
 
+        QOP_UNPACK_8A,
+        QOP_UNPACK_8B,
+        QOP_UNPACK_8C,
+        QOP_UNPACK_8D,
+
         /** Texture x coordinate parameter write */
         QOP_TEX_S,
         /** Texture y coordinate parameter write */
@@ -386,4 +391,12 @@ qir_SEL_X_0_COND(struct vc4_compile *c, int i)
         return t;
 }
 
+static inline struct qreg
+qir_UNPACK_8(struct vc4_compile *c, struct qreg src, int i)
+{
+        struct qreg t = qir_get_temp(c);
+        qir_emit(c, qir_inst(QOP_UNPACK_8A + i, t, src, c->undef));
+        return t;
+}
+
 #endif /* VC4_QIR_H */
diff --git a/src/gallium/drivers/vc4/vc4_qpu_emit.c b/src/gallium/drivers/vc4/vc4_qpu_emit.c
index 3f30f2c..81b3b8b 100644
--- a/src/gallium/drivers/vc4/vc4_qpu_emit.c
+++ b/src/gallium/drivers/vc4/vc4_qpu_emit.c
@@ -490,6 +490,31 @@ vc4_generate_code(struct vc4_context *vc4, struct vc4_compile *c)
 
                         break;
 
+                case QOP_UNPACK_8A:
+                case QOP_UNPACK_8B:
+                case QOP_UNPACK_8C:
+                case QOP_UNPACK_8D: {
+                        assert(src[0].mux == QPU_MUX_A);
+
+                        /* And, since we're setting the pack bits, if the
+                         * destination is in A it would get re-packed.
+                         */
+                        struct qpu_reg orig_dst = dst;
+                        if (orig_dst.mux == QPU_MUX_A)
+                                dst = qpu_rn(3);
+
+                        queue(c, qpu_a_FMAX(dst, src[0], src[0]));
+                        *last_inst(c) |= QPU_SET_FIELD(QPU_UNPACK_8A +
+                                                       (qinst->op -
+                                                        QOP_UNPACK_8A),
+                                                       QPU_UNPACK);
+
+                        if (orig_dst.mux == QPU_MUX_A) {
+                                queue(c, qpu_a_MOV(orig_dst, dst));
+                        }
+                }
+                        break;
+
                 default:
                         assert(qinst->op < ARRAY_SIZE(translate));
                         assert(translate[qinst->op].op != 0); /* NOPs */
diff --git a/src/gallium/drivers/vc4/vc4_register_allocate.c b/src/gallium/drivers/vc4/vc4_register_allocate.c
index 204c080..639037e 100644
--- a/src/gallium/drivers/vc4/vc4_register_allocate.c
+++ b/src/gallium/drivers/vc4/vc4_register_allocate.c
@@ -212,6 +212,14 @@ vc4_register_allocate(struct vc4_context *vc4, struct vc4_compile *c)
                         ra_set_node_class(g, inst->dst.index, vc4->reg_class_a);
                         break;
 
+                case QOP_UNPACK_8A:
+                case QOP_UNPACK_8B:
+                case QOP_UNPACK_8C:
+                case QOP_UNPACK_8D:
+                        /* The unpack flags require an A-file src register. */
+                        ra_set_node_class(g, inst->src[0].index, vc4->reg_class_a);
+                        break;
+
                 default:
                         break;
                 }
diff --git a/src/gallium/drivers/vc4/vc4_screen.c b/src/gallium/drivers/vc4/vc4_screen.c
index 58d5f71..4a5ce4f 100644
--- a/src/gallium/drivers/vc4/vc4_screen.c
+++ b/src/gallium/drivers/vc4/vc4_screen.c
@@ -327,12 +327,25 @@ vc4_screen_is_format_supported(struct pipe_screen *pscreen,
                 return FALSE;
         }
 
-        if (usage & PIPE_BIND_VERTEX_BUFFER &&
-            (format == PIPE_FORMAT_R32G32B32A32_FLOAT ||
-             format == PIPE_FORMAT_R32G32B32_FLOAT ||
-             format == PIPE_FORMAT_R32G32_FLOAT ||
-             format == PIPE_FORMAT_R32_FLOAT)) {
-                retval |= PIPE_BIND_VERTEX_BUFFER;
+        if (usage & PIPE_BIND_VERTEX_BUFFER) {
+                switch (format) {
+                case PIPE_FORMAT_R32G32B32A32_FLOAT:
+                case PIPE_FORMAT_R32G32B32_FLOAT:
+                case PIPE_FORMAT_R32G32_FLOAT:
+                case PIPE_FORMAT_R32_FLOAT:
+                case PIPE_FORMAT_R8G8B8A8_UNORM:
+                case PIPE_FORMAT_R8G8B8_UNORM:
+                case PIPE_FORMAT_R8G8_UNORM:
+                case PIPE_FORMAT_R8_UNORM:
+                case PIPE_FORMAT_R8G8B8A8_SNORM:
+                case PIPE_FORMAT_R8G8B8_SNORM:
+                case PIPE_FORMAT_R8G8_SNORM:
+                case PIPE_FORMAT_R8_SNORM:
+                        retval |= PIPE_BIND_VERTEX_BUFFER;
+                        break;
+                default:
+                        break;
+                }
         }
 
         if ((usage & PIPE_BIND_RENDER_TARGET) &&




More information about the mesa-commit mailing list