asahi: extend epilog key for force early frag handling

need to be extra careful around the sample mask.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/29179>
This commit is contained in:
Alyssa Rosenzweig 2024-04-27 11:33:10 -04:00 committed by Marge Bot
parent ee9dab83e7
commit 48d16b3972
2 changed files with 25 additions and 11 deletions

View File

@ -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;

View File

@ -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)