glsl: handle max_vertices/primitives for mesh shader

Reviewed-by: Ian Romanick <ian.d.romanick@intel.com>
Acked-by: Marek Olšák <marek.olsak@amd.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36405>
This commit is contained in:
Qiang Yu 2025-02-18 10:34:40 +08:00 committed by Marge Bot
parent de22e59231
commit 611370965f
6 changed files with 105 additions and 3 deletions

View file

@ -681,6 +681,7 @@ struct ast_type_qualifier {
/** GL_EXT_mesh_shader */
unsigned task_payload:1;
unsigned per_primitive:1;
unsigned max_primitives:1;
}
/** \brief Set of flags, accessed by name. */
q;
@ -729,6 +730,9 @@ struct ast_type_qualifier {
/** Maximum output vertices in GLSL 1.50 geometry shaders. */
ast_layout_expression *max_vertices;
/** Maximum output primitives in mesh shader. */
ast_layout_expression *max_primitives;
/** Stream in GLSL 1.50 geometry shaders. */
ast_expression *stream;

View file

@ -354,6 +354,16 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
}
}
if (q.flags.q.max_primitives) {
if (this->flags.q.max_primitives
&& !is_single_layout_merge && !is_multiple_layouts_merge) {
this->max_primitives->merge_qualifier(q.max_primitives);
} else {
this->flags.q.max_primitives = 1;
this->max_primitives = q.max_primitives;
}
}
if (q.subroutine_list) {
if (this->subroutine_list) {
_mesa_glsl_error(loc, state,
@ -603,6 +613,8 @@ ast_type_qualifier::validate_out_qualifier(YYLTYPE *loc,
break;
}
}
valid_out_mask.flags.q.max_vertices = 1;
valid_out_mask.flags.q.max_primitives = 1;
valid_out_mask.flags.q.prim_type = 1;
break;
default:
@ -972,6 +984,7 @@ ast_type_qualifier::validate_flags(YYLTYPE *loc,
Q2(non_coherent, noncoherent);
Q(task_payload);
Q(per_primitive);
Q(max_primitives);
#undef Q
#undef Q2

View file

@ -2567,6 +2567,8 @@ link_ms_inout_layout_qualifiers(struct gl_shader_program *prog,
if (gl_prog->info.stage != MESA_SHADER_MESH)
return;
int max_vertices = -1;
int max_primitives = -1;
enum mesa_prim prim_type = MESA_PRIM_UNKNOWN;
for (unsigned i = 0; i < num_shaders; i++) {
@ -2581,6 +2583,28 @@ link_ms_inout_layout_qualifiers(struct gl_shader_program *prog,
}
prim_type = shader->info.Mesh.OutputType;
}
if (shader->info.Mesh.MaxVertices != -1) {
if (max_vertices != -1 &&
max_vertices != shader->info.Mesh.MaxVertices) {
linker_error(prog, "mesh shader defined with conflicting "
"max_vertices count (%d and %d)\n",
max_vertices, shader->info.Mesh.MaxVertices);
return;
}
max_vertices = shader->info.Mesh.MaxVertices;
}
if (shader->info.Mesh.MaxPrimitives != -1) {
if (max_primitives != -1 &&
max_primitives != shader->info.Mesh.MaxPrimitives) {
linker_error(prog, "mesh shader defined with conflicting "
"max_primitives count (%d and %d)\n",
max_primitives, shader->info.Mesh.MaxPrimitives);
return;
}
max_primitives = shader->info.Mesh.MaxPrimitives;
}
}
if (prim_type == MESA_PRIM_UNKNOWN) {
@ -2589,6 +2613,20 @@ link_ms_inout_layout_qualifiers(struct gl_shader_program *prog,
} else {
gl_prog->nir->info.mesh.primitive_type = prim_type;
}
if (max_vertices == -1) {
linker_error(prog, "mesh shader didn't declare max_vertices\n");
return;
} else {
gl_prog->nir->info.mesh.max_vertices_out = max_vertices;
}
if (max_primitives == -1) {
linker_error(prog, "mesh shader didn't declare max_primitives\n");
return;
} else {
gl_prog->nir->info.mesh.max_primitives_out = max_primitives;
}
}

View file

@ -1816,10 +1816,18 @@ layout_qualifier_id:
if (match_layout_qualifier("max_vertices", $1, state) == 0) {
$$.flags.q.max_vertices = 1;
$$.max_vertices = new(ctx) ast_layout_expression(@1, $3);
if (!state->has_geometry_shader()) {
if (!state->has_geometry_shader() && !state->EXT_mesh_shader_enable) {
_mesa_glsl_error(& @3, state,
"#version 150 max_vertices qualifier "
"specified");
"max_vertices qualifier specified");
}
}
if (match_layout_qualifier("max_primitives", $1, state) == 0) {
$$.flags.q.max_primitives = 1;
$$.max_primitives = new(ctx) ast_layout_expression(@1, $3);
if (!state->EXT_mesh_shader_enable) {
_mesa_glsl_error(& @3, state,
"max_primitives qualifier specified");
}
}

View file

@ -2106,6 +2106,42 @@ set_shader_inout_layout(struct gl_shader *shader,
} else {
shader->info.Mesh.OutputType = MESA_PRIM_UNKNOWN;
}
shader->info.Mesh.MaxVertices = -1;
if (state->out_qualifier->flags.q.max_vertices) {
unsigned qual_max_vertices;
if (state->out_qualifier->max_vertices->
process_qualifier_constant(state, "max_vertices",
&qual_max_vertices, true)) {
if (qual_max_vertices > state->caps->mesh.max_mesh_output_vertices) {
YYLTYPE loc = state->out_qualifier->max_vertices->get_location();
_mesa_glsl_error(&loc, state,
"maximum output vertices (%d) exceeds "
"GL_MAX_MESH_OUTPUT_VERTICES_EXT",
qual_max_vertices);
}
shader->info.Mesh.MaxVertices = qual_max_vertices;
}
}
shader->info.Mesh.MaxPrimitives = -1;
if (state->out_qualifier->flags.q.max_primitives) {
unsigned qual_max_primitives;
if (state->out_qualifier->max_primitives->
process_qualifier_constant(state, "max_primitives",
&qual_max_primitives, true)) {
if (qual_max_primitives > state->caps->mesh.max_mesh_output_primitives) {
YYLTYPE loc = state->out_qualifier->max_primitives->get_location();
_mesa_glsl_error(&loc, state,
"maximum output primitives (%d) exceeds "
"GL_MAX_MESH_OUTPUT_PRIMITIVES_EXT",
qual_max_primitives);
}
shader->info.Mesh.MaxPrimitives = qual_max_primitives;
}
}
break;
default:

View file

@ -138,6 +138,9 @@ struct gl_shader_info
*/
struct {
enum mesa_prim OutputType;
GLint MaxVertices;
GLint MaxPrimitives;
} Mesh;
};