agx: Lower discard to zs_emit when zs_emit used

It is invalid to use both sample_mask and zs_emit in the same shader. We'll need
to do something similar for sample mask writes.

Fixes Dolphin ubershaders.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20446>
This commit is contained in:
Alyssa Rosenzweig 2022-12-27 15:09:24 -05:00
parent ebe40b15ea
commit fa96dfb2d7
2 changed files with 46 additions and 0 deletions

View file

@ -463,6 +463,11 @@ agx_emit_local_store_pixel(agx_builder *b, nir_intrinsic_instr *instr)
*/
agx_sample_mask(b, agx_immediate(1));
b->shader->did_sample_mask = true;
assert(!(b->shader->nir->info.outputs_written &
(BITFIELD64_BIT(FRAG_RESULT_DEPTH) |
BITFIELD64_BIT(FRAG_RESULT_STENCIL))) &&
"incompatible");
}
/* Compact the registers according to the mask */
@ -504,6 +509,7 @@ agx_emit_store_zs(agx_builder *b, nir_intrinsic_instr *instr)
* maybe rename this flag to something more general.
*/
b->shader->out->writes_sample_mask = true;
assert(!b->shader->did_sample_mask && "incompatible");
return agx_zs_emit(b, agx_src_index(&instr->src[0]), zs, base);
}

View file

@ -62,11 +62,47 @@ lower(nir_function_impl *impl, nir_block *block)
return progress;
}
static bool
lower_discard_to_z(nir_builder *b, nir_instr *instr, UNUSED void *data)
{
if (instr->type != nir_instr_type_intrinsic)
return false;
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
if (intr->intrinsic != nir_intrinsic_discard &&
intr->intrinsic != nir_intrinsic_discard_if)
return false;
b->cursor = nir_before_instr(instr);
if (intr->intrinsic == nir_intrinsic_discard_if)
nir_push_if(b, intr->src[0].ssa);
bool stencil_written =
b->shader->info.outputs_written & BITFIELD64_BIT(FRAG_RESULT_STENCIL);
nir_store_zs_agx(b, nir_imm_intN_t(b, ALL_SAMPLES, 16),
nir_imm_float(b, NAN),
stencil_written ? nir_imm_intN_t(b, 0, 16)
: nir_ssa_undef(b, 1, 16) /* stencil */,
.base = BASE_Z | (stencil_written ? BASE_S : 0));
if (intr->intrinsic == nir_intrinsic_discard_if)
nir_push_else(b, NULL);
nir_instr_remove(instr);
return false;
}
bool
agx_nir_lower_zs_emit(nir_shader *s)
{
bool any_progress = false;
if (!(s->info.outputs_written & (BITFIELD64_BIT(FRAG_RESULT_STENCIL) |
BITFIELD64_BIT(FRAG_RESULT_DEPTH))))
return false;
nir_foreach_function(function, s) {
if (!function->impl)
continue;
@ -87,5 +123,9 @@ agx_nir_lower_zs_emit(nir_shader *s)
any_progress |= progress;
}
any_progress |= nir_shader_instructions_pass(
s, lower_discard_to_z, nir_metadata_block_index | nir_metadata_dominance,
NULL);
s->info.fs.uses_discard = false;
return any_progress;
}