Replacing NIR with SPIR-V?

Timur Kristóf timur.kristof at
Sun Jan 23 15:16:48 UTC 2022

Hi Abel,

On Sun, 2022-01-23 at 13:58 +0100, Abel Bernabeu wrote:
> That is the thing: there is already a community maintained LLVM
> backend for RISC-V and I need to see how to get value from that
> effort. And that is a very typical escenario for new architectures.
> There is already an LLVM backend for a programmable device and
> someone asks: could you do some graphics around this without spending
> millions?

While LLVM is a very good tool, it is not perfect and may not be the
best tool for compiling shaders. For example, ACO (the Valve-funded
compiler for AMD GPUs) was created despite the existence of an LLVM
backend. Our main concerns were:

1. Games stuttering due to slow compilation speed.
2. We are part of the Mesa source tree so we can fix bugs without
waiting for a new LLVM release.

> - Use Mesa as a framework and translate NIR to assembly (most likely
> choice).

I think this is the optimal solution. See below for a writeup about how
this works in practice.

> - Use Mesa as a framework and translate NIR to LLVM IR with some
> intrinsics, then feed the pre-existing LLVM backend.

A viable choice if you want to benefit from the infrastructure in Mesa,
but don't want to invest in a custom backend yet. You can always choose
to create a custom backend later, if you reached the limits of what
LLVM can do for you.

> - Use some new alternative, possibly a Mesa fork relying on the
> Khronos SPIR-V to LLVM IR translator. Start fixing the tool for
> supporting graphics... Make SPIR-V the IR that communicates frontend
> and backend :-)

I'm not familiar with those tools so I can't judge their viability.

> I am not thinking in terms of what is best for Mesa, but in terms of
> how could the RISC-V community organize its effort given that an LLVM
> backend is a given thing.
> I see the current reasons why NIR is preferred over SPIR-V in Mesa.
> So far you have given me three
> - There is a well designed library for traversing NIR, whereas SPIR-V
> defines nothing.
> - The arrays and structs are lowered before the shader is passed to
> the backend.
> - You see SPIR-V as a "serializing" format for IR to be exchanged
> through the network (like a .PNG for shaders), whereas NIR's focus is
> more about how the data structures are represented in memory while in
> use.

SPIR-V and NIR are designed for two different purposes:

- SPIR-V is meant to be a high-level platform-independent format and
the input to a compiler.
- NIR is an intermediate representation to be used internally by a
shader compiler. NIR's job is to represent a shader in such a way that
it will be fast and easy to modify and optimize.

The process of compilation is roughly this:

1. SPIR-V or GLSL (or another representation) is parsed into NIR.
2. Various optimizations are applied. We have a wide range of
optimizations and thanks to the nature of NIR, it's rather easy to
create more if the need arises.
3. Various lowerings are applied. NIR can understand which instructions
are available in your backend and which aren't. It transforms the
unsupported instructions to use supported ones.
4. A backend compiler gets the NIR and parses it into its own backend-
specific IR. This is easy because the backend will only see
instructions that it actually supports on the target hardware.
5. The backend may do further optimization and finally emit machine
code that the GPU can understand.

If you are interested how to build an OpenGL driver in Mesa, I
recommend watching the XDC 2018 talk by Kenneth Graunke who talks about
why and how he made the Intel Iris driver:

If you are interested in learning more about how to build a backend
that uses NIR, I recommend these talks:

Hope this helps,

More information about the mesa-dev mailing list