diff --git a/src/asahi/lib/agx_linker.h b/src/asahi/lib/agx_linker.h index 06ce2362074f5..fe2e40afbc0e3 100644 --- a/src/asahi/lib/agx_linker.h +++ b/src/asahi/lib/agx_linker.h @@ -102,30 +102,44 @@ struct agx_fs_epilog_link_info { */ uint8_t size_32; + /* Mask of render targets written by the main shader */ + uint8_t rt_written; + /* If set, the API fragment shader uses sample shading. This means the epilog * will be invoked per-sample as well. */ - bool sample_shading; + unsigned sample_shading : 1; /* If set, broadcast the render target #0 value to all render targets. This * implements gl_FragColor semantics. */ - bool broadcast_rt0; + unsigned broadcast_rt0 : 1; /* If set, force render target 0's W channel to 1.0. This optimizes blending * calculations in some applications. */ - bool rt0_w_1; + unsigned rt0_w_1 : 1; /* If set, the API fragment shader wants to write depth/stencil respectively. * This happens in the epilog for correctness when the epilog discards. */ - bool write_z, write_s; + unsigned write_z : 1; + unsigned write_s : 1; - /* Mask of render targets written by the main shader */ - uint8_t rt_written; + /* Whether the fragment prolog or main fragment shader already ran tests due + * to early_fragment_tests. In this case, the epilog must not run tests. + */ + unsigned already_ran_zs : 1; + + /* Whether the main fragment shader ran tests before discards due to + * early_fragment_tests. In this case, the epilog must mask the stores in + * software instead. + */ + bool sample_mask_after_force_early : 1; + + unsigned padding : 1; }; -static_assert(sizeof(struct agx_fs_epilog_link_info) == 8, "packed"); +static_assert(sizeof(struct agx_fs_epilog_link_info) == 4, "packed"); struct agx_fs_epilog_key { struct agx_fs_epilog_link_info link; diff --git a/src/asahi/lib/agx_nir_prolog_epilog.c b/src/asahi/lib/agx_nir_prolog_epilog.c index 4f0fc8c31505b..e9ce52af58d3a 100644 --- a/src/asahi/lib/agx_nir_prolog_epilog.c +++ b/src/asahi/lib/agx_nir_prolog_epilog.c @@ -432,9 +432,9 @@ agx_nir_fs_epilog(nir_builder *b, const void *key_) NULL); /* There is no shader part after the epilog, so we're always responsible for - * running our own tests. + * running our own tests, unless the fragment shader forced early tests. */ - NIR_PASS(_, b->shader, lower_tests_zs, true); + NIR_PASS(_, b->shader, lower_tests_zs, !key->link.already_ran_zs); b->shader->info.io_lowered = true; b->shader->info.fs.uses_fbfetch_output |= force_translucent; @@ -450,8 +450,8 @@ lower_output_to_epilog(nir_builder *b, nir_intrinsic_instr *intr, void *data) b->cursor = nir_instr_remove(&intr->instr); unsigned base = nir_intrinsic_base(intr); - info->write_z = base & 1; - info->write_s = base & 2; + info->write_z = !!(base & 1); + info->write_s = !!(base & 2); /* ABI: r2 contains the written depth */ if (info->write_z)