panfrost/bi: Emit varying descriptors based on the VS varying layout

Signed-off-by: Lorenzo Rossi <lorenzo.rossi@collabora.com>
Reviewed-by: Faith Ekstrand <faith.ekstrand@collabora.com>
Acked-by: Eric R. Smith <eric.smith@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/38681>
This commit is contained in:
Lorenzo Rossi 2026-01-29 20:04:56 +01:00 committed by Marge Bot
parent 70398866a1
commit 0c4d2c8722
2 changed files with 72 additions and 77 deletions

View file

@ -2548,8 +2548,9 @@ pan_varying_index(unsigned present, enum pan_special_varying v)
static inline unsigned
panfrost_bi_varying_present(const struct panfrost_device *dev,
struct pan_shader_info *producer,
struct pan_shader_info *consumer, uint16_t point_coord_mask)
const struct panfrost_compiled_shader *producer,
const struct panfrost_compiled_shader *consumer,
uint16_t point_coord_mask)
{
/* At the moment we always emit general and position buffers. Not
* strictly necessary but usually harmless */
@ -2557,28 +2558,35 @@ panfrost_bi_varying_present(const struct panfrost_device *dev,
unsigned present =
BITFIELD_BIT(PAN_VARY_GENERAL) | BITFIELD_BIT(PAN_VARY_POSITION);
const struct pan_shader_info *prod_info = &producer->info;
/* Enable special buffers by the shader info */
if (producer->vs.writes_point_size)
if (prod_info->vs.writes_point_size)
present |= BITFIELD_BIT(PAN_VARY_PSIZ);
#if PAN_ARCH <= 5
/* On Midgard, these exist as real varyings. Later architectures use
* LD_VAR_SPECIAL reads instead. */
const struct pan_shader_info *cons_info = &consumer->info;
if (consumer->fs.reads_point_coord)
if (cons_info->fs.reads_point_coord)
present |= BITFIELD_BIT(PAN_VARY_PNTCOORD);
if (consumer->fs.reads_face)
if (cons_info->fs.reads_face)
present |= BITFIELD_BIT(PAN_VARY_FACE);
if (consumer->fs.reads_frag_coord)
if (cons_info->fs.reads_frag_coord)
present |= BITFIELD_BIT(PAN_VARY_FRAGCOORD);
/* Also, if we have a point sprite, we need a point coord buffer */
for (unsigned i = 0; i < consumer->varyings.input_count; i++) {
gl_varying_slot loc = consumer->varyings.input[i].location;
const struct pan_varying_layout *layout = &consumer->info.varyings.formats;
for (unsigned i = 0; i < layout->count; i++) {
const struct pan_varying_slot *slot =
pan_varying_layout_slot_at(layout, i);
if (!slot) continue;
gl_varying_slot loc = slot->location;
if (util_varying_is_point_coord(loc, point_coord_mask))
present |= BITFIELD_BIT(PAN_VARY_PNTCOORD);
@ -2656,48 +2664,14 @@ pan_find_vary(const struct pan_shader_varying *vary, unsigned vary_count,
return -1;
}
/* Assign varying locations for the general buffer. Returns the calculated
* per-vertex stride, and outputs offsets into the passed array. Negative
* offset indicates a varying is not used. */
static unsigned
pan_assign_varyings(const struct panfrost_device *dev,
struct pan_shader_info *producer,
struct pan_shader_info *consumer, signed *offsets)
{
unsigned producer_count = producer->varyings.output_count;
unsigned consumer_count = consumer->varyings.input_count;
const struct pan_shader_varying *producer_vars = producer->varyings.output;
const struct pan_shader_varying *consumer_vars = consumer->varyings.input;
unsigned stride = 0;
for (unsigned i = 0; i < producer_count; ++i) {
signed loc = pan_find_vary(consumer_vars, consumer_count,
producer_vars[i].location);
enum pipe_format format =
loc >= 0 ? consumer_vars[loc].format : PIPE_FORMAT_NONE;
if (format != PIPE_FORMAT_NONE) {
offsets[i] = stride;
stride += util_format_get_blocksize(format);
} else {
offsets[i] = -1;
}
}
return stride;
}
/* Emitter for a single varying (attribute) descriptor */
static void
panfrost_bi_emit_varying(const struct panfrost_device *dev,
struct mali_attribute_packed *out,
const struct pan_shader_varying varying,
gl_varying_slot loc,
enum pipe_format pipe_format, unsigned present,
uint16_t point_sprite_mask, signed offset,
uint16_t point_sprite_mask, unsigned offset,
enum pan_special_varying pos_varying)
{
/* Note: varying.format != pipe_format in some obscure cases due to a
@ -2705,7 +2679,6 @@ panfrost_bi_emit_varying(const struct panfrost_device *dev,
* eliminate the additional lookups. See:
* dEQP-GLES3.functional.shaders.conditionals.if.sequence_statements_vertex
*/
gl_varying_slot loc = varying.location;
mali_pixel_format format =
GENX(pan_format_from_pipe_format)(pipe_format)->hw;
@ -2717,7 +2690,7 @@ panfrost_bi_emit_varying(const struct panfrost_device *dev,
pan_emit_vary_special(dev, out, present, PAN_VARY_PSIZ);
} else if (loc == VARYING_SLOT_FACE) {
pan_emit_vary_special(dev, out, present, PAN_VARY_FACE);
} else if (offset < 0) {
} else if (pipe_format == PIPE_FORMAT_NONE) {
pan_emit_vary(dev, out, 0, (MALI_CONSTANT << 12), 0);
} else {
STATIC_ASSERT(PAN_VARY_GENERAL == 0);
@ -2734,18 +2707,26 @@ panfrost_bi_emit_varying_descs(struct panfrost_pool *pool,
struct panfrost_compiled_shader *consumer,
uint16_t point_coord_mask, struct pan_linkage *out)
{
assert(producer->info.stage == MESA_SHADER_VERTEX);
assert(consumer->info.stage == MESA_SHADER_FRAGMENT);
struct panfrost_device *dev = pool->dev;
unsigned producer_count = producer->info.varyings.output_count;
unsigned consumer_count = consumer->info.varyings.input_count;
bool loc_matched[VARYING_SLOT_MAX] = {false};
/* Offsets within the general varying buffer, indexed by location */
signed offsets[PAN_MAX_VARYINGS];
assert(producer_count <= ARRAY_SIZE(offsets));
assert(consumer_count <= ARRAY_SIZE(offsets));
const struct pan_varying_layout *vs_layout = &producer->info.varyings.formats;
/* These do not contain any layout, but contain the format */
const struct pan_varying_layout *fs_layout = &consumer->info.varyings.formats;
pan_varying_layout_require_layout(vs_layout);
pan_varying_layout_require_format(fs_layout);
const unsigned vs_count = vs_layout->count;
const unsigned fs_count = fs_layout->count;
/* Allocate enough descriptors for both shader stages */
struct pan_ptr T = pan_pool_alloc_desc_array(
&pool->base, producer_count + consumer_count, ATTRIBUTE);
&pool->base, vs_count + fs_count, ATTRIBUTE);
/* Take a reference if we're being put on the CSO */
if (!pool->owned) {
@ -2754,43 +2735,57 @@ panfrost_bi_emit_varying_descs(struct panfrost_pool *pool,
}
struct mali_attribute_packed *descs = T.cpu;
out->producer = producer_count ? T.gpu : 0;
out->consumer =
consumer_count ? T.gpu + (pan_size(ATTRIBUTE) * producer_count) : 0;
out->producer = vs_count ? T.gpu : 0;
out->consumer = fs_count ? T.gpu + (pan_size(ATTRIBUTE) * vs_count) : 0;
/* Count the required buffers */
out->present = panfrost_bi_varying_present(
dev, &producer->info, &consumer->info, point_coord_mask);
dev, producer, consumer, point_coord_mask);
out->stride =
pan_assign_varyings(dev, &producer->info, &consumer->info, offsets);
out->stride = vs_layout->generic_size_B;
for (unsigned i = 0; i < producer_count; ++i) {
signed j = pan_find_vary(consumer->info.varyings.input,
consumer->info.varyings.input_count,
producer->info.varyings.output[i].location);
for (unsigned i = 0; i < fs_count; i++) {
const struct pan_varying_slot *fs_slot =
pan_varying_layout_slot_at(fs_layout, i);
if (!fs_slot)
continue;
enum pipe_format format = (j >= 0)
? consumer->info.varyings.input[j].format
: producer->info.varyings.output[i].format;
unsigned offset = 0;
enum pipe_format format = PIPE_FORMAT_NONE;
panfrost_bi_emit_varying(dev, descs + i, producer->info.varyings.output[i],
format, out->present, 0, offsets[i],
PAN_VARY_POSITION);
}
const struct pan_varying_slot *vs_slot =
pan_varying_layout_find_slot(vs_layout, fs_slot->location);
for (unsigned i = 0; i < consumer_count; ++i) {
signed j = pan_find_vary(producer->info.varyings.output,
producer->info.varyings.output_count,
consumer->info.varyings.input[i].location);
if (vs_slot) {
offset = vs_slot->offset;
/* Trust the bit-size from VS */
nir_alu_type base_type = nir_alu_type_get_base_type(fs_slot->alu_type);
nir_alu_type bit_size = nir_alu_type_get_type_size(vs_slot->alu_type);
if (vs_slot->section == PAN_VARYING_SECTION_GENERIC)
format = pan_varying_format(base_type | bit_size, vs_slot->ncomps);
signed offset = (j >= 0) ? offsets[j] : -1;
loc_matched[fs_slot->location] = true;
}
panfrost_bi_emit_varying(
dev, descs + producer_count + i, consumer->info.varyings.input[i],
consumer->info.varyings.input[i].format, out->present,
dev, descs + vs_count + i, fs_slot->location, format, out->present,
point_coord_mask, offset, PAN_VARY_FRAGCOORD);
}
/* Now just write the computed formats and offsets in the right order */
for (unsigned i = 0; i < vs_count; ++i) {
const struct pan_varying_slot *slot =
pan_varying_layout_slot_at(vs_layout, i);
if (!slot)
continue;
enum pipe_format format = PIPE_FORMAT_NONE;
if (loc_matched[slot->location] && slot->section == PAN_VARYING_SECTION_GENERIC)
format = pan_varying_format(slot->alu_type, slot->ncomps);
panfrost_bi_emit_varying(
dev, descs + i, slot->location, format, out->present,
0, slot->offset, PAN_VARY_POSITION);
}
}
#if PAN_ARCH <= 5

View file

@ -777,7 +777,7 @@ jm_emit_malloc_vertex_job(struct panfrost_batch *batch,
pan_section_pack(job, MALLOC_VERTEX_JOB, ALLOCATION, cfg) {
if (secondary_shader) {
unsigned sz = panfrost_vertex_attribute_stride(vs, fs);
unsigned sz = vs->info.varyings.formats.generic_size_B;
cfg.vertex_packet_stride = sz + 16;
cfg.vertex_attribute_stride = sz;
} else {