<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Mon, May 22, 2017 at 6:48 PM, Jason Ekstrand <span dir="ltr"><<a href="mailto:jason@jlekstrand.net" target="_blank">jason@jlekstrand.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr"><div><div class="h5"><div class="gmail_extra"><div class="gmail_quote">On Mon, May 22, 2017 at 6:45 PM, 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="m_-4887686186637721807HOEnZb"><div class="m_-4887686186637721807h5">On Mon, May 22, 2017 at 9:33 PM, Rob Clark <<a href="mailto:robdclark@gmail.com" target="_blank">robdclark@gmail.com</a>> wrote:<br>
> On Mon, May 22, 2017 at 9:15 PM, Timothy Arceri <<a href="mailto:tarceri@itsqueeze.com" target="_blank">tarceri@itsqueeze.com</a>> wrote:<br>
>> On 23/05/17 10:44, Marek Olšák wrote:<br>
>>><br>
>>> On Tue, May 23, 2017 at 12:07 AM, Timothy Arceri <<a href="mailto:tarceri@itsqueeze.com" target="_blank">tarceri@itsqueeze.com</a>><br>
>>> wrote:<br>
>>>><br>
>>>> On 23/05/17 05:02, Marek Olšák wrote:<br>
>>>>><br>
>>>>><br>
>>>>> On Sun, May 21, 2017 at 12:48 PM, Nicolai Hähnle <<a href="mailto:nhaehnle@gmail.com" target="_blank">nhaehnle@gmail.com</a>><br>
>>>>> wrote:<br>
>>>>>><br>
>>>>>><br>
>>>>>> Hi all,<br>
>>>>>><br>
>>>>>> I've been looking into ARB_gl_spirv for radeonsi. I don't fancy<br>
>>>>>> re-inventing<br>
>>>>>> the ~8k LOC of src/compiler/spirv, and there's already a perfectly fine<br>
>>>>>> SPIR-V -> NIR -> LLVM compiler pipeline in radv, so I looked into<br>
>>>>>> re-using<br>
>>>>>> that.<br>
>>>>>><br>
>>>>>> It's not entirely straightforward because radeonsi and radv use<br>
>>>>>> different<br>
>>>>>> "ABIs" for their shaders, i.e. prolog/epilog shader parts, different<br>
>>>>>> user<br>
>>>>>> SGPR allocations, descriptor loads work differently (obviously), and so<br>
>>>>>> on.<br>
>>>>>><br>
>>>>>> Still, it's possible to separate the ABI from the meat of the NIR -><br>
>>>>>> LLVM<br>
>>>>>> translation. So here goes...<br>
>>>>>><br>
>>>>>><br>
>>>>>> The Step-by-Step Plan<br>
>>>>>> =====================<br>
>>>>>><br>
>>>>>> 1. Add an optional GLSL-to-NIR path (controlled by R600_DEBUG=nir) for<br>
>>>>>> very<br>
>>>>>> simple VS-PS pipelines.<br>
>>>>>><br>
>>>>>> 2. Add GL_ARB_gl_spirv support to Mesa and test it on simple VS-PS<br>
>>>>>> pipelines.<br>
>>>>>><br>
>>>>>> 3. Fill in all the rest:<br>
>>>>>> 3a. GL 4.x shader extensions (SSBOs, images, atomics, ...)<br>
>>>>>> 3b. Geometry and tessellation shaders<br>
>>>>>> 3c. Compute shaders<br>
>>>>>> 3d. Tests<br>
>>>>>><br>
>>>>>> I've started with step 1 and got basic GLSL 1.30-level vertex shaders<br>
>>>>>> working via NIR. The code is here:<br>
>>>>>> <a href="https://cgit.freedesktop.org/~nh/mesa/log/?h=nir" rel="noreferrer" target="_blank">https://cgit.freedesktop.org/~<wbr>nh/mesa/log/?h=nir</a><br>
>>>>>><br>
>>>>>> The basic approach is to introduce `struct ac_shader_abi' to capture<br>
>>>>>> the<br>
>>>>>> differences between radeonsi and radv. In the end, the entry point for<br>
>>>>>> NIR<br>
>>>>>> -> LLVM translation will simply be:<br>
>>>>>><br>
>>>>>>      void ac_nir_translate(struct ac_llvm_context *ac,<br>
>>>>>>                            struct ac_shader_abi *abi,<br>
>>>>>>                            struct nir_shader *nir);<br>
>>>>>><br>
>>>>>> Setting up the LLVM function with its parameters is still considered<br>
>>>>>> part<br>
>>>>>> of<br>
>>>>>> the driver.<br>
>>>>><br>
>>>>><br>
>>>>><br>
>>>>> This sounds good.<br>
>>>>><br>
>>>>>><br>
>>>>>><br>
>>>>>> Questions<br>
>>>>>> =========<br>
>>>>>><br>
>>>>>> 1. How do we get good test coverage?<br>
>>>>>> ------------------------------<wbr>------<br>
>>>>>> A natural candidate would be to add a SPIR-V execution mode for the<br>
>>>>>> piglit<br>
>>>>>> shader_runner. That is, use build scripts to extract shaders from<br>
>>>>>> shader_test files and feed them through glslang to get spv files, and<br>
>>>>>> then<br>
>>>>>> load those from shader_runner if a `-spirv' flag is passed on the<br>
>>>>>> command<br>
>>>>>> line.<br>
>>>>>><br>
>>>>>> This immediately runs into the difficulty that GL_ARB_gl_spirv wants<br>
>>>>>> SSO<br>
>>>>>> linking semantics, and I'm pretty sure the majority of shader_test<br>
>>>>>> files<br>
>>>>>> don't support that -- if only because they don't set a location on the<br>
>>>>>> fragment shader color output.<br>
>>>>>><br>
>>>>>> Some ideas:<br>
>>>>>> 1. Add a GL_MESA_spirv_link_by_name extension<br>
>>>>>> 2. Have glslang add the locations for us (probably difficult because<br>
>>>>>> glslang<br>
>>>>>> seems to be focused on one shader stage at a time.)<br>
>>>>>> 3. Hack something together in the shader_test-to-spv build scripts via<br>
>>>>>> regular expressions (and now we have two problems? :-) )<br>
>>>>>> 4. Other ideas?<br>
>>>>><br>
>>>>><br>
>>>>><br>
>>>>> We have plenty of GLSL SSO shader tests in shader-db, but we can only<br>
>>>>> compile-test them.<br>
>>>>><br>
>>>>> Initially I think we can convert a few shader tests to SSO manually<br>
>>>>> and use those.<br>
>>>>><br>
>>>>>><br>
>>>>>><br>
>>>>>> 2. What's the Gallium interface?<br>
>>>>>> ------------------------------<wbr>--<br>
>>>>>> Specifically, does it pass SPIR-V or NIR?<br>
>>>>>><br>
>>>>>> I'm leaning towards NIR, because then specialization, mapping of<br>
>>>>>> uniform<br>
>>>>>> locations, atomics, etc. can be done entirely in st/mesa.<br>
>>>>>><br>
>>>>>> On the other hand, Pierre Moreau's work passes SPIR-V directly. On the<br>
>>>>>> third<br>
>>>>>> hand, it wouldn't be the first time that clover does things<br>
>>>>>> differently.<br>
>>>>><br>
>>>>><br>
>>>>><br>
>>>>> If you passed SPIR-V to radeonsi and let radeonsi do SPIR-V -> NIR -><br>
>>>>> LLVM, you wouldn't need the serialization capability in NIR. You can<br>
>>>>> just use SPIR-V as the shader binary and the major NIR disadvantage is<br>
>>>>> gone. Also, you won't have to touch GLSL-to-NIR, and the radeonsi<br>
>>>>> shader cache will continue working as-is.<br>
>>>>><br>
>>>>> However, I don't know how much GL awareness is required for doing<br>
>>>>> SPIR-V -> NIR in radeonsi. Additional GL-specific information might<br>
>>>>> have to be added to SPIR-V by st/mesa for the conversion to be doable.<br>
>>>>> You probably know better.<br>
>>>>><br>
>>>>> st/mesa or core Mesa just needs to fill gl_program, gl_shader, and<br>
>>>>> gl_shader_program by parsing SPIR-V and not relying on NIR. I don't<br>
>>>>> know how feasible that is, but it seems to be the only thing needed in<br>
>>>>> shared code.<br>
>>>>><br>
>>>>> That also answers the NIR vs TGSI debate for the shader cache. The<br>
>>>>> answer is: Neither.<br>
>>>>><br>
>>>><br>
>>>> Just to list some downsides to this approach, not switching the the GLSL<br>
>>>> path to also use NIR has the following negatives:<br>
>>>><br>
>>>> 1. We don't get to leverage the large GL test suits and app ecosystem for<br>
>>>> testing the NIR -> LLVM pass both during development and afterwards.<br>
>>>><br>
>>>> 2. Jason has already said it best so to quote his reply:<br>
>>>> "There have been a variety of different discussions over the last few<br>
>>>> years<br>
>>>> about compiler design choices but we've lacked the ability to get any<br>
>>>> good<br>
>>>> apples-to-apples comparisons.  This may provide some opportunities to do<br>
>>>> so."<br>
>>>><br>
>>>> 3. The GLSL IR opts are both slow and not always optimal (possibly<br>
>>>> transforming the code to something that's harder to opt later), but due<br>
>>>> to<br>
>>>> uniform/varying optimisation requirements some optimisations are required<br>
>>>> *before* we can do validation. With NIR we have an opportunity to do<br>
>>>> these<br>
>>>> optimisations in NIR either by building a nir based linker for the final<br>
>>>> linking stage (uniform/varying validation/location assignment) or by a<br>
>>>> little bit of back and forth of information between NIR and GLSL IR. This<br>
>>>> is<br>
>>>> something that can't really be done with LLVM/Gallium. I was working<br>
>>>> towards<br>
>>>> this while at Collabora.<br>
>>>><br>
>>>> 4. We don't get to drop the glsl_to_tgsi pass which is not the most<br>
>>>> maintenance friendly piece of code. Also currently 10% of cpu is spent in<br>
>>>> the slow tgsi optimisations during start-up of Deus EX which equals<br>
>>>> around<br>
>>>> 50 seconds on my machine. Most of this optimisation is clean-up simply<br>
>>>> due<br>
>>>> to how sloppy the glsl_to_tgsi pass is.<br>
>>>><br>
>>>> 5. It's probably arguable but using GLSL -> NIR should result in more<br>
>>>> shared<br>
>>>> code paths both between radeonsi/radv and the drivers for other gpus<br>
>>>> anv/freedreno/vc4.<br>
>>>><br>
>>>> Anyway just a few things to think about.<br>
>>><br>
>>><br>
>>> Using GLSL -> NIR for radeonsi won't really change the GLSL linker<br>
>>> situation, because there are 12 other drivers consuming only TGSI.<br>
>><br>
>><br>
>> Ignoring the software drivers Nouveau is the only one in active development<br>
>> though right?<br>
><br>
> on x86, probably.. although etnaviv hasn't switched to nir and is<br>
> seeing active development.  (And, well, there are a couple arm/SoC<br>
> gpu's that still need a driver, although I guess if a foss mali driver<br>
> happens it is a good candidate to skip straight to nir)<br>
><br>
>>> I<br>
>>> guess it's OK to switch only radeonsi to NIR if it improves compile<br>
>>> times, but we also have the shader cache, so I don't know if it's<br>
>>> worth it just for the faster compilation that takes place only on the<br>
>>> first run. It's very hard to justify the massive development effort<br>
>>> here.<br>
>>><br>
>><br>
>> Rob seemed to think wiring up geom/tess support for glsl_to_nir should be<br>
>> straightforward.<br>
><br>
> I guess shader-stage aspect of it should be dead simple..<br>
> shader-feature aspect *might* be more involved (but really only to the<br>
> extent that mesa/st does clever things.. I probably should have split<br>
> up the patch that added mesa/st glsl->nir support for compute shaders<br>
> from the part that added ssbo's and atomic counters, because of the<br>
> way mesa/st lowers atomic counters to ssbo..).  Not sure if mesa/st<br>
> does anything clever with images (like it does w/ lowering atomic<br>
> counters to atomic ops to ssbo's).. if not that should require nothing<br>
> additional.<br>
><br>
> Anyways, if there is anything I can do to help on the plumbing nir<br>
> through mesa/st end of things, let me know.. I'll need it eventually<br>
> for freedreno.  But there are some things I haven't looked at yet just<br>
> because of features I haven't r/e'd and implemented yet.<br>
<br>
</div></div>btw, random thought, but if serializing/deserializing nir is going to<br>
be needed for on-disk shader cache (something I haven't had time to<br>
look at yet), maybe I should add that near the top of the todo-pile?<br>
AFAIU freedreno and vc4 will want that, and if it turns out to be<br>
useful for radeonsi too down the road, then bonus-points..<br></blockquote></div><br></div></div></div><div class="gmail_extra">Serializing NIR would also potentially be useful for us for caching purposes.  We could probably get quite a bit of benefit today if we just cached the optimized but not yet 100% lowered NIR.<br></div></div>
</blockquote></div><br></div><div class="gmail_extra">Also, if we had a way of serializing to a blob of memory, I'd be reasonably happy to add a NIR_TEST_SERIALIZATION option and stick it in our CI to ensure it keeps working.<br></div></div>