[Mesa-dev] [PATCH 1/2] spirv/nir: add support for ImageGatherExtended

Ilia Mirkin imirkin at alum.mit.edu
Thu Dec 15 02:23:54 UTC 2016


ping

On Sun, Nov 27, 2016 at 4:22 PM, Ilia Mirkin <imirkin at alum.mit.edu> wrote:
> The strategy is to do the same thing that the GLSL lower_offset_arrays
> pass does - create 4 separate texture gather ops, one per offset, and
> read in the results from each gather's w component to recreate the
> desired result.
>
> Signed-off-by: Ilia Mirkin <imirkin at alum.mit.edu>
> ---
>  src/compiler/spirv/spirv_to_nir.c | 76 +++++++++++++++++++++++++++++++++++----
>  1 file changed, 69 insertions(+), 7 deletions(-)
>
> diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c
> index 34968a4..73d0643 100644
> --- a/src/compiler/spirv/spirv_to_nir.c
> +++ b/src/compiler/spirv/spirv_to_nir.c
> @@ -1487,6 +1487,7 @@ vtn_handle_texture(struct vtn_builder *b, SpvOp opcode,
>        (*p++) = vtn_tex_src(b, w[idx++], nir_tex_src_lod);
>
>     /* Now we need to handle some number of optional arguments */
> +   const struct vtn_ssa_value *gather_offsets = NULL;
>     if (idx < count) {
>        uint32_t operands = w[idx++];
>
> @@ -1513,8 +1514,10 @@ vtn_handle_texture(struct vtn_builder *b, SpvOp opcode,
>            operands & SpvImageOperandsConstOffsetMask)
>           (*p++) = vtn_tex_src(b, w[idx++], nir_tex_src_offset);
>
> -      if (operands & SpvImageOperandsConstOffsetsMask)
> -         assert(!"Constant offsets to texture gather not yet implemented");
> +      if (operands & SpvImageOperandsConstOffsetsMask) {
> +         gather_offsets = vtn_ssa_value(b, w[idx++]);
> +         (*p++) = (nir_tex_src){};
> +      }
>
>        if (operands & SpvImageOperandsSampleMask) {
>           assert(texop == nir_texop_txf_ms);
> @@ -1548,13 +1551,16 @@ vtn_handle_texture(struct vtn_builder *b, SpvOp opcode,
>     }
>
>     nir_deref_var *sampler = vtn_access_chain_to_deref(b, sampled.sampler);
> +   nir_deref *texture;
>     if (sampled.image) {
>        nir_deref_var *image = vtn_access_chain_to_deref(b, sampled.image);
> -      instr->texture = nir_deref_as_var(nir_copy_deref(instr, &image->deref));
> +      texture = &image->deref;
>     } else {
> -      instr->texture = nir_deref_as_var(nir_copy_deref(instr, &sampler->deref));
> +      texture = &sampler->deref;
>     }
>
> +   instr->texture = nir_deref_as_var(nir_copy_deref(instr, texture));
> +
>     switch (instr->op) {
>     case nir_texop_tex:
>     case nir_texop_txb:
> @@ -1584,10 +1590,66 @@ vtn_handle_texture(struct vtn_builder *b, SpvOp opcode,
>     assert(glsl_get_vector_elements(ret_type->type) ==
>            nir_tex_instr_dest_size(instr));
>
> +   nir_ssa_def *def;
> +   nir_instr *instruction;
> +   if (gather_offsets) {
> +      assert(glsl_get_base_type(gather_offsets->type) == GLSL_TYPE_ARRAY);
> +      assert(glsl_get_length(gather_offsets->type) == 4);
> +      nir_tex_instr *instrs[4] = {instr, NULL, NULL, NULL};
> +
> +      /* Copy the current instruction 4x */
> +      for (uint32_t i = 1; i < 4; i++) {
> +         instrs[i] = nir_tex_instr_create(b->shader, instr->num_srcs);
> +         instrs[i]->op = instr->op;
> +         instrs[i]->coord_components = instr->coord_components;
> +         instrs[i]->sampler_dim = instr->sampler_dim;
> +         instrs[i]->is_array = instr->is_array;
> +         instrs[i]->is_shadow = instr->is_shadow;
> +         instrs[i]->is_new_style_shadow = instr->is_new_style_shadow;
> +         instrs[i]->component = instr->component;
> +         instrs[i]->dest_type = instr->dest_type;
> +         instrs[i]->texture =
> +            nir_deref_as_var(nir_copy_deref(instrs[i], texture));
> +         instrs[i]->sampler = NULL;
> +
> +         memcpy(instrs[i]->src, srcs, instr->num_srcs * sizeof(*instr->src));
> +
> +         nir_ssa_dest_init(&instrs[i]->instr, &instrs[i]->dest,
> +                           nir_tex_instr_dest_size(instr), 32, NULL);
> +      }
> +
> +      /* Fill in the last argument with the offset from the passed in offsets
> +       * and insert the instruction into the stream.
> +       */
> +      for (uint32_t i = 0; i < 4; i++) {
> +         nir_tex_src src;
> +         src.src = nir_src_for_ssa(gather_offsets->elems[i]->def);
> +         src.src_type = nir_tex_src_offset;
> +         instrs[i]->src[instrs[i]->num_srcs - 1] = src;
> +         nir_builder_instr_insert(&b->nb, &instrs[i]->instr);
> +      }
> +
> +      /* Combine the results of the 4 instructions by taking their .w
> +       * components
> +       */
> +      nir_alu_instr *vec4 = nir_alu_instr_create(b->shader, nir_op_vec4);
> +      nir_ssa_dest_init(&vec4->instr, &vec4->dest.dest, 4, 32, NULL);
> +      vec4->dest.write_mask = 0xf;
> +      for (uint32_t i = 0; i < 4; i++) {
> +         vec4->src[i].src = nir_src_for_ssa(&instrs[i]->dest.ssa);
> +         vec4->src[i].swizzle[0] = 3;
> +      }
> +      def = &vec4->dest.dest.ssa;
> +      instruction = &vec4->instr;
> +   } else {
> +      def = &instr->dest.ssa;
> +      instruction = &instr->instr;
> +   }
> +
>     val->ssa = vtn_create_ssa_value(b, ret_type->type);
> -   val->ssa->def = &instr->dest.ssa;
> +   val->ssa->def = def;
>
> -   nir_builder_instr_insert(&b->nb, &instr->instr);
> +   nir_builder_instr_insert(&b->nb, instruction);
>  }
>
>  static void
> @@ -2446,6 +2508,7 @@ vtn_handle_preamble_instruction(struct vtn_builder *b, SpvOp opcode,
>        case SpvCapabilityClipDistance:
>        case SpvCapabilityCullDistance:
>        case SpvCapabilityInputAttachment:
> +      case SpvCapabilityImageGatherExtended:
>           break;
>
>        case SpvCapabilityGeometryStreams:
> @@ -2460,7 +2523,6 @@ vtn_handle_preamble_instruction(struct vtn_builder *b, SpvOp opcode,
>        case SpvCapabilityInt64Atomics:
>        case SpvCapabilityAtomicStorage:
>        case SpvCapabilityInt16:
> -      case SpvCapabilityImageGatherExtended:
>        case SpvCapabilityStorageImageMultisample:
>        case SpvCapabilityImageCubeArray:
>        case SpvCapabilityInt8:
> --
> 2.7.3
>


More information about the mesa-dev mailing list