[Mesa-dev] [PATCH v3 09/19] nir/vtn: initial OpenCL.std extension

Jason Ekstrand jason at jlekstrand.net
Fri Mar 23 22:46:40 UTC 2018


On Fri, Mar 23, 2018 at 12:33 PM, Karol Herbst <kherbst at redhat.com> wrote:

> 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)")
>

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 (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
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20180323/763dd237/attachment-0001.html>


More information about the mesa-dev mailing list