panfrost: Plumb VS varying_layout in FS
Some checks are pending
macOS-CI / macOS-CI (dri) (push) Waiting to run
macOS-CI / macOS-CI (xlib) (push) Waiting to run

This allows us to use LD_VAR_BUF instead of LD_VAR when the shaders are
linked together.

Signed-off-by: Lorenzo Rossi <lorenzo.rossi@collabora.com>
Reviewed-by: Christoph Pillmayer <christoph.pillmayer@arm.com>
Reviewed-by: Erik Faye-Lund <erik.faye-lund@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/40761>
This commit is contained in:
Lorenzo Rossi 2026-05-12 18:10:20 +02:00 committed by Marge Bot
parent 12b9a23cb5
commit 32ca5f7515
2 changed files with 75 additions and 11 deletions

View file

@ -346,6 +346,13 @@ struct panfrost_fs_key {
uint8_t clip_plane_enable;
bool line_smooth;
/* The VS varying layout determines how the FS is compiled (LD_VAR vs
* LD_VAR_BUF and byte offsets). Include the full layout in the key so
* the disk cache and in-memory variant cache correctly distinguish FS
* binaries compiled against different VS layouts.
*/
struct pan_varying_layout vs_varying_layout;
};
struct panfrost_vs_key {
@ -403,6 +410,9 @@ struct panfrost_uncompiled_shader {
/* Stream output information */
struct pipe_stream_output_info stream_output;
/* Varying layout (if known) */
struct pan_varying_layout vs_varying_layout;
/** Lock for the variants array */
simple_mtx_t lock;

View file

@ -94,6 +94,7 @@ lower_sample_mask_writes(nir_builder *b, nir_intrinsic_instr *intrin,
static void
panfrost_shader_compile(struct panfrost_screen *screen, const nir_shader *ir,
struct util_debug_callback *dbg,
const struct pan_varying_layout *varying_layout,
struct panfrost_shader_key *key, unsigned req_local_mem,
struct panfrost_shader_binary *out)
{
@ -133,15 +134,7 @@ panfrost_shader_compile(struct panfrost_screen *screen, const nir_shader *ir,
/* nir_opt_varyings is replacing all flat highp types with float32, we need
* to figure out the varying types ourselves */
inputs.trust_varying_flat_highp_types = false;
struct pan_varying_layout varyings_layout;
/* TODO: wire up VS layout in FS when linked together */
if (s->info.stage == MESA_SHADER_VERTEX) {
pan_varying_collect_formats(&varyings_layout, s,
inputs.gpu_id,
inputs.trust_varying_flat_highp_types, false);
pan_build_varying_layout_compact(&varyings_layout, s, inputs.gpu_id);
inputs.varying_layout = &varyings_layout;
}
inputs.varying_layout = varying_layout;
if (s->info.stage == MESA_SHADER_FRAGMENT) {
if (key->fs.nr_cbufs_for_fragcolor) {
@ -262,8 +255,12 @@ panfrost_shader_get(struct pipe_screen *pscreen,
*/
if (!panfrost_disk_cache_retrieve(screen->disk_cache, uncompiled,
&state->key, &res)) {
panfrost_shader_compile(screen, uncompiled->nir, dbg, &state->key,
req_local_mem, &res);
const struct pan_varying_layout *varying_layout =
uncompiled->vs_varying_layout.known != 0
? &uncompiled->vs_varying_layout : NULL;
panfrost_shader_compile(screen, uncompiled->nir, dbg, varying_layout,
&state->key, req_local_mem, &res);
panfrost_disk_cache_store(screen->disk_cache, uncompiled, &state->key,
&res);
@ -332,6 +329,8 @@ panfrost_build_fs_key(struct panfrost_context *ctx,
key->line_smooth = rast->line_smooth;
}
key->vs_varying_layout = uncompiled->vs_varying_layout;
if (dev->arch <= 5) {
u_foreach_bit(i, (nir->info.outputs_read >> FRAG_RESULT_DATA0)) {
enum pipe_format fmt = PIPE_FORMAT_R8G8B8A8_UNORM;
@ -485,6 +484,8 @@ panfrost_default_shader_key(struct panfrost_uncompiled_shader *so)
*/
if (so->fragcolor_lowered)
key.fs.nr_cbufs_for_fragcolor = 1;
key.fs.vs_varying_layout = so->vs_varying_layout;
}
return key;
@ -574,6 +575,16 @@ panfrost_create_shader_state(struct pipe_context *pctx,
so->noperspective_varyings =
pan_nir_collect_noperspective_varyings_fs(nir);
if (nir->info.stage == MESA_SHADER_VERTEX) {
struct pan_varying_layout *varying_layout = &so->vs_varying_layout;
pan_varying_collect_formats(varying_layout, nir,
panfrost_device_gpu_id(dev),
false, /* trust_varying_flat_highp_types */
false /* lower_mediump */);
pan_build_varying_layout_compact(varying_layout, nir,
panfrost_device_gpu_id(dev));
}
/* If this shader uses transform feedback, compile the transform
* feedback program. This is a special shader variant.
*/
@ -592,6 +603,14 @@ panfrost_create_shader_state(struct pipe_context *pctx,
nir->info.has_transform_feedback_varyings = false;
}
/* If we're not using separate shaders, the FS can use VS varying_layout to
* optimize loads (LD_VAR_BUF instead of LD_VAR). Gallium won't provide us
* with the VS directly, so we need to delay the default variant compilation
* until link time
*/
if (nir->info.stage == MESA_SHADER_FRAGMENT && !nir->info.separate_shader)
return so;
/* Compile the program. We don't use vertex shader keys, so there will
* be no further vertex shader variants. We do have fragment shader
* keys, but we can still compile with a default key that will work most
@ -632,6 +651,39 @@ panfrost_delete_shader_state(struct pipe_context *pctx, void *so)
ralloc_free(so);
}
static void
panfrost_link_shader(struct pipe_context *pctx, void** handles)
{
struct panfrost_context *ctx = pan_context(pctx);
struct panfrost_uncompiled_shader *vs = handles[MESA_SHADER_VERTEX];
struct panfrost_uncompiled_shader *fs = handles[MESA_SHADER_FRAGMENT];
if (!fs || fs->nir->info.separate_shader)
return;
/* We only handle VS and FS for now, it's not clear how varying layout will
* fit when more shader types are supported. So assert those are the only
* shaders present.
*/
for (unsigned i = 0; i < MESA_SHADER_MESH_STAGES; i++) {
if (i != MESA_SHADER_VERTEX && i != MESA_SHADER_FRAGMENT)
assert(handles[i] == NULL);
}
/* Only copy the varying layout if we have a VS, sometimes we don't have one
* (e.g. fixed-function VS), in those cases we just compile a default FS.
*/
if (vs)
fs->vs_varying_layout = vs->vs_varying_layout;
simple_mtx_lock(&fs->lock);
struct panfrost_shader_key key = panfrost_default_shader_key(fs);
panfrost_new_variant_locked(ctx, fs, &key);
simple_mtx_unlock(&fs->lock);
}
/*
* Create a compute CSO. As compute kernels do not require variants, they are
* precompiled, creating both the uncompiled and compiled shaders now.
@ -698,6 +750,8 @@ panfrost_shader_context_init(struct pipe_context *pctx)
pctx->delete_fs_state = panfrost_delete_shader_state;
pctx->bind_fs_state = panfrost_bind_fs_state;
pctx->link_shader = panfrost_link_shader;
pctx->create_compute_state = panfrost_create_compute_state;
pctx->bind_compute_state = panfrost_bind_compute_state;
pctx->get_compute_state_info = panfrost_get_compute_state_info;