Use this to mark optional access qualifiers as "do not write". For now
this is a good enough way to not write out access qualifiers, which is
disallowed in GLSL shaders.
The stage is just passed to everywhere it's needed. The compiler does
not keep a stage property, instead it requires passing the stage as an
argument to every compilation.
As a side effect, environment treatment has changed:
Environments now allow creating "similar" (for lack of a better term)
environments with different version/profile.
We use this to pass the stage as part of the environment.
Instead of having a code block abstraction, just make code deal with
label ids instead. that way, code can just use gsk_spv_writer_make_id()
and pass that ID to the label func.
This simplifies code a lot as it allows special treatment of those
labels at eg the beginning of functions which can be kept local to where
it happens.
The C spec doesn't guarantee an order of evaluation for function
arguments. In fact, gcc evaluates them last to first while clang
evaluated them first to last.
We would like the left argument to be written into the SPIRV file first
(the GLSL spec wants that), so enforce this by calling the functions
before.
When writing SPIRV, statements return TRUE if they terminate the current
block (such as in a return statement). This is necessary because no code
may be written into a block after a termination opcode, so make all
other code check this return value and stop writing anything into the
current block.
Instead of creating a large const array of a custom struct holding all
the infos about native functions and iterating over that array, make the
macros generate code that register the functions directly.
So we don't need to deal with that weird struct anymore.
Instead of specifying the GskSlNativeFunction struct as the interface,
just have a more verbose constructor for native functins.
This will allow refactoring at will in the native function code.
This is the object that is meant to hold information about different GL
versions and take care of intializing native functions and variables at
the start of parsing.
If an expression is constant, always get the constant expression and
write it to the SPIRV file instead of doing an evaluation.
This has immense benefits when dealing with initializations, because
vec4(1, 2, 3, 4) will actually result in a constant instead of first
creating 4 integers, manually converting each of them to float before
calling the constructor. Yuck.
Logical or is not a binary expression in that the right side of the
expression is only executed if the left side returns false while all
binary operations always execute both sides.
This requires some changes to the generated code from the SPIRV spec,
because the grammar does not list the optional argument for OpDecorate.
Bad spec!
We can't just pass the value, SPIRV expects to be able to write to the
parameter if it's not const.
This does not yet do the right thing for for out variables. They are not
copied back to the caller.
For assignable expressions, we can always use an access chain to query
the value. Access chains are not just faster, they also contain lots of
optimizations for merging swizzles and whatnot.
A single swizzle can be reduced to an access chain lookup. This is
especially useful during assignments, because it means we don't need to
load the whole vector and OpVectorShuffle it.
This allows transitioning variables to different types. Which in the end
makes it possible to write different load/store code for parameters,
global variables or potentially GL builtins.
Represents a function, its argument types and whether they are
in/out/const arguments.
For now, this is just used to not duplicate function types in SPV files.
And use it to implement assignments.
And because I rock, this is all assignments, including member variables
swizzles and *= assignments. So this works:
foo.member.rgba.rgb *= vec3(0);
Store quantifier and real type in GskSlVariable instead.
Make gsk_spv_writer_get_id_for_pointer_type() take type and storage
class.
And generate writer opcodes using 2 arguments: Type and storage class.