From: Eric Anholt Date: Fri, 22 Aug 2014 22:02:52 +0000 (-0700) Subject: vc4: Add support for 8-bit unorm/snorm vertex inputs. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=2e48b286bf21501ac06832799a4b7957bb8ac893;p=mesa.git vc4: Add support for 8-bit unorm/snorm vertex inputs. --- diff --git a/src/gallium/drivers/vc4/vc4_program.c b/src/gallium/drivers/vc4/vc4_program.c index 60d9ce92935..b7b64c0de3a 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 b4d6812311b..efba6d3c55e 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 f3e5332edfc..d1bfc77621e 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 3f30f2cd3c5..81b3b8bd784 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 204c080467e..639037e60f7 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 58d5f711376..4a5ce4feee7 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) &&