mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-11 03:40:22 +01:00
glsl: add xfb_offset compile time rules
We also copy the qualifier values to the IR in this step. Reviewed-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
parent
f6a8c7ef21
commit
edddad0eee
1 changed files with 123 additions and 2 deletions
|
|
@ -2600,6 +2600,67 @@ validate_xfb_buffer_qualifier(YYLTYPE *loc,
|
|||
return true;
|
||||
}
|
||||
|
||||
/* From the ARB_enhanced_layouts spec:
|
||||
*
|
||||
* "Variables and block members qualified with *xfb_offset* can be
|
||||
* scalars, vectors, matrices, structures, and (sized) arrays of these.
|
||||
* The offset must be a multiple of the size of the first component of
|
||||
* the first qualified variable or block member, or a compile-time error
|
||||
* results. Further, if applied to an aggregate containing a double,
|
||||
* the offset must also be a multiple of 8, and the space taken in the
|
||||
* buffer will be a multiple of 8.
|
||||
*/
|
||||
static bool
|
||||
validate_xfb_offset_qualifier(YYLTYPE *loc,
|
||||
struct _mesa_glsl_parse_state *state,
|
||||
int xfb_offset, const glsl_type *type,
|
||||
unsigned component_size) {
|
||||
const glsl_type *t_without_array = type->without_array();
|
||||
|
||||
if (xfb_offset != -1 && type->is_unsized_array()) {
|
||||
_mesa_glsl_error(loc, state,
|
||||
"xfb_offset can't be used with unsized arrays.");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Make sure nested structs don't contain unsized arrays, and validate
|
||||
* any xfb_offsets on interface members.
|
||||
*/
|
||||
if (t_without_array->is_record() || t_without_array->is_interface())
|
||||
for (unsigned int i = 0; i < t_without_array->length; i++) {
|
||||
const glsl_type *member_t = t_without_array->fields.structure[i].type;
|
||||
|
||||
/* When the interface block doesn't have an xfb_offset qualifier then
|
||||
* we apply the component size rules at the member level.
|
||||
*/
|
||||
if (xfb_offset == -1)
|
||||
component_size = member_t->contains_double() ? 8 : 4;
|
||||
|
||||
int xfb_offset = t_without_array->fields.structure[i].offset;
|
||||
validate_xfb_offset_qualifier(loc, state, xfb_offset, member_t,
|
||||
component_size);
|
||||
}
|
||||
|
||||
/* Nested structs or interface block without offset may not have had an
|
||||
* offset applied yet so return.
|
||||
*/
|
||||
if (xfb_offset == -1) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (xfb_offset % component_size) {
|
||||
_mesa_glsl_error(loc, state,
|
||||
"invalid qualifier xfb_offset=%d must be a multiple "
|
||||
"of the first component size of the first qualified "
|
||||
"variable or block member. Or double if an aggregate "
|
||||
"that contains a double (%d).",
|
||||
xfb_offset, component_size);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
validate_stream_qualifier(YYLTYPE *loc, struct _mesa_glsl_parse_state *state,
|
||||
unsigned stream)
|
||||
|
|
@ -3172,6 +3233,19 @@ apply_layout_qualifier_to_variable(const struct ast_type_qualifier *qual,
|
|||
}
|
||||
}
|
||||
|
||||
if (qual->flags.q.explicit_xfb_offset) {
|
||||
unsigned qual_xfb_offset;
|
||||
unsigned component_size = var->type->contains_double() ? 8 : 4;
|
||||
|
||||
if (process_qualifier_constant(state, loc, "xfb_offset",
|
||||
qual->offset, &qual_xfb_offset) &&
|
||||
validate_xfb_offset_qualifier(loc, state, (int) qual_xfb_offset,
|
||||
var->type, component_size)) {
|
||||
var->data.offset = qual_xfb_offset;
|
||||
var->data.explicit_xfb_offset = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (var->type->contains_atomic()) {
|
||||
if (var->data.mode == ir_var_uniform) {
|
||||
if (var->data.explicit_binding) {
|
||||
|
|
@ -6285,6 +6359,7 @@ ast_process_struct_or_iface_block_members(exec_list *instructions,
|
|||
ast_type_qualifier *layout,
|
||||
unsigned block_stream,
|
||||
unsigned block_xfb_buffer,
|
||||
unsigned block_xfb_offset,
|
||||
unsigned expl_location,
|
||||
unsigned expl_align)
|
||||
{
|
||||
|
|
@ -6505,6 +6580,7 @@ ast_process_struct_or_iface_block_members(exec_list *instructions,
|
|||
fields[i].sample = qual->flags.q.sample ? 1 : 0;
|
||||
fields[i].patch = qual->flags.q.patch ? 1 : 0;
|
||||
fields[i].precision = qual->precision;
|
||||
fields[i].offset = -1;
|
||||
fields[i].explicit_xfb_buffer = explicit_xfb_buffer;
|
||||
fields[i].xfb_buffer = xfb_buffer;
|
||||
|
||||
|
|
@ -6569,8 +6645,6 @@ ast_process_struct_or_iface_block_members(exec_list *instructions,
|
|||
"with std430 and std140 layouts");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fields[i].offset = -1;
|
||||
}
|
||||
|
||||
if (qual->flags.q.explicit_align || expl_align != 0) {
|
||||
|
|
@ -6603,6 +6677,31 @@ ast_process_struct_or_iface_block_members(exec_list *instructions,
|
|||
next_offset = glsl_align(next_offset + size, align);
|
||||
}
|
||||
|
||||
/* From the ARB_enhanced_layouts spec:
|
||||
*
|
||||
* "The given offset applies to the first component of the first
|
||||
* member of the qualified entity. Then, within the qualified
|
||||
* entity, subsequent components are each assigned, in order, to
|
||||
* the next available offset aligned to a multiple of that
|
||||
* component's size. Aggregate types are flattened down to the
|
||||
* component level to get this sequence of components."
|
||||
*/
|
||||
if (qual->flags.q.explicit_xfb_offset) {
|
||||
unsigned xfb_offset;
|
||||
if (process_qualifier_constant(state, &loc, "xfb_offset",
|
||||
qual->offset, &xfb_offset)) {
|
||||
fields[i].offset = xfb_offset;
|
||||
block_xfb_offset = fields[i].offset +
|
||||
4 * field_type->component_slots();
|
||||
}
|
||||
} else {
|
||||
if (layout && layout->flags.q.explicit_xfb_offset) {
|
||||
unsigned align = field_type->is_double() ? 8 : 4;
|
||||
fields[i].offset = glsl_align(block_xfb_offset, align);
|
||||
block_xfb_offset += 4 * field_type->component_slots();
|
||||
}
|
||||
}
|
||||
|
||||
/* Propogate row- / column-major information down the fields of the
|
||||
* structure or interface block. Structures need this data because
|
||||
* the structure may contain a structure that contains ... a matrix
|
||||
|
|
@ -6698,6 +6797,7 @@ ast_struct_specifier::hir(exec_list *instructions,
|
|||
layout,
|
||||
0, /* for interface only */
|
||||
0, /* for interface only */
|
||||
0, /* for interface only */
|
||||
expl_location,
|
||||
0 /* for interface only */);
|
||||
|
||||
|
|
@ -6864,6 +6964,14 @@ ast_interface_block::hir(exec_list *instructions,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
unsigned qual_xfb_offset;
|
||||
if (layout.flags.q.explicit_xfb_offset) {
|
||||
if (!process_qualifier_constant(state, &loc, "xfb_offset",
|
||||
layout.offset, &qual_xfb_offset)) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned expl_location = 0;
|
||||
if (layout.flags.q.explicit_location) {
|
||||
if (!process_qualifier_constant(state, &loc, "location",
|
||||
|
|
@ -6900,6 +7008,7 @@ ast_interface_block::hir(exec_list *instructions,
|
|||
&this->layout,
|
||||
qual_stream,
|
||||
qual_xfb_buffer,
|
||||
qual_xfb_offset,
|
||||
expl_location,
|
||||
expl_align);
|
||||
|
||||
|
|
@ -7018,6 +7127,8 @@ ast_interface_block::hir(exec_list *instructions,
|
|||
earlier_per_vertex->fields.structure[j].explicit_xfb_buffer;
|
||||
fields[i].xfb_buffer =
|
||||
earlier_per_vertex->fields.structure[j].xfb_buffer;
|
||||
fields[i].xfb_stride =
|
||||
earlier_per_vertex->fields.structure[j].xfb_stride;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -7048,6 +7159,12 @@ ast_interface_block::hir(exec_list *instructions,
|
|||
packing,
|
||||
this->block_name);
|
||||
|
||||
unsigned component_size = block_type->contains_double() ? 8 : 4;
|
||||
int xfb_offset =
|
||||
layout.flags.q.explicit_xfb_offset ? (int) qual_xfb_offset : -1;
|
||||
validate_xfb_offset_qualifier(&loc, state, xfb_offset, block_type,
|
||||
component_size);
|
||||
|
||||
if (!state->symbols->add_interface(block_type->name, block_type, var_mode)) {
|
||||
YYLTYPE loc = this->get_location();
|
||||
_mesa_glsl_error(&loc, state, "interface block `%s' with type `%s' "
|
||||
|
|
@ -7276,6 +7393,10 @@ ast_interface_block::hir(exec_list *instructions,
|
|||
var->data.explicit_xfb_buffer = fields[i].explicit_xfb_buffer;
|
||||
var->data.xfb_buffer = fields[i].xfb_buffer;
|
||||
|
||||
if (fields[i].offset != -1)
|
||||
var->data.explicit_xfb_offset = true;
|
||||
var->data.offset = fields[i].offset;
|
||||
|
||||
var->init_interface_type(block_type);
|
||||
|
||||
if (var_mode == ir_var_shader_in || var_mode == ir_var_uniform)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue