panvk: Add FS read support for PrimitiveID

Adds support for reading PrimitiveID in a fragment shader assuming the
previous shader was vertex.

If support for shaders that can modify PrimitiveID is added, additional
changes will be required.

Reviewed-by: Boris Brezillon <boris.brezillon@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35367>
This commit is contained in:
Lars-Ivar Hesselberg Simonsen
2025-06-02 16:57:52 +02:00
committed by Marge Bot
parent 49a7b1a5b8
commit e6d53fc1d8
6 changed files with 62 additions and 0 deletions
+4
View File
@@ -2231,6 +2231,10 @@ bi_emit_intrinsic(bi_builder *b, nir_intrinsic_instr *instr)
bi_load_sample_id_to(b, dst);
break;
case nir_intrinsic_load_primitive_id:
bi_mov_i32_to(b, dst, bi_preload(b, 57));
break;
case nir_intrinsic_load_front_face: {
/* (r58 & 1) == 0 means primitive is front facing */
bi_index primitive_facing = bi_preload(b, 58);
+3
View File
@@ -143,6 +143,9 @@ pan_shader_compile(nir_shader *s, struct pan_compile_inputs *inputs,
info->fs.reads_frag_coord =
(s->info.inputs_read & (1 << VARYING_SLOT_POS)) ||
BITSET_TEST(s->info.system_values_read, SYSTEM_VALUE_FRAG_COORD);
info->fs.reads_primitive_id =
(s->info.inputs_read & (1 << VARYING_SLOT_PRIMITIVE_ID)) ||
BITSET_TEST(s->info.system_values_read, SYSTEM_VALUE_PRIMITIVE_ID);
info->fs.reads_point_coord =
s->info.inputs_read & (1 << VARYING_SLOT_PNTC);
info->fs.reads_face =
+1
View File
@@ -206,6 +206,7 @@ struct pan_shader_info {
struct {
bool reads_frag_coord;
bool reads_point_coord;
bool reads_primitive_id;
bool reads_face;
bool can_discard;
bool writes_depth;
@@ -2085,6 +2085,8 @@ set_tiler_idvs_flags(struct cs_builder *b, struct panvk_cmd_buffer *cmdbuf,
if (dirty) {
pan_pack(&tiler_idvs_flags, PRIMITIVE_FLAGS, cfg) {
cfg.draw_mode = translate_prim_topology(ia->primitive_topology);
cfg.primitive_index_enable =
fs ? fs->info.fs.reads_primitive_id : false;
#if PAN_ARCH < 13
cfg.point_size_array_format = writes_point_size
@@ -835,11 +835,14 @@ panvk_emit_tiler_primitive(struct panvk_cmd_buffer *cmdbuf,
vs->info.vs.writes_point_size &&
ia->primitive_topology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
bool secondary_shader = vs->info.vs.secondary_enable && fs != NULL;
bool fs_reads_primitive_id = fs ? fs->info.fs.reads_primitive_id : false;
pan_pack(prim, PRIMITIVE, cfg) {
cfg.draw_mode = translate_prim_topology(ia->primitive_topology);
if (writes_point_size)
cfg.point_size_array_format = MALI_POINT_SIZE_ARRAY_FORMAT_FP16;
cfg.primitive_index_enable = fs_reads_primitive_id;
cfg.primitive_index_writeback = fs_reads_primitive_id;
cfg.first_provoking_vertex =
cmdbuf->state.gfx.render.first_provoking_vertex != U_TRISTATE_NO;
@@ -900,6 +903,24 @@ panvk_emit_tiler_primitive_size(struct panvk_cmd_buffer *cmdbuf,
}
}
static uint32_t
primitive_vertex_count(enum mali_draw_mode in)
{
switch (in) {
case MALI_DRAW_MODE_POINTS:
return 1;
case MALI_DRAW_MODE_LINES:
case MALI_DRAW_MODE_LINE_STRIP:
return 2;
case MALI_DRAW_MODE_TRIANGLES:
case MALI_DRAW_MODE_TRIANGLE_STRIP:
case MALI_DRAW_MODE_TRIANGLE_FAN:
return 3;
default:
unreachable("Invalid draw mode");
}
}
static void
panvk_emit_tiler_dcd(struct panvk_cmd_buffer *cmdbuf,
const struct panvk_draw_data *draw,
@@ -936,6 +957,14 @@ panvk_emit_tiler_dcd(struct panvk_cmd_buffer *cmdbuf,
cfg.offset_start = draw->info.vertex.raw_offset;
cfg.instance_size =
draw->info.instance.count > 1 ? draw->padded_vertex_count : 1;
uint32_t primitives_per_instance =
DIV_ROUND_UP(draw->padded_vertex_count,
primitive_vertex_count(
translate_prim_topology(ia->primitive_topology)));
/* instance_primitive_size has the same restrictions as
* padded_vertex_count, so we can use pan_padded_vertex_count here. */
cfg.instance_primitive_size =
pan_padded_vertex_count(primitives_per_instance);
cfg.uniform_buffers = fs_desc_state->tables[PANVK_BIFROST_DESC_TABLE_UBO];
cfg.push_uniforms = cmdbuf->state.gfx.fs.push_uniforms;
cfg.textures = fs_desc_state->tables[PANVK_BIFROST_DESC_TABLE_TEXTURE];
+23
View File
@@ -224,6 +224,26 @@ panvk_lower_load_vs_input(nir_builder *b, nir_intrinsic_instr *intrin,
return true;
}
static bool
panvk_lower_load_fs_input(nir_builder *b, nir_intrinsic_instr *intrin,
UNUSED void *data)
{
if (intrin->intrinsic != nir_intrinsic_load_input)
return false;
/* Lower PrimitiveID varying loads to the equivalent intrinsic. This only
* works since v6 and will require additional changes if PrimitiveID is
* explicitly written to (for example by a geometry shader). */
if (nir_intrinsic_io_semantics(intrin).location ==
VARYING_SLOT_PRIMITIVE_ID) {
b->cursor = nir_before_instr(&intrin->instr);
nir_def_replace(&intrin->def, nir_load_primitive_id(b));
return true;
}
return false;
}
#if PAN_ARCH <= 7
static bool
lower_gl_pos_layer_writes(nir_builder *b, nir_instr *instr, void *data)
@@ -867,6 +887,9 @@ panvk_lower_nir(struct panvk_device *dev, nir_shader *nir,
if (stage == MESA_SHADER_VERTEX)
NIR_PASS(_, nir, nir_shader_intrinsics_pass, panvk_lower_load_vs_input,
nir_metadata_control_flow, NULL);
else if (stage == MESA_SHADER_FRAGMENT)
NIR_PASS(_, nir, nir_shader_intrinsics_pass, panvk_lower_load_fs_input,
nir_metadata_control_flow, NULL);
/* since valhall, panvk_per_arch(nir_lower_descriptors) separates the
* driver set and the user sets, and does not need pan_lower_image_index