It turns out it was completely tangled up when I first wrote it. The
previous correction got things mostly right, but the overall sign was
wrong (ie, it gave -1..0 instead of 1..0)
I had forgotten the parameters needed to be in reverse order (since
constructor_expr was written as the implementation of a function call),
and I had also forgotten I need to do the assignment. No more broken
lights :)
This is a hack until I rethink the entire glsl implementation, but it
gets my vertex shaders such that Vulkan no longer rejects them. However,
there are a couple struct related bugs (next).
Things aren't quite working yet (currently due to buffer blocks not
getting marked NonWritable (or maybe they should be BufferBlock)), but
this gets shader compilation via qfcc working at all, including
automatic dependencies.
This allows struct block members to be copied out of a block for spir-v.
The code may not be optimal (the full struct is copied rather than only
used members), but it gets my vertex shaders compiling again and thus
passing that part of validation.
SPIR-V buffer block members need to be fully decorated with offsets
(recursively), which means that any members with struct or array types
need their own types in order to support having different offset and
stride (arrays) decorations. This breaks struct assignment at the
language level, but that is intentional as I want to deal with the
member copying needed to implement struct assignment before emitting
code. It also removes the need for some of the complication in
target_spirv.c, but I'll deal with that later.
The recursively built tag for nested structs might be a bit too
aggressive, but that too can wait until I have a better idea of what's
needed.
Any matrix, array or struct member in a uniform/buffer block requires
offset and stride annotations. These seem to be calculated correctly
(tricky due to qfcc's internal size system, which I should probably
adjust based on target (I think type_size() and type_align() should help
here). Now I've got fun with incompatible structs that are the same type
in the source (thus pass type checks), but different in the target (due
to concrete vs abstract addressing).
Fixes an ICE when compiling simplex.r (thus its addition to qfcc's
tests). It still fails due to having lost the points parameter, but yet
another automated test :)
It both seems to be a bit of a hack (since it probably doesn't conform
with the GLSL spec, but I've given up on worrying too much about that),
and the most sensible thing to do.
Shadow swizzling can return a single component but OpVectorShuffle
doesn't support returning a scalar. This is essentially duplicating the
vector logic in proc_field.
The whole point of prototypes is to ensure arguments are of the correct
type. Fixes some ints getting into places where floats were expected
(eg, mix, smoothstep, etc).
The function queue needs to be cleared before figuring out the interface
symbols otherwise the variables referenced only by called functions will
not get into the list of interface symbols.
This fixes the constant type reference ICE for subpassLoad. The problem
was stale symbols recorded in the expressions thus gsubpassInput
referred to the allowed types for the generic function rather than the
type specific to the call.
`address_expr()` wasn't enough because it returns pointers instead of
references (quite correct) which messes with checks for references
elsewhere (also quite correct). It seems I've finally got reference
parameters working.
Generic function parameters can now use references (currently via
`@reference()`) for generic types. And seem to work. There's still a
problem with chains: `atomicExchange(__imageTexel(...))` is
dereferencing __imageTexel's return value.
It seems it should return an Image storage class pointer. Validation
still fails because of the ptr local var (not allowed by default) and so
needs to be an SSA temp, but I'm having a little trouble with *that*.