nir/spirv: Beef up the type system a bit

This adds a vtn concept of base_type as well as a couple of other
fields.  This lets us be a tiny bit more efficient in some cases but,
more importantly, it will eventually let us express things the GLSL type
system can't.

Reviewed-by: Connor Abbott <cwabbott0@gmail.com>
This commit is contained in:
Jason Ekstrand
2017-06-29 10:33:37 -07:00
committed by Jason Ekstrand
parent ad4519696d
commit 96f2439858
2 changed files with 59 additions and 28 deletions

View File

@@ -415,34 +415,29 @@ vtn_type_copy(struct vtn_builder *b, struct vtn_type *src)
struct vtn_type *dest = ralloc(b, struct vtn_type); struct vtn_type *dest = ralloc(b, struct vtn_type);
*dest = *src; *dest = *src;
if (!glsl_type_is_scalar(src->type)) { switch (src->base_type) {
switch (glsl_get_base_type(src->type)) { case vtn_base_type_void:
case GLSL_TYPE_INT: case vtn_base_type_scalar:
case GLSL_TYPE_UINT: case vtn_base_type_vector:
case GLSL_TYPE_INT64: case vtn_base_type_matrix:
case GLSL_TYPE_UINT64: case vtn_base_type_array:
case GLSL_TYPE_BOOL: case vtn_base_type_image:
case GLSL_TYPE_FLOAT: case vtn_base_type_sampler:
case GLSL_TYPE_DOUBLE: case vtn_base_type_function:
case GLSL_TYPE_ARRAY: /* Nothing more to do */
break; break;
case GLSL_TYPE_STRUCT: { case vtn_base_type_struct:
unsigned elems = glsl_get_length(src->type); dest->members = ralloc_array(b, struct vtn_type *, src->length);
memcpy(dest->members, src->members,
src->length * sizeof(src->members[0]));
dest->members = ralloc_array(b, struct vtn_type *, elems); dest->offsets = ralloc_array(b, unsigned, src->length);
memcpy(dest->members, src->members, elems * sizeof(struct vtn_type *)); memcpy(dest->offsets, src->offsets,
src->length * sizeof(src->offsets[0]));
dest->offsets = ralloc_array(b, unsigned, elems);
memcpy(dest->offsets, src->offsets, elems * sizeof(unsigned));
break; break;
} }
default:
unreachable("unhandled type");
}
}
return dest; return dest;
} }
@@ -732,14 +727,17 @@ vtn_handle_type(struct vtn_builder *b, SpvOp opcode,
switch (opcode) { switch (opcode) {
case SpvOpTypeVoid: case SpvOpTypeVoid:
val->type->base_type = vtn_base_type_void;
val->type->type = glsl_void_type(); val->type->type = glsl_void_type();
break; break;
case SpvOpTypeBool: case SpvOpTypeBool:
val->type->base_type = vtn_base_type_scalar;
val->type->type = glsl_bool_type(); val->type->type = glsl_bool_type();
break; break;
case SpvOpTypeInt: { case SpvOpTypeInt: {
int bit_size = w[2]; int bit_size = w[2];
const bool signedness = w[3]; const bool signedness = w[3];
val->type->base_type = vtn_base_type_scalar;
if (bit_size == 64) if (bit_size == 64)
val->type->type = (signedness ? glsl_int64_t_type() : glsl_uint64_t_type()); val->type->type = (signedness ? glsl_int64_t_type() : glsl_uint64_t_type());
else else
@@ -748,6 +746,7 @@ vtn_handle_type(struct vtn_builder *b, SpvOp opcode,
} }
case SpvOpTypeFloat: { case SpvOpTypeFloat: {
int bit_size = w[2]; int bit_size = w[2];
val->type->base_type = vtn_base_type_scalar;
val->type->type = bit_size == 64 ? glsl_double_type() : glsl_float_type(); val->type->type = bit_size == 64 ? glsl_double_type() : glsl_float_type();
break; break;
} }
@@ -757,6 +756,7 @@ vtn_handle_type(struct vtn_builder *b, SpvOp opcode,
unsigned elems = w[3]; unsigned elems = w[3];
assert(glsl_type_is_scalar(base->type)); assert(glsl_type_is_scalar(base->type));
val->type->base_type = vtn_base_type_vector;
val->type->type = glsl_vector_type(glsl_get_base_type(base->type), elems); val->type->type = glsl_vector_type(glsl_get_base_type(base->type), elems);
/* Vectors implicitly have sizeof(base_type) stride. For now, this /* Vectors implicitly have sizeof(base_type) stride. For now, this
@@ -773,10 +773,12 @@ vtn_handle_type(struct vtn_builder *b, SpvOp opcode,
unsigned columns = w[3]; unsigned columns = w[3];
assert(glsl_type_is_vector(base->type)); assert(glsl_type_is_vector(base->type));
val->type->base_type = vtn_base_type_matrix;
val->type->type = glsl_matrix_type(glsl_get_base_type(base->type), val->type->type = glsl_matrix_type(glsl_get_base_type(base->type),
glsl_get_vector_elements(base->type), glsl_get_vector_elements(base->type),
columns); columns);
assert(!glsl_type_is_error(val->type->type)); assert(!glsl_type_is_error(val->type->type));
val->type->length = columns;
val->type->array_element = base; val->type->array_element = base;
val->type->row_major = false; val->type->row_major = false;
val->type->stride = 0; val->type->stride = 0;
@@ -788,16 +790,16 @@ vtn_handle_type(struct vtn_builder *b, SpvOp opcode,
struct vtn_type *array_element = struct vtn_type *array_element =
vtn_value(b, w[2], vtn_value_type_type)->type; vtn_value(b, w[2], vtn_value_type_type)->type;
unsigned length;
if (opcode == SpvOpTypeRuntimeArray) { if (opcode == SpvOpTypeRuntimeArray) {
/* A length of 0 is used to denote unsized arrays */ /* A length of 0 is used to denote unsized arrays */
length = 0; val->type->length = 0;
} else { } else {
length = val->type->length =
vtn_value(b, w[3], vtn_value_type_constant)->constant->values[0].u32[0]; vtn_value(b, w[3], vtn_value_type_constant)->constant->values[0].u32[0];
} }
val->type->type = glsl_array_type(array_element->type, length); val->type->base_type = vtn_base_type_array;
val->type->type = glsl_array_type(array_element->type, val->type->length);
val->type->array_element = array_element; val->type->array_element = array_element;
val->type->stride = 0; val->type->stride = 0;
break; break;
@@ -805,6 +807,8 @@ vtn_handle_type(struct vtn_builder *b, SpvOp opcode,
case SpvOpTypeStruct: { case SpvOpTypeStruct: {
unsigned num_fields = count - 2; unsigned num_fields = count - 2;
val->type->base_type = vtn_base_type_struct;
val->type->length = num_fields;
val->type->members = ralloc_array(b, struct vtn_type *, num_fields); val->type->members = ralloc_array(b, struct vtn_type *, num_fields);
val->type->offsets = ralloc_array(b, unsigned, num_fields); val->type->offsets = ralloc_array(b, unsigned, num_fields);
@@ -835,6 +839,8 @@ vtn_handle_type(struct vtn_builder *b, SpvOp opcode,
} }
case SpvOpTypeFunction: { case SpvOpTypeFunction: {
val->type->base_type = vtn_base_type_function;
const struct glsl_type *return_type = const struct glsl_type *return_type =
vtn_value(b, w[2], vtn_value_type_type)->type->type; vtn_value(b, w[2], vtn_value_type_type)->type->type;
NIR_VLA(struct glsl_function_param, params, count - 3); NIR_VLA(struct glsl_function_param, params, count - 3);
@@ -858,6 +864,8 @@ vtn_handle_type(struct vtn_builder *b, SpvOp opcode,
break; break;
case SpvOpTypeImage: { case SpvOpTypeImage: {
val->type->base_type = vtn_base_type_image;
const struct glsl_type *sampled_type = const struct glsl_type *sampled_type =
vtn_value(b, w[2], vtn_value_type_type)->type->type; vtn_value(b, w[2], vtn_value_type_type)->type->type;
@@ -899,10 +907,12 @@ vtn_handle_type(struct vtn_builder *b, SpvOp opcode,
val->type->image_format = translate_image_format(format); val->type->image_format = translate_image_format(format);
if (sampled == 1) { if (sampled == 1) {
val->type->sampled = true;
val->type->type = glsl_sampler_type(dim, is_shadow, is_array, val->type->type = glsl_sampler_type(dim, is_shadow, is_array,
glsl_get_base_type(sampled_type)); glsl_get_base_type(sampled_type));
} else if (sampled == 2) { } else if (sampled == 2) {
assert(!is_shadow); assert(!is_shadow);
val->type->sampled = false;
val->type->type = glsl_image_type(dim, is_array, val->type->type = glsl_image_type(dim, is_array,
glsl_get_base_type(sampled_type)); glsl_get_base_type(sampled_type));
} else { } else {
@@ -921,6 +931,7 @@ vtn_handle_type(struct vtn_builder *b, SpvOp opcode,
* matters is that it's a sampler type as opposed to an integer type * matters is that it's a sampler type as opposed to an integer type
* so the backend knows what to do. * so the backend knows what to do.
*/ */
val->type->base_type = vtn_base_type_sampler;
val->type->type = glsl_bare_sampler_type(); val->type->type = glsl_bare_sampler_type();
break; break;

View File

@@ -196,12 +196,29 @@ struct vtn_ssa_value {
const struct glsl_type *type; const struct glsl_type *type;
}; };
enum vtn_base_type {
vtn_base_type_void,
vtn_base_type_scalar,
vtn_base_type_vector,
vtn_base_type_matrix,
vtn_base_type_array,
vtn_base_type_struct,
vtn_base_type_image,
vtn_base_type_sampler,
vtn_base_type_function,
};
struct vtn_type { struct vtn_type {
enum vtn_base_type base_type;
const struct glsl_type *type; const struct glsl_type *type;
/* The value that declares this type. Used for finding decorations */ /* The value that declares this type. Used for finding decorations */
struct vtn_value *val; struct vtn_value *val;
/* Specifies the length of complex types. */
unsigned length;
union { union {
/* Members for scalar, vector, and array-like types */ /* Members for scalar, vector, and array-like types */
struct { struct {
@@ -245,6 +262,9 @@ struct vtn_type {
/* Members for image types */ /* Members for image types */
struct { struct {
/* For images, indicates whether it's sampled or storage */
bool sampled;
/* Image format for image_load_store type images */ /* Image format for image_load_store type images */
unsigned image_format; unsigned image_format;