[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