Module: Mesa Branch: main Commit: 9645fa9107916287bad05afda7443a016dec2767 URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=9645fa9107916287bad05afda7443a016dec2767
Author: Alyssa Rosenzweig <[email protected]> Date: Wed Dec 15 21:01:19 2021 -0500 agx: Handle discard intrinsics Lower to `sample_mask = 0`. Actually that implements a demote... doing discard correctly probably requires rewriting the shader control flow to insert a return where necessary... Also, possibly we should be lowering this in NIR to play nice with gl_SampleMask writes but that's a problem for when we understand the hardware better. Signed-off-by: Alyssa Rosenzweig <[email protected]> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14219> --- src/asahi/compiler/agx_compile.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/src/asahi/compiler/agx_compile.c b/src/asahi/compiler/agx_compile.c index da71f79d715..9424bfe44e5 100644 --- a/src/asahi/compiler/agx_compile.c +++ b/src/asahi/compiler/agx_compile.c @@ -278,6 +278,15 @@ agx_emit_fragment_out(agx_builder *b, nir_intrinsic_instr *instr) agx_writeout(b, 0x000C); } + if (b->shader->nir->info.fs.uses_discard) { + /* If the shader uses discard, the sample mask must be written by the + * shader on all exeuction paths. If we've reached the end of the shader, + * we are therefore still active and need to write a full sample mask. + * TODO: interactions with MSAA and gl_SampleMask writes + */ + agx_sample_mask(b, agx_immediate(1)); + } + b->shader->did_writeout = true; return agx_st_tile(b, agx_src_index(&instr->src[0]), b->shader->key->fs.tib_formats[rt]); @@ -391,6 +400,25 @@ agx_blend_const(agx_builder *b, agx_index dst, unsigned comp) return agx_mov_to(b, dst, val); } +/* + * Demoting a helper invocation is logically equivalent to zeroing the sample + * mask. Metal implement discard as such. + * + * XXX: Actually, Metal's "discard" is a demote, and what is implemented here + * is a demote. There might be a better way to implement this to get correct + * helper invocation semantics. For now, I'm kicking the can down the road. + */ +static agx_instr * +agx_emit_discard(agx_builder *b, nir_intrinsic_instr *instr) +{ + agx_writeout(b, 0xC200); + agx_writeout(b, 0x0001); + b->shader->did_writeout = true; + + b->shader->out->writes_sample_mask = true; + return agx_sample_mask(b, agx_immediate(0)); +} + static agx_instr * agx_emit_intrinsic(agx_builder *b, nir_intrinsic_instr *instr) { @@ -437,6 +465,9 @@ agx_emit_intrinsic(agx_builder *b, nir_intrinsic_instr *instr) case nir_intrinsic_load_frag_coord: return agx_emit_load_frag_coord(b, instr); + case nir_intrinsic_discard: + return agx_emit_discard(b, instr); + case nir_intrinsic_load_back_face_agx: return agx_get_sr_to(b, dst, AGX_SR_BACKFACING);
