glsl: handle PerPrimitiveEXT qualifier

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-17 11:09:00 +08:00 committed by Marge Bot
parent b2e9a6d935
commit 6415cec230
17 changed files with 89 additions and 10 deletions

View file

@ -680,6 +680,7 @@ struct ast_type_qualifier {
/** GL_EXT_mesh_shader */
unsigned task_payload:1;
unsigned per_primitive:1;
}
/** \brief Set of flags, accessed by name. */
q;

View file

@ -4413,6 +4413,28 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
"with task and mesh shaders");
}
if (qual->flags.q.per_primitive) {
if (state->stage == MESA_SHADER_MESH) {
if (var->data.mode != ir_var_shader_out) {
_mesa_glsl_error(loc, state,
"the perprimitiveEXT auxiliary storage qualifier can only be "
"used on `out` variables with mesh shader");
}
} else if (state->stage == MESA_SHADER_FRAGMENT) {
if (var->data.mode != ir_var_shader_in) {
_mesa_glsl_error(loc, state,
"the perprimitiveEXT auxiliary storage qualifier can only be "
"used on `in` variables with fragment shader");
}
} else {
_mesa_glsl_error(loc, state,
"the perprimitiveEXT auxiliary storage qualifier can only be "
"used with mesh and fragment shaders");
}
var->data.per_primitive = 1;
}
apply_image_qualifier_to_variable(qual, var, state, loc);
}
@ -7732,6 +7754,7 @@ ast_process_struct_or_iface_block_members(ir_exec_list *instructions,
fields[i].centroid = qual->flags.q.centroid ? 1 : 0;
fields[i].sample = qual->flags.q.sample ? 1 : 0;
fields[i].patch = qual->flags.q.patch ? 1 : 0;
fields[i].per_primitive = qual->flags.q.per_primitive ? 1 : 0;
fields[i].offset = -1;
fields[i].explicit_xfb_buffer = explicit_xfb_buffer;
fields[i].xfb_buffer = xfb_buffer;
@ -8161,14 +8184,17 @@ ast_interface_block::hir(ir_exec_list *instructions,
if (state->stage == MESA_SHADER_GEOMETRY) {
allowed_blk_qualifiers.flags.q.stream = 1;
allowed_blk_qualifiers.flags.q.explicit_stream = 1;
}
if (state->stage == MESA_SHADER_TESS_CTRL) {
} else if (state->stage == MESA_SHADER_TESS_CTRL) {
allowed_blk_qualifiers.flags.q.patch = 1;
} else if (state->stage == MESA_SHADER_MESH) {
allowed_blk_qualifiers.flags.q.per_primitive = 1;
}
} else {
allowed_blk_qualifiers.flags.q.in = 1;
if (state->stage == MESA_SHADER_TESS_EVAL) {
allowed_blk_qualifiers.flags.q.patch = 1;
} else if (state->stage == MESA_SHADER_FRAGMENT) {
allowed_blk_qualifiers.flags.q.per_primitive = 1;
}
}
}
@ -8414,6 +8440,8 @@ ast_interface_block::hir(ir_exec_list *instructions,
earlier_per_vertex->fields.structure[j].sample;
fields[i].patch =
earlier_per_vertex->fields.structure[j].patch;
fields[i].per_primitive =
earlier_per_vertex->fields.structure[j].per_primitive;
fields[i].precision =
earlier_per_vertex->fields.structure[j].precision;
fields[i].explicit_xfb_buffer =
@ -8660,6 +8688,7 @@ ast_interface_block::hir(ir_exec_list *instructions,
var->data.read_only = true;
var->data.patch = this->layout.flags.q.patch;
var->data.per_primitive = this->layout.flags.q.per_primitive;
if (state->stage == MESA_SHADER_GEOMETRY && var_mode == ir_var_shader_in)
handle_geometry_shader_input_decl(state, loc, var);
@ -8715,6 +8744,7 @@ ast_interface_block::hir(ir_exec_list *instructions,
var->data.patch = fields[i].patch;
var->data.stream = qual_stream;
var->data.location = fields[i].location;
var->data.per_primitive = fields[i].per_primitive;
if (fields[i].location != -1)
var->data.explicit_location = true;

View file

@ -107,7 +107,8 @@ ast_type_qualifier::has_auxiliary_storage() const
{
return this->flags.q.centroid
|| this->flags.q.sample
|| this->flags.q.patch;
|| this->flags.q.patch
|| this->flags.q.per_primitive;
}
bool ast_type_qualifier::has_memory() const
@ -295,6 +296,7 @@ ast_type_qualifier::merge_qualifier(YYLTYPE *loc,
input_layout_mask.flags.q.smooth = 1;
input_layout_mask.flags.q.non_coherent = 1;
input_layout_mask.flags.q.explicit_numviews = 1;
input_layout_mask.flags.q.per_primitive = 1;
if (state->has_bindless()) {
/* Allow to use image qualifiers with shader inputs/outputs. */
@ -952,6 +954,7 @@ ast_type_qualifier::validate_flags(YYLTYPE *loc,
Q(sample_interlock_unordered);
Q2(non_coherent, noncoherent);
Q(task_payload);
Q(per_primitive);
#undef Q
#undef Q2

View file

@ -286,6 +286,9 @@ interstage_member_mismatch(struct gl_shader_program *prog,
if (c->fields.structure[i].patch !=
p->fields.structure[i].patch)
return true;
if (c->fields.structure[i].per_primitive !=
p->fields.structure[i].per_primitive)
return true;
/* From Section 4.5 (Interpolation Qualifiers) of the GLSL 4.40 spec:
*

View file

@ -689,6 +689,7 @@ create_shader_variable(struct gl_shader_program *shProg,
out->interpolation = in->data.interpolation;
out->precision = in->data.precision;
out->explicit_location = in->data.explicit_location;
out->per_primitive = in->data.per_primitive;
return out;
}

View file

@ -289,6 +289,7 @@ lower_named_interface_blocks(struct gl_linked_shader *sh)
new_var->data.centroid = field_data->centroid;
new_var->data.sample = field_data->sample;
new_var->data.patch = field_data->patch;
new_var->data.per_primitive = field_data->per_primitive;
new_var->data.stream = var->data.stream;
new_var->data.how_declared = var->data.how_declared;
new_var->data.from_named_ifc_block = 1;

View file

@ -294,6 +294,7 @@ create_or_update_packed_varying(struct lower_packed_varyings_state *state,
packed_var->data.centroid = unpacked_var->data.centroid;
packed_var->data.sample = unpacked_var->data.sample;
packed_var->data.patch = unpacked_var->data.patch;
packed_var->data.per_primitive = unpacked_var->data.per_primitive;
packed_var->data.interpolation = is_interpolation_flat ?
(unsigned) INTERP_MODE_FLAT : unpacked_var->data.interpolation;
packed_var->data.location = location;

View file

@ -558,6 +558,13 @@ taskPayloadSharedEXT {
return classify_identifier(yyextra, yytext, yyleng, yylval);
}
perprimitiveEXT {
if (yyextra->EXT_mesh_shader_enable)
return PERPRIMITIVE;
else
return classify_identifier(yyextra, yytext, yyleng, yylval);
}
struct return STRUCT;
void return VOID_TOK;

View file

@ -147,7 +147,7 @@ static bool match_layout_qualifier(const char *s1, const char *s2,
%token IMAGE1DSHADOW IMAGE2DSHADOW IMAGE1DARRAYSHADOW IMAGE2DARRAYSHADOW
%token COHERENT VOLATILE RESTRICT READONLY WRITEONLY
%token SHARED
%token TASKPAYLOAD
%token TASKPAYLOAD PERPRIMITIVE
%token STRUCT VOID_TOK WHILE
%token <identifier> IDENTIFIER TYPE_IDENTIFIER NEW_IDENTIFIER
%type <identifier> any_identifier
@ -2190,6 +2190,11 @@ auxiliary_storage_qualifier:
memset(& $$, 0, sizeof($$));
$$.flags.q.patch = 1;
}
| PERPRIMITIVE
{
memset(& $$, 0, sizeof($$));
$$.flags.q.per_primitive = 1;
}
storage_qualifier:
CONST_TOK
@ -2951,14 +2956,15 @@ interface_qualifier:
}
| auxiliary_storage_qualifier interface_qualifier
{
if (!$1.flags.q.patch) {
if (!$1.flags.q.patch && !$1.flags.q.per_primitive) {
_mesa_glsl_error(&@1, state, "invalid interface qualifier");
}
if ($2.has_auxiliary_storage()) {
_mesa_glsl_error(&@1, state, "duplicate patch qualifier");
_mesa_glsl_error(&@1, state, "duplicate auxiliary storage qualifier");
}
$$ = $2;
$$.flags.q.patch = 1;
$$.flags.q.patch = $1.flags.q.patch;
$$.flags.q.per_primitive = $1.flags.q.per_primitive;
}
;

View file

@ -1217,6 +1217,7 @@ _mesa_ast_process_interface_block(YYLTYPE *locp,
temp_type_qualifier.flags.q.out = true;
temp_type_qualifier.flags.q.buffer = true;
temp_type_qualifier.flags.q.patch = true;
temp_type_qualifier.flags.q.per_primitive = true;
interface_type_mask = temp_type_qualifier.flags.i;
/* Get the block's interface qualifier. The interface_qualifier
@ -1325,6 +1326,8 @@ _mesa_ast_type_qualifier_print(const struct ast_type_qualifier *q)
printf("flat ");
if (q->flags.q.noperspective)
printf("noperspective ");
if (q->flags.q.per_primitive)
printf("per_primitive ");
}

View file

@ -471,6 +471,7 @@ nir_visitor::visit(ir_variable *ir)
var->data.max_array_access = ir->data.max_array_access;
var->data.implicit_sized_array = ir->data.implicit_sized_array;
var->data.from_ssbo_unsized_array = ir->data.from_ssbo_unsized_array;
var->data.per_primitive = ir->data.per_primitive;
switch(ir->data.mode) {
case ir_var_auto:

View file

@ -2020,6 +2020,7 @@ ir_variable::ir_variable(const struct glsl_type *type, const char *name,
this->data.xfb_buffer = -1;
this->data.xfb_stride = -1;
this->data.implicit_conversion_prohibited = false;
this->data.per_primitive = false;
this->interface_type = NULL;
@ -2115,6 +2116,7 @@ ir_function_signature::qualifiers_match(ir_exec_list *params)
a->data.centroid != b->data.centroid ||
a->data.sample != b->data.sample ||
a->data.patch != b->data.patch ||
a->data.per_primitive != b->data.per_primitive ||
a->data.memory_read_only != b->data.memory_read_only ||
a->data.memory_write_only != b->data.memory_write_only ||
a->data.memory_coherent != b->data.memory_coherent ||

View file

@ -858,6 +858,11 @@ public:
*/
unsigned implicit_conversion_prohibited:1;
/**
* Non-zero if the variable is per-primitive as defined by EXT_mesh_shader
*/
unsigned per_primitive:1;
/**
* Emit a warning if this variable is accessed.
*/

View file

@ -212,17 +212,18 @@ void ir_print_visitor::visit(ir_variable *ir)
"shader_shared ", "task_payload ", "shader_in ", "shader_out ",
"in ", "out ", "inout ",
"const_in ", "sys ", "temporary " };
const char *const per_primitive = (ir->data.per_primitive) ? "per_primitive " : "";
STATIC_ASSERT(ARRAY_SIZE(mode) == ir_var_mode_count);
const char *const interp[] = { "", "smooth", "flat", "noperspective", "explicit" };
STATIC_ASSERT(ARRAY_SIZE(interp) == INTERP_MODE_COUNT);
const char *const precision[] = { "", "highp ", "mediump ", "lowp "};
fprintf(f, "(%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s) ",
fprintf(f, "(%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s) ",
binding, loc, component, cent, bindless, bound,
image_format, memory_read_only, memory_write_only,
memory_coherent, memory_volatile, memory_restrict,
samp, patc, inv, explicit_inv, prec, mode[ir->data.mode],
stream,
samp, patc, inv, explicit_inv, prec, per_primitive,
mode[ir->data.mode], stream,
interp[ir->data.interpolation], precision[ir->data.precision]);
glsl_print_type(f, ir->type);

View file

@ -1506,6 +1506,9 @@ glsl_record_compare(const glsl_type *a, const glsl_type *b, bool match_name,
if (a->fields.structure[i].xfb_stride
!= b->fields.structure[i].xfb_stride)
return false;
if (a->fields.structure[i].per_primitive
!= b->fields.structure[i].per_primitive)
return false;
}
return true;

View file

@ -484,6 +484,12 @@ struct glsl_struct_field {
unsigned explicit_xfb_buffer:1;
unsigned implicit_sized_array:1;
/**
* For interface blocks, 1 if this variable is a per-primitive input or output
* (as in ir_variable::patch). 0 otherwise.
*/
unsigned per_primitive:1;
};
unsigned flags;
};

View file

@ -1170,6 +1170,11 @@ struct gl_shader_variable
* Precision qualifier.
*/
unsigned precision:2;
/**
* Per-primitive qualifier
*/
unsigned per_primitive:1;
};
#endif