<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Dec 28, 2015 at 10:33 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 Mon, Dec 28, 2015 at 1:20 PM, Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>> wrote:<br>
><br>
><br>
> On Mon, Dec 28, 2015 at 9:37 AM, Connor Abbott <<a href="mailto:cwabbott0@gmail.com">cwabbott0@gmail.com</a>> wrote:<br>
>><br>
>> On Mon, Dec 28, 2015 at 10:13 AM, Rob Clark <<a href="mailto:robdclark@gmail.com">robdclark@gmail.com</a>> wrote:<br>
>> > On Tue, Dec 22, 2015 at 10:11 PM, Connor Abbott <<a href="mailto:cwabbott0@gmail.com">cwabbott0@gmail.com</a>><br>
>> > wrote:<br>
>> >> On Tue, Dec 22, 2015 at 9:55 PM, Rob Clark <<a href="mailto:robdclark@gmail.com">robdclark@gmail.com</a>> wrote:<br>
>> >>> On Tue, Dec 22, 2015 at 9:47 PM, Connor Abbott <<a href="mailto:cwabbott0@gmail.com">cwabbott0@gmail.com</a>><br>
>> >>> wrote:<br>
>> >>>> On Tue, Dec 22, 2015 at 9:02 PM, Rob Clark <<a href="mailto:robdclark@gmail.com">robdclark@gmail.com</a>><br>
>> >>>> wrote:<br>
>> >>>>> On Mon, Dec 21, 2015 at 1:48 PM, Jason Ekstrand<br>
>> >>>>> <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>> wrote:<br>
>> >>>>>><br>
>> >>>>>> I think two different concepts of ownership are getting conflated<br>
>> >>>>>> here:<br>
>> >>>>>> Right/responsibility to delete and right to modify.<br>
>> >>>>>><br>
>> >>>>>> The way I understand it, gallium, as it stands, gives neither to<br>
>> >>>>>> the driver.<br>
>> >>>>>> A back-end using NIR requires the right to modify but who deletes<br>
>> >>>>>> it doesn't<br>
>> >>>>>> ultimately matter.  I think it's dangerous to pass one of these<br>
>> >>>>>> rights to<br>
>> >>>>>> the driver and not the other but we need to think about both.<br>
>> >>>>><br>
>> >>>>> yeah, uneasy about driver modifying the IR if the state tracker is<br>
>> >>>>> still going to potentially spin off variants of the IR.. that sounds<br>
>> >>>>> like madness.<br>
>> >>>>><br>
>> >>>>> The refcnt'ing I proposed does deal w/ right to modify vs delete via<br>
>> >>>>> nir_shader(_is)_mutable() which returns something that is guaranteed<br>
>> >>>>> to be safe to modify (ie. has only a single reference)<br>
>> >>>>><br>
>> >>>>>> What I'm trying to say is that we have two options here:<br>
>> >>>>>><br>
>> >>>>>> 1) gallium passes IR to the back-end that it is free to modify and<br>
>> >>>>>> is<br>
>> >>>>>> required to delete when it's done.<br>
>> >>>>><br>
>> >>>>> with refcnt'ing, s/delete/unref/<br>
>> >>>>><br>
>> >>>>> The idea is, the st transfers ownership of the reference it passes<br>
>> >>>>> to<br>
>> >>>>> the driver.  If the st wants to hang on to a reference itself, it<br>
>> >>>>> must<br>
>> >>>>> increment the refcnt before passing to the driver (backend).<br>
>> >>>>><br>
>> >>>>> Without refcnt'ing, I suppose we could (since we don't have to<br>
>> >>>>> follow<br>
>> >>>>> TGSI semantics), just decree that the driver always takes ownership<br>
>> >>>>> of<br>
>> >>>>> the copy passed in, and if the st wants to hang on to a copy too,<br>
>> >>>>> then<br>
>> >>>>> it must clone.  I suppose this would work well enough for<br>
>> >>>>> freedreno/vc4, which both end up generating variants later.  It does<br>
>> >>>>> force an extra clone for drivers that immediately translate into<br>
>> >>>>> their<br>
>> >>>>> own backend IR and don't need to keep the NIR around, for example.<br>
>> >>>>> Maybe that is not worth caring about (since at this point it is<br>
>> >>>>> hypothetical).<br>
>> >>>><br>
>> >>>> While always cloning does have this disadvantage, I don't think it's<br>
>> >>>> really relevant here. Even if the driver throws away the NIR<br>
>> >>>> immediately after consuming it, almost invariably it's going to want<br>
>> >>>> to modify  it. The generic NIR passed in by the state tracker (other<br>
>> >>>> IR -> NIR + some optimizations) is almost never going to be the same<br>
>> >>>> as the NIR after going through driver-specific lowering passes, which<br>
>> >>>> means that drivers are never going to want a read-only version of the<br>
>> >>>> IR. In light of that, I think making the driver own the IR passed in<br>
>> >>>> seems like the most sensible thing.<br>
>> >>><br>
>> >>> well, unless the driver is already doing it's own lowering in it's own<br>
>> >>> native IR..<br>
>> >><br>
>> >> Well, if you're not doing any lowering in NIR, then you aren't really<br>
>> >> taking any advantage of it. I can't see a plausible scenario where all<br>
>> >> the lowering is done in the driver's own IR -- and as soon as you do<br>
>> >> anything in NIR, you need the driver-owns-IR semantics.<br>
>> ><br>
>> > When it comes to shader variants, I have a mix, with some things<br>
>> > lowered in nir and others just handled in backend..<br>
>> ><br>
>> > The re-work / cleanup that I have had on a branch for a while now<br>
>> > (since it is currently blocked on refcnt'ing) does a first round of<br>
>> > variant-key independent NIR lowering/opt passes.  And then at draw<br>
>> > time, if the variant key has anything that is lowered in nir, I do a<br>
>> > second round.<br>
><br>
><br>
> Just to be clear, your key-dependent lowering happens after all of your<br>
> other lowering?  If this is the case, then I guarantee you that you're<br>
> unique in this since i965 and vc4 need to at least run out-of-SSA<br>
> afterwards.  To be honest, I completely forgot that a driver could use fully<br>
> ssa NIR.<br>
<br>
</div></div>It is a mix.. I do texcoord saturate, clip-plane, and 2-sided color<br>
lowering in NIR.  But flat-shading, binning-pass, and half vs full<br>
precision color output in ir3.<br>
<br>
I do as much lowering in NIR as I can, in an effort to do as much as<br>
possible at compile time, vs draw time.  I do the first round of<br>
lowering/opt w/ null shader key, which is enough for the common cases.<br>
<br>
Pretty much independent, I suppose, of whether I came out of SSA or<br>
not first.  Although binning-pass variant and the instruction<br>
scheduling I do are easier in SSA.<br>
<br>
Somewhat unrelated, but I may end up converting array access to<br>
registers, but leave everything else in SSA, so I can benefit from<br>
converting multi-dimensional offsets into a single offset..  this is<br>
still one open issue w/ gallium glsl_to_nir.. right now I have a<br>
hacked up version of nir_lower_io that converts global/local<br>
load/store_var's into load/store_var2 which take an offset as a src<br>
(like load_input/store_output) instead of deref chain.. not sure yet<br>
whether this will be the permanent solution, but at least it fixes a<br>
huge heap of variable-indexing piglits and lets me continue w/<br>
implementing lowering passes for everything else that was previously<br>
done in glsl->tgsi or tgsi->tgsi passes.<br></blockquote><div><br></div><div>If you do this, you'll be back to always needing a mutable copy.  Most lowering and optimization passes die the moment they see a register.  You'll either have to go fix a bunch of stuff up to no-op properly or run vars_to_regs after doing your NIR lowering but before going into your backend IR.  This means that your "gold copy" still has variables and you always need to lower them to registers before you go into the backend.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
BR,<br>
-R<br>
<div class="HOEnZb"><div class="h5"><br>
>><br>
>> >>><br>
>> >>> Maybe it is too much of a hypothetical.. I still think refcnt'ing<br>
>> >>> gives some nice flexibility to deal with various scenarios, and having<br>
>> >>> to call nir_shader_unref() isn't so much of a burden.<br>
>> >><br>
>> >> Still, I can't see how this flexibility is at all useful, and it seems<br>
>> >> like overkill since the driver will always want a mutable version of<br>
>> >> the IR anyways.<br>
>> ><br>
>> > Well, due to the structure I mentioned above, at draw time when I need<br>
>> > to generate a variant with nothing lowered in NIR, I simply incr the<br>
>> > refcnt on the IR which has already gone through first round of NIR<br>
>> > passes, and pass that in to my back end compiler.  At the end, once<br>
>> > the shader binary is generated, I can unconditionally unref the<br>
>> > nir_shader without having to care.<br>
>> ><br>
>> > Without refcnt'ing I'd either have to generate a pointless clone or<br>
>> > keep track that the nir_shader should not actually be free'd.  Not<br>
>> > impossible, just a bit more ugly.<br>
>><br>
>> Assuming you do all your variant management in your driver's IR, then<br>
>> you don't need to do anything. If you do some variant management in<br>
>> NIR, then in the function where you do the NIR-based lowering you can<br>
>> check if you need to do any lowering based on the shader key, clone<br>
>> first, and give the NIR->ir3 function the cloned IR and then free it.<br>
>> It might be a "bit more ugly," but it's really not that much different<br>
>> from the refcounting, and when the extra shader gets created/freed is<br>
>> made explicit.<br>
>><br>
>> ><br>
>> > (The gallium glsl_to_nir stuff is also currently using refcnt'ing,<br>
>> > although at least for freedreno/ir3 it isn't strictly needed.. I could<br>
>> > just unconditionally clone in the state tracker.  That said, I'm still<br>
>> > of the opinion that refcnt'ing could be useful to some other driver<br>
>> > someday)<br>
>><br>
>> "It could be useful to some driver someday" isn't a good argument for<br>
>> adding stuff today. We've already had enough examples of things in NIR<br>
>> that we added because we thought it was useful, but turned out not to<br>
>> be.<br>
>><br>
>> ><br>
>> > BR,<br>
>> > -R<br>
>> ><br>
>> >>><br>
>> >>> BR,<br>
>> >>> -R<br>
>> >>><br>
>> >>>>><br>
>> >>>>> (I guess nouveau is the one driver, that if it ever consumed NIR,<br>
>> >>>>> would translate immediately into it's own backend IR?)<br>
>> >>>>><br>
>> >>>>>> 2) gallium passes read-only IR to the back-end and it always makes<br>
>> >>>>>> a copy.<br>
>> >>>>><br>
>> >>>>> This is how it is w/ TGSI, but I think with NIR we are free to make<br>
>> >>>>> a<br>
>> >>>>> clean break.  And we *definitely* want to avoid<br>
>> >>>>> the-driver-always-copies semantics..<br>
>> >>>>><br>
>> >>>>>> It sounds like, from what Marek is saying, that gallium is<br>
>> >>>>>> currently doing<br>
>> >>>>>> (2) and changing it to (1) would be painful.  I think reference<br>
>> >>>>>> counting is<br>
>> >>>>>> more like an awkward option 1.5 than option 3.  Reference counting<br>
>> >>>>>> would<br>
>> >>>>>> mean that gallium passes a reference to the driver which it is<br>
>> >>>>>> expected to<br>
>> >>>>>> unref but may keep a second reference if it wants to keep the<br>
>> >>>>>> driver from<br>
>> >>>>>> modifying it.  Then the driver may or may not make a copy based on<br>
>> >>>>>> the<br>
>> >>>>>> number of references.  Why don't we just make it explicit and add a<br>
>> >>>>>> read-only bit and call it a day.<br>
>> >>>>>><br>
>> >>>>>> One of the reasons I don't like passing a reference is that it<br>
>> >>>>>> effectively<br>
>> >>>>>> puts allocation and freeing in different components of the driver.<br>
>> >>>>><br>
>> >>>>> With refcnt'ing you should talk in terms of ref/unref rather than<br>
>> >>>>> allocate/free.. imho.  Although maybe that is what you meant.  (In<br>
>> >>>>> which case, yes, that was my idea, that passing in to driver<br>
>> >>>>> transfers<br>
>> >>>>> ownership of the passed reference.)<br>
>> >>>>><br>
>> >>>>>> This<br>
>> >>>>>> means that if and driver doesn't care at all about the shader that<br>
>> >>>>>> gets<br>
>> >>>>>> passed in, it still has to under it to avoid a memory leak.  You<br>
>> >>>>>> can't have<br>
>> >>>>>> the driver take the reference because then, either it comes in with<br>
>> >>>>>> a<br>
>> >>>>>> recount of 0 and should have been deleted, or the "can I modify<br>
>> >>>>>> this" check<br>
>> >>>>>> becomes "recount <= 2" which makes no sense.<br>
>> >>>>><br>
>> >>>>> hmm, no, if ownership of the reference is transferred to the driver,<br>
>> >>>>> then it becomes "refcount == 1" (and refcount == 0 should be an<br>
>> >>>>> assert, because something has gone horribly wrong)<br>
>> >>>>><br>
>> >>>>> BR,<br>
>> >>>>> -R<br>
><br>
><br>
</div></div></blockquote></div><br></div></div>