<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Fri, Jul 14, 2017 at 2:57 AM, Iago Toral <span dir="ltr"><<a href="mailto:itoral@igalia.com" target="_blank">itoral@igalia.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">On Thu, 2017-07-13 at 12:41 -0700, Jason Ekstrand wrote:<br>
> ---<br>
>  src/compiler/spirv/nir_spirv.<wbr>h     |  1 +<br>
>  src/compiler/spirv/spirv_to_<wbr>nir.c  | 42<br>
> ++++++++++++++++++++++++++++++<wbr>++---<br>
>  src/compiler/spirv/vtn_cfg.c <wbr>      |  5 +++--<br>
>  src/compiler/spirv/vtn_<wbr>private.h   | 23 +++++++++++++++++--<br>
>  src/compiler/spirv/vtn_<wbr>variables.c | 45<br>
> ++++++++++++++++++++++++++++++<wbr>+++++---<br>
>  5 files changed, 106 insertions(+), 10 deletions(-)<br>
><br>
> diff --git a/src/compiler/spirv/nir_<wbr>spirv.h<br>
> b/src/compiler/spirv/nir_<wbr>spirv.h<br>
> index 7f16866..83577fb 100644<br>
> --- a/src/compiler/spirv/nir_<wbr>spirv.h<br>
> +++ b/src/compiler/spirv/nir_<wbr>spirv.h<br>
> @@ -51,6 +51,7 @@ struct nir_spirv_supported_extensions {<br>
>     bool image_write_without_format;<br>
>     bool int64;<br>
>     bool multiview;<br>
> +   bool variable_pointers;<br>
>  };<br>
>  <br>
>  nir_function *spirv_to_nir(const uint32_t *words, size_t word_count,<br>
> diff --git a/src/compiler/spirv/spirv_to_<wbr>nir.c<br>
> b/src/compiler/spirv/spirv_to_<wbr>nir.c<br>
> index 6e35f83..e60c9f7 100644<br>
> --- a/src/compiler/spirv/spirv_to_<wbr>nir.c<br>
> +++ b/src/compiler/spirv/spirv_to_<wbr>nir.c<br>
> @@ -185,6 +185,13 @@ vtn_ssa_value(struct vtn_builder *b, uint32_t<br>
> value_id)<br>
>     case vtn_value_type_ssa:<br>
>        return val->ssa;<br>
>  <br>
> +   case vtn_value_type_pointer:<br>
> +      assert(val->pointer-><wbr>ptr_type && val->pointer->ptr_type-<br>
> >type);<br>
> +      struct vtn_ssa_value *ssa =<br>
> +         vtn_create_ssa_<wbr>value(b, val->pointer->ptr_type->type);<br>
> +      ssa->def = vtn_pointer_to_ssa(b, val->pointer);<br>
> +      return ssa;<br>
> +<br>
>     default:<br>
>        unreachable("Invalid type for an SSA value");<br>
>     }<br>
> @@ -861,9 +868,20 @@ vtn_handle_type(struct vtn_builder *b, SpvOp<br>
> opcode,<br>
>           vtn_value(b, w[3], vtn_value_type_type)->type;<br>
>  <br>
>        val->type->base_type = vtn_base_type_pointer;<br>
> -      val->type->type = NULL;<br>
<br>
</div></div>Right, we use rzalloc for val->type so this was redundant.<br>
<span class=""><br>
>        val->type->storage_<wbr>class = storage_class;<br>
>        val->type->deref = deref_type;<br>
> +<br>
> +      struct vtn_type *without_array = deref_type;<br>
> +      while (without_array->base_type == vtn_base_type_array)<br>
> +         without_array = without_array->array_element;<br>
><br>
<br>
</span>What's the purpose of this loop? 'without_array' isn't used for<br>
anything here...<span class=""><br></span></blockquote><div><br></div><div>None, aparently.  I had it in there for some reason in an older version but that reason has aparently been lost.  I'll drop it.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
> +      if (storage_class == SpvStorageClassUniform ||<br>
> +          storage_class == SpvStorageClassStorageBuffer) {<br>
> +         /* These can actually be stored to nir_variables and used<br>
> as SSA<br>
> +          * values so they need a real glsl_type.<br>
> +          */<br>
> +         val->type->type = glsl_vector_type(GLSL_TYPE_<wbr>UINT, 2);<br>
> +      }<br>
>        break;<br>
>     }<br>
<br>
</span>(...)<br>
<span class=""><br>
> static inline struct vtn_value *<br>
>  vtn_push_value(struct vtn_builder *b, uint32_t value_id,<br>
>                 enum vtn_value_type value_type)<br>
> @@ -517,8 +530,14 @@ static inline struct vtn_value *<br>
>  vtn_push_ssa(struct vtn_builder *b, uint32_t value_id,<br>
>               struct vtn_type *type, struct vtn_ssa_value *ssa)<br>
>  {<br>
> -   struct vtn_value *val = vtn_push_value(b, value_id,<br>
> vtn_value_type_ssa);<br>
> -   val->ssa = ssa;<br>
> +   struct vtn_value *val;<br>
> +   if (type->base_type == vtn_base_type_pointer) {<br>
> +      val = vtn_push_value(b, value_id, vtn_value_type_pointer);<br>
> +      val->pointer = vtn_pointer_from_ssa(b, ssa->def, type);<br>
> +   } else {<br>
> +      val = vtn_push_value(b, value_id, vtn_value_type_ssa);<br>
> +      val->ssa = ssa;<br>
> +   }<br>
<br>
</span>So you start using the 'type' parameter here... I guess it is okay if<br>
it was added in the previous patch then.<br>
<div><div class="h5"><br>
>     return val;<br>
>  }<br>
>  <br>
> diff --git a/src/compiler/spirv/vtn_<wbr>variables.c<br>
> b/src/compiler/spirv/vtn_<wbr>variables.c<br>
> index a9e2dbf..47f111b 100644<br>
> --- a/src/compiler/spirv/vtn_<wbr>variables.c<br>
> +++ b/src/compiler/spirv/vtn_<wbr>variables.c<br>
> @@ -223,8 +223,7 @@ vtn_pointer_dereference(struct vtn_builder *b,<br>
>                          <wbr>struct vtn_pointer *base,<br>
>                          <wbr>struct vtn_access_chain *deref_chain)<br>
>  {<br>
> -   if (base->mode == vtn_variable_mode_ubo ||<br>
> -       base->mode == vtn_variable_mode_ssbo) {<br>
> +   if (vtn_pointer_uses_ssa_offset(<wbr>base)) {<br>
>        return vtn_ssa_offset_pointer_<wbr>dereference(b, base,<br>
> deref_chain);<br>
>     } else {<br>
>        return vtn_access_chain_pointer_<wbr>dereference(b, base,<br>
> deref_chain);<br>
> @@ -1478,6 +1477,47 @@ vtn_storage_class_to_mode(<wbr>SpvStorageClass<br>
> class,<br>
>     return mode;<br>
>  }<br>
>  <br>
> +nir_ssa_def *<br>
> +vtn_pointer_to_ssa(struct vtn_builder *b, struct vtn_pointer *ptr)<br>
> +{<br>
> +   if (ptr->offset && ptr->block_index) {<br>
> +      return nir_vec2(&b->nb, ptr->block_index, ptr->offset);<br>
> +   } else {<br>
> +      /* If we don't have an offset or block index, then we must be<br>
> a pointer<br>
> +       * to the variable itself.<br>
> +       */<br>
> +      assert(!ptr->offset && !ptr->block_index);<br>
> +<br>
> +      /* We can't handle a pointer to an array of descriptors<br>
> because we have<br>
> +       * no way of knowing later on that we need to add to update<br>
> the block<br>
> +       * index when dereferencing.<br>
> +       */<br>
> +      assert(ptr->var && ptr->var->type->base_type ==<br>
> vtn_base_type_struct);<br>
> +<br>
> +      return nir_vec2(&b->nb, vtn_variable_resource_index(b, ptr-<br>
> >var, NULL),<br>
> +                             <wbr> nir_imm_int(&b->nb, 0));<br>
> +   }<br>
> +}<br>
> +<br>
> +struct vtn_pointer *<br>
> +vtn_pointer_from_ssa(struct vtn_builder *b, nir_ssa_def *ssa,<br>
> +                     struct vtn_type *ptr_type)<br>
> +{<br>
> +   assert(ssa->num_components == 2 && ssa->bit_size == 32);<br>
> +   assert(ptr_type->base_type == vtn_base_type_pointer);<br>
> +   assert(ptr_type->deref-><wbr>base_type != vtn_base_type_pointer);<br>
> +<br>
> +   struct vtn_pointer *ptr = rzalloc(b, struct vtn_pointer);<br>
> +   ptr->mode = vtn_storage_class_to_mode(ptr_<wbr>type->storage_class,<br>
> +                             <wbr>            ptr_type, NULL);<br>
> +   ptr->type = ptr_type->deref;<br>
> +   ptr->ptr_type = ptr_type;<br>
> +   ptr->block_index = nir_channel(&b->nb, ssa, 0);<br>
> +   ptr->offset = nir_channel(&b->nb, ssa, 1);<br>
><br>
<br>
</div></div>So here we always create (block,offset) pointers, which I guess means<br>
that we can't call this with ssa values that represent pointers to<br>
variables</blockquote><div><br></div><div>Correct.  Variable pointers only applies to SSBOs.  (Our implementation also works for UBOs but I don't think the spec requires that.)<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"> (the else branch in vtn_pointer_to_ssa)... is that checked<br>
anywhere? It doesn't look like vtn_push_ssa() check anything, so I<br>
wonder if there is a chance that this can happen.<br><div class="HOEnZb"><div class="h5"></div></div></blockquote><div><br></div><div>Hrm... Maybe not?  I'm happy to add some type checks.<br><br></div><div>--Jason<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">
> +   return ptr;<br>
> +}<br>
> +<br>
>  static bool<br>
>  is_per_vertex_inout(const struct vtn_variable *var, gl_shader_stage<br>
> stage)<br>
>  {<br>
> @@ -1503,7 +1543,6 @@ vtn_create_variable(struct vtn_builder *b,<br>
> struct vtn_value *val,<br>
>  {<br>
>     assert(ptr_type->base_type == vtn_base_type_pointer);<br>
>     struct vtn_type *type = ptr_type->deref;<br>
> -   assert(type->base_type != vtn_base_type_pointer);<br>
>  <br>
>     struct vtn_type *without_array = type;<br>
>     while(glsl_type_is_array(<wbr>without_array->type))<br>
</div></div></blockquote></div><br></div></div>