nir/spirv: Use real pointer types

Reviewed-by: Connor Abbott <cwabbott0@gmail.com>
This commit is contained in:
Jason Ekstrand
2017-06-29 10:33:39 -07:00
committed by Jason Ekstrand
parent ca62e849d3
commit 849bfc85c9
4 changed files with 60 additions and 15 deletions

View File

@@ -421,6 +421,7 @@ vtn_type_copy(struct vtn_builder *b, struct vtn_type *src)
case vtn_base_type_vector: case vtn_base_type_vector:
case vtn_base_type_matrix: case vtn_base_type_matrix:
case vtn_base_type_array: case vtn_base_type_array:
case vtn_base_type_pointer:
case vtn_base_type_image: case vtn_base_type_image:
case vtn_base_type_sampler: case vtn_base_type_sampler:
/* Nothing more to do */ /* Nothing more to do */
@@ -858,13 +859,17 @@ vtn_handle_type(struct vtn_builder *b, SpvOp opcode,
break; break;
} }
case SpvOpTypePointer: case SpvOpTypePointer: {
/* FIXME: For now, we'll just do the really lame thing and return SpvStorageClass storage_class = w[2];
* the same type. The validator should ensure that the proper number struct vtn_type *deref_type =
* of dereferences happen vtn_value(b, w[3], vtn_value_type_type)->type;
*/
val->type = vtn_value(b, w[3], vtn_value_type_type)->type; val->type->base_type = vtn_base_type_pointer;
val->type->type = NULL;
val->type->storage_class = storage_class;
val->type->deref = deref_type;
break; break;
}
case SpvOpTypeImage: { case SpvOpTypeImage: {
val->type->base_type = vtn_base_type_image; val->type->base_type = vtn_base_type_image;
@@ -956,6 +961,12 @@ vtn_null_constant(struct vtn_builder *b, const struct glsl_type *type)
{ {
nir_constant *c = rzalloc(b, nir_constant); nir_constant *c = rzalloc(b, nir_constant);
/* For pointers and other typeless things, we have to return something but
* it doesn't matter what.
*/
if (!type)
return c;
switch (glsl_get_base_type(type)) { switch (glsl_get_base_type(type)) {
case GLSL_TYPE_INT: case GLSL_TYPE_INT:
case GLSL_TYPE_UINT: case GLSL_TYPE_UINT:

View File

@@ -52,7 +52,11 @@ vtn_cfg_handle_prepass_instruction(struct vtn_builder *b, SpvOp opcode,
func->num_params = func_type->length; func->num_params = func_type->length;
func->params = ralloc_array(b->shader, nir_parameter, func->num_params); func->params = ralloc_array(b->shader, nir_parameter, func->num_params);
for (unsigned i = 0; i < func->num_params; i++) { for (unsigned i = 0; i < func->num_params; i++) {
if (func_type->params[i]->base_type == vtn_base_type_pointer) {
func->params[i].type = func_type->params[i]->deref->type;
} else {
func->params[i].type = func_type->params[i]->type; func->params[i].type = func_type->params[i]->type;
}
/* TODO: We could do something smarter here. */ /* TODO: We could do something smarter here. */
func->params[i].param_type = nir_parameter_inout; func->params[i].param_type = nir_parameter_inout;
@@ -73,11 +77,15 @@ vtn_cfg_handle_prepass_instruction(struct vtn_builder *b, SpvOp opcode,
case SpvOpFunctionParameter: { case SpvOpFunctionParameter: {
struct vtn_type *type = vtn_value(b, w[1], vtn_value_type_type)->type; struct vtn_type *type = vtn_value(b, w[1], vtn_value_type_type)->type;
if (type->base_type == vtn_base_type_pointer) {
type = type->deref;
assert(type->base_type != vtn_base_type_pointer);
}
assert(b->func_param_idx < b->func->impl->num_params); assert(b->func_param_idx < b->func->impl->num_params);
nir_variable *param = b->func->impl->params[b->func_param_idx++]; nir_variable *param = b->func->impl->params[b->func_param_idx++];
assert(param->type == type->type); assert(type->type == param->type);
struct vtn_variable *vtn_var = rzalloc(b, struct vtn_variable); struct vtn_variable *vtn_var = rzalloc(b, struct vtn_variable);
vtn_var->type = type; vtn_var->type = type;
@@ -102,7 +110,7 @@ vtn_cfg_handle_prepass_instruction(struct vtn_builder *b, SpvOp opcode,
/* Name the parameter so it shows up nicely in NIR */ /* Name the parameter so it shows up nicely in NIR */
param->name = ralloc_strdup(param, val->name); param->name = ralloc_strdup(param, val->name);
val->pointer = vtn_pointer_for_variable(b, vtn_var); val->pointer = vtn_pointer_for_variable(b, vtn_var, NULL);
break; break;
} }

View File

@@ -203,6 +203,7 @@ enum vtn_base_type {
vtn_base_type_matrix, vtn_base_type_matrix,
vtn_base_type_array, vtn_base_type_array,
vtn_base_type_struct, vtn_base_type_struct,
vtn_base_type_pointer,
vtn_base_type_image, vtn_base_type_image,
vtn_base_type_sampler, vtn_base_type_sampler,
vtn_base_type_function, vtn_base_type_function,
@@ -260,6 +261,15 @@ struct vtn_type {
bool builtin_block:1; bool builtin_block:1;
}; };
/* Members for pointer types */
struct {
/* For pointers, the vtn_type for dereferenced type */
struct vtn_type *deref;
/* Storage class for pointers */
SpvStorageClass storage_class;
};
/* Members for image types */ /* Members for image types */
struct { struct {
/* For images, indicates whether it's sampled or storage */ /* For images, indicates whether it's sampled or storage */
@@ -327,6 +337,14 @@ struct vtn_pointer {
/** The dereferenced type of this pointer */ /** The dereferenced type of this pointer */
struct vtn_type *type; struct vtn_type *type;
/** The pointer type of this pointer
*
* This may be NULL for some temporary pointers constructed as part of a
* large load, store, or copy. It MUST be valid for all pointers which are
* stored as SPIR-V SSA values.
*/
struct vtn_type *ptr_type;
/** The referenced variable, if known /** The referenced variable, if known
* *
* This field may be NULL if the pointer uses a (block_index, offset) pair * This field may be NULL if the pointer uses a (block_index, offset) pair
@@ -529,7 +547,8 @@ nir_ssa_def *vtn_vector_insert_dynamic(struct vtn_builder *b, nir_ssa_def *src,
nir_deref_var *vtn_nir_deref(struct vtn_builder *b, uint32_t id); nir_deref_var *vtn_nir_deref(struct vtn_builder *b, uint32_t id);
struct vtn_pointer *vtn_pointer_for_variable(struct vtn_builder *b, struct vtn_pointer *vtn_pointer_for_variable(struct vtn_builder *b,
struct vtn_variable *var); struct vtn_variable *var,
struct vtn_type *ptr_type);
nir_deref_var *vtn_pointer_to_deref(struct vtn_builder *b, nir_deref_var *vtn_pointer_to_deref(struct vtn_builder *b,
struct vtn_pointer *ptr); struct vtn_pointer *ptr);

View File

@@ -227,12 +227,13 @@ rewrite_deref_types(nir_deref *deref, const struct glsl_type *type)
struct vtn_pointer * struct vtn_pointer *
vtn_pointer_for_variable(struct vtn_builder *b, vtn_pointer_for_variable(struct vtn_builder *b,
struct vtn_variable *var) struct vtn_variable *var, struct vtn_type *ptr_type)
{ {
struct vtn_pointer *pointer = rzalloc(b, struct vtn_pointer); struct vtn_pointer *pointer = rzalloc(b, struct vtn_pointer);
pointer->mode = var->mode; pointer->mode = var->mode;
pointer->type = var->type; pointer->type = var->type;
pointer->ptr_type = ptr_type;
pointer->var = var; pointer->var = var;
return pointer; return pointer;
@@ -1470,9 +1471,13 @@ is_per_vertex_inout(const struct vtn_variable *var, gl_shader_stage stage)
static void static void
vtn_create_variable(struct vtn_builder *b, struct vtn_value *val, vtn_create_variable(struct vtn_builder *b, struct vtn_value *val,
struct vtn_type *type, SpvStorageClass storage_class, struct vtn_type *ptr_type, SpvStorageClass storage_class,
nir_constant *initializer) nir_constant *initializer)
{ {
assert(ptr_type->base_type == vtn_base_type_pointer);
struct vtn_type *type = ptr_type->deref;
assert(type->base_type != vtn_base_type_pointer);
struct vtn_type *without_array = type; struct vtn_type *without_array = type;
while(glsl_type_is_array(without_array->type)) while(glsl_type_is_array(without_array->type))
without_array = without_array->array_element; without_array = without_array->array_element;
@@ -1507,7 +1512,7 @@ vtn_create_variable(struct vtn_builder *b, struct vtn_value *val,
var->mode = mode; var->mode = mode;
assert(val->value_type == vtn_value_type_pointer); assert(val->value_type == vtn_value_type_pointer);
val->pointer = vtn_pointer_for_variable(b, var); val->pointer = vtn_pointer_for_variable(b, var, ptr_type);
switch (var->mode) { switch (var->mode) {
case vtn_variable_mode_local: case vtn_variable_mode_local:
@@ -1674,7 +1679,7 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
} }
case SpvOpVariable: { case SpvOpVariable: {
struct vtn_type *type = vtn_value(b, w[1], vtn_value_type_type)->type; struct vtn_type *ptr_type = vtn_value(b, w[1], vtn_value_type_type)->type;
struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_pointer); struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_pointer);
@@ -1683,7 +1688,7 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
if (count > 4) if (count > 4)
initializer = vtn_value(b, w[4], vtn_value_type_constant)->constant; initializer = vtn_value(b, w[4], vtn_value_type_constant)->constant;
vtn_create_variable(b, val, type, storage_class, initializer); vtn_create_variable(b, val, ptr_type, storage_class, initializer);
break; break;
} }
@@ -1705,6 +1710,7 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
idx++; idx++;
} }
struct vtn_type *ptr_type = vtn_value(b, w[1], vtn_value_type_type)->type;
struct vtn_value *base_val = vtn_untyped_value(b, w[3]); struct vtn_value *base_val = vtn_untyped_value(b, w[3]);
if (base_val->value_type == vtn_value_type_sampled_image) { if (base_val->value_type == vtn_value_type_sampled_image) {
/* This is rather insane. SPIR-V allows you to use OpSampledImage /* This is rather insane. SPIR-V allows you to use OpSampledImage
@@ -1725,6 +1731,7 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
struct vtn_value *val = struct vtn_value *val =
vtn_push_value(b, w[2], vtn_value_type_pointer); vtn_push_value(b, w[2], vtn_value_type_pointer);
val->pointer = vtn_pointer_dereference(b, base_val->pointer, chain); val->pointer = vtn_pointer_dereference(b, base_val->pointer, chain);
val->pointer->ptr_type = ptr_type;
} }
break; break;
} }