From: Rob Clark <robdcl...@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 <kher...@redhat.com>) Signed-off-by: Rob Clark <robdcl...@gmail.com> Signed-off-by: Karol Herbst <kher...@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 (robdcl...@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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev