diff options
author | Eric Anholt <[email protected]> | 2016-08-26 13:57:09 -0700 |
---|---|---|
committer | Eric Anholt <[email protected]> | 2016-08-29 11:03:11 -0700 |
commit | 60bed14d0fdc3a05b6251b4ffc6013b5d3ca3e0f (patch) | |
tree | a66021502eb0ced924df355e1f544914248ab714 /src/gallium/drivers | |
parent | b9a74fbec7e3fe8c159a3a18447a416e09c68693 (diff) |
vc4: Handle discards while in control flow.
I missed this while adding loop support because the discard test inside a
loop was crashing before, anyway. Fixes piglit glsl-fs-discard-04.
Diffstat (limited to 'src/gallium/drivers')
-rw-r--r-- | src/gallium/drivers/vc4/vc4_program.c | 33 | ||||
-rw-r--r-- | src/gallium/drivers/vc4/vc4_qir.h | 1 |
2 files changed, 28 insertions, 6 deletions
diff --git a/src/gallium/drivers/vc4/vc4_program.c b/src/gallium/drivers/vc4/vc4_program.c index 19bb8a332b4..b1189bf4c6b 100644 --- a/src/gallium/drivers/vc4/vc4_program.c +++ b/src/gallium/drivers/vc4/vc4_program.c @@ -1236,7 +1236,7 @@ emit_frag_end(struct vc4_compile *c) } uint32_t discard_cond = QPU_COND_ALWAYS; - if (c->discard.file != QFILE_NULL) { + if (c->s->info.fs.uses_discard) { qir_SF(c, c->discard); discard_cond = QPU_COND_ZS; } @@ -1721,15 +1721,33 @@ ntq_emit_intrinsic(struct vc4_compile *c, nir_intrinsic_instr *instr) break; case nir_intrinsic_discard: - c->discard = qir_uniform_ui(c, ~0); + if (c->execute.file != QFILE_NULL) { + qir_SF(c, c->execute); + qir_MOV_cond(c, QPU_COND_ZS, c->discard, + qir_uniform_ui(c, ~0)); + } else { + qir_MOV_dest(c, c->discard, qir_uniform_ui(c, ~0)); + } break; - case nir_intrinsic_discard_if: - if (c->discard.file == QFILE_NULL) - c->discard = qir_uniform_ui(c, 0); - c->discard = qir_OR(c, c->discard, + case nir_intrinsic_discard_if: { + /* true (~0) if we're discarding */ + struct qreg cond = ntq_get_src(c, instr->src[0], 0); + + if (c->execute.file != QFILE_NULL) { + /* execute == 0 means the channel is active. Invert + * the condition so that we can use zero as "executing + * and discarding." + */ + qir_SF(c, qir_AND(c, c->execute, qir_NOT(c, cond))); + qir_MOV_cond(c, QPU_COND_ZS, c->discard, cond); + } else { + qir_OR_dest(c, c->discard, c->discard, ntq_get_src(c, instr->src[0], 0)); + } + break; + } default: fprintf(stderr, "Unknown intrinsic: "); @@ -2001,6 +2019,9 @@ ntq_emit_impl(struct vc4_compile *c, nir_function_impl *impl) static void nir_to_qir(struct vc4_compile *c) { + if (c->stage == QSTAGE_FRAG && c->s->info.fs.uses_discard) + c->discard = qir_MOV(c, qir_uniform_ui(c, 0)); + ntq_setup_inputs(c); ntq_setup_outputs(c); ntq_setup_uniforms(c); diff --git a/src/gallium/drivers/vc4/vc4_qir.h b/src/gallium/drivers/vc4/vc4_qir.h index a82c47c0341..36652167595 100644 --- a/src/gallium/drivers/vc4/vc4_qir.h +++ b/src/gallium/drivers/vc4/vc4_qir.h @@ -448,6 +448,7 @@ struct vc4_compile { struct qreg execute; struct qreg line_x, point_x, point_y; + /** boolean (~0 -> true) if the fragment has been discarded. */ struct qreg discard; struct qreg payload_FRAG_Z; struct qreg payload_FRAG_W; |