summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJason Ekstrand <[email protected]>2015-04-29 20:56:36 -0700
committerJason Ekstrand <[email protected]>2015-05-16 11:16:33 -0700
commit5acd472271d72866a36a5de374f3e1a846b61dc8 (patch)
tree56d450f313c7ecc8e7044c1c486d3504189f761f /src
parent7182597e50253f07b66cb0edb806b11a56242b5c (diff)
nir/spirv: Add support for deref chains
Diffstat (limited to 'src')
-rw-r--r--src/glsl/nir/spirv_to_nir.c86
1 files changed, 74 insertions, 12 deletions
diff --git a/src/glsl/nir/spirv_to_nir.c b/src/glsl/nir/spirv_to_nir.c
index e8acb33f481..ba536e8c81d 100644
--- a/src/glsl/nir/spirv_to_nir.c
+++ b/src/glsl/nir/spirv_to_nir.c
@@ -38,11 +38,10 @@ enum vtn_value_type {
vtn_value_type_decoration_group,
vtn_value_type_type,
vtn_value_type_constant,
- vtn_value_type_variable,
+ vtn_value_type_deref,
vtn_value_type_function,
vtn_value_type_block,
vtn_value_type_ssa,
- vtn_value_type_deref,
};
struct vtn_value {
@@ -54,11 +53,10 @@ struct vtn_value {
char *str;
const struct glsl_type *type;
nir_constant *constant;
- nir_variable *var;
+ nir_deref_var *deref;
nir_function_impl *impl;
nir_block *block;
nir_ssa_def *ssa;
- nir_deref_var *deref;
};
};
@@ -353,10 +351,13 @@ vtn_handle_constant(struct vtn_builder *b, SpvOp opcode,
static void
var_decoration_cb(struct vtn_builder *b, struct vtn_value *val,
- const struct vtn_decoration *dec, void *unused)
+ const struct vtn_decoration *dec, void *void_var)
{
- assert(val->value_type == vtn_value_type_variable);
- nir_variable *var = val->var;
+ assert(val->value_type == vtn_value_type_deref);
+ assert(val->deref->deref.child == NULL);
+ assert(val->deref->var == void_var);
+
+ nir_variable *var = void_var;
switch (dec->decoration) {
case SpvDecorationPrecisionLow:
case SpvDecorationPrecisionMedium:
@@ -446,10 +447,9 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
case SpvOpVariable: {
const struct glsl_type *type =
vtn_value(b, w[1], vtn_value_type_type)->type;
- struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_variable);
+ struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_deref);
nir_variable *var = ralloc(b->shader, nir_variable);
- val->var = var;
var->type = type;
var->name = ralloc_strdup(var, val->name);
@@ -488,7 +488,71 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
vtn_value(b, w[4], vtn_value_type_constant)->constant;
}
- vtn_foreach_decoration(b, val, var_decoration_cb, NULL);
+ val->deref = nir_deref_var_create(b->shader, var);
+
+ vtn_foreach_decoration(b, val, var_decoration_cb, var);
+ break;
+ }
+
+ case SpvOpAccessChain:
+ case SpvOpInBoundsAccessChain: {
+ struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_deref);
+ nir_deref_var *base = vtn_value(b, w[3], vtn_value_type_deref)->deref;
+ val->deref = nir_deref_as_var(nir_copy_deref(b, &base->deref));
+
+ nir_deref *tail = &val->deref->deref;
+ while (tail->child)
+ tail = tail->child;
+
+ for (unsigned i = 0; i < count - 3; i++) {
+ assert(w[i + 3] < b->value_id_bound);
+ struct vtn_value *idx_val = &b->values[w[i + 3]];
+
+ enum glsl_base_type base_type = glsl_get_base_type(tail->type);
+ switch (base_type) {
+ case GLSL_TYPE_UINT:
+ case GLSL_TYPE_INT:
+ case GLSL_TYPE_FLOAT:
+ case GLSL_TYPE_DOUBLE:
+ case GLSL_TYPE_BOOL:
+ case GLSL_TYPE_ARRAY: {
+ nir_deref_array *deref_arr = nir_deref_array_create(b);
+ if (base_type == GLSL_TYPE_ARRAY) {
+ deref_arr->deref.type = glsl_get_array_element(tail->type);
+ } else if (glsl_type_is_matrix(tail->type)) {
+ deref_arr->deref.type = glsl_get_column_type(tail->type);
+ } else {
+ assert(glsl_type_is_vector(tail->type));
+ deref_arr->deref.type = glsl_scalar_type(base_type);
+ }
+
+ if (idx_val->value_type == vtn_value_type_constant) {
+ unsigned idx = idx_val->constant->value.u[0];
+ deref_arr->deref_array_type = nir_deref_array_type_direct;
+ deref_arr->base_offset = idx;
+ } else {
+ assert(idx_val->value_type == vtn_value_type_ssa);
+ deref_arr->deref_array_type = nir_deref_array_type_indirect;
+ /* TODO */
+ unreachable("Indirect array accesses not implemented");
+ }
+ tail->child = &deref_arr->deref;
+ break;
+ }
+
+ case GLSL_TYPE_STRUCT: {
+ assert(idx_val->value_type == vtn_value_type_constant);
+ unsigned idx = idx_val->constant->value.u[0];
+ nir_deref_struct *deref_struct = nir_deref_struct_create(b, idx);
+ deref_struct->deref.type = glsl_get_struct_field(tail->type, idx);
+ tail->child = &deref_struct->deref;
+ break;
+ }
+ default:
+ unreachable("Invalid type for deref");
+ }
+ tail = tail->child;
+ }
break;
}
@@ -497,8 +561,6 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
case SpvOpStore:
case SpvOpCopyMemory:
case SpvOpCopyMemorySized:
- case SpvOpAccessChain:
- case SpvOpInBoundsAccessChain:
case SpvOpArrayLength:
case SpvOpImagePointer:
default: