diff options
-rw-r--r-- | src/gallium/drivers/vc4/vc4_context.h | 8 | ||||
-rw-r--r-- | src/gallium/drivers/vc4/vc4_draw.c | 2 | ||||
-rw-r--r-- | src/gallium/drivers/vc4/vc4_program.c | 27 | ||||
-rw-r--r-- | src/gallium/drivers/vc4/vc4_qir.c | 1 | ||||
-rw-r--r-- | src/gallium/drivers/vc4/vc4_qir.h | 3 | ||||
-rw-r--r-- | src/gallium/drivers/vc4/vc4_qpu_emit.c | 4 | ||||
-rw-r--r-- | src/gallium/drivers/vc4/vc4_simulator_validate_shaders.c | 4 | ||||
-rw-r--r-- | 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 e5864333a68..549becdbf66 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 90d98b37b01..c88e43cf823 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 c6603767b5e..1afb587754b 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 69152e79dda..6196b92e2e0 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 2ab30496aad..833795afcc5 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 592fab90785..b8524e36e20 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 40b7f35309b..183cd4c977e 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 58c300e6549..c7757709ee6 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; } |