[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