<div dir="ltr"><br><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Dec 28, 2015 at 9:37 AM, Connor Abbott <span dir="ltr"><<a href="mailto:cwabbott0@gmail.com" target="_blank">cwabbott0@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 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>> 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>> wrote:<br>
>>>> On Tue, Dec 22, 2015 at 9:02 PM, Rob Clark <<a href="mailto:robdclark@gmail.com">robdclark@gmail.com</a>> wrote:<br>
>>>>> On Mon, Dec 21, 2015 at 1:48 PM, Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>> wrote:<br>
>>>>>><br>
>>>>>> I think two different concepts of ownership are getting conflated here:<br>
>>>>>> Right/responsibility to delete and right to modify.<br>
>>>>>><br>
>>>>>> The way I understand it, gallium, as it stands, gives neither to the driver.<br>
>>>>>> A back-end using NIR requires the right to modify but who deletes it doesn't<br>
>>>>>> ultimately matter.  I think it's dangerous to pass one of these 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 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 to<br>
>>>>> the driver.  If the st wants to hang on to a reference itself, it 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 follow<br>
>>>>> TGSI semantics), just decree that the driver always takes ownership of<br>
>>>>> the copy passed in, and if the st wants to hang on to a copy too, 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 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></div></div></blockquote><div><br></div><div>Just to be clear, your key-dependent lowering happens after all of your other lowering?  If this is the case, then I guarantee you that you're unique in this since i965 and vc4 need to at least run out-of-SSA afterwards.  To be honest, I completely forgot that a driver could use fully ssa NIR.<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">
>>><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>
</div></div>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>
<span class=""><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>
</span>"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>
<div class="HOEnZb"><div class="h5"><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 a copy.<br>
>>>>><br>
>>>>> This is how it is w/ TGSI, but I think with NIR we are free to make 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 currently doing<br>
>>>>>> (2) and changing it to (1) would be painful.  I think reference counting is<br>
>>>>>> more like an awkward option 1.5 than option 3.  Reference counting would<br>
>>>>>> mean that gallium passes a reference to the driver which it is expected to<br>
>>>>>> unref but may keep a second reference if it wants to keep the driver from<br>
>>>>>> modifying it.  Then the driver may or may not make a copy based on 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 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 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 gets<br>
>>>>>> passed in, it still has to under it to avoid a memory leak.  You can't have<br>
>>>>>> the driver take the reference because then, either it comes in with a<br>
>>>>>> recount of 0 and should have been deleted, or the "can I modify 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>
</div></div></blockquote></div><br></div></div>