On Fri, Mar 23, 2018 at 12:33 PM, Karol Herbst <kher...@redhat.com> wrote:
> 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)") > This bit should be it's own patch. It looks correct to me. Might as well add the other two when you make a patch for it though. For whatever it's worth, Intel hardware calls this opcode AVG (for average). I'm not sure what "hadd" is supposed to stand for. Maybe half-add? Anyway, I don't care about naming. --Jason > 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 >
_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev