[Mesa-dev] [PATCH] spirv/nir: Add support for OpAtomicLoad/Store

Lionel Landwerlin llandwerlin at gmail.com
Wed Sep 7 18:28:15 UTC 2016


Hi Mark,

Thanks for the report.
The assumption is that coord will be set on the image by a preceding
SpvOpImageTexelPointer opcode (see top of the
vtn_handle_image function).

I don't think there are tests in the CTS exercising this at the moment
:(

-
Lionel

On Wed, 2016-09-07 at 10:14 -0700, Mark Janes wrote:
> Hi Lionel,
> 
> This patch triggered CID 1372521 in Coverity.  Please let me know if
> my
> the analysis is correct below:
> 
> Lionel Landwerlin <llandwerlin at gmail.com> writes:
> 
> > 
> > Fixes new CTS tests :
> > 
> > dEQP-VK.spirv_assembly.instruction.compute.opatomic.load
> > dEQP-VK.spirv_assembly.instruction.compute.opatomic.store
> > 
> > v2: don't handle images like ssbo/ubo (Jason)
> > 
> > Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin at intel.com>
> > Cc: Jason Ekstrand <jason.ekstrand at intel.com>
> > ---
> >  src/compiler/spirv/spirv_to_nir.c | 124
> > ++++++++++++++++++++++++++++++++++----
> >  1 file changed, 113 insertions(+), 11 deletions(-)
> > 
> > diff --git a/src/compiler/spirv/spirv_to_nir.c
> > b/src/compiler/spirv/spirv_to_nir.c
> > index fda38f9..1fcd70f 100644
> > --- a/src/compiler/spirv/spirv_to_nir.c
> > +++ b/src/compiler/spirv/spirv_to_nir.c
> > @@ -1640,6 +1640,18 @@ vtn_handle_image(struct vtn_builder *b,
> > SpvOp opcode,
> >        image = *vtn_value(b, w[3], vtn_value_type_image_pointer)-
> > >image;
> >        break;
> >  
> > +   case SpvOpAtomicLoad: {
> > +      image.image =
> > +         vtn_value(b, w[3], vtn_value_type_access_chain)-
> > >access_chain;
> > +      break;
> > +   }
> > +
> > +   case SpvOpAtomicStore: {
> > +      image.image =
> > +         vtn_value(b, w[1], vtn_value_type_access_chain)-
> > >access_chain;
> > +      break;
> > +   }
> 
> These cases do not initialize image.coord, which is dereferenced on
> line
> 1773.  SpvOpImageQuerySize is a similar case which sets image.coord
> to
> NULL and is excepted from the code path at line 1773.
> 
> > 
> >     case SpvOpImageQuerySize:
> >        image.image =
> >           vtn_value(b, w[3], vtn_value_type_access_chain)-
> > >access_chain;
> > @@ -1685,6 +1697,8 @@ vtn_handle_image(struct vtn_builder *b, SpvOp
> > opcode,
> >     OP(ImageQuerySize,         size)
> >     OP(ImageRead,              load)
> >     OP(ImageWrite,             store)
> > +   OP(AtomicLoad,             load)
> > +   OP(AtomicStore,            store)
> >     OP(AtomicExchange,         atomic_exchange)
> >     OP(AtomicCompareExchange,  atomic_comp_swap)
> >     OP(AtomicIIncrement,       atomic_add)
> > @@ -1723,9 +1737,13 @@ vtn_handle_image(struct vtn_builder *b,
> > SpvOp opcode,
> >     }
> >  
> >     switch (opcode) {
> > +   case SpvOpAtomicLoad:
> >     case SpvOpImageQuerySize:
> >     case SpvOpImageRead:
> >        break;
> > +   case SpvOpAtomicStore:
> > +      intrin->src[2] = nir_src_for_ssa(vtn_ssa_value(b, w[4])-
> > >def);
> > +      break;
> >     case SpvOpImageWrite:
> >        intrin->src[2] = nir_src_for_ssa(vtn_ssa_value(b, w[3])-
> > >def);
> >        break;
> > @@ -1784,6 +1802,8 @@ static nir_intrinsic_op
> >  get_ssbo_nir_atomic_op(SpvOp opcode)
> >  {
> >     switch (opcode) {
> > +   case SpvOpAtomicLoad:      return nir_intrinsic_load_ssbo;
> > +   case SpvOpAtomicStore:     return nir_intrinsic_store_ssbo;
> >  #define OP(S, N) case SpvOp##S: return nir_intrinsic_ssbo_##N;
> >     OP(AtomicExchange,         atomic_exchange)
> >     OP(AtomicCompareExchange,  atomic_comp_swap)
> > @@ -1808,6 +1828,8 @@ static nir_intrinsic_op
> >  get_shared_nir_atomic_op(SpvOp opcode)
> >  {
> >     switch (opcode) {
> > +   case SpvOpAtomicLoad:      return nir_intrinsic_load_var;
> > +   case SpvOpAtomicStore:     return nir_intrinsic_store_var;
> >  #define OP(S, N) case SpvOp##S: return nir_intrinsic_var_##N;
> >     OP(AtomicExchange,         atomic_exchange)
> >     OP(AtomicCompareExchange,  atomic_comp_swap)
> > @@ -1873,10 +1895,38 @@ static void
> >  vtn_handle_ssbo_or_shared_atomic(struct vtn_builder *b, SpvOp
> > opcode,
> >                                   const uint32_t *w, unsigned
> > count)
> >  {
> > -   struct vtn_access_chain *chain =
> > -      vtn_value(b, w[3], vtn_value_type_access_chain)-
> > >access_chain;
> > +   struct vtn_access_chain *chain;
> >     nir_intrinsic_instr *atomic;
> >  
> > +   switch (opcode) {
> > +   case SpvOpAtomicLoad:
> > +   case SpvOpAtomicExchange:
> > +   case SpvOpAtomicCompareExchange:
> > +   case SpvOpAtomicCompareExchangeWeak:
> > +   case SpvOpAtomicIIncrement:
> > +   case SpvOpAtomicIDecrement:
> > +   case SpvOpAtomicIAdd:
> > +   case SpvOpAtomicISub:
> > +   case SpvOpAtomicSMin:
> > +   case SpvOpAtomicUMin:
> > +   case SpvOpAtomicSMax:
> > +   case SpvOpAtomicUMax:
> > +   case SpvOpAtomicAnd:
> > +   case SpvOpAtomicOr:
> > +   case SpvOpAtomicXor:
> > +      chain =
> > +         vtn_value(b, w[3], vtn_value_type_access_chain)-
> > >access_chain;
> > +      break;
> > +
> > +   case SpvOpAtomicStore:
> > +      chain =
> > +         vtn_value(b, w[1], vtn_value_type_access_chain)-
> > >access_chain;
> > +      break;
> > +
> > +   default:
> > +      unreachable("Invalid SPIR-V atomic");
> > +   }
> > +
> >     /*
> >     SpvScope scope = w[4];
> >     SpvMemorySemanticsMask semantics = w[5];
> > @@ -1897,18 +1947,58 @@ vtn_handle_ssbo_or_shared_atomic(struct
> > vtn_builder *b, SpvOp opcode,
> >        nir_intrinsic_op op = get_ssbo_nir_atomic_op(opcode);
> >  
> >        atomic = nir_intrinsic_instr_create(b->nb.shader, op);
> > -      atomic->src[0] = nir_src_for_ssa(index);
> > -      atomic->src[1] = nir_src_for_ssa(offset);
> > -      fill_common_atomic_sources(b, opcode, w, &atomic->src[2]);
> > +
> > +      switch (opcode) {
> > +      case SpvOpAtomicLoad:
> > +         atomic->num_components = glsl_get_vector_elements(type-
> > >type);
> > +         atomic->src[0] = nir_src_for_ssa(index);
> > +         atomic->src[1] = nir_src_for_ssa(offset);
> > +         break;
> > +
> > +      case SpvOpAtomicStore:
> > +         atomic->num_components = glsl_get_vector_elements(type-
> > >type);
> > +         nir_intrinsic_set_write_mask(atomic, (1 << atomic-
> > >num_components) - 1);
> > +         atomic->src[0] = nir_src_for_ssa(vtn_ssa_value(b, w[4])-
> > >def);
> > +         atomic->src[1] = nir_src_for_ssa(index);
> > +         atomic->src[2] = nir_src_for_ssa(offset);
> > +         break;
> > +
> > +      case SpvOpAtomicExchange:
> > +      case SpvOpAtomicCompareExchange:
> > +      case SpvOpAtomicCompareExchangeWeak:
> > +      case SpvOpAtomicIIncrement:
> > +      case SpvOpAtomicIDecrement:
> > +      case SpvOpAtomicIAdd:
> > +      case SpvOpAtomicISub:
> > +      case SpvOpAtomicSMin:
> > +      case SpvOpAtomicUMin:
> > +      case SpvOpAtomicSMax:
> > +      case SpvOpAtomicUMax:
> > +      case SpvOpAtomicAnd:
> > +      case SpvOpAtomicOr:
> > +      case SpvOpAtomicXor:
> > +         atomic->src[0] = nir_src_for_ssa(index);
> > +         atomic->src[1] = nir_src_for_ssa(offset);
> > +         fill_common_atomic_sources(b, opcode, w, &atomic-
> > >src[2]);
> > +         break;
> > +
> > +      default:
> > +         unreachable("Invalid SPIR-V atomic");
> > +      }
> >     }
> >  
> > -   nir_ssa_dest_init(&atomic->instr, &atomic->dest, 1, 32, NULL);
> > +   if (opcode != SpvOpAtomicStore) {
> > +      struct vtn_type *type = vtn_value(b, w[1],
> > vtn_value_type_type)->type;
> > +
> > +      nir_ssa_dest_init(&atomic->instr, &atomic->dest,
> > +                        glsl_get_vector_elements(type->type),
> > +                        glsl_get_bit_size(type->type), NULL);
> >  
> > -   struct vtn_type *type = vtn_value(b, w[1],
> > vtn_value_type_type)->type;
> > -   struct vtn_value *val = vtn_push_value(b, w[2],
> > vtn_value_type_ssa);
> > -   val->ssa = rzalloc(b, struct vtn_ssa_value);
> > -   val->ssa->def = &atomic->dest.ssa;
> > -   val->ssa->type = type->type;
> > +      struct vtn_value *val = vtn_push_value(b, w[2],
> > vtn_value_type_ssa);
> > +      val->ssa = rzalloc(b, struct vtn_ssa_value);
> > +      val->ssa->def = &atomic->dest.ssa;
> > +      val->ssa->type = type->type;
> > +   }
> >  
> >     nir_builder_instr_insert(&b->nb, &atomic->instr);
> >  }
> > @@ -2690,6 +2780,7 @@ vtn_handle_body_instruction(struct
> > vtn_builder *b, SpvOp opcode,
> >        break;
> >     }
> >  
> > +   case SpvOpAtomicLoad:
> >     case SpvOpAtomicExchange:
> >     case SpvOpAtomicCompareExchange:
> >     case SpvOpAtomicCompareExchangeWeak:
> > @@ -2714,6 +2805,17 @@ vtn_handle_body_instruction(struct
> > vtn_builder *b, SpvOp opcode,
> >        break;
> >     }
> >  
> > +   case SpvOpAtomicStore: {
> > +      struct vtn_value *pointer = vtn_untyped_value(b, w[1]);
> > +      if (pointer->value_type == vtn_value_type_image_pointer) {
> > +         vtn_handle_image(b, opcode, w, count);
> > +      } else {
> > +         assert(pointer->value_type ==
> > vtn_value_type_access_chain);
> > +         vtn_handle_ssbo_or_shared_atomic(b, opcode, w, count);
> > +      }
> > +      break;
> > +   }
> > +
> >     case SpvOpSNegate:
> >     case SpvOpFNegate:
> >     case SpvOpNot:
> > -- 
> > 2.9.3
> > 
> > _______________________________________________
> > mesa-dev mailing list
> > mesa-dev at lists.freedesktop.org
> > https://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list