[Mesa-dev] [PATCH 17/18] nir/spirv: Use real pointer types
Jason Ekstrand
jason at jlekstrand.net
Thu Jun 29 17:33:39 UTC 2017
---
src/compiler/spirv/spirv_to_nir.c | 23 +++++++++++++++++------
src/compiler/spirv/vtn_cfg.c | 12 ++++++++++--
src/compiler/spirv/vtn_private.h | 18 ++++++++++++++++++
src/compiler/spirv/vtn_variables.c | 13 ++++++++++---
4 files changed, 55 insertions(+), 11 deletions(-)
diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c
index cc3ba0d..462b049 100644
--- a/src/compiler/spirv/spirv_to_nir.c
+++ b/src/compiler/spirv/spirv_to_nir.c
@@ -421,6 +421,7 @@ vtn_type_copy(struct vtn_builder *b, struct vtn_type *src)
case vtn_base_type_vector:
case vtn_base_type_matrix:
case vtn_base_type_array:
+ case vtn_base_type_pointer:
case vtn_base_type_image:
case vtn_base_type_sampler:
/* Nothing more to do */
@@ -858,13 +859,17 @@ vtn_handle_type(struct vtn_builder *b, SpvOp opcode,
break;
}
- case SpvOpTypePointer:
- /* FIXME: For now, we'll just do the really lame thing and return
- * the same type. The validator should ensure that the proper number
- * of dereferences happen
- */
- val->type = vtn_value(b, w[3], vtn_value_type_type)->type;
+ case SpvOpTypePointer: {
+ SpvStorageClass storage_class = w[2];
+ struct vtn_type *deref_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;
+ }
case SpvOpTypeImage: {
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);
+ /* 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)) {
case GLSL_TYPE_INT:
case GLSL_TYPE_UINT:
diff --git a/src/compiler/spirv/vtn_cfg.c b/src/compiler/spirv/vtn_cfg.c
index dc429e6..83e77e2 100644
--- a/src/compiler/spirv/vtn_cfg.c
+++ b/src/compiler/spirv/vtn_cfg.c
@@ -52,7 +52,11 @@ vtn_cfg_handle_prepass_instruction(struct vtn_builder *b, SpvOp opcode,
func->num_params = func_type->length;
func->params = ralloc_array(b->shader, nir_parameter, func->num_params);
for (unsigned i = 0; i < func->num_params; i++) {
- func->params[i].type = func_type->params[i]->type;
+ 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;
+ }
/* TODO: We could do something smarter here. */
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: {
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);
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);
vtn_var->type = type;
diff --git a/src/compiler/spirv/vtn_private.h b/src/compiler/spirv/vtn_private.h
index 4972b55..446d9fa 100644
--- a/src/compiler/spirv/vtn_private.h
+++ b/src/compiler/spirv/vtn_private.h
@@ -203,6 +203,7 @@ enum vtn_base_type {
vtn_base_type_matrix,
vtn_base_type_array,
vtn_base_type_struct,
+ vtn_base_type_pointer,
vtn_base_type_image,
vtn_base_type_sampler,
vtn_base_type_function,
@@ -260,6 +261,15 @@ struct vtn_type {
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 */
struct {
/* For images, indicates whether it's sampled or storage */
@@ -327,6 +337,14 @@ struct vtn_pointer {
/** The dereferenced type of this pointer */
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
*
* This field may be NULL if the pointer uses a (block_index, offset) pair
diff --git a/src/compiler/spirv/vtn_variables.c b/src/compiler/spirv/vtn_variables.c
index d26863b..12504f4 100644
--- a/src/compiler/spirv/vtn_variables.c
+++ b/src/compiler/spirv/vtn_variables.c
@@ -1457,9 +1457,13 @@ is_per_vertex_inout(const struct vtn_variable *var, gl_shader_stage stage)
static void
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)
{
+ 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;
while(glsl_type_is_array(without_array->type))
without_array = without_array->array_element;
@@ -1492,6 +1496,7 @@ vtn_create_variable(struct vtn_builder *b, struct vtn_value *val,
assert(val->value_type == vtn_value_type_pointer);
val->pointer = rzalloc(b, struct vtn_pointer);
val->pointer->type = type;
+ val->pointer->ptr_type = ptr_type;
val->pointer->mode = mode;
struct vtn_variable *var = rzalloc(b, struct vtn_variable);
@@ -1664,7 +1669,7 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
}
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);
@@ -1673,7 +1678,7 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
if (count > 4)
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;
}
@@ -1695,6 +1700,7 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
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]);
if (base_val->value_type == vtn_value_type_sampled_image) {
/* This is rather insane. SPIR-V allows you to use OpSampledImage
@@ -1715,6 +1721,7 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
struct vtn_value *val =
vtn_push_value(b, w[2], vtn_value_type_pointer);
val->pointer = vtn_pointer_dereference(b, base_val->pointer, chain);
+ val->pointer->ptr_type = ptr_type;
}
break;
}
--
2.5.0.400.gff86faf
More information about the mesa-dev
mailing list