diff --git a/src/asahi/lib/agx_device.h b/src/asahi/lib/agx_device.h index dfc7c1c76c5..787da7d8ba7 100644 --- a/src/asahi/lib/agx_device.h +++ b/src/asahi/lib/agx_device.h @@ -31,6 +31,7 @@ enum agx_dbg { AGX_DBG_SMALLTILE = BITFIELD_BIT(14), AGX_DBG_NOMSAA = BITFIELD_BIT(15), AGX_DBG_NOSHADOW = BITFIELD_BIT(16), + AGX_DBG_VARYINGS = BITFIELD_BIT(17), }; /* Dummy partial declarations, pending real UAPI */ diff --git a/src/gallium/drivers/asahi/agx_pipe.c b/src/gallium/drivers/asahi/agx_pipe.c index b4f6a7fee8a..74003e542f1 100644 --- a/src/gallium/drivers/asahi/agx_pipe.c +++ b/src/gallium/drivers/asahi/agx_pipe.c @@ -74,6 +74,7 @@ static const struct debug_named_value agx_debug_options[] = { {"nomsaa", AGX_DBG_NOMSAA, "Force disable MSAA"}, {"noshadow", AGX_DBG_NOSHADOW, "Force disable resource shadowing"}, {"noclipctrl",AGX_DBG_NOCLIPCTRL,"Disable ARB_clip_control"}, + {"varyings", AGX_DBG_VARYINGS, "Validate varying linkage"}, DEBUG_NAMED_VALUE_END }; /* clang-format on */ diff --git a/src/gallium/drivers/asahi/agx_state.c b/src/gallium/drivers/asahi/agx_state.c index 9c702ac54a7..957eceb2dca 100644 --- a/src/gallium/drivers/asahi/agx_state.c +++ b/src/gallium/drivers/asahi/agx_state.c @@ -1482,7 +1482,7 @@ asahi_cs_shader_key_equal(const void *a, const void *b) static unsigned agx_find_linked_slot(struct agx_varyings_vs *vs, struct agx_varyings_fs *fs, - gl_varying_slot slot, unsigned offset) + gl_varying_slot slot, unsigned offset, bool debug) { assert(offset < 4); assert(slot != VARYING_SLOT_PNTC && "point coords aren't linked"); @@ -1500,15 +1500,21 @@ agx_find_linked_slot(struct agx_varyings_vs *vs, struct agx_varyings_fs *fs, unsigned vs_index = vs->slots[slot]; - /* If the layer is read but not written, its value will be ignored by the - * agx_nir_predicate_layer_id lowering, so read garbage. - */ - if (vs_index >= vs->nr_index && slot == VARYING_SLOT_LAYER) + if (!(vs_index < vs->nr_index)) { + /* Varyings not written by vertex shader are undefined, be robust. + * + * If the layer is read but not written, its value will be ignored by the + * agx_nir_predicate_layer_id lowering, so read garbage. + * + * For other varyings, this is probably an app bug. + */ + if (unlikely(debug && (slot != VARYING_SLOT_LAYER))) + unreachable("Fragment shader read varying not written by vertex!"); + return 0; + } assert(vs_index >= 4 && "gl_Position should have been the first 4 slots"); - assert(vs_index < vs->nr_index && - "varyings not written by vertex shader are undefined"); assert((vs_index < vs->base_index_fp16) == ((vs_index + offset) < vs->base_index_fp16) && "a given varying must have a consistent type"); @@ -1571,10 +1577,12 @@ agx_link_varyings_vs_fs(struct agx_pool *pool, struct agx_varyings_vs *vs, assert(fs->bindings[i].offset == 0); cfg.source = AGX_COEFFICIENT_SOURCE_POINT_COORD; } else { - cfg.base_slot = agx_find_linked_slot(vs, fs, fs->bindings[i].slot, - fs->bindings[i].offset); + cfg.base_slot = agx_find_linked_slot( + vs, fs, fs->bindings[i].slot, fs->bindings[i].offset, + pool->dev->debug & AGX_DBG_VARYINGS); - assert(cfg.base_slot + cfg.components <= nr_slots && + assert(cfg.base_slot + cfg.components <= + MAX2(nr_slots, cfg.components) && "overflow slots"); }