diff --git a/src/asahi/compiler/agx_compile.h b/src/asahi/compiler/agx_compile.h index 8dcca9dc824..a38aa0922b3 100644 --- a/src/asahi/compiler/agx_compile.h +++ b/src/asahi/compiler/agx_compile.h @@ -146,6 +146,17 @@ enum agx_format { AGX_NUM_FORMATS, }; +struct agx_vs_shader_key { + /* The GPU ABI requires all smooth shaded varyings to come first, then all + * flat shaded varyings, then all linear shaded varyings, as written by the + * VS. In order to correctly remap the varyings into the right order in the + * VS, we need to propagate the mask of flat/linear shaded varyings into the + * compiler. + */ + uint64_t outputs_flat_shaded; + uint64_t outputs_linear_shaded; +}; + struct agx_fs_shader_key { /* Normally, access to the tilebuffer must be guarded by appropriate fencing * instructions to ensure correct results in the presence of out-of-order @@ -172,6 +183,7 @@ struct agx_shader_key { unsigned reserved_preamble; union { + struct agx_vs_shader_key vs; struct agx_fs_shader_key fs; }; }; diff --git a/src/gallium/drivers/asahi/agx_state.c b/src/gallium/drivers/asahi/agx_state.c index 809a30dd32c..4ae696e1aa9 100644 --- a/src/gallium/drivers/asahi/agx_state.c +++ b/src/gallium/drivers/asahi/agx_state.c @@ -1455,7 +1455,9 @@ agx_compile_variant(struct agx_device *dev, struct agx_uncompiled_shader *so, } /* Clip plane lowering creates discard instructions, so run that before - * lowering discards. + * lowering discards. Note: this introduces extra loads from the clip + * plane outputs, but they use smooth interpolation so it does not affect + * the flat/linear masks that get propagated back to the VS. */ if (key->clip_plane_enable) { NIR_PASS_V(nir, nir_lower_clip_fs, key->clip_plane_enable, false); @@ -1494,6 +1496,11 @@ agx_compile_variant(struct agx_device *dev, struct agx_uncompiled_shader *so, if (nir->info.stage == MESA_SHADER_FRAGMENT) base_key.fs.nr_samples = key_->fs.nr_samples; + if (nir->info.stage == MESA_SHADER_VERTEX) { + base_key.vs.outputs_flat_shaded = key_->vs.outputs_flat_shaded; + base_key.vs.outputs_linear_shaded = key_->vs.outputs_linear_shaded; + } + NIR_PASS_V(nir, agx_nir_lower_sysvals, compiled, &base_key.reserved_preamble); @@ -1713,13 +1720,19 @@ agx_update_vs(struct agx_context *ctx) * * vb_mask, attributes, vertex_buffers: VERTEX * streamout.active: XFB + * outputs_{flat,linear}_shaded: FS_PROG */ - if (!(ctx->dirty & (AGX_DIRTY_VS_PROG | AGX_DIRTY_VERTEX | AGX_DIRTY_XFB))) + if (!(ctx->dirty & (AGX_DIRTY_VS_PROG | AGX_DIRTY_VERTEX | AGX_DIRTY_XFB | + AGX_DIRTY_FS_PROG))) return false; struct asahi_vs_shader_key key = { .vbuf.count = util_last_bit(ctx->vb_mask), .xfb = ctx->streamout.key, + .outputs_flat_shaded = + ctx->stage[PIPE_SHADER_FRAGMENT].shader->info.inputs_flat_shaded, + .outputs_linear_shaded = + ctx->stage[PIPE_SHADER_FRAGMENT].shader->info.inputs_linear_shaded, }; memcpy(key.vbuf.attributes, ctx->attributes, diff --git a/src/gallium/drivers/asahi/agx_state.h b/src/gallium/drivers/asahi/agx_state.h index 2d015530078..b109b96877c 100644 --- a/src/gallium/drivers/asahi/agx_state.h +++ b/src/gallium/drivers/asahi/agx_state.h @@ -286,6 +286,8 @@ struct agx_blend { struct asahi_vs_shader_key { struct agx_vbufs vbuf; struct agx_xfb_key xfb; + uint64_t outputs_flat_shaded; + uint64_t outputs_linear_shaded; }; struct asahi_fs_shader_key {