summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJordan Justen <[email protected]>2016-01-11 21:53:35 -0800
committerJordan Justen <[email protected]>2016-01-13 23:34:45 -0800
commit8ce2b0e1405b3d6d3590dcd3ce1ac2d04d228ad4 (patch)
tree3dc81a556675e3f2e2a5426fd3acdb14f9b0ef7e
parent4507d8a57af7df679fc0e7b56f4441519ff7e3d4 (diff)
nir/spirv: Add support for ArrayLength op
Signed-off-by: Jordan Justen <[email protected]>
-rw-r--r--src/glsl/nir/spirv/spirv_to_nir.c33
1 files changed, 32 insertions, 1 deletions
diff --git a/src/glsl/nir/spirv/spirv_to_nir.c b/src/glsl/nir/spirv/spirv_to_nir.c
index ca9781d263d..4462c9f5a80 100644
--- a/src/glsl/nir/spirv/spirv_to_nir.c
+++ b/src/glsl/nir/spirv/spirv_to_nir.c
@@ -2188,8 +2188,39 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
break;
}
+ case SpvOpArrayLength: {
+ struct vtn_value *v_deref = vtn_value(b, w[3], vtn_value_type_deref);
+ struct vtn_type *type = v_deref->deref_type;
+ const uint32_t offset = type->offsets[w[4]];
+ const uint32_t stride = type->members[w[4]]->stride;
+ nir_deref *n_deref = &v_deref->deref->deref;
+ nir_ssa_def *index =
+ get_vulkan_resource_index(b, &n_deref, &type);
+ nir_intrinsic_instr *instr =
+ nir_intrinsic_instr_create(b->nb.shader,
+ nir_intrinsic_get_buffer_size);
+ instr->src[0] = nir_src_for_ssa(index);
+ nir_ssa_dest_init(&instr->instr, &instr->dest, 1, NULL);
+ nir_builder_instr_insert(&b->nb, &instr->instr);
+ nir_ssa_def *buf_size = &instr->dest.ssa;
+
+ /* array_length = max(buffer_size - offset, 0) / stride */
+ nir_ssa_def *array_length =
+ nir_idiv(&b->nb,
+ nir_imax(&b->nb,
+ nir_isub(&b->nb,
+ buf_size,
+ nir_imm_int(&b->nb, offset)),
+ nir_imm_int(&b->nb, 0u)),
+ nir_imm_int(&b->nb, stride));
+
+ struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_ssa);
+ val->ssa = vtn_create_ssa_value(b, glsl_uint_type());
+ val->ssa->def = array_length;
+ break;
+ }
+
case SpvOpCopyMemorySized:
- case SpvOpArrayLength:
default:
unreachable("Unhandled opcode");
}