Used the wrong generic type name for gvec4*, and missed @construct. Now
gridplane.frag tries to generate spir-v again (fails due to the
instruction names).
The goal is to make it easy to get size/coord/base types from image
types without creating a zillion type functions.
It was necessary to make it possible for any type to have an attribute
function (returns an expression so it can be more useful: types are
returned via type expressions). Algebra types were the first victim
(which was nice for testing).
And disable it for GLSL. I might need to make it target-dependent
instead as I don't know if I'll be able to implement it in SPIR-V, and
when I get to the C back-end, it will be superfluous.
GLSL's texture functions are a bit of a nightmare. The return types are
wrong, but I need to decide how I want to pull the sample type from a
texture or sampler.
Spir-v is pretty slack with the exact types of the operants to the
right-shift instructions so no need to care about the type for shift so
long as it has the correct number of components.
I had already implemented the code generation side (though using type
ids instead of encodings is a nice change), but I hadn't implemented the
actual evaluation or even called it. Now return types can be computed
from generic parameters (eg, ivecN from vecN).
It's still not great (mostly on the language side, I think), but
different glsl shader types get the correct model and fragment shaders
even get the correct mode.
Access qualifiers aren't supported yet, and some of the image handling
is a bit messy (currently tied to glsl when it should be general), but
the basics are there. However, now I've got to sort out the execution
model (need Fragment or GLCompute for ImplicitLod).
I really don't like the way they're included (I'm really looking forward
to #embed, but gotta wait for gcc 15), and I'm a tad grumpy that the
documentation for them
(https://registry.khronos.org/SPIR-V/specs/unified1/MachineReadableGrammar.html)
is wrong (missing fields), but I think I like the result.
The grammars (core and glsl.std.450) are parsed into structs that should
be fairly easy to interpret: the instructions, kinds, and enumerant
values are sorted by name for search with bsearch. Having the data
parsed in means source code can refer to the items by name rather than
magic numbers, which will be very nice for intrinsics and image types
(and probably a few other things).
The idea is to allow certain contexts to interpret something like `2D`
as an identifier instead of 2.0 (double), or (not sure I'll go there,
5e12 as a bivector instead of a double or float.
In the end, it does simplify things a lot, though it helped get function
pointers working at least a bit (they're not quite the same as C yet,
but I think that's mostly that functions can be struct fields).
They should now work in generic contexts, but the pressing need to work
on arrays was due to constant expressions for element counts breaking.
As a side effect, function pointers are now a thing (and seem to work
like they do in C)
GA expressions need to be optimized so things that should cancel out do,
and this requires everything to be dagged. Doing so in expr_process gets
most of the expressions, and then a few stragglers in proc_field. There
might still be some more, but my test scene compiles again.
I suspect they were once for dealing with class and typedef names in
selectors, but they're confusing things now that I'm trying to rework
type declarations, and I doubt they were ever actually needed.
I suspect this is actually a bug in parameter setup for inline function
calls, but it would certainly be a bug to get an unprocessed swizzle
expression as they're generated from field expressions.
It's just a jump to a label at the end of the block, but it's enough for
now as it takes care of the assumption that the return is the last
expression in the inlined function.
The code is pretty lousy in that it assumes there's only one `return`
and it's the end of the function, and the generated code is even worse
(too many load/store ops in the spir-v), but it looks like it at least
works. It does pass validation.
This gets the incoming parameters initialized, though currently rather
suboptimally (but that's due to the setup of the call). Next, just need
to handle `return` in inline functions.
Sometimes, premature optimization can help, but whatever. Finally,
alias.vert compiles, but the output is fairly broken (incorrect handling
of `return` and the parameters aren't initialized).
They need a valid name for the stricter checks. The name is taken from
the interface name, and since that needs to be unique, prepending a `.`
should be enough.
However, once past a couple of errors, they're not getting initialized
in the spir-v, so I've probably missed something there. For now I've
kept things simple and made them regular variables regardless of
qualifiers (and no support for out/inout yet).
If the block's result is just a variable reference, it won't match any
expression in the block's list so it needs to be processed independently
in such cases. The `mix(genFType x, genFType y, float a)` inline now
gets as far as spir-v code gen although there are still many issues to
fix (parameter symbols, `return` handling, etc).