[Mesa-dev] [PATCH v3 09/19] nir/vtn: initial OpenCL.std extension
Karol Herbst
kherbst at redhat.com
Fri Mar 23 19:33:46 UTC 2018
From: Rob Clark <robdclark at gmail.com>
Not complete, mostly just adding things as I encounter them in CTS. But
not getting far enough yet to hit most of the OpenCL.std instructions.
v2: update hadd definition (Karol Herbst <kherbst at redhat.com>)
Signed-off-by: Rob Clark <robdclark at gmail.com>
Signed-off-by: Karol Herbst <kherbst at redhat.com>
---
src/compiler/nir/meson.build | 1 +
src/compiler/nir/nir_opcodes.py | 3 +-
src/compiler/spirv/spirv_to_nir.c | 2 +
src/compiler/spirv/vtn_opencl.c | 266 ++++++++++++++++++++++++++++++++++++++
src/compiler/spirv/vtn_private.h | 3 +
5 files changed, 274 insertions(+), 1 deletion(-)
create mode 100644 src/compiler/spirv/vtn_opencl.c
diff --git a/src/compiler/nir/meson.build b/src/compiler/nir/meson.build
index a70c236b958..213a139a1b8 100644
--- a/src/compiler/nir/meson.build
+++ b/src/compiler/nir/meson.build
@@ -192,6 +192,7 @@ files_libnir = files(
'../spirv/vtn_amd.c',
'../spirv/vtn_cfg.c',
'../spirv/vtn_glsl450.c',
+ '../spirv/vtn_opencl.c',
'../spirv/vtn_private.h',
'../spirv/vtn_subgroup.c',
'../spirv/vtn_variables.c',
diff --git a/src/compiler/nir/nir_opcodes.py b/src/compiler/nir/nir_opcodes.py
index 65d13200624..86fd6b6d68e 100644
--- a/src/compiler/nir/nir_opcodes.py
+++ b/src/compiler/nir/nir_opcodes.py
@@ -768,4 +768,5 @@ dst.z = src2.x;
dst.w = src3.x;
""")
-
+binop("ihadd", tint, commutative, "(src0 >> 1) + (src1 >> 1) + (src0 & src1 & 1)")
+binop("uhadd", tuint, commutative, "(src0 >> 1) + (src1 >> 1) + (src0 & src1 & 1)")
diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c
index 3acb3fc0b42..6a16d77a771 100644
--- a/src/compiler/spirv/spirv_to_nir.c
+++ b/src/compiler/spirv/spirv_to_nir.c
@@ -379,6 +379,8 @@ vtn_handle_extension(struct vtn_builder *b, SpvOp opcode,
} else if ((strcmp((const char *)&w[2], "SPV_AMD_gcn_shader") == 0)
&& (b->options && b->options->caps.gcn_shader)) {
val->ext_handler = vtn_handle_amd_gcn_shader_instruction;
+ } else if (strcmp(ext, "OpenCL.std") == 0) {
+ val->ext_handler = vtn_handle_opencl_instruction;
} else {
vtn_fail("Unsupported extension: %s", ext);
}
diff --git a/src/compiler/spirv/vtn_opencl.c b/src/compiler/spirv/vtn_opencl.c
new file mode 100644
index 00000000000..3c5ecd22452
--- /dev/null
+++ b/src/compiler/spirv/vtn_opencl.c
@@ -0,0 +1,266 @@
+/*
+ * Copyright © 2018 Red Hat
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ * Rob Clark (robdclark at gmail.com)
+ */
+
+#include "vtn_private.h"
+#include "OpenCL.std.h"
+
+typedef nir_ssa_def *(*nir_handler)(struct vtn_builder *b, enum OpenCLstd opcode,
+ unsigned num_srcs, nir_ssa_def **srcs);
+
+static void
+handle_instr(struct vtn_builder *b, enum OpenCLstd opcode, const uint32_t *w,
+ unsigned count, nir_handler handler)
+{
+ const struct glsl_type *dest_type =
+ vtn_value(b, w[1], vtn_value_type_type)->type->type;
+
+ unsigned num_srcs = count - 5;
+ nir_ssa_def *srcs[3] = { NULL, };
+ vtn_assert(num_srcs <= ARRAY_SIZE(srcs));
+ for (unsigned i = 0; i < num_srcs; i++) {
+ srcs[i] = vtn_ssa_value(b, w[i + 5])->def;
+ }
+
+ nir_ssa_def *result = handler(b, opcode, num_srcs, srcs);
+ if (result) {
+ struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_ssa);
+ val->ssa = vtn_create_ssa_value(b, dest_type);
+ val->ssa->def = result;
+ } else {
+ vtn_assert(dest_type == glsl_void_type());
+ }
+}
+
+static nir_op
+nir_alu_op_for_opencl_opcode(struct vtn_builder *b, enum OpenCLstd opcode)
+{
+ switch (opcode) {
+ case SHadd: return nir_op_ihadd;
+ case UHadd: return nir_op_uhadd;
+ default:
+ vtn_fail("No NIR equivalent");
+ }
+}
+
+static nir_ssa_def *
+handle_alu(struct vtn_builder *b, enum OpenCLstd opcode, unsigned num_srcs,
+ nir_ssa_def **srcs)
+{
+ return nir_build_alu(&b->nb, nir_alu_op_for_opencl_opcode(b, opcode),
+ srcs[0], srcs[1], srcs[2], NULL);
+}
+
+static nir_ssa_def *
+handle_printf(struct vtn_builder *b, enum OpenCLstd opcode, unsigned num_srcs,
+ nir_ssa_def **srcs)
+{
+ /* hahah, yeah, right.. */
+ return nir_imm_int(&b->nb, -1);
+}
+
+static void
+vtn_handle_opencl_vload(struct vtn_builder *b, enum OpenCLstd opcode,
+ const uint32_t *w, unsigned count)
+{
+ const struct glsl_type *dest_type =
+ vtn_value(b, w[1], vtn_value_type_type)->type->type;
+ unsigned num_components, bit_size;
+
+ struct vtn_value *val = vtn_push_value(b, w[2], vtn_value_type_ssa);
+ val->ssa = vtn_create_ssa_value(b, dest_type);
+
+ switch (opcode) {
+ case Vload_half:
+ case Vload_halfn:
+ case Vloada_halfn:
+ bit_size = 16;
+ break;
+ default:
+ bit_size = glsl_get_bit_size(dest_type);
+ break;
+ }
+
+ nir_ssa_def *offset = vtn_ssa_value(b, w[5])->def;
+ nir_ssa_def *p = vtn_ssa_value(b, w[6])->def;
+
+ if (count >= 7) {
+ num_components = w[7];
+
+ unsigned off;
+ if ((opcode == Vloada_halfn) && (num_components == 3)) {
+ off = 4 * bit_size / 8;
+ } else {
+ off = num_components * bit_size / 8;
+ }
+
+ nir_ssa_def *n = (b->ptr_size == 64) ?
+ nir_imm_int64(&b->nb, off) :
+ nir_imm_int(&b->nb, off);
+
+ offset = nir_imul(&b->nb, offset, n);
+ } else {
+ num_components = 1;
+ }
+
+ /* add offset to pointer: */
+ p = nir_iadd(&b->nb, p, offset);
+
+ nir_intrinsic_op op = nir_intrinsic_load_global;
+
+ nir_intrinsic_instr *intrin = nir_intrinsic_instr_create(b->shader, op);
+ intrin->num_components = num_components;
+ intrin->src[0] = nir_src_for_ssa(p);
+
+ nir_ssa_dest_init(&intrin->instr, &intrin->dest,
+ intrin->num_components,
+ bit_size,
+ NULL);
+ val->ssa->def = &intrin->dest.ssa;
+
+ nir_builder_instr_insert(&b->nb, &intrin->instr);
+
+ switch (opcode) {
+ case Vload_half:
+ case Vload_halfn:
+ case Vloada_halfn:
+ /* convert f16->f32: */
+ val->ssa->def = nir_f2f32(&b->nb, val->ssa->def);
+ break;
+ default:
+ break;
+ }
+}
+
+static void
+vtn_handle_opencl_vstore(struct vtn_builder *b, enum OpenCLstd opcode,
+ const uint32_t *w, unsigned count)
+{
+ unsigned num_components, bit_size;
+ const struct glsl_type *src_type = vtn_ssa_value(b, w[5])->type;
+
+ nir_ssa_def *data = vtn_ssa_value(b, w[5])->def;
+ nir_ssa_def *offset = vtn_ssa_value(b, w[6])->def;
+ nir_ssa_def *p = vtn_ssa_value(b, w[7])->def;
+
+ // ??? MAX2(1, glsl_get_vector_elements(src_type));
+ num_components = data->num_components;
+
+ switch (opcode) {
+ case Vstore_half_r:
+ case Vstore_halfn_r:
+ case Vstorea_halfn_r:
+ bit_size = 16;
+ switch (w[8]) {
+ case SpvFPRoundingModeRTE:
+ data = nir_f2f16_rtne(&b->nb, data);
+ break;
+ case SpvFPRoundingModeRTZ:
+ data = nir_f2f16_rtz(&b->nb, data);
+ break;
+ case SpvFPRoundingModeRTP:
+ case SpvFPRoundingModeRTN:
+ default:
+ vtn_fail("unsupported rounding mode: %u\n", w[8]);
+ break;
+ }
+ break;
+ case Vstore_half:
+ case Vstore_halfn:
+ case Vstorea_halfn:
+ bit_size = 16;
+ data = nir_f2f16_undef(&b->nb, data);
+ break;
+ default:
+ bit_size = glsl_get_bit_size(src_type);
+ break;
+ }
+
+ if (num_components > 1) {
+ unsigned off;
+
+ if (((opcode == Vstorea_halfn_r) || (opcode == Vstorea_halfn)) &&
+ (num_components == 3)) {
+ off = 4 * bit_size / 8;
+ } else {
+ off = num_components * bit_size / 8;
+ }
+
+ nir_ssa_def *n = (b->ptr_size == 64) ?
+ nir_imm_int64(&b->nb, off) :
+ nir_imm_int(&b->nb, off);
+
+ offset = nir_imul(&b->nb, offset, n);
+ }
+
+ /* add offset to pointer: */
+ p = nir_iadd(&b->nb, p, offset);
+
+ nir_intrinsic_op op = nir_intrinsic_store_global;
+
+ nir_intrinsic_instr *intrin = nir_intrinsic_instr_create(b->shader, op);
+ intrin->num_components = num_components;
+ intrin->src[0] = nir_src_for_ssa(data);
+ intrin->src[1] = nir_src_for_ssa(p);
+ nir_intrinsic_set_write_mask(intrin, (1 << num_components) - 1);
+
+ nir_builder_instr_insert(&b->nb, &intrin->instr);
+}
+
+bool
+vtn_handle_opencl_instruction(struct vtn_builder *b, uint32_t ext_opcode,
+ const uint32_t *w, unsigned count)
+{
+ switch (ext_opcode) {
+ case SHadd:
+ case UHadd:
+ handle_instr(b, ext_opcode, w, count, handle_alu);
+ return true;
+ case Vloadn:
+ case Vload_half:
+ case Vload_halfn:
+ case Vloada_halfn:
+ vtn_handle_opencl_vload(b, ext_opcode, w, count);
+ return true;
+ case Vstoren:
+ case Vstore_half:
+ case Vstore_half_r:
+ case Vstore_halfn:
+ case Vstore_halfn_r:
+ case Vstorea_halfn:
+ case Vstorea_halfn_r:
+ vtn_handle_opencl_vstore(b, ext_opcode, w, count);
+ return true;
+ case Printf:
+ handle_instr(b, ext_opcode, w, count, handle_printf);
+ return true;
+ case Prefetch:
+ /* TODO maybe add a nir instruction for this? */
+ return true;
+ default:
+ vtn_fail("unhandled opencl opc: %u\n", ext_opcode);
+ return false;
+ }
+}
diff --git a/src/compiler/spirv/vtn_private.h b/src/compiler/spirv/vtn_private.h
index dbfe9eab58a..510c12faa87 100644
--- a/src/compiler/spirv/vtn_private.h
+++ b/src/compiler/spirv/vtn_private.h
@@ -744,6 +744,9 @@ void vtn_handle_subgroup(struct vtn_builder *b, SpvOp opcode,
bool vtn_handle_glsl450_instruction(struct vtn_builder *b, uint32_t ext_opcode,
const uint32_t *words, unsigned count);
+bool vtn_handle_opencl_instruction(struct vtn_builder *b, uint32_t ext_opcode,
+ const uint32_t *words, unsigned count);
+
static inline uint32_t
vtn_align_u32(uint32_t v, uint32_t a)
{
--
2.14.3
More information about the mesa-dev
mailing list