I just recently learned about the effort to target SPIR-V from Zig. I gather that this is mostly aimed at the GPGPU use case. I’m interested in graphics, but I’ve had previous bad experiences with non-GLSL shading languages not supporting image uniforms, integer samplers, or even combined image/sampler which is mandatory in SDL3 GPU API.
So, if there is any plans to make Zig an actual shading language for Vulkan or not, I’d like to hear about it to manage my expectations.
The code snippets that were posted a little while ago were essentially a fragment shader, so it looks like they’re aiming for rendering support, not just compute: Zig Shaders · GitHub
I would like to see full shader support for Zig too, and of all language projects the Zig project is probably best suited for this, but tbh, it’s a massive amount of work to create a shader compiler that could rival something like https://shader-slang.org/ (I would know maintaining my own shader cross-compiler for sokol-gfx, but this is built on the shoulder of giants (glsang, SPIRVTools, SPIRCross and Tint): sokol-tools/docs/sokol-shdc.md at master · floooh/sokol-tools · GitHub
A little list of things off the top of my head that needs to be solved:
as you mentioned, there’s different flavours of SPIRV (at least the GL-flavour with combined texture-sampler uniforms and the Vulkan flavour with separate texture and sampler uniforms), in sokol-shdc shaders are authored in the Vulkan flavour (with separate textures and samplers) and SPIRVCross takes care of transforming those into GL-flavoured SPIRV with combined texture-samplers)
there’s different alignment/packing rules for structs (std140, std430, packed) - probably quite easy to add to Zig
@Vector() definitely needs swizzling support (.xxyy etc…)
definitely need a @Matrix() builtin
the stdlib needs a complete set of shader builtin functions (maybe under std.gpu)
…and the biggest thing: SPIRV output alone doesn’t cut it (but is the foundation for everything else), because GL and Vulkan are actually not all that relevant. What’s also needed is a SPIRVCross/Tint equivalent which converts the SPIRV into backend specific shaders source or blobs, at least for D3D, Metal and WGSL, and for the foreseeable future also various GLSL versions. The main problem with this translation step is that different 3D APIs have wildly different resource binding models - but tbf this entire cross-step could be moved into a build system step - and could also be a 3rd-party project.
IMHO merging the CPU and GPU compiler is definitely the future though. Most of the API surface of today’s 3D APIs is about building data on the CPU side in the right ‘format’ that’s expected on the GPU side - but without a real compile-time connection between the two sides, which means a lot of information that already exists in the shader code needs to be replicated on the CPU side - or alternatively must be extracted via reflection, followed by code-generation for CPU structs and constants (that’s what I do in sokol-shdc).
If the compiler had direct access to all CPU- and GPU-side code, a lot of the 3D API surface could actually disappear.
Thanks for the thought-out reply. It seems that Zig isn’t really the kind of project that says “we won’t do that”, for better or worse, so I’m cautiously optimistic.
Hach, while it works, I’m not a fan of doing such fundamental things with wrapper functions. It really should be direct syntax (const v1 = v0.wzyx).
Zig should be a programming language, not a programming language construction kit (like C++ has become by preferring to do things that should be syntax in the stdlib instead - Rust also suffers from this problem)
Ah right I forgot. AFAIK they’re still in the ‘we intend to move’ phase though?
But I fully expect that this will be a 3rd flavour of SPIRV (the other two being GL and Vulkan). E.g. I’m willing to bet you can’t take a SPIRV blob compiled for Vulkan and stuff that into the D3D12 API.
I wonder if the differences between the Vulkan and D3D12 flavour could (or even should!) be transparently handled in the Zig SPIRV backend without some internal hardwired bindslot mapping rules, or whether it also requires a different shader source (at least to define the resource binding interface).
Also D3D11 won’t switch, and IMHO that’s still a so much better 3D API than D3D12 that it will be around for a while.
PS: a lot of the mapping to backend specific binding models can of course be done as a post-processing step one the output SPIRV (see SPIRVCross), would be nicer though if the number of tools/steps required to get from shader source to 3D API input could be reduced one day.
Maybe it’s off topic but I am interested in hearing your opinion on slang. I have looked into to it and it seems promising, especially with the feature of modules. Though some of the syntax I am not really a fan off but guess one gets used to it.
Mostly familiar with wgsl which seems like they can’t decide if it’s rust or c. Some glsl but not that much.
Really hope zig makes it less of a nuisance to write shader code.
I haven’t looked too deeply into Slang yet, but AFAIK it’s essentially HLSL with some language extensions (which makes sense since HLSL is the defacto industry standard for shader languages).
I don’t have much of an opinion on the different shader languages though, they all suck in different ways