[Mesa-dev] Adding a SPIR-V back-end to the GLSL compiler
Timothy Arceri
tarceri at itsqueeze.com
Wed May 31 00:05:44 UTC 2017
On 31/05/17 09:46, Jason Ekstrand wrote:
> On Tue, May 30, 2017 at 4:32 PM, Ian Romanick <idr at freedesktop.org
> <mailto:idr at freedesktop.org>> wrote:
>
> On 05/26/2017 08:57 AM, Jason Ekstrand wrote:
> > This is something that I have considered doing on multiple occasions and
> > have given a significant amount of thought. Unfortunately, it has never
> > made it particularly high on my priority list so no code has been
> > written. However, there have been a number of people who have brought
> > this up lately so I thought I would do a brain-dump on the topic in the
> > hopes of saving someone some effort.
>
> I've thought about this a lot too. I agree, to at least some extent,
> with everything you say below.
>
> > Why?
> >
> > That's as good a place to start as any. I think there a re a number of
> > reasons why this may be a useful thing to do:
> >
> > 1) Provide another GLSL -> SPIR-V compiler. Right now, the only thing
> > in that space is GLSLang and, while it seems to be servicing the need
> > ok, it also means that drivers tend not to implement SPIR-V support so
> > much as GLSLang support. SPIR-V provides a decent amount of freedom in
> > how you do things and GLSLang tends to only do them one way. This means
> > that the other 10 ways are untested in most drivers. Having another
> > SPIR-V producer out there would help the ecosystem.
> >
> > 2) Optimizations. One thing that I've heard developers asking for is
> > some basic platform-agnostic optimizations specifically to reduce SPIR-V
> > code size. Our compiler stack already has quite a few optimizations
> > that developers may want such as copy propagation, dead code
> > elimination, constant folding, loop unrolling, CSE, etc. In a GLSL ->
> > SPIR-V translator, we would probably want these to be optional, but it
> > wouldn't be hard to provide them as flags.
>
> So... isn't that going to be a problem? Pretty much all of our
> optimization infrastructure is now in NIR, and we're working towards
> removing at least some of the existing GLSL IR passes.
>
>
> Yes and no. GLSL IR will always have some of those optimizations if for
> nothing other than enforcing GLSL rules about varyings etc. Even if all
> they get is basic copy propagation, constant folding, and dead-code,
> that should be enough to cut the SPIR-V file size in half in a lot of cases.
I've mentioned this a few times before but this is not necessarily true.
i965 is very close to being able to drop GLSL IR opts and still being
able to enforce varying/uniform rules. The next question is of course
does dropping all the opts cause the increase in time in the glsl
linker, glsl->nir pass, etc not to be worth dropping them completely?
Anyway I just wanted to point out that always having GLSL IR opts isn't
necessarily a given (although they will be around for a long time given
the current use cases). Of course if you had a nir -> SPIR-V pass as you
talk about below we could just use the nir opts.
>
> > 3) Bootstrapping GL_ARB_spirv. The biggest barrier here is going to be
> > testing and convincing ourselves that we've done everything right.
> > However, if we did GLSL -> SPIR-V -> NIR -> back-end, then we would be
> > able to exercise both the GLSL -> SPIR-V path and the SPIR-V -> NIR path
> > with the full piglit suite. Some people have suggested modifying
> > shader_runner. However, I think that if we simply did the SPIR-V
> > translation inside the driver, it would be much easier to test things
> > like non-SSO because we could go into SPIR-V after linking.
> >
> > 4) Better testing spirv_to_nir. See above.
>
> This would augment the existing testing for spriv_to_nir (and
> not-yet-existing testing for GL_ARB_spriv), but we will probably need to
> start using a SPIR-V assembler to really hit all the corners.
>
>
> Yes. Fortunately, the Vulkan CTS has a medium sized set of hand-written
> SPIR-V tests. Most of the interesting ones target control flow which is
> by far the trickiest bit.
>
> > 5) Better spec compliance. I don't know the glslang code base well
> > enough to speak particularly strongly about it's correctness.
> What I do
> > know, however, is that the GLSL compiler in mesa is used in
> > production-grade drivers that pass piglit, the Open GL 4.5 CTS,
> the Open
> > GL ES 3.2 CTS, and the Android CTS. That's not something you can say
> > about GLSLang. I think we should make that available to game devs
> > wishing to target Vulkan.
> >
> > Where?
> >
> > This is a question that I have internally debated for some time.
> When
> > we first started working on Vulkan, we boot-strapped it by adding
> some
> > hacks to the GLSL compiler to provide the descriptor set bindings and
> > just used GLSL. When it came time for SPIR-V support, I chose to go
> > directly into NIR. At the time, I thought that SPIR-V was going
> to end
> > up being a fairly low-level IR and that NIR would be a better match.
> > However, as things turned out, SPIR-V (at least for graphics) is
> more of
> > a binary form of GLSL than anything else. In retrospect, there are a
> > number of things (dealing with built-ins comes to mind) which
> would have
> > been easier had we gone SPIR-V -> GLSL. However, I still stand by my
> > original decision for two reasons:
> >
> > 1) As we try to add some of these "advanced compute" features that
> > people keep talking about, I think NIR will be a better and
> better fit.
> > Trying to retrofit some of those things into GLSL may be more trouble
> > than it's worth.
> >
> > 2) Going directly into NIR meant that we didn't have to pull in
> > mtypes.h. NIR is a fairly stand-alone chunk of the mesa tree and we
> > have pulled our i965 back-end compiler out so it only depends on NIR.
> > This makes the Vulkan driver much smaller and keeps it separate
> from the
> > GL state tracker.
> >
> > When considering a GLSL -> SPIR-V path there is some question about
> > whether it should be GLSL -> NIR -> SPIR-V or GLSL -> SPIR-V
> directly.
> > There are pros and cons to both:
> >
> > 1) SPIR-V would actually make a reasonable serialization format for
> > NIR. It's maybe not as compact as we could do if we made our
> own, but
> > it's not bad.
>
> Yeah, I think I suggested that to Nicolai in the SPIR-V for Radeon
> thread.
>
> > 2) NIR is, in some ways simpler than GLSL IR so it may be a bit
> > easier. Unfortunately, that's not always a help...
> >
> > 3) Because NIR is simpler, it requires a lot of lowering. There are
> > several things such as block variables (for UBOs and SSBOs) that NIR
> > doesn't know how to handle. It assumes that it just gets
> > load_ubo(index, offset). NIR also doesn't handle GLSL built-ins. For
> > SPIR-V -> NIR, those things are lowered a way on-the-fly. This means
> > that we would have to add some things to NIR and the SPIR-V code you get
> > out would necessarily be lower-level than what glslang produces.
> >
> > 4) As I pointed out above, GLSL is a bit better fit than NIR in a lot
> > of ways.
> >
> > 5) If we did NIR -> SPIR-V, we could also compile ARB programs to
> > SPIR-V. Maybe that's a downside?
>
> I'm somewhat ambivalent about that. I think an interesting standalone
> project would be a compiler that could take some of the "advanced" NV
> assembly shaders to SPRI-V. I don't really want to see any of that
> support come back into Mesa.
>
>
> Fair enough. :-)
>
> > All in all, my recommendation would be to do GLSL -> SPIR-V directly. I
> > think there's less of an impedance mismatch there and I think it would
> > be easier to handle some of the higher-level things such as built-ins
> > and block variables.
> >
> > How?
> >
> > This is something that I've also given quite a bit of thought. :-) You
> > could even say that I've written a decent chunk of it in my head. Too
> > bad I haven't typed it into a computer yet. :-(
> >
> > The first thing I would do would be to write some sort of SPIR-V builder
> > and put it in src/compiler/spirv. It have multiple dword streams going
> > at a time (SPIR-V has multiple sections) to handle things such as types,
> > constants, etc. as well as function bodies. Then you would have
>
> An alternative would be to do it in two passes: the first pass figures
> out the sizes of the sections, and the second pass fills in the data.
> Or perhaps I'm misunderstanding.
>
>
> I don't think that's practical. You can't know the size of the sections
> without basically doing a full walk of the shader and pretending to
> generate SPIR-V. I think glslang has 3 or 4 instances of
> std::vector<uint32_t>. I think you need at least 3: decorations,
> types+constants, code. It's a bit unfortunate and I'm not convinced
> that splitting things into sections actually helps parsers, but it is
> what it is.
>
> > functions which would generate SPIR-V opcodes similar to
> nir_builder.h.
> > For Types, you would have a single spv_type function that turned a
> > glsl_type pointer into a SPIR-V ID. You would want to have this
> backed
> > by a hash map so that they aren't re-emitted all the time. For
> the rest
> > of the opcodes, SPIRV-Headers project on the Khronos github
> project has
> > a JSON representation of SPIR-V so it shouldn't be hard to write a
> > little python code that generates most of the "build an opcode"
> > functions similar to what we do for nir_builder_opcodes.h.
> >
> > Finally, you would write the GLSL -> SPIR-V (or NIR -> SPIR-V)
> pass on
> > top of that. If you did GLSL -> SPIR-V, you could probably look at
> > glsl_to_nir for inspiration.
> >
> > Ok, there's my brain-dump. It's on the list now so anyone who
> wants to
> > pick up the project has it. I'm happy to chat further via e-mail
> or IRC
> > about different approaches but I think I've given a fairly complete
> > picture of my thoughts at the moment. Happy Hacking!
> >
> > --Jason
>
>
>
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
>
More information about the mesa-dev
mailing list