From 611370965ff77d5fcca07adbe35284e3b950c6b1 Mon Sep 17 00:00:00 2001 From: Qiang Yu Date: Tue, 18 Feb 2025 10:34:40 +0800 Subject: [PATCH] glsl: handle max_vertices/primitives for mesh shader MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reviewed-by: Ian Romanick Acked-by: Marek Olšák Part-of: --- src/compiler/glsl/ast.h | 4 +++ src/compiler/glsl/ast_type.cpp | 13 ++++++++ src/compiler/glsl/gl_nir_linker.c | 38 ++++++++++++++++++++++++ src/compiler/glsl/glsl_parser.yy | 14 +++++++-- src/compiler/glsl/glsl_parser_extras.cpp | 36 ++++++++++++++++++++++ src/mesa/main/shader_types.h | 3 ++ 6 files changed, 105 insertions(+), 3 deletions(-) diff --git a/src/compiler/glsl/ast.h b/src/compiler/glsl/ast.h index b1b723117b9..10b9cf2608d 100644 --- a/src/compiler/glsl/ast.h +++ b/src/compiler/glsl/ast.h @@ -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; diff --git a/src/compiler/glsl/ast_type.cpp b/src/compiler/glsl/ast_type.cpp index 6073ca4f175..6c432f661f3 100644 --- a/src/compiler/glsl/ast_type.cpp +++ b/src/compiler/glsl/ast_type.cpp @@ -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 diff --git a/src/compiler/glsl/gl_nir_linker.c b/src/compiler/glsl/gl_nir_linker.c index 1a67316740f..134db1bf108 100644 --- a/src/compiler/glsl/gl_nir_linker.c +++ b/src/compiler/glsl/gl_nir_linker.c @@ -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; + } } diff --git a/src/compiler/glsl/glsl_parser.yy b/src/compiler/glsl/glsl_parser.yy index 23d42309d18..812571d2e42 100644 --- a/src/compiler/glsl/glsl_parser.yy +++ b/src/compiler/glsl/glsl_parser.yy @@ -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"); } } diff --git a/src/compiler/glsl/glsl_parser_extras.cpp b/src/compiler/glsl/glsl_parser_extras.cpp index 6242acd39cc..1c3878db35d 100644 --- a/src/compiler/glsl/glsl_parser_extras.cpp +++ b/src/compiler/glsl/glsl_parser_extras.cpp @@ -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: diff --git a/src/mesa/main/shader_types.h b/src/mesa/main/shader_types.h index 0c2d70ace9f..f602074ae50 100644 --- a/src/mesa/main/shader_types.h +++ b/src/mesa/main/shader_types.h @@ -138,6 +138,9 @@ struct gl_shader_info */ struct { enum mesa_prim OutputType; + + GLint MaxVertices; + GLint MaxPrimitives; } Mesh; };