<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Tue, Apr 10, 2018 at 8:17 AM, Rob Clark <span dir="ltr"><<a href="mailto:robdclark@gmail.com" target="_blank">robdclark@gmail.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 Tue, Apr 10, 2018 at 11:04 AM, Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>> wrote:<br>
> On Tue, Apr 10, 2018 at 6:20 AM, Rob Clark <<a href="mailto:robdclark@gmail.com">robdclark@gmail.com</a>> wrote:<br>
>><br>
>> On Mon, Apr 9, 2018 at 10:52 PM, Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>><br>
>> wrote:<br>
>> > + A bunch of potentially interested parties.<br>
>> ><br>
>> > On Mon, Apr 9, 2018 at 4:25 PM, Caio Marcelo de Oliveira Filho<br>
>> > <<a href="mailto:caio.oliveira@intel.com">caio.oliveira@intel.com</a>> wrote:<br>
>> >><br>
>> >> Hi,<br>
>> >><br>
>> >> >  typedef struct {<br>
>> >> > -   nir_parameter_type param_type;<br>
>> >> > -   const struct glsl_type *type;<br>
>> >> > +   uint8_t num_components;<br>
>> >> > +   uint8_t bit_size;<br>
>> >> >  } nir_parameter;<br>
>> >><br>
>> >> (...)<br>
>> >><br>
>> >> > @@ -683,18 +692,12 @@ validate_tex_instr(nir_tex_<wbr>instr *instr,<br>
>> >> > validate_state *state)<br>
>> >> >  static void<br>
>> >> >  validate_call_instr(nir_call_<wbr>instr *instr, validate_state *state)<br>
>> >> >  {<br>
>> >> > -   if (instr->return_deref == NULL) {<br>
>> >> > -      validate_assert(state,<br>
>> >> > glsl_type_is_void(instr-><wbr>callee->return_type));<br>
>> >> > -   } else {<br>
>> >> > -      validate_assert(state, instr->return_deref->deref.<wbr>type ==<br>
>> >> > instr->callee->return_type);<br>
>> >> > -      validate_deref_var(instr, instr->return_deref, state);<br>
>> >> > -   }<br>
>> >> > -<br>
>> >> >     validate_assert(state, instr->num_params ==<br>
>> >> > instr->callee->num_params);<br>
>> >> ><br>
>> >> >     for (unsigned i = 0; i < instr->num_params; i++) {<br>
>> >> > -      validate_assert(state, instr->callee->params[i].type ==<br>
>> >> > instr->params[i]->deref.type);<br>
>> >> > -      validate_deref_var(instr, instr->params[i], state);<br>
>> >> > +      validate_src(&instr->params[i]<wbr>, state,<br>
>> >> > +                   instr->callee->params[i].bit_<wbr>size,<br>
>> >> > +                   instr->callee->params[i].num_<wbr>components);<br>
>> >> >     }<br>
>> >> >  }<br>
>> >><br>
>> >> Question: I might be misreading, but it seems like we are losing the<br>
>> >> type information for functions. Isn't that something worth keeping,<br>
>> >> maybe in some other way, e.g. load_param specifying the expected type?<br>
>> ><br>
>> ><br>
>> > That's a very good question!  To be honest, I'm not sure what the answer<br>
>> > is.<br>
>> > At the moment, the type information is fairly useless for most of what<br>
>> > we<br>
>> > use functions for.  Really, all we need is something that NIR can<br>
>> > inline.<br>
>> > As it is, we're not really preserving the types from SPIR-V because of<br>
>> > the<br>
>> > gymnastics we're doing to handle pointers.<br>
>> ><br>
>> > If we did want to preserve types, we'd need to have more detailed type<br>
>> > information.  In particular, we'd need to be able to provide pointer<br>
>> > types<br>
>> > and maybe combined image-sampler types.  And along with those pointer<br>
>> > types,<br>
>> > we'd need to somehow express those pointer's storage requirements.<br>
>> ><br>
>> > The philosophy behind this commit is that, if we don't have a good match<br>
>> > to<br>
>> > SPIR-V anyway, we might as well just chuck that information and do<br>
>> > whatever<br>
>> > makes our lives the easiest.  My philosophy here may be flawed and I'm<br>
>> > happy<br>
>> > to hear arguments in favor of keeping the information.  The best<br>
>> > argument I<br>
>> > can come up with for keeping the information is if we find ourselves<br>
>> > wanting<br>
>> > to do some sort of linking in the future where we have to match<br>
>> > functions by<br>
>> > both name and type.  If we want to do that, however, we'll need all the<br>
>> > SPIR-V type information.<br>
>> ><br>
>><br>
>> We do end up wanting the type information for cl kernels.  This is<br>
>> maybe a slightly different case from calls within shader code (ie.<br>
>> when both caller and callee are in shader).<br>
><br>
><br>
> Yes, I think it is.  Question: Is there a distinction in CL between<br>
> functions which are entrypoints callable from the API and functions which<br>
> are helpers?  i.e. Can you call an entrypoint as a helper?<br>
><br>
<br>
</div></div>There is the __kernel annotation.  And you know the entry point name<br>
when compiling.  However I'm not sure anything prevents one entry<br>
point from calling another.<br></blockquote><div><br></div><div>That would be worth investigating.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
I'm not sure we want the calling convention to be the same internally<br>
as for kernel entry points so in that case, if we aren't inlining<br>
everything, we might end up generating two versions of a function (or<br>
possibly a shim.. or possibly between the two based on size.. or??)<span class=""><br></span></blockquote><br></div><div class="gmail_quote">Having a shim seems like a reasonable plan.<br></div><div class="gmail_quote"><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
>><br>
>> Although I'd kinda like<br>
>> to think that we don't need to make vtn aware of this distinction.<br>
><br>
><br>
> Someone has to be aware of it. :-)  There are lots of places in spirv_to_nir<br>
> were we take the SPIR-V and do something slightly different with it than the<br>
> obvious translation.  Also, using function parameters for this is a<br>
> significant anachronism because no other shader I/O in NIR has ever worked<br>
> that way.<br>
><br>
>><br>
>> So just to throw out an idea.  What if vtn just used load_deref for<br>
>> everything, and in the case of fxn params it just points to a local<br>
>> var with type nir_var_param?  (Or something roughly like that.)  Then<br>
>> lower_io lowers this to load_param.<br>
><br>
><br>
> That's kind-of what the original thing did.  However, for SPIR-V helper<br>
> functions we have to be able to pass through pointers, SSA values with<br>
> arbitrary type, and image/sampler pointers.  SSA values can be handled by<br>
> just making a variable and storing them to it.  Pointers are tricky because<br>
> they're not really copy-in/out.  For images, samplers, and pointers, we have<br>
> a pile of "try to patch up the deref chain" code in nir_inline_functions<br>
> that's rather tricky.  The moral of the story is that "just use variables"<br>
> is not nearly as obvious of a choice as it looks.<br>
<br>
</span>So, I'm considering just adding nir_variable ptr back to<br>
nir_parameter.  That would be rather easy, and gives something that<br>
some lowering pass could fixup data.driver_loc with parameter<br>
position.  That would be rather easy for driver backends:<br>
<br>
  param_loc = fxn->params[param_idx]->var-><wbr>data.driver_loc<br></blockquote></div><br></div><div class="gmail_extra">Why can't you just add a mode nir_var_kernel_param and keep a running uint32_t offset in the builder.  When you process an OpParameter in an entrypoint, create a nir_var_kernel_param variable and set var->data.location = offset and add the size of the param to offset.  Then the OpParameter can return an access chain to the newly created interface variable.  I fail to see why load_param is needed at all here.<br></div></div>