From fd0068612f2ab5aa46a9de437cb4fec8824003e5 Mon Sep 17 00:00:00 2001 From: Alyssa Rosenzweig Date: Tue, 6 Feb 2024 17:52:32 -0400 Subject: [PATCH] agx: remove discard -> zs_emit lower doesn't seem to be necessary, the Sonoma compiler uses sample_mask-based discards even with zs_emit. Signed-off-by: Alyssa Rosenzweig Part-of: --- .../compiler/agx_nir_lower_sample_mask.c | 84 ++++--------------- 1 file changed, 14 insertions(+), 70 deletions(-) diff --git a/src/asahi/compiler/agx_nir_lower_sample_mask.c b/src/asahi/compiler/agx_nir_lower_sample_mask.c index e28bf606f05..8cfd176387a 100644 --- a/src/asahi/compiler/agx_nir_lower_sample_mask.c +++ b/src/asahi/compiler/agx_nir_lower_sample_mask.c @@ -52,8 +52,8 @@ * sample_mask ~0, ~discarded * sample_mask ~0, ~0 <-- incorrect: depth/stencil tests run twice * - * 4. If zs_emit is used anywhere in the shader, sample_mask must not be used. - * Instead, zs_emit with depth = NaN can be emitted. + * 4. zs_emit may be used in the shader exactly once to trigger tests. + * sample_mask with 0 may be used to discard early. * * This pass lowers discard_agx to sample_mask instructions satisfying these * rules. Other passes should not generate sample_mask instructions, as there @@ -64,48 +64,6 @@ #define BASE_Z 1 #define BASE_S 2 -static bool -lower_sample_mask_to_zs(nir_builder *b, nir_intrinsic_instr *intr, - UNUSED void *data) -{ - bool depth_written = - b->shader->info.outputs_written & BITFIELD64_BIT(FRAG_RESULT_DEPTH); - bool stencil_written = - b->shader->info.outputs_written & BITFIELD64_BIT(FRAG_RESULT_STENCIL); - - b->cursor = nir_before_instr(&intr->instr); - - /* Existing zs_emit instructions need to be fixed up to write their own depth - * for consistency. - */ - if (intr->intrinsic == nir_intrinsic_store_zs_agx && !depth_written) { - /* Load the current depth at this pixel */ - nir_def *z = nir_load_frag_coord_zw(b, .component = 2); - - /* Write it out from this store_zs */ - nir_intrinsic_set_base(intr, nir_intrinsic_base(intr) | BASE_Z); - nir_src_rewrite(&intr->src[1], z); - - /* We'll set outputs_written after the pass in case there are multiple - * store_zs_agx instructions needing fixup. - */ - b->shader->info.fs.depth_layout = FRAG_DEPTH_LAYOUT_ANY; - return true; - } - - if (intr->intrinsic != nir_intrinsic_discard_agx) - return false; - - /* Write a NaN depth value for discarded samples */ - nir_store_zs_agx(b, intr->src[0].ssa, nir_imm_float(b, NAN), - stencil_written ? nir_imm_intN_t(b, 0, 16) - : nir_undef(b, 1, 16) /* stencil */, - .base = BASE_Z | (stencil_written ? BASE_S : 0)); - - nir_instr_remove(&intr->instr); - return true; -} - static bool lower_discard_to_sample_mask_0(nir_builder *b, nir_intrinsic_instr *intr, UNUSED void *data) @@ -205,42 +163,28 @@ run_tests_at_start(nir_shader *shader) bool agx_nir_lower_sample_mask(nir_shader *shader, unsigned nr_samples) { + bool writes_zs = + shader->info.outputs_written & + (BITFIELD64_BIT(FRAG_RESULT_STENCIL) | BITFIELD64_BIT(FRAG_RESULT_DEPTH)); + if (shader->info.fs.early_fragment_tests) { /* run tests early, if we need testing */ - if (shader->info.fs.uses_discard || - (shader->info.outputs_written & - (BITFIELD64_BIT(FRAG_RESULT_STENCIL) | - BITFIELD64_BIT(FRAG_RESULT_DEPTH))) || + if (shader->info.fs.uses_discard || writes_zs || shader->info.writes_memory) { run_tests_at_start(shader); } } else if (shader->info.fs.uses_discard) { - /* sample_mask can't be used with zs_emit, so lower sample_mask to zs_emit. - * We ignore depth/stencil writes with early fragment testing though. + /* If we have zs_emit, the tests will be triggered by zs_emit, otherwise + * we need to trigger tests explicitly. Allow sample_mask with zs_emit. */ - if (shader->info.outputs_written & - (BITFIELD64_BIT(FRAG_RESULT_DEPTH) | - BITFIELD64_BIT(FRAG_RESULT_STENCIL))) { - bool progress = nir_shader_intrinsics_pass( - shader, lower_sample_mask_to_zs, - nir_metadata_block_index | nir_metadata_dominance, NULL); + if (!writes_zs) { + nir_function_impl *impl = nir_shader_get_entrypoint(shader); + nir_builder b = nir_builder_create(impl); - /* The lowering requires an unconditional depth write. We mark this - * after lowering so the lowering knows whether there was already a - * depth write - */ - assert(progress && "must have lowered something,given the outputs"); - shader->info.outputs_written |= BITFIELD64_BIT(FRAG_RESULT_DEPTH); - - return true; + /* run tests late */ + run_tests_after_last_discard(&b); } - - nir_function_impl *impl = nir_shader_get_entrypoint(shader); - nir_builder b = nir_builder_create(impl); - - /* run tests late */ - run_tests_after_last_discard(&b); } else { /* regular shaders that don't use discard have nothing to lower */ return false;