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

Author: Eric Anholt <[email protected]>
Date:   Thu Sep 18 12:22:07 2014 -0700

vc4: Add support for stencil operations.

While depth test state is passed through the fragment shader as sideband,
data, the stencil test state has to be set by the fragment shader itself.

Many tests are still failing, but this gets most of hiz/ passing.

---

 src/gallium/drivers/vc4/vc4_context.h              |    8 +++
 src/gallium/drivers/vc4/vc4_draw.c                 |    2 +
 src/gallium/drivers/vc4/vc4_program.c              |   27 +++++++-
 src/gallium/drivers/vc4/vc4_qir.c                  |    1 +
 src/gallium/drivers/vc4/vc4_qir.h                  |    3 +
 src/gallium/drivers/vc4/vc4_qpu_emit.c             |    4 ++
 .../drivers/vc4/vc4_simulator_validate_shaders.c   |    4 +-
 src/gallium/drivers/vc4/vc4_state.c                |   71 ++++++++++++++++++++
 8 files changed, 118 insertions(+), 2 deletions(-)

diff --git a/src/gallium/drivers/vc4/vc4_context.h 
b/src/gallium/drivers/vc4/vc4_context.h
index e586433..549becd 100644
--- a/src/gallium/drivers/vc4/vc4_context.h
+++ b/src/gallium/drivers/vc4/vc4_context.h
@@ -203,6 +203,14 @@ struct vc4_depth_stencil_alpha_state {
 
         /* VC4_CONFIGURATION_BITS */
         uint8_t config_bits[3];
+
+        /** Uniforms for stencil state.
+         *
+         * Index 0 is either the front config, or the front-and-back config.
+         * Index 1 is the back config if doing separate back stencil.
+         * Index 2 is the writemask config if it's not a common mask value.
+         */
+        uint32_t stencil_uniforms[3];
 };
 
 static inline struct vc4_context *
diff --git a/src/gallium/drivers/vc4/vc4_draw.c 
b/src/gallium/drivers/vc4/vc4_draw.c
index 90d98b3..c88e43c 100644
--- a/src/gallium/drivers/vc4/vc4_draw.c
+++ b/src/gallium/drivers/vc4/vc4_draw.c
@@ -190,6 +190,8 @@ vc4_draw_vbo(struct pipe_context *pctx, const struct 
pipe_draw_info *info)
         if (vc4->zsa && vc4->zsa->base.depth.enabled) {
                 vc4->resolve |= PIPE_CLEAR_DEPTH;
         }
+        if (vc4->zsa && vc4->zsa->base.stencil[0].enabled)
+                vc4->resolve |= PIPE_CLEAR_STENCIL;
         vc4->resolve |= PIPE_CLEAR_COLOR0;
 
         vc4->shader_rec_count++;
diff --git a/src/gallium/drivers/vc4/vc4_program.c 
b/src/gallium/drivers/vc4/vc4_program.c
index c660376..1afb587 100644
--- a/src/gallium/drivers/vc4/vc4_program.c
+++ b/src/gallium/drivers/vc4/vc4_program.c
@@ -53,6 +53,9 @@ struct vc4_fs_key {
         struct vc4_key base;
         enum pipe_format color_format;
         bool depth_enabled;
+        bool stencil_enabled;
+        bool stencil_twoside;
+        bool stencil_full_writemasks;
         bool is_points;
         bool is_lines;
 
@@ -1253,6 +1256,16 @@ emit_frag_end(struct vc4_compile *c)
         if (c->discard.file != QFILE_NULL)
                 qir_TLB_DISCARD_SETUP(c, c->discard);
 
+        if (c->fs_key->stencil_enabled) {
+                qir_TLB_STENCIL_SETUP(c, add_uniform(c, QUNIFORM_STENCIL, 0));
+                if (c->fs_key->stencil_twoside) {
+                        qir_TLB_STENCIL_SETUP(c, add_uniform(c, 
QUNIFORM_STENCIL, 1));
+                }
+                if (c->fs_key->stencil_full_writemasks) {
+                        qir_TLB_STENCIL_SETUP(c, add_uniform(c, 
QUNIFORM_STENCIL, 2));
+                }
+        }
+
         if (c->fs_key->depth_enabled) {
                 struct qreg z;
                 if (c->output_position_index != -1) {
@@ -1567,7 +1580,11 @@ vc4_update_compiled_fs(struct vc4_context *vc4, uint8_t 
prim_mode)
         if (vc4->framebuffer.cbufs[0])
                 key->color_format = vc4->framebuffer.cbufs[0]->format;
 
-        key->depth_enabled = vc4->zsa->base.depth.enabled;
+        key->stencil_enabled = vc4->zsa->stencil_uniforms[0] != 0;
+        key->stencil_twoside = vc4->zsa->stencil_uniforms[1] != 0;
+        key->stencil_full_writemasks = vc4->zsa->stencil_uniforms[2] != 0;
+        key->depth_enabled = (vc4->zsa->base.depth.enabled ||
+                              key->stencil_enabled);
 
         vc4->prog.fs = util_hash_table_get(vc4->fs_cache, key);
         if (vc4->prog.fs)
@@ -1826,6 +1843,14 @@ vc4_write_uniforms(struct vc4_context *vc4, struct 
vc4_compiled_shader *shader,
                         cl_f(&vc4->uniforms,
                              vc4->blend_color.color[uinfo->data[i]]);
                         break;
+
+                case QUNIFORM_STENCIL:
+                        cl_u32(&vc4->uniforms,
+                               vc4->zsa->stencil_uniforms[uinfo->data[i]] |
+                               (uinfo->data[i] <= 1 ?
+                                (vc4->stencil_ref.ref_value[uinfo->data[i]] << 
8) :
+                                0));
+                        break;
                 }
 #if 0
                 uint32_t written_val = *(uint32_t *)(vc4->uniforms.next - 4);
diff --git a/src/gallium/drivers/vc4/vc4_qir.c 
b/src/gallium/drivers/vc4/vc4_qir.c
index 69152e7..6196b92 100644
--- a/src/gallium/drivers/vc4/vc4_qir.c
+++ b/src/gallium/drivers/vc4/vc4_qir.c
@@ -77,6 +77,7 @@ static const struct qir_op_info qir_op_info[] = {
         [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_STENCIL_SETUP] = { "tlb_stencil_setup", 0, 1, true },
         [QOP_TLB_Z_WRITE] = { "tlb_z", 0, 1, true },
         [QOP_TLB_COLOR_WRITE] = { "tlb_color", 0, 1, true },
         [QOP_TLB_COLOR_READ] = { "tlb_color_read", 1, 0, true },
diff --git a/src/gallium/drivers/vc4/vc4_qir.h 
b/src/gallium/drivers/vc4/vc4_qir.h
index 2ab3049..833795a 100644
--- a/src/gallium/drivers/vc4/vc4_qir.h
+++ b/src/gallium/drivers/vc4/vc4_qir.h
@@ -97,6 +97,7 @@ enum qop {
         QOP_VPM_WRITE,
         QOP_VPM_READ,
         QOP_TLB_DISCARD_SETUP,
+        QOP_TLB_STENCIL_SETUP,
         QOP_TLB_Z_WRITE,
         QOP_TLB_COLOR_WRITE,
         QOP_TLB_COLOR_READ,
@@ -199,6 +200,7 @@ enum quniform_contents {
         QUNIFORM_TEXRECT_SCALE_Y,
 
         QUNIFORM_BLEND_CONST_COLOR,
+        QUNIFORM_STENCIL,
 };
 
 struct vc4_compile {
@@ -366,6 +368,7 @@ QIR_ALU0(TEX_RESULT)
 QIR_ALU0(TLB_COLOR_READ)
 QIR_NODST_1(TLB_Z_WRITE)
 QIR_NODST_1(TLB_DISCARD_SETUP)
+QIR_NODST_1(TLB_STENCIL_SETUP)
 
 static inline struct qreg
 qir_R4_UNPACK(struct vc4_compile *c, struct qreg r4, int i)
diff --git a/src/gallium/drivers/vc4/vc4_qpu_emit.c 
b/src/gallium/drivers/vc4/vc4_qpu_emit.c
index 592fab9..b8524e3 100644
--- a/src/gallium/drivers/vc4/vc4_qpu_emit.c
+++ b/src/gallium/drivers/vc4/vc4_qpu_emit.c
@@ -419,6 +419,10 @@ vc4_generate_code(struct vc4_compile *c)
                         *last_inst(c) |= QPU_SF;
                         break;
 
+                case QOP_TLB_STENCIL_SETUP:
+                        queue(c, qpu_a_MOV(qpu_ra(QPU_W_TLB_STENCIL_SETUP), 
src[0]));
+                        break;
+
                 case QOP_TLB_Z_WRITE:
                         queue(c, qpu_a_MOV(qpu_ra(QPU_W_TLB_Z), src[0]));
                         if (discard) {
diff --git a/src/gallium/drivers/vc4/vc4_simulator_validate_shaders.c 
b/src/gallium/drivers/vc4/vc4_simulator_validate_shaders.c
index 40b7f35..183cd4c 100644
--- a/src/gallium/drivers/vc4/vc4_simulator_validate_shaders.c
+++ b/src/gallium/drivers/vc4/vc4_simulator_validate_shaders.c
@@ -153,7 +153,6 @@ check_register_write(struct vc4_validated_shader_info 
*validated_shader,
 
        case QPU_W_HOST_INT:
        case QPU_W_TMU_NOSWAP:
-       case QPU_W_TLB_STENCIL_SETUP:
        case QPU_W_TLB_ALPHA_MASK:
        case QPU_W_MUTEX_RELEASE:
                /* XXX: I haven't thought about these, so don't support them
@@ -173,6 +172,9 @@ check_register_write(struct vc4_validated_shader_info 
*validated_shader,
                 * triggered by QPU_W_VPM_ADDR writes.
                 */
                return true;
+
+       case QPU_W_TLB_STENCIL_SETUP:
+                return true;
        }
 
        return true;
diff --git a/src/gallium/drivers/vc4/vc4_state.c 
b/src/gallium/drivers/vc4/vc4_state.c
index 58c300e..c775770 100644
--- a/src/gallium/drivers/vc4/vc4_state.c
+++ b/src/gallium/drivers/vc4/vc4_state.c
@@ -116,6 +116,50 @@ vc4_create_blend_state(struct pipe_context *pctx,
         return vc4_generic_cso_state_create(cso, sizeof(*cso));
 }
 
+/**
+ * The TLB_STENCIL_SETUP data has a little bitfield for common writemask
+ * values, so you don't have to do a separate writemask setup.
+ */
+static uint8_t
+tlb_stencil_setup_writemask(uint8_t mask)
+{
+        switch (mask) {
+        case 0x1: return 0;
+        case 0x3: return 1;
+        case 0xf: return 2;
+        case 0xff: return 3;
+        default: return 0xff;
+        }
+}
+
+static uint32_t
+tlb_stencil_setup_bits(const struct pipe_stencil_state *state,
+                       uint8_t writemask_bits)
+{
+        static const uint8_t op_map[] = {
+                [PIPE_STENCIL_OP_ZERO] = 0,
+                [PIPE_STENCIL_OP_KEEP] = 1,
+                [PIPE_STENCIL_OP_REPLACE] = 2,
+                [PIPE_STENCIL_OP_INCR] = 3,
+                [PIPE_STENCIL_OP_DECR] = 4,
+                [PIPE_STENCIL_OP_INVERT] = 5,
+                [PIPE_STENCIL_OP_INCR_WRAP] = 6,
+                [PIPE_STENCIL_OP_DECR_WRAP] = 7,
+        };
+        uint32_t bits = 0;
+
+        if (writemask_bits != 0xff)
+                bits |= writemask_bits << 28;
+        bits |= op_map[state->zfail_op] << 25;
+        bits |= op_map[state->zpass_op] << 22;
+        bits |= op_map[state->fail_op] << 19;
+        bits |= state->func << 16;
+        /* Ref is filled in at uniform upload time */
+        bits |= state->valuemask << 0;
+
+        return bits;
+}
+
 static void *
 vc4_create_depth_stencil_alpha_state(struct pipe_context *pctx,
                                      const struct 
pipe_depth_stencil_alpha_state *cso)
@@ -139,6 +183,33 @@ vc4_create_depth_stencil_alpha_state(struct pipe_context 
*pctx,
                                        VC4_CONFIG_BITS_DEPTH_FUNC_SHIFT);
         }
 
+        if (cso->stencil[0].enabled) {
+                const struct pipe_stencil_state *front = &cso->stencil[0];
+                const struct pipe_stencil_state *back = &cso->stencil[1];
+
+                uint8_t front_writemask_bits =
+                        tlb_stencil_setup_writemask(front->writemask);
+                uint8_t back_writemask_bits =
+                        tlb_stencil_setup_writemask(back->writemask);
+
+                so->stencil_uniforms[0] =
+                        tlb_stencil_setup_bits(front, front_writemask_bits);
+                if (back->enabled) {
+                        so->stencil_uniforms[0] |= (1 << 30);
+                        so->stencil_uniforms[1] =
+                                tlb_stencil_setup_bits(back, 
back_writemask_bits);
+                        so->stencil_uniforms[1] |= (2 << 30);
+                } else {
+                        so->stencil_uniforms[0] |= (3 << 30);
+                }
+
+                if (front_writemask_bits == 0xff ||
+                    back_writemask_bits == 0xff) {
+                        so->stencil_uniforms[2] = (front_writemask_bits |
+                                                   (back_writemask_bits << 8));
+                }
+        }
+
         return so;
 }
 

_______________________________________________
mesa-commit mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/mesa-commit

Reply via email to