Just wanted to share this
add vec2, vec3, vec4 types to the language #32032
Marked âurgentâ even. I wonder why?
Yeah canât wait to see how this will pan out ![]()
Urgent just means triage
Would any graphics programmer be willing to go more into detail about what SPIR-V backend + glsl means within the Zig ecosystem. I understand one is an Intermediate Representation and I understand the second is a shader language (?)
Does zig want to allow shader code to be run on GPUs to be entirely written in Zig?
not a graphics programmer, but Iâm pretty sure this is one of zigâs ambition, to be usable as a shading language at least thereâs an ofmt=spirv option when emiting code.
Targeting SPIR-V would allow (at least a sizable subset of) the same Zig code to be run reasonably parallel on a CPU, or massively parallel on a GPU or NPU.
This would make Zigâs strength in cross-compilation really useful for use cases like simulation, offline graphics, UI rendering, and anything else where youâd normally have to duplicate work just to have it both on the CPU and GPU (communicating data between the two can be expensive and troublesome, and sometimes you want the CPU as a fallback when a GPU isnât available or suitable).
It also just makes shader code more approachable for people not specialized in graphics programming. Breakpoints / debuggers are platform and vendor-specific (and necessarily different from CPU debuggers), and print statements are essentially unavailable in GPU programming.
Pardon my ignorance but does it mean zig wants to do what cuda does?
This feels like Zig would be getting multiple features doing extremely similar things without a clear distinction between them. The ticket talks about how @Vector is for SIMD, but vec2/3/4 also describes a number of SIMD operations. It also talks about vec types supporting swizzles, but CPU SIMD often has âpermutationâ instructions which are swizzles so @Vector would probably benefit from a way to describe those.
Now i16 is equivalent to @Int(signed, 16), so maybe vec4 is equivalent to @Vector(4, f32) as a shorthand. That makes sense to me, but a whole new type doesnât.
it is an accepted proposal to rename @Vector to @Simd which should help. But the line is pretty clear once you know what the types are.
@Simd is an optimisation primitive for when the compiler doesnât do a good enough job for you. Meaning that when you use it the compiler trusts that you know better, even if it is clearly suboptimal.
As is usually the case if you try to use it in place of mathematical vectors.
The proposed vec types will be mathematical vectors intended specifically for shaders/game dev.
They have very different use cases, if you find the terminology confusing that is the fault of SIMD using maths language inaccurately. Though it is at least better than using âvectorâ to describe a dynamic, and generic, array as c++/rust/etc have done.
The proposed
vectypes will be mathematical vectors intended specifically for shaders/game dev.
Tbh the distinction isnât clear to me either.
I also never understood where the âmathematical vectorâ angle is coming from, since game-dev/shading-language vectors are SIMD-style vectors - all operators on vec2..4 are component-wise (most notably multiplication is { .x=a.x*b.x, .y=a.y*b.y, .z=a.z*b.z, .w=a.w*b.w }, and special âalgebraicâ products like cross- or dot-product are implemented as builtin functions in shading languages (in old-school C++ vector libraries the * and % operators were sometimes overridden to mean either cross- or dot-product, but I donât think thatâs still en vogue and I would advice Zig to not go down that road, instead have a @dot(x, y) and @cross(x, y) builtin, and/or stdlib funcs).
Dot product for single inputs donât really simdify well. The idea of simd is always to work in batches. For example good simd dot product would look something like (which gives you 3 different dot products!):
pub fn dot_batch(x1: @Vector(3, f32), y1: @Vector(3, f32), z1: @Vector(3, f32), x2: @Vector(3, f32), y2: @Vector(3, f32), z2: @Vector(3, f32)) @Vector(3, f32) {
const x = x1 * x2;
const y = y1 * y2;
const z = z1 * z2;
return x + y + z;
}
Iâm also always perplexed by the mathematical vector distinction. Itâs just some âlist of numbersâ and the easiest way to lay them out is just everything one by one, a SIMD-style.
As for multiplication I would go even so far and just disallow the * operator completely because it isnât well defined. There at least 4 vector products I can think of on the top of my head that are used reasonably often: dot, cross, hadamard/component, and outer. Having the * as a shortcut for one of those just leads to confusion because the one you want the shortcut for very much depends on context.
If we go further to matrices itâs pretty similar. There are a bunch of products mathematicians came up with. But in contrast to vectors when one talks about a matrix product itâs always the same, while things like the hadamard product here are way more niche.
The batching is a good point, but that works just as well with GLSL-style vec2..vec4, the input data just needs to be provided differently (basically âpre-swizzledâ), e.g. I do this sort of â4-batchingâ in this GLSL shader for GPU skinning (note the xxxx, yyyy, zzzz vecs, this is basically doing a âmanualâ matrix multiplication via 3 dot products).
My point is that if you use SIMD vector to calculate single dot product, you end up with worse code than doing it with scalars. Linear algebra vectors wouldnât have to force SIMD code generation so it could decide more what kind of code to generate I guess.
Here is writeup about state of zig gpu backend Zig and GPUs.