summaryrefslogtreecommitdiffstats
path: root/src/gallium/drivers/vc4
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/vc4')
-rw-r--r--src/gallium/drivers/vc4/vc4_context.h8
-rw-r--r--src/gallium/drivers/vc4/vc4_draw.c2
-rw-r--r--src/gallium/drivers/vc4/vc4_program.c27
-rw-r--r--src/gallium/drivers/vc4/vc4_qir.c1
-rw-r--r--src/gallium/drivers/vc4/vc4_qir.h3
-rw-r--r--src/gallium/drivers/vc4/vc4_qpu_emit.c4
-rw-r--r--src/gallium/drivers/vc4/vc4_simulator_validate_shaders.c4
-rw-r--r--src/gallium/drivers/vc4/vc4_state.c71
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;
}