Mesa (master): vc4: Add support for fragment discards.

Eric Anholt anholt at kemper.freedesktop.org
Fri Aug 22 17:19:15 UTC 2014


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

Author: Eric Anholt <eric at anholt.net>
Date:   Thu Aug 21 13:12:19 2014 -0700

vc4: Add support for fragment discards.

Fixes piglit glsl-fs-discard-01 and -03, and allows a lot of mesa demos to
start running.  glsl-fs-discard-02 has a problem where the first tile is
not getting stored on the first render.

---

 src/gallium/drivers/vc4/vc4_program.c  |   24 ++++++++++++++++++++++++
 src/gallium/drivers/vc4/vc4_qir.c      |    1 +
 src/gallium/drivers/vc4/vc4_qir.h      |    2 ++
 src/gallium/drivers/vc4/vc4_qpu_emit.c |   16 ++++++++++++++++
 4 files changed, 43 insertions(+)

diff --git a/src/gallium/drivers/vc4/vc4_program.c b/src/gallium/drivers/vc4/vc4_program.c
index 08ac5e8..d404047 100644
--- a/src/gallium/drivers/vc4/vc4_program.c
+++ b/src/gallium/drivers/vc4/vc4_program.c
@@ -47,6 +47,7 @@ struct tgsi_to_qir {
         struct qreg *uniforms;
         struct qreg *consts;
         struct qreg line_x, point_x, point_y;
+        struct qreg discard;
 
         uint32_t num_consts;
 
@@ -606,6 +607,19 @@ emit_vertex_input(struct tgsi_to_qir *trans, int attr)
 }
 
 static void
+tgsi_to_qir_kill_if(struct tgsi_to_qir *trans, struct qreg *src, int i)
+{
+        struct qcompile *c = trans->c;
+
+        if (trans->discard.file == QFILE_NULL)
+                trans->discard = qir_uniform_f(trans, 0.0);
+        trans->discard = qir_CMP(c,
+                                 src[0 * 4 + i],
+                                 qir_uniform_f(trans, 1.0),
+                                 trans->discard);
+}
+
+static void
 emit_fragcoord_input(struct tgsi_to_qir *trans, int attr)
 {
         struct qcompile *c = trans->c;
@@ -734,6 +748,13 @@ emit_tgsi_instruction(struct tgsi_to_qir *trans,
                 tgsi_to_qir_tex(trans, tgsi_inst,
                                 op_trans[tgsi_op].op, src_regs);
                 return;
+        case TGSI_OPCODE_KILL:
+                trans->discard = qir_uniform_f(trans, 1.0);
+                return;
+        case TGSI_OPCODE_KILL_IF:
+                for (int i = 0; i < 4; i++)
+                        tgsi_to_qir_kill_if(trans, src_regs, i);
+                return;
         default:
                 break;
         }
@@ -984,6 +1005,9 @@ emit_frag_end(struct tgsi_to_qir *trans)
                                                            format_swiz[i]);
         }
 
+        if (trans->discard.file != QFILE_NULL)
+                qir_TLB_DISCARD_SETUP(c, trans->discard);
+
         if (trans->fs_key->depth_enabled) {
                 qir_emit(c, qir_inst(QOP_TLB_PASSTHROUGH_Z_WRITE, c->undef,
                                      c->undef, c->undef));
diff --git a/src/gallium/drivers/vc4/vc4_qir.c b/src/gallium/drivers/vc4/vc4_qir.c
index aa1f40b..0b0d2c1 100644
--- a/src/gallium/drivers/vc4/vc4_qir.c
+++ b/src/gallium/drivers/vc4/vc4_qir.c
@@ -59,6 +59,7 @@ static const struct qir_op_info qir_op_info[] = {
         [QOP_PACK_SCALED] = { "pack_scaled", 1, 2 },
         [QOP_VPM_WRITE] = { "vpm_write", 0, 1, true },
         [QOP_VPM_READ] = { "vpm_read", 0, 1, true },
+        [QOP_TLB_DISCARD_SETUP] = { "discard", 0, 1, true },
         [QOP_TLB_PASSTHROUGH_Z_WRITE] = { "tlb_passthrough_z", 0, 0, true },
         [QOP_TLB_COLOR_WRITE] = { "tlb_color", 0, 1, true },
         [QOP_TLB_COLOR_READ] = { "tlb_color_read", 0, 0, true },
diff --git a/src/gallium/drivers/vc4/vc4_qir.h b/src/gallium/drivers/vc4/vc4_qir.h
index 9277d4a..77b5f1a 100644
--- a/src/gallium/drivers/vc4/vc4_qir.h
+++ b/src/gallium/drivers/vc4/vc4_qir.h
@@ -72,6 +72,7 @@ enum qop {
         QOP_PACK_COLORS,
         QOP_VPM_WRITE,
         QOP_VPM_READ,
+        QOP_TLB_DISCARD_SETUP,
         QOP_TLB_PASSTHROUGH_Z_WRITE,
         QOP_TLB_COLOR_WRITE,
         QOP_TLB_COLOR_READ,
@@ -280,6 +281,7 @@ QIR_ALU0(FRAG_X)
 QIR_ALU0(FRAG_Y)
 QIR_ALU0(FRAG_Z)
 QIR_ALU0(FRAG_RCP_W)
+QIR_NODST_1(TLB_DISCARD_SETUP)
 
 static inline struct qreg
 qir_CMP(struct qcompile *c, struct qreg cmp, struct qreg a, struct qreg b)
diff --git a/src/gallium/drivers/vc4/vc4_qpu_emit.c b/src/gallium/drivers/vc4/vc4_qpu_emit.c
index d777af6..415d2b0 100644
--- a/src/gallium/drivers/vc4/vc4_qpu_emit.c
+++ b/src/gallium/drivers/vc4/vc4_qpu_emit.c
@@ -213,6 +213,7 @@ vc4_generate_code(struct qcompile *c)
         int *reg_allocated = calloc(c->num_temps, sizeof(*reg_allocated));
         int *reg_uses_remaining =
                 calloc(c->num_temps, sizeof(*reg_uses_remaining));
+        bool discard = false;
 
         for (int i = 0; i < ARRAY_SIZE(reg_in_use); i++)
                 reg_in_use[i] = false;
@@ -508,10 +509,21 @@ vc4_generate_code(struct qcompile *c)
                                           qpu_m_NOP()));
                         break;
 
+                case QOP_TLB_DISCARD_SETUP:
+                        discard = true;
+                        queue(c, qpu_inst(qpu_a_MOV(src[0], src[0]),
+                                          qpu_m_NOP()));
+                        *last_inst(c) |= QPU_SF;
+                        break;
+
                 case QOP_TLB_PASSTHROUGH_Z_WRITE:
                         queue(c, qpu_inst(qpu_a_MOV(qpu_ra(QPU_W_TLB_Z),
                                                     qpu_rb(QPU_R_FRAG_PAYLOAD_ZW)),
                                           qpu_m_NOP()));
+                        if (discard) {
+                                *last_inst(c) = qpu_set_cond_add(*last_inst(c),
+                                                                 QPU_COND_ZS);
+                        }
                         break;
 
                 case QOP_TLB_COLOR_READ:
@@ -525,6 +537,10 @@ vc4_generate_code(struct qcompile *c)
                         queue(c, qpu_inst(qpu_a_MOV(qpu_tlbc(),
                                                     src[0]),
                                           qpu_m_NOP()));
+                        if (discard) {
+                                *last_inst(c) = qpu_set_cond_add(*last_inst(c),
+                                                                 QPU_COND_ZS);
+                        }
                         break;
 
                 case QOP_VARY_ADD_C:




More information about the mesa-commit mailing list