summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaio Marcelo de Oliveira Filho <caio.oliveira@intel.com>2020-12-16 20:51:30 -0800
committerCaio Marcelo de Oliveira Filho <caio.oliveira@intel.com>2020-12-18 12:52:28 -0800
commita5f47bc43d6c34ed76d921b9aeaae952ca6a8bd9 (patch)
tree597863eff0eca35bd28d09a4e915542b92c2d38a
parentf99fc9e73e374494536101d42abdab5e45f0ab5d (diff)
spirv: Implement OpArrayLength for OpenGL
Uses same NIR intrinsic as glsl_to_nir. Make it an option so it is easy later to move Vulkan drivers incrementally to use it. Fixes piglit test spec/arb_gl_spirv/execution/ssbo/unsized-array-length. Backported from f65750d2215 ("spirv: Implement OpArrayLength for OpenGL"). Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/3691 Fixes: 15e43907 ("iris: Enable ARB_gl_spirv and ARB_spirv_extensions") Reviewed-by: Alejandro PiƱeiro <apinheiro@igalia.com> Reviewed-by: Jason Ekstrand <jason@jlekstrand.net> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8167>
-rw-r--r--src/compiler/spirv/nir_spirv.h5
-rw-r--r--src/compiler/spirv/vtn_variables.c73
-rw-r--r--src/mesa/main/glspirv.c1
3 files changed, 52 insertions, 27 deletions
diff --git a/src/compiler/spirv/nir_spirv.h b/src/compiler/spirv/nir_spirv.h
index 5964184338b..750c77764e0 100644
--- a/src/compiler/spirv/nir_spirv.h
+++ b/src/compiler/spirv/nir_spirv.h
@@ -69,6 +69,11 @@ struct spirv_to_nir_options {
/* Create a nir library. */
bool create_library;
+ /* Whether to use nir_intrinsic_deref_buffer_array_length intrinsic instead
+ * of nir_intrinsic_get_ssbo_size to lower OpArrayLength.
+ */
+ bool use_deref_buffer_array_length;
+
struct spirv_supported_capabilities caps;
/* Address format for various kinds of pointers. */
diff --git a/src/compiler/spirv/vtn_variables.c b/src/compiler/spirv/vtn_variables.c
index 168d0e5156f..83171160a59 100644
--- a/src/compiler/spirv/vtn_variables.c
+++ b/src/compiler/spirv/vtn_variables.c
@@ -2434,36 +2434,55 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
"OpArrayLength must reference the last memeber of the "
"structure and that must be an array");
- const uint32_t offset = ptr->type->offsets[field];
- const uint32_t stride = ptr->type->members[field]->stride;
-
- if (!ptr->block_index) {
+ if (b->options->use_deref_buffer_array_length) {
struct vtn_access_chain chain = {
- .length = 0,
+ .length = 1,
+ .link = {
+ { .mode = vtn_access_mode_literal, .id = field },
+ }
};
- ptr = vtn_pointer_dereference(b, ptr, &chain);
- vtn_assert(ptr->block_index);
- }
+ struct vtn_pointer *array = vtn_pointer_dereference(b, ptr, &chain);
- nir_intrinsic_instr *instr =
- nir_intrinsic_instr_create(b->nb.shader,
- nir_intrinsic_get_ssbo_size);
- instr->src[0] = nir_src_for_ssa(ptr->block_index);
- nir_ssa_dest_init(&instr->instr, &instr->dest, 1, 32, 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));
-
- vtn_push_nir_ssa(b, w[2], array_length);
+ nir_intrinsic_instr *instr =
+ nir_intrinsic_instr_create(b->nb.shader,
+ nir_intrinsic_deref_buffer_array_length);
+ instr->src[0] = nir_src_for_ssa(vtn_pointer_to_ssa(b, array));
+ nir_ssa_dest_init(&instr->instr, &instr->dest, 1, 32, NULL);
+ nir_builder_instr_insert(&b->nb, &instr->instr);
+
+ vtn_push_nir_ssa(b, w[2], &instr->dest.ssa);
+ } else {
+ const uint32_t offset = ptr->type->offsets[field];
+ const uint32_t stride = ptr->type->members[field]->stride;
+
+ if (!ptr->block_index) {
+ struct vtn_access_chain chain = {
+ .length = 0,
+ };
+ ptr = vtn_pointer_dereference(b, ptr, &chain);
+ vtn_assert(ptr->block_index);
+ }
+
+ nir_intrinsic_instr *instr =
+ nir_intrinsic_instr_create(b->nb.shader,
+ nir_intrinsic_get_ssbo_size);
+ instr->src[0] = nir_src_for_ssa(ptr->block_index);
+ nir_ssa_dest_init(&instr->instr, &instr->dest, 1, 32, 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));
+
+ vtn_push_nir_ssa(b, w[2], array_length);
+ }
break;
}
diff --git a/src/mesa/main/glspirv.c b/src/mesa/main/glspirv.c
index 92c521ba649..1668be08d95 100644
--- a/src/mesa/main/glspirv.c
+++ b/src/mesa/main/glspirv.c
@@ -244,6 +244,7 @@ _mesa_spirv_to_nir(struct gl_context *ctx,
const struct spirv_to_nir_options spirv_options = {
.environment = NIR_SPIRV_OPENGL,
.frag_coord_is_sysval = ctx->Const.GLSLFragCoordIsSysVal,
+ .use_deref_buffer_array_length = true,
.caps = ctx->Const.SpirVCapabilities,
.ubo_addr_format = nir_address_format_32bit_index_offset,
.ssbo_addr_format = nir_address_format_32bit_index_offset,