nir: Add a size_align helper function for aligning elements to 16 bytes.

This is useful for freedreno's intrinsic opt_large_constant lowering,
where we want arrays and struct elements aligned to 16 to avoid generating
lots of extra instructions to extract from the right component.

Reviewed-by: Rob Clark <robdclark@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5810>
This commit is contained in:
Eric Anholt 2020-08-04 16:09:25 -07:00
parent 433841d9eb
commit 51f2b11b04
2 changed files with 84 additions and 18 deletions

View file

@ -701,6 +701,31 @@ glsl_uint16_type(const struct glsl_type *type)
return type->get_uint16_type();
}
static void
glsl_size_align_handle_array_and_structs(const struct glsl_type *type,
glsl_type_size_align_func size_align,
unsigned *size, unsigned *align)
{
if (type->base_type == GLSL_TYPE_ARRAY) {
unsigned elem_size = 0, elem_align = 0;
size_align(type->fields.array, &elem_size, &elem_align);
*align = elem_align;
*size = type->length * ALIGN_POT(elem_size, elem_align);
} else {
assert(type->base_type == GLSL_TYPE_STRUCT ||
type->base_type == GLSL_TYPE_INTERFACE);
*size = 0;
*align = 0;
for (unsigned i = 0; i < type->length; i++) {
unsigned elem_size = 0, elem_align = 0;
size_align(type->fields.structure[i].type, &elem_size, &elem_align);
*align = MAX2(*align, elem_align);
*size = ALIGN_POT(*size, elem_align) + elem_size;
}
}
}
void
glsl_get_natural_size_align_bytes(const struct glsl_type *type,
unsigned *size, unsigned *align)
@ -731,26 +756,12 @@ glsl_get_natural_size_align_bytes(const struct glsl_type *type,
break;
}
case GLSL_TYPE_ARRAY: {
unsigned elem_size = 0, elem_align = 0;
glsl_get_natural_size_align_bytes(type->fields.array,
&elem_size, &elem_align);
*align = elem_align;
*size = type->length * ALIGN_POT(elem_size, elem_align);
break;
}
case GLSL_TYPE_ARRAY:
case GLSL_TYPE_INTERFACE:
case GLSL_TYPE_STRUCT:
*size = 0;
*align = 0;
for (unsigned i = 0; i < type->length; i++) {
unsigned elem_size = 0, elem_align = 0;
glsl_get_natural_size_align_bytes(type->fields.structure[i].type,
&elem_size, &elem_align);
*align = MAX2(*align, elem_align);
*size = ALIGN_POT(*size, elem_align) + elem_size;
}
glsl_size_align_handle_array_and_structs(type,
glsl_get_natural_size_align_bytes,
size, align);
break;
case GLSL_TYPE_SAMPLER:
@ -769,6 +780,59 @@ glsl_get_natural_size_align_bytes(const struct glsl_type *type,
}
}
/**
* Returns a byte size/alignment for a type where each array element or struct
* field is aligned to 16 bytes.
*/
void
glsl_get_vec4_size_align_bytes(const struct glsl_type *type,
unsigned *size, unsigned *align)
{
switch (type->base_type) {
case GLSL_TYPE_BOOL:
/* We special-case Booleans to 32 bits to not cause heartburn for
* drivers that suddenly get an 8-bit load.
*/
*size = 4 * type->components();
*align = 16;
break;
case GLSL_TYPE_UINT8:
case GLSL_TYPE_INT8:
case GLSL_TYPE_UINT16:
case GLSL_TYPE_INT16:
case GLSL_TYPE_FLOAT16:
case GLSL_TYPE_UINT:
case GLSL_TYPE_INT:
case GLSL_TYPE_FLOAT:
case GLSL_TYPE_DOUBLE:
case GLSL_TYPE_UINT64:
case GLSL_TYPE_INT64: {
unsigned N = glsl_get_bit_size(type) / 8;
*size = 16 * (type->matrix_columns - 1) + N * type->vector_elements;
*align = 16;
break;
}
case GLSL_TYPE_ARRAY:
case GLSL_TYPE_INTERFACE:
case GLSL_TYPE_STRUCT:
glsl_size_align_handle_array_and_structs(type,
glsl_get_vec4_size_align_bytes,
size, align);
break;
case GLSL_TYPE_SAMPLER:
case GLSL_TYPE_IMAGE:
case GLSL_TYPE_ATOMIC_UINT:
case GLSL_TYPE_SUBROUTINE:
case GLSL_TYPE_VOID:
case GLSL_TYPE_ERROR:
case GLSL_TYPE_FUNCTION:
unreachable("type does not make sense for glsl_get_vec4_size_align_bytes()");
}
}
const glsl_type *
glsl_atomic_uint_type(void)
{

View file

@ -228,6 +228,8 @@ const struct glsl_type *glsl_uint16_type(const struct glsl_type *type);
void glsl_get_natural_size_align_bytes(const struct glsl_type *type,
unsigned *size, unsigned *align);
void glsl_get_vec4_size_align_bytes(const struct glsl_type *type,
unsigned *size, unsigned *align);
const struct glsl_type *glsl_atomic_uint_type(void);