<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Mon, Jul 2, 2018 at 11:10 AM, Kenneth Graunke <span dir="ltr"><<a href="mailto:kenneth@whitecape.org" target="_blank">kenneth@whitecape.org</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 Friday, June 29, 2018 5:13:52 PM PDT Jason Ekstrand wrote:<br>
> These are very similar to the related function in nir_lower_io except<br>
> that they don't handle per-vertex or packed things (that could be added,<br>
> in theory) and they take a more detailed size/align function pointer.<br>
> One day, we should consider switching nir_lower_io over to using the<br>
> more detailed size/align functions and then we could make it use these<br>
> helpers instead of having its own.<br>
> ---<br>
>  src/compiler/nir/nir_deref.c | 91 ++++++++++++++++++++++++++++++<wbr>++++++<br>
>  src/compiler/nir/nir_deref.h |  6 +++<br>
>  2 files changed, 97 insertions(+)<br>
> <br>
> diff --git a/src/compiler/nir/nir_deref.c b/src/compiler/nir/nir_deref.c<br>
> index 22ecde4ecca..94f91df5a0f 100644<br>
> --- a/src/compiler/nir/nir_deref.c<br>
> +++ b/src/compiler/nir/nir_deref.c<br>
> @@ -120,6 +120,97 @@ nir_deref_instr_has_indirect(<wbr>nir_deref_instr *instr)<br>
>     return false;<br>
>  }<br>
>  <br>
> +static unsigned<br>
> +type_get_array_stride(const struct glsl_type *elem_type,<br>
> +                      glsl_type_size_align_func size_align)<br>
> +{<br>
> +   unsigned elem_size, elem_align;<br>
> +   glsl_get_natural_size_align_<wbr>bytes(elem_type, &elem_size, &elem_align);<br>
> +   return ALIGN_POT(elem_size, elem_align);<br>
> +}<br>
> +<br>
> +static unsigned<br>
> +struct_type_get_field_offset(<wbr>const struct glsl_type *struct_type,<br>
> +                             glsl_type_size_align_func size_align,<br>
> +                             unsigned field_idx)<br>
> +{<br>
> +   assert(glsl_type_is_struct(<wbr>struct_type));<br>
> +   unsigned offset = 0;<br>
> +   for (unsigned i = 0; i <= field_idx; i++) {<br>
> +      unsigned elem_size, elem_align;<br>
> +      glsl_get_natural_size_align_<wbr>bytes(glsl_get_struct_field(<wbr>struct_type, i),<br>
> +                                        &elem_size, &elem_align);<br>
> +      offset = ALIGN_POT(offset, elem_align);<br>
> +      if (i < field_idx)<br>
> +         offset += elem_size;<br>
> +   }<br>
> +   return offset;<br>
> +}<br>
> +<br>
> +unsigned<br>
> +nir_deref_instr_get_const_<wbr>offset(nir_deref_instr *deref,<br>
> +                                 glsl_type_size_align_func size_align)<br>
> +{<br>
> +   nir_deref_path path;<br>
> +   nir_deref_path_init(&path, deref, NULL);<br>
> +<br>
> +   assert(path.path[0]->deref_<wbr>type == nir_deref_type_var);<br>
> +   nir_deref_instr **p = &path.path[1];<br>
> +<br>
> +   unsigned offset = 0;<br>
> +   for (; *p; p++) {<br>
<br>
</div></div>Personally, I'd just write<br>
<br>
   for (nir_deref_instr **p = &path.path[1]; *p; p++) {<br>
<br>
since you don't need it after the loop.<br><div><div class="h5"></div></div></blockquote><div><br></div><div>Good call.  Done.  The only reason I wrote it the way I did was because the code I copied it from did it that way.  I think there is a good reason there but not here.</div><div><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><div class="h5">
> +      if ((*p)->deref_type == nir_deref_type_array) {<br>
> +         offset += nir_src_as_const_value((*p)-><wbr>arr.index)->u32[0] *<br>
> +                   type_get_array_stride((*p)-><wbr>type, size_align);<br>
> +      } else if ((*p)->deref_type == nir_deref_type_struct) {<br>
> +         /* p starts at path[1], so this is safe */<br>
> +         nir_deref_instr *parent = *(p - 1);<br>
> +         offset += struct_type_get_field_offset(<wbr>parent->type, size_align,<br>
> +                                                (*p)->strct.index);<br>
> +      } else {<br>
> +         unreachable("Unsupported deref type");<br>
> +      }<br>
> +   }<br>
> +<br>
> +   nir_deref_path_finish(&path);<br>
> +<br>
> +   return offset;<br>
> +}<br>
> +<br>
> +nir_ssa_def *<br>
> +nir_build_deref_offset(nir_<wbr>builder *b, nir_deref_instr *deref,<br>
> +                       glsl_type_size_align_func size_align)<br>
> +{<br>
> +   nir_deref_path path;<br>
> +   nir_deref_path_init(&path, deref, NULL);<br>
> +<br>
> +   assert(path.path[0]->deref_<wbr>type == nir_deref_type_var);<br>
> +   nir_deref_instr **p = &path.path[1];<br>
> +<br>
> +   nir_ssa_def *offset = nir_imm_int(b, 0);<br>
> +   for (; *p; p++) {<br>
<br>
</div></div>Ditto here.<br>
<div class="HOEnZb"><div class="h5"><br>
> +      if ((*p)->deref_type == nir_deref_type_array) {<br>
> +         nir_ssa_def *index = nir_ssa_for_src(b, (*p)->arr.index, 1);<br>
> +         nir_ssa_def *stride =<br>
> +            nir_imm_int(b, type_get_array_stride((*p)-><wbr>type, size_align));<br>
> +         offset = nir_iadd(b, offset, nir_imul(b, index, stride));<br>
> +      } else if ((*p)->deref_type == nir_deref_type_struct) {<br>
> +         /* p starts at path[1], so this is safe */<br>
> +         nir_deref_instr *parent = *(p - 1);<br>
> +         unsigned field_offset =<br>
> +            struct_type_get_field_offset(<wbr>parent->type, size_align,<br>
> +                                         (*p)->strct.index);<br>
> +         nir_iadd(b, offset, nir_imm_int(b, field_offset));<br>
> +      } else {<br>
> +         unreachable("Unsupported deref type");<br>
> +      }<br>
> +   }<br>
> +<br>
> +   nir_deref_path_finish(&path);<br>
> +<br>
> +   return offset;<br>
> +}<br>
> +<br>
>  bool<br>
>  nir_remove_dead_derefs_impl(<wbr>nir_function_impl *impl)<br>
>  {<br>
> diff --git a/src/compiler/nir/nir_deref.h b/src/compiler/nir/nir_deref.h<br>
> index 0980bae7215..6f4141aaf82 100644<br>
> --- a/src/compiler/nir/nir_deref.h<br>
> +++ b/src/compiler/nir/nir_deref.h<br>
> @@ -48,6 +48,12 @@ void nir_deref_path_init(nir_deref_<wbr>path *path,<br>
>                           nir_deref_instr *deref, void *mem_ctx);<br>
>  void nir_deref_path_finish(nir_<wbr>deref_path *path);<br>
>  <br>
> +unsigned nir_deref_instr_get_const_<wbr>offset(nir_deref_instr *deref,<br>
> +                                          glsl_type_size_align_func size_align);<br>
> +<br>
> +nir_ssa_def *nir_build_deref_offset(nir_<wbr>builder *b, nir_deref_instr *deref,<br>
> +                                    glsl_type_size_align_func size_align);<br>
> +<br>
>  #ifdef __cplusplus<br>
>  } /* extern "C" */<br>
>  #endif<br>
> <br>
<br>
</div></div></blockquote></div><br></div></div>