Compare commits

...

177 Commits

Author SHA1 Message Date
Benjamin Otte
3680f0850f gskslstatement: Implement switch() 2017-10-30 02:58:03 +01:00
Benjamin Otte
92fd8ccdee gskslbinary: Implement modulo 2017-10-30 02:58:03 +01:00
Benjamin Otte
73ec3734bd gskslstatement: Implement break 2017-10-30 02:58:03 +01:00
Benjamin Otte
39a277260f gskslpreprocessor: Implement #if and #elif
Actually, just implement numbers and defined() parsing. But that's
enough for now.
2017-10-30 02:58:03 +01:00
Benjamin Otte
5bb7c2ecc3 gskslpreprocessor: Error if #endif is missing 2017-10-30 02:58:03 +01:00
Benjamin Otte
651b5bb9b6 gskslpreprocessor: Redo preprocessor directive parsing
Instead of manually keeping track of when we encounter a newline, just
parse everything up to the newline into a token array and then operate
on the array.
2017-10-30 02:58:03 +01:00
Benjamin Otte
9f4da8c509 gsksl: Error on redeclaration of variable
Also, emit shadow warnings whenever possible.
2017-10-30 02:58:03 +01:00
Benjamin Otte
cb857e7231 gsksl: Add support for native blocks
and implement gl_PerVertex's gl_Position and gl_PointSize with it.
2017-10-30 02:58:03 +01:00
Benjamin Otte
a7dac28a3a gsksl: Redo block parsing
Do not parse blocks while parsing types, instead move it to the
declaration parsing. Also, add a special variable type for the case of
unnamed blocks, so that we can access them directly.
2017-10-30 02:58:03 +01:00
Benjamin Otte
ad53eed564 gskslvariable: Make creating the access chain a vfunc
This just shuffles code around (so the vfunc can either return NULL or
create an access chain), but will be useful later.
2017-10-30 02:58:03 +01:00
Benjamin Otte
648cf099a8 gskslvariable: Remove gsk_sl_variable_store_spv()
A bunch of variables can't be written to. Instead of assuming code just
knows that and doesn't call store() on those, force storing to use
access chains. In that case, a NULL access chain should make it kinda
obvious that storing won't work.
2017-10-30 02:58:03 +01:00
Benjamin Otte
ff05d6ca35 gskslexpression: Add an "error" expression
Use it instead of initializing members to NULL and crashing later. The
error expression also takes a type so that the parser can continue
reporting potentially useful errors.

Fixes a crash when initializers were used with too few members.
2017-10-30 02:58:03 +01:00
Benjamin Otte
056cce93db gsksltype: Make sure blocks can't be compared
Testcase included
2017-10-30 02:58:03 +01:00
Benjamin Otte
0bc120414c gskslvariable: Refactor
Split the variable more up into its seperate subclasses.

For example, only store an initial value for variables that can have
one.
2017-10-30 02:58:03 +01:00
Benjamin Otte
2ce1bbacda gsksl: Move access chain API to GskSlVariable
An access chain is used to access a variable after all.
2017-10-30 02:58:03 +01:00
Benjamin Otte
ab91b013d5 gskslexpression: Implement initializers
So now this works:

float array[3] = { 1, 2, 3 };
2017-10-30 02:58:03 +01:00
Benjamin Otte
30c040a87c gskslexpression: Make gsk_sl_expression_write_spv() take a type argument
This is an optional argument that forces a conversion to this type. The
type must be compatible with the expression's return type.

This achieves 2 things:
1. It coerces constants to the correct type before they get written to
   SPV, like when doing
     float f = 1;
   we used to save an integer constant in the SPV and then convert it to
   float.
2. It makes people think about the return type when calling this
   function.
   3 cases (variable initialization and return types) did not properly
   convert values before. This is not fixed.
2017-10-30 02:58:03 +01:00
Benjamin Otte
b68aff252a gskslstatement: Implement discard statement 2017-10-30 02:58:03 +01:00
Benjamin Otte
c2773ef803 gskslexpression: Implement conditional expressions
Is_with_tests ? Commit_it : Commit_it_anyway
2017-10-30 02:58:03 +01:00
Benjamin Otte
9275cec204 gskslexpression: Detect out of range for array indexing
Obviously this only works for constants, but that should be enough.
2017-10-30 02:58:03 +01:00
Benjamin Otte
59f415dfe2 gsksl: Add initial support for native variables
So far, that's just gl_VertexIndex and gl_InstanceIndex.
2017-10-30 02:58:03 +01:00
Benjamin Otte
ac95c0606a gsksl: Add a special case for vector-to-vector casts
We don't have to extract all components and fold them back together if
the vectors already have the same size. Just cast them.
2017-10-30 02:58:03 +01:00
Benjamin Otte
e304738cfb gsksl: Parse array declarations 2017-10-30 02:58:03 +01:00
Benjamin Otte
6573df58e1 gsksltype: Add hash/equal vfuncs
This is because different array type objects may compare equal, so we
can't use direct pointer comparison anymore.
2017-10-30 02:58:03 +01:00
Benjamin Otte
d33881e0ec gsksltype: Implement arrays
This is incomplete as we can only declare variables using array types
but not as arrays of static types yet.
2017-10-30 02:58:03 +01:00
Benjamin Otte
7e9aa97fd5 gsksl: Add gsk_sl_expression_parse_integral_constant()
This is for parsing constant expressions, like array indices or layout
specifiers.
2017-10-30 02:58:03 +01:00
Benjamin Otte
38bc5f3d37 gskslbinary: Implement equal and not equal operations 2017-10-30 02:58:03 +01:00
Benjamin Otte
119f7fe74a gsksl: Comparisons aren't allowed between opaque types
For that purpose, export gsk_sl_type_contains_opaque() as it's used in
multiple places. It checks if a type or any of it's members are opaque.
2017-10-30 02:58:03 +01:00
Benjamin Otte
516cd4b499 gsksltype: Add sampler types
Also add texture() and texelFetch() functions and all variants.

textureGather() and textureQuery() functions are still missing
2017-10-30 02:58:03 +01:00
Benjamin Otte
38a255d132 gskspv: Deal with ImageOperands
ImageOperands are followed by an optional list of arguments for those
arguments.
2017-10-30 02:58:03 +01:00
Benjamin Otte
15cbfc8370 gskslqualifier: Require type to determine storage class
Opaque type uniforms have a different storage class than regular
uniforms.
2017-10-30 02:58:03 +01:00
Benjamin Otte
caaf1845c3 gsksl: Allow an optional access qualifier of -1
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.
2017-10-30 02:58:03 +01:00
Benjamin Otte
031a1812b8 gskslstatement: Implement for loops 2017-10-30 02:58:03 +01:00
Benjamin Otte
d59333da9e gsksl: Don't pass matcher to function argument parser
... when an error has occured. That way we avoid duplicate error
messages for nonexisting functions.
2017-10-30 02:58:03 +01:00
Benjamin Otte
fe4d17fee1 gskspvwriter: Change get_id_for_zero/one() functions
Accept a basic GskSlType instead of a scalar. That way, we can return
0/1 for vectors and matrices, which is kinda common.
2017-10-30 02:58:03 +01:00
Benjamin Otte
6a95433046 gsksltype: Add gsk_sl_type_is_basic()
That way, code doesn't have to do if (is_vector() || is_matrix() ||
is_scalar()) everywhere.
2017-10-30 02:58:03 +01:00
Benjamin Otte
b5919bf848 gskslexpression: Parse ++ and -- increment and decrement 2017-10-30 02:58:03 +01:00
Benjamin Otte
41fd67263f gsksl: Parse interpolation qualifiers 2017-10-30 02:58:03 +01:00
Benjamin Otte
5472458e6b gsksl: Check qualifier/type combinations are valid
So far, this is only implemented for in variables.
2017-10-30 02:58:03 +01:00
Benjamin Otte
8431b63b5d gsksl: Add support for stages
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.
2017-10-30 02:58:03 +01:00
Benjamin Otte
d17abee4eb gsksldeclaration: Correctly parse initializers
And store them as initializers for later.
2017-10-30 02:58:03 +01:00
Benjamin Otte
8a59adedfc testsuite: Add a simple test runner for errors
The test runner does nothing more but try to parse a given source and
check that that fails.

If it succeeds or crashes, the test fails.
2017-10-30 02:58:03 +01:00
Benjamin Otte
0b7b7a31b4 gskslvariable: Add API to query if access chain usage is possible
This is necessary so access chain creation can fail early when a
reference expression is asked to create one.
2017-10-30 02:58:03 +01:00
Benjamin Otte
4f8a422410 gsksltype: Write decorations for struct and block members 2017-10-30 02:58:03 +01:00
Benjamin Otte
f440e23bba gskslnative: Implement all native functions
Well, with the exception of modf() (out arguments, booo!) and the GL 150
functions.
2017-10-30 02:58:03 +01:00
Benjamin Otte
8d5fce4c69 gskspv: Change the way we deal with labels
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.
2017-10-30 02:58:03 +01:00
Benjamin Otte
fd83132d76 gskspv: Generate code for the extended instructions
This way, we can use the same approach to emit code for built-in
functions that we use for the rest of SPIRV emission.
2017-10-30 02:58:03 +01:00
Benjamin Otte
fde721eda8 gskslexpression: Function arguments are evaluated randomly
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.
2017-10-30 02:58:03 +01:00
Benjamin Otte
c546e64419 gskslstatement: Add a return value to spirv writing
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.
2017-10-30 02:58:03 +01:00
Benjamin Otte
04dc25ed62 gskslnative: Reorganize more
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.
2017-10-30 02:58:03 +01:00
Benjamin Otte
4d49471685 gskslfunction: Move native function details to native function code
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.
2017-10-30 02:58:03 +01:00
Benjamin Otte
481cb8ffad gsk: Add GskSlEnvironment
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.
2017-10-30 02:58:03 +01:00
Benjamin Otte
97a80e9169 gskslexpression: Implement a logical and expression
This mirrors what we did for || - because the right side is not always
evaluated, this isn't a normal binary operation.
2017-10-30 02:58:03 +01:00
Benjamin Otte
7445483691 gskslexpression: Fold constant expressions into SPIRV
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.
2017-10-30 02:58:03 +01:00
Benjamin Otte
2ee2457e82 gskslexpression: Add a logical or expression
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.
2017-10-30 02:58:03 +01:00
Benjamin Otte
9a0374f4fb gsksl: Implement relational comparisons 2017-10-30 02:58:03 +01:00
Benjamin Otte
4e61c71a5a gsksl: Implement subtraction 2017-10-30 02:58:03 +01:00
Benjamin Otte
d6c2c00a0a gskspv: Implement writing constructor functions
Calling a constructor is a simple OpConstantComposite call. Who'd have
thought.
2017-10-30 02:58:03 +01:00
Benjamin Otte
a7f11b5923 gsksl: Implement addition 2017-10-30 02:58:03 +01:00
Benjamin Otte
3124dffa37 gsksl: Emit decorations for variables
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!
2017-10-30 02:58:03 +01:00
Benjamin Otte
bde7a1f51c gskspv: Collect in and out variables
Send those variables as interaces with the entry point.
2017-10-30 02:58:03 +01:00
Benjamin Otte
fabb55524e gsksldeclaration: Type declarations aren't variables 2017-10-30 02:58:03 +01:00
Benjamin Otte
97118140be gskslprogram: Split out GskSlDeclaration
That's the object that will keep the toplevel declarations that make up
a program.
2017-10-30 02:58:03 +01:00
Benjamin Otte
1d5ac3b892 gskspv: Pass inout parameters by reference
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.
2017-10-30 02:58:03 +01:00
Benjamin Otte
9aa73600f1 gskslexpression: Add spv writing optimization
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.
2017-10-30 02:58:03 +01:00
Benjamin Otte
c4299a10c0 gskspvwriter: Add optimization for access chain
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.
2017-10-30 02:58:03 +01:00
Benjamin Otte
a0233d96e1 gskslvariable: Fold constant variables away in SPV output
This mirrors glslang behavior.
2017-10-30 02:58:03 +01:00
Benjamin Otte
6f551adf10 gskslvariable: Add a class for parameters
This simplifies the SPV writing.
2017-10-30 02:58:03 +01:00
Benjamin Otte
53bc1a1d35 gskslvariable: Make it classed
This is still in preparation for supporting multiple types of variables.
2017-10-30 02:58:03 +01:00
Benjamin Otte
1a5615ed73 gskslvariable: Add load()/store() functions
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.
2017-10-30 02:58:03 +01:00
Benjamin Otte
b63463f1a2 gsksl: Introduce GskSlFunctionType
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.
2017-10-30 02:58:03 +01:00
Benjamin Otte
940c13c25c gskspv: Ensure function labels come before variables 2017-10-30 02:58:03 +01:00
Benjamin Otte
31db111ae5 gskspv: Add GskSpvAccessChain
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);
2017-10-30 02:58:03 +01:00
Benjamin Otte
88413ad585 gsksl: Get rid of pointer types
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.
2017-10-30 02:58:03 +01:00
Benjamin Otte
bda72e2c23 gskslexpression: Add gsk_sl_expression_is_assignable()
And use it to fail when parsing assignments.
2017-10-30 02:58:03 +01:00
Benjamin Otte
115182d6e6 gskslexpression: Convert assignment expression to GskSlBinary
This also tightens the checks we do. So the code will now properly error
out if you try to assign an int to a matrix or try to &= with a float.
2017-10-30 02:58:03 +01:00
Benjamin Otte
41a0ce4621 gskslexpression: Move GskSlExpressionOperation to binaries
All those operations are now unimplemented binary types.
2017-10-30 02:58:03 +01:00
Benjamin Otte
093e9194b9 gskslexpression: Move division to the new binary vfuncs 2017-10-30 02:58:03 +01:00
Benjamin Otte
cb975b4faa gsksl: Split binary expressions into their own header
Ad a first step, do this for multiplication.
2017-10-30 02:58:02 +01:00
Benjamin Otte
3482a7de13 gskspv: Variables can go different places
Global variables are declared in the type definition section while local
variables are part of the function body.
2017-10-30 02:58:02 +01:00
Benjamin Otte
c803f5e5e4 gskspv: Claim to support the same source extensions as glslc
Makes it easier to compare disassembler output and hurts nobody.
2017-10-30 02:58:02 +01:00
Benjamin Otte
6d9a5feb43 gskspv: Reorganize code more
Now we create IDs in the same way glslang does and we write out code in
the same order - at least for "void main() { }"
2017-10-30 02:58:02 +01:00
Benjamin Otte
17661af6da gskspvwriter: Allow writing a function with initializer
That way, we can initialize global variables.

We're also a lot closer to emitting code in the way glslc does.
2017-10-30 02:58:02 +01:00
Benjamin Otte
1455ef2c21 gskspv: emit Debug information 2017-10-30 02:58:02 +01:00
Benjamin Otte
cccca8c2f0 gskspvwriter: Put the declaration section into the block
Declarations are per-function, so treat them like that.
2017-10-30 02:58:02 +01:00
Benjamin Otte
a29a486442 gskspv: Allow writing function calls
The code is all very wonky still in the way it orders instructions
and needs some reorganization to consistently do the right thing.
2017-10-30 02:58:02 +01:00
Benjamin Otte
807b63fded gskspv: Add GskSpvCodeBlock
This represents a block of code. For now it's only used for if
statements (which are now enabled again), but in future commits
writing of function blocks will use it, too.
2017-10-30 02:58:02 +01:00
Benjamin Otte
918ff3d58e gskpsv: Completely redo SPV writing
Autogenerate the headers for SPIR-V from the JSON file provided by the
spec (and now included here).
This provides a way more readable and on top of that type-safe way to
emit bytecodes when generating code.

As a result of this, the whole bytecode emission was rewritten, so there
are probably lots of different bugs in it now.

Note: If statement SPV generation was disabled. Code generation needs
some more support for control flow before I can reenable if statements.
2017-10-30 02:58:02 +01:00
Benjamin Otte
bfdc7ad4ab gskslexpression: Implement Division
Split out arithmetic expressions and implement constant evaluation SPV
writing for division.
2017-10-30 02:58:02 +01:00
Benjamin Otte
c45e88f36a gskslfunction: Actually write arguments to SPV
This includes code in the variable path to write parameter variables out
as parameters instead of regular global/local variables.
2017-10-30 02:58:02 +01:00
Benjamin Otte
bc83778cd5 gskslstatement: Add SPV code for return statement 2017-10-30 02:58:02 +01:00
Benjamin Otte
737bb72ccc gsksltype: Add gsk_sl_type_get_matching()
Returns the matching basic type for a different scalar type, ie returns
bvec3 for boolean vec3 or dmat3x4 for double mat3x4.

If the function is called when no matching type exists, it will explode
in your face.
2017-10-30 02:58:02 +01:00
Benjamin Otte
9825d95857 gsksl: Add gsk_spv_writer_get_id_for_zero()
and gsk_spv_writer_get_id_for_one(). Those are functions that return the
id for the value 0 or 1 in the given scalar. Note that they can be used
for FALSE/TRUE.
2017-10-30 02:58:02 +01:00
Benjamin Otte
6bdf46fbcf gskslprinter: Deal with non-normal floating points
Instead of NaN, print "(0.0 / 0.0)" and instead of INF, print "(1.0 /
0.0)".

Both of that is not spec-conformant, but the best we can do if we
encounter constant expressions that evaluate to these numbers.
2017-10-30 02:58:02 +01:00
Benjamin Otte
420fb00e1e gskslexpression: Split multiplication from other binary operations
Also implement get_constant() and write_spv() vfuncs.
2017-10-30 02:58:02 +01:00
Benjamin Otte
764f6708f6 gsksl: Implement constructor writing to SPIR-V
This includes the new function gsk_spv_writer_add_conversion() which
does the daunting task of doing a conversion for all types that can
convert, so it's the equivalent to gsk_sl_value_new_convert().
2017-10-30 02:58:02 +01:00
Benjamin Otte
6e7c348654 gsksltype: Add gsk_sl_type_value_equal()
Use this in gsk_sl_value_equal().
2017-10-30 02:58:02 +01:00
Benjamin Otte
0a9f758c36 gskslfunction: Add gsk_sl_function_get_constant()
Also, call it from the function call expression.

It's completely unimplemented so far, so it's not that useful.
2017-10-30 02:58:02 +01:00
Benjamin Otte
0c567d6c28 gsksl: Builtin constructors are no longer functions
They don't obey the laws that govern constructors (argument promotion,
constant amount of predefined types of arguments and so on).
So we turn constructor calls into their own expression type.

This also dimplifies function call validation because we don't have to
do two-in-one with constructors in there.

And while doing that, also fix up the rules that govern constructor
arguments: Matrixes aren't allowed as arguments for matrixes unless
they're the first and only argument.
And if scalars are the first and only argument, they behave differently
than they would otherwise.
2017-10-30 02:58:02 +01:00
Benjamin Otte
a50d932150 gskslvalue: Add gsk_sl_value_to_string ()
Very useful to have in gdb.
2017-10-30 02:58:02 +01:00
Benjamin Otte
6af46a0659 gsksltype: Add concept of components
A type has components, if it is essentially an array of tighly packed
scalar values. In this case, a GskSlValue's data is essentially
  ScalarType data[n_components];
2017-10-30 02:58:02 +01:00
Benjamin Otte
c624bae54c gskslpreprocessor: Support parsing #version
This required a lot of reorganization because we have to track if we're
at the start of the document.

On the plus side, we now parse the #version tag and if it's correctly
used, we emit a warning that we don't support it.

Aren't we awesome?
2017-10-30 02:58:02 +01:00
Benjamin Otte
c5a1eaf1a1 gskslpreprocessor: Implement #include 2017-10-30 02:58:02 +01:00
Benjamin Otte
35476639c4 gskslcompiler: Provide a way to compile files
And use it from gtk-glsl.

A neat side effect is that we now get the actual file printed in error
messages.
2017-10-30 02:58:02 +01:00
Benjamin Otte
e48be683c7 gsk: Add GskCodeSource
This is basically the source format we use to represent source code.

It can be created either from a file or from a GBytes, so we can use it
to hold all data that can be provided by user input (#defines) or by
actual files.
2017-10-30 02:58:02 +01:00
Benjamin Otte
a07924c0d6 gsksltokenizer: Parse strings
And when we encounter any strings in the preprocessor, we promptly emit
an error and skip them. But we do that after the preprocessor runs, so
we can access strings inside the preprocessor.
2017-10-30 02:58:02 +01:00
Benjamin Otte
4927e229b3 gskslqualifier: Implement layout(push_constant) 2017-10-30 02:58:02 +01:00
Benjamin Otte
deb3d26ff6 gsksl: Add support for parsing blocks 2017-10-30 02:58:02 +01:00
Benjamin Otte
60add60236 gskslqualifier: Handle uniform variables 2017-10-30 02:58:02 +01:00
Benjamin Otte
19ae9c0f8e gsksl: Redo qualifier handling
This is the 3rd time at least that I've rewritten it. This time, I've
added a GskSlQualifier struct that contains all the information relevant
to qualifiers. It replaces the previous GskSlDecorationList.
2017-10-30 02:58:02 +01:00
Benjamin Otte
a3dec06d3f gskslstatement: Add gsk_sl_Stement_get_jump()
This queries where a statement jumps to after it is done. The enum is
sorted by importance, larger values jump further.

We use this to do 3 things:
1. Error out if the function body statement does not return a value from
   a non-void function.
2. Make sure to emit a Return as last instruction in a function body
3. Print a warning about dead code when statements follow a jump.
2017-10-30 02:58:02 +01:00
Benjamin Otte
196ee554b4 gsksltype: Turn void into a custom type class
Previously, void was a scalar type. It's not anymore.

On the plus side, we now got a gsk_sl_type_is_void() function that's
kinda useful in places.
2017-10-30 02:58:02 +01:00
Benjamin Otte
7b416c9dc5 gskslpreprocessor: Implement #ifdef, #else and #endif 2017-10-30 02:58:02 +01:00
Benjamin Otte
a05961d57a gskslstatement: Handle if statements 2017-10-30 02:58:02 +01:00
Benjamin Otte
7e55c4760a gskslfunction: the body of a function is a single statement
Now that we have compound statements, we can use them as the function
body.
2017-10-30 02:58:02 +01:00
Benjamin Otte
e2d6d07c2a gsksl: Don't return a value from gsk_sl_statement_write_spv()
Statements emit code, they don't return any values. That's what
expressions are for.
2017-10-30 02:58:02 +01:00
Benjamin Otte
607b4b40a0 gskslstatement: Parse compound statements 2017-10-30 02:58:02 +01:00
Benjamin Otte
622dccd438 gskslstatement: Print semicolon in the statement print function
This is necessary for compound statements which don't have a semicolon.
2017-10-30 02:58:02 +01:00
Benjamin Otte
6247fae076 gsksl: Rename GskSlNode to GskSlStatement
The generic node class from the beginning was only used by statements,
so better name it appropriately.
2017-10-30 02:58:02 +01:00
Benjamin Otte
3279b11a99 gsksl: Add native functions
This basically just adds the prototypes, actually evaluating the
functions doesn't work.
2017-10-30 02:58:02 +01:00
Benjamin Otte
6f80039428 gsksl: Add GskSlPrinter
This is a subclass for pretty-printing. It's not yet very useful, but
will become so once we nest blocks or have way too long statements to
fit on a single line.
2017-10-30 02:58:02 +01:00
Benjamin Otte
11ab6f823b gsksl: Add support for overloaded functions
This changes GskSlScope to allow multiple functions of the same name.

It also introduces GskSlFunctionMatcher, which does overload matching in
a way that can be used while parsing function calls.
2017-10-30 02:58:02 +01:00
Benjamin Otte
d3b452e303 gskslfunction: Reorganize gsk_sl_function_matches()
This is the first step towards implementing function overloading.

Instead of having the matches() vfunc the code now can query argument
type and count and uses this to implement a generic matches().

Constructors are checked seperately and manually. They also report 0
arguments.
2017-10-30 02:58:02 +01:00
Benjamin Otte
88eac26f5a gskslfunction: Split regular and builtin constructors
Their behavior is just too different.
2017-10-30 02:58:02 +01:00
Benjamin Otte
21fe62ec66 gskslexpression: Implement negation
This includes adding gsk_sl_value_componentwise() which is not something
I particularly like, but it does its job - and will be useful for the
other operations.
2017-10-30 02:58:02 +01:00
Benjamin Otte
69b4834764 gskslexpression: Change function call error handling
Allow calling the function call parsing code with a NULL function. In
that case, we will parse the arguments and then return without emitting
an error. This ensures that the parser is in a sane state and reports
useful errors even if there's a typo in a function call.
2017-10-30 02:58:02 +01:00
Benjamin Otte
6fa6e9964c gskslexpression: Parse (sub)expressions in parenthesis
Well, that was easy.
2017-10-30 02:58:02 +01:00
Benjamin Otte
c22b36d2b5 gskslfunction: Parse arguments 2017-10-30 02:58:02 +01:00
Benjamin Otte
fad4112d78 gsksl: Introduce gsk_sl_preprocessor_sync()
Instead of just returning after an error an continuing to parse
wherever, use gsk_sl_preprocessor_sync() to find the next point in the
token stream that looks like a useful way to continue parsing.
2017-10-30 02:58:02 +01:00
Benjamin Otte
c30089a1cb gskslfunction: Properly type-check calls to struct constructors 2017-10-30 02:58:02 +01:00
Benjamin Otte
4450d83cb9 gsksltype: Generate better type names
If multiple consecutive struct names share their types, use comma
notation to goup them.
2017-10-30 02:58:02 +01:00
Benjamin Otte
500e6bc2bc gsksl: Add support for parsing members of struct variables
This includes adding the concept of members to GskSlType.
2017-10-30 02:58:02 +01:00
Benjamin Otte
8d6a332482 gsksl: Add support for structs 2017-10-30 02:58:02 +01:00
Benjamin Otte
4d5cf80003 gskslexpression: Implment function calls 2017-10-30 02:58:02 +01:00
Benjamin Otte
458a9e3e44 gskslscope: Track function calls 2017-10-30 02:58:02 +01:00
Benjamin Otte
1d87210572 gskslnode: Always return a statement
Same thing as with expresssions: On parsing errors, return something,
anything really.
2017-10-30 02:58:02 +01:00
Benjamin Otte
2a7f343714 gsksl: Make expression parsing never fail
Code will always return a valid expression - for an invlaid token
stream, that might be a very random expression, but still, it's an
expression.
2017-10-30 02:58:02 +01:00
Benjamin Otte
a2aaf2b90e gskslpreprocessor: Return fatalness of parsing
Instead of relying on parsing functions to return FALSE on error, we
record that parsing failed inside the preprocessor object and continue
parsing (potentially using dummy objects as the result).

That way, we keep parsing and can emit potentially useful error messages
for the rest of the document.

Now we just need to implement that mentality.
2017-10-30 02:58:02 +01:00
Benjamin Otte
2bceaedd37 gsksl: Add an error enum
And specify the correct error value whenever an error is emitted.
2017-10-30 02:58:02 +01:00
Benjamin Otte
46c9a3aaaa gskslpreprocessor: Redo error emission
Instead of an error function, we now have a macro that calls
gsk_sl_preprocessor_emit_error().
2017-10-30 02:58:02 +01:00
Benjamin Otte
13dd620828 gskslexpression: Parse swizzles 2017-10-30 02:58:02 +01:00
Benjamin Otte
c8f234971b gsksltype: Add gsk_sl_type_get_index_stride()
This allows operations on GskSlValues that are arrays, because one can
just do code like:
  data = gsk_sl_value_get_data (value);
  stride = gsk_sl_value_get_index_stride (type);
  for (i = 0; i < gsk_sl_value_get_length (type); i++)
    {
      do_stuff_with_data (data + i * stride);
    }
2017-10-30 02:58:02 +01:00
Benjamin Otte
0e284138e3 gskslexpression: References to const variables are const
So we return a const value if that happens.
2017-10-30 02:58:02 +01:00
Benjamin Otte
7e4d163f11 gskslprogram: Allow variables to have constant initializers
Technically, all intiializers should be allowed, but for now we're happy
we can do const ones.

Also store them properly in the SPIR-V output.
2017-10-30 02:58:02 +01:00
Benjamin Otte
850c6d1116 gskslvariable: Allow storing an initializer value with a variable
This code requires the addition of gsk_sl_value_new_convert() so
constants can be converted to the right type.
2017-10-30 02:58:02 +01:00
Benjamin Otte
ea45570850 gsksldeclaration: Throw an error if a variable initializer doesn't match
... the type of the declared variable and cannot be converted to it.
2017-10-30 02:58:02 +01:00
Benjamin Otte
3fc253c57d gskslvariable: Store constness of variables 2017-10-30 02:58:02 +01:00
Benjamin Otte
545ce13981 gskslexpression: Change is_constant() to get_constant()
Actually use this to evaluate layout () expressions.

Unfortunately get_constant() is not implemented in many places, so it
doesn't do much more than the int constant parsing.
2017-10-30 02:58:02 +01:00
Benjamin Otte
c2672540d9 gsksl: Parse common layout() specifiers
In particular: binding, set, location and component.
2017-10-30 02:58:02 +01:00
Benjamin Otte
a7fce5603a gsksl: Redo declaration "decorator" parsing
Instead of parsing into a list of flags, have an array of values that
can be set to certain values. This way, we can reuse it for layout()
contents.
2017-10-30 02:58:02 +01:00
Benjamin Otte
cf40318d9b gsksl: Introduce GskSlValue
This is - analog to a GValue - a type plus the memory of a value in that
type.

So far it is only used to represent constant expressions.
2017-10-30 02:58:02 +01:00
Benjamin Otte
4395675c58 gskslprogram: Parse global variables
We don't parse initializations yet, but whatever.
2017-10-30 02:58:02 +01:00
Benjamin Otte
b522801c5a gskslfunction: Change name printing to name getting
Since gsk_sl_type_get_name() exists now, we can have a name getter also
for builtin constructors.
2017-10-30 02:58:02 +01:00
Benjamin Otte
eb12740151 gsksl: Turn functions into functions
Don't use a GskSlNode subclass to handle declared functions but make
them a GskSlFunction subclass.
2017-10-30 02:58:02 +01:00
Benjamin Otte
7e8604372d gsksl: Split Expression from Node 2017-10-30 02:58:02 +01:00
Benjamin Otte
4deaddeb70 gsksl: Add GskSlVariable
A variable is the abstraction used for declarations of variables.

I chose the name Variable over Declaration because it's the result of
the SPIRV instruction OpVariable.
2017-10-30 02:58:02 +01:00
Benjamin Otte
935402e0aa gskslpreprocessor: Implement #define and #undef 2017-10-30 02:58:02 +01:00
Benjamin Otte
67b60b54ac gskslcompiler: Add support for adding defines
gtk-glsl implements this via the usual -D and -U options.

Preprocessor directives aren't implemented yet, but defines are replaced
in the source code already.
2017-10-30 02:58:02 +01:00
Benjamin Otte
f8299719b4 gsksl: Introduce GskSlCompiler
This is the object that is used to create programs from. It also holds
(or will hold) all the settings necessary to parse GLSL - like defines
or include directories.
2017-10-30 02:58:02 +01:00
Benjamin Otte
eee9142397 gsksl: Split out GskSlProgram
And turn it into public API.
2017-10-30 02:58:02 +01:00
Benjamin Otte
d3511003cf gsksltokenizer: Always return idents
Turning idents into keywords is the job of the preprocessor and has to
be done after processing #defines.
2017-10-30 02:58:02 +01:00
Benjamin Otte
9417507829 gsksl: Implement skeleton SPIRV output 2017-10-30 02:58:02 +01:00
Benjamin Otte
45ad50a61c gsk: Add GskSlPointerType
This describes a type with qualifiers like const, volatile and so on.
2017-10-30 02:58:02 +01:00
Benjamin Otte
447f52502a gtk: Add gtk-glsl binary
That's supposed to become the command-line compiler.

So far all it does is parse and then dump as text again the provided
input file(s).
2017-10-30 02:58:02 +01:00
Benjamin Otte
c7590f310f gskslnode: Parse return statements 2017-10-30 02:58:02 +01:00
Benjamin Otte
f607087201 gskslnode: Add builtin constructors
Do this by implementing function call nodes and adding GskSlFunction,
which is meant to be used for anything that is callable.
2017-10-30 02:58:02 +01:00
Benjamin Otte
36a61f0ad0 gskslnode: Add comparison and shift operators 2017-10-30 02:58:02 +01:00
Benjamin Otte
b6adb44dfd gsksltype: Add matrix type 2017-10-30 02:58:02 +01:00
Benjamin Otte
0e56c28725 gsksltype: Add support for vector types 2017-10-30 02:58:02 +01:00
Benjamin Otte
0362778524 gskslnode: Add GskSlNodeOperation
This is for operations in expressions, like and, or, shift, addition or
multiplication.

These operations need to do sophisticated type checks that can't be done
yet, so only the logical operations are implemented so far.
2017-10-30 02:58:02 +01:00
Benjamin Otte
ad4b45639b gskslnode: Add variables
This requires keeping a scope object that we can use to store and load
variables.
2017-10-30 02:58:02 +01:00
Benjamin Otte
dc519ad2a2 gskslnode: Add gsk_sl_node_is_constant()
And use it to emit a compile error when trying to assign to a constant
value.
2017-10-30 02:58:02 +01:00
Benjamin Otte
7a215a6b39 gskslnode: Add gsk_sl_node_get_return_type()
It's unused for now.

But the idea is that (most) nodes return a value and we can know the
type of value they return at compile-time. And then we can check type
compatibility while parsing using this function.
2017-10-30 02:58:02 +01:00
Benjamin Otte
da5417def4 gsksl: Add gsksltypesprivate.h
All those types are recursively needing each other in their functions,
so add a generic header for all those types and only include that
header.
2017-10-30 02:58:02 +01:00
Benjamin Otte
4e0def2806 gsksl: Parse assignments 2017-10-30 02:58:02 +01:00
Benjamin Otte
bc5c3e1b56 gsksl: Start parsing statements by parsing constants 2017-10-30 02:58:02 +01:00
Benjamin Otte
3a298f8f9c gsk: Add a skeleton for a GLSL parser 2017-10-30 02:58:02 +01:00
111 changed files with 41740 additions and 0 deletions

View File

@@ -5,6 +5,7 @@ private_headers = [
'gskgldriverprivate.h',
'gskglprofilerprivate.h',
'gskglrendererprivate.h',
'gskpixelshaderprivate.h',
'gskprivate.h',
'gskprofilerprivate.h',
'gskrendererprivate.h',

View File

@@ -0,0 +1,642 @@
{
"copyright" : [
"Copyright (c) 2014-2016 The Khronos Group Inc.",
"",
"Permission is hereby granted, free of charge, to any person obtaining a copy",
"of this software and/or associated documentation files (the \"Materials\"),",
"to deal in the Materials without restriction, including without limitation",
"the rights to use, copy, modify, merge, publish, distribute, sublicense,",
"and/or sell copies of the Materials, and to permit persons to whom the",
"Materials are furnished to do so, subject to the following conditions:",
"",
"The above copyright notice and this permission notice shall be included in",
"all copies or substantial portions of the Materials.",
"",
"MODIFICATIONS TO THIS FILE MAY MEAN IT NO LONGER ACCURATELY REFLECTS KHRONOS",
"STANDARDS. THE UNMODIFIED, NORMATIVE VERSIONS OF KHRONOS SPECIFICATIONS AND",
"HEADER INFORMATION ARE LOCATED AT https://www.khronos.org/registry/ ",
"",
"THE MATERIALS ARE PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS",
"OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,",
"FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL",
"THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER",
"LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING",
"FROM,OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE USE OR OTHER DEALINGS",
"IN THE MATERIALS."
],
"version" : 100,
"revision" : 2,
"instructions" : [
{
"opname" : "Round",
"opcode" : 1,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "RoundEven",
"opcode" : 2,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "Trunc",
"opcode" : 3,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "FAbs",
"opcode" : 4,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "SAbs",
"opcode" : 5,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "FSign",
"opcode" : 6,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "SSign",
"opcode" : 7,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "Floor",
"opcode" : 8,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "Ceil",
"opcode" : 9,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "Fract",
"opcode" : 10,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "Radians",
"opcode" : 11,
"operands" : [
{ "kind" : "IdRef", "name" : "'degrees'" }
]
},
{
"opname" : "Degrees",
"opcode" : 12,
"operands" : [
{ "kind" : "IdRef", "name" : "'radians'" }
]
},
{
"opname" : "Sin",
"opcode" : 13,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "Cos",
"opcode" : 14,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "Tan",
"opcode" : 15,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "Asin",
"opcode" : 16,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "Acos",
"opcode" : 17,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "Atan",
"opcode" : 18,
"operands" : [
{ "kind" : "IdRef", "name" : "'y_over_x'" }
]
},
{
"opname" : "Sinh",
"opcode" : 19,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "Cosh",
"opcode" : 20,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "Tanh",
"opcode" : 21,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "Asinh",
"opcode" : 22,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "Acosh",
"opcode" : 23,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "Atanh",
"opcode" : 24,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "Atan2",
"opcode" : 25,
"operands" : [
{ "kind" : "IdRef", "name" : "'y'" },
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "Pow",
"opcode" : 26,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" },
{ "kind" : "IdRef", "name" : "'y'" }
]
},
{
"opname" : "Exp",
"opcode" : 27,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "Log",
"opcode" : 28,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "Exp2",
"opcode" : 29,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "Log2",
"opcode" : 30,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "Sqrt",
"opcode" : 31,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "InverseSqrt",
"opcode" : 32,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "Determinant",
"opcode" : 33,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "MatrixInverse",
"opcode" : 34,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "Modf",
"opcode" : 35,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" },
{ "kind" : "IdRef", "name" : "'i'" }
]
},
{
"opname" : "ModfStruct",
"opcode" : 36,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "FMin",
"opcode" : 37,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" },
{ "kind" : "IdRef", "name" : "'y'" }
]
},
{
"opname" : "UMin",
"opcode" : 38,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" },
{ "kind" : "IdRef", "name" : "'y'" }
]
},
{
"opname" : "SMin",
"opcode" : 39,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" },
{ "kind" : "IdRef", "name" : "'y'" }
]
},
{
"opname" : "FMax",
"opcode" : 40,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" },
{ "kind" : "IdRef", "name" : "'y'" }
]
},
{
"opname" : "UMax",
"opcode" : 41,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" },
{ "kind" : "IdRef", "name" : "'y'" }
]
},
{
"opname" : "SMax",
"opcode" : 42,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" },
{ "kind" : "IdRef", "name" : "'y'" }
]
},
{
"opname" : "FClamp",
"opcode" : 43,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" },
{ "kind" : "IdRef", "name" : "'minVal'" },
{ "kind" : "IdRef", "name" : "'maxVal'" }
]
},
{
"opname" : "UClamp",
"opcode" : 44,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" },
{ "kind" : "IdRef", "name" : "'minVal'" },
{ "kind" : "IdRef", "name" : "'maxVal'" }
]
},
{
"opname" : "SClamp",
"opcode" : 45,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" },
{ "kind" : "IdRef", "name" : "'minVal'" },
{ "kind" : "IdRef", "name" : "'maxVal'" }
]
},
{
"opname" : "FMix",
"opcode" : 46,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" },
{ "kind" : "IdRef", "name" : "'y'" },
{ "kind" : "IdRef", "name" : "'a'" }
]
},
{
"opname" : "IMix",
"opcode" : 47,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" },
{ "kind" : "IdRef", "name" : "'y'" },
{ "kind" : "IdRef", "name" : "'a'" }
]
},
{
"opname" : "Step",
"opcode" : 48,
"operands" : [
{ "kind" : "IdRef", "name" : "'edge'" },
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "SmoothStep",
"opcode" : 49,
"operands" : [
{ "kind" : "IdRef", "name" : "'edge0'" },
{ "kind" : "IdRef", "name" : "'edge1'" },
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "Fma",
"opcode" : 50,
"operands" : [
{ "kind" : "IdRef", "name" : "'a'" },
{ "kind" : "IdRef", "name" : "'b'" },
{ "kind" : "IdRef", "name" : "'c'" }
]
},
{
"opname" : "Frexp",
"opcode" : 51,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" },
{ "kind" : "IdRef", "name" : "'exp'" }
]
},
{
"opname" : "FrexpStruct",
"opcode" : 52,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "Ldexp",
"opcode" : 53,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" },
{ "kind" : "IdRef", "name" : "'exp'" }
]
},
{
"opname" : "PackSnorm4x8",
"opcode" : 54,
"operands" : [
{ "kind" : "IdRef", "name" : "'v'" }
]
},
{
"opname" : "PackUnorm4x8",
"opcode" : 55,
"operands" : [
{ "kind" : "IdRef", "name" : "'v'" }
]
},
{
"opname" : "PackSnorm2x16",
"opcode" : 56,
"operands" : [
{ "kind" : "IdRef", "name" : "'v'" }
]
},
{
"opname" : "PackUnorm2x16",
"opcode" : 57,
"operands" : [
{ "kind" : "IdRef", "name" : "'v'" }
]
},
{
"opname" : "PackHalf2x16",
"opcode" : 58,
"operands" : [
{ "kind" : "IdRef", "name" : "'v'" }
]
},
{
"opname" : "PackDouble2x32",
"opcode" : 59,
"operands" : [
{ "kind" : "IdRef", "name" : "'v'" }
],
"capabilities" : [ "Float64" ]
},
{
"opname" : "UnpackSnorm2x16",
"opcode" : 60,
"operands" : [
{ "kind" : "IdRef", "name" : "'p'" }
]
},
{
"opname" : "UnpackUnorm2x16",
"opcode" : 61,
"operands" : [
{ "kind" : "IdRef", "name" : "'p'" }
]
},
{
"opname" : "UnpackHalf2x16",
"opcode" : 62,
"operands" : [
{ "kind" : "IdRef", "name" : "'v'" }
]
},
{
"opname" : "UnpackSnorm4x8",
"opcode" : 63,
"operands" : [
{ "kind" : "IdRef", "name" : "'p'" }
]
},
{
"opname" : "UnpackUnorm4x8",
"opcode" : 64,
"operands" : [
{ "kind" : "IdRef", "name" : "'p'" }
]
},
{
"opname" : "UnpackDouble2x32",
"opcode" : 65,
"operands" : [
{ "kind" : "IdRef", "name" : "'v'" }
],
"capabilities" : [ "Float64" ]
},
{
"opname" : "Length",
"opcode" : 66,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "Distance",
"opcode" : 67,
"operands" : [
{ "kind" : "IdRef", "name" : "'p0'" },
{ "kind" : "IdRef", "name" : "'p1'" }
]
},
{
"opname" : "Cross",
"opcode" : 68,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" },
{ "kind" : "IdRef", "name" : "'y'" }
]
},
{
"opname" : "Normalize",
"opcode" : 69,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" }
]
},
{
"opname" : "FaceForward",
"opcode" : 70,
"operands" : [
{ "kind" : "IdRef", "name" : "'N'" },
{ "kind" : "IdRef", "name" : "'I'" },
{ "kind" : "IdRef", "name" : "'Nref'" }
]
},
{
"opname" : "Reflect",
"opcode" : 71,
"operands" : [
{ "kind" : "IdRef", "name" : "'I'" },
{ "kind" : "IdRef", "name" : "'N'" }
]
},
{
"opname" : "Refract",
"opcode" : 72,
"operands" : [
{ "kind" : "IdRef", "name" : "'I'" },
{ "kind" : "IdRef", "name" : "'N'" },
{ "kind" : "IdRef", "name" : "'eta'" }
]
},
{
"opname" : "FindILsb",
"opcode" : 73,
"operands" : [
{ "kind" : "IdRef", "name" : "'Value'" }
]
},
{
"opname" : "FindSMsb",
"opcode" : 74,
"operands" : [
{ "kind" : "IdRef", "name" : "'Value'" }
]
},
{
"opname" : "FindUMsb",
"opcode" : 75,
"operands" : [
{ "kind" : "IdRef", "name" : "'Value'" }
]
},
{
"opname" : "InterpolateAtCentroid",
"opcode" : 76,
"operands" : [
{ "kind" : "IdRef", "name" : "'interpolant'" }
],
"capabilities" : [ "InterpolationFunction" ]
},
{
"opname" : "InterpolateAtSample",
"opcode" : 77,
"operands" : [
{ "kind" : "IdRef", "name" : "'interpolant'" },
{ "kind" : "IdRef", "name" : "'sample'" }
],
"capabilities" : [ "InterpolationFunction" ]
},
{
"opname" : "InterpolateAtOffset",
"opcode" : 78,
"operands" : [
{ "kind" : "IdRef", "name" : "'interpolant'" },
{ "kind" : "IdRef", "name" : "'offset'" }
],
"capabilities" : [ "InterpolationFunction" ]
},
{
"opname" : "NMin",
"opcode" : 79,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" },
{ "kind" : "IdRef", "name" : "'y'" }
]
},
{
"opname" : "NMax",
"opcode" : 80,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" },
{ "kind" : "IdRef", "name" : "'y'" }
]
},
{
"opname" : "NClamp",
"opcode" : 81,
"operands" : [
{ "kind" : "IdRef", "name" : "'x'" },
{ "kind" : "IdRef", "name" : "'minVal'" },
{ "kind" : "IdRef", "name" : "'maxVal'" }
]
}
]
}

View File

@@ -20,10 +20,14 @@
#define __GSK_H_INSIDE__
#include <gsk/gskcodesource.h>
#include <gsk/gskenums.h>
#include <gsk/gskpixelshader.h>
#include <gsk/gskrenderer.h>
#include <gsk/gskrendernode.h>
#include <gsk/gskroundedrect.h>
#include <gsk/gskslcompiler.h>
#include <gsk/gskslprogram.h>
#include <gsk/gsktexture.h>
#include <gsk/gsktypes.h>

152
gsk/gskcodesource.c Normal file
View File

@@ -0,0 +1,152 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gskcodesourceprivate.h"
struct _GskCodeSource {
GObject parent_instance;
char *name;
GFile *file;
GBytes *bytes;
};
G_DEFINE_TYPE (GskCodeSource, gsk_code_source, G_TYPE_OBJECT)
static void
gsk_code_source_dispose (GObject *object)
{
GskCodeSource *source = GSK_CODE_SOURCE (object);
g_free (source->name);
if (source->file)
g_object_unref (source->file);
if (source->bytes)
g_bytes_unref (source->bytes);
G_OBJECT_CLASS (gsk_code_source_parent_class)->dispose (object);
}
static void
gsk_code_source_class_init (GskCodeSourceClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = gsk_code_source_dispose;
}
static void
gsk_code_source_init (GskCodeSource *source)
{
}
const char *
gsk_code_source_get_name (GskCodeSource *source)
{
g_return_val_if_fail (GSK_IS_CODE_SOURCE (source), NULL);
return source->name;
}
GFile *
gsk_code_source_get_file (GskCodeSource *source)
{
g_return_val_if_fail (GSK_IS_CODE_SOURCE (source), NULL);
return source->file;
}
GskCodeSource *
gsk_code_source_new_for_bytes (const char *name,
GBytes *data)
{
GskCodeSource *result;
g_return_val_if_fail (name != NULL, NULL);
g_return_val_if_fail (data != NULL, NULL);
result = g_object_new (GSK_TYPE_CODE_SOURCE, NULL);
result->name = g_strdup (name);
result->bytes = g_bytes_ref (data);
return result;
}
static char *
get_name_for_file (GFile *file)
{
GFileInfo *info;
char *result;
info = g_file_query_info (file, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, 0, NULL, NULL);
if (info)
{
result = g_strdup (g_file_info_get_display_name (info));
g_object_unref (info);
}
else
{
result = g_strdup ("<broken file>");
}
return result;
}
GskCodeSource *
gsk_code_source_new_for_file (GFile *file)
{
GskCodeSource *result;
g_return_val_if_fail (G_IS_FILE (file), NULL);
result = g_object_new (GSK_TYPE_CODE_SOURCE, NULL);
result->file = g_object_ref (file);
result->name = get_name_for_file (file);
return result;
}
GBytes *
gsk_code_source_load (GskCodeSource *source,
GError **error)
{
gchar *data;
gsize length;
if (source->bytes)
return g_bytes_ref (source->bytes);
g_return_val_if_fail (source->file, NULL);
if (!g_file_load_contents (source->file,
NULL,
&data, &length,
NULL,
error))
return NULL;
source->bytes = g_bytes_new_take (data, length);
return g_bytes_ref (source->bytes);
}

41
gsk/gskcodesource.h Normal file
View File

@@ -0,0 +1,41 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_CODE_SOURCE_H__
#define __GSK_CODE_SOURCE_H__
#if !defined (__GSK_H_INSIDE__) && !defined (GSK_COMPILATION)
#error "Only <gsk/gsk.h> can be included directly."
#endif
#include <gsk/gsktypes.h>
G_BEGIN_DECLS
#define GSK_TYPE_CODE_SOURCE (gsk_code_source_get_type ())
G_DECLARE_FINAL_TYPE (GskCodeSource, gsk_code_source, GSK, CODE_SOURCE, GObject)
GDK_AVAILABLE_IN_3_92
const char * gsk_code_source_get_name (GskCodeSource *source);
GDK_AVAILABLE_IN_3_92
GFile * gsk_code_source_get_file (GskCodeSource *source);
G_END_DECLS
#endif /* __GSK_CODE_SOURCE_H__ */

View File

@@ -0,0 +1,35 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_CODE_SOURCE_PRIVATE_H__
#define __GSK_CODE_SOURCE_PRIVATE_H__
#include "gsk/gskcodesource.h"
G_BEGIN_DECLS
GskCodeSource * gsk_code_source_new_for_bytes (const char *name,
GBytes *data);
GskCodeSource * gsk_code_source_new_for_file (GFile *file);
GBytes * gsk_code_source_load (GskCodeSource *source,
GError **error);
G_END_DECLS
#endif /* __GSK_CODE_SOURCE_PRIVATE_H__ */

View File

@@ -175,4 +175,33 @@ typedef enum {
GSK_SERIALIZATION_INVALID_DATA
} GskSerializationError;
/**
* GskSlProfile:
* @GSK_SL_PROFILE_NONE: No profile has been selected. Behaves the same
* as @GSK_SL_PROFILE_CORE.
* @GSK_SL_PROFILE_CORE: The OpenGL core profile
* @GSK_SL_PROFILE_COMPATIBILITY: The OpenGL compatibility profile
* @GSK_SL_PROFILE_ES: The OpenGL-ES profile
*
* Profile to use for GLSL compilation.
**/
typedef enum {
GSK_SL_PROFILE_NONE,
GSK_SL_PROFILE_CORE,
GSK_SL_PROFILE_COMPATIBILITY,
GSK_SL_PROFILE_ES,
} GskSlProfile;
/**
* GskSlShaderStage:
* @GSK_SL_SHADER_VERTEX: The vertex shader stage
* @GSK_SL_SHADER_FRAGMENT: The fragment shader stage
*
* The shader stage associated with a GLSL program.
*/
typedef enum {
GSK_SL_SHADER_VERTEX,
GSK_SL_SHADER_FRAGMENT
} GskSlShaderStage;
#endif /* __GSK_TYPES_H__ */

189
gsk/gskpixelshader.c Normal file
View File

@@ -0,0 +1,189 @@
/* GSK - The GTK Scene Kit
*
* Copyright 2017 © Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/**
* SECTION:GskPixelShader
* @Title: GskPixelShader
* @Short_description: A pixel shader
*
* #GskPixelShader is the object used to create pixel shaders. The language
* used is GLSL with a few extensions.
*
* #GskPixelShader is an immutable object: That means you cannot change
* anything about it other than increasing the reference count via
* g_object_ref().
*/
#include "config.h"
#include "gskpixelshaderprivate.h"
#include "gskdebugprivate.h"
#include "gskslcompiler.h"
#include "gskslprogram.h"
#include "gdk/gdkinternals.h"
/**
* GskPixelShader:
*
* The `GskPixelShader` structure contains only private data.
*
* Since: 3.90
*/
enum {
PROP_0,
PROP_N_TEXTURES,
N_PROPS
};
static GParamSpec *properties[N_PROPS];
G_DEFINE_TYPE (GskPixelShader, gsk_pixel_shader, G_TYPE_OBJECT)
static void
gsk_pixel_shader_set_property (GObject *gobject,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
/* GskPixelShader *self = GSK_PIXEL_SHADER (gobject); */
switch (prop_id)
{
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
gsk_pixel_shader_get_property (GObject *gobject,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
GskPixelShader *self = GSK_PIXEL_SHADER (gobject);
switch (prop_id)
{
case PROP_N_TEXTURES:
g_value_set_uint (value, self->n_textures);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (gobject, prop_id, pspec);
break;
}
}
static void
gsk_pixel_shader_dispose (GObject *object)
{
GskPixelShader *self = GSK_PIXEL_SHADER (object);
g_object_unref (self->program);
G_OBJECT_CLASS (gsk_pixel_shader_parent_class)->dispose (object);
}
static void
gsk_pixel_shader_class_init (GskPixelShaderClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
gobject_class->set_property = gsk_pixel_shader_set_property;
gobject_class->get_property = gsk_pixel_shader_get_property;
gobject_class->dispose = gsk_pixel_shader_dispose;
/**
* GskPixelShader:n-textures:
*
* The number of input textures to the shader.
*
* Since: 3.92
*/
properties[PROP_N_TEXTURES] =
g_param_spec_uint ("n-textures",
"n textures",
"The number of input textures",
0,
G_MAXUINT,
0,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS |
G_PARAM_EXPLICIT_NOTIFY);
g_object_class_install_properties (gobject_class, N_PROPS, properties);
}
static void
gsk_pixel_shader_init (GskPixelShader *self)
{
}
GskPixelShader *
gsk_pixel_shader_new_for_data (GBytes *source,
GskShaderErrorFunc error_func,
gpointer error_data)
{
GskSlCompiler *compiler;
GskPixelShader *shader;
GskSlProgram *program;
g_return_val_if_fail (source != NULL, NULL);
compiler = gsk_sl_compiler_new ();
program = gsk_sl_compiler_compile_bytes (compiler, GSK_SL_SHADER_FRAGMENT, source);
g_object_unref (compiler);
if (program == NULL)
return NULL;
shader = g_object_new (GSK_TYPE_PIXEL_SHADER, NULL);
shader->program = program;
return shader;
}
void
gsk_pixel_shader_print (GskPixelShader *shader,
GString *string)
{
g_return_if_fail (GSK_IS_PIXEL_SHADER (shader));
g_return_if_fail (string != NULL);
gsk_sl_program_print (shader->program, string);
}
char *
gsk_pixel_shader_to_string (GskPixelShader *shader)
{
GString *string;
g_return_val_if_fail (GSK_IS_PIXEL_SHADER (shader), NULL);
string = g_string_new (NULL);
gsk_pixel_shader_print (shader, string);
return g_string_free (string, FALSE);
}

62
gsk/gskpixelshader.h Normal file
View File

@@ -0,0 +1,62 @@
/* GSK - The GTK Scene Kit
*
* Copyright 2017 © Benjamin Otte
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_PIXEL_SHADER_H__
#define __GSK_PIXEL_SHADER_H__
#if !defined (__GSK_H_INSIDE__) && !defined (GSK_COMPILATION)
#error "Only <gsk/gsk.h> can be included directly."
#endif
#include <gsk/gsktypes.h>
G_BEGIN_DECLS
#define GSK_TYPE_PIXEL_SHADER (gsk_pixel_shader_get_type ())
#define GSK_PIXEL_SHADER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GSK_TYPE_PIXEL_SHADER, GskPixelShader))
#define GSK_IS_PIXEL_SHADER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GSK_TYPE_PIXEL_SHADER))
typedef struct _GskPixelShaderClass GskPixelShaderClass;
typedef void (* GskShaderErrorFunc) (GskPixelShader *shader,
gboolean fatal,
const GskCodeLocation *location,
const GError *error,
gpointer user_data);
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GskPixelShader, g_object_unref)
GDK_AVAILABLE_IN_3_92
GType gsk_pixel_shader_get_type (void) G_GNUC_CONST;
GDK_AVAILABLE_IN_3_92
GskPixelShader * gsk_pixel_shader_new_for_data (GBytes *source,
GskShaderErrorFunc error_func,
gpointer error_data);
GDK_AVAILABLE_IN_3_92
void gsk_pixel_shader_print (GskPixelShader *shader,
GString *string);
GDK_AVAILABLE_IN_3_92
char * gsk_pixel_shader_to_string (GskPixelShader *shader);
G_END_DECLS
#endif /* __GSK_PIXEL_SHADER_H__ */

View File

@@ -0,0 +1,27 @@
#ifndef __GSK_PIXEL_SHADER_PRIVATE_H__
#define __GSK_PIXEL_SHADER_PRIVATE_H__
#include "gskpixelshader.h"
G_BEGIN_DECLS
#define GSK_PIXEL_SHADER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GSK_TYPE_TEXTURE, GskPixelShaderClass))
#define GSK_IS_TEXTURE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GSK_TYPE_TEXTURE))
#define GSK_PIXEL_SHADER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GSK_TYPE_TEXTURE, GskPixelShaderClass))
struct _GskPixelShader
{
GObject parent_instance;
GskSlProgram *program;
guint n_textures;
};
struct _GskPixelShaderClass {
GObjectClass parent_class;
};
G_END_DECLS
#endif /* __GSK_PIXEL_SHADER_PRIVATE_H__ */

2230
gsk/gskslbinary.c Normal file

File diff suppressed because it is too large Load Diff

52
gsk/gskslbinaryprivate.h Normal file
View File

@@ -0,0 +1,52 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_SL_BINARY_PRIVATE_H__
#define __GSK_SL_BINARY_PRIVATE_H__
#include "gsk/gsksltypesprivate.h"
#include "gsk/gsksltokenizerprivate.h"
G_BEGIN_DECLS
typedef struct _GskSlBinary GskSlBinary;
const GskSlBinary * gsk_sl_binary_get_for_token (GskSlTokenType token);
const char * gsk_sl_binary_get_sign (const GskSlBinary *binary);
GskSlType * gsk_sl_binary_check_type (const GskSlBinary *binary,
GskSlPreprocessor *stream,
GskSlType *ltype,
GskSlType *rtype);
GskSlValue * gsk_sl_binary_get_constant (const GskSlBinary *binary,
GskSlType *type,
GskSlValue *lvalue,
GskSlValue *rvalue);
guint32 gsk_sl_binary_write_spv (const GskSlBinary *binary,
GskSpvWriter *writer,
GskSlType *type,
GskSlType *ltype,
guint32 left_id,
GskSlType *rtype,
guint32 right_id);
G_END_DECLS
#endif /* __GSK_SL_BINARY_PRIVATE_H__ */

300
gsk/gskslcompiler.c Normal file
View File

@@ -0,0 +1,300 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gskslcompilerprivate.h"
#include "gskcodesourceprivate.h"
#include "gsksldefineprivate.h"
#include "gskslenvironmentprivate.h"
#include "gskslpreprocessorprivate.h"
#include "gskslprogramprivate.h"
#include "gsksltokenizerprivate.h"
struct _GskSlCompiler {
GObject parent_instance;
GHashTable *defines;
};
G_DEFINE_QUARK (gsk-sl-compiler-error-quark, gsk_sl_compiler_error)
G_DEFINE_QUARK (gsk-sl-compiler-warning-quark, gsk_sl_compiler_warning)
G_DEFINE_TYPE (GskSlCompiler, gsk_sl_compiler, G_TYPE_OBJECT)
static void
gsk_sl_compiler_dispose (GObject *object)
{
GskSlCompiler *compiler = GSK_SL_COMPILER (object);
g_hash_table_destroy (compiler->defines);
G_OBJECT_CLASS (gsk_sl_compiler_parent_class)->dispose (object);
}
static void
gsk_sl_compiler_class_init (GskSlCompilerClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = gsk_sl_compiler_dispose;
}
static void
gsk_sl_compiler_init (GskSlCompiler *compiler)
{
compiler->defines = g_hash_table_new_full (g_str_hash, g_str_equal,
NULL, (GDestroyNotify) gsk_sl_define_unref);
}
GskSlCompiler *
gsk_sl_compiler_new (void)
{
return g_object_new (GSK_TYPE_SL_COMPILER, NULL);
}
static void
gsk_sl_compiler_add_define_error_func (GskSlTokenizer *parser,
gboolean fatal,
const GskCodeLocation *location,
const GskSlToken *token,
const GError *error,
gpointer user_data)
{
GError **real_error = user_data;
if (!fatal)
return;
if (*real_error)
return;
*real_error = g_error_copy (error);
g_prefix_error (real_error,
"%3zu:%2zu: ",
location->lines + 1,
location->line_bytes);
}
gboolean
gsk_sl_compiler_add_define (GskSlCompiler *compiler,
const char *name,
const char *definition,
GError **error)
{
GskSlTokenizer *tokenizer;
GskSlDefine *define;
GskCodeLocation location;
GskSlToken token = { 0, };
GError *real_error = NULL;
GskCodeSource *source;
GBytes *bytes;
g_return_val_if_fail (GSK_IS_SL_COMPILER (compiler), FALSE);
g_return_val_if_fail (name != NULL, FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
if (!gsk_sl_string_is_valid_identifier (name))
{
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_FAILED, "Define name \"%s\" is not a valid identifier", name);
return FALSE;
}
if (definition == NULL)
definition = "1";
define = gsk_sl_define_new (name, NULL);
bytes = g_bytes_new_static (definition, strlen (definition));
source = gsk_code_source_new_for_bytes ("<define>", bytes);
tokenizer = gsk_sl_tokenizer_new (source,
gsk_sl_compiler_add_define_error_func,
&real_error,
NULL);
while (TRUE)
{
do
{
gsk_sl_token_clear (&token);
location = *gsk_sl_tokenizer_get_location (tokenizer);
gsk_sl_tokenizer_read_token (tokenizer, &token);
}
while (gsk_sl_token_is_skipped (&token));
if (gsk_sl_token_is (&token, GSK_SL_TOKEN_EOF))
break;
gsk_sl_define_add_token (define, &location, &token);
}
gsk_sl_token_clear (&token);
gsk_sl_tokenizer_unref (tokenizer);
g_bytes_unref (bytes);
g_object_unref (source);
if (real_error == NULL)
{
g_hash_table_replace (compiler->defines, (gpointer) gsk_sl_define_get_name (define), define);
return TRUE;
}
else
{
gsk_sl_define_unref (define);
g_propagate_error (error, real_error);
return FALSE;
}
}
void
gsk_sl_compiler_remove_define (GskSlCompiler *compiler,
const char *name)
{
g_return_if_fail (GSK_IS_SL_COMPILER (compiler));
g_return_if_fail (name != NULL);
g_hash_table_remove (compiler->defines, name);
}
GHashTable *
gsk_sl_compiler_copy_defines (GskSlCompiler *compiler)
{
GHashTable *copy;
GHashTableIter iter;
gpointer key, value;
copy = g_hash_table_new_full (g_str_hash, g_str_equal,
NULL, (GDestroyNotify) gsk_sl_define_unref);
g_hash_table_iter_init (&iter, compiler->defines);
while (g_hash_table_iter_next (&iter, &key, &value))
{
g_hash_table_replace (copy, key, gsk_sl_define_ref (value));
}
return copy;
}
GskCodeSource *
gsk_sl_compiler_resolve_include (GskSlCompiler *compiler,
GskCodeSource *source,
gboolean local,
const char *name,
GError **error)
{
GskCodeSource *result;
GBytes *bytes;
if (local)
{
GFile *source_file = gsk_code_source_get_file (source);
if (source_file)
{
GFile *parent, *file;
parent = g_file_get_parent (source_file);
file = g_file_resolve_relative_path (parent, name);
result = gsk_code_source_new_for_file (file);
g_object_unref (parent);
g_object_unref (file);
bytes = gsk_code_source_load (result, error);
if (bytes)
{
g_bytes_unref (bytes);
return result;
}
g_object_unref (result);
}
}
else
{
g_set_error (error, G_FILE_ERROR, G_FILE_ERROR_EXIST,
"Could not resolve \"%s\" in search path.", name);
}
return NULL;
}
static GskSlProgram *
gsk_sl_compiler_compile (GskSlCompiler *compiler,
GskSlShaderStage stage,
GskCodeSource *source)
{
GskSlPreprocessor *preproc;
GskSlEnvironment *environment;
GskSlProgram *program;
program = g_object_new (GSK_TYPE_SL_PROGRAM, NULL);
environment = gsk_sl_environment_new (stage, GSK_SL_PROFILE_CORE, 150);
preproc = gsk_sl_preprocessor_new (compiler, environment, source);
gsk_sl_environment_unref (environment);
gsk_sl_program_parse (program, preproc);
if (gsk_sl_preprocessor_has_fatal_error (preproc))
{
g_object_unref (program);
program = NULL;
}
gsk_sl_preprocessor_unref (preproc);
return program;
}
GskSlProgram *
gsk_sl_compiler_compile_file (GskSlCompiler *compiler,
GskSlShaderStage stage,
GFile *file)
{
GskSlProgram *program;
GskCodeSource *source;
g_return_val_if_fail (GSK_IS_SL_COMPILER (compiler), NULL);
g_return_val_if_fail (G_IS_FILE (file), NULL);
source = gsk_code_source_new_for_file (file);
program = gsk_sl_compiler_compile (compiler, stage, source);
g_object_unref (source);
return program;
}
GskSlProgram *
gsk_sl_compiler_compile_bytes (GskSlCompiler *compiler,
GskSlShaderStage stage,
GBytes *bytes)
{
GskSlProgram *program;
GskCodeSource *source;
g_return_val_if_fail (GSK_IS_SL_COMPILER (compiler), NULL);
g_return_val_if_fail (bytes != NULL, NULL);
source = gsk_code_source_new_for_bytes ("<program>", bytes);
program = gsk_sl_compiler_compile (compiler, stage, source);
g_object_unref (source);
return program;
}

88
gsk/gskslcompiler.h Normal file
View File

@@ -0,0 +1,88 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_SL_COMPILER_H__
#define __GSK_SL_COMPILER_H__
#if !defined (__GSK_H_INSIDE__) && !defined (GSK_COMPILATION)
#error "Only <gsk/gsk.h> can be included directly."
#endif
#include <gsk/gsktypes.h>
G_BEGIN_DECLS
typedef enum {
GSK_SL_COMPILER_ERROR_ARGUMENT_COUNT,
GSK_SL_COMPILER_ERROR_CONSTANT,
GSK_SL_COMPILER_ERROR_DECLARATION,
GSK_SL_COMPILER_ERROR_PREPROCESSOR,
GSK_SL_COMPILER_ERROR_RANGE,
GSK_SL_COMPILER_ERROR_SCOPE,
GSK_SL_COMPILER_ERROR_SYNTAX,
GSK_SL_COMPILER_ERROR_TOKENIZER,
GSK_SL_COMPILER_ERROR_TYPE_MISMATCH,
GSK_SL_COMPILER_ERROR_UNIQUENESS,
GSK_SL_COMPILER_ERROR_UNSUPPORTED,
} GskSlCompilerError;
typedef enum {
GSK_SL_COMPILER_WARNING_ARRAY_OF_ARRAY,
GSK_SL_COMPILER_WARNING_CONSTANT,
GSK_SL_COMPILER_WARNING_DEAD_CODE,
GSK_SL_COMPILER_WARNING_SHADOW,
GSK_SL_COMPILER_WARNING_UNIMPLEMENTED,
GSK_SL_COMPILER_WARNING_VERSION
} GskSlCompilerWarning;
#define GSK_SL_COMPILER_ERROR (gsk_sl_compiler_error_quark ())
#define GSK_SL_COMPILER_WARNING (gsk_sl_compiler_warning_quark ())
#define GSK_TYPE_SL_COMPILER (gsk_sl_compiler_get_type ())
G_DECLARE_FINAL_TYPE (GskSlCompiler, gsk_sl_compiler, GSK, SL_COMPILER, GObject)
GDK_AVAILABLE_IN_3_92
GQuark gsk_sl_compiler_error_quark (void);
GDK_AVAILABLE_IN_3_92
GQuark gsk_sl_compiler_warning_quark (void);
GDK_AVAILABLE_IN_3_92
GskSlCompiler * gsk_sl_compiler_new (void);
GDK_AVAILABLE_IN_3_92
gboolean gsk_sl_compiler_add_define (GskSlCompiler *compiler,
const char *name,
const char *definition,
GError **error);
GDK_AVAILABLE_IN_3_92
void gsk_sl_compiler_remove_define (GskSlCompiler *compiler,
const char *name);
GDK_AVAILABLE_IN_3_92
GskSlProgram * gsk_sl_compiler_compile_file (GskSlCompiler *compiler,
GskSlShaderStage stage,
GFile *file);
GDK_AVAILABLE_IN_3_92
GskSlProgram * gsk_sl_compiler_compile_bytes (GskSlCompiler *compiler,
GskSlShaderStage stage,
GBytes *bytes);
G_END_DECLS
#endif /* __GSK_SL_COMPILER_H__ */

View File

@@ -0,0 +1,36 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_SL_COMPILER_PRIVATE_H__
#define __GSK_SL_COMPILER_PRIVATE_H__
#include "gsk/gskslcompiler.h"
G_BEGIN_DECLS
GHashTable * gsk_sl_compiler_copy_defines (GskSlCompiler *compiler);
GskCodeSource * gsk_sl_compiler_resolve_include (GskSlCompiler *compiler,
GskCodeSource *source,
gboolean local,
const char *name,
GError **error);
G_END_DECLS
#endif /* __GSK_SL_COMPILER_PRIVATE_H__ */

549
gsk/gsksldeclaration.c Normal file
View File

@@ -0,0 +1,549 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gsksldeclarationprivate.h"
#include "gskslexpressionprivate.h"
#include "gskslfunctionprivate.h"
#include "gskslpreprocessorprivate.h"
#include "gskslprinterprivate.h"
#include "gskslscopeprivate.h"
#include "gsksltokenizerprivate.h"
#include "gsksltypeprivate.h"
#include "gskslqualifierprivate.h"
#include "gskslvalueprivate.h"
#include "gskslvariableprivate.h"
#include "gskspvwriterprivate.h"
#include <string.h>
typedef struct _GskSlDeclarationClass GskSlDeclarationClass;
struct _GskSlDeclaration {
const GskSlDeclarationClass *class;
guint ref_count;
};
struct _GskSlDeclarationClass {
gsize element_size;
void (* finalize) (GskSlDeclaration *declaration);
void (* print) (const GskSlDeclaration *declaration,
GskSlPrinter *printer);
void (* write_initializer_spv) (const GskSlDeclaration *declaration,
GskSpvWriter *writer);
};
static gpointer
gsk_sl_declaration_new (const GskSlDeclarationClass *klass)
{
GskSlDeclaration *declaration;
declaration = g_slice_alloc0 (klass->element_size);
declaration->class = klass;
declaration->ref_count = 1;
return declaration;
}
/* VARIABLE */
typedef struct _GskSlDeclarationVariable GskSlDeclarationVariable;
struct _GskSlDeclarationVariable {
GskSlDeclaration parent;
GskSlVariable *variable;
GskSlExpression *initial;
};
static void
gsk_sl_declaration_variable_finalize (GskSlDeclaration *declaration)
{
GskSlDeclarationVariable *variable = (GskSlDeclarationVariable *) declaration;
gsk_sl_variable_unref (variable->variable);
if (variable->initial)
gsk_sl_expression_unref (variable->initial);
}
static void
gsk_sl_declaration_variable_print (const GskSlDeclaration *declaration,
GskSlPrinter *printer)
{
GskSlDeclarationVariable *variable = (GskSlDeclarationVariable *) declaration;
gsk_sl_variable_print (variable->variable, printer);
if (variable->initial)
{
gsk_sl_printer_append (printer, " = ");
gsk_sl_expression_print (variable->initial, printer);
}
gsk_sl_printer_append (printer, ";");
gsk_sl_printer_newline (printer);
}
static void
gsk_sl_declaration_variable_write_initializer_spv (const GskSlDeclaration *declaration,
GskSpvWriter *writer)
{
GskSlDeclarationVariable *variable = (GskSlDeclarationVariable *) declaration;
/* make sure it's written */
gsk_spv_writer_get_id_for_variable (writer, variable->variable);
if (variable->initial && ! gsk_sl_variable_get_initial_value (variable->variable))
{
GskSpvAccessChain *chain = gsk_sl_variable_get_access_chain (variable->variable, writer);
g_assert (chain); /* code further up should make sure this never happens */
gsk_spv_access_chain_store (chain,
gsk_sl_expression_write_spv (variable->initial,
writer,
gsk_sl_variable_get_type (variable->variable)));
gsk_spv_access_chain_free (chain);
}
}
static const GskSlDeclarationClass GSK_SL_DECLARATION_VARIABLE = {
sizeof (GskSlDeclarationVariable),
gsk_sl_declaration_variable_finalize,
gsk_sl_declaration_variable_print,
gsk_sl_declaration_variable_write_initializer_spv
};
/* TYPE */
typedef struct _GskSlDeclarationType GskSlDeclarationType;
struct _GskSlDeclarationType {
GskSlDeclaration parent;
GskSlQualifier qualifier;
GskSlType *type;
};
static void
gsk_sl_declaration_type_finalize (GskSlDeclaration *declaration)
{
GskSlDeclarationType *type = (GskSlDeclarationType *) declaration;
gsk_sl_type_unref (type->type);
}
static void
gsk_sl_declaration_type_print (const GskSlDeclaration *declaration,
GskSlPrinter *printer)
{
GskSlDeclarationType *type = (GskSlDeclarationType *) declaration;
if (gsk_sl_qualifier_print (&type->qualifier, printer))
gsk_sl_printer_append (printer, " ");
gsk_sl_printer_append (printer, gsk_sl_type_get_name (type->type));
gsk_sl_printer_append (printer, ";");
gsk_sl_printer_newline (printer);
}
static void
gsk_sl_declaration_type_write_initializer_spv (const GskSlDeclaration *declaration,
GskSpvWriter *writer)
{
/* This declaration is only relevant for printing as it just declares a type */
}
static const GskSlDeclarationClass GSK_SL_DECLARATION_TYPE = {
sizeof (GskSlDeclarationType),
gsk_sl_declaration_type_finalize,
gsk_sl_declaration_type_print,
gsk_sl_declaration_type_write_initializer_spv
};
/* FUNCTION */
typedef struct _GskSlDeclarationFunction GskSlDeclarationFunction;
struct _GskSlDeclarationFunction {
GskSlDeclaration parent;
GskSlFunction *function;
};
static void
gsk_sl_declaration_function_free (GskSlDeclaration *declaration)
{
GskSlDeclarationFunction *function = (GskSlDeclarationFunction *) declaration;
gsk_sl_function_unref (function->function);
}
static void
gsk_sl_declaration_function_print (const GskSlDeclaration *declaration,
GskSlPrinter *printer)
{
GskSlDeclarationFunction *function = (GskSlDeclarationFunction *) declaration;
gsk_sl_function_print (function->function, printer);
}
static void
gsk_sl_declaration_function_write_initializer_spv (const GskSlDeclaration *declaration,
GskSpvWriter *writer)
{
/* functions are written out as-needed, so no need to force it */
}
static const GskSlDeclarationClass GSK_SL_DECLARATION_FUNCTION = {
sizeof (GskSlDeclarationFunction),
gsk_sl_declaration_function_free,
gsk_sl_declaration_function_print,
gsk_sl_declaration_function_write_initializer_spv
};
/* API */
static GskSlType *
gsk_sl_declaration_parse_block_type (GskSlScope *scope,
GskSlPreprocessor *preproc)
{
GskSlType *type;
const GskSlToken *token;
GskSlTypeBuilder *builder;
token = gsk_sl_preprocessor_get (preproc);
if (gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER))
{
builder = gsk_sl_type_builder_new_block (token->str);
gsk_sl_preprocessor_consume (preproc, NULL);
}
else
{
gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected block name.");
return gsk_sl_type_ref (gsk_sl_type_get_scalar (GSK_SL_FLOAT));
}
token = gsk_sl_preprocessor_get (preproc);
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_LEFT_BRACE))
{
gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected opening \"{\" after block declaration.");
goto out;
}
gsk_sl_preprocessor_consume (preproc, NULL);
for (token = gsk_sl_preprocessor_get (preproc);
!gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_BRACE) && !gsk_sl_token_is (token, GSK_SL_TOKEN_EOF);
token = gsk_sl_preprocessor_get (preproc))
{
type = gsk_sl_type_new_parse (scope, preproc);
while (TRUE)
{
token = gsk_sl_preprocessor_get (preproc);
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER))
{
gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected identifier for type name.");
break;
}
if (gsk_sl_type_builder_has_member (builder, token->str))
gsk_sl_preprocessor_error (preproc, DECLARATION, "Duplicate block member name \"%s\".", token->str);
else
gsk_sl_type_builder_add_member (builder, type, token->str);
gsk_sl_preprocessor_consume (preproc, NULL);
token = gsk_sl_preprocessor_get (preproc);
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_COMMA))
break;
gsk_sl_preprocessor_consume (preproc, NULL);
}
gsk_sl_type_unref (type);
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_SEMICOLON))
gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected semicolon after block member declaration.");
else
gsk_sl_preprocessor_consume (preproc, NULL);
}
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_BRACE))
{
gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected closing \"}\" after block declaration.");
gsk_sl_preprocessor_sync (preproc, GSK_SL_TOKEN_RIGHT_BRACE);
}
gsk_sl_preprocessor_consume (preproc, NULL);
out:
return gsk_sl_type_builder_free (builder);
}
static GskSlDeclaration *
gsk_sl_declaration_parse_block (GskSlScope *scope,
GskSlPreprocessor *preproc,
const GskSlQualifier *qualifier)
{
GskSlDeclarationVariable *variable;
const GskSlToken *token;
GskSlType *type;
type = gsk_sl_declaration_parse_block_type (scope, preproc);
token = gsk_sl_preprocessor_get (preproc);
if (gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER))
{
char *name;
name = g_strdup (token->str);
gsk_sl_preprocessor_consume (preproc, NULL);
type = gsk_sl_type_parse_array (type, scope, preproc);
gsk_sl_qualifier_check_type (qualifier, preproc, type);
variable = gsk_sl_declaration_new (&GSK_SL_DECLARATION_VARIABLE);
variable->variable = gsk_sl_variable_new (name, type, qualifier, NULL);
gsk_sl_scope_try_add_variable (scope, preproc, variable->variable);
token = gsk_sl_preprocessor_get (preproc);
}
else
{
gsize i;
gsk_sl_qualifier_check_type (qualifier, preproc, type);
variable = gsk_sl_declaration_new (&GSK_SL_DECLARATION_VARIABLE);
variable->variable = gsk_sl_variable_new (NULL, type, qualifier, NULL);
for (i = 0; i < gsk_sl_type_get_n_members (type); i++)
{
GskSlVariable *sub;
sub = gsk_sl_variable_new_block_member (variable->variable, i);
gsk_sl_scope_try_add_variable (scope, preproc, sub);
gsk_sl_variable_unref (sub);
}
}
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_SEMICOLON))
{
gsk_sl_preprocessor_error (preproc, SYNTAX, "No semicolon at end of variable declaration.");
gsk_sl_preprocessor_sync (preproc, GSK_SL_TOKEN_SEMICOLON);
}
gsk_sl_preprocessor_consume (preproc, NULL);
return &variable->parent;
}
static GskSlDeclaration *
gsk_sl_declaration_parse_variable (GskSlScope *scope,
GskSlPreprocessor *preproc,
const GskSlQualifier *qualifier,
GskSlType *base_type,
const char *name)
{
GskSlDeclarationVariable *variable;
GskSlValue *initial_value = NULL;
GskSlExpression *initial = NULL;
GskSlType *type;
const GskSlToken *token;
type = gsk_sl_type_ref (base_type);
type = gsk_sl_type_parse_array (type, scope, preproc);
gsk_sl_qualifier_check_type (qualifier, preproc, type);
token = gsk_sl_preprocessor_get (preproc);
if (gsk_sl_token_is (token, GSK_SL_TOKEN_EQUAL))
{
gsk_sl_preprocessor_consume (preproc, NULL);
initial = gsk_sl_expression_parse_initializer (scope, preproc, type);
if (!gsk_sl_type_can_convert (type, gsk_sl_expression_get_return_type (initial)))
{
gsk_sl_preprocessor_error (preproc, TYPE_MISMATCH,
"Cannot convert from initializer type %s to variable type %s",
gsk_sl_type_get_name (gsk_sl_expression_get_return_type (initial)),
gsk_sl_type_get_name (type));
gsk_sl_expression_unref (initial);
initial = NULL;
}
else
{
GskSlValue *unconverted = gsk_sl_expression_get_constant (initial);
if (unconverted)
{
initial_value = gsk_sl_value_new_convert (unconverted, type);
gsk_sl_value_free (unconverted);
}
}
token = gsk_sl_preprocessor_get (preproc);
}
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_SEMICOLON))
{
gsk_sl_preprocessor_error (preproc, SYNTAX, "No semicolon at end of variable declaration.");
gsk_sl_preprocessor_sync (preproc, GSK_SL_TOKEN_SEMICOLON);
}
gsk_sl_preprocessor_consume (preproc, NULL);
if (qualifier->storage == GSK_SL_STORAGE_GLOBAL_CONST &&
initial_value == NULL)
{
gsk_sl_preprocessor_error (preproc, DECLARATION, "Variables with \"const\" qualifier must be initialized with a constant value.");
initial_value = gsk_sl_value_new (type);
}
variable = gsk_sl_declaration_new (&GSK_SL_DECLARATION_VARIABLE);
variable->variable = gsk_sl_variable_new (name, type, qualifier, initial_value);
variable->initial = initial;
gsk_sl_scope_try_add_variable (scope, preproc, variable->variable);
gsk_sl_type_unref (type);
return &variable->parent;
}
GskSlDeclaration *
gsk_sl_declaration_parse (GskSlScope *scope,
GskSlPreprocessor *preproc)
{
GskSlDeclaration *result;
GskSlType *type;
const GskSlToken *token;
GskSlQualifier qualifier;
char *name;
gsk_sl_qualifier_parse (&qualifier, scope, preproc, GSK_SL_QUALIFIER_GLOBAL);
token = gsk_sl_preprocessor_get (preproc);
if (gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER))
{
type = gsk_sl_scope_lookup_type (scope, token->str);
if (type == NULL)
return gsk_sl_declaration_parse_block (scope, preproc, &qualifier);
gsk_sl_type_ref (type);
gsk_sl_preprocessor_consume (preproc, NULL);
}
else
{
type = gsk_sl_type_new_parse (scope, preproc);
}
token = gsk_sl_preprocessor_get (preproc);
if (gsk_sl_token_is (token, GSK_SL_TOKEN_SEMICOLON))
{
GskSlDeclarationType *type_decl = gsk_sl_declaration_new (&GSK_SL_DECLARATION_TYPE);
type_decl->qualifier = qualifier;
type_decl->type = type;
gsk_sl_preprocessor_consume (preproc, type_decl);
return &type_decl->parent;
}
else if (!gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER))
{
gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected a variable name");
gsk_sl_preprocessor_consume (preproc, NULL);
gsk_sl_type_unref (type);
return NULL;
}
name = g_strdup (token->str);
gsk_sl_preprocessor_consume (preproc, NULL);
token = gsk_sl_preprocessor_get (preproc);
if (gsk_sl_token_is (token, GSK_SL_TOKEN_LEFT_PAREN))
{
GskSlFunctionMatcher matcher;
GskSlDeclarationFunction *function;
function = gsk_sl_declaration_new (&GSK_SL_DECLARATION_FUNCTION);
function->function = gsk_sl_function_new_parse (scope,
preproc,
type,
name);
gsk_sl_scope_match_function (scope, &matcher, gsk_sl_function_get_name (function->function));
gsk_sl_function_matcher_match_function (&matcher, function->function);
if (gsk_sl_function_matcher_has_matches (&matcher))
gsk_sl_preprocessor_error (preproc, DECLARATION, "A function with the same prototype has already been defined.");
else
gsk_sl_scope_add_function (scope, function->function);
gsk_sl_function_matcher_finish (&matcher);
result = &function->parent;
}
else
{
result = gsk_sl_declaration_parse_variable (scope, preproc, &qualifier, type, name);
}
g_free (name);
gsk_sl_type_unref (type);
return result;
}
GskSlDeclaration *
gsk_sl_declaration_ref (GskSlDeclaration *declaration)
{
g_return_val_if_fail (declaration != NULL, NULL);
declaration->ref_count += 1;
return declaration;
}
void
gsk_sl_declaration_unref (GskSlDeclaration *declaration)
{
if (declaration == NULL)
return;
declaration->ref_count -= 1;
if (declaration->ref_count > 0)
return;
declaration->class->finalize (declaration);
g_slice_free1 (declaration->class->element_size, declaration);
}
GskSlFunction *
gsk_sl_declaration_get_function (GskSlDeclaration *declaration)
{
if (declaration->class != &GSK_SL_DECLARATION_FUNCTION)
return NULL;
return ((GskSlDeclarationFunction *) declaration)->function;
}
void
gsk_sl_declaration_print (const GskSlDeclaration *declaration,
GskSlPrinter *printer)
{
declaration->class->print (declaration, printer);
}
void
gsk_sl_declaration_write_initializer_spv (const GskSlDeclaration *declaration,
GskSpvWriter *writer)
{
declaration->class->write_initializer_spv (declaration, writer);
}

View File

@@ -0,0 +1,44 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_SL_DECLARATION_PRIVATE_H__
#define __GSK_SL_DECLARATION_PRIVATE_H__
#include <glib.h>
#include "gsk/gsksltypesprivate.h"
G_BEGIN_DECLS
GskSlDeclaration * gsk_sl_declaration_parse (GskSlScope *scope,
GskSlPreprocessor *preproc);
GskSlDeclaration * gsk_sl_declaration_ref (GskSlDeclaration *declaration);
void gsk_sl_declaration_unref (GskSlDeclaration *declaration);
GskSlFunction * gsk_sl_declaration_get_function (GskSlDeclaration *declaration);
void gsk_sl_declaration_print (const GskSlDeclaration *declaration,
GskSlPrinter *printer);
void gsk_sl_declaration_write_initializer_spv(const GskSlDeclaration *declaration,
GskSpvWriter *writer);
G_END_DECLS
#endif /* __GSK_SL_DECLARATION_PRIVATE_H__ */

132
gsk/gsksldefine.c Normal file
View File

@@ -0,0 +1,132 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gsksldefineprivate.h"
typedef struct _GskSlDefineToken GskSlDefineToken;
struct _GskSlDefineToken {
GskCodeLocation location;
GskSlToken token;
};
struct _GskSlDefine {
int ref_count;
char *name;
GFile *source_file;
GArray *tokens;
};
GskSlDefine *
gsk_sl_define_new (const char *name,
GFile *source_file)
{
GskSlDefine *result;
result = g_slice_new0 (GskSlDefine);
result->ref_count = 1;
result->name = g_strdup (name);
if (source_file)
result->source_file = g_object_ref (source_file);
result->tokens = g_array_new (FALSE, FALSE, sizeof (GskSlDefineToken));
return result;
}
GskSlDefine *
gsk_sl_define_ref (GskSlDefine *define)
{
g_return_val_if_fail (define != NULL, NULL);
define->ref_count += 1;
return define;
}
void
gsk_sl_define_unref (GskSlDefine *define)
{
if (define == NULL)
return;
define->ref_count -= 1;
if (define->ref_count > 0)
return;
g_array_free (define->tokens, TRUE);
if (define->source_file)
g_object_unref (define->source_file);
g_free (define->name);
g_slice_free (GskSlDefine, define);
}
const char *
gsk_sl_define_get_name (GskSlDefine *define)
{
return define->name;
}
GFile *
gsk_sl_define_get_source_file (GskSlDefine *define)
{
return define->source_file;
}
guint
gsk_sl_define_get_n_tokens (GskSlDefine *define)
{
return define->tokens->len;
}
void
gsk_sl_define_get_token (GskSlDefine *define,
guint i,
GskCodeLocation *location,
GskSlToken *token)
{
GskSlDefineToken *dt;
dt = &g_array_index (define->tokens, GskSlDefineToken, i);
if (location)
*location = dt->location;
if (token)
gsk_sl_token_copy (token, &dt->token);
}
void
gsk_sl_define_add_token (GskSlDefine *define,
const GskCodeLocation *location,
const GskSlToken *token)
{
GskSlDefineToken dt;
dt.location = *location;
gsk_sl_token_copy (&dt.token, token);
g_array_append_val (define->tokens, dt);
}

51
gsk/gsksldefineprivate.h Normal file
View File

@@ -0,0 +1,51 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_SL_DEFINE_PRIVATE_H__
#define __GSK_SL_DEFINE_PRIVATE_H__
#include <glib.h>
#include "gsksltokenizerprivate.h"
#include "gsksltypesprivate.h"
G_BEGIN_DECLS
typedef struct _GskSlDefine GskSlDefine;
GskSlDefine * gsk_sl_define_new (const char *name,
GFile *source_file);
GskSlDefine * gsk_sl_define_ref (GskSlDefine *define);
void gsk_sl_define_unref (GskSlDefine *define);
const char * gsk_sl_define_get_name (GskSlDefine *define);
GFile * gsk_sl_define_get_source_file (GskSlDefine *define);
guint gsk_sl_define_get_n_tokens (GskSlDefine *define);
void gsk_sl_define_get_token (GskSlDefine *define,
guint i,
GskCodeLocation *location,
GskSlToken *token);
void gsk_sl_define_add_token (GskSlDefine *define,
const GskCodeLocation *location,
const GskSlToken *token);
G_END_DECLS
#endif /* __GSK_SL_DEFINE_PRIVATE_H__ */

119
gsk/gskslenvironment.c Normal file
View File

@@ -0,0 +1,119 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gskslenvironmentprivate.h"
#include "gskslnativefunctionprivate.h"
#include "gskslnativevariableprivate.h"
#include "gskslscopeprivate.h"
#include <string.h>
struct _GskSlEnvironment
{
int ref_count;
GskSlShaderStage stage;
GskSlProfile profile;
guint version;
};
GskSlEnvironment *
gsk_sl_environment_new (GskSlShaderStage stage,
GskSlProfile profile,
guint version)
{
GskSlEnvironment *environment;
environment = g_slice_new0 (GskSlEnvironment);
environment->ref_count = 1;
environment->stage = stage;
environment->profile = profile;
environment->version = version;
return environment;
}
GskSlEnvironment *
gsk_sl_environment_new_similar (GskSlEnvironment *environment,
GskSlProfile profile,
guint version,
GError **error)
{
return gsk_sl_environment_new (environment->stage,
profile == GSK_SL_PROFILE_NONE ? environment->profile : profile,
version);
}
GskSlEnvironment *
gsk_sl_environment_ref (GskSlEnvironment *environment)
{
g_return_val_if_fail (environment != NULL, NULL);
environment->ref_count += 1;
return environment;
}
void
gsk_sl_environment_unref (GskSlEnvironment *environment)
{
if (environment == NULL)
return;
environment->ref_count -= 1;
if (environment->ref_count > 0)
return;
g_slice_free (GskSlEnvironment, environment);
}
GskSlShaderStage
gsk_sl_environment_get_stage (GskSlEnvironment *environment)
{
return environment->stage;
}
GskSlProfile
gsk_sl_environment_get_profile (GskSlEnvironment *environment)
{
return environment->profile;
}
guint
gsk_sl_environment_get_version (GskSlEnvironment *environment)
{
return environment->version;
}
GskSlScope *
gsk_sl_environment_create_scope (GskSlEnvironment *environment)
{
GskSlScope *scope;
scope = gsk_sl_scope_new (NULL, NULL);
gsk_sl_native_functions_add (scope, environment);
gsk_sl_native_variables_add (scope, environment);
return scope;
}

View File

@@ -0,0 +1,47 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_SL_ENVIRONMENT_PRIVATE_H__
#define __GSK_SL_ENVIRONMENT_PRIVATE_H__
#include <glib.h>
#include "gsksltypesprivate.h"
G_BEGIN_DECLS
GskSlEnvironment * gsk_sl_environment_new (GskSlShaderStage stage,
GskSlProfile profile,
guint version);
GskSlEnvironment * gsk_sl_environment_new_similar (GskSlEnvironment *environment,
GskSlProfile profile,
guint version,
GError **error);
GskSlEnvironment * gsk_sl_environment_ref (GskSlEnvironment *environment);
void gsk_sl_environment_unref (GskSlEnvironment *environment);
GskSlShaderStage gsk_sl_environment_get_stage (GskSlEnvironment *environment);
GskSlProfile gsk_sl_environment_get_profile (GskSlEnvironment *environment);
guint gsk_sl_environment_get_version (GskSlEnvironment *environment);
GskSlScope * gsk_sl_environment_create_scope (GskSlEnvironment *environment);
G_END_DECLS
#endif /* __GSK_SL_ENVIRONMENT_PRIVATE_H__ */

3955
gsk/gskslexpression.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,60 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_SL_EXPRESSION_PRIVATE_H__
#define __GSK_SL_EXPRESSION_PRIVATE_H__
#include "gsk/gsksltypesprivate.h"
G_BEGIN_DECLS
GskSlExpression * gsk_sl_expression_parse (GskSlScope *scope,
GskSlPreprocessor *stream);
GskSlExpression * gsk_sl_expression_parse_initializer (GskSlScope *scope,
GskSlPreprocessor *preproc,
GskSlType *type);
GskSlExpression * gsk_sl_expression_parse_constant (GskSlScope *scope,
GskSlPreprocessor *stream);
gint32 gsk_sl_expression_parse_integral_constant (GskSlScope *scope,
GskSlPreprocessor *preproc,
gint32 minimum,
guint32 maximum);
GskSlExpression * gsk_sl_expression_parse_constructor (GskSlScope *scope,
GskSlPreprocessor *stream,
GskSlType *type);
GskSlExpression * gsk_sl_expression_parse_function_call (GskSlScope *scope,
GskSlPreprocessor *stream,
GskSlFunctionMatcher *matcher);
GskSlExpression * gsk_sl_expression_ref (GskSlExpression *expression);
void gsk_sl_expression_unref (GskSlExpression *expression);
void gsk_sl_expression_print (const GskSlExpression *expression,
GskSlPrinter *printer);
gboolean gsk_sl_expression_is_assignable (const GskSlExpression *expression,
GError **error);
GskSlType * gsk_sl_expression_get_return_type (const GskSlExpression *expression);
GskSlValue * gsk_sl_expression_get_constant (const GskSlExpression *expression);
guint32 gsk_sl_expression_write_spv (const GskSlExpression *expression,
GskSpvWriter *writer,
GskSlType *result_type);
G_END_DECLS
#endif /* __GSK_SL_EXPRESSION_PRIVATE_H__ */

921
gsk/gskslfunction.c Normal file
View File

@@ -0,0 +1,921 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gskslfunctionprivate.h"
#include "gskslfunctiontypeprivate.h"
#include "gskslnativefunctionprivate.h"
#include "gskslpreprocessorprivate.h"
#include "gskslprinterprivate.h"
#include "gskslqualifierprivate.h"
#include "gskslscopeprivate.h"
#include "gskslstatementprivate.h"
#include "gsksltokenizerprivate.h"
#include "gsksltypeprivate.h"
#include "gskslvalueprivate.h"
#include "gskslvariableprivate.h"
#include "gskspvwriterprivate.h"
typedef struct _GskSlFunctionClass GskSlFunctionClass;
struct _GskSlFunction
{
const GskSlFunctionClass *class;
int ref_count;
};
struct _GskSlFunctionClass {
void (* free) (GskSlFunction *function);
GskSlType * (* get_return_type) (const GskSlFunction *function);
const char * (* get_name) (const GskSlFunction *function);
gsize (* get_n_arguments) (const GskSlFunction *function);
GskSlType * (* get_argument_type) (const GskSlFunction *function,
gsize i);
GskSlValue * (* get_constant) (const GskSlFunction *function,
GskSlValue **values,
gsize n_values);
void (* print) (const GskSlFunction *function,
GskSlPrinter *printer);
guint32 (* write_spv) (const GskSlFunction *function,
GskSpvWriter *writer,
GskSpvWriterFunc initializer,
gpointer initializer_data);
guint32 (* write_call_spv) (GskSlFunction *function,
GskSpvWriter *writer,
guint32 *arguments);
};
static GskSlFunction *
gsk_sl_function_alloc (const GskSlFunctionClass *klass,
gsize size)
{
GskSlFunction *function;
function = g_slice_alloc0 (size);
function->class = klass;
function->ref_count = 1;
return function;
}
#define gsk_sl_function_new(_name, _klass) ((_name *) gsk_sl_function_alloc ((_klass), sizeof (_name)))
/* CONSTRUCTOR */
typedef struct _GskSlFunctionConstructor GskSlFunctionConstructor;
struct _GskSlFunctionConstructor {
GskSlFunction parent;
GskSlType *type;
};
static void
gsk_sl_function_constructor_free (GskSlFunction *function)
{
GskSlFunctionConstructor *constructor = (GskSlFunctionConstructor *) function;
gsk_sl_type_unref (constructor->type);
g_slice_free (GskSlFunctionConstructor, constructor);
}
static GskSlType *
gsk_sl_function_constructor_get_return_type (const GskSlFunction *function)
{
const GskSlFunctionConstructor *constructor = (const GskSlFunctionConstructor *) function;
return constructor->type;
}
static const char *
gsk_sl_function_constructor_get_name (const GskSlFunction *function)
{
const GskSlFunctionConstructor *constructor = (const GskSlFunctionConstructor *) function;
return gsk_sl_type_get_name (constructor->type);
}
static gsize
gsk_sl_function_constructor_get_n_arguments (const GskSlFunction *function)
{
const GskSlFunctionConstructor *constructor = (const GskSlFunctionConstructor *) function;
return gsk_sl_type_get_n_members (constructor->type);
}
static GskSlType *
gsk_sl_function_constructor_get_argument_type (const GskSlFunction *function,
gsize i)
{
const GskSlFunctionConstructor *constructor = (const GskSlFunctionConstructor *) function;
return gsk_sl_type_get_member_type (constructor->type, i);
}
static GskSlValue *
gsk_sl_function_constructor_get_constant (const GskSlFunction *function,
GskSlValue **values,
gsize n_values)
{
return NULL;
}
static void
gsk_sl_function_constructor_print (const GskSlFunction *function,
GskSlPrinter *printer)
{
}
static guint32
gsk_sl_function_constructor_write_spv (const GskSlFunction *function,
GskSpvWriter *writer,
GskSpvWriterFunc initializer,
gpointer initializer_data)
{
g_assert (initializer == NULL);
return 0;
}
static guint32
gsk_sl_function_constructor_write_call_spv (GskSlFunction *function,
GskSpvWriter *writer,
guint32 *arguments)
{
const GskSlFunctionConstructor *constructor = (const GskSlFunctionConstructor *) function;
return gsk_spv_writer_composite_construct (writer,
constructor->type,
arguments,
gsk_sl_type_get_n_members (constructor->type));
}
static const GskSlFunctionClass GSK_SL_FUNCTION_CONSTRUCTOR = {
gsk_sl_function_constructor_free,
gsk_sl_function_constructor_get_return_type,
gsk_sl_function_constructor_get_name,
gsk_sl_function_constructor_get_n_arguments,
gsk_sl_function_constructor_get_argument_type,
gsk_sl_function_constructor_get_constant,
gsk_sl_function_constructor_print,
gsk_sl_function_constructor_write_spv,
gsk_sl_function_constructor_write_call_spv
};
/* NATIVE */
typedef struct _GskSlFunctionNative GskSlFunctionNative;
struct _GskSlFunctionNative {
GskSlFunction parent;
char *name;
GskSlFunctionType *type;
void (* get_constant) (gpointer *retval, gpointer *arguments, gpointer user_data);
guint32 (* write_spv) (GskSpvWriter *writer, guint32 *arguments, gpointer user_data);
gpointer user_data;
GDestroyNotify destroy;
};
static void
gsk_sl_function_native_free (GskSlFunction *function)
{
GskSlFunctionNative *native = (GskSlFunctionNative *) function;
if (native->destroy)
native->destroy (native->user_data);
gsk_sl_function_type_unref (native->type);
g_free (native->name);
g_slice_free (GskSlFunctionNative, native);
}
static GskSlType *
gsk_sl_function_native_get_return_type (const GskSlFunction *function)
{
const GskSlFunctionNative *native = (const GskSlFunctionNative *) function;
return gsk_sl_function_type_get_return_type (native->type);
}
static const char *
gsk_sl_function_native_get_name (const GskSlFunction *function)
{
const GskSlFunctionNative *native = (const GskSlFunctionNative *) function;
return native->name;
}
static gsize
gsk_sl_function_native_get_n_arguments (const GskSlFunction *function)
{
const GskSlFunctionNative *native = (const GskSlFunctionNative *) function;
return gsk_sl_function_type_get_n_arguments (native->type);
}
static GskSlType *
gsk_sl_function_native_get_argument_type (const GskSlFunction *function,
gsize i)
{
const GskSlFunctionNative *native = (const GskSlFunctionNative *) function;
return gsk_sl_function_type_get_argument_type (native->type, i);
}
static GskSlValue *
gsk_sl_function_native_get_constant (const GskSlFunction *function,
GskSlValue **values,
gsize n_values)
{
const GskSlFunctionNative *native = (const GskSlFunctionNative *) function;
gpointer data[gsk_sl_function_type_get_n_arguments (native->type)];
GskSlValue *result;
gsize i;
if (native->get_constant == NULL)
return NULL;
result = gsk_sl_value_new (gsk_sl_function_type_get_return_type (native->type));
for (i = 0; i < n_values; i++)
{
data[i] = gsk_sl_value_get_data (values[i]);
}
native->get_constant (gsk_sl_value_get_data (result),
data,
native->user_data);
return result;
}
static void
gsk_sl_function_native_print (const GskSlFunction *function,
GskSlPrinter *printer)
{
}
static guint32
gsk_sl_function_native_write_spv (const GskSlFunction *function,
GskSpvWriter *writer,
GskSpvWriterFunc initializer,
gpointer initializer_data)
{
g_assert (initializer == NULL);
return 0;
}
static guint32
gsk_sl_function_native_write_call_spv (GskSlFunction *function,
GskSpvWriter *writer,
guint32 *arguments)
{
const GskSlFunctionNative *native = (const GskSlFunctionNative *) function;
return native->write_spv (writer, arguments, native->user_data);
}
static const GskSlFunctionClass GSK_SL_FUNCTION_NATIVE = {
gsk_sl_function_native_free,
gsk_sl_function_native_get_return_type,
gsk_sl_function_native_get_name,
gsk_sl_function_native_get_n_arguments,
gsk_sl_function_native_get_argument_type,
gsk_sl_function_native_get_constant,
gsk_sl_function_native_print,
gsk_sl_function_native_write_spv,
gsk_sl_function_native_write_call_spv
};
/* DECLARED */
typedef struct _GskSlFunctionDeclared GskSlFunctionDeclared;
struct _GskSlFunctionDeclared {
GskSlFunction parent;
GskSlScope *scope;
char *name;
GskSlFunctionType *function_type;
GskSlVariable **arguments;
GskSlStatement *statement;
};
static void
gsk_sl_function_declared_free (GskSlFunction *function)
{
GskSlFunctionDeclared *declared = (GskSlFunctionDeclared *) function;
guint i;
for (i = 0; i < gsk_sl_function_type_get_n_arguments (declared->function_type); i++)
gsk_sl_variable_unref (declared->arguments[i]);
g_free (declared->arguments);
if (declared->scope)
gsk_sl_scope_unref (declared->scope);
gsk_sl_function_type_unref (declared->function_type);
g_free (declared->name);
if (declared->statement)
gsk_sl_statement_unref (declared->statement);
g_slice_free (GskSlFunctionDeclared, declared);
}
static GskSlType *
gsk_sl_function_declared_get_return_type (const GskSlFunction *function)
{
const GskSlFunctionDeclared *declared = (const GskSlFunctionDeclared *) function;
return gsk_sl_function_type_get_return_type (declared->function_type);
}
static const char *
gsk_sl_function_declared_get_name (const GskSlFunction *function)
{
const GskSlFunctionDeclared *declared = (const GskSlFunctionDeclared *) function;
return declared->name;
}
static gsize
gsk_sl_function_declared_get_n_arguments (const GskSlFunction *function)
{
const GskSlFunctionDeclared *declared = (const GskSlFunctionDeclared *) function;
return gsk_sl_function_type_get_n_arguments (declared->function_type);
}
static GskSlType *
gsk_sl_function_declared_get_argument_type (const GskSlFunction *function,
gsize i)
{
const GskSlFunctionDeclared *declared = (const GskSlFunctionDeclared *) function;
return gsk_sl_function_type_get_argument_type (declared->function_type, i);
}
static GskSlValue *
gsk_sl_function_declared_get_constant (const GskSlFunction *function,
GskSlValue **values,
gsize n_values)
{
return NULL;
}
static void
gsk_sl_function_declared_print (const GskSlFunction *function,
GskSlPrinter *printer)
{
const GskSlFunctionDeclared *declared = (const GskSlFunctionDeclared *) function;
guint i;
gsk_sl_printer_append (printer, gsk_sl_type_get_name (gsk_sl_function_type_get_return_type (declared->function_type)));
gsk_sl_printer_newline (printer);
gsk_sl_printer_append (printer, declared->name);
gsk_sl_printer_append (printer, " (");
for (i = 0; i < gsk_sl_function_type_get_n_arguments (declared->function_type); i++)
{
if (i > 0)
gsk_sl_printer_append (printer, ", ");
gsk_sl_variable_print (declared->arguments[i], printer);
}
gsk_sl_printer_append (printer, ")");
if (declared->statement)
{
gsk_sl_printer_newline (printer);
gsk_sl_statement_print (declared->statement, printer);
}
else
{
gsk_sl_printer_append (printer, ";");
}
gsk_sl_printer_newline (printer);
}
static guint32
gsk_sl_function_declared_write_spv (const GskSlFunction *function,
GskSpvWriter *writer,
GskSpvWriterFunc initializer,
gpointer initializer_data)
{
GskSlFunctionDeclared *declared = (GskSlFunctionDeclared *) function;
guint32 function_type_id, function_id, label_id;
GskSlType *return_type;
gsize i;
if (declared->statement == NULL)
return 0;
return_type = gsk_sl_function_type_get_return_type (declared->function_type);
/* declare type of function */
function_type_id = gsk_spv_writer_get_id_for_function_type (writer, declared->function_type);
function_id = gsk_spv_writer_function (writer, return_type, 0, function_type_id);
/* add function header */
for (i = 0; i < gsk_sl_function_type_get_n_arguments (declared->function_type); i++)
{
gsk_spv_writer_get_id_for_variable (writer, declared->arguments[i]);
}
/* add debug info */
gsk_spv_writer_name (writer, function_id, declared->name);
/* add function body */
label_id = gsk_spv_writer_make_id (writer);
gsk_spv_writer_start_code_block (writer, label_id, 0, 0);
gsk_spv_writer_label (writer, GSK_SPV_WRITER_SECTION_DECLARE, label_id);
if (initializer)
initializer (writer, initializer_data);
if (!gsk_sl_statement_write_spv (declared->statement, writer))
gsk_spv_writer_return (writer);
gsk_spv_writer_function_end (writer);
return function_id;
}
static guint32
gsk_sl_function_declared_write_call_spv (GskSlFunction *function,
GskSpvWriter *writer,
guint32 *arguments)
{
GskSlFunctionDeclared *declared = (GskSlFunctionDeclared *) function;
gsize n = gsk_sl_function_type_get_n_arguments (declared->function_type);
guint32 real_args[n];
guint32 result;
gsize i;
for (i = 0; i < gsk_sl_function_type_get_n_arguments (declared->function_type); i++)
{
if (gsk_sl_function_type_is_argument_const (declared->function_type, i))
{
real_args[i] = arguments[i];
}
else
{
real_args[i] = gsk_spv_writer_variable (writer,
GSK_SPV_WRITER_SECTION_DECLARE,
gsk_sl_function_type_get_argument_type (declared->function_type, i),
GSK_SPV_STORAGE_CLASS_FUNCTION,
GSK_SPV_STORAGE_CLASS_FUNCTION,
0);
if (gsk_sl_function_type_is_argument_in (declared->function_type, i))
{
gsk_spv_writer_store (writer, real_args[i], arguments[i], 0);
}
}
}
result = gsk_spv_writer_function_call (writer,
gsk_sl_function_type_get_return_type (declared->function_type),
gsk_spv_writer_get_id_for_function (writer, function),
real_args,
gsk_sl_function_type_get_n_arguments (declared->function_type));
return result;
}
static const GskSlFunctionClass GSK_SL_FUNCTION_DECLARED = {
gsk_sl_function_declared_free,
gsk_sl_function_declared_get_return_type,
gsk_sl_function_declared_get_name,
gsk_sl_function_declared_get_n_arguments,
gsk_sl_function_declared_get_argument_type,
gsk_sl_function_declared_get_constant,
gsk_sl_function_declared_print,
gsk_sl_function_declared_write_spv,
gsk_sl_function_declared_write_call_spv
};
/* API */
GskSlFunction *
gsk_sl_function_new_constructor (GskSlType *type)
{
if (gsk_sl_type_is_struct (type))
{
GskSlFunctionConstructor *constructor;
constructor = gsk_sl_function_new (GskSlFunctionConstructor, &GSK_SL_FUNCTION_CONSTRUCTOR);
constructor->type = gsk_sl_type_ref (type);
return &constructor->parent;
}
else
{
g_assert_not_reached ();
return NULL;
}
}
GskSlFunction *
gsk_sl_function_new_native (const char *name,
GskSlFunctionType *type,
void (* get_constant) (gpointer *retval, gpointer *arguments, gpointer user_data),
guint32 (* write_spv) (GskSpvWriter *writer, guint32 *arguments, gpointer user_data),
gpointer user_data,
GDestroyNotify destroy)
{
GskSlFunctionNative *function;
g_return_val_if_fail (name != NULL, NULL);
g_return_val_if_fail (write_spv != NULL, NULL);
function = gsk_sl_function_new (GskSlFunctionNative, &GSK_SL_FUNCTION_NATIVE);
function->name = g_strdup (name);
function->type = gsk_sl_function_type_ref (type);
function->get_constant = get_constant;
function->write_spv = write_spv;
function->user_data = user_data;
function->destroy = destroy;
return &function->parent;
}
GskSlFunction *
gsk_sl_function_new_parse (GskSlScope *scope,
GskSlPreprocessor *preproc,
GskSlType *return_type,
const char *name)
{
GskSlFunctionDeclared *function;
const GskSlToken *token;
function = gsk_sl_function_new (GskSlFunctionDeclared, &GSK_SL_FUNCTION_DECLARED);
function->function_type = gsk_sl_function_type_new (return_type);
function->name = g_strdup (name);
token = gsk_sl_preprocessor_get (preproc);
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_LEFT_PAREN))
{
gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected an openening \"(\"");
return (GskSlFunction *) function;
}
gsk_sl_preprocessor_consume (preproc, (GskSlStatement *) function);
function->scope = gsk_sl_scope_new (scope, return_type);
token = gsk_sl_preprocessor_get (preproc);
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_PAREN))
{
GPtrArray *arguments = g_ptr_array_new ();
while (TRUE)
{
GskSlQualifier qualifier;
GskSlType *type;
GskSlVariable *variable;
gsk_sl_qualifier_parse (&qualifier, scope, preproc, GSK_SL_QUALIFIER_PARAMETER);
type = gsk_sl_type_new_parse (scope, preproc);
token = gsk_sl_preprocessor_get (preproc);
if (gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER))
{
char *name;
name = g_strdup (token->str);
gsk_sl_preprocessor_consume (preproc, (GskSlStatement *) function);
type = gsk_sl_type_parse_array (type, scope, preproc);
variable = gsk_sl_variable_new (name, type, &qualifier, NULL);
function->function_type = gsk_sl_function_type_add_argument (function->function_type,
qualifier.storage,
type);
g_ptr_array_add (arguments, variable);
gsk_sl_scope_try_add_variable (function->scope, preproc, variable);
g_free (name);
}
else
{
gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected an identifier as the variable name.");
}
gsk_sl_type_unref (type);
token = gsk_sl_preprocessor_get (preproc);
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_COMMA))
break;
gsk_sl_preprocessor_consume (preproc, (GskSlStatement *) function);
}
g_assert (gsk_sl_function_type_get_n_arguments (function->function_type) == arguments->len);
function->arguments = (GskSlVariable **) g_ptr_array_free (arguments, FALSE);
}
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_PAREN))
{
gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected a closing \")\"");
gsk_sl_preprocessor_sync (preproc, GSK_SL_TOKEN_RIGHT_PAREN);
}
gsk_sl_preprocessor_consume (preproc, (GskSlStatement *) function);
token = gsk_sl_preprocessor_get (preproc);
if (gsk_sl_token_is (token, GSK_SL_TOKEN_SEMICOLON))
{
gsk_sl_preprocessor_consume (preproc, (GskSlStatement *) function);
return (GskSlFunction *) function;
}
function->statement = gsk_sl_statement_parse_compound (function->scope, preproc, FALSE);
if (!gsk_sl_type_is_void (return_type) &&
gsk_sl_statement_get_jump (function->statement) < GSK_SL_JUMP_RETURN)
{
gsk_sl_preprocessor_error (preproc, SYNTAX, "Function does not return a value.");
}
return (GskSlFunction *) function;
}
GskSlFunction *
gsk_sl_function_ref (GskSlFunction *function)
{
g_return_val_if_fail (function != NULL, NULL);
function->ref_count += 1;
return function;
}
void
gsk_sl_function_unref (GskSlFunction *function)
{
if (function == NULL)
return;
function->ref_count -= 1;
if (function->ref_count > 0)
return;
function->class->free (function);
}
GskSlType *
gsk_sl_function_get_return_type (const GskSlFunction *function)
{
return function->class->get_return_type (function);
}
const char *
gsk_sl_function_get_name (const GskSlFunction *function)
{
return function->class->get_name (function);
}
gsize
gsk_sl_function_get_n_arguments (const GskSlFunction *function)
{
return function->class->get_n_arguments (function);
}
GskSlType *
gsk_sl_function_get_argument_type (const GskSlFunction *function,
gsize i)
{
return function->class->get_argument_type (function, i);
}
GskSlValue *
gsk_sl_function_get_constant (const GskSlFunction *function,
GskSlValue **values,
gsize n_values)
{
return function->class->get_constant (function, values, n_values);
}
void
gsk_sl_function_print (const GskSlFunction *function,
GskSlPrinter *printer)
{
function->class->print (function, printer);
}
guint32
gsk_sl_function_write_spv (const GskSlFunction *function,
GskSpvWriter *writer,
GskSpvWriterFunc initializer,
gpointer initializer_data)
{
return function->class->write_spv (function, writer, initializer, initializer_data);
}
guint32
gsk_sl_function_write_call_spv (GskSlFunction *function,
GskSpvWriter *writer,
guint32 *arguments)
{
return function->class->write_call_spv (function, writer, arguments);
}
void
gsk_sl_function_matcher_init (GskSlFunctionMatcher *matcher,
GList *list)
{
matcher->best_matches = list;
matcher->matches = NULL;
}
void
gsk_sl_function_matcher_finish (GskSlFunctionMatcher *matcher)
{
g_list_free (matcher->best_matches);
g_list_free (matcher->matches);
}
gboolean
gsk_sl_function_matcher_has_matches (GskSlFunctionMatcher *matcher)
{
return matcher->best_matches || matcher->matches;
}
GskSlFunction *
gsk_sl_function_matcher_get_match (GskSlFunctionMatcher *matcher)
{
if (matcher->best_matches == NULL)
return NULL;
if (matcher->best_matches->next != NULL)
return NULL;
return matcher->best_matches->data;
}
void
gsk_sl_function_matcher_match_n_arguments (GskSlFunctionMatcher *matcher,
gsize n_arguments)
{
GList *l;
for (l = matcher->best_matches; l; l = l->next)
{
if (gsk_sl_function_get_n_arguments (l->data) != n_arguments)
matcher->best_matches = g_list_delete_link (matcher->best_matches, l);
}
for (l = matcher->matches; l; l = l->next)
{
if (gsk_sl_function_get_n_arguments (l->data) != n_arguments)
matcher->matches = g_list_delete_link (matcher->matches, l);
}
}
typedef enum {
MATCH_NONE,
MATCH_CONVERT_TO_DOUBLE,
MATCH_CONVERT,
MATCH_EXACT
} GskSlFunctionMatch;
static GskSlFunctionMatch
gsk_sl_function_matcher_match_types (const GskSlType *function_type,
const GskSlType *argument_type)
{
if (!gsk_sl_type_can_convert (function_type, argument_type))
return MATCH_NONE;
if (gsk_sl_type_equal (function_type, argument_type))
return MATCH_EXACT;
if (gsk_sl_type_get_scalar_type (function_type))
return MATCH_CONVERT_TO_DOUBLE;
return MATCH_CONVERT;
}
void
gsk_sl_function_matcher_match_argument (GskSlFunctionMatcher *matcher,
gsize n,
const GskSlType *argument_type)
{
GList *best_matches = NULL, *matches = NULL, *l;
GskSlFunctionMatch best = MATCH_NONE, function_match;
for (l = matcher->best_matches; l; l = l->next)
{
GskSlType *function_type;
GskSlFunctionMatch function_match;
if (gsk_sl_function_get_n_arguments (l->data) <= n)
continue;
function_type = gsk_sl_function_get_argument_type (l->data, n);
function_match = gsk_sl_function_matcher_match_types (function_type, argument_type);
if (function_match == MATCH_NONE)
continue;
if (function_match == best)
{
best_matches = g_list_prepend (best_matches, l->data);
best = function_match;
}
else if (function_match > best)
{
matches = g_list_concat (matches, best_matches);
best_matches = g_list_prepend (NULL, l->data);
best = function_match;
}
else
{
matches = g_list_prepend (matches, l->data);
}
}
for (l = matcher->matches; l; l = l->next)
{
GskSlType *function_type;
if (gsk_sl_function_get_n_arguments (l->data) <= n)
continue;
function_type = gsk_sl_function_get_argument_type (l->data, n);
function_match = gsk_sl_function_matcher_match_types (function_type, argument_type);
if (function_match == MATCH_NONE)
continue;
if (function_match > best)
{
matches = g_list_concat (matches, best_matches);
best_matches = NULL;
best = function_match;
}
matches = g_list_prepend (matches, l->data);
}
g_list_free (matcher->best_matches);
g_list_free (matcher->matches);
matcher->best_matches = best_matches;
matcher->matches = matches;
}
void
gsk_sl_function_matcher_match_function (GskSlFunctionMatcher *matcher,
const GskSlFunction *function)
{
GList *l;
gsize i, n;
n = gsk_sl_function_get_n_arguments (function);
for (l = matcher->best_matches; l; l = l->next)
{
GskSlFunction *f = l->data;
if (gsk_sl_function_get_n_arguments (f) != n)
continue;
for (i = 0; i < n; i++)
{
if (!gsk_sl_type_equal (gsk_sl_function_get_argument_type (f, i),
gsk_sl_function_get_argument_type (function, i)))
break;
}
if (i == n)
{
g_list_free (matcher->best_matches);
g_list_free (matcher->matches);
matcher->best_matches = g_list_prepend (NULL, f);
matcher->matches = NULL;
return;
}
}
g_list_free (matcher->best_matches);
g_list_free (matcher->matches);
matcher->best_matches = NULL;
matcher->matches = NULL;
}

View File

@@ -0,0 +1,85 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_SL_FUNCTION_PRIVATE_H__
#define __GSK_SL_FUNCTION_PRIVATE_H__
#include <glib.h>
#include "gsksltypesprivate.h"
G_BEGIN_DECLS
GskSlFunction * gsk_sl_function_new_constructor (GskSlType *type);
GskSlFunction * gsk_sl_function_new_native (const char *name,
GskSlFunctionType *type,
void (* get_constant) (gpointer *retval, gpointer *arguments, gpointer user_data),
guint32 (* write_spv) (GskSpvWriter *writer, guint32 *arguments, gpointer user_data),
gpointer user_data,
GDestroyNotify destroy);
GskSlFunction * gsk_sl_function_new_parse (GskSlScope *scope,
GskSlPreprocessor *stream,
GskSlType *return_type,
const char *name);
GskSlFunction * gsk_sl_function_ref (GskSlFunction *function);
void gsk_sl_function_unref (GskSlFunction *function);
void gsk_sl_function_print (const GskSlFunction *function,
GskSlPrinter *printer);
const char * gsk_sl_function_get_name (const GskSlFunction *function);
GskSlType * gsk_sl_function_get_return_type (const GskSlFunction *function);
gsize gsk_sl_function_get_n_arguments (const GskSlFunction *function);
GskSlType * gsk_sl_function_get_argument_type (const GskSlFunction *function,
gsize i);
GskSlValue * gsk_sl_function_get_constant (const GskSlFunction *function,
GskSlValue **values,
gsize n_values);
guint32 gsk_sl_function_write_spv (const GskSlFunction *function,
GskSpvWriter *writer,
GskSpvWriterFunc initializer,
gpointer initializer_data);
guint32 gsk_sl_function_write_call_spv (GskSlFunction *function,
GskSpvWriter *writer,
guint32 *arguments);
struct _GskSlFunctionMatcher
{
GList *best_matches;
GList *matches;
};
void gsk_sl_function_matcher_init (GskSlFunctionMatcher *matcher,
GList *list);
void gsk_sl_function_matcher_finish (GskSlFunctionMatcher *matcher);
gboolean gsk_sl_function_matcher_has_matches (GskSlFunctionMatcher *matcher);
GskSlFunction * gsk_sl_function_matcher_get_match (GskSlFunctionMatcher *matcher);
void gsk_sl_function_matcher_match_n_arguments (GskSlFunctionMatcher *matcher,
gsize n_arguments);
void gsk_sl_function_matcher_match_argument (GskSlFunctionMatcher *matcher,
gsize n,
const GskSlType *argument_type);
void gsk_sl_function_matcher_match_function (GskSlFunctionMatcher *matcher,
const GskSlFunction *function);
G_END_DECLS
#endif /* __GSK_SL_FUNCTION_PRIVATE_H__ */

242
gsk/gskslfunctiontype.c Normal file
View File

@@ -0,0 +1,242 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gskslfunctiontypeprivate.h"
#include "gsksltypeprivate.h"
#include "gskspvwriterprivate.h"
typedef struct _GskSlArgument GskSlArgument;
struct _GskSlArgument
{
GskSlStorage storage;
GskSlType *type;
};
struct _GskSlFunctionType
{
int ref_count;
GskSlType *return_type;
gsize n_arguments;
GskSlArgument arguments[0];
};
static GskSlFunctionType *
gsk_sl_function_type_alloc (gsize n_arguments)
{
GskSlFunctionType *function_type;
function_type = g_slice_alloc0 (sizeof (GskSlFunctionType) + n_arguments * sizeof (GskSlArgument));
function_type->ref_count = 1;
function_type->n_arguments = n_arguments;
return function_type;
}
GskSlFunctionType *
gsk_sl_function_type_new (GskSlType *return_type)
{
GskSlFunctionType *function_type;
function_type = gsk_sl_function_type_alloc (0);
function_type->return_type = gsk_sl_type_ref (return_type);
return function_type;
}
GskSlFunctionType *
gsk_sl_function_type_add_argument (GskSlFunctionType *function_type,
GskSlStorage argument_storage,
GskSlType *argument_type)
{
GskSlFunctionType *result_type;
gsize i;
g_assert (argument_storage >= GSK_SL_STORAGE_PARAMETER_IN && argument_storage <= GSK_SL_STORAGE_PARAMETER_CONST);
result_type = gsk_sl_function_type_alloc (function_type->n_arguments + 1);
result_type->return_type = gsk_sl_type_ref (function_type->return_type);
for (i = 0; i < function_type->n_arguments; i++)
{
result_type->arguments[i].type = gsk_sl_type_ref (function_type->arguments[i].type);
result_type->arguments[i].storage = function_type->arguments[i].storage;
}
result_type->arguments[i].type = gsk_sl_type_ref (argument_type);
result_type->arguments[i].storage = argument_storage;
gsk_sl_function_type_unref (function_type);
return result_type;
}
GskSlFunctionType *
gsk_sl_function_type_ref (GskSlFunctionType *function_type)
{
g_return_val_if_fail (function_type != NULL, NULL);
function_type->ref_count += 1;
return function_type;
}
void
gsk_sl_function_type_unref (GskSlFunctionType *function_type)
{
gsize i;
if (function_type == NULL)
return;
function_type->ref_count -= 1;
if (function_type->ref_count > 0)
return;
for (i = 0; i < function_type->n_arguments; i++)
{
gsk_sl_type_unref (function_type->arguments[i].type);
}
gsk_sl_type_unref (function_type->return_type);
g_slice_free1 (sizeof (GskSlFunctionType) + function_type->n_arguments * sizeof (GskSlArgument), function_type);
}
GskSlType *
gsk_sl_function_type_get_return_type (const GskSlFunctionType *function_type)
{
return function_type->return_type;
}
gsize
gsk_sl_function_type_get_n_arguments (const GskSlFunctionType *function_type)
{
return function_type->n_arguments;
}
GskSlType *
gsk_sl_function_type_get_argument_type (const GskSlFunctionType *function_type,
gsize i)
{
return function_type->arguments[i].type;
}
GskSlStorage
gsk_sl_function_type_get_argument_storage (const GskSlFunctionType *function_type,
gsize i)
{
return function_type->arguments[i].storage;
}
gboolean
gsk_sl_function_type_is_argument_const (const GskSlFunctionType *function_type,
gsize i)
{
return function_type->arguments[i].storage == GSK_SL_STORAGE_PARAMETER_CONST;
}
gboolean
gsk_sl_function_type_is_argument_in (const GskSlFunctionType *function_type,
gsize i)
{
return function_type->arguments[i].storage == GSK_SL_STORAGE_PARAMETER_IN
|| function_type->arguments[i].storage == GSK_SL_STORAGE_PARAMETER_INOUT;
}
gboolean
gsk_sl_function_type_is_argument_out (const GskSlFunctionType *function_type,
gsize i)
{
return function_type->arguments[i].storage == GSK_SL_STORAGE_PARAMETER_OUT
|| function_type->arguments[i].storage == GSK_SL_STORAGE_PARAMETER_INOUT;
}
guint32
gsk_sl_function_type_write_spv (const GskSlFunctionType *function_type,
GskSpvWriter *writer)
{
guint32 argument_types[function_type->n_arguments], return_type_id;
gsize i;
return_type_id = gsk_spv_writer_get_id_for_type (writer, function_type->return_type);
for (i = 0; i < function_type->n_arguments; i++)
{
if (function_type->arguments[i].storage == GSK_SL_STORAGE_PARAMETER_CONST)
{
argument_types[i] = gsk_spv_writer_get_id_for_type (writer,
function_type->arguments[i].type);
}
else
{
argument_types[i] = gsk_spv_writer_get_id_for_pointer_type (writer,
function_type->arguments[i].type,
GSK_SPV_STORAGE_CLASS_FUNCTION);
}
}
return gsk_spv_writer_type_function (writer, return_type_id, argument_types, function_type->n_arguments);
}
gboolean
gsk_sl_function_type_equal (gconstpointer a,
gconstpointer b)
{
const GskSlFunctionType *function_type_a = a;
const GskSlFunctionType *function_type_b = b;
gsize i;
if (function_type_a->n_arguments != function_type_b->n_arguments)
return FALSE;
if (!gsk_sl_type_equal (function_type_a->return_type, function_type_b->return_type))
return FALSE;
for (i = 0; i < function_type_a->n_arguments; i++)
{
if (function_type_a->arguments[i].storage != function_type_b->arguments[i].storage ||
!gsk_sl_type_equal (function_type_a->arguments[i].type, function_type_b->arguments[i].type))
return FALSE;
}
return TRUE;
}
guint
gsk_sl_function_type_hash (gconstpointer value)
{
const GskSlFunctionType *function_type = value;
guint hash;
gsize i;
hash = gsk_sl_type_hash (function_type->return_type);
for (i = 0; i < function_type->n_arguments; i++)
{
hash <<= 5;
hash ^= gsk_sl_type_hash (function_type->arguments[i].type);
hash ^= function_type->arguments[i].storage;
}
return hash;
}

View File

@@ -0,0 +1,58 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_SL_FUNCTION_TYPE_PRIVATE_H__
#define __GSK_SL_FUNCTION_TYPE_PRIVATE_H__
#include <glib.h>
#include "gsksltypesprivate.h"
G_BEGIN_DECLS
GskSlFunctionType * gsk_sl_function_type_new (GskSlType *return_type);
GskSlFunctionType * gsk_sl_function_type_add_argument (GskSlFunctionType *function_type,
GskSlStorage argument_storage,
GskSlType *argument_type);
GskSlFunctionType * gsk_sl_function_type_ref (GskSlFunctionType *function_type);
void gsk_sl_function_type_unref (GskSlFunctionType *function_type);
GskSlType * gsk_sl_function_type_get_return_type (const GskSlFunctionType*function_type);
gsize gsk_sl_function_type_get_n_arguments (const GskSlFunctionType*function_type);
GskSlType * gsk_sl_function_type_get_argument_type (const GskSlFunctionType*function_type,
gsize i);
GskSlStorage gsk_sl_function_type_get_argument_storage (const GskSlFunctionType*function_type,
gsize i);
gboolean gsk_sl_function_type_is_argument_const (const GskSlFunctionType*function_type,
gsize i);
gboolean gsk_sl_function_type_is_argument_in (const GskSlFunctionType*function_type,
gsize i);
gboolean gsk_sl_function_type_is_argument_out (const GskSlFunctionType*function_type,
gsize i);
guint32 gsk_sl_function_type_write_spv (const GskSlFunctionType*function_type,
GskSpvWriter *writer);
gboolean gsk_sl_function_type_equal (gconstpointer a,
gconstpointer b);
guint gsk_sl_function_type_hash (gconstpointer value);
G_END_DECLS
#endif /* __GSK_SL_FUNCTION_TYPE_PRIVATE_H__ */

268
gsk/gskslimagetype.c Normal file
View File

@@ -0,0 +1,268 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gskslimagetypeprivate.h"
#include "gsksltypeprivate.h"
#include "gskspvwriterprivate.h"
gboolean
gsk_sl_image_type_supports_projection (const GskSlImageType *type,
gboolean extra_dim)
{
if (type->arrayed)
return FALSE;
if (type->multisampled)
return FALSE;
if (extra_dim && type->shadow)
return FALSE;
switch (type->dim)
{
case GSK_SPV_DIM_1_D:
case GSK_SPV_DIM_2_D:
case GSK_SPV_DIM_RECT:
return TRUE;
case GSK_SPV_DIM_3_D:
return !extra_dim;
case GSK_SPV_DIM_CUBE:
case GSK_SPV_DIM_BUFFER:
case GSK_SPV_DIM_SUBPASS_DATA:
default:
return FALSE;
}
}
gboolean
gsk_sl_image_type_supports_lod (const GskSlImageType *type)
{
if (type->multisampled)
return FALSE;
switch (type->dim)
{
case GSK_SPV_DIM_1_D:
return TRUE;
case GSK_SPV_DIM_2_D:
case GSK_SPV_DIM_3_D:
return !type->arrayed || !type->shadow;
case GSK_SPV_DIM_CUBE:
return !type->shadow;
case GSK_SPV_DIM_RECT:
case GSK_SPV_DIM_BUFFER:
case GSK_SPV_DIM_SUBPASS_DATA:
default:
return FALSE;
}
}
gboolean
gsk_sl_image_type_supports_bias (const GskSlImageType *type)
{
if (type->multisampled)
return FALSE;
switch (type->dim)
{
case GSK_SPV_DIM_1_D:
case GSK_SPV_DIM_3_D:
case GSK_SPV_DIM_CUBE:
return TRUE;
case GSK_SPV_DIM_2_D:
return !type->arrayed || !type->shadow;
case GSK_SPV_DIM_RECT:
case GSK_SPV_DIM_BUFFER:
case GSK_SPV_DIM_SUBPASS_DATA:
default:
return FALSE;
}
}
gboolean
gsk_sl_image_type_supports_offset (const GskSlImageType *type)
{
if (type->multisampled)
return FALSE;
switch (type->dim)
{
case GSK_SPV_DIM_1_D:
case GSK_SPV_DIM_2_D:
case GSK_SPV_DIM_3_D:
case GSK_SPV_DIM_RECT:
return TRUE;
case GSK_SPV_DIM_CUBE:
case GSK_SPV_DIM_BUFFER:
case GSK_SPV_DIM_SUBPASS_DATA:
default:
return FALSE;
}
}
gboolean
gsk_sl_image_type_supports_gradient (const GskSlImageType *type)
{
if (type->multisampled)
return FALSE;
if (type->dim == GSK_SPV_DIM_BUFFER)
return FALSE;
return TRUE;
}
gboolean
gsk_sl_image_type_supports_texel_fetch (const GskSlImageType *type)
{
if (type->shadow)
return FALSE;
if (type->dim == GSK_SPV_DIM_CUBE)
return FALSE;
return TRUE;
}
gboolean
gsk_sl_image_type_supports_texture (const GskSlImageType *type)
{
if (type->multisampled)
return FALSE;
if (type->dim == GSK_SPV_DIM_BUFFER)
return FALSE;
return TRUE;
}
gboolean
gsk_sl_image_type_needs_lod_argument (const GskSlImageType *type,
gboolean texel_fetch)
{
if (type->multisampled)
return TRUE;
return type->dim != GSK_SPV_DIM_RECT
&& type->dim != GSK_SPV_DIM_BUFFER;
}
guint
gsk_sl_image_type_get_dimensions (const GskSlImageType *type)
{
switch (type->dim)
{
case GSK_SPV_DIM_1_D:
case GSK_SPV_DIM_BUFFER:
return 1;
case GSK_SPV_DIM_2_D:
case GSK_SPV_DIM_RECT:
case GSK_SPV_DIM_SUBPASS_DATA:
return 2;
case GSK_SPV_DIM_3_D:
case GSK_SPV_DIM_CUBE:
return 3;
default:
g_assert_not_reached ();
return 1;
}
}
guint
gsk_sl_image_type_get_lookup_dimensions (const GskSlImageType *type,
gboolean projection)
{
guint result = gsk_sl_image_type_get_dimensions (type);
if (type->arrayed)
result++;
if (type->shadow)
{
/* because GLSL is GLSL */
result = MAX (result, 2);
result++;
}
if (projection)
result++;
return result;
}
GskSlType *
gsk_sl_image_type_get_pixel_type (const GskSlImageType *type)
{
if (type->shadow)
return gsk_sl_type_get_scalar (type->sampled_type);
else
return gsk_sl_type_get_vector (type->sampled_type, 4);
}
guint32
gsk_sl_image_type_write_spv (const GskSlImageType *type,
GskSpvWriter *writer)
{
guint32 sampled_type_id;
sampled_type_id = gsk_spv_writer_get_id_for_type (writer, gsk_sl_type_get_scalar (type->sampled_type));
return gsk_spv_writer_type_image (writer,
sampled_type_id,
type->dim,
type->shadow,
type->arrayed,
type->multisampled,
2 - type->sampler,
GSK_SPV_IMAGE_FORMAT_UNKNOWN,
-1);
}
guint
gsk_sl_image_type_hash (gconstpointer type)
{
const GskSlImageType *image = type;
return image->sampled_type
| (image->dim << 8)
| (image->shadow << 16)
| (image->arrayed << 17)
| (image->multisampled << 18)
| (image->sampler << 19);
}
gboolean
gsk_sl_image_type_equal (gconstpointer a,
gconstpointer b)
{
const GskSlImageType *ia = a;
const GskSlImageType *ib = b;
return ia->sampled_type == ib->sampled_type
&& ia->dim == ib->dim
&& ia->shadow == ib->shadow
&& ia->arrayed == ib->arrayed
&& ia->multisampled == ib->multisampled
&& ia->sampler == ib->sampler;
}

View File

@@ -0,0 +1,65 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_SL_IMAGE_TYPE_PRIVATE_H__
#define __GSK_SL_IMAGE_TYPE_PRIVATE_H__
#include <glib.h>
#include "gsksltypesprivate.h"
#include "gskspvenumsprivate.h"
G_BEGIN_DECLS
struct _GskSlImageType
{
GskSlScalarType sampled_type;
GskSpvDim dim;
guint shadow :1;
guint arrayed :1;
guint multisampled :1;
guint sampler :1;
};
gboolean gsk_sl_image_type_supports_projection (const GskSlImageType *type,
gboolean extra_dim);
gboolean gsk_sl_image_type_supports_lod (const GskSlImageType *type);
gboolean gsk_sl_image_type_supports_bias (const GskSlImageType *type);
gboolean gsk_sl_image_type_supports_offset (const GskSlImageType *type);
gboolean gsk_sl_image_type_supports_gradient (const GskSlImageType *type);
gboolean gsk_sl_image_type_supports_texture (const GskSlImageType *type);
gboolean gsk_sl_image_type_supports_texel_fetch (const GskSlImageType *type);
gboolean gsk_sl_image_type_needs_lod_argument (const GskSlImageType *type,
gboolean texel_fetch);
guint gsk_sl_image_type_get_dimensions (const GskSlImageType *type);
guint gsk_sl_image_type_get_lookup_dimensions (const GskSlImageType *type,
gboolean projection);
GskSlType * gsk_sl_image_type_get_pixel_type (const GskSlImageType *type);
guint32 gsk_sl_image_type_write_spv (const GskSlImageType *type,
GskSpvWriter *writer);
guint gsk_sl_image_type_hash (gconstpointer type);
gboolean gsk_sl_image_type_equal (gconstpointer a,
gconstpointer b);
G_END_DECLS
#endif /* __GSK_SL_IMAGE_TYPE_PRIVATE_H__ */

1830
gsk/gskslnativefunction.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,33 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_SL_NATIVE_FUNCTION_PRIVATE_H__
#define __GSK_SL_NATIVE_FUNCTION_PRIVATE_H__
#include <glib.h>
#include "gsksltypesprivate.h"
G_BEGIN_DECLS
void gsk_sl_native_functions_add (GskSlScope *scope,
GskSlEnvironment *environment);
G_END_DECLS
#endif /* __GSK_SL_NATIVE_FUNCTION_PRIVATE_H__ */

140
gsk/gskslnativevariable.c Normal file
View File

@@ -0,0 +1,140 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gskslnativevariableprivate.h"
#include "gskslenvironmentprivate.h"
#include "gskslqualifierprivate.h"
#include "gskslscopeprivate.h"
#include "gsksltypeprivate.h"
#include "gskslvariableprivate.h"
typedef struct _NativeVariable NativeVariable;
struct _NativeVariable {
const char *name;
GskSlType *type;
GskSpvBuiltIn builtin;
};
static void
gsk_sl_native_variable_add_block (GskSlScope *scope,
const char *block_name,
const char *block_instance_name,
GskSlStorage storage,
const NativeVariable *variables,
gsize n_variables)
{
GskSlQualifier qualifier;
GskSlVariable *variable;
GskSlTypeBuilder *builder;
GskSlType *type;
gsize i;
gsk_sl_qualifier_init (&qualifier);
qualifier.storage = storage;
builder = gsk_sl_type_builder_new_block (block_name);
for (i = 0; i < n_variables; i++)
{
gsk_sl_type_builder_add_builtin_member (builder,
variables[i].type,
variables[i].name,
variables[i].builtin);
}
type = gsk_sl_type_builder_free (builder);
variable = gsk_sl_variable_new (block_instance_name,
type,
&qualifier,
NULL);
if (block_instance_name)
{
gsk_sl_scope_add_variable (scope, variable);
}
else
{
for (i = 0; i < n_variables; i++)
{
GskSlVariable *sub;
sub = gsk_sl_variable_new_block_member (variable, i);
gsk_sl_scope_add_variable (scope, sub);
gsk_sl_variable_unref (sub);
}
}
gsk_sl_variable_unref (variable);
}
static void
gsk_sl_native_variable_add (GskSlScope *scope,
const char *name,
GskSlStorage storage,
GskSlType *type,
GskSpvBuiltIn builtin)
{
GskSlQualifier qualifier;
GskSlVariable *variable;
gsk_sl_qualifier_init (&qualifier);
qualifier.storage = storage;
variable = gsk_sl_variable_new_builtin (name,
type,
&qualifier,
builtin);
gsk_sl_scope_add_variable (scope, variable);
gsk_sl_variable_unref (variable);
}
static void
gsk_sl_native_variable_add_simple (GskSlScope *scope,
const char *name,
GskSlScalarType scalar,
GskSpvBuiltIn builtin)
{
gsk_sl_native_variable_add (scope, name, GSK_SL_STORAGE_GLOBAL_IN, gsk_sl_type_get_scalar (scalar), builtin);
}
void
gsk_sl_native_variables_add (GskSlScope *scope,
GskSlEnvironment *environment)
{
if (gsk_sl_environment_get_stage (environment) == GSK_SL_SHADER_VERTEX)
{
gsk_sl_native_variable_add_simple (scope, "gl_VertexIndex", GSK_SL_INT, GSK_SPV_BUILT_IN_VERTEX_INDEX);
gsk_sl_native_variable_add_simple (scope, "gl_InstanceIndex", GSK_SL_INT, GSK_SPV_BUILT_IN_INSTANCE_INDEX);
if (gsk_sl_environment_get_version (environment) >= 150)
{
gsk_sl_native_variable_add_block (scope,
"gl_PerVertex", NULL,
GSK_SL_STORAGE_GLOBAL_OUT,
(NativeVariable[2]) {
{ "gl_Position", gsk_sl_type_get_vector (GSK_SL_FLOAT, 4), GSK_SPV_BUILT_IN_POSITION },
{ "gl_PointSize", gsk_sl_type_get_scalar (GSK_SL_FLOAT), GSK_SPV_BUILT_IN_POINT_SIZE }
}, 2);
}
else
{
gsk_sl_native_variable_add (scope, "gl_Position", GSK_SL_STORAGE_GLOBAL_OUT, gsk_sl_type_get_vector (GSK_SL_FLOAT, 4), GSK_SPV_BUILT_IN_POSITION);
gsk_sl_native_variable_add (scope, "gl_PointSize", GSK_SL_STORAGE_GLOBAL_OUT, gsk_sl_type_get_scalar (GSK_SL_FLOAT), GSK_SPV_BUILT_IN_POINT_SIZE);
}
}
}

View File

@@ -0,0 +1,31 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_SL_NATIVE_VARIABLE_PRIVATE_H__
#define __GSK_SL_NATIVE_VARIABLE_PRIVATE_H__
#include "gsksltypesprivate.h"
G_BEGIN_DECLS
void gsk_sl_native_variables_add (GskSlScope *scope,
GskSlEnvironment *environment);
G_END_DECLS
#endif /* __GSK_SL_NATIVE_VARIABLE_PRIVATE_H__ */

948
gsk/gskslpreprocessor.c Normal file
View File

@@ -0,0 +1,948 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gskslpreprocessorprivate.h"
#include "gskcodesource.h"
#include "gskslcompilerprivate.h"
#include "gsksldefineprivate.h"
#include "gskslenvironmentprivate.h"
#include "gsksltokenizerprivate.h"
typedef struct _GskSlPpToken GskSlPpToken;
struct _GskSlPpToken {
GskCodeLocation location;
GskSlToken token;
};
struct _GskSlPreprocessor
{
int ref_count;
GskSlCompiler *compiler;
GskSlEnvironment *environment;
GskSlTokenizer *tokenizer;
GSList *pending_tokenizers;
GArray *tokens;
GHashTable *defines;
gboolean fatal_error;
GSList *conditionals;
};
typedef enum {
/* ignore this part, the last conditional check didn't match */
GSK_COND_IGNORE = (1 << 0),
/* we're inside the else block, so no more elif */
GSK_COND_ELSE = (1 << 1),
/* we've had a match in one of the previous blocks (or this one matches) */
GSK_COND_MATCH = (1 << 2)
} GskConditional;
/* API */
static void
gsk_sl_preprocessor_error_func (GskSlTokenizer *parser,
gboolean fatal,
const GskCodeLocation *location,
const GskSlToken *token,
const GError *error,
gpointer user_data)
{
gsk_sl_preprocessor_emit_error (user_data, TRUE, location, error);
}
static void
gsk_sl_preprocessor_clear_token (gpointer data)
{
GskSlPpToken *pp = data;
gsk_sl_token_clear (&pp->token);
}
GskSlPreprocessor *
gsk_sl_preprocessor_ref (GskSlPreprocessor *preproc)
{
g_return_val_if_fail (preproc != NULL, NULL);
preproc->ref_count += 1;
return preproc;
}
void
gsk_sl_preprocessor_unref (GskSlPreprocessor *preproc)
{
if (preproc == NULL)
return;
preproc->ref_count -= 1;
if (preproc->ref_count > 0)
return;
g_slist_free (preproc->conditionals);
g_hash_table_destroy (preproc->defines);
g_slist_free_full (preproc->pending_tokenizers, (GDestroyNotify) gsk_sl_tokenizer_unref);
gsk_sl_tokenizer_unref (preproc->tokenizer);
gsk_sl_environment_unref (preproc->environment);
g_object_unref (preproc->compiler);
g_array_free (preproc->tokens, TRUE);
g_slice_free (GskSlPreprocessor, preproc);
}
gboolean
gsk_sl_preprocessor_has_fatal_error (GskSlPreprocessor *preproc)
{
return preproc->fatal_error;
}
GskSlEnvironment *
gsk_sl_preprocessor_get_environment (GskSlPreprocessor *preproc)
{
return preproc->environment;
}
static void
gsk_sl_preprocessor_push_conditional (GskSlPreprocessor *preproc,
GskConditional cond)
{
preproc->conditionals = g_slist_prepend (preproc->conditionals, GUINT_TO_POINTER (cond));
}
static GskConditional
gsk_sl_preprocessor_pop_conditional (GskSlPreprocessor *preproc)
{
GskConditional cond = GPOINTER_TO_UINT (preproc->conditionals->data);
preproc->conditionals = g_slist_remove (preproc->conditionals, preproc->conditionals->data);
return cond;
}
static gboolean
gsk_sl_preprocessor_has_conditional (GskSlPreprocessor *preproc)
{
return preproc->conditionals != NULL;
}
static gboolean
gsk_sl_preprocessor_in_ignored_conditional (GskSlPreprocessor *preproc)
{
GSList *l;
for (l = preproc->conditionals; l; l = l->next)
{
if (GPOINTER_TO_UINT (l->data) & GSK_COND_IGNORE)
return TRUE;
}
return FALSE;
}
static void
gsk_sl_preprocessor_handle_version (GskSlPreprocessor *preproc,
GskCodeLocation *location,
int version,
const char *profile_name,
gboolean first_token_ever)
{
GskSlEnvironment *new_environment;
GskSlProfile profile;
GError *error = NULL;
if (version <= 0)
{
gsk_sl_preprocessor_error_full (preproc, PREPROCESSOR, location, "version must be a positive number.");
return;
}
if (profile_name == NULL)
profile = GSK_SL_PROFILE_NONE;
else if (g_str_equal (profile_name, "core"))
profile = GSK_SL_PROFILE_CORE;
else if (g_str_equal (profile_name, "compatibility"))
profile = GSK_SL_PROFILE_COMPATIBILITY;
else if (g_str_equal (profile_name, "es"))
profile = GSK_SL_PROFILE_ES;
else
{
gsk_sl_preprocessor_error_full (preproc, PREPROCESSOR, location, "Unknown #version profile \"%s\".", profile_name);
return;
}
if (!first_token_ever)
{
gsk_sl_preprocessor_error_full (preproc, PREPROCESSOR, location, "#version directive must be first in compilation.");
return;
}
new_environment = gsk_sl_environment_new_similar (preproc->environment, profile, version, &error);
if (new_environment == NULL)
{
gsk_sl_preprocessor_emit_error (preproc, TRUE, location, error);
g_clear_error (&error);
}
else
{
gsk_sl_environment_unref (preproc->environment);
preproc->environment = new_environment;
}
}
#define token_array_get_token(array, i) (&g_array_index ((array), GskSlPpToken, (i)).token)
#define token_array_get_location(array, i) (&g_array_index ((array), GskSlPpToken, (i)).location)
#define token_array_error(preproc, array, i, ...) gsk_sl_preprocessor_error_full ((preproc), PREPROCESSOR, token_array_get_location (array, i), __VA_ARGS__)
static int
gsk_sl_preprocessor_handle_defined_expression (GskSlPreprocessor *preproc,
GArray *tokens,
gint *index)
{
const GskSlToken *token;
gboolean paren = FALSE;
int result;
(*index)++;
if (*index >= tokens->len)
{
token_array_error (preproc, tokens, tokens->len - 1, "\"defined\" without argument.");
return 0;
}
token = token_array_get_token (tokens, *index);
if (gsk_sl_token_is (token, GSK_SL_TOKEN_LEFT_PAREN))
{
paren = TRUE;
(*index)++;
if (*index >= tokens->len)
{
token_array_error (preproc, tokens, tokens->len - 1, "\"defined()\" without argument.");
return 0;
}
token = token_array_get_token (tokens, *index);
}
if (gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER))
{
(*index)++;
if (g_hash_table_lookup (preproc->defines, token->str))
result = 1;
else
result = 0;
}
else
{
token_array_error (preproc, tokens, *index, "Expected identifier after \"defined\".");
}
if (paren)
{
if (*index >= tokens->len ||
!gsk_sl_token_is (token_array_get_token (tokens, *index), GSK_SL_TOKEN_RIGHT_PAREN))
{
token_array_error (preproc, tokens, *index, "Expected closing \")\" for \"defined()\".");
return 0;
}
else
{
(*index)++;
}
}
return result;
}
static int
gsk_sl_preprocessor_handle_primary_expression (GskSlPreprocessor *preproc,
GArray *tokens,
gint *index)
{
const GskSlToken *token;
if (*index >= tokens->len)
{
token_array_error (preproc, tokens, tokens->len - 1, "Expected value.");
return 0;
}
token = token_array_get_token (tokens, (*index));
if (gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER))
{
if (g_str_equal (token->str, "defined"))
{
return gsk_sl_preprocessor_handle_defined_expression (preproc, tokens, index);
}
else
{
token_array_error (preproc, tokens, *index, "Unexpected identifier \"%s\".", token->str);
(*index)++;
return 0;
}
}
else if (gsk_sl_token_is (token, GSK_SL_TOKEN_INTCONSTANT))
{
(*index)++;
return token->i32;
}
else if (gsk_sl_token_is (token, GSK_SL_TOKEN_UINTCONSTANT))
{
(*index)++;
return token->u32;
}
else
{
token_array_error (preproc, tokens, *index, "Unexpected token in #if statement.");
(*index)++;
return 0;
}
}
static int
gsk_sl_preprocessor_handle_expression (GskSlPreprocessor *preproc,
GArray *tokens,
gint *index)
{
int result;
result = gsk_sl_preprocessor_handle_primary_expression (preproc, tokens, index);
if (*index < tokens->len)
{
token_array_error (preproc, tokens, *index, "Expected newline after expression.");
}
return result;
}
static gboolean
gsk_sl_preprocessor_next_token (GskSlPreprocessor *preproc,
GskSlPpToken *pp,
gboolean *last_was_newline)
{
gboolean contained_newline = FALSE;
pp->token = (GskSlToken) { 0, };
do
{
pp->location = *gsk_sl_tokenizer_get_location (preproc->tokenizer);
*last_was_newline = gsk_sl_token_is (&pp->token, GSK_SL_TOKEN_NEWLINE);
contained_newline |= gsk_sl_token_is (&pp->token, GSK_SL_TOKEN_NEWLINE);
gsk_sl_tokenizer_read_token (preproc->tokenizer, &pp->token);
}
while (gsk_sl_token_is_skipped (&pp->token));
return contained_newline || gsk_sl_token_is (&pp->token, GSK_SL_TOKEN_EOF);
}
static void
gsk_sl_preprocessor_handle_token (GskSlPreprocessor *preproc,
GskSlPpToken *pp,
gboolean was_newline,
gboolean was_start_of_document);
static gboolean
gsk_sl_preprocessor_include (GskSlPreprocessor *preproc,
GArray *tokens,
gboolean include_local)
{
GskCodeSource *source;
GError *error = NULL;
source = gsk_sl_compiler_resolve_include (preproc->compiler,
gsk_sl_tokenizer_get_location (preproc->tokenizer)->source,
include_local,
token_array_get_token (tokens, 1)->str,
&error);
if (source == NULL)
{
gsk_sl_preprocessor_emit_error (preproc, TRUE, token_array_get_location (tokens, 1), error);
g_error_free (error);
return FALSE;
}
if (g_slist_length (preproc->pending_tokenizers) > 20)
{
token_array_error (preproc, tokens, 1, "#include nested too deeply.");
return FALSE;
}
if (tokens->len > 2)
{
token_array_error (preproc, tokens, 2, "Extra content after #include directive");
return FALSE;
}
preproc->pending_tokenizers = g_slist_prepend (preproc->pending_tokenizers, preproc->tokenizer);
preproc->tokenizer = gsk_sl_tokenizer_new (source,
gsk_sl_preprocessor_error_func,
preproc,
NULL);
return TRUE;
}
static void
gsk_sl_preprocessor_append_token (GskSlPreprocessor *preproc,
GskSlPpToken *pp,
GSList *used_defines)
{
if (gsk_sl_token_is (&pp->token, GSK_SL_TOKEN_EOF) &&
preproc->pending_tokenizers)
{
gboolean was_newline;
gsk_sl_tokenizer_unref (preproc->tokenizer);
preproc->tokenizer = preproc->pending_tokenizers->data;
preproc->pending_tokenizers = g_slist_remove (preproc->pending_tokenizers, preproc->tokenizer);
gsk_sl_preprocessor_clear_token (pp);
gsk_sl_preprocessor_next_token (preproc, pp, &was_newline);
gsk_sl_preprocessor_handle_token (preproc, pp, TRUE, FALSE);
return;
}
if (gsk_sl_token_is (&pp->token, GSK_SL_TOKEN_EOF))
{
while (gsk_sl_preprocessor_has_conditional (preproc))
{
gsk_sl_preprocessor_pop_conditional (preproc);
gsk_sl_preprocessor_error_full (preproc, PREPROCESSOR, &pp->location, "Missing #endif.");
}
}
if (gsk_sl_preprocessor_in_ignored_conditional (preproc))
{
gsk_sl_preprocessor_clear_token (pp);
return;
}
if (gsk_sl_token_is (&pp->token, GSK_SL_TOKEN_IDENTIFIER))
{
GskSlDefine *define;
char *ident = pp->token.str;
define = g_hash_table_lookup (preproc->defines, ident);
if (define &&
!g_slist_find (used_defines, define))
{
GSList new_defines = { define, used_defines };
GskSlPpToken dpp;
guint i;
for (i = 0; i < gsk_sl_define_get_n_tokens (define); i++)
{
gsk_sl_define_get_token (define, i, &dpp.location, &dpp.token);
gsk_sl_preprocessor_append_token (preproc, &dpp, &new_defines);
}
gsk_sl_preprocessor_clear_token (pp);
return;
}
gsk_sl_token_init_from_identifier (&pp->token, ident);
g_free (ident);
}
else if (gsk_sl_token_is (&pp->token, GSK_SL_TOKEN_STRING))
{
gsk_sl_preprocessor_error_full (preproc, PREPROCESSOR, &pp->location, "Unexpected string.");
gsk_sl_preprocessor_clear_token (pp);
return;
}
g_array_append_val (preproc->tokens, *pp);
}
static GArray *
gsk_sl_preprocessor_read_line (GskSlPreprocessor *preproc)
{
GskSlPpToken pp;
GArray *tokens;
tokens = g_array_new (FALSE, FALSE, sizeof (GskSlPpToken));
g_array_set_clear_func (tokens, gsk_sl_preprocessor_clear_token);
while (TRUE)
{
pp.location = *gsk_sl_tokenizer_get_location (preproc->tokenizer);
gsk_sl_tokenizer_read_token (preproc->tokenizer, &pp.token);
if (gsk_sl_token_is (&pp.token, GSK_SL_TOKEN_EOF) ||
gsk_sl_token_is (&pp.token, GSK_SL_TOKEN_NEWLINE))
break;
if (!gsk_sl_token_is_skipped (&pp.token))
g_array_append_val (tokens, pp);
}
return tokens;
}
static void
gsk_sl_preprocessor_handle_preprocessor_directive (GskSlPreprocessor *preproc,
gboolean first_token_ever)
{
GskSlPpToken pp;
const GskSlToken *token;
gboolean was_newline;
GArray *tokens;
tokens = gsk_sl_preprocessor_read_line (preproc);
if (tokens->len == 0)
/* empty # line */
goto out;
token = &g_array_index (tokens, GskSlPpToken, 0).token;
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER))
{
token_array_error (preproc, tokens, 0, "Missing identifier for preprocessor directive.");
goto out;
}
if (g_str_equal (token->str, "else"))
{
if (gsk_sl_preprocessor_has_conditional (preproc))
{
GskConditional cond = gsk_sl_preprocessor_pop_conditional (preproc);
if (cond & GSK_COND_ELSE)
{
token_array_error (preproc, tokens, 0, "#else after #else.");
cond |= GSK_COND_IGNORE;
}
else if (cond & GSK_COND_MATCH)
cond |= GSK_COND_IGNORE;
else
cond &= ~GSK_COND_IGNORE;
cond |= GSK_COND_ELSE | GSK_COND_MATCH;
gsk_sl_preprocessor_push_conditional (preproc, cond);
}
else
{
token_array_error (preproc, tokens, 0, "#else without #if.");
}
if (tokens->len > 1)
token_array_error (preproc, tokens, 1, "Expected newline after #else.");
}
else if (g_str_equal (token->str, "elif"))
{
if (gsk_sl_preprocessor_has_conditional (preproc))
{
GskConditional cond = gsk_sl_preprocessor_pop_conditional (preproc);
if (cond & GSK_COND_ELSE)
{
token_array_error (preproc, tokens, 0, "#elif after #else.");
cond |= GSK_COND_IGNORE;
}
else
{
int expr, index;
index = 1;
expr = gsk_sl_preprocessor_handle_expression (preproc, tokens, &index);
if (cond & GSK_COND_MATCH)
{
cond |= GSK_COND_IGNORE;
}
else if (expr)
{
cond &= ~GSK_COND_IGNORE;
cond |= GSK_COND_MATCH;
}
else
{
cond |= GSK_COND_IGNORE;
}
}
gsk_sl_preprocessor_push_conditional (preproc, cond);
}
else
{
token_array_error (preproc, tokens, 0, "#elif without #if.");
}
}
else if (g_str_equal (token->str, "endif"))
{
if (gsk_sl_preprocessor_has_conditional (preproc))
{
gsk_sl_preprocessor_pop_conditional (preproc);
}
else
{
token_array_error (preproc, tokens, 0, "#endif without #if.");
}
if (tokens->len > 1)
token_array_error (preproc, tokens, 1, "Expected newline after #endif.");
}
else if (g_str_equal (token->str, "if"))
{
int expr, index;
index = 1;
expr = gsk_sl_preprocessor_handle_expression (preproc, tokens, &index);
if (expr)
gsk_sl_preprocessor_push_conditional (preproc, GSK_COND_MATCH);
else
gsk_sl_preprocessor_push_conditional (preproc, GSK_COND_IGNORE);
}
else if (g_str_equal (token->str, "ifdef"))
{
if (tokens->len == 1)
{
token_array_error (preproc, tokens, 0, "No variable after #ifdef.");
}
else
{
token = token_array_get_token (tokens, 1);
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER))
{
token_array_error (preproc, tokens, 1, "Expected identifier after #ifdef.");
}
else
{
if (g_hash_table_lookup (preproc->defines, token->str))
{
gsk_sl_preprocessor_push_conditional (preproc, GSK_COND_MATCH);
}
else
{
gsk_sl_preprocessor_push_conditional (preproc, GSK_COND_IGNORE);
}
}
if (tokens->len > 2)
token_array_error (preproc, tokens, 2, "Expected newline after #ifdef.");
}
}
else if (g_str_equal (token->str, "ifndef"))
{
if (tokens->len == 1)
{
token_array_error (preproc, tokens, 0, "No variable after #ifdef.");
}
else
{
token = token_array_get_token (tokens, 1);
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER))
{
token_array_error (preproc, tokens, 1, "Expected identifier after #ifndef.");
}
else
{
if (g_hash_table_lookup (preproc->defines, token->str))
{
gsk_sl_preprocessor_push_conditional (preproc, GSK_COND_IGNORE);
}
else
{
gsk_sl_preprocessor_push_conditional (preproc, GSK_COND_MATCH);
}
}
if (tokens->len > 2)
token_array_error (preproc, tokens, 2, "Expected newline after #ifndef.");
}
}
else if (gsk_sl_preprocessor_in_ignored_conditional (preproc))
{
/* All checks above are for preprocessor directives that are checked even in
* ignored parts of code */
/* Everything below has no effect in ignored parts of the code */
}
else if (g_str_equal (token->str, "define"))
{
if (tokens->len == 1)
{
token_array_error (preproc, tokens, 0, "No variable after #define.");
}
else
{
token = token_array_get_token (tokens, 1);
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER))
{
token_array_error (preproc, tokens, 1, "Expected identifier after #define.");
}
else
{
GskSlDefine *define;
guint i;
if (g_hash_table_lookup (preproc->defines, token->str))
token_array_error (preproc, tokens, 1, "\"%s\" redefined.", token->str);
define = gsk_sl_define_new (token->str, NULL);
for (i = 2; i < tokens->len; i++)
{
gsk_sl_define_add_token (define,
token_array_get_location (tokens, i),
token_array_get_token (tokens, i));
}
g_hash_table_replace (preproc->defines, (gpointer) gsk_sl_define_get_name (define), define);
}
}
}
else if (g_str_equal (token->str, "include"))
{
if (tokens->len == 1)
{
token_array_error (preproc, tokens, 0, "No filename after #include.");
}
else
{
token = token_array_get_token (tokens, 1);
if (gsk_sl_token_is (token, GSK_SL_TOKEN_STRING))
{
gsk_sl_preprocessor_include (preproc, tokens, TRUE);
}
else
{
token_array_error (preproc, tokens, 1, "Expected filename after #include.");
}
}
}
#if 0
else if (g_str_equal (token->str, "line"))
{
}
else if (g_str_equal (token->str, "pragma"))
{
}
else if (g_str_equal (token->str, "error"))
{
}
else if (g_str_equal (token->str, "extension"))
{
}
#endif
else if (g_str_equal (token->str, "undef"))
{
if (tokens->len == 1)
{
token_array_error (preproc, tokens, 0, "No variable after #undef.");
}
else
{
token = token_array_get_token (tokens, 1);
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER))
{
token_array_error (preproc, tokens, 1, "Expected identifier after #undef.");
}
else
{
g_hash_table_remove (preproc->defines, token->str);
}
if (tokens->len > 2)
token_array_error (preproc, tokens, 2, "Expected newline after #undef.");
}
}
else if (g_str_equal (token->str, "version"))
{
if (tokens->len == 1)
{
token_array_error (preproc, tokens, 0, "No version specified after #version.");
}
else
{
token = token_array_get_token (tokens, 1);
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_INTCONSTANT))
{
token_array_error (preproc, tokens, 1, "Expected version number.");
}
else
{
gint version = token->i32;
if (tokens->len == 2)
{
gsk_sl_preprocessor_handle_version (preproc, token_array_get_location (tokens, 1), version, NULL, first_token_ever);
}
else
{
token = token_array_get_token (tokens, 2);
if (gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER))
gsk_sl_preprocessor_handle_version (preproc, token_array_get_location (tokens, 1), version, token->str, first_token_ever);
else
token_array_error (preproc, tokens, 2, "Expected newline after #version.");
}
}
}
}
else
{
token_array_error (preproc, tokens, 0, "Unknown preprocessor directive #%s.", token->str);
}
out:
g_array_free (tokens, TRUE);
/* process first token, so we can ensure it assumes a newline */
gsk_sl_preprocessor_next_token (preproc, &pp, &was_newline);
gsk_sl_preprocessor_handle_token (preproc, &pp, TRUE, FALSE);
}
static void
gsk_sl_preprocessor_handle_token (GskSlPreprocessor *preproc,
GskSlPpToken *pp,
gboolean was_newline,
gboolean start_of_document)
{
if (gsk_sl_token_is (&pp->token, GSK_SL_TOKEN_HASH))
{
if (!was_newline)
{
gsk_sl_preprocessor_error (preproc, SYNTAX, "Unexpected \"#\" - preprocessor directives must be at start of line.");
gsk_sl_preprocessor_clear_token (pp);
}
else
{
gsk_sl_preprocessor_clear_token (pp);
gsk_sl_preprocessor_handle_preprocessor_directive (preproc, start_of_document);
}
}
else
{
gsk_sl_preprocessor_append_token (preproc, pp, NULL);
}
}
GskSlPreprocessor *
gsk_sl_preprocessor_new (GskSlCompiler *compiler,
GskSlEnvironment *environment,
GskCodeSource *source)
{
GskSlPreprocessor *preproc;
GskSlPpToken pp;
gboolean was_newline;
preproc = g_slice_new0 (GskSlPreprocessor);
preproc->ref_count = 1;
preproc->compiler = g_object_ref (compiler);
if (environment)
preproc->environment = gsk_sl_environment_ref (environment);
preproc->tokenizer = gsk_sl_tokenizer_new (source,
gsk_sl_preprocessor_error_func,
preproc,
NULL);
preproc->tokens = g_array_new (FALSE, FALSE, sizeof (GskSlPpToken));
g_array_set_clear_func (preproc->tokens, gsk_sl_preprocessor_clear_token);
preproc->defines = gsk_sl_compiler_copy_defines (compiler);
/* process the first token, so we can parse #version */
gsk_sl_preprocessor_next_token (preproc, &pp, &was_newline);
gsk_sl_preprocessor_handle_token (preproc, &pp, TRUE, TRUE);
return preproc;
}
static void
gsk_sl_preprocessor_ensure (GskSlPreprocessor *preproc)
{
GskSlPpToken pp;
gboolean was_newline = FALSE;
while (preproc->tokens->len <= 0)
{
gsk_sl_preprocessor_next_token (preproc, &pp, &was_newline);
gsk_sl_preprocessor_handle_token (preproc, &pp, was_newline, FALSE);
}
}
const GskSlToken *
gsk_sl_preprocessor_get (GskSlPreprocessor *preproc)
{
gsk_sl_preprocessor_ensure (preproc);
return &g_array_index (preproc->tokens, GskSlPpToken, 0).token;
}
const GskCodeLocation *
gsk_sl_preprocessor_get_location (GskSlPreprocessor *preproc)
{
gsk_sl_preprocessor_ensure (preproc);
return &g_array_index (preproc->tokens, GskSlPpToken, 0).location;
}
void
gsk_sl_preprocessor_consume (GskSlPreprocessor *preproc,
gpointer consumer)
{
gsk_sl_preprocessor_ensure (preproc);
g_array_remove_index (preproc->tokens, 0);
}
void
gsk_sl_preprocessor_sync (GskSlPreprocessor *preproc,
GskSlTokenType token_type)
{
const GskSlToken *token;
for (token = gsk_sl_preprocessor_get (preproc);
!gsk_sl_token_is (token, GSK_SL_TOKEN_EOF) && !gsk_sl_token_is (token, token_type);
token = gsk_sl_preprocessor_get (preproc))
{
if (gsk_sl_token_is (token, GSK_SL_TOKEN_LEFT_BRACE))
{
gsk_sl_preprocessor_consume (preproc, NULL);
gsk_sl_preprocessor_sync (preproc, GSK_SL_TOKEN_RIGHT_BRACE);
}
else if (gsk_sl_token_is (token, GSK_SL_TOKEN_LEFT_BRACKET))
{
gsk_sl_preprocessor_consume (preproc, NULL);
gsk_sl_preprocessor_sync (preproc, GSK_SL_TOKEN_RIGHT_BRACKET);
}
else if (gsk_sl_token_is (token, GSK_SL_TOKEN_LEFT_PAREN))
{
gsk_sl_preprocessor_consume (preproc, NULL);
gsk_sl_preprocessor_sync (preproc, GSK_SL_TOKEN_RIGHT_PAREN);
}
else
{
gsk_sl_preprocessor_consume (preproc, NULL);
}
}
}
void
gsk_sl_preprocessor_emit_error (GskSlPreprocessor *preproc,
gboolean fatal,
const GskCodeLocation *location,
const GError *error)
{
preproc->fatal_error |= fatal;
g_printerr ("%s:%zu:%zu: %s: %s\n",
gsk_code_source_get_name (location->source),
location->lines + 1, location->line_bytes,
fatal ? "error" : "warn",
error->message);
}

View File

@@ -0,0 +1,89 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_SL_PREPROCESSOR_PRIVATE_H__
#define __GSK_SL_PREPROCESSOR_PRIVATE_H__
#include "gskslcompilerprivate.h"
#include "gskslenvironmentprivate.h"
#include "gsksltypesprivate.h"
#include "gsksltokenizerprivate.h"
G_BEGIN_DECLS
GskSlPreprocessor * gsk_sl_preprocessor_new (GskSlCompiler *compiler,
GskSlEnvironment *environment,
GskCodeSource *source);
GskSlPreprocessor * gsk_sl_preprocessor_ref (GskSlPreprocessor *preproc);
void gsk_sl_preprocessor_unref (GskSlPreprocessor *preproc);
gboolean gsk_sl_preprocessor_has_fatal_error (GskSlPreprocessor *preproc);
GskSlEnvironment * gsk_sl_preprocessor_get_environment (GskSlPreprocessor *preproc);
const GskSlToken * gsk_sl_preprocessor_get (GskSlPreprocessor *preproc);
const GskCodeLocation * gsk_sl_preprocessor_get_location (GskSlPreprocessor *preproc);
void gsk_sl_preprocessor_consume (GskSlPreprocessor *preproc,
gpointer consumer);
#define gsk_sl_preprocessor_is_stage(preproc,stage) (gsk_sl_environment_get_stage (gsk_sl_preprocessor_get_environment (preproc)) == (stage))
void gsk_sl_preprocessor_sync (GskSlPreprocessor *preproc,
GskSlTokenType token);
void gsk_sl_preprocessor_emit_error (GskSlPreprocessor *preproc,
gboolean fatal,
const GskCodeLocation *location,
const GError *error);
#define gsk_sl_preprocessor_error(preproc, type, ...) \
gsk_sl_preprocessor_error_full (preproc, type, gsk_sl_preprocessor_get_location (preproc), __VA_ARGS__)
#define gsk_sl_preprocessor_error_full(preproc, type, location, ...) G_STMT_START{\
GError *error; \
\
error = g_error_new (GSK_SL_COMPILER_ERROR, \
GSK_SL_COMPILER_ERROR_ ## type, \
__VA_ARGS__); \
\
gsk_sl_preprocessor_emit_error (preproc, \
TRUE, \
location, \
error); \
\
g_error_free (error);\
}G_STMT_END
#define gsk_sl_preprocessor_warn(preproc, type, ...) \
gsk_sl_preprocessor_warn_full (preproc, type, gsk_sl_preprocessor_get_location (preproc), __VA_ARGS__)
#define gsk_sl_preprocessor_warn_full(preproc, type, location, ...) G_STMT_START{\
GError *error; \
\
error = g_error_new (GSK_SL_COMPILER_WARNING, \
GSK_SL_COMPILER_WARNING_ ## type, \
__VA_ARGS__); \
\
gsk_sl_preprocessor_emit_error (preproc, \
FALSE, \
location, \
error); \
\
g_error_free (error);\
}G_STMT_END
G_END_DECLS
#endif /* __GSK_SL_PREPROCESSOR_PRIVATE_H__ */

185
gsk/gskslprinter.c Normal file
View File

@@ -0,0 +1,185 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gskslprinterprivate.h"
struct _GskSlPrinter
{
guint ref_count;
GString *string;
guint indentation;
};
GskSlPrinter *
gsk_sl_printer_new (void)
{
GskSlPrinter *printer;
printer = g_slice_new0 (GskSlPrinter);
printer->ref_count = 1;
printer->string = g_string_new (NULL);
return printer;
}
GskSlPrinter *
gsk_sl_printer_ref (GskSlPrinter *printer)
{
g_return_val_if_fail (printer != NULL, NULL);
printer->ref_count += 1;
return printer;
}
void
gsk_sl_printer_unref (GskSlPrinter *printer)
{
if (printer == NULL)
return;
printer->ref_count -= 1;
if (printer->ref_count > 0)
return;
if (printer->indentation > 0)
{
g_warning ("Missing call to gsk_sl_printer_pop_indentation().");
}
g_string_free (printer->string, TRUE);
g_slice_free (GskSlPrinter, printer);
}
char *
gsk_sl_printer_write_to_string (GskSlPrinter *printer)
{
return g_strdup (printer->string->str);
}
void
gsk_sl_printer_push_indentation (GskSlPrinter *printer)
{
printer->indentation++;
}
void
gsk_sl_printer_pop_indentation (GskSlPrinter *printer)
{
if (printer->indentation == 0)
{
g_warning ("Calling gsk_sl_printer_pop_indentation() without preceding call to gsk_sl_printer_push_indentation()");
return;
}
printer->indentation--;
}
void
gsk_sl_printer_append (GskSlPrinter *printer,
const char *str)
{
g_string_append (printer->string, str);
}
void
gsk_sl_printer_append_c (GskSlPrinter *printer,
char c)
{
g_string_append_c (printer->string, c);
}
void
gsk_sl_printer_append_int (GskSlPrinter *printer,
int i)
{
g_string_append_printf (printer->string, "%d", i);
}
void
gsk_sl_printer_append_uint (GskSlPrinter *printer,
guint u)
{
g_string_append_printf (printer->string, "%u", u);
}
void
gsk_sl_printer_append_float (GskSlPrinter *printer,
float f)
{
char buf[G_ASCII_DTOSTR_BUF_SIZE];
if (isnanf (f))
g_string_append (printer->string, "(0.0 / 0.0)");
else if (isinff (f) > 0)
g_string_append (printer->string, "(1.0 / 0.0)");
else if (isinff (f) < 0)
g_string_append (printer->string, "(-1.0 / 0.0)");
else
{
g_ascii_dtostr (buf, G_ASCII_DTOSTR_BUF_SIZE, f);
g_string_append (printer->string, buf);
if (strchr (buf, '.') == NULL)
g_string_append (printer->string, ".0");
}
}
void
gsk_sl_printer_append_double (GskSlPrinter *printer,
double d)
{
char buf[G_ASCII_DTOSTR_BUF_SIZE];
if (isnan (d))
g_string_append (printer->string, "(0.0lf / 0.0lf)");
else if (isinf (d) > 0)
g_string_append (printer->string, "(1.0lf / 0.0lf)");
else if (isinf (d) < 0)
g_string_append (printer->string, "(-1.0lf / 0.0lf)");
else
{
g_ascii_dtostr (buf, G_ASCII_DTOSTR_BUF_SIZE, d);
g_string_append (printer->string, buf);
if (strchr (buf, '.') == NULL)
g_string_append (printer->string, ".0lf");
else
g_string_append (printer->string, "lf");
}
}
void
gsk_sl_printer_newline (GskSlPrinter *printer)
{
guint i;
g_string_append_c (printer->string, '\n');
for (i = 0; i < printer->indentation; i++)
{
g_string_append (printer->string, " ");
}
}

54
gsk/gskslprinterprivate.h Normal file
View File

@@ -0,0 +1,54 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_SL_PRINTER_PRIVATE_H__
#define __GSK_SL_PRINTER_PRIVATE_H__
#include <glib.h>
#include "gsksltypesprivate.h"
G_BEGIN_DECLS
GskSlPrinter * gsk_sl_printer_new (void);
GskSlPrinter * gsk_sl_printer_ref (GskSlPrinter *printer);
void gsk_sl_printer_unref (GskSlPrinter *printer);
char * gsk_sl_printer_write_to_string (GskSlPrinter *printer);
void gsk_sl_printer_push_indentation (GskSlPrinter *printer);
void gsk_sl_printer_pop_indentation (GskSlPrinter *printer);
void gsk_sl_printer_append (GskSlPrinter *printer,
const char *str);
void gsk_sl_printer_append_c (GskSlPrinter *printer,
char c);
void gsk_sl_printer_append_int (GskSlPrinter *printer,
int i);
void gsk_sl_printer_append_uint (GskSlPrinter *printer,
guint u);
void gsk_sl_printer_append_float (GskSlPrinter *printer,
float f);
void gsk_sl_printer_append_double (GskSlPrinter *printer,
double d);
void gsk_sl_printer_newline (GskSlPrinter *printer);
G_END_DECLS
#endif /* __GSK_SL_PRINTER_PRIVATE_H__ */

168
gsk/gskslprogram.c Normal file
View File

@@ -0,0 +1,168 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gskslprogramprivate.h"
#include "gsksldeclarationprivate.h"
#include "gskslenvironmentprivate.h"
#include "gskslfunctionprivate.h"
#include "gskslpreprocessorprivate.h"
#include "gskslprinterprivate.h"
#include "gskslscopeprivate.h"
#include "gsksltokenizerprivate.h"
#include "gsksltypeprivate.h"
#include "gskspvwriterprivate.h"
struct _GskSlProgram {
GObject parent_instance;
GskSlShaderStage stage;
GskSlScope *scope;
GSList *declarations;
};
G_DEFINE_TYPE (GskSlProgram, gsk_sl_program, G_TYPE_OBJECT)
static void
gsk_sl_program_dispose (GObject *object)
{
GskSlProgram *program = GSK_SL_PROGRAM (object);
g_slist_free_full (program->declarations, (GDestroyNotify) gsk_sl_declaration_unref);
g_clear_pointer (&program->scope, gsk_sl_scope_unref);
G_OBJECT_CLASS (gsk_sl_program_parent_class)->dispose (object);
}
static void
gsk_sl_program_class_init (GskSlProgramClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->dispose = gsk_sl_program_dispose;
}
static void
gsk_sl_program_init (GskSlProgram *program)
{
}
void
gsk_sl_program_parse (GskSlProgram *program,
GskSlPreprocessor *preproc)
{
GskSlDeclaration *declaration;
const GskSlToken *token;
program->stage = gsk_sl_environment_get_stage (gsk_sl_preprocessor_get_environment (preproc));
program->scope = gsk_sl_environment_create_scope (gsk_sl_preprocessor_get_environment (preproc));
for (token = gsk_sl_preprocessor_get (preproc);
!gsk_sl_token_is (token, GSK_SL_TOKEN_EOF);
token = gsk_sl_preprocessor_get (preproc))
{
declaration = gsk_sl_declaration_parse (program->scope, preproc);
if (declaration)
program->declarations = g_slist_prepend (program->declarations, declaration);
}
program->declarations = g_slist_reverse (program->declarations);
}
void
gsk_sl_program_print (GskSlProgram *program,
GString *string)
{
GskSlPrinter *printer;
GskSlFunction *function;
gboolean need_newline = FALSE;
GSList *l;
char *str;
g_return_if_fail (GSK_IS_SL_PROGRAM (program));
g_return_if_fail (string != NULL);
printer = gsk_sl_printer_new ();
for (l = program->declarations; l; l = l->next)
{
function = gsk_sl_declaration_get_function (l->data);
if ((function || need_newline) && l != program->declarations)
gsk_sl_printer_newline (printer);
gsk_sl_declaration_print (l->data, printer);
need_newline = function != NULL;
}
str = gsk_sl_printer_write_to_string (printer);
g_string_append (string, str);
g_free (str);
gsk_sl_printer_unref (printer);
}
static void
gsk_sl_program_write_spv_initializer (GskSpvWriter *writer,
gpointer data)
{
GskSlProgram *program = data;
GSList *l;
for (l = program->declarations; l; l = l->next)
gsk_sl_declaration_write_initializer_spv (l->data, writer);
}
static GskSlFunction *
gsk_sl_program_get_entry_point (GskSlProgram *program)
{
GSList *l;
for (l = program->declarations; l; l = l->next)
{
GskSlFunction *function = gsk_sl_declaration_get_function (l->data);
if (function && g_str_equal (gsk_sl_function_get_name (function), "main"))
return function;
}
return NULL;
}
GBytes *
gsk_sl_program_to_spirv (GskSlProgram *program)
{
GskSpvWriter *writer;
GBytes *bytes;
g_return_val_if_fail (GSK_IS_SL_PROGRAM (program), NULL);
writer = gsk_spv_writer_new (program->stage);
bytes = gsk_spv_writer_write (writer,
gsk_sl_program_get_entry_point (program),
gsk_sl_program_write_spv_initializer,
program);
gsk_spv_writer_unref (writer);
return bytes;
}

43
gsk/gskslprogram.h Normal file
View File

@@ -0,0 +1,43 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_SL_PROGRAM_H__
#define __GSK_SL_PROGRAM_H__
#if !defined (__GSK_H_INSIDE__) && !defined (GSK_COMPILATION)
#error "Only <gsk/gsk.h> can be included directly."
#endif
#include <gsk/gsktypes.h>
G_BEGIN_DECLS
#define GSK_TYPE_SL_PROGRAM (gsk_sl_program_get_type ())
G_DECLARE_FINAL_TYPE (GskSlProgram, gsk_sl_program, GSK, SL_PROGRAM, GObject)
GDK_AVAILABLE_IN_3_92
void gsk_sl_program_print (GskSlProgram *program,
GString *string);
GDK_AVAILABLE_IN_3_92
GBytes * gsk_sl_program_to_spirv (GskSlProgram *program);
G_END_DECLS
#endif /* __GSK_SL_PROGRAM_H__ */

32
gsk/gskslprogramprivate.h Normal file
View File

@@ -0,0 +1,32 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_SL_PROGRAM_PRIVATE_H__
#define __GSK_SL_PROGRAM_PRIVATE_H__
#include "gsk/gskslprogram.h"
#include "gsk/gsksltypesprivate.h"
G_BEGIN_DECLS
void gsk_sl_program_parse (GskSlProgram *program,
GskSlPreprocessor *preproc);
G_END_DECLS
#endif /* __GSK_SL_PROGRAM_PRIVATE_H__ */

723
gsk/gskslqualifier.c Normal file
View File

@@ -0,0 +1,723 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gskslqualifierprivate.h"
#include "gskslexpressionprivate.h"
#include "gskslpreprocessorprivate.h"
#include "gskslprinterprivate.h"
#include "gsksltokenizerprivate.h"
#include "gsksltypeprivate.h"
#include "gskslvalueprivate.h"
void
gsk_sl_qualifier_init (GskSlQualifier *qualifier)
{
*qualifier = (GskSlQualifier) { .storage = GSK_SL_STORAGE_DEFAULT,
.layout = { -1, -1, -1, -1 },
};
}
static void
gsk_sl_qualifier_parse_layout_assignment (GskSlPreprocessor *preproc,
GskSlScope *scope,
int *target)
{
const GskSlToken *token;
gsk_sl_preprocessor_consume (preproc, NULL);
token = gsk_sl_preprocessor_get (preproc);
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_EQUAL))
{
gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected \"=\" sign to assign a value.");
return;
}
gsk_sl_preprocessor_consume (preproc, NULL);
*target = gsk_sl_expression_parse_integral_constant (scope, preproc, 0, G_MAXINT);
}
static void
gsk_sl_qualifier_parse_layout (GskSlQualifier *qualifier,
GskSlPreprocessor *preproc,
GskSlScope *scope)
{
const GskSlToken *token;
while (TRUE)
{
token = gsk_sl_preprocessor_get (preproc);
if (gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_PAREN))
{
gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected layout identifier.");
break;
}
else if (gsk_sl_token_is (token, GSK_SL_TOKEN_IDENTIFIER))
{
if (g_str_equal (token->str, "location"))
gsk_sl_qualifier_parse_layout_assignment (preproc, scope, &qualifier->layout.location);
else if (g_str_equal (token->str, "component"))
gsk_sl_qualifier_parse_layout_assignment (preproc, scope, &qualifier->layout.component);
else if (g_str_equal (token->str, "binding"))
gsk_sl_qualifier_parse_layout_assignment (preproc, scope, &qualifier->layout.binding);
else if (g_str_equal (token->str, "set"))
gsk_sl_qualifier_parse_layout_assignment (preproc, scope, &qualifier->layout.set);
else if (g_str_equal (token->str, "push_constant"))
{
qualifier->layout.push_constant = TRUE;
gsk_sl_preprocessor_consume (preproc, NULL);
}
else
{
gsk_sl_preprocessor_error (preproc, UNSUPPORTED, "Unknown layout identifier.");
gsk_sl_preprocessor_consume (preproc, NULL);
}
}
else
{
gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected layout identifier.");
gsk_sl_preprocessor_consume (preproc, NULL);
}
token = gsk_sl_preprocessor_get (preproc);
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_COMMA))
break;
gsk_sl_preprocessor_consume (preproc, NULL);
}
}
static const char *
gsk_sl_storage_get_name (GskSlStorage storage)
{
switch (storage)
{
default:
case GSK_SL_STORAGE_DEFAULT:
g_assert_not_reached ();
return "???";
case GSK_SL_STORAGE_GLOBAL:
case GSK_SL_STORAGE_LOCAL:
case GSK_SL_STORAGE_PARAMETER_IN:
return "";
case GSK_SL_STORAGE_GLOBAL_CONST:
case GSK_SL_STORAGE_LOCAL_CONST:
case GSK_SL_STORAGE_PARAMETER_CONST:
return "const";
case GSK_SL_STORAGE_GLOBAL_IN:
return "in";
case GSK_SL_STORAGE_GLOBAL_OUT:
case GSK_SL_STORAGE_PARAMETER_OUT:
return "out";
case GSK_SL_STORAGE_PARAMETER_INOUT:
return "inout";
case GSK_SL_STORAGE_GLOBAL_UNIFORM:
return "uniform";
}
}
static const char *
gsk_sl_interpolation_get_name (GskSlInterpolation interp)
{
switch (interp)
{
default:
g_assert_not_reached ();
case GSK_SL_INTERPOLATE_DEFAULT:
return "";
case GSK_SL_INTERPOLATE_SMOOTH:
return "smooth";
case GSK_SL_INTERPOLATE_FLAT:
return "flat";
case GSK_SL_INTERPOLATE_NO_PERSPECTIVE:
return "noperspective";
}
}
static gboolean
gsk_sl_storage_allows_const (GskSlStorage storage)
{
switch (storage)
{
case GSK_SL_STORAGE_GLOBAL_CONST:
case GSK_SL_STORAGE_LOCAL_CONST:
case GSK_SL_STORAGE_PARAMETER_CONST:
default:
g_assert_not_reached ();
case GSK_SL_STORAGE_GLOBAL_OUT:
case GSK_SL_STORAGE_GLOBAL_UNIFORM:
case GSK_SL_STORAGE_PARAMETER_OUT:
case GSK_SL_STORAGE_PARAMETER_INOUT:
return FALSE;
case GSK_SL_STORAGE_DEFAULT:
case GSK_SL_STORAGE_GLOBAL:
case GSK_SL_STORAGE_GLOBAL_IN:
case GSK_SL_STORAGE_LOCAL:
case GSK_SL_STORAGE_PARAMETER_IN:
return TRUE;
}
}
void
gsk_sl_qualifier_parse (GskSlQualifier *qualifier,
GskSlScope *scope,
GskSlPreprocessor *preproc,
GskSlQualifierLocation location)
{
const GskSlToken *token;
gboolean seen_const = FALSE;
gsk_sl_qualifier_init (qualifier);
while (TRUE)
{
token = gsk_sl_preprocessor_get (preproc);
switch ((guint) token->type)
{
case GSK_SL_TOKEN_CONST:
if (seen_const)
gsk_sl_preprocessor_error (preproc, SYNTAX, "Duplicate \"const\" qualifier.");
if (!gsk_sl_storage_allows_const (qualifier->storage))
gsk_sl_preprocessor_error (preproc, SYNTAX, "\"%s\" qualifier cannot be const.", gsk_sl_storage_get_name (qualifier->storage));
else
seen_const = TRUE;
gsk_sl_preprocessor_consume (preproc, NULL);
break;
case GSK_SL_TOKEN_IN:
if (qualifier->storage == GSK_SL_STORAGE_DEFAULT)
{
if (location == GSK_SL_QUALIFIER_LOCAL)
gsk_sl_preprocessor_error (preproc, SYNTAX, "Local variables cannot have \"in\" qualifier.");
else
qualifier->storage = location == GSK_SL_QUALIFIER_GLOBAL ? GSK_SL_STORAGE_GLOBAL_IN
: GSK_SL_STORAGE_PARAMETER_IN;
}
else if (qualifier->storage == GSK_SL_STORAGE_PARAMETER_OUT)
qualifier->storage = GSK_SL_STORAGE_PARAMETER_INOUT;
else
gsk_sl_preprocessor_error (preproc, SYNTAX, "Qualifiers \"%s\" and \"in\" cannot be combined.", gsk_sl_storage_get_name (qualifier->storage));
gsk_sl_preprocessor_consume (preproc, NULL);
break;
case GSK_SL_TOKEN_OUT:
if (seen_const)
gsk_sl_preprocessor_error (preproc, SYNTAX, "Const variables cannot have \"out\" qualifier.");
else if (qualifier->storage == GSK_SL_STORAGE_DEFAULT)
{
if (location == GSK_SL_QUALIFIER_LOCAL)
gsk_sl_preprocessor_error (preproc, SYNTAX, "Local variables cannot have \"out\" qualifier.");
else
qualifier->storage = location == GSK_SL_QUALIFIER_GLOBAL ? GSK_SL_STORAGE_GLOBAL_OUT
: GSK_SL_STORAGE_PARAMETER_OUT;
}
else if (qualifier->storage == GSK_SL_STORAGE_PARAMETER_IN)
qualifier->storage = GSK_SL_STORAGE_PARAMETER_INOUT;
else
gsk_sl_preprocessor_error (preproc, SYNTAX, "Qualifiers \"%s\" and \"out\" cannot be combined.", gsk_sl_storage_get_name (qualifier->storage));
gsk_sl_preprocessor_consume (preproc, NULL);
break;
case GSK_SL_TOKEN_INOUT:
if (seen_const)
gsk_sl_preprocessor_error (preproc, SYNTAX, "Const variables cannot have \"inout\" qualifier.");
else if (qualifier->storage == GSK_SL_STORAGE_DEFAULT)
{
if (location != GSK_SL_QUALIFIER_PARAMETER)
gsk_sl_preprocessor_error (preproc, SYNTAX, "\"inout\" can only be used on parameters.");
else
qualifier->storage = GSK_SL_STORAGE_PARAMETER_INOUT;
}
else
gsk_sl_preprocessor_error (preproc, SYNTAX, "Qualifiers \"%s\" and \"inout\" cannot be combined.", gsk_sl_storage_get_name (qualifier->storage));
gsk_sl_preprocessor_consume (preproc, NULL);
break;
case GSK_SL_TOKEN_UNIFORM:
if (seen_const)
gsk_sl_preprocessor_error (preproc, SYNTAX, "Const variables cannot have \"uniform\" qualifier.");
else if (qualifier->storage == GSK_SL_STORAGE_DEFAULT)
{
if (location != GSK_SL_QUALIFIER_GLOBAL)
gsk_sl_preprocessor_error (preproc, SYNTAX, "\"uniform\" can only be used on globals.");
else
qualifier->storage = GSK_SL_STORAGE_GLOBAL_UNIFORM;
}
else
gsk_sl_preprocessor_error (preproc, SYNTAX, "Qualifiers \"%s\" and \"uniform\" cannot be combined.", gsk_sl_storage_get_name (qualifier->storage));
gsk_sl_preprocessor_consume (preproc, NULL);
break;
case GSK_SL_TOKEN_SMOOTH:
if (qualifier->interpolation != GSK_SL_INTERPOLATE_DEFAULT)
gsk_sl_preprocessor_error (preproc, SYNTAX,
"Duplicate interpolation qualifiers: \"%s\" and \"smooth\".",
gsk_sl_interpolation_get_name (qualifier->interpolation));
else
qualifier->interpolation = GSK_SL_INTERPOLATE_SMOOTH;
gsk_sl_preprocessor_consume (preproc, NULL);
break;
case GSK_SL_TOKEN_FLAT:
if (qualifier->interpolation != GSK_SL_INTERPOLATE_DEFAULT)
gsk_sl_preprocessor_error (preproc, SYNTAX,
"Duplicate interpolation qualifiers: \"%s\" and \"flat\".",
gsk_sl_interpolation_get_name (qualifier->interpolation));
else
qualifier->interpolation = GSK_SL_INTERPOLATE_FLAT;
gsk_sl_preprocessor_consume (preproc, NULL);
break;
case GSK_SL_TOKEN_NOPERSPECTIVE:
if (qualifier->interpolation != GSK_SL_INTERPOLATE_DEFAULT)
gsk_sl_preprocessor_error (preproc, SYNTAX,
"Duplicate interpolation qualifiers: \"%s\" and \"noperspective\".",
gsk_sl_interpolation_get_name (qualifier->interpolation));
else
qualifier->interpolation = GSK_SL_INTERPOLATE_NO_PERSPECTIVE;
gsk_sl_preprocessor_consume (preproc, NULL);
break;
case GSK_SL_TOKEN_INVARIANT:
if (qualifier->invariant)
gsk_sl_preprocessor_error (preproc, SYNTAX, "Duplicate \"invariant\" qualifier.");
qualifier->invariant = TRUE;
gsk_sl_preprocessor_consume (preproc, NULL);
break;
case GSK_SL_TOKEN_COHERENT:
if (qualifier->coherent)
gsk_sl_preprocessor_error (preproc, SYNTAX, "Duplicate \"coherent\" qualifier.");
qualifier->coherent = TRUE;
gsk_sl_preprocessor_consume (preproc, NULL);
break;
case GSK_SL_TOKEN_VOLATILE:
if (qualifier->volatile_)
gsk_sl_preprocessor_error (preproc, SYNTAX, "Duplicate \"volatile\" qualifier.");
qualifier->volatile_ = TRUE;
gsk_sl_preprocessor_consume (preproc, NULL);
break;
case GSK_SL_TOKEN_RESTRICT:
if (qualifier->restrict_)
gsk_sl_preprocessor_error (preproc, SYNTAX, "Duplicate \"restrict\" qualifier.");
qualifier->restrict_ = TRUE;
break;
case GSK_SL_TOKEN_READONLY:
if (qualifier->readonly)
gsk_sl_preprocessor_error (preproc, SYNTAX, "Duplicate \"readonly\" qualifier.");
qualifier->readonly = TRUE;
gsk_sl_preprocessor_consume (preproc, NULL);
break;
case GSK_SL_TOKEN_WRITEONLY:
if (qualifier->writeonly)
gsk_sl_preprocessor_error (preproc, SYNTAX, "Duplicate \"writeonly\" qualifier.");
qualifier->writeonly = TRUE;
gsk_sl_preprocessor_consume (preproc, NULL);
break;
case GSK_SL_TOKEN_LAYOUT:
if (location != GSK_SL_QUALIFIER_GLOBAL)
gsk_sl_preprocessor_error (preproc, SYNTAX, "Only global variables can have layout qualifiers.");
gsk_sl_preprocessor_consume (preproc, NULL);
token = gsk_sl_preprocessor_get (preproc);
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_LEFT_PAREN))
{
gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected opening \"(\" after layout specifier");
break;
}
gsk_sl_preprocessor_consume (preproc, NULL);
gsk_sl_qualifier_parse_layout (qualifier, preproc, scope);
token = gsk_sl_preprocessor_get (preproc);
if (!gsk_sl_token_is (token, GSK_SL_TOKEN_RIGHT_PAREN))
{
gsk_sl_preprocessor_error (preproc, SYNTAX, "Expected closing \")\" at end of layout specifier");
gsk_sl_preprocessor_sync (preproc, GSK_SL_TOKEN_RIGHT_PAREN);
}
gsk_sl_preprocessor_consume (preproc, NULL);
break;
default:
goto out;
}
}
out:
/* fixup storage qualifier */
switch (qualifier->storage)
{
case GSK_SL_STORAGE_DEFAULT:
if (location == GSK_SL_QUALIFIER_GLOBAL)
qualifier->storage = seen_const ? GSK_SL_STORAGE_GLOBAL_CONST : GSK_SL_STORAGE_GLOBAL;
else if (location == GSK_SL_QUALIFIER_LOCAL)
qualifier->storage = seen_const ? GSK_SL_STORAGE_LOCAL_CONST : GSK_SL_STORAGE_LOCAL;
else if (location == GSK_SL_QUALIFIER_PARAMETER)
qualifier->storage = seen_const ? GSK_SL_STORAGE_PARAMETER_CONST : GSK_SL_STORAGE_PARAMETER_IN;
else
{
g_assert_not_reached ();
}
break;
case GSK_SL_STORAGE_GLOBAL:
if (seen_const)
qualifier->storage = GSK_SL_STORAGE_GLOBAL_CONST;
break;
case GSK_SL_STORAGE_LOCAL:
if (seen_const)
qualifier->storage = GSK_SL_STORAGE_LOCAL_CONST;
break;
case GSK_SL_STORAGE_PARAMETER_IN:
if (seen_const)
qualifier->storage = GSK_SL_STORAGE_PARAMETER_CONST;
break;
case GSK_SL_STORAGE_GLOBAL_IN:
case GSK_SL_STORAGE_GLOBAL_OUT:
case GSK_SL_STORAGE_GLOBAL_UNIFORM:
case GSK_SL_STORAGE_PARAMETER_OUT:
case GSK_SL_STORAGE_PARAMETER_INOUT:
g_assert (!seen_const);
break;
case GSK_SL_STORAGE_GLOBAL_CONST:
case GSK_SL_STORAGE_LOCAL_CONST:
case GSK_SL_STORAGE_PARAMETER_CONST:
default:
g_assert_not_reached ();
break;
}
}
static gboolean
gsk_sl_qualifier_has_layout (const GskSlQualifier *qualifier)
{
return qualifier->layout.set >= 0
|| qualifier->layout.binding >= 0
|| qualifier->layout.location >= 0
|| qualifier->layout.component >= 0
|| qualifier->layout.push_constant;
}
static gboolean
print_qualifier (GskSlPrinter *printer,
const char *name,
gint value,
gboolean needs_comma)
{
if (value < 0)
return needs_comma;
if (needs_comma)
gsk_sl_printer_append (printer, ", ");
gsk_sl_printer_append (printer, name);
gsk_sl_printer_append (printer, "=");
gsk_sl_printer_append_uint (printer, value);
return TRUE;
}
static gboolean
append_with_space (GskSlPrinter *printer,
const char *s,
gboolean need_space)
{
if (s[0] == '\0')
return need_space;
if (need_space)
gsk_sl_printer_append_c (printer, ' ');
gsk_sl_printer_append (printer, s);
return TRUE;
}
gboolean
gsk_sl_qualifier_print (const GskSlQualifier *qualifier,
GskSlPrinter *printer)
{
gboolean need_space = FALSE;
if (qualifier->invariant)
need_space = append_with_space (printer, "invariant ", need_space);
if (qualifier->volatile_)
need_space = append_with_space (printer, "volatile ", need_space);
if (qualifier->restrict_)
need_space = append_with_space (printer, "restrict ", need_space);
if (qualifier->coherent)
need_space = append_with_space (printer, "coherent ", need_space);
if (qualifier->readonly)
need_space = append_with_space (printer, "readonly ", need_space);
if (qualifier->writeonly)
need_space = append_with_space (printer, "writeonly ", need_space);
if (gsk_sl_qualifier_has_layout (qualifier))
{
gboolean had_value;
gsk_sl_printer_append (printer, "layout(");
had_value = print_qualifier (printer, "set", qualifier->layout.set, FALSE);
had_value = print_qualifier (printer, "binding", qualifier->layout.binding, had_value);
had_value = print_qualifier (printer, "location", qualifier->layout.location, had_value);
had_value = print_qualifier (printer, "component", qualifier->layout.component, had_value);
if (qualifier->layout.push_constant)
{
if (had_value)
gsk_sl_printer_append (printer, ", ");
gsk_sl_printer_append (printer, "push_constant");
}
gsk_sl_printer_append (printer, ")");
need_space = TRUE;
}
need_space = append_with_space (printer, gsk_sl_interpolation_get_name (qualifier->interpolation), need_space);
need_space = append_with_space (printer, gsk_sl_storage_get_name (qualifier->storage), need_space);
return need_space;
}
gboolean
gsk_sl_qualifier_is_constant (const GskSlQualifier *qualifier)
{
switch (qualifier->storage)
{
case GSK_SL_STORAGE_DEFAULT:
default:
g_assert_not_reached ();
return TRUE;
case GSK_SL_STORAGE_GLOBAL_UNIFORM:
case GSK_SL_STORAGE_GLOBAL_CONST:
case GSK_SL_STORAGE_LOCAL_CONST:
case GSK_SL_STORAGE_PARAMETER_CONST:
return TRUE;
case GSK_SL_STORAGE_GLOBAL:
case GSK_SL_STORAGE_GLOBAL_IN:
case GSK_SL_STORAGE_GLOBAL_OUT:
case GSK_SL_STORAGE_LOCAL:
case GSK_SL_STORAGE_PARAMETER_IN:
case GSK_SL_STORAGE_PARAMETER_OUT:
case GSK_SL_STORAGE_PARAMETER_INOUT:
return FALSE;
}
}
GskSlQualifierLocation
gsk_sl_qualifier_get_location (const GskSlQualifier *qualifier)
{
switch (qualifier->storage)
{
case GSK_SL_STORAGE_DEFAULT:
default:
g_assert_not_reached ();
return GSK_SL_QUALIFIER_GLOBAL;
case GSK_SL_STORAGE_GLOBAL_UNIFORM:
case GSK_SL_STORAGE_GLOBAL:
case GSK_SL_STORAGE_GLOBAL_IN:
case GSK_SL_STORAGE_GLOBAL_OUT:
case GSK_SL_STORAGE_GLOBAL_CONST:
return GSK_SL_QUALIFIER_GLOBAL;
case GSK_SL_STORAGE_LOCAL:
case GSK_SL_STORAGE_LOCAL_CONST:
return GSK_SL_QUALIFIER_LOCAL;
case GSK_SL_STORAGE_PARAMETER_IN:
case GSK_SL_STORAGE_PARAMETER_OUT:
case GSK_SL_STORAGE_PARAMETER_INOUT:
case GSK_SL_STORAGE_PARAMETER_CONST:
return GSK_SL_QUALIFIER_PARAMETER;
}
}
GskSpvStorageClass
gsk_sl_qualifier_get_storage_class (const GskSlQualifier *qualifier,
const GskSlType *type)
{
switch (qualifier->storage)
{
case GSK_SL_STORAGE_DEFAULT:
default:
g_assert_not_reached ();
return GSK_SPV_STORAGE_CLASS_FUNCTION;
case GSK_SL_STORAGE_GLOBAL:
case GSK_SL_STORAGE_GLOBAL_CONST:
return GSK_SPV_STORAGE_CLASS_PRIVATE;
case GSK_SL_STORAGE_GLOBAL_IN:
return GSK_SPV_STORAGE_CLASS_INPUT;
case GSK_SL_STORAGE_GLOBAL_OUT:
return GSK_SPV_STORAGE_CLASS_OUTPUT;
case GSK_SL_STORAGE_GLOBAL_UNIFORM:
if (qualifier->layout.push_constant)
return GSK_SPV_STORAGE_CLASS_PUSH_CONSTANT;
else if (gsk_sl_type_contains_opaque (type))
return GSK_SPV_STORAGE_CLASS_UNIFORM_CONSTANT;
else
return GSK_SPV_STORAGE_CLASS_UNIFORM;
case GSK_SL_STORAGE_LOCAL:
case GSK_SL_STORAGE_LOCAL_CONST:
case GSK_SL_STORAGE_PARAMETER_IN:
case GSK_SL_STORAGE_PARAMETER_OUT:
case GSK_SL_STORAGE_PARAMETER_INOUT:
case GSK_SL_STORAGE_PARAMETER_CONST:
return GSK_SPV_STORAGE_CLASS_FUNCTION;
}
}
#define ERROR(...) G_STMT_START{\
gsk_sl_preprocessor_error (preproc, DECLARATION, __VA_ARGS__); \
result = FALSE; \
}G_STMT_END
static gboolean
gsk_sl_qualifier_check_type_for_input (const GskSlQualifier *qualifier,
GskSlPreprocessor *preproc,
GskSlType *type)
{
gboolean result = TRUE;
gsize i;
if (gsk_sl_type_is_struct (type) &&
gsk_sl_preprocessor_is_stage (preproc, GSK_SL_SHADER_VERTEX))
ERROR ("In variables in vertex shaders must not contain structs");
if (gsk_sl_type_is_opaque (type) &&
gsk_sl_preprocessor_is_stage (preproc, GSK_SL_SHADER_VERTEX))
ERROR ("In variables must not contain opaque types");
if (gsk_sl_type_get_scalar_type (type) == GSK_SL_BOOL)
ERROR ("In variables must not contain boolean types");
if (gsk_sl_type_get_scalar_type (type) != GSK_SL_FLOAT &&
gsk_sl_preprocessor_is_stage (preproc, GSK_SL_SHADER_FRAGMENT) &&
qualifier->interpolation != GSK_SL_INTERPOLATE_FLAT)
ERROR ("Non-float in variables in fragment shader must be qualified as \"flat\".");
for (i = 0; i < gsk_sl_type_get_n_members (type); i++)
{
result &= gsk_sl_qualifier_check_type_for_input (qualifier,
preproc,
gsk_sl_type_get_member_type (type, i));
}
return result;
}
gboolean
gsk_sl_qualifier_check_type (const GskSlQualifier *qualifier,
GskSlPreprocessor *preproc,
GskSlType *type)
{
switch (qualifier->storage)
{
case GSK_SL_STORAGE_DEFAULT:
default:
g_assert_not_reached ();
return FALSE;
case GSK_SL_STORAGE_GLOBAL:
case GSK_SL_STORAGE_GLOBAL_CONST:
return TRUE;
case GSK_SL_STORAGE_GLOBAL_IN:
return gsk_sl_qualifier_check_type_for_input (qualifier, preproc, type);
case GSK_SL_STORAGE_GLOBAL_OUT:
case GSK_SL_STORAGE_GLOBAL_UNIFORM:
case GSK_SL_STORAGE_LOCAL:
case GSK_SL_STORAGE_LOCAL_CONST:
case GSK_SL_STORAGE_PARAMETER_IN:
case GSK_SL_STORAGE_PARAMETER_OUT:
case GSK_SL_STORAGE_PARAMETER_INOUT:
case GSK_SL_STORAGE_PARAMETER_CONST:
return TRUE;
}
}
static void
gsk_sl_qualifier_write_inout_decorations (const GskSlQualifier *qualifier,
GskSpvWriter *writer,
guint32 value_id)
{
switch (qualifier->interpolation)
{
case GSK_SL_INTERPOLATE_FLAT:
gsk_spv_writer_decorate (writer, value_id, GSK_SPV_DECORATION_FLAT, NULL, 0);
break;
case GSK_SL_INTERPOLATE_NO_PERSPECTIVE:
gsk_spv_writer_decorate (writer, value_id, GSK_SPV_DECORATION_NO_PERSPECTIVE, NULL, 0);
break;
case GSK_SL_INTERPOLATE_DEFAULT:
case GSK_SL_INTERPOLATE_SMOOTH:
default:
break;
}
if (qualifier->layout.set >= 0)
gsk_spv_writer_decorate (writer, value_id, GSK_SPV_DECORATION_LOCATION, (guint32[1]) { qualifier->layout.set }, 1);
if (qualifier->layout.binding >= 0)
gsk_spv_writer_decorate (writer, value_id, GSK_SPV_DECORATION_LOCATION, (guint32[1]) { qualifier->layout.binding }, 1);
if (qualifier->layout.location >= 0)
gsk_spv_writer_decorate (writer, value_id, GSK_SPV_DECORATION_LOCATION, (guint32[1]) { qualifier->layout.location }, 1);
if (qualifier->layout.component >= 0)
gsk_spv_writer_decorate (writer, value_id, GSK_SPV_DECORATION_LOCATION, (guint32[1]) { qualifier->layout.component }, 1);
}
void
gsk_sl_qualifier_write_spv_decorations (const GskSlQualifier *qualifier,
GskSpvWriter *writer,
guint32 value_id)
{
switch (qualifier->storage)
{
case GSK_SL_STORAGE_DEFAULT:
default:
g_assert_not_reached ();
case GSK_SL_STORAGE_LOCAL:
case GSK_SL_STORAGE_LOCAL_CONST:
case GSK_SL_STORAGE_PARAMETER_IN:
case GSK_SL_STORAGE_PARAMETER_OUT:
case GSK_SL_STORAGE_PARAMETER_INOUT:
case GSK_SL_STORAGE_PARAMETER_CONST:
case GSK_SL_STORAGE_GLOBAL:
case GSK_SL_STORAGE_GLOBAL_CONST:
return;
case GSK_SL_STORAGE_GLOBAL_IN:
case GSK_SL_STORAGE_GLOBAL_OUT:
case GSK_SL_STORAGE_GLOBAL_UNIFORM:
gsk_sl_qualifier_write_inout_decorations (qualifier, writer, value_id);
}
}

View File

@@ -0,0 +1,87 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_SL_QUALIFIER_PRIVATE_H__
#define __GSK_SL_QUALIFIER_PRIVATE_H__
#include <glib.h>
#include "gsksltypesprivate.h"
#include "gskslqualifierprivate.h"
#include "gskspvwriterprivate.h"
G_BEGIN_DECLS
typedef enum {
GSK_SL_QUALIFIER_GLOBAL,
GSK_SL_QUALIFIER_PARAMETER,
GSK_SL_QUALIFIER_LOCAL
} GskSlQualifierLocation;
typedef enum {
GSK_SL_INTERPOLATE_DEFAULT,
GSK_SL_INTERPOLATE_SMOOTH,
GSK_SL_INTERPOLATE_FLAT,
GSK_SL_INTERPOLATE_NO_PERSPECTIVE
} GskSlInterpolation;
struct _GskSlQualifier
{
GskSlStorage storage;
GskSlInterpolation interpolation;
struct {
gint set;
gint binding;
gint location;
gint component;
guint push_constant :1;
} layout;
guint invariant :1;
guint volatile_ :1;
guint restrict_ :1;
guint coherent :1;
guint readonly :1;
guint writeonly :1;
};
void gsk_sl_qualifier_init (GskSlQualifier *qualifier);
void gsk_sl_qualifier_parse (GskSlQualifier *qualifier,
GskSlScope *scope,
GskSlPreprocessor *stream,
GskSlQualifierLocation location);
gboolean gsk_sl_qualifier_print (const GskSlQualifier *qualifier,
GskSlPrinter *printer);
gboolean gsk_sl_qualifier_is_constant (const GskSlQualifier *qualifier);
GskSlQualifierLocation gsk_sl_qualifier_get_location (const GskSlQualifier *qualifier);
GskSpvStorageClass gsk_sl_qualifier_get_storage_class (const GskSlQualifier *qualifier,
const GskSlType *type);
gboolean gsk_sl_qualifier_check_type (const GskSlQualifier *qualifier,
GskSlPreprocessor *preproc,
GskSlType *type);
void gsk_sl_qualifier_write_spv_decorations (const GskSlQualifier *qualifier,
GskSpvWriter *writer,
guint32 value_id);
G_END_DECLS
#endif /* __GSK_SL_QUALIFIER_PRIVATE_H__ */

283
gsk/gskslscope.c Normal file
View File

@@ -0,0 +1,283 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gskslscopeprivate.h"
#include "gskslfunctionprivate.h"
#include "gskslpreprocessorprivate.h"
#include "gskslqualifierprivate.h"
#include "gsksltypeprivate.h"
#include "gskslvariableprivate.h"
#include <string.h>
struct _GskSlScope
{
int ref_count;
GskSlScope *parent;
GSList *children;
GskSlType *return_type;
GHashTable *variables;
GHashTable *functions;
GHashTable *types;
guint can_break :1;
guint can_continue :1;
};
static void
free_function_list (gpointer data)
{
g_list_free_full (data, (GDestroyNotify) gsk_sl_function_unref);
}
GskSlScope *
gsk_sl_scope_new (GskSlScope *parent,
GskSlType *return_type)
{
if (parent)
return gsk_sl_scope_new_full (parent, return_type, parent->can_break, parent->can_continue);
else
return gsk_sl_scope_new_full (parent, return_type, FALSE, FALSE);
}
GskSlScope *
gsk_sl_scope_new_full (GskSlScope *parent,
GskSlType *return_type,
gboolean can_break,
gboolean can_continue)
{
GskSlScope *scope;
scope = g_slice_new0 (GskSlScope);
scope->ref_count = 1;
if (parent)
{
scope->parent = parent;
parent->children = g_slist_prepend (parent->children, scope);
}
if (return_type)
scope->return_type = gsk_sl_type_ref (return_type);
scope->can_break = can_break;
scope->can_continue = can_continue;
scope->variables = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) gsk_sl_variable_unref);
scope->functions = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) free_function_list);
scope->types = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, (GDestroyNotify) gsk_sl_type_unref);
return scope;
}
GskSlScope *
gsk_sl_scope_ref (GskSlScope *scope)
{
g_return_val_if_fail (scope != NULL, NULL);
scope->ref_count += 1;
return scope;
}
void
gsk_sl_scope_unref (GskSlScope *scope)
{
GSList *l;
if (scope == NULL)
return;
scope->ref_count -= 1;
if (scope->ref_count > 0)
return;
g_hash_table_unref (scope->variables);
g_hash_table_unref (scope->functions);
g_hash_table_unref (scope->types);
if (scope->parent)
scope->parent->children = g_slist_remove (scope->parent->children, scope);
for (l = scope->children; l; l = l->next)
((GskSlScope *) l->data)->parent = NULL;
g_slist_free (scope->children);
if (scope->return_type)
gsk_sl_type_unref (scope->return_type);
g_slice_free (GskSlScope, scope);
}
GskSlType *
gsk_sl_scope_get_return_type (const GskSlScope *scope)
{
return scope->return_type;
}
gboolean
gsk_sl_scope_can_break (const GskSlScope *scope)
{
return scope->can_break;
}
gboolean
gsk_sl_scope_can_continue (const GskSlScope *scope)
{
return scope->can_continue;
}
gboolean
gsk_sl_scope_is_global (const GskSlScope *scope)
{
return scope->parent == NULL;
}
void
gsk_sl_scope_add_variable (GskSlScope *scope,
GskSlVariable *variable)
{
g_hash_table_replace (scope->variables, (gpointer) gsk_sl_variable_get_name (variable), gsk_sl_variable_ref (variable));
}
static const char *
gsk_sl_scope_describe_variable (GskSlVariable *variable)
{
switch (gsk_sl_qualifier_get_location (gsk_sl_variable_get_qualifier (variable)))
{
default:
g_assert_not_reached ();
case GSK_SL_QUALIFIER_GLOBAL:
return "global variable";
case GSK_SL_QUALIFIER_PARAMETER:
return "function parameter";
case GSK_SL_QUALIFIER_LOCAL:
return "local variable";
}
}
void
gsk_sl_scope_try_add_variable (GskSlScope *scope,
GskSlPreprocessor *preproc,
GskSlVariable *variable)
{
GskSlVariable *shadow;
/* only look in current scope for error */
shadow = g_hash_table_lookup (scope->variables, gsk_sl_variable_get_name (variable));
if (shadow)
{
gsk_sl_preprocessor_error (preproc, DECLARATION,
"Redefinition of %s \"%s\".",
gsk_sl_scope_describe_variable (shadow),
gsk_sl_variable_get_name (variable));
return;
}
if (scope->parent)
{
shadow = gsk_sl_scope_lookup_variable (scope->parent, gsk_sl_variable_get_name (variable));
if (shadow)
{
gsk_sl_preprocessor_warn (preproc, SHADOW,
"Name \"%s\" shadows %s of same name.",
gsk_sl_variable_get_name (variable),
gsk_sl_scope_describe_variable (shadow));
}
}
gsk_sl_scope_add_variable (scope, variable);
}
GskSlVariable *
gsk_sl_scope_lookup_variable (GskSlScope *scope,
const char *name)
{
GskSlVariable *result;
for (;
scope != NULL;
scope = scope->parent)
{
result = g_hash_table_lookup (scope->variables, name);
if (result)
return result;
}
return NULL;
}
void
gsk_sl_scope_add_function (GskSlScope *scope,
GskSlFunction *function)
{
GList *functions;
const char *name;
name = gsk_sl_function_get_name (function);
functions = g_hash_table_lookup (scope->functions, name);
gsk_sl_function_ref (function);
if (functions)
functions = g_list_append (functions, function);
else
g_hash_table_insert (scope->functions, (gpointer) name, g_list_prepend (NULL, function));
}
void
gsk_sl_scope_match_function (GskSlScope *scope,
GskSlFunctionMatcher *matcher,
const char *name)
{
GList *result = NULL, *lookup;
for (;
scope != NULL;
scope = scope->parent)
{
lookup = g_hash_table_lookup (scope->functions, name);
result = g_list_concat (result, g_list_copy (lookup));
}
gsk_sl_function_matcher_init (matcher, result);
}
void
gsk_sl_scope_add_type (GskSlScope *scope,
GskSlType *type)
{
g_hash_table_replace (scope->types, (gpointer) gsk_sl_type_get_name (type), gsk_sl_type_ref (type));
}
GskSlType *
gsk_sl_scope_lookup_type (GskSlScope *scope,
const char *name)
{
GskSlType *result;
for (;
scope != NULL;
scope = scope->parent)
{
result = g_hash_table_lookup (scope->types, name);
if (result)
return result;
}
return NULL;
}

62
gsk/gskslscopeprivate.h Normal file
View File

@@ -0,0 +1,62 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_SL_SCOPE_PRIVATE_H__
#define __GSK_SL_SCOPE_PRIVATE_H__
#include <glib.h>
#include "gsksltypesprivate.h"
G_BEGIN_DECLS
GskSlScope * gsk_sl_scope_new (GskSlScope *parent,
GskSlType *return_type);
GskSlScope * gsk_sl_scope_new_full (GskSlScope *parent,
GskSlType *return_type,
gboolean can_break,
gboolean can_continue);
GskSlScope * gsk_sl_scope_ref (GskSlScope *scope);
void gsk_sl_scope_unref (GskSlScope *scope);
GskSlType * gsk_sl_scope_get_return_type (const GskSlScope *scope);
gboolean gsk_sl_scope_can_break (const GskSlScope *scope);
gboolean gsk_sl_scope_can_continue (const GskSlScope *scope);
gboolean gsk_sl_scope_is_global (const GskSlScope *scope);
void gsk_sl_scope_add_variable (GskSlScope *scope,
GskSlVariable *variable);
void gsk_sl_scope_try_add_variable (GskSlScope *scope,
GskSlPreprocessor *preproc,
GskSlVariable *variable);
GskSlVariable * gsk_sl_scope_lookup_variable (GskSlScope *scope,
const char *name);
void gsk_sl_scope_add_function (GskSlScope *scope,
GskSlFunction *function);
void gsk_sl_scope_match_function (GskSlScope *scope,
GskSlFunctionMatcher *matcher,
const char *name);
void gsk_sl_scope_add_type (GskSlScope *scope,
GskSlType *type);
GskSlType * gsk_sl_scope_lookup_type (GskSlScope *scope,
const char *name);
G_END_DECLS
#endif /* __GSK_SL_SCOPE_PRIVATE_H__ */

1675
gsk/gskslstatement.c Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,56 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_SL_STATEMENT_PRIVATE_H__
#define __GSK_SL_STATEMENT_PRIVATE_H__
#include <glib.h>
#include "gsk/gsksltypesprivate.h"
G_BEGIN_DECLS
typedef enum {
GSK_SL_JUMP_NONE,
GSK_SL_JUMP_BREAK,
GSK_SL_JUMP_CONTINUE,
GSK_SL_JUMP_RETURN,
GSK_SL_JUMP_DISCARD
} GskSlJump;
GskSlStatement * gsk_sl_statement_parse (GskSlScope *scope,
GskSlPreprocessor *preproc,
gboolean parse_everything);
GskSlStatement * gsk_sl_statement_parse_compound (GskSlScope *scope,
GskSlPreprocessor *preproc,
gboolean new_scope);
GskSlStatement * gsk_sl_statement_ref (GskSlStatement *statement);
void gsk_sl_statement_unref (GskSlStatement *statement);
void gsk_sl_statement_print (const GskSlStatement *statement,
GskSlPrinter *printer);
GskSlJump gsk_sl_statement_get_jump (const GskSlStatement *statement);
gboolean gsk_sl_statement_write_spv (const GskSlStatement *statement,
GskSpvWriter *writer);
G_END_DECLS
#endif /* __GSK_SL_STATEMENT_PRIVATE_H__ */

2197
gsk/gsksltokenizer.c Normal file

File diff suppressed because it is too large Load Diff

302
gsk/gsksltokenizerprivate.h Normal file
View File

@@ -0,0 +1,302 @@
/* GTK - The GIMP Toolkit
* Copyright (C) 2011 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_SL_TOKENIZER_PRIVATE_H__
#define __GSK_SL_TOKENIZER_PRIVATE_H__
#include <gsktypes.h>
G_BEGIN_DECLS
typedef enum {
GSK_SL_TOKEN_EOF = 0,
GSK_SL_TOKEN_ERROR,
GSK_SL_TOKEN_NEWLINE,
GSK_SL_TOKEN_WHITESPACE,
GSK_SL_TOKEN_COMMENT,
GSK_SL_TOKEN_SINGLE_LINE_COMMENT,
GSK_SL_TOKEN_STRING,
/* real tokens */
GSK_SL_TOKEN_CONST,
GSK_SL_TOKEN_BOOL,
GSK_SL_TOKEN_FLOAT,
GSK_SL_TOKEN_DOUBLE,
GSK_SL_TOKEN_INT,
GSK_SL_TOKEN_UINT,
GSK_SL_TOKEN_BREAK,
GSK_SL_TOKEN_CONTINUE,
GSK_SL_TOKEN_DO,
GSK_SL_TOKEN_ELSE,
GSK_SL_TOKEN_FOR,
GSK_SL_TOKEN_IF,
GSK_SL_TOKEN_DISCARD,
GSK_SL_TOKEN_RETURN,
GSK_SL_TOKEN_SWITCH,
GSK_SL_TOKEN_CASE,
GSK_SL_TOKEN_DEFAULT,
GSK_SL_TOKEN_SUBROUTINE,
GSK_SL_TOKEN_BVEC2,
GSK_SL_TOKEN_BVEC3,
GSK_SL_TOKEN_BVEC4,
GSK_SL_TOKEN_IVEC2,
GSK_SL_TOKEN_IVEC3,
GSK_SL_TOKEN_IVEC4,
GSK_SL_TOKEN_UVEC2,
GSK_SL_TOKEN_UVEC3,
GSK_SL_TOKEN_UVEC4,
GSK_SL_TOKEN_VEC2,
GSK_SL_TOKEN_VEC3,
GSK_SL_TOKEN_VEC4,
GSK_SL_TOKEN_MAT2,
GSK_SL_TOKEN_MAT3,
GSK_SL_TOKEN_MAT4,
GSK_SL_TOKEN_CENTROID,
GSK_SL_TOKEN_IN,
GSK_SL_TOKEN_OUT,
GSK_SL_TOKEN_INOUT,
GSK_SL_TOKEN_UNIFORM,
GSK_SL_TOKEN_PATCH,
GSK_SL_TOKEN_SAMPLE,
GSK_SL_TOKEN_BUFFER,
GSK_SL_TOKEN_SHARED,
GSK_SL_TOKEN_COHERENT,
GSK_SL_TOKEN_VOLATILE,
GSK_SL_TOKEN_RESTRICT,
GSK_SL_TOKEN_READONLY,
GSK_SL_TOKEN_WRITEONLY,
GSK_SL_TOKEN_DVEC2,
GSK_SL_TOKEN_DVEC3,
GSK_SL_TOKEN_DVEC4,
GSK_SL_TOKEN_DMAT2,
GSK_SL_TOKEN_DMAT3,
GSK_SL_TOKEN_DMAT4,
GSK_SL_TOKEN_NOPERSPECTIVE,
GSK_SL_TOKEN_FLAT,
GSK_SL_TOKEN_SMOOTH,
GSK_SL_TOKEN_LAYOUT,
GSK_SL_TOKEN_MAT2X2,
GSK_SL_TOKEN_MAT2X3,
GSK_SL_TOKEN_MAT2X4,
GSK_SL_TOKEN_MAT3X2,
GSK_SL_TOKEN_MAT3X3,
GSK_SL_TOKEN_MAT3X4,
GSK_SL_TOKEN_MAT4X2,
GSK_SL_TOKEN_MAT4X3,
GSK_SL_TOKEN_MAT4X4,
GSK_SL_TOKEN_DMAT2X2,
GSK_SL_TOKEN_DMAT2X3,
GSK_SL_TOKEN_DMAT2X4,
GSK_SL_TOKEN_DMAT3X2,
GSK_SL_TOKEN_DMAT3X3,
GSK_SL_TOKEN_DMAT3X4,
GSK_SL_TOKEN_DMAT4X2,
GSK_SL_TOKEN_DMAT4X3,
GSK_SL_TOKEN_DMAT4X4,
GSK_SL_TOKEN_ATOMIC_UINT,
GSK_SL_TOKEN_SAMPLER1D,
GSK_SL_TOKEN_SAMPLER2D,
GSK_SL_TOKEN_SAMPLER3D,
GSK_SL_TOKEN_SAMPLERCUBE,
GSK_SL_TOKEN_SAMPLER1DSHADOW,
GSK_SL_TOKEN_SAMPLER2DSHADOW,
GSK_SL_TOKEN_SAMPLERCUBESHADOW,
GSK_SL_TOKEN_SAMPLER1DARRAY,
GSK_SL_TOKEN_SAMPLER2DARRAY,
GSK_SL_TOKEN_SAMPLER1DARRAYSHADOW,
GSK_SL_TOKEN_SAMPLER2DARRAYSHADOW,
GSK_SL_TOKEN_ISAMPLER1D,
GSK_SL_TOKEN_ISAMPLER2D,
GSK_SL_TOKEN_ISAMPLER3D,
GSK_SL_TOKEN_ISAMPLERCUBE,
GSK_SL_TOKEN_ISAMPLER1DARRAY,
GSK_SL_TOKEN_ISAMPLER2DARRAY,
GSK_SL_TOKEN_USAMPLER1D,
GSK_SL_TOKEN_USAMPLER2D,
GSK_SL_TOKEN_USAMPLER3D,
GSK_SL_TOKEN_USAMPLERCUBE,
GSK_SL_TOKEN_USAMPLER1DARRAY,
GSK_SL_TOKEN_USAMPLER2DARRAY,
GSK_SL_TOKEN_SAMPLER2DRECT,
GSK_SL_TOKEN_SAMPLER2DRECTSHADOW,
GSK_SL_TOKEN_ISAMPLER2DRECT,
GSK_SL_TOKEN_USAMPLER2DRECT,
GSK_SL_TOKEN_SAMPLERBUFFER,
GSK_SL_TOKEN_ISAMPLERBUFFER,
GSK_SL_TOKEN_USAMPLERBUFFER,
GSK_SL_TOKEN_SAMPLERCUBEARRAY,
GSK_SL_TOKEN_SAMPLERCUBEARRAYSHADOW,
GSK_SL_TOKEN_ISAMPLERCUBEARRAY,
GSK_SL_TOKEN_USAMPLERCUBEARRAY,
GSK_SL_TOKEN_SAMPLER2DMS,
GSK_SL_TOKEN_ISAMPLER2DMS,
GSK_SL_TOKEN_USAMPLER2DMS,
GSK_SL_TOKEN_SAMPLER2DMSARRAY,
GSK_SL_TOKEN_ISAMPLER2DMSARRAY,
GSK_SL_TOKEN_USAMPLER2DMSARRAY,
GSK_SL_TOKEN_IMAGE1D,
GSK_SL_TOKEN_IIMAGE1D,
GSK_SL_TOKEN_UIMAGE1D,
GSK_SL_TOKEN_IMAGE2D,
GSK_SL_TOKEN_IIMAGE2D,
GSK_SL_TOKEN_UIMAGE2D,
GSK_SL_TOKEN_IMAGE3D,
GSK_SL_TOKEN_IIMAGE3D,
GSK_SL_TOKEN_UIMAGE3D,
GSK_SL_TOKEN_IMAGE2DRECT,
GSK_SL_TOKEN_IIMAGE2DRECT,
GSK_SL_TOKEN_UIMAGE2DRECT,
GSK_SL_TOKEN_IMAGECUBE,
GSK_SL_TOKEN_IIMAGECUBE,
GSK_SL_TOKEN_UIMAGECUBE,
GSK_SL_TOKEN_IMAGEBUFFER,
GSK_SL_TOKEN_IIMAGEBUFFER,
GSK_SL_TOKEN_UIMAGEBUFFER,
GSK_SL_TOKEN_IMAGE1DARRAY,
GSK_SL_TOKEN_IIMAGE1DARRAY,
GSK_SL_TOKEN_UIMAGE1DARRAY,
GSK_SL_TOKEN_IMAGE2DARRAY,
GSK_SL_TOKEN_IIMAGE2DARRAY,
GSK_SL_TOKEN_UIMAGE2DARRAY,
GSK_SL_TOKEN_IMAGECUBEARRAY,
GSK_SL_TOKEN_IIMAGECUBEARRAY,
GSK_SL_TOKEN_UIMAGECUBEARRAY,
GSK_SL_TOKEN_IMAGE2DMS,
GSK_SL_TOKEN_IIMAGE2DMS,
GSK_SL_TOKEN_UIMAGE2DMS,
GSK_SL_TOKEN_IMAGE2DMSARRAY,
GSK_SL_TOKEN_IIMAGE2DMSARRAY,
GSK_SL_TOKEN_UIMAGE2DMSARRAY,
GSK_SL_TOKEN_STRUCT,
GSK_SL_TOKEN_VOID,
GSK_SL_TOKEN_WHILE,
GSK_SL_TOKEN_IDENTIFIER,
GSK_SL_TOKEN_FLOATCONSTANT,
GSK_SL_TOKEN_DOUBLECONSTANT,
GSK_SL_TOKEN_INTCONSTANT,
GSK_SL_TOKEN_UINTCONSTANT,
GSK_SL_TOKEN_BOOLCONSTANT,
GSK_SL_TOKEN_LEFT_OP,
GSK_SL_TOKEN_RIGHT_OP,
GSK_SL_TOKEN_INC_OP,
GSK_SL_TOKEN_DEC_OP,
GSK_SL_TOKEN_LE_OP,
GSK_SL_TOKEN_GE_OP,
GSK_SL_TOKEN_EQ_OP,
GSK_SL_TOKEN_NE_OP,
GSK_SL_TOKEN_AND_OP,
GSK_SL_TOKEN_OR_OP,
GSK_SL_TOKEN_XOR_OP,
GSK_SL_TOKEN_MUL_ASSIGN,
GSK_SL_TOKEN_DIV_ASSIGN,
GSK_SL_TOKEN_ADD_ASSIGN,
GSK_SL_TOKEN_MOD_ASSIGN,
GSK_SL_TOKEN_LEFT_ASSIGN,
GSK_SL_TOKEN_RIGHT_ASSIGN,
GSK_SL_TOKEN_AND_ASSIGN,
GSK_SL_TOKEN_XOR_ASSIGN,
GSK_SL_TOKEN_OR_ASSIGN,
GSK_SL_TOKEN_SUB_ASSIGN,
GSK_SL_TOKEN_LEFT_PAREN,
GSK_SL_TOKEN_RIGHT_PAREN,
GSK_SL_TOKEN_LEFT_BRACKET,
GSK_SL_TOKEN_RIGHT_BRACKET,
GSK_SL_TOKEN_LEFT_BRACE,
GSK_SL_TOKEN_RIGHT_BRACE,
GSK_SL_TOKEN_DOT,
GSK_SL_TOKEN_COMMA,
GSK_SL_TOKEN_COLON,
GSK_SL_TOKEN_EQUAL,
GSK_SL_TOKEN_SEMICOLON,
GSK_SL_TOKEN_BANG,
GSK_SL_TOKEN_DASH,
GSK_SL_TOKEN_TILDE,
GSK_SL_TOKEN_PLUS,
GSK_SL_TOKEN_STAR,
GSK_SL_TOKEN_SLASH,
GSK_SL_TOKEN_PERCENT,
GSK_SL_TOKEN_LEFT_ANGLE,
GSK_SL_TOKEN_RIGHT_ANGLE,
GSK_SL_TOKEN_VERTICAL_BAR,
GSK_SL_TOKEN_CARET,
GSK_SL_TOKEN_AMPERSAND,
GSK_SL_TOKEN_QUESTION,
GSK_SL_TOKEN_HASH,
GSK_SL_TOKEN_INVARIANT,
GSK_SL_TOKEN_PRECISE,
GSK_SL_TOKEN_HIGH_PRECISION,
GSK_SL_TOKEN_MEDIUM_PRECISION,
GSK_SL_TOKEN_LOW_PRECISION,
GSK_SL_TOKEN_PRECISION
} GskSlTokenType;
typedef struct _GskSlToken GskSlToken;
typedef struct _GskSlTokenizer GskSlTokenizer;
typedef void (* GskSlTokenizerErrorFunc) (GskSlTokenizer *parser,
gboolean fatal,
const GskCodeLocation *location,
const GskSlToken *token,
const GError *error,
gpointer user_data);
struct _GskSlToken {
GskSlTokenType type;
union {
gint32 i32;
guint32 u32;
float f;
double d;
gboolean b;
char *str;
};
};
void gsk_sl_token_clear (GskSlToken *token);
void gsk_sl_token_copy (GskSlToken *dest,
const GskSlToken *src);
gboolean gsk_sl_string_is_valid_identifier (const char *ident);
void gsk_sl_token_init_from_identifier (GskSlToken *token,
const char *ident);
gboolean gsk_sl_token_is_skipped (const GskSlToken *token);
#define gsk_sl_token_is(token, _type) ((token)->type == (_type))
gboolean gsk_sl_token_is_ident (const GskSlToken *token,
const char *ident);
gboolean gsk_sl_token_is_function (const GskSlToken *token,
const char *ident);
void gsk_sl_token_print (const GskSlToken *token,
GString *string);
char * gsk_sl_token_to_string (const GskSlToken *token);
GskSlTokenizer * gsk_sl_tokenizer_new (GskCodeSource *source,
GskSlTokenizerErrorFunc func,
gpointer user_data,
GDestroyNotify user_destroy);
GskSlTokenizer * gsk_sl_tokenizer_ref (GskSlTokenizer *tokenizer);
void gsk_sl_tokenizer_unref (GskSlTokenizer *tokenizer);
const GskCodeLocation * gsk_sl_tokenizer_get_location (GskSlTokenizer *tokenizer);
void gsk_sl_tokenizer_read_token (GskSlTokenizer *tokenizer,
GskSlToken *token);
G_END_DECLS
#endif /* __GSK_SL_TOKENIZER_PRIVATE_H__ */

3093
gsk/gsksltype.c Normal file

File diff suppressed because it is too large Load Diff

128
gsk/gsksltypeprivate.h Normal file
View File

@@ -0,0 +1,128 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_SL_TYPE_PRIVATE_H__
#define __GSK_SL_TYPE_PRIVATE_H__
#include <glib.h>
#include "gsksltypesprivate.h"
#include "gskspvenumsprivate.h"
G_BEGIN_DECLS
typedef struct _GskSlTypeBuilder GskSlTypeBuilder;
gsize gsk_sl_scalar_type_get_size (GskSlScalarType type);
GskSlType * gsk_sl_type_new_array (GskSlType *type,
gsize length);
GskSlType * gsk_sl_type_new_parse (GskSlScope *scope,
GskSlPreprocessor *preproc);
GskSlType * gsk_sl_type_parse_array (GskSlType *type,
GskSlScope *scope,
GskSlPreprocessor *preproc);
GskSlType * gsk_sl_type_get_void (void);
GskSlType * gsk_sl_type_get_scalar (GskSlScalarType scalar);
GskSlType * gsk_sl_type_get_vector (GskSlScalarType scalar,
guint length);
GskSlType * gsk_sl_type_get_matrix (GskSlScalarType scalar,
guint columns,
guint rows);
GskSlType * gsk_sl_type_get_sampler (GskSlSamplerType sampler);
GskSlType * gsk_sl_type_get_matching (GskSlType *type,
GskSlScalarType scalar);
GskSlType * gsk_sl_type_ref (GskSlType *type);
void gsk_sl_type_unref (GskSlType *type);
gboolean gsk_sl_type_is_void (const GskSlType *type);
gboolean gsk_sl_type_is_scalar (const GskSlType *type);
gboolean gsk_sl_type_is_vector (const GskSlType *type);
gboolean gsk_sl_type_is_matrix (const GskSlType *type);
gboolean gsk_sl_type_is_basic (const GskSlType *type);
gboolean gsk_sl_type_is_array (const GskSlType *type);
gboolean gsk_sl_type_is_struct (const GskSlType *type);
gboolean gsk_sl_type_is_block (const GskSlType *type);
gboolean gsk_sl_type_is_sampler (const GskSlType *type);
gboolean gsk_sl_type_is_opaque (const GskSlType *type);
gboolean gsk_sl_type_contains_opaque (const GskSlType *type);
const char * gsk_sl_type_get_name (const GskSlType *type);
GskSlScalarType gsk_sl_type_get_scalar_type (const GskSlType *type);
const GskSlImageType * gsk_sl_type_get_image_type (const GskSlType *type);
GskSlType * gsk_sl_type_get_index_type (const GskSlType *type);
gsize gsk_sl_type_get_index_stride (const GskSlType *type);
guint gsk_sl_type_get_length (const GskSlType *type);
gsize gsk_sl_type_get_size (const GskSlType *type);
gsize gsk_sl_type_get_n_components (const GskSlType *type);
guint gsk_sl_type_get_n_members (const GskSlType *type);
GskSlType * gsk_sl_type_get_member_type (const GskSlType *type,
guint n);
const char * gsk_sl_type_get_member_name (const GskSlType *type,
guint n);
gsize gsk_sl_type_get_member_offset (const GskSlType *type,
guint n);
gboolean gsk_sl_type_find_member (const GskSlType *type,
const char *name,
guint *out_index,
GskSlType **out_type,
gsize *out_offset);
gboolean gsk_sl_scalar_type_can_convert (GskSlScalarType target,
GskSlScalarType source);
gboolean gsk_sl_type_can_convert (const GskSlType *target,
const GskSlType *source);
gboolean gsk_sl_type_equal (gconstpointer a,
gconstpointer b);
guint gsk_sl_type_hash (gconstpointer type);
guint32 gsk_sl_type_write_spv (GskSlType *type,
GskSpvWriter *writer);
void gsk_sl_type_print_value (const GskSlType *type,
GskSlPrinter *printer,
gconstpointer value);
gboolean gsk_sl_type_value_equal (const GskSlType *type,
gconstpointer a,
gconstpointer b);
guint32 gsk_sl_type_write_value_spv (GskSlType *type,
GskSpvWriter *writer,
gconstpointer value);
void gsk_sl_scalar_type_convert_value (GskSlScalarType target_type,
gpointer target_value,
GskSlScalarType source_type,
gconstpointer source_value);
GskSlTypeBuilder * gsk_sl_type_builder_new_struct (const char *name);
GskSlTypeBuilder * gsk_sl_type_builder_new_block (const char *name);
GskSlType * gsk_sl_type_builder_free (GskSlTypeBuilder *builder);
void gsk_sl_type_builder_add_member (GskSlTypeBuilder *builder,
GskSlType *type,
const char *name);
void gsk_sl_type_builder_add_builtin_member (GskSlTypeBuilder *builder,
GskSlType *type,
const char *name,
GskSpvBuiltIn builtin);
gboolean gsk_sl_type_builder_has_member (GskSlTypeBuilder *builder,
const char *name);
G_END_DECLS
#endif /* __GSK_SL_TYPE_PRIVATE_H__ */

118
gsk/gsksltypesprivate.h Normal file
View File

@@ -0,0 +1,118 @@
/* GSK - The GTK Scene Kit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_SL_TYPES_H__
#define __GSK_SL_TYPES_H__
#include <gsk/gsktypes.h>
typedef struct _GskSlDeclaration GskSlDeclaration;
typedef struct _GskSlEnvironment GskSlEnvironment;
typedef struct _GskSlExpression GskSlExpression;
typedef struct _GskSlFunction GskSlFunction;
typedef struct _GskSlFunctionMatcher GskSlFunctionMatcher;
typedef struct _GskSlFunctionType GskSlFunctionType;
typedef struct _GskSlImageType GskSlImageType;
typedef struct _GskSlNativeFunction GskSlNativeFunction;
typedef struct _GskSlPreprocessor GskSlPreprocessor;
typedef struct _GskSlPointerType GskSlPointerType;
typedef struct _GskSlPrinter GskSlPrinter;
typedef struct _GskSlQualifier GskSlQualifier;
typedef struct _GskSlScope GskSlScope;
typedef struct _GskSlStatement GskSlStatement;
typedef struct _GskSlToken GskSlToken;
typedef struct _GskSlType GskSlType;
typedef struct _GskSlValue GskSlValue;
typedef struct _GskSlVariable GskSlVariable;
typedef struct _GskSpvAccessChain GskSpvAccessChain;
typedef struct _GskSpvWriter GskSpvWriter;
typedef void (* GskSpvWriterFunc) (GskSpvWriter *, gpointer);
typedef enum {
GSK_SL_VOID,
GSK_SL_FLOAT,
GSK_SL_DOUBLE,
GSK_SL_INT,
GSK_SL_UINT,
GSK_SL_BOOL
} GskSlScalarType;
typedef enum {
GSK_SL_SAMPLER_1D,
GSK_SL_SAMPLER_1D_INT,
GSK_SL_SAMPLER_1D_UINT,
GSK_SL_SAMPLER_1D_SHADOW,
GSK_SL_SAMPLER_2D,
GSK_SL_SAMPLER_2D_INT,
GSK_SL_SAMPLER_2D_UINT,
GSK_SL_SAMPLER_2D_SHADOW,
GSK_SL_SAMPLER_3D,
GSK_SL_SAMPLER_3D_INT,
GSK_SL_SAMPLER_3D_UINT,
GSK_SL_SAMPLER_CUBE,
GSK_SL_SAMPLER_CUBE_INT,
GSK_SL_SAMPLER_CUBE_UINT,
GSK_SL_SAMPLER_CUBE_SHADOW,
GSK_SL_SAMPLER_2D_RECT,
GSK_SL_SAMPLER_2D_RECT_INT,
GSK_SL_SAMPLER_2D_RECT_UINT,
GSK_SL_SAMPLER_2D_RECT_SHADOW,
GSK_SL_SAMPLER_1D_ARRAY,
GSK_SL_SAMPLER_1D_ARRAY_INT,
GSK_SL_SAMPLER_1D_ARRAY_UINT,
GSK_SL_SAMPLER_1D_ARRAY_SHADOW,
GSK_SL_SAMPLER_2D_ARRAY,
GSK_SL_SAMPLER_2D_ARRAY_INT,
GSK_SL_SAMPLER_2D_ARRAY_UINT,
GSK_SL_SAMPLER_2D_ARRAY_SHADOW,
GSK_SL_SAMPLER_CUBE_ARRAY,
GSK_SL_SAMPLER_CUBE_ARRAY_INT,
GSK_SL_SAMPLER_CUBE_ARRAY_UINT,
GSK_SL_SAMPLER_CUBE_ARRAY_SHADOW,
GSK_SL_SAMPLER_BUFFER,
GSK_SL_SAMPLER_BUFFER_INT,
GSK_SL_SAMPLER_BUFFER_UINT,
GSK_SL_SAMPLER_2DMS,
GSK_SL_SAMPLER_2DMS_INT,
GSK_SL_SAMPLER_2DMS_UINT,
GSK_SL_SAMPLER_2DMS_ARRAY,
GSK_SL_SAMPLER_2DMS_ARRAY_INT,
GSK_SL_SAMPLER_2DMS_ARRAY_UINT,
GSK_SL_N_SAMPLER_TYPES
} GskSlSamplerType;
typedef enum {
GSK_SL_STORAGE_DEFAULT,
GSK_SL_STORAGE_GLOBAL,
GSK_SL_STORAGE_GLOBAL_CONST,
GSK_SL_STORAGE_GLOBAL_IN,
GSK_SL_STORAGE_GLOBAL_OUT,
GSK_SL_STORAGE_GLOBAL_UNIFORM,
GSK_SL_STORAGE_LOCAL,
GSK_SL_STORAGE_LOCAL_CONST,
GSK_SL_STORAGE_PARAMETER_IN,
GSK_SL_STORAGE_PARAMETER_OUT,
GSK_SL_STORAGE_PARAMETER_INOUT,
GSK_SL_STORAGE_PARAMETER_CONST
} GskSlStorage;
#endif /* __GSK_SL_TYPES_H__ */

348
gsk/gskslvalue.c Normal file
View File

@@ -0,0 +1,348 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gskslvalueprivate.h"
#include "gskslprinterprivate.h"
#include "gsksltypeprivate.h"
#include "gskspvwriterprivate.h"
struct _GskSlValue {
GskSlType *type;
gpointer data;
GDestroyNotify free_func;
gpointer user_data;
};
GskSlValue *
gsk_sl_value_new (GskSlType *type)
{
gpointer data;
g_return_val_if_fail (gsk_sl_type_get_size (type) > 0, NULL);
data = g_malloc0 (gsk_sl_type_get_size (type));
return gsk_sl_value_new_for_data (type, data, g_free, data);
}
GskSlValue *
gsk_sl_value_new_for_data (GskSlType *type,
gpointer data,
GDestroyNotify free_func,
gpointer user_data)
{
GskSlValue *value;
g_return_val_if_fail (gsk_sl_type_get_size (type) > 0, NULL);
g_return_val_if_fail (data != NULL, NULL);
value = g_slice_new0 (GskSlValue);
value->type = gsk_sl_type_ref (type);
value->data = data;
value->free_func = free_func;
value->user_data = user_data;
return value;
}
/**
* gsk_sl_value_new_convert:
* @source: value to convert
* @new_type: type to convert to
*
* Converts @source into the @new_type. This function uses the extended
* conversion rules for constructors. If you want to restrict yourself
* to the usual conversion rules, call this function after checking
* for compatibility via gsk_sl_type_can_convert().
*
* Returns: a new value containing the converted @source or %NULL
* if the source cannot be converted to @type.
**/
GskSlValue *
gsk_sl_value_new_convert (GskSlValue *source,
GskSlType *new_type)
{
GskSlValue *result;
if (gsk_sl_type_equal (source->type, new_type))
{
return gsk_sl_value_copy (source);
}
else if (gsk_sl_type_is_scalar (source->type))
{
if (!gsk_sl_type_is_scalar (new_type))
return NULL;
result = gsk_sl_value_new (new_type);
gsk_sl_scalar_type_convert_value (gsk_sl_type_get_scalar_type (new_type),
result->data,
gsk_sl_type_get_scalar_type (source->type),
source->data);
return result;
}
else if (gsk_sl_type_is_vector (source->type))
{
guchar *sdata, *ddata;
gsize sstride, dstride;
guint i, n;
if (!gsk_sl_type_is_vector (new_type) ||
gsk_sl_type_get_length (new_type) != gsk_sl_type_get_length (source->type))
return NULL;
n = gsk_sl_type_get_length (new_type);
result = gsk_sl_value_new (new_type);
sdata = source->data;
ddata = result->data;
sstride = gsk_sl_type_get_index_stride (source->type);
dstride = gsk_sl_type_get_index_stride (new_type);
for (i = 0; i < n; i++)
{
gsk_sl_scalar_type_convert_value (gsk_sl_type_get_scalar_type (new_type),
ddata + i * dstride,
gsk_sl_type_get_scalar_type (source->type),
sdata + i * sstride);
}
return result;
}
else if (gsk_sl_type_is_matrix (source->type))
{
guchar *sdata, *ddata;
gsize sstride, dstride;
guint i, n;
if (!gsk_sl_type_is_matrix (new_type) ||
gsk_sl_type_get_length (new_type) != gsk_sl_type_get_length (source->type) ||
gsk_sl_type_get_length (gsk_sl_type_get_index_type (new_type)) != gsk_sl_type_get_length (gsk_sl_type_get_index_type (source->type)))
return NULL;
n = gsk_sl_type_get_length (new_type) * gsk_sl_type_get_length (gsk_sl_type_get_index_type (source->type));
result = gsk_sl_value_new (new_type);
sdata = source->data;
ddata = result->data;
sstride = gsk_sl_type_get_size (source->type) / n;
dstride = gsk_sl_type_get_size (new_type) / n;
for (i = 0; i < n; i++)
{
gsk_sl_scalar_type_convert_value (gsk_sl_type_get_scalar_type (new_type),
ddata + i * dstride,
gsk_sl_type_get_scalar_type (source->type),
sdata + i * sstride);
}
return result;
}
else
{
return NULL;
}
}
GskSlValue *
gsk_sl_value_new_index (GskSlValue *value,
gsize n)
{
GskSlType *index_type;
gpointer data;
if (n >= gsk_sl_type_get_length (value->type))
return NULL;
index_type = gsk_sl_type_get_index_type (value->type);
data = g_memdup ((guchar *) value->data + gsk_sl_type_get_index_stride (value->type) * n,
gsk_sl_type_get_size (index_type));
return gsk_sl_value_new_for_data (index_type, data, g_free, data);
}
GskSlValue *
gsk_sl_value_new_member (GskSlValue *value,
guint n)
{
GskSlType *member_type;
gpointer data;
member_type = gsk_sl_type_get_member_type (value->type, n);
data = g_memdup ((guchar *) value->data + gsk_sl_type_get_member_offset (value->type, n),
gsk_sl_type_get_size (member_type));
return gsk_sl_value_new_for_data (member_type, data, g_free, data);
}
/**
* gsk_sl_value_convert_components:
* @source: (transfer full): value to convert
* @scalar: new scalar type to convert to
*
* Converts the scalar components of @source into the @scalar.
* This function uses the extended conversion rules for constructors.
*
* Returns: A value containing the converted values. This may or may not
* be the original @source.
**/
GskSlValue *
gsk_sl_value_convert_components (GskSlValue *source,
GskSlScalarType scalar)
{
GskSlValue *result;
GskSlType *result_type;
guchar *sdata, *ddata;
gsize sstride, dstride;
gsize i, n;
GskSlScalarType sscalar;
sscalar = gsk_sl_type_get_scalar_type (source->type);
if (sscalar == scalar)
return source;
result_type = gsk_sl_type_get_matching (source->type, scalar);
result = gsk_sl_value_new (result_type);
n = gsk_sl_type_get_n_components (result_type);
sdata = gsk_sl_value_get_data (source);
sstride = gsk_sl_scalar_type_get_size (sscalar);
ddata = gsk_sl_value_get_data (result);
dstride = gsk_sl_scalar_type_get_size (scalar);
for (i = 0; i < n; i++)
{
gsk_sl_scalar_type_convert_value (scalar,
ddata + i * dstride,
sscalar,
sdata + i * sstride);
}
gsk_sl_value_free (source);
return result;
}
GskSlValue *
gsk_sl_value_copy (const GskSlValue *source)
{
gpointer data;
data = g_memdup (source->data, gsk_sl_type_get_size (source->type));
return gsk_sl_value_new_for_data (source->type, data, g_free, data);
}
void
gsk_sl_value_free (GskSlValue *value)
{
if (value == NULL)
return;
if (value->free_func)
value->free_func (value->user_data);
gsk_sl_type_unref (value->type);
g_slice_free (GskSlValue, value);
}
void
gsk_sl_value_componentwise (GskSlValue *value,
void (* func) (gpointer, gpointer),
gpointer user_data)
{
gsize stride;
gsize i, n;
g_return_if_fail (gsk_sl_type_get_n_components (value->type) > 0);
stride = gsk_sl_scalar_type_get_size (gsk_sl_type_get_scalar_type (value->type));
n = gsk_sl_type_get_n_components (value->type);
for (i = 0; i < n; i++)
{
func ((guchar *) value->data + stride * i, user_data);
}
}
void
gsk_sl_value_print (const GskSlValue *value,
GskSlPrinter *printer)
{
gsk_sl_type_print_value (value->type, printer, value->data);
}
char *
gsk_sl_value_to_string (const GskSlValue *value)
{
GskSlPrinter *printer;
char *s;
printer = gsk_sl_printer_new ();
gsk_sl_value_print (value, printer);
s = gsk_sl_printer_write_to_string (printer);
gsk_sl_printer_unref (printer);
return s;
}
GskSlType *
gsk_sl_value_get_type (const GskSlValue *value)
{
return value->type;
}
gpointer
gsk_sl_value_get_data (const GskSlValue *value)
{
return value->data;
}
gboolean
gsk_sl_value_equal (gconstpointer a_,
gconstpointer b_)
{
const GskSlValue *a = a_;
const GskSlValue *b = b_;
if (!gsk_sl_type_equal (a->type, b->type))
return FALSE;
return gsk_sl_type_value_equal (a->type, a->data, b->data);
}
guint
gsk_sl_value_hash (gconstpointer value_)
{
const GskSlValue *value = value_;
/* XXX: We definitely want to hash the data here ! */
return gsk_sl_type_hash (value->type);
}
guint32
gsk_sl_value_write_spv (const GskSlValue *value,
GskSpvWriter *writer)
{
return gsk_sl_type_write_value_spv (value->type, writer, value->data);
}

61
gsk/gskslvalueprivate.h Normal file
View File

@@ -0,0 +1,61 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_SL_VALUE_PRIVATE_H__
#define __GSK_SL_VALUE_PRIVATE_H__
#include "gsk/gsksltypesprivate.h"
G_BEGIN_DECLS
GskSlValue * gsk_sl_value_new (GskSlType *type);
GskSlValue * gsk_sl_value_new_for_data (GskSlType *type,
gpointer data,
GDestroyNotify free_func,
gpointer user_data);
GskSlValue * gsk_sl_value_new_convert (GskSlValue *source,
GskSlType *new_type);
GskSlValue * gsk_sl_value_new_index (GskSlValue *value,
gsize n);
GskSlValue * gsk_sl_value_new_member (GskSlValue *value,
guint n);
GskSlValue * gsk_sl_value_copy (const GskSlValue *source);
void gsk_sl_value_free (GskSlValue *value);
GskSlValue * gsk_sl_value_convert_components (GskSlValue *source,
GskSlScalarType scalar);
void gsk_sl_value_componentwise (GskSlValue *value,
void (* func) (gpointer, gpointer),
gpointer user_data);
void gsk_sl_value_print (const GskSlValue *value,
GskSlPrinter *printer);
char * gsk_sl_value_to_string (const GskSlValue *value);
GskSlType * gsk_sl_value_get_type (const GskSlValue *value);
gpointer gsk_sl_value_get_data (const GskSlValue *value);
gboolean gsk_sl_value_equal (gconstpointer a,
gconstpointer b);
guint gsk_sl_value_hash (gconstpointer type);
guint32 gsk_sl_value_write_spv (const GskSlValue *value,
GskSpvWriter *writer);
G_END_DECLS
#endif /* __GSK_SL_VALUE_PRIVATE_H__ */

844
gsk/gskslvariable.c Normal file
View File

@@ -0,0 +1,844 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gskslvariableprivate.h"
#include "gskslexpressionprivate.h"
#include "gskslprinterprivate.h"
#include "gskslqualifierprivate.h"
#include "gsksltypeprivate.h"
#include "gskslvalueprivate.h"
#include "gskspvwriterprivate.h"
typedef struct _GskSlVariableClass GskSlVariableClass;
struct _GskSlVariable {
const GskSlVariableClass *class;
guint ref_count;
char *name;
GskSlType *type;
GskSlQualifier qualifier;
};
struct _GskSlVariableClass
{
gsize size;
void (* free) (GskSlVariable *variable);
GskSlValue * (* get_initial_value) (const GskSlVariable *variable);
GskSpvAccessChain * (* get_access_chain) (GskSlVariable *variable,
GskSpvWriter *writer);
guint32 (* write_spv) (const GskSlVariable *variable,
GskSpvWriter *writer);
guint32 (* load_spv) (GskSlVariable *variable,
GskSpvWriter *writer);
};
static gpointer
gsk_sl_variable_alloc (const GskSlVariableClass *klass,
const char *name,
const GskSlQualifier *qualifier,
GskSlType *type)
{
GskSlVariable *variable;
variable = g_slice_alloc0 (klass->size);
variable->class = klass;
variable->ref_count = 1;
variable->name = g_strdup (name);
variable->qualifier = *qualifier;
variable->type = gsk_sl_type_ref (type);
return variable;
}
static void
gsk_sl_variable_free (GskSlVariable *variable)
{
gsk_sl_type_unref (variable->type);
g_free (variable->name);
g_slice_free1 (variable->class->size, variable);
}
static GskSlValue *
gsk_sl_variable_default_get_initial_value (const GskSlVariable *variable)
{
return NULL;
}
static GskSpvAccessChain *
gsk_spv_access_chain_new (GskSlVariable *variable,
GskSpvWriter *writer);
static GskSpvAccessChain *
gsk_sl_variable_default_get_access_chain (GskSlVariable *variable,
GskSpvWriter *writer)
{
return gsk_spv_access_chain_new (variable, writer);
}
static GskSpvAccessChain *
gsk_sl_variable_default_get_no_access_chain (GskSlVariable *variable,
GskSpvWriter *writer)
{
return NULL;
}
static guint32
gsk_sl_variable_default_load_spv (GskSlVariable *variable,
GskSpvWriter *writer)
{
return gsk_spv_writer_load (writer,
variable->type,
gsk_spv_writer_get_id_for_variable (writer, variable),
0);
}
/* STANDARD */
typedef struct _GskSlVariableStandard GskSlVariableStandard;
struct _GskSlVariableStandard {
GskSlVariable parent;
GskSlValue *initial_value;
};
static void
gsk_sl_variable_standard_free (GskSlVariable *variable)
{
const GskSlVariableStandard *standard = (const GskSlVariableStandard *) variable;
if (standard->initial_value)
gsk_sl_value_free (standard->initial_value);
gsk_sl_variable_free (variable);
}
static GskSlValue *
gsk_sl_variable_standard_get_initial_value (const GskSlVariable *variable)
{
const GskSlVariableStandard *standard = (const GskSlVariableStandard *) variable;
return standard->initial_value;
}
static guint32
gsk_sl_variable_standard_write_spv (const GskSlVariable *variable,
GskSpvWriter *writer)
{
const GskSlVariableStandard *standard = (const GskSlVariableStandard *) variable;
guint32 result_id;
guint32 value_id;
GskSlQualifierLocation location;
GskSpvStorageClass storage_class;
location = gsk_sl_qualifier_get_location (&variable->qualifier);
if (standard->initial_value)
value_id = gsk_spv_writer_get_id_for_value (writer, standard->initial_value);
else
value_id = 0;
storage_class = gsk_sl_qualifier_get_storage_class (&variable->qualifier, variable->type);
result_id = gsk_spv_writer_variable (writer,
location == GSK_SL_QUALIFIER_GLOBAL ? GSK_SPV_WRITER_SECTION_DEFINE : GSK_SPV_WRITER_SECTION_DECLARE,
variable->type,
storage_class,
storage_class,
value_id);
if (variable->name)
gsk_spv_writer_name (writer, result_id, variable->name);
gsk_sl_qualifier_write_spv_decorations (&variable->qualifier, writer, result_id);
return result_id;
}
static const GskSlVariableClass GSK_SL_VARIABLE_STANDARD = {
sizeof (GskSlVariableStandard),
gsk_sl_variable_standard_free,
gsk_sl_variable_standard_get_initial_value,
gsk_sl_variable_default_get_access_chain,
gsk_sl_variable_standard_write_spv,
gsk_sl_variable_default_load_spv
};
/* BUILTIN */
typedef struct _GskSlVariableBuiltin GskSlVariableBuiltin;
struct _GskSlVariableBuiltin {
GskSlVariable parent;
GskSpvBuiltIn builtin;
};
static guint32
gsk_sl_variable_builtin_write_spv (const GskSlVariable *variable,
GskSpvWriter *writer)
{
const GskSlVariableBuiltin *builtin = (const GskSlVariableBuiltin *) variable;
guint32 result_id;
GskSpvStorageClass storage_class;
storage_class = gsk_sl_qualifier_get_storage_class (&variable->qualifier, variable->type);
result_id = gsk_spv_writer_variable (writer,
GSK_SPV_WRITER_SECTION_DEFINE,
variable->type,
storage_class,
storage_class,
0);
if (variable->name)
gsk_spv_writer_name (writer, result_id, variable->name);
gsk_sl_qualifier_write_spv_decorations (&variable->qualifier, writer, result_id);
gsk_spv_writer_decorate (writer, result_id, GSK_SPV_DECORATION_BUILT_IN, (guint32[1]) { builtin->builtin }, 1);
return result_id;
}
static const GskSlVariableClass GSK_SL_VARIABLE_BUILTIN = {
sizeof (GskSlVariableBuiltin),
gsk_sl_variable_free,
gsk_sl_variable_default_get_initial_value,
gsk_sl_variable_default_get_access_chain,
gsk_sl_variable_builtin_write_spv,
gsk_sl_variable_default_load_spv
};
/* CONSTANT */
typedef struct _GskSlVariableConstant GskSlVariableConstant;
struct _GskSlVariableConstant {
GskSlVariable parent;
GskSlValue *value;
};
static void
gsk_sl_variable_constant_free (GskSlVariable *variable)
{
const GskSlVariableConstant *constant = (const GskSlVariableConstant *) variable;
gsk_sl_value_free (constant->value);
gsk_sl_variable_free (variable);
}
static GskSlValue *
gsk_sl_variable_constant_get_initial_value (const GskSlVariable *variable)
{
const GskSlVariableConstant *constant = (const GskSlVariableConstant *) variable;
return constant->value;
}
static guint32
gsk_sl_variable_constant_write_spv (const GskSlVariable *variable,
GskSpvWriter *writer)
{
return 0;
}
static guint32
gsk_sl_variable_constant_load_spv (GskSlVariable *variable,
GskSpvWriter *writer)
{
const GskSlVariableConstant *constant = (const GskSlVariableConstant *) variable;
return gsk_spv_writer_get_id_for_value (writer, constant->value);
}
static const GskSlVariableClass GSK_SL_VARIABLE_CONSTANT = {
sizeof (GskSlVariableConstant),
gsk_sl_variable_constant_free,
gsk_sl_variable_constant_get_initial_value,
gsk_sl_variable_default_get_no_access_chain,
gsk_sl_variable_constant_write_spv,
gsk_sl_variable_constant_load_spv
};
/* PARAMETER */
static guint32
gsk_sl_variable_parameter_write_spv (const GskSlVariable *variable,
GskSpvWriter *writer)
{
guint32 type_id, result_id;
type_id = gsk_spv_writer_get_id_for_pointer_type (writer,
variable->type,
GSK_SPV_STORAGE_CLASS_FUNCTION);
result_id = gsk_spv_writer_function_parameter (writer, type_id);
gsk_spv_writer_name (writer, result_id, variable->name);
return result_id;
}
static const GskSlVariableClass GSK_SL_VARIABLE_PARAMETER = {
sizeof (GskSlVariable),
gsk_sl_variable_free,
gsk_sl_variable_default_get_initial_value,
gsk_sl_variable_default_get_access_chain,
gsk_sl_variable_parameter_write_spv,
gsk_sl_variable_default_load_spv
};
/* CONST_PARAMETER */
static guint32
gsk_sl_variable_const_parameter_write_spv (const GskSlVariable *variable,
GskSpvWriter *writer)
{
guint32 result_id, type_id;
type_id = gsk_spv_writer_get_id_for_type (writer, variable->type);
result_id = gsk_spv_writer_function_parameter (writer, type_id);
gsk_spv_writer_name (writer, result_id, variable->name);
return result_id;
}
static guint32
gsk_sl_variable_const_parameter_load_spv (GskSlVariable *variable,
GskSpvWriter *writer)
{
return gsk_spv_writer_get_id_for_variable (writer, variable);
}
static const GskSlVariableClass GSK_SL_VARIABLE_CONST_PARAMETER = {
sizeof (GskSlVariable),
gsk_sl_variable_free,
gsk_sl_variable_default_get_initial_value,
gsk_sl_variable_default_get_no_access_chain,
gsk_sl_variable_const_parameter_write_spv,
gsk_sl_variable_const_parameter_load_spv
};
/* MEMBER */
typedef struct _GskSlVariableMember GskSlVariableMember;
struct _GskSlVariableMember {
GskSlVariable parent;
GskSlVariable *block;
gsize member_id;
};
static void
gsk_sl_variable_member_free (GskSlVariable *variable)
{
const GskSlVariableMember *member = (const GskSlVariableMember *) variable;
gsk_sl_variable_unref (member->block);
gsk_sl_variable_free (variable);
}
static GskSpvAccessChain *
gsk_sl_variable_member_get_access_chain (GskSlVariable *variable,
GskSpvWriter *writer)
{
const GskSlVariableMember *member = (const GskSlVariableMember *) variable;
GskSpvAccessChain *chain;
GskSlValue *value;
chain = gsk_sl_variable_get_access_chain (member->block, writer);
value = gsk_sl_value_new_for_data (gsk_sl_type_get_scalar (GSK_SL_INT), &(gint32) { member->member_id }, NULL, NULL);
gsk_spv_access_chain_add_index (chain,
variable->type,
gsk_spv_writer_get_id_for_value (writer, value));
gsk_sl_value_free (value);
return chain;
}
static guint32
gsk_sl_variable_member_write_spv (const GskSlVariable *variable,
GskSpvWriter *writer)
{
const GskSlVariableMember *member = (const GskSlVariableMember *) variable;
return gsk_spv_writer_get_id_for_variable (writer, member->block);
}
static const GskSlVariableClass GSK_SL_VARIABLE_MEMBER = {
sizeof (GskSlVariableMember),
gsk_sl_variable_member_free,
gsk_sl_variable_default_get_initial_value,
gsk_sl_variable_member_get_access_chain,
gsk_sl_variable_member_write_spv,
gsk_sl_variable_default_load_spv
};
/* API */
GskSlVariable *
gsk_sl_variable_new (const char *name,
GskSlType *type,
const GskSlQualifier *qualifier,
GskSlValue *initial_value)
{
g_return_val_if_fail (initial_value == NULL || gsk_sl_type_equal (type, gsk_sl_value_get_type (initial_value)), NULL);
switch (qualifier->storage)
{
case GSK_SL_STORAGE_GLOBAL_CONST:
g_assert (initial_value != NULL);
case GSK_SL_STORAGE_LOCAL_CONST:
if (initial_value)
{
GskSlVariableConstant *constant = gsk_sl_variable_alloc (&GSK_SL_VARIABLE_CONSTANT, name, qualifier, type);
constant->value = initial_value;
return &constant->parent;
}
/* else fall through */
case GSK_SL_STORAGE_GLOBAL:
case GSK_SL_STORAGE_GLOBAL_IN:
case GSK_SL_STORAGE_GLOBAL_OUT:
case GSK_SL_STORAGE_GLOBAL_UNIFORM:
case GSK_SL_STORAGE_LOCAL:
{
GskSlVariableStandard *standard = gsk_sl_variable_alloc (&GSK_SL_VARIABLE_STANDARD, name, qualifier, type);
standard->initial_value = initial_value;
return &standard->parent;
}
case GSK_SL_STORAGE_PARAMETER_IN:
case GSK_SL_STORAGE_PARAMETER_OUT:
case GSK_SL_STORAGE_PARAMETER_INOUT:
g_assert (initial_value == NULL);
return gsk_sl_variable_alloc (&GSK_SL_VARIABLE_PARAMETER, name, qualifier, type);
case GSK_SL_STORAGE_PARAMETER_CONST:
g_assert (initial_value == NULL);
return gsk_sl_variable_alloc (&GSK_SL_VARIABLE_CONST_PARAMETER, name, qualifier, type);
case GSK_SL_STORAGE_DEFAULT:
default:
g_assert_not_reached ();
return NULL;
}
}
GskSlVariable *
gsk_sl_variable_new_block_member (GskSlVariable *block,
guint member_id)
{
GskSlVariableMember *member;
g_return_val_if_fail (block != NULL, NULL);
g_return_val_if_fail (gsk_sl_type_is_block (block->type), NULL);
g_return_val_if_fail (member_id < gsk_sl_type_get_n_members (block->type), NULL);
member = gsk_sl_variable_alloc (&GSK_SL_VARIABLE_MEMBER,
gsk_sl_type_get_member_name (block->type, member_id),
&block->qualifier,
gsk_sl_type_get_member_type (block->type, member_id));
member->block = gsk_sl_variable_ref (block);
member->member_id = member_id;
return &member->parent;
}
GskSlVariable *
gsk_sl_variable_new_builtin (const char *name,
GskSlType *type,
const GskSlQualifier *qualifier,
GskSpvBuiltIn builtin)
{
GskSlVariableBuiltin *builtin_var;
builtin_var = gsk_sl_variable_alloc (&GSK_SL_VARIABLE_BUILTIN, name, qualifier, type);
builtin_var->builtin = builtin;
return &builtin_var->parent;
}
GskSlVariable *
gsk_sl_variable_ref (GskSlVariable *variable)
{
g_return_val_if_fail (variable != NULL, NULL);
variable->ref_count += 1;
return variable;
}
void
gsk_sl_variable_unref (GskSlVariable *variable)
{
if (variable == NULL)
return;
variable->ref_count -= 1;
if (variable->ref_count > 0)
return;
variable->class->free (variable);
}
void
gsk_sl_variable_print (const GskSlVariable *variable,
GskSlPrinter *printer)
{
if (gsk_sl_qualifier_print (&variable->qualifier, printer))
gsk_sl_printer_append (printer, " ");
gsk_sl_printer_append (printer, gsk_sl_type_get_name (variable->type));
if (gsk_sl_type_is_block (variable->type))
{
guint i, n;
gsk_sl_printer_append (printer, " {");
gsk_sl_printer_push_indentation (printer);
n = gsk_sl_type_get_n_members (variable->type);
for (i = 0; i < n; i++)
{
gsk_sl_printer_newline (printer);
gsk_sl_printer_append (printer, gsk_sl_type_get_name (gsk_sl_type_get_member_type (variable->type, i)));
gsk_sl_printer_append (printer, " ");
gsk_sl_printer_append (printer, gsk_sl_type_get_member_name (variable->type, i));
gsk_sl_printer_append (printer, ";");
}
gsk_sl_printer_pop_indentation (printer);
gsk_sl_printer_newline (printer);
gsk_sl_printer_append (printer, "}");
}
if (variable->name)
{
gsk_sl_printer_append (printer, " ");
gsk_sl_printer_append (printer, variable->name);
}
}
GskSlType *
gsk_sl_variable_get_type (const GskSlVariable *variable)
{
return variable->type;
}
const GskSlQualifier *
gsk_sl_variable_get_qualifier (const GskSlVariable *variable)
{
return &variable->qualifier;
}
const char *
gsk_sl_variable_get_name (const GskSlVariable *variable)
{
return variable->name;
}
const GskSlValue *
gsk_sl_variable_get_initial_value (const GskSlVariable *variable)
{
return variable->class->get_initial_value (variable);
}
gboolean
gsk_sl_variable_is_constant (const GskSlVariable *variable)
{
return gsk_sl_qualifier_is_constant (&variable->qualifier);
}
GskSpvAccessChain *
gsk_sl_variable_get_access_chain (GskSlVariable *variable,
GskSpvWriter *writer)
{
return variable->class->get_access_chain (variable, writer);
}
guint32
gsk_sl_variable_write_spv (const GskSlVariable *variable,
GskSpvWriter *writer)
{
return variable->class->write_spv (variable, writer);
}
guint32
gsk_sl_variable_load_spv (GskSlVariable *variable,
GskSpvWriter *writer)
{
return variable->class->load_spv (variable, writer);
}
/* ACCESS CHAIN */
struct _GskSpvAccessChain
{
GskSpvWriter *writer;
GskSlVariable *variable;
GskSlType *type;
GArray *chain;
GSList *pending_indexes;
guint32 swizzle[4];
guint swizzle_length;
};
static GskSpvAccessChain *
gsk_spv_access_chain_new (GskSlVariable *variable,
GskSpvWriter *writer)
{
GskSpvAccessChain *chain;
chain = g_slice_new0 (GskSpvAccessChain);
chain->writer = gsk_spv_writer_ref (writer);
chain->variable = gsk_sl_variable_ref (variable);
chain->type = gsk_sl_type_ref (gsk_sl_variable_get_type (variable));
return chain;
}
void
gsk_spv_access_chain_free (GskSpvAccessChain *chain)
{
if (chain->chain)
g_array_free (chain->chain, TRUE);
g_slist_free_full (chain->pending_indexes, (GDestroyNotify) gsk_sl_expression_unref);
gsk_sl_type_unref (chain->type);
gsk_sl_variable_unref (chain->variable);
gsk_spv_writer_unref (chain->writer);
g_slice_free (GskSpvAccessChain, chain);
}
void
gsk_spv_access_chain_add_index (GskSpvAccessChain *chain,
GskSlType *type,
guint32 index_id)
{
g_assert (!gsk_spv_access_chain_has_swizzle (chain));
if (chain->chain == NULL)
chain->chain = g_array_new (FALSE, FALSE, sizeof (guint32));
gsk_sl_type_unref (chain->type);
chain->type = gsk_sl_type_ref (type);
g_array_append_val (chain->chain, index_id);
}
void
gsk_spv_access_chain_add_dynamic_index (GskSpvAccessChain *chain,
GskSlType *type,
GskSlExpression *expr)
{
gsk_spv_access_chain_add_index (chain, type, 0);
chain->pending_indexes = g_slist_prepend (chain->pending_indexes, gsk_sl_expression_ref (expr));
}
gboolean
gsk_spv_access_chain_has_swizzle (GskSpvAccessChain *chain)
{
return chain->swizzle_length > 0;
}
void
gsk_spv_access_chain_swizzle (GskSpvAccessChain *chain,
const guint *indexes,
guint length)
{
guint tmp[4];
guint i;
if (length == 1)
{
GskSlValue *value;
guint32 new_index;
if (chain->swizzle_length != 0)
new_index = chain->swizzle[indexes[0]];
else
new_index = indexes[0];
chain->swizzle_length = 0;
value = gsk_sl_value_new_for_data (gsk_sl_type_get_scalar (GSK_SL_UINT),
&new_index,
NULL, NULL);
gsk_spv_access_chain_add_index (chain,
gsk_sl_type_get_index_type (chain->type),
gsk_spv_writer_get_id_for_value (chain->writer, value));
gsk_sl_value_free (value);
return;
}
if (chain->swizzle_length != 0)
{
g_assert (length <= chain->swizzle_length);
for (i = 0; i < length; i++)
{
tmp[i] = chain->swizzle[indexes[i]];
}
indexes = tmp;
}
/* Mean trick to do optimization: We only assign a swizzle_length
* If something is actually swizzled. If we're doing an identity
* swizzle, ignore it.
*/
if (length < gsk_sl_type_get_n_components (chain->type))
chain->swizzle_length = length;
else
chain->swizzle_length = 0;
for (i = 0; i < length; i++)
{
chain->swizzle[i] = indexes[i];
if (indexes[i] != i)
chain->swizzle_length = length;
}
}
static void
gsk_spv_access_resolve_pending (GskSpvAccessChain *chain)
{
GSList *l;
guint i;
if (chain->pending_indexes == NULL)
return;
i = chain->chain->len;
l = chain->pending_indexes;
while (i-- > 0)
{
if (g_array_index (chain->chain, guint32, i) != 0)
continue;
g_array_index (chain->chain, guint32, i) = gsk_sl_expression_write_spv (l->data, chain->writer, NULL);
l = l->next;
}
g_slist_free_full (chain->pending_indexes, (GDestroyNotify) gsk_sl_expression_unref);
chain->pending_indexes = NULL;
}
static guint32
gsk_spv_access_get_variable (GskSpvAccessChain *chain)
{
guint32 variable_id;
gsk_spv_access_resolve_pending (chain);
variable_id = gsk_spv_writer_get_id_for_variable (chain->writer,
chain->variable);
if (chain->chain)
variable_id = gsk_spv_writer_access_chain (chain->writer,
chain->type,
gsk_sl_qualifier_get_storage_class (gsk_sl_variable_get_qualifier (chain->variable),
gsk_sl_variable_get_type (chain->variable)),
variable_id,
(guint32 *) chain->chain->data,
chain->chain->len);
return variable_id;
}
static GskSlType *
gsk_spv_access_chain_get_swizzle_type (GskSpvAccessChain *chain)
{
g_assert (chain->swizzle_length != 0);
if (chain->swizzle_length == 1)
return gsk_sl_type_get_scalar (gsk_sl_type_get_scalar_type (chain->type));
else
return gsk_sl_type_get_vector (gsk_sl_type_get_scalar_type (chain->type), chain->swizzle_length);
}
guint32
gsk_spv_access_chain_load (GskSpvAccessChain *chain)
{
guint result_id;
result_id = gsk_spv_writer_load (chain->writer,
chain->type,
gsk_spv_access_get_variable (chain),
0);
if (chain->swizzle_length)
result_id = gsk_spv_writer_vector_shuffle (chain->writer,
gsk_spv_access_chain_get_swizzle_type (chain),
result_id,
result_id,
chain->swizzle,
chain->swizzle_length);
return result_id;
}
void
gsk_spv_access_chain_store (GskSpvAccessChain *chain,
guint32 value)
{
guint32 chain_id;
chain_id = gsk_spv_access_get_variable (chain);
if (chain->swizzle_length)
{
guint32 indexes[4] = { 0, };
guint32 merge;
guint i, n;
merge = gsk_spv_writer_load (chain->writer,
chain->type,
chain_id,
0);
n = gsk_sl_type_get_n_components (chain->type);
for (i = 0; i < n; i++)
{
if (i < chain->swizzle_length)
indexes[chain->swizzle[i]] = n + i;
if (indexes[i] == 0)
indexes[i] = i;
}
value = gsk_spv_writer_vector_shuffle (chain->writer,
chain->type,
merge,
value,
indexes,
n);
}
gsk_spv_writer_store (chain->writer,
chain_id,
value,
0);
}

View File

@@ -0,0 +1,77 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_SL_VARIABLE_PRIVATE_H__
#define __GSK_SL_VARIABLE_PRIVATE_H__
#include <glib.h>
#include "gsk/gsksltypesprivate.h"
#include "gsk/gskspvenumsprivate.h"
G_BEGIN_DECLS
GskSlVariable * gsk_sl_variable_new (const char *name,
GskSlType *type,
const GskSlQualifier *qualifier,
GskSlValue *initial_value);
GskSlVariable * gsk_sl_variable_new_block_member (GskSlVariable *block,
guint member_id);
GskSlVariable * gsk_sl_variable_new_builtin (const char *name,
GskSlType *type,
const GskSlQualifier *qualifier,
GskSpvBuiltIn builtin);
GskSlVariable * gsk_sl_variable_ref (GskSlVariable *variable);
void gsk_sl_variable_unref (GskSlVariable *variable);
void gsk_sl_variable_print (const GskSlVariable *variable,
GskSlPrinter *printer);
GskSlType * gsk_sl_variable_get_type (const GskSlVariable *variable);
const GskSlQualifier * gsk_sl_variable_get_qualifier (const GskSlVariable *variable);
const char * gsk_sl_variable_get_name (const GskSlVariable *variable);
const GskSlValue * gsk_sl_variable_get_initial_value (const GskSlVariable *variable);
gboolean gsk_sl_variable_is_constant (const GskSlVariable *variable);
GskSpvAccessChain * gsk_sl_variable_get_access_chain (GskSlVariable *variable,
GskSpvWriter *writer);
guint32 gsk_sl_variable_write_spv (const GskSlVariable *variable,
GskSpvWriter *writer);
guint32 gsk_sl_variable_load_spv (GskSlVariable *variable,
GskSpvWriter *writer);
void gsk_spv_access_chain_free (GskSpvAccessChain *chain);
void gsk_spv_access_chain_add_index (GskSpvAccessChain *chain,
GskSlType *type,
guint32 index_id);
void gsk_spv_access_chain_add_dynamic_index (GskSpvAccessChain *chain,
GskSlType *type,
GskSlExpression *expr);
void gsk_spv_access_chain_swizzle (GskSpvAccessChain *chain,
const guint *indexes,
guint n_indexes);
gboolean gsk_spv_access_chain_has_swizzle (GskSpvAccessChain *chain);
guint32 gsk_spv_access_chain_load (GskSpvAccessChain *chain);
void gsk_spv_access_chain_store (GskSpvAccessChain *chain,
guint32 value);
G_END_DECLS
#endif /* __GSK_SL_VARIABLE_PRIVATE_H__ */

View File

@@ -0,0 +1,114 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* !!! THIS FILE WAS AUTOGENERATED !!!
*
* This file was created using the command
* gjs spirv.js Glsl-enums extinst.glsl.std.450.grammar.json
* Apply any changes to those files and then regenerate using above command.
*/
#ifndef __GSK_SPV_GLSL_ENUMS_H__
#define __GSK_SPV_GLSL_ENUMS_H__
typedef enum {
GSK_SPV_OP_GLSL_ROUND = 1,
GSK_SPV_OP_GLSL_ROUND_EVEN = 2,
GSK_SPV_OP_GLSL_TRUNC = 3,
GSK_SPV_OP_GLSL_F_ABS = 4,
GSK_SPV_OP_GLSL_S_ABS = 5,
GSK_SPV_OP_GLSL_F_SIGN = 6,
GSK_SPV_OP_GLSL_S_SIGN = 7,
GSK_SPV_OP_GLSL_FLOOR = 8,
GSK_SPV_OP_GLSL_CEIL = 9,
GSK_SPV_OP_GLSL_FRACT = 10,
GSK_SPV_OP_GLSL_RADIANS = 11,
GSK_SPV_OP_GLSL_DEGREES = 12,
GSK_SPV_OP_GLSL_SIN = 13,
GSK_SPV_OP_GLSL_COS = 14,
GSK_SPV_OP_GLSL_TAN = 15,
GSK_SPV_OP_GLSL_ASIN = 16,
GSK_SPV_OP_GLSL_ACOS = 17,
GSK_SPV_OP_GLSL_ATAN = 18,
GSK_SPV_OP_GLSL_SINH = 19,
GSK_SPV_OP_GLSL_COSH = 20,
GSK_SPV_OP_GLSL_TANH = 21,
GSK_SPV_OP_GLSL_ASINH = 22,
GSK_SPV_OP_GLSL_ACOSH = 23,
GSK_SPV_OP_GLSL_ATANH = 24,
GSK_SPV_OP_GLSL_ATAN2 = 25,
GSK_SPV_OP_GLSL_POW = 26,
GSK_SPV_OP_GLSL_EXP = 27,
GSK_SPV_OP_GLSL_LOG = 28,
GSK_SPV_OP_GLSL_EXP2 = 29,
GSK_SPV_OP_GLSL_LOG2 = 30,
GSK_SPV_OP_GLSL_SQRT = 31,
GSK_SPV_OP_GLSL_INVERSE_SQRT = 32,
GSK_SPV_OP_GLSL_DETERMINANT = 33,
GSK_SPV_OP_GLSL_MATRIX_INVERSE = 34,
GSK_SPV_OP_GLSL_MODF = 35,
GSK_SPV_OP_GLSL_MODF_STRUCT = 36,
GSK_SPV_OP_GLSL_F_MIN = 37,
GSK_SPV_OP_GLSL_U_MIN = 38,
GSK_SPV_OP_GLSL_S_MIN = 39,
GSK_SPV_OP_GLSL_F_MAX = 40,
GSK_SPV_OP_GLSL_U_MAX = 41,
GSK_SPV_OP_GLSL_S_MAX = 42,
GSK_SPV_OP_GLSL_F_CLAMP = 43,
GSK_SPV_OP_GLSL_U_CLAMP = 44,
GSK_SPV_OP_GLSL_S_CLAMP = 45,
GSK_SPV_OP_GLSL_F_MIX = 46,
GSK_SPV_OP_GLSL_I_MIX = 47,
GSK_SPV_OP_GLSL_STEP = 48,
GSK_SPV_OP_GLSL_SMOOTH_STEP = 49,
GSK_SPV_OP_GLSL_FMA = 50,
GSK_SPV_OP_GLSL_FREXP = 51,
GSK_SPV_OP_GLSL_FREXP_STRUCT = 52,
GSK_SPV_OP_GLSL_LDEXP = 53,
GSK_SPV_OP_GLSL_PACK_SNORM4X8 = 54,
GSK_SPV_OP_GLSL_PACK_UNORM4X8 = 55,
GSK_SPV_OP_GLSL_PACK_SNORM2X16 = 56,
GSK_SPV_OP_GLSL_PACK_UNORM2X16 = 57,
GSK_SPV_OP_GLSL_PACK_HALF2X16 = 58,
GSK_SPV_OP_GLSL_PACK_DOUBLE2X32 = 59,
GSK_SPV_OP_GLSL_UNPACK_SNORM2X16 = 60,
GSK_SPV_OP_GLSL_UNPACK_UNORM2X16 = 61,
GSK_SPV_OP_GLSL_UNPACK_HALF2X16 = 62,
GSK_SPV_OP_GLSL_UNPACK_SNORM4X8 = 63,
GSK_SPV_OP_GLSL_UNPACK_UNORM4X8 = 64,
GSK_SPV_OP_GLSL_UNPACK_DOUBLE2X32 = 65,
GSK_SPV_OP_GLSL_LENGTH = 66,
GSK_SPV_OP_GLSL_DISTANCE = 67,
GSK_SPV_OP_GLSL_CROSS = 68,
GSK_SPV_OP_GLSL_NORMALIZE = 69,
GSK_SPV_OP_GLSL_FACE_FORWARD = 70,
GSK_SPV_OP_GLSL_REFLECT = 71,
GSK_SPV_OP_GLSL_REFRACT = 72,
GSK_SPV_OP_GLSL_FIND_I_LSB = 73,
GSK_SPV_OP_GLSL_FIND_S_MSB = 74,
GSK_SPV_OP_GLSL_FIND_U_MSB = 75,
GSK_SPV_OP_GLSL_INTERPOLATE_AT_CENTROID = 76,
GSK_SPV_OP_GLSL_INTERPOLATE_AT_SAMPLE = 77,
GSK_SPV_OP_GLSL_INTERPOLATE_AT_OFFSET = 78,
GSK_SPV_OP_GLSL_N_MIN = 79,
GSK_SPV_OP_GLSL_N_MAX = 80,
GSK_SPV_OP_GLSL_N_CLAMP = 81
} GskSpvOpcodeGlsl;
#endif /* __GSK_SPV_GLSL_ENUMS_H__ */

855
gsk/gskspvenumsprivate.h Normal file
View File

@@ -0,0 +1,855 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* !!! THIS FILE WAS AUTOGENERATED !!!
*
* This file was created using the command
* gjs spirv.js enums spirv.core.grammar.json
* Apply any changes to those files and then regenerate using above command.
*/
#ifndef __GSK_SPV_ENUMS_H__
#define __GSK_SPV_ENUMS_H__
typedef enum {
GSK_SPV_IMAGE_OPERANDS_NONE = 0x0000,
GSK_SPV_IMAGE_OPERANDS_BIAS = 0x0001,
GSK_SPV_IMAGE_OPERANDS_LOD = 0x0002,
GSK_SPV_IMAGE_OPERANDS_GRAD = 0x0004,
GSK_SPV_IMAGE_OPERANDS_CONST_OFFSET = 0x0008,
GSK_SPV_IMAGE_OPERANDS_OFFSET = 0x0010,
GSK_SPV_IMAGE_OPERANDS_CONST_OFFSETS = 0x0020,
GSK_SPV_IMAGE_OPERANDS_SAMPLE = 0x0040,
GSK_SPV_IMAGE_OPERANDS_MIN_LOD = 0x0080
} GskSpvImageOperands;
typedef enum {
GSK_SPV_FP_FAST_MATH_MODE_NONE = 0x0000,
GSK_SPV_FP_FAST_MATH_MODE_NOT_NA_N = 0x0001,
GSK_SPV_FP_FAST_MATH_MODE_NOT_INF = 0x0002,
GSK_SPV_FP_FAST_MATH_MODE_NSZ = 0x0004,
GSK_SPV_FP_FAST_MATH_MODE_ALLOW_RECIP = 0x0008,
GSK_SPV_FP_FAST_MATH_MODE_FAST = 0x0010
} GskSpvFPFastMathMode;
typedef enum {
GSK_SPV_SELECTION_CONTROL_NONE = 0x0000,
GSK_SPV_SELECTION_CONTROL_FLATTEN = 0x0001,
GSK_SPV_SELECTION_CONTROL_DONT_FLATTEN = 0x0002
} GskSpvSelectionControl;
typedef enum {
GSK_SPV_LOOP_CONTROL_NONE = 0x0000,
GSK_SPV_LOOP_CONTROL_UNROLL = 0x0001,
GSK_SPV_LOOP_CONTROL_DONT_UNROLL = 0x0002
} GskSpvLoopControl;
typedef enum {
GSK_SPV_FUNCTION_CONTROL_NONE = 0x0000,
GSK_SPV_FUNCTION_CONTROL_INLINE = 0x0001,
GSK_SPV_FUNCTION_CONTROL_DONT_INLINE = 0x0002,
GSK_SPV_FUNCTION_CONTROL_PURE = 0x0004,
GSK_SPV_FUNCTION_CONTROL_CONST = 0x0008
} GskSpvFunctionControl;
typedef enum {
GSK_SPV_MEMORY_SEMANTICS_RELAXED = 0x0000,
GSK_SPV_MEMORY_SEMANTICS_NONE = 0x0000,
GSK_SPV_MEMORY_SEMANTICS_ACQUIRE = 0x0002,
GSK_SPV_MEMORY_SEMANTICS_RELEASE = 0x0004,
GSK_SPV_MEMORY_SEMANTICS_ACQUIRE_RELEASE = 0x0008,
GSK_SPV_MEMORY_SEMANTICS_SEQUENTIALLY_CONSISTENT = 0x0010,
GSK_SPV_MEMORY_SEMANTICS_UNIFORM_MEMORY = 0x0040,
GSK_SPV_MEMORY_SEMANTICS_SUBGROUP_MEMORY = 0x0080,
GSK_SPV_MEMORY_SEMANTICS_WORKGROUP_MEMORY = 0x0100,
GSK_SPV_MEMORY_SEMANTICS_CROSS_WORKGROUP_MEMORY = 0x0200,
GSK_SPV_MEMORY_SEMANTICS_ATOMIC_COUNTER_MEMORY = 0x0400,
GSK_SPV_MEMORY_SEMANTICS_IMAGE_MEMORY = 0x0800
} GskSpvMemorySemantics;
typedef enum {
GSK_SPV_MEMORY_ACCESS_NONE = 0x0000,
GSK_SPV_MEMORY_ACCESS_VOLATILE = 0x0001,
GSK_SPV_MEMORY_ACCESS_ALIGNED = 0x0002,
GSK_SPV_MEMORY_ACCESS_NONTEMPORAL = 0x0004
} GskSpvMemoryAccess;
typedef enum {
GSK_SPV_KERNEL_PROFILING_INFO_NONE = 0x0000,
GSK_SPV_KERNEL_PROFILING_INFO_CMD_EXEC_TIME = 0x0001
} GskSpvKernelProfilingInfo;
typedef enum {
GSK_SPV_SOURCE_LANGUAGE_UNKNOWN = 0,
GSK_SPV_SOURCE_LANGUAGE_ESSL = 1,
GSK_SPV_SOURCE_LANGUAGE_GLSL = 2,
GSK_SPV_SOURCE_LANGUAGE_OPEN_CL_C = 3,
GSK_SPV_SOURCE_LANGUAGE_OPEN_CL_CPP = 4,
GSK_SPV_SOURCE_LANGUAGE_HLSL = 5
} GskSpvSourceLanguage;
typedef enum {
GSK_SPV_EXECUTION_MODEL_VERTEX = 0,
GSK_SPV_EXECUTION_MODEL_TESSELLATION_CONTROL = 1,
GSK_SPV_EXECUTION_MODEL_TESSELLATION_EVALUATION = 2,
GSK_SPV_EXECUTION_MODEL_GEOMETRY = 3,
GSK_SPV_EXECUTION_MODEL_FRAGMENT = 4,
GSK_SPV_EXECUTION_MODEL_GL_COMPUTE = 5,
GSK_SPV_EXECUTION_MODEL_KERNEL = 6
} GskSpvExecutionModel;
typedef enum {
GSK_SPV_ADDRESSING_MODEL_LOGICAL = 0,
GSK_SPV_ADDRESSING_MODEL_PHYSICAL32 = 1,
GSK_SPV_ADDRESSING_MODEL_PHYSICAL64 = 2
} GskSpvAddressingModel;
typedef enum {
GSK_SPV_MEMORY_MODEL_SIMPLE = 0,
GSK_SPV_MEMORY_MODEL_GLSL450 = 1,
GSK_SPV_MEMORY_MODEL_OPEN_CL = 2
} GskSpvMemoryModel;
typedef enum {
GSK_SPV_EXECUTION_MODE_INVOCATIONS = 0,
GSK_SPV_EXECUTION_MODE_SPACING_EQUAL = 1,
GSK_SPV_EXECUTION_MODE_SPACING_FRACTIONAL_EVEN = 2,
GSK_SPV_EXECUTION_MODE_SPACING_FRACTIONAL_ODD = 3,
GSK_SPV_EXECUTION_MODE_VERTEX_ORDER_CW = 4,
GSK_SPV_EXECUTION_MODE_VERTEX_ORDER_CCW = 5,
GSK_SPV_EXECUTION_MODE_PIXEL_CENTER_INTEGER = 6,
GSK_SPV_EXECUTION_MODE_ORIGIN_UPPER_LEFT = 7,
GSK_SPV_EXECUTION_MODE_ORIGIN_LOWER_LEFT = 8,
GSK_SPV_EXECUTION_MODE_EARLY_FRAGMENT_TESTS = 9,
GSK_SPV_EXECUTION_MODE_POINT_MODE = 10,
GSK_SPV_EXECUTION_MODE_XFB = 11,
GSK_SPV_EXECUTION_MODE_DEPTH_REPLACING = 12,
GSK_SPV_EXECUTION_MODE_DEPTH_GREATER = 14,
GSK_SPV_EXECUTION_MODE_DEPTH_LESS = 15,
GSK_SPV_EXECUTION_MODE_DEPTH_UNCHANGED = 16,
GSK_SPV_EXECUTION_MODE_LOCAL_SIZE = 17,
GSK_SPV_EXECUTION_MODE_LOCAL_SIZE_HINT = 18,
GSK_SPV_EXECUTION_MODE_INPUT_POINTS = 19,
GSK_SPV_EXECUTION_MODE_INPUT_LINES = 20,
GSK_SPV_EXECUTION_MODE_INPUT_LINES_ADJACENCY = 21,
GSK_SPV_EXECUTION_MODE_TRIANGLES = 22,
GSK_SPV_EXECUTION_MODE_INPUT_TRIANGLES_ADJACENCY = 23,
GSK_SPV_EXECUTION_MODE_QUADS = 24,
GSK_SPV_EXECUTION_MODE_ISOLINES = 25,
GSK_SPV_EXECUTION_MODE_OUTPUT_VERTICES = 26,
GSK_SPV_EXECUTION_MODE_OUTPUT_POINTS = 27,
GSK_SPV_EXECUTION_MODE_OUTPUT_LINE_STRIP = 28,
GSK_SPV_EXECUTION_MODE_OUTPUT_TRIANGLE_STRIP = 29,
GSK_SPV_EXECUTION_MODE_VEC_TYPE_HINT = 30,
GSK_SPV_EXECUTION_MODE_CONTRACTION_OFF = 31,
GSK_SPV_EXECUTION_MODE_POST_DEPTH_COVERAGE = 4446,
GSK_SPV_EXECUTION_MODE_STENCIL_REF_REPLACING_EXT = 5027
} GskSpvExecutionMode;
typedef enum {
GSK_SPV_STORAGE_CLASS_UNIFORM_CONSTANT = 0,
GSK_SPV_STORAGE_CLASS_INPUT = 1,
GSK_SPV_STORAGE_CLASS_UNIFORM = 2,
GSK_SPV_STORAGE_CLASS_OUTPUT = 3,
GSK_SPV_STORAGE_CLASS_WORKGROUP = 4,
GSK_SPV_STORAGE_CLASS_CROSS_WORKGROUP = 5,
GSK_SPV_STORAGE_CLASS_PRIVATE = 6,
GSK_SPV_STORAGE_CLASS_FUNCTION = 7,
GSK_SPV_STORAGE_CLASS_GENERIC = 8,
GSK_SPV_STORAGE_CLASS_PUSH_CONSTANT = 9,
GSK_SPV_STORAGE_CLASS_ATOMIC_COUNTER = 10,
GSK_SPV_STORAGE_CLASS_IMAGE = 11,
GSK_SPV_STORAGE_CLASS_STORAGE_BUFFER = 12
} GskSpvStorageClass;
typedef enum {
GSK_SPV_DIM_1_D = 0,
GSK_SPV_DIM_2_D = 1,
GSK_SPV_DIM_3_D = 2,
GSK_SPV_DIM_CUBE = 3,
GSK_SPV_DIM_RECT = 4,
GSK_SPV_DIM_BUFFER = 5,
GSK_SPV_DIM_SUBPASS_DATA = 6
} GskSpvDim;
typedef enum {
GSK_SPV_SAMPLER_ADDRESSING_MODE_NONE = 0,
GSK_SPV_SAMPLER_ADDRESSING_MODE_CLAMP_TO_EDGE = 1,
GSK_SPV_SAMPLER_ADDRESSING_MODE_CLAMP = 2,
GSK_SPV_SAMPLER_ADDRESSING_MODE_REPEAT = 3,
GSK_SPV_SAMPLER_ADDRESSING_MODE_REPEAT_MIRRORED = 4
} GskSpvSamplerAddressingMode;
typedef enum {
GSK_SPV_SAMPLER_FILTER_MODE_NEAREST = 0,
GSK_SPV_SAMPLER_FILTER_MODE_LINEAR = 1
} GskSpvSamplerFilterMode;
typedef enum {
GSK_SPV_IMAGE_FORMAT_UNKNOWN = 0,
GSK_SPV_IMAGE_FORMAT_RGBA32F = 1,
GSK_SPV_IMAGE_FORMAT_RGBA16F = 2,
GSK_SPV_IMAGE_FORMAT_R32F = 3,
GSK_SPV_IMAGE_FORMAT_RGBA8 = 4,
GSK_SPV_IMAGE_FORMAT_RGBA8_SNORM = 5,
GSK_SPV_IMAGE_FORMAT_RG32F = 6,
GSK_SPV_IMAGE_FORMAT_RG16F = 7,
GSK_SPV_IMAGE_FORMAT_R11F_G11F_B10F = 8,
GSK_SPV_IMAGE_FORMAT_R16F = 9,
GSK_SPV_IMAGE_FORMAT_RGBA16 = 10,
GSK_SPV_IMAGE_FORMAT_RGB10_A2 = 11,
GSK_SPV_IMAGE_FORMAT_RG16 = 12,
GSK_SPV_IMAGE_FORMAT_RG8 = 13,
GSK_SPV_IMAGE_FORMAT_R16 = 14,
GSK_SPV_IMAGE_FORMAT_R8 = 15,
GSK_SPV_IMAGE_FORMAT_RGBA16_SNORM = 16,
GSK_SPV_IMAGE_FORMAT_RG16_SNORM = 17,
GSK_SPV_IMAGE_FORMAT_RG8_SNORM = 18,
GSK_SPV_IMAGE_FORMAT_R16_SNORM = 19,
GSK_SPV_IMAGE_FORMAT_R8_SNORM = 20,
GSK_SPV_IMAGE_FORMAT_RGBA32I = 21,
GSK_SPV_IMAGE_FORMAT_RGBA16I = 22,
GSK_SPV_IMAGE_FORMAT_RGBA8I = 23,
GSK_SPV_IMAGE_FORMAT_R32I = 24,
GSK_SPV_IMAGE_FORMAT_RG32I = 25,
GSK_SPV_IMAGE_FORMAT_RG16I = 26,
GSK_SPV_IMAGE_FORMAT_RG8I = 27,
GSK_SPV_IMAGE_FORMAT_R16I = 28,
GSK_SPV_IMAGE_FORMAT_R8I = 29,
GSK_SPV_IMAGE_FORMAT_RGBA32UI = 30,
GSK_SPV_IMAGE_FORMAT_RGBA16UI = 31,
GSK_SPV_IMAGE_FORMAT_RGBA8UI = 32,
GSK_SPV_IMAGE_FORMAT_R32UI = 33,
GSK_SPV_IMAGE_FORMAT_RGB10A2UI = 34,
GSK_SPV_IMAGE_FORMAT_RG32UI = 35,
GSK_SPV_IMAGE_FORMAT_RG16UI = 36,
GSK_SPV_IMAGE_FORMAT_RG8UI = 37,
GSK_SPV_IMAGE_FORMAT_R16UI = 38,
GSK_SPV_IMAGE_FORMAT_R8UI = 39
} GskSpvImageFormat;
typedef enum {
GSK_SPV_IMAGE_CHANNEL_ORDER_R = 0,
GSK_SPV_IMAGE_CHANNEL_ORDER_A = 1,
GSK_SPV_IMAGE_CHANNEL_ORDER_RG = 2,
GSK_SPV_IMAGE_CHANNEL_ORDER_RA = 3,
GSK_SPV_IMAGE_CHANNEL_ORDER_RGB = 4,
GSK_SPV_IMAGE_CHANNEL_ORDER_RGBA = 5,
GSK_SPV_IMAGE_CHANNEL_ORDER_BGRA = 6,
GSK_SPV_IMAGE_CHANNEL_ORDER_ARGB = 7,
GSK_SPV_IMAGE_CHANNEL_ORDER_INTENSITY = 8,
GSK_SPV_IMAGE_CHANNEL_ORDER_LUMINANCE = 9,
GSK_SPV_IMAGE_CHANNEL_ORDER_RX = 10,
GSK_SPV_IMAGE_CHANNEL_ORDER_R_GX = 11,
GSK_SPV_IMAGE_CHANNEL_ORDER_RG_BX = 12,
GSK_SPV_IMAGE_CHANNEL_ORDER_DEPTH = 13,
GSK_SPV_IMAGE_CHANNEL_ORDER_DEPTH_STENCIL = 14,
GSK_SPV_IMAGE_CHANNEL_ORDER_S_RGB = 15,
GSK_SPV_IMAGE_CHANNEL_ORDER_S_RG_BX = 16,
GSK_SPV_IMAGE_CHANNEL_ORDER_S_RGBA = 17,
GSK_SPV_IMAGE_CHANNEL_ORDER_S_BGRA = 18,
GSK_SPV_IMAGE_CHANNEL_ORDER_ABGR = 19
} GskSpvImageChannelOrder;
typedef enum {
GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_SNORM_INT8 = 0,
GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_SNORM_INT16 = 1,
GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_UNORM_INT8 = 2,
GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_UNORM_INT16 = 3,
GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_UNORM_SHORT565 = 4,
GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_UNORM_SHORT555 = 5,
GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_UNORM_INT101010 = 6,
GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_SIGNED_INT8 = 7,
GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_SIGNED_INT16 = 8,
GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_SIGNED_INT32 = 9,
GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_UNSIGNED_INT8 = 10,
GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_UNSIGNED_INT16 = 11,
GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_UNSIGNED_INT32 = 12,
GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_HALF_FLOAT = 13,
GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_FLOAT = 14,
GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_UNORM_INT24 = 15,
GSK_SPV_IMAGE_CHANNEL_DATA_TYPE_UNORM_INT101010_2 = 16
} GskSpvImageChannelDataType;
typedef enum {
GSK_SPV_FP_ROUNDING_MODE_RTE = 0,
GSK_SPV_FP_ROUNDING_MODE_RTZ = 1,
GSK_SPV_FP_ROUNDING_MODE_RTP = 2,
GSK_SPV_FP_ROUNDING_MODE_RTN = 3
} GskSpvFPRoundingMode;
typedef enum {
GSK_SPV_LINKAGE_TYPE_EXPORT = 0,
GSK_SPV_LINKAGE_TYPE_IMPORT = 1
} GskSpvLinkageType;
typedef enum {
GSK_SPV_ACCESS_QUALIFIER_READ_ONLY = 0,
GSK_SPV_ACCESS_QUALIFIER_WRITE_ONLY = 1,
GSK_SPV_ACCESS_QUALIFIER_READ_WRITE = 2
} GskSpvAccessQualifier;
typedef enum {
GSK_SPV_FUNCTION_PARAMETER_ATTRIBUTE_ZEXT = 0,
GSK_SPV_FUNCTION_PARAMETER_ATTRIBUTE_SEXT = 1,
GSK_SPV_FUNCTION_PARAMETER_ATTRIBUTE_BY_VAL = 2,
GSK_SPV_FUNCTION_PARAMETER_ATTRIBUTE_SRET = 3,
GSK_SPV_FUNCTION_PARAMETER_ATTRIBUTE_NO_ALIAS = 4,
GSK_SPV_FUNCTION_PARAMETER_ATTRIBUTE_NO_CAPTURE = 5,
GSK_SPV_FUNCTION_PARAMETER_ATTRIBUTE_NO_WRITE = 6,
GSK_SPV_FUNCTION_PARAMETER_ATTRIBUTE_NO_READ_WRITE = 7
} GskSpvFunctionParameterAttribute;
typedef enum {
GSK_SPV_DECORATION_RELAXED_PRECISION = 0,
GSK_SPV_DECORATION_SPEC_ID = 1,
GSK_SPV_DECORATION_BLOCK = 2,
GSK_SPV_DECORATION_BUFFER_BLOCK = 3,
GSK_SPV_DECORATION_ROW_MAJOR = 4,
GSK_SPV_DECORATION_COL_MAJOR = 5,
GSK_SPV_DECORATION_ARRAY_STRIDE = 6,
GSK_SPV_DECORATION_MATRIX_STRIDE = 7,
GSK_SPV_DECORATION_GLSL_SHARED = 8,
GSK_SPV_DECORATION_GLSL_PACKED = 9,
GSK_SPV_DECORATION_C_PACKED = 10,
GSK_SPV_DECORATION_BUILT_IN = 11,
GSK_SPV_DECORATION_NO_PERSPECTIVE = 13,
GSK_SPV_DECORATION_FLAT = 14,
GSK_SPV_DECORATION_PATCH = 15,
GSK_SPV_DECORATION_CENTROID = 16,
GSK_SPV_DECORATION_SAMPLE = 17,
GSK_SPV_DECORATION_INVARIANT = 18,
GSK_SPV_DECORATION_RESTRICT = 19,
GSK_SPV_DECORATION_ALIASED = 20,
GSK_SPV_DECORATION_VOLATILE = 21,
GSK_SPV_DECORATION_CONSTANT = 22,
GSK_SPV_DECORATION_COHERENT = 23,
GSK_SPV_DECORATION_NON_WRITABLE = 24,
GSK_SPV_DECORATION_NON_READABLE = 25,
GSK_SPV_DECORATION_UNIFORM = 26,
GSK_SPV_DECORATION_SATURATED_CONVERSION = 28,
GSK_SPV_DECORATION_STREAM = 29,
GSK_SPV_DECORATION_LOCATION = 30,
GSK_SPV_DECORATION_COMPONENT = 31,
GSK_SPV_DECORATION_INDEX = 32,
GSK_SPV_DECORATION_BINDING = 33,
GSK_SPV_DECORATION_DESCRIPTOR_SET = 34,
GSK_SPV_DECORATION_OFFSET = 35,
GSK_SPV_DECORATION_XFB_BUFFER = 36,
GSK_SPV_DECORATION_XFB_STRIDE = 37,
GSK_SPV_DECORATION_FUNC_PARAM_ATTR = 38,
GSK_SPV_DECORATION_FP_ROUNDING_MODE = 39,
GSK_SPV_DECORATION_FP_FAST_MATH_MODE = 40,
GSK_SPV_DECORATION_LINKAGE_ATTRIBUTES = 41,
GSK_SPV_DECORATION_NO_CONTRACTION = 42,
GSK_SPV_DECORATION_INPUT_ATTACHMENT_INDEX = 43,
GSK_SPV_DECORATION_ALIGNMENT = 44,
GSK_SPV_DECORATION_EXPLICIT_INTERP_AMD = 4999,
GSK_SPV_DECORATION_OVERRIDE_COVERAGE_NV = 5248,
GSK_SPV_DECORATION_PASSTHROUGH_NV = 5250,
GSK_SPV_DECORATION_VIEWPORT_RELATIVE_NV = 5252,
GSK_SPV_DECORATION_SECONDARY_VIEWPORT_RELATIVE_NV = 5256
} GskSpvDecoration;
typedef enum {
GSK_SPV_BUILT_IN_POSITION = 0,
GSK_SPV_BUILT_IN_POINT_SIZE = 1,
GSK_SPV_BUILT_IN_CLIP_DISTANCE = 3,
GSK_SPV_BUILT_IN_CULL_DISTANCE = 4,
GSK_SPV_BUILT_IN_VERTEX_ID = 5,
GSK_SPV_BUILT_IN_INSTANCE_ID = 6,
GSK_SPV_BUILT_IN_PRIMITIVE_ID = 7,
GSK_SPV_BUILT_IN_INVOCATION_ID = 8,
GSK_SPV_BUILT_IN_LAYER = 9,
GSK_SPV_BUILT_IN_VIEWPORT_INDEX = 10,
GSK_SPV_BUILT_IN_TESS_LEVEL_OUTER = 11,
GSK_SPV_BUILT_IN_TESS_LEVEL_INNER = 12,
GSK_SPV_BUILT_IN_TESS_COORD = 13,
GSK_SPV_BUILT_IN_PATCH_VERTICES = 14,
GSK_SPV_BUILT_IN_FRAG_COORD = 15,
GSK_SPV_BUILT_IN_POINT_COORD = 16,
GSK_SPV_BUILT_IN_FRONT_FACING = 17,
GSK_SPV_BUILT_IN_SAMPLE_ID = 18,
GSK_SPV_BUILT_IN_SAMPLE_POSITION = 19,
GSK_SPV_BUILT_IN_SAMPLE_MASK = 20,
GSK_SPV_BUILT_IN_FRAG_DEPTH = 22,
GSK_SPV_BUILT_IN_HELPER_INVOCATION = 23,
GSK_SPV_BUILT_IN_NUM_WORKGROUPS = 24,
GSK_SPV_BUILT_IN_WORKGROUP_SIZE = 25,
GSK_SPV_BUILT_IN_WORKGROUP_ID = 26,
GSK_SPV_BUILT_IN_LOCAL_INVOCATION_ID = 27,
GSK_SPV_BUILT_IN_GLOBAL_INVOCATION_ID = 28,
GSK_SPV_BUILT_IN_LOCAL_INVOCATION_INDEX = 29,
GSK_SPV_BUILT_IN_WORK_DIM = 30,
GSK_SPV_BUILT_IN_GLOBAL_SIZE = 31,
GSK_SPV_BUILT_IN_ENQUEUED_WORKGROUP_SIZE = 32,
GSK_SPV_BUILT_IN_GLOBAL_OFFSET = 33,
GSK_SPV_BUILT_IN_GLOBAL_LINEAR_ID = 34,
GSK_SPV_BUILT_IN_SUBGROUP_SIZE = 36,
GSK_SPV_BUILT_IN_SUBGROUP_MAX_SIZE = 37,
GSK_SPV_BUILT_IN_NUM_SUBGROUPS = 38,
GSK_SPV_BUILT_IN_NUM_ENQUEUED_SUBGROUPS = 39,
GSK_SPV_BUILT_IN_SUBGROUP_ID = 40,
GSK_SPV_BUILT_IN_SUBGROUP_LOCAL_INVOCATION_ID = 41,
GSK_SPV_BUILT_IN_VERTEX_INDEX = 42,
GSK_SPV_BUILT_IN_INSTANCE_INDEX = 43,
GSK_SPV_BUILT_IN_SUBGROUP_EQ_MASK_KHR = 4416,
GSK_SPV_BUILT_IN_SUBGROUP_GE_MASK_KHR = 4417,
GSK_SPV_BUILT_IN_SUBGROUP_GT_MASK_KHR = 4418,
GSK_SPV_BUILT_IN_SUBGROUP_LE_MASK_KHR = 4419,
GSK_SPV_BUILT_IN_SUBGROUP_LT_MASK_KHR = 4420,
GSK_SPV_BUILT_IN_BASE_VERTEX = 4424,
GSK_SPV_BUILT_IN_BASE_INSTANCE = 4425,
GSK_SPV_BUILT_IN_DRAW_INDEX = 4426,
GSK_SPV_BUILT_IN_DEVICE_INDEX = 4438,
GSK_SPV_BUILT_IN_VIEW_INDEX = 4440,
GSK_SPV_BUILT_IN_BARY_COORD_NO_PERSP_AMD = 4992,
GSK_SPV_BUILT_IN_BARY_COORD_NO_PERSP_CENTROID_AMD = 4993,
GSK_SPV_BUILT_IN_BARY_COORD_NO_PERSP_SAMPLE_AMD = 4994,
GSK_SPV_BUILT_IN_BARY_COORD_SMOOTH_AMD = 4995,
GSK_SPV_BUILT_IN_BARY_COORD_SMOOTH_CENTROID_AMD = 4996,
GSK_SPV_BUILT_IN_BARY_COORD_SMOOTH_SAMPLE_AMD = 4997,
GSK_SPV_BUILT_IN_BARY_COORD_PULL_MODEL_AMD = 4998,
GSK_SPV_BUILT_IN_FRAG_STENCIL_REF_EXT = 5014,
GSK_SPV_BUILT_IN_VIEWPORT_MASK_NV = 5253,
GSK_SPV_BUILT_IN_SECONDARY_POSITION_NV = 5257,
GSK_SPV_BUILT_IN_SECONDARY_VIEWPORT_MASK_NV = 5258,
GSK_SPV_BUILT_IN_POSITION_PER_VIEW_NV = 5261,
GSK_SPV_BUILT_IN_VIEWPORT_MASK_PER_VIEW_NV = 5262
} GskSpvBuiltIn;
typedef enum {
GSK_SPV_SCOPE_CROSS_DEVICE = 0,
GSK_SPV_SCOPE_DEVICE = 1,
GSK_SPV_SCOPE_WORKGROUP = 2,
GSK_SPV_SCOPE_SUBGROUP = 3,
GSK_SPV_SCOPE_INVOCATION = 4
} GskSpvScope;
typedef enum {
GSK_SPV_GROUP_OPERATION_REDUCE = 0,
GSK_SPV_GROUP_OPERATION_INCLUSIVE_SCAN = 1,
GSK_SPV_GROUP_OPERATION_EXCLUSIVE_SCAN = 2
} GskSpvGroupOperation;
typedef enum {
GSK_SPV_KERNEL_ENQUEUE_FLAGS_NO_WAIT = 0,
GSK_SPV_KERNEL_ENQUEUE_FLAGS_WAIT_KERNEL = 1,
GSK_SPV_KERNEL_ENQUEUE_FLAGS_WAIT_WORK_GROUP = 2
} GskSpvKernelEnqueueFlags;
typedef enum {
GSK_SPV_CAPABILITY_MATRIX = 0,
GSK_SPV_CAPABILITY_SHADER = 1,
GSK_SPV_CAPABILITY_GEOMETRY = 2,
GSK_SPV_CAPABILITY_TESSELLATION = 3,
GSK_SPV_CAPABILITY_ADDRESSES = 4,
GSK_SPV_CAPABILITY_LINKAGE = 5,
GSK_SPV_CAPABILITY_KERNEL = 6,
GSK_SPV_CAPABILITY_VECTOR16 = 7,
GSK_SPV_CAPABILITY_FLOAT16_BUFFER = 8,
GSK_SPV_CAPABILITY_FLOAT16 = 9,
GSK_SPV_CAPABILITY_FLOAT64 = 10,
GSK_SPV_CAPABILITY_INT64 = 11,
GSK_SPV_CAPABILITY_INT64_ATOMICS = 12,
GSK_SPV_CAPABILITY_IMAGE_BASIC = 13,
GSK_SPV_CAPABILITY_IMAGE_READ_WRITE = 14,
GSK_SPV_CAPABILITY_IMAGE_MIPMAP = 15,
GSK_SPV_CAPABILITY_PIPES = 17,
GSK_SPV_CAPABILITY_GROUPS = 18,
GSK_SPV_CAPABILITY_DEVICE_ENQUEUE = 19,
GSK_SPV_CAPABILITY_LITERAL_SAMPLER = 20,
GSK_SPV_CAPABILITY_ATOMIC_STORAGE = 21,
GSK_SPV_CAPABILITY_INT16 = 22,
GSK_SPV_CAPABILITY_TESSELLATION_POINT_SIZE = 23,
GSK_SPV_CAPABILITY_GEOMETRY_POINT_SIZE = 24,
GSK_SPV_CAPABILITY_IMAGE_GATHER_EXTENDED = 25,
GSK_SPV_CAPABILITY_STORAGE_IMAGE_MULTISAMPLE = 27,
GSK_SPV_CAPABILITY_UNIFORM_BUFFER_ARRAY_DYNAMIC_INDEXING = 28,
GSK_SPV_CAPABILITY_SAMPLED_IMAGE_ARRAY_DYNAMIC_INDEXING = 29,
GSK_SPV_CAPABILITY_STORAGE_BUFFER_ARRAY_DYNAMIC_INDEXING = 30,
GSK_SPV_CAPABILITY_STORAGE_IMAGE_ARRAY_DYNAMIC_INDEXING = 31,
GSK_SPV_CAPABILITY_CLIP_DISTANCE = 32,
GSK_SPV_CAPABILITY_CULL_DISTANCE = 33,
GSK_SPV_CAPABILITY_IMAGE_CUBE_ARRAY = 34,
GSK_SPV_CAPABILITY_SAMPLE_RATE_SHADING = 35,
GSK_SPV_CAPABILITY_IMAGE_RECT = 36,
GSK_SPV_CAPABILITY_SAMPLED_RECT = 37,
GSK_SPV_CAPABILITY_GENERIC_POINTER = 38,
GSK_SPV_CAPABILITY_INT8 = 39,
GSK_SPV_CAPABILITY_INPUT_ATTACHMENT = 40,
GSK_SPV_CAPABILITY_SPARSE_RESIDENCY = 41,
GSK_SPV_CAPABILITY_MIN_LOD = 42,
GSK_SPV_CAPABILITY_SAMPLED1_D = 43,
GSK_SPV_CAPABILITY_IMAGE1_D = 44,
GSK_SPV_CAPABILITY_SAMPLED_CUBE_ARRAY = 45,
GSK_SPV_CAPABILITY_SAMPLED_BUFFER = 46,
GSK_SPV_CAPABILITY_IMAGE_BUFFER = 47,
GSK_SPV_CAPABILITY_IMAGE_MS_ARRAY = 48,
GSK_SPV_CAPABILITY_STORAGE_IMAGE_EXTENDED_FORMATS = 49,
GSK_SPV_CAPABILITY_IMAGE_QUERY = 50,
GSK_SPV_CAPABILITY_DERIVATIVE_CONTROL = 51,
GSK_SPV_CAPABILITY_INTERPOLATION_FUNCTION = 52,
GSK_SPV_CAPABILITY_TRANSFORM_FEEDBACK = 53,
GSK_SPV_CAPABILITY_GEOMETRY_STREAMS = 54,
GSK_SPV_CAPABILITY_STORAGE_IMAGE_READ_WITHOUT_FORMAT = 55,
GSK_SPV_CAPABILITY_STORAGE_IMAGE_WRITE_WITHOUT_FORMAT = 56,
GSK_SPV_CAPABILITY_MULTI_VIEWPORT = 57,
GSK_SPV_CAPABILITY_SUBGROUP_BALLOT_KHR = 4423,
GSK_SPV_CAPABILITY_DRAW_PARAMETERS = 4427,
GSK_SPV_CAPABILITY_SUBGROUP_VOTE_KHR = 4431,
GSK_SPV_CAPABILITY_STORAGE_BUFFER16_BIT_ACCESS = 4433,
GSK_SPV_CAPABILITY_STORAGE_UNIFORM_BUFFER_BLOCK16 = 4433,
GSK_SPV_CAPABILITY_UNIFORM_AND_STORAGE_BUFFER16_BIT_ACCESS = 4434,
GSK_SPV_CAPABILITY_STORAGE_UNIFORM16 = 4434,
GSK_SPV_CAPABILITY_STORAGE_PUSH_CONSTANT16 = 4435,
GSK_SPV_CAPABILITY_STORAGE_INPUT_OUTPUT16 = 4436,
GSK_SPV_CAPABILITY_DEVICE_GROUP = 4437,
GSK_SPV_CAPABILITY_MULTI_VIEW = 4439,
GSK_SPV_CAPABILITY_VARIABLE_POINTERS_STORAGE_BUFFER = 4441,
GSK_SPV_CAPABILITY_VARIABLE_POINTERS = 4442,
GSK_SPV_CAPABILITY_ATOMIC_STORAGE_OPS = 4445,
GSK_SPV_CAPABILITY_SAMPLE_MASK_POST_DEPTH_COVERAGE = 4447,
GSK_SPV_CAPABILITY_IMAGE_GATHER_BIAS_LOD_AMD = 5009,
GSK_SPV_CAPABILITY_FRAGMENT_MASK_AMD = 5010,
GSK_SPV_CAPABILITY_STENCIL_EXPORT_EXT = 5013,
GSK_SPV_CAPABILITY_IMAGE_READ_WRITE_LOD_AMD = 5015,
GSK_SPV_CAPABILITY_SAMPLE_MASK_OVERRIDE_COVERAGE_NV = 5249,
GSK_SPV_CAPABILITY_GEOMETRY_SHADER_PASSTHROUGH_NV = 5251,
GSK_SPV_CAPABILITY_SHADER_VIEWPORT_INDEX_LAYER_EXT = 5254,
GSK_SPV_CAPABILITY_SHADER_VIEWPORT_INDEX_LAYER_NV = 5254,
GSK_SPV_CAPABILITY_SHADER_VIEWPORT_MASK_NV = 5255,
GSK_SPV_CAPABILITY_SHADER_STEREO_VIEW_NV = 5259,
GSK_SPV_CAPABILITY_PER_VIEW_ATTRIBUTES_NV = 5260
} GskSpvCapability;
typedef enum {
GSK_SPV_OP_NOP = 0,
GSK_SPV_OP_UNDEF = 1,
GSK_SPV_OP_SOURCE_CONTINUED = 2,
GSK_SPV_OP_SOURCE = 3,
GSK_SPV_OP_SOURCE_EXTENSION = 4,
GSK_SPV_OP_NAME = 5,
GSK_SPV_OP_MEMBER_NAME = 6,
GSK_SPV_OP_STRING = 7,
GSK_SPV_OP_LINE = 8,
GSK_SPV_OP_EXTENSION = 10,
GSK_SPV_OP_EXT_INST_IMPORT = 11,
GSK_SPV_OP_EXT_INST = 12,
GSK_SPV_OP_MEMORY_MODEL = 14,
GSK_SPV_OP_ENTRY_POINT = 15,
GSK_SPV_OP_EXECUTION_MODE = 16,
GSK_SPV_OP_CAPABILITY = 17,
GSK_SPV_OP_TYPE_VOID = 19,
GSK_SPV_OP_TYPE_BOOL = 20,
GSK_SPV_OP_TYPE_INT = 21,
GSK_SPV_OP_TYPE_FLOAT = 22,
GSK_SPV_OP_TYPE_VECTOR = 23,
GSK_SPV_OP_TYPE_MATRIX = 24,
GSK_SPV_OP_TYPE_IMAGE = 25,
GSK_SPV_OP_TYPE_SAMPLER = 26,
GSK_SPV_OP_TYPE_SAMPLED_IMAGE = 27,
GSK_SPV_OP_TYPE_ARRAY = 28,
GSK_SPV_OP_TYPE_RUNTIME_ARRAY = 29,
GSK_SPV_OP_TYPE_STRUCT = 30,
GSK_SPV_OP_TYPE_OPAQUE = 31,
GSK_SPV_OP_TYPE_POINTER = 32,
GSK_SPV_OP_TYPE_FUNCTION = 33,
GSK_SPV_OP_TYPE_EVENT = 34,
GSK_SPV_OP_TYPE_DEVICE_EVENT = 35,
GSK_SPV_OP_TYPE_RESERVE_ID = 36,
GSK_SPV_OP_TYPE_QUEUE = 37,
GSK_SPV_OP_TYPE_PIPE = 38,
GSK_SPV_OP_TYPE_FORWARD_POINTER = 39,
GSK_SPV_OP_CONSTANT_TRUE = 41,
GSK_SPV_OP_CONSTANT_FALSE = 42,
GSK_SPV_OP_CONSTANT = 43,
GSK_SPV_OP_CONSTANT_COMPOSITE = 44,
GSK_SPV_OP_CONSTANT_SAMPLER = 45,
GSK_SPV_OP_CONSTANT_NULL = 46,
GSK_SPV_OP_SPEC_CONSTANT_TRUE = 48,
GSK_SPV_OP_SPEC_CONSTANT_FALSE = 49,
GSK_SPV_OP_SPEC_CONSTANT = 50,
GSK_SPV_OP_SPEC_CONSTANT_COMPOSITE = 51,
GSK_SPV_OP_SPEC_CONSTANT_OP = 52,
GSK_SPV_OP_FUNCTION = 54,
GSK_SPV_OP_FUNCTION_PARAMETER = 55,
GSK_SPV_OP_FUNCTION_END = 56,
GSK_SPV_OP_FUNCTION_CALL = 57,
GSK_SPV_OP_VARIABLE = 59,
GSK_SPV_OP_IMAGE_TEXEL_POINTER = 60,
GSK_SPV_OP_LOAD = 61,
GSK_SPV_OP_STORE = 62,
GSK_SPV_OP_COPY_MEMORY = 63,
GSK_SPV_OP_COPY_MEMORY_SIZED = 64,
GSK_SPV_OP_ACCESS_CHAIN = 65,
GSK_SPV_OP_IN_BOUNDS_ACCESS_CHAIN = 66,
GSK_SPV_OP_PTR_ACCESS_CHAIN = 67,
GSK_SPV_OP_ARRAY_LENGTH = 68,
GSK_SPV_OP_GENERIC_PTR_MEM_SEMANTICS = 69,
GSK_SPV_OP_IN_BOUNDS_PTR_ACCESS_CHAIN = 70,
GSK_SPV_OP_DECORATE = 71,
GSK_SPV_OP_MEMBER_DECORATE = 72,
GSK_SPV_OP_DECORATION_GROUP = 73,
GSK_SPV_OP_GROUP_DECORATE = 74,
GSK_SPV_OP_GROUP_MEMBER_DECORATE = 75,
GSK_SPV_OP_VECTOR_EXTRACT_DYNAMIC = 77,
GSK_SPV_OP_VECTOR_INSERT_DYNAMIC = 78,
GSK_SPV_OP_VECTOR_SHUFFLE = 79,
GSK_SPV_OP_COMPOSITE_CONSTRUCT = 80,
GSK_SPV_OP_COMPOSITE_EXTRACT = 81,
GSK_SPV_OP_COMPOSITE_INSERT = 82,
GSK_SPV_OP_COPY_OBJECT = 83,
GSK_SPV_OP_TRANSPOSE = 84,
GSK_SPV_OP_SAMPLED_IMAGE = 86,
GSK_SPV_OP_IMAGE_SAMPLE_IMPLICIT_LOD = 87,
GSK_SPV_OP_IMAGE_SAMPLE_EXPLICIT_LOD = 88,
GSK_SPV_OP_IMAGE_SAMPLE_DREF_IMPLICIT_LOD = 89,
GSK_SPV_OP_IMAGE_SAMPLE_DREF_EXPLICIT_LOD = 90,
GSK_SPV_OP_IMAGE_SAMPLE_PROJ_IMPLICIT_LOD = 91,
GSK_SPV_OP_IMAGE_SAMPLE_PROJ_EXPLICIT_LOD = 92,
GSK_SPV_OP_IMAGE_SAMPLE_PROJ_DREF_IMPLICIT_LOD = 93,
GSK_SPV_OP_IMAGE_SAMPLE_PROJ_DREF_EXPLICIT_LOD = 94,
GSK_SPV_OP_IMAGE_FETCH = 95,
GSK_SPV_OP_IMAGE_GATHER = 96,
GSK_SPV_OP_IMAGE_DREF_GATHER = 97,
GSK_SPV_OP_IMAGE_READ = 98,
GSK_SPV_OP_IMAGE_WRITE = 99,
GSK_SPV_OP_IMAGE = 100,
GSK_SPV_OP_IMAGE_QUERY_FORMAT = 101,
GSK_SPV_OP_IMAGE_QUERY_ORDER = 102,
GSK_SPV_OP_IMAGE_QUERY_SIZE_LOD = 103,
GSK_SPV_OP_IMAGE_QUERY_SIZE = 104,
GSK_SPV_OP_IMAGE_QUERY_LOD = 105,
GSK_SPV_OP_IMAGE_QUERY_LEVELS = 106,
GSK_SPV_OP_IMAGE_QUERY_SAMPLES = 107,
GSK_SPV_OP_CONVERT_F_TO_U = 109,
GSK_SPV_OP_CONVERT_F_TO_S = 110,
GSK_SPV_OP_CONVERT_S_TO_F = 111,
GSK_SPV_OP_CONVERT_U_TO_F = 112,
GSK_SPV_OP_U_CONVERT = 113,
GSK_SPV_OP_S_CONVERT = 114,
GSK_SPV_OP_F_CONVERT = 115,
GSK_SPV_OP_QUANTIZE_TO_F16 = 116,
GSK_SPV_OP_CONVERT_PTR_TO_U = 117,
GSK_SPV_OP_SAT_CONVERT_S_TO_U = 118,
GSK_SPV_OP_SAT_CONVERT_U_TO_S = 119,
GSK_SPV_OP_CONVERT_U_TO_PTR = 120,
GSK_SPV_OP_PTR_CAST_TO_GENERIC = 121,
GSK_SPV_OP_GENERIC_CAST_TO_PTR = 122,
GSK_SPV_OP_GENERIC_CAST_TO_PTR_EXPLICIT = 123,
GSK_SPV_OP_BITCAST = 124,
GSK_SPV_OP_S_NEGATE = 126,
GSK_SPV_OP_F_NEGATE = 127,
GSK_SPV_OP_I_ADD = 128,
GSK_SPV_OP_F_ADD = 129,
GSK_SPV_OP_I_SUB = 130,
GSK_SPV_OP_F_SUB = 131,
GSK_SPV_OP_I_MUL = 132,
GSK_SPV_OP_F_MUL = 133,
GSK_SPV_OP_U_DIV = 134,
GSK_SPV_OP_S_DIV = 135,
GSK_SPV_OP_F_DIV = 136,
GSK_SPV_OP_U_MOD = 137,
GSK_SPV_OP_S_REM = 138,
GSK_SPV_OP_S_MOD = 139,
GSK_SPV_OP_F_REM = 140,
GSK_SPV_OP_F_MOD = 141,
GSK_SPV_OP_VECTOR_TIMES_SCALAR = 142,
GSK_SPV_OP_MATRIX_TIMES_SCALAR = 143,
GSK_SPV_OP_VECTOR_TIMES_MATRIX = 144,
GSK_SPV_OP_MATRIX_TIMES_VECTOR = 145,
GSK_SPV_OP_MATRIX_TIMES_MATRIX = 146,
GSK_SPV_OP_OUTER_PRODUCT = 147,
GSK_SPV_OP_DOT = 148,
GSK_SPV_OP_I_ADD_CARRY = 149,
GSK_SPV_OP_I_SUB_BORROW = 150,
GSK_SPV_OP_U_MUL_EXTENDED = 151,
GSK_SPV_OP_S_MUL_EXTENDED = 152,
GSK_SPV_OP_ANY = 154,
GSK_SPV_OP_ALL = 155,
GSK_SPV_OP_IS_NAN = 156,
GSK_SPV_OP_IS_INF = 157,
GSK_SPV_OP_IS_FINITE = 158,
GSK_SPV_OP_IS_NORMAL = 159,
GSK_SPV_OP_SIGN_BIT_SET = 160,
GSK_SPV_OP_LESS_OR_GREATER = 161,
GSK_SPV_OP_ORDERED = 162,
GSK_SPV_OP_UNORDERED = 163,
GSK_SPV_OP_LOGICAL_EQUAL = 164,
GSK_SPV_OP_LOGICAL_NOT_EQUAL = 165,
GSK_SPV_OP_LOGICAL_OR = 166,
GSK_SPV_OP_LOGICAL_AND = 167,
GSK_SPV_OP_LOGICAL_NOT = 168,
GSK_SPV_OP_SELECT = 169,
GSK_SPV_OP_I_EQUAL = 170,
GSK_SPV_OP_I_NOT_EQUAL = 171,
GSK_SPV_OP_U_GREATER_THAN = 172,
GSK_SPV_OP_S_GREATER_THAN = 173,
GSK_SPV_OP_U_GREATER_THAN_EQUAL = 174,
GSK_SPV_OP_S_GREATER_THAN_EQUAL = 175,
GSK_SPV_OP_U_LESS_THAN = 176,
GSK_SPV_OP_S_LESS_THAN = 177,
GSK_SPV_OP_U_LESS_THAN_EQUAL = 178,
GSK_SPV_OP_S_LESS_THAN_EQUAL = 179,
GSK_SPV_OP_F_ORD_EQUAL = 180,
GSK_SPV_OP_F_UNORD_EQUAL = 181,
GSK_SPV_OP_F_ORD_NOT_EQUAL = 182,
GSK_SPV_OP_F_UNORD_NOT_EQUAL = 183,
GSK_SPV_OP_F_ORD_LESS_THAN = 184,
GSK_SPV_OP_F_UNORD_LESS_THAN = 185,
GSK_SPV_OP_F_ORD_GREATER_THAN = 186,
GSK_SPV_OP_F_UNORD_GREATER_THAN = 187,
GSK_SPV_OP_F_ORD_LESS_THAN_EQUAL = 188,
GSK_SPV_OP_F_UNORD_LESS_THAN_EQUAL = 189,
GSK_SPV_OP_F_ORD_GREATER_THAN_EQUAL = 190,
GSK_SPV_OP_F_UNORD_GREATER_THAN_EQUAL = 191,
GSK_SPV_OP_SHIFT_RIGHT_LOGICAL = 194,
GSK_SPV_OP_SHIFT_RIGHT_ARITHMETIC = 195,
GSK_SPV_OP_SHIFT_LEFT_LOGICAL = 196,
GSK_SPV_OP_BITWISE_OR = 197,
GSK_SPV_OP_BITWISE_XOR = 198,
GSK_SPV_OP_BITWISE_AND = 199,
GSK_SPV_OP_NOT = 200,
GSK_SPV_OP_BIT_FIELD_INSERT = 201,
GSK_SPV_OP_BIT_FIELD_S_EXTRACT = 202,
GSK_SPV_OP_BIT_FIELD_U_EXTRACT = 203,
GSK_SPV_OP_BIT_REVERSE = 204,
GSK_SPV_OP_BIT_COUNT = 205,
GSK_SPV_OP_D_PDX = 207,
GSK_SPV_OP_D_PDY = 208,
GSK_SPV_OP_FWIDTH = 209,
GSK_SPV_OP_D_PDX_FINE = 210,
GSK_SPV_OP_D_PDY_FINE = 211,
GSK_SPV_OP_FWIDTH_FINE = 212,
GSK_SPV_OP_D_PDX_COARSE = 213,
GSK_SPV_OP_D_PDY_COARSE = 214,
GSK_SPV_OP_FWIDTH_COARSE = 215,
GSK_SPV_OP_EMIT_VERTEX = 218,
GSK_SPV_OP_END_PRIMITIVE = 219,
GSK_SPV_OP_EMIT_STREAM_VERTEX = 220,
GSK_SPV_OP_END_STREAM_PRIMITIVE = 221,
GSK_SPV_OP_CONTROL_BARRIER = 224,
GSK_SPV_OP_MEMORY_BARRIER = 225,
GSK_SPV_OP_ATOMIC_LOAD = 227,
GSK_SPV_OP_ATOMIC_STORE = 228,
GSK_SPV_OP_ATOMIC_EXCHANGE = 229,
GSK_SPV_OP_ATOMIC_COMPARE_EXCHANGE = 230,
GSK_SPV_OP_ATOMIC_COMPARE_EXCHANGE_WEAK = 231,
GSK_SPV_OP_ATOMIC_I_INCREMENT = 232,
GSK_SPV_OP_ATOMIC_I_DECREMENT = 233,
GSK_SPV_OP_ATOMIC_I_ADD = 234,
GSK_SPV_OP_ATOMIC_I_SUB = 235,
GSK_SPV_OP_ATOMIC_S_MIN = 236,
GSK_SPV_OP_ATOMIC_U_MIN = 237,
GSK_SPV_OP_ATOMIC_S_MAX = 238,
GSK_SPV_OP_ATOMIC_U_MAX = 239,
GSK_SPV_OP_ATOMIC_AND = 240,
GSK_SPV_OP_ATOMIC_OR = 241,
GSK_SPV_OP_ATOMIC_XOR = 242,
GSK_SPV_OP_PHI = 245,
GSK_SPV_OP_LOOP_MERGE = 246,
GSK_SPV_OP_SELECTION_MERGE = 247,
GSK_SPV_OP_LABEL = 248,
GSK_SPV_OP_BRANCH = 249,
GSK_SPV_OP_BRANCH_CONDITIONAL = 250,
GSK_SPV_OP_SWITCH = 251,
GSK_SPV_OP_KILL = 252,
GSK_SPV_OP_RETURN = 253,
GSK_SPV_OP_RETURN_VALUE = 254,
GSK_SPV_OP_UNREACHABLE = 255,
GSK_SPV_OP_LIFETIME_START = 256,
GSK_SPV_OP_LIFETIME_STOP = 257,
GSK_SPV_OP_GROUP_ASYNC_COPY = 259,
GSK_SPV_OP_GROUP_WAIT_EVENTS = 260,
GSK_SPV_OP_GROUP_ALL = 261,
GSK_SPV_OP_GROUP_ANY = 262,
GSK_SPV_OP_GROUP_BROADCAST = 263,
GSK_SPV_OP_GROUP_I_ADD = 264,
GSK_SPV_OP_GROUP_F_ADD = 265,
GSK_SPV_OP_GROUP_F_MIN = 266,
GSK_SPV_OP_GROUP_U_MIN = 267,
GSK_SPV_OP_GROUP_S_MIN = 268,
GSK_SPV_OP_GROUP_F_MAX = 269,
GSK_SPV_OP_GROUP_U_MAX = 270,
GSK_SPV_OP_GROUP_S_MAX = 271,
GSK_SPV_OP_READ_PIPE = 274,
GSK_SPV_OP_WRITE_PIPE = 275,
GSK_SPV_OP_RESERVED_READ_PIPE = 276,
GSK_SPV_OP_RESERVED_WRITE_PIPE = 277,
GSK_SPV_OP_RESERVE_READ_PIPE_PACKETS = 278,
GSK_SPV_OP_RESERVE_WRITE_PIPE_PACKETS = 279,
GSK_SPV_OP_COMMIT_READ_PIPE = 280,
GSK_SPV_OP_COMMIT_WRITE_PIPE = 281,
GSK_SPV_OP_IS_VALID_RESERVE_ID = 282,
GSK_SPV_OP_GET_NUM_PIPE_PACKETS = 283,
GSK_SPV_OP_GET_MAX_PIPE_PACKETS = 284,
GSK_SPV_OP_GROUP_RESERVE_READ_PIPE_PACKETS = 285,
GSK_SPV_OP_GROUP_RESERVE_WRITE_PIPE_PACKETS = 286,
GSK_SPV_OP_GROUP_COMMIT_READ_PIPE = 287,
GSK_SPV_OP_GROUP_COMMIT_WRITE_PIPE = 288,
GSK_SPV_OP_ENQUEUE_MARKER = 291,
GSK_SPV_OP_ENQUEUE_KERNEL = 292,
GSK_SPV_OP_GET_KERNEL_N_DRANGE_SUB_GROUP_COUNT = 293,
GSK_SPV_OP_GET_KERNEL_N_DRANGE_MAX_SUB_GROUP_SIZE = 294,
GSK_SPV_OP_GET_KERNEL_WORK_GROUP_SIZE = 295,
GSK_SPV_OP_GET_KERNEL_PREFERRED_WORK_GROUP_SIZE_MULTIPLE = 296,
GSK_SPV_OP_RETAIN_EVENT = 297,
GSK_SPV_OP_RELEASE_EVENT = 298,
GSK_SPV_OP_CREATE_USER_EVENT = 299,
GSK_SPV_OP_IS_VALID_EVENT = 300,
GSK_SPV_OP_SET_USER_EVENT_STATUS = 301,
GSK_SPV_OP_CAPTURE_EVENT_PROFILING_INFO = 302,
GSK_SPV_OP_GET_DEFAULT_QUEUE = 303,
GSK_SPV_OP_BUILD_ND_RANGE = 304,
GSK_SPV_OP_IMAGE_SPARSE_SAMPLE_IMPLICIT_LOD = 305,
GSK_SPV_OP_IMAGE_SPARSE_SAMPLE_EXPLICIT_LOD = 306,
GSK_SPV_OP_IMAGE_SPARSE_SAMPLE_DREF_IMPLICIT_LOD = 307,
GSK_SPV_OP_IMAGE_SPARSE_SAMPLE_DREF_EXPLICIT_LOD = 308,
GSK_SPV_OP_IMAGE_SPARSE_SAMPLE_PROJ_IMPLICIT_LOD = 309,
GSK_SPV_OP_IMAGE_SPARSE_SAMPLE_PROJ_EXPLICIT_LOD = 310,
GSK_SPV_OP_IMAGE_SPARSE_SAMPLE_PROJ_DREF_IMPLICIT_LOD = 311,
GSK_SPV_OP_IMAGE_SPARSE_SAMPLE_PROJ_DREF_EXPLICIT_LOD = 312,
GSK_SPV_OP_IMAGE_SPARSE_FETCH = 313,
GSK_SPV_OP_IMAGE_SPARSE_GATHER = 314,
GSK_SPV_OP_IMAGE_SPARSE_DREF_GATHER = 315,
GSK_SPV_OP_IMAGE_SPARSE_TEXELS_RESIDENT = 316,
GSK_SPV_OP_NO_LINE = 317,
GSK_SPV_OP_ATOMIC_FLAG_TEST_AND_SET = 318,
GSK_SPV_OP_ATOMIC_FLAG_CLEAR = 319,
GSK_SPV_OP_IMAGE_SPARSE_READ = 320,
GSK_SPV_OP_SUBGROUP_BALLOT_KHR = 4421,
GSK_SPV_OP_SUBGROUP_FIRST_INVOCATION_KHR = 4422,
GSK_SPV_OP_SUBGROUP_ALL_KHR = 4428,
GSK_SPV_OP_SUBGROUP_ANY_KHR = 4429,
GSK_SPV_OP_SUBGROUP_ALL_EQUAL_KHR = 4430,
GSK_SPV_OP_SUBGROUP_READ_INVOCATION_KHR = 4432,
GSK_SPV_OP_GROUP_I_ADD_NON_UNIFORM_AMD = 5000,
GSK_SPV_OP_GROUP_F_ADD_NON_UNIFORM_AMD = 5001,
GSK_SPV_OP_GROUP_F_MIN_NON_UNIFORM_AMD = 5002,
GSK_SPV_OP_GROUP_U_MIN_NON_UNIFORM_AMD = 5003,
GSK_SPV_OP_GROUP_S_MIN_NON_UNIFORM_AMD = 5004,
GSK_SPV_OP_GROUP_F_MAX_NON_UNIFORM_AMD = 5005,
GSK_SPV_OP_GROUP_U_MAX_NON_UNIFORM_AMD = 5006,
GSK_SPV_OP_GROUP_S_MAX_NON_UNIFORM_AMD = 5007,
GSK_SPV_OP_FRAGMENT_MASK_FETCH_AMD = 5011,
GSK_SPV_OP_FRAGMENT_FETCH_AMD = 5012
} GskSpvOpcode;
#endif /* __GSK_SPV_ENUMS_H__ */

809
gsk/gskspvwriter.c Normal file
View File

@@ -0,0 +1,809 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "gskspvwriterprivate.h"
#include "gskslfunctionprivate.h"
#include "gskslfunctiontypeprivate.h"
#include "gskslimagetypeprivate.h"
#include "gskslqualifierprivate.h"
#include "gsksltypeprivate.h"
#include "gskslvalueprivate.h"
#include "gskslvariableprivate.h"
typedef struct _GskSpvCodeBlock GskSpvCodeBlock;
typedef struct _GskSpvPointerType GskSpvPointerType;
struct _GskSpvPointerType
{
GskSlType *type;
GskSpvStorageClass storage;
};
struct _GskSpvCodeBlock
{
GArray *code[GSK_SPV_WRITER_N_BLOCK_SECTIONS];
guint32 label_id;
guint32 continue_id;
guint32 break_id;
};
struct _GskSpvWriter
{
int ref_count;
GskSlShaderStage stage;
guint32 last_id;
guint extended_instructions_id;
GArray *code[GSK_SPV_WRITER_N_GLOBAL_SECTIONS];
GSList *blocks;
GSList *pending_blocks;
GHashTable *types;
GHashTable *image_types;
GHashTable *pointer_types;
GHashTable *values;
GHashTable *variables;
GHashTable *functions;
GHashTable *function_types;
};
static GskSpvCodeBlock *
gsk_spv_code_block_new (void)
{
GskSpvCodeBlock *block;
guint i;
block = g_slice_new0 (GskSpvCodeBlock);
for (i = 0; i < GSK_SPV_WRITER_N_BLOCK_SECTIONS; i++)
{
block->code[i] = g_array_new (FALSE, TRUE, sizeof (guint32));
}
return block;
}
static void
gsk_spv_code_block_free (GskSpvCodeBlock *block)
{
guint i;
for (i = 0; i < GSK_SPV_WRITER_N_BLOCK_SECTIONS; i++)
g_array_free (block->code[i], TRUE);
g_slice_free (GskSpvCodeBlock, block);
}
static gboolean
pointer_type_equal (gconstpointer a,
gconstpointer b)
{
const GskSpvPointerType *typea = a;
const GskSpvPointerType *typeb = b;
if (!gsk_sl_type_equal (typea->type, typeb->type))
return FALSE;
return typea->storage == typeb->storage;
}
static guint
pointer_type_hash (gconstpointer t)
{
const GskSpvPointerType *type = t;
return gsk_sl_type_hash (type->type)
^ type->storage;
}
static void
pointer_type_free (gpointer data)
{
GskSpvPointerType *pointer_type = data;
gsk_sl_type_unref (pointer_type->type);
g_free (pointer_type);
}
GskSpvWriter *
gsk_spv_writer_new (GskSlShaderStage stage)
{
GskSpvWriter *writer;
guint i;
writer = g_slice_new0 (GskSpvWriter);
writer->ref_count = 1;
writer->stage = stage;
for (i = 0; i < GSK_SPV_WRITER_N_GLOBAL_SECTIONS; i++)
{
writer->code[i] = g_array_new (FALSE, TRUE, sizeof (guint32));
}
writer->types = g_hash_table_new_full (gsk_sl_type_hash, gsk_sl_type_equal,
(GDestroyNotify) gsk_sl_type_unref, NULL);
writer->image_types = g_hash_table_new_full (gsk_sl_image_type_hash, gsk_sl_image_type_equal,
NULL, NULL);
writer->pointer_types = g_hash_table_new_full (pointer_type_hash, pointer_type_equal,
pointer_type_free, NULL);
writer->values = g_hash_table_new_full (gsk_sl_value_hash, gsk_sl_value_equal,
(GDestroyNotify) gsk_sl_value_free, NULL);
writer->variables = g_hash_table_new_full (g_direct_hash, g_direct_equal,
(GDestroyNotify) gsk_sl_variable_unref, NULL);
writer->functions = g_hash_table_new_full (g_direct_hash, g_direct_equal,
(GDestroyNotify) gsk_sl_function_unref, NULL);
writer->function_types = g_hash_table_new_full (gsk_sl_function_type_hash, gsk_sl_function_type_equal,
(GDestroyNotify) gsk_sl_function_type_unref, NULL);
return writer;
}
GskSpvWriter *
gsk_spv_writer_ref (GskSpvWriter *writer)
{
g_return_val_if_fail (writer != NULL, NULL);
writer->ref_count += 1;
return writer;
}
void
gsk_spv_writer_unref (GskSpvWriter *writer)
{
guint i;
if (writer == NULL)
return;
writer->ref_count -= 1;
if (writer->ref_count > 0)
return;
g_slist_free_full (writer->pending_blocks, (GDestroyNotify) gsk_spv_code_block_free);
for (i = 0; i < GSK_SPV_WRITER_N_GLOBAL_SECTIONS; i++)
{
g_array_free (writer->code[i], TRUE);
}
g_hash_table_destroy (writer->pointer_types);
g_hash_table_destroy (writer->types);
g_hash_table_destroy (writer->image_types);
g_hash_table_destroy (writer->values);
g_hash_table_destroy (writer->variables);
g_hash_table_destroy (writer->functions);
g_hash_table_destroy (writer->function_types);
g_slice_free (GskSpvWriter, writer);
}
static guint32
gsk_spv_writer_write_function (GskSpvWriter *writer,
GskSlFunction *function,
GskSpvWriterFunc initializer,
gpointer initializer_data)
{
GskSpvCodeBlock *block;
guint32 result;
g_assert (g_hash_table_lookup (writer->functions, function) == NULL);
block = gsk_spv_code_block_new ();
writer->blocks = g_slist_prepend (writer->blocks, block);
result = gsk_sl_function_write_spv (function, writer, initializer, initializer_data);
g_hash_table_insert (writer->functions, gsk_sl_function_ref (function), GUINT_TO_POINTER (result));
g_assert (writer->blocks->data == block);
writer->blocks = g_slist_remove (writer->blocks, block);
writer->pending_blocks = g_slist_prepend (writer->pending_blocks, block);
return result;
}
static gint
compare_guint32 (gconstpointer a,
gconstpointer b)
{
guint32 ua = *(const guint32 *) a;
guint32 ub = *(const guint32 *) b;
return ua - ub;
}
static guint32 *
gsk_spv_writer_collect_entry_point_interfaces (GskSpvWriter *writer,
gsize *n_interfaces)
{
GHashTableIter iter;
GArray *interfaces;
gpointer variable, id;
interfaces = g_array_new (FALSE, FALSE, sizeof (guint32));
g_hash_table_iter_init (&iter, writer->variables);
while (g_hash_table_iter_next (&iter, &variable, &id))
{
switch (gsk_sl_variable_get_qualifier (variable)->storage)
{
case GSK_SL_STORAGE_DEFAULT:
default:
g_assert_not_reached();
case GSK_SL_STORAGE_GLOBAL:
case GSK_SL_STORAGE_GLOBAL_CONST:
case GSK_SL_STORAGE_LOCAL:
case GSK_SL_STORAGE_LOCAL_CONST:
case GSK_SL_STORAGE_PARAMETER_IN:
case GSK_SL_STORAGE_PARAMETER_OUT:
case GSK_SL_STORAGE_PARAMETER_INOUT:
case GSK_SL_STORAGE_PARAMETER_CONST:
case GSK_SL_STORAGE_GLOBAL_UNIFORM:
continue;
case GSK_SL_STORAGE_GLOBAL_IN:
case GSK_SL_STORAGE_GLOBAL_OUT:
break;
}
g_array_append_val (interfaces, (guint32) { GPOINTER_TO_UINT (id) });
}
/* Try to be like glslang */
g_array_sort (interfaces, compare_guint32);
*n_interfaces = interfaces->len;
return (guint32 *) g_array_free (interfaces, FALSE);
}
static GskSpvExecutionModel
gsk_spv_writer_get_execution_model (GskSpvWriter *writer)
{
switch (writer->stage)
{
case GSK_SL_SHADER_VERTEX:
return GSK_SPV_EXECUTION_MODEL_VERTEX;
case GSK_SL_SHADER_FRAGMENT:
return GSK_SPV_EXECUTION_MODEL_FRAGMENT;
default:
g_assert_not_reached ();
return GSK_SPV_EXECUTION_MODEL_FRAGMENT;
}
}
static void
gsk_spv_writer_do_write (GskSpvWriter *writer,
GskSlFunction *entry_point,
GskSpvWriterFunc initializer,
gpointer initializer_data)
{
guint32 *interfaces;
gsize n_interfaces;
guint32 entry_point_id;
gsk_spv_writer_capability (writer, GSK_SPV_CAPABILITY_SHADER);
writer->extended_instructions_id = gsk_spv_writer_ext_inst_import (writer,
"GLSL.std.450");
gsk_spv_writer_source (writer,
GSK_SPV_SOURCE_LANGUAGE_GLSL,
440,
0,
NULL);
gsk_spv_writer_source_extension (writer, "GL_GOOGLE_cpp_style_line_directive");
gsk_spv_writer_source_extension (writer, "GL_GOOGLE_include_directive");
gsk_spv_writer_memory_model (writer,
GSK_SPV_ADDRESSING_MODEL_LOGICAL,
GSK_SPV_MEMORY_MODEL_GLSL450);
entry_point_id = gsk_spv_writer_write_function (writer, entry_point, initializer, initializer_data);
interfaces = gsk_spv_writer_collect_entry_point_interfaces (writer,
&n_interfaces);
gsk_spv_writer_entry_point (writer,
gsk_spv_writer_get_execution_model (writer),
entry_point_id,
"main",
interfaces,
n_interfaces);
g_free (interfaces);
if (writer->stage == GSK_SL_SHADER_FRAGMENT)
gsk_spv_writer_execution_mode (writer,
entry_point_id,
GSK_SPV_EXECUTION_MODE_ORIGIN_UPPER_LEFT);
}
static void
gsk_spv_writer_clear (GskSpvWriter *writer)
{
guint i;
g_slist_free_full (writer->pending_blocks, (GDestroyNotify) gsk_spv_code_block_free);
writer->pending_blocks = NULL;
writer->extended_instructions_id = 0;
for (i = 0; i < GSK_SPV_WRITER_N_GLOBAL_SECTIONS; i++)
{
g_array_set_size (writer->code[i], 0);
}
g_hash_table_remove_all (writer->pointer_types);
g_hash_table_remove_all (writer->types);
g_hash_table_remove_all (writer->image_types);
g_hash_table_remove_all (writer->values);
g_hash_table_remove_all (writer->variables);
g_hash_table_remove_all (writer->functions);
g_hash_table_remove_all (writer->function_types);
}
GBytes *
gsk_spv_writer_write (GskSpvWriter *writer,
GskSlFunction *entry_point,
GskSpvWriterFunc initializer,
gpointer initializer_data)
{
GArray *array;
gsize size;
GSList *l;
guint i;
gsk_spv_writer_do_write (writer, entry_point, initializer, initializer_data);
array = g_array_new (FALSE, FALSE, sizeof (guint32));
g_array_append_val (array, (guint32) { GSK_SPV_MAGIC_NUMBER });
g_array_append_val (array, (guint32) { (GSK_SPV_VERSION_MAJOR << 16) | (GSK_SPV_VERSION_MINOR << 8) });
g_array_append_val (array, (guint32) { GSK_SPV_GENERATOR });
g_array_append_val (array, (guint32) { writer->last_id + 1 });
g_array_append_val (array, (guint32) { 0 });
for (i = 0; i < GSK_SPV_WRITER_N_GLOBAL_SECTIONS; i++)
{
g_array_append_vals (array, writer->code[i]->data, writer->code[i]->len);
}
for (l = writer->pending_blocks; l; l = l->next)
{
GskSpvCodeBlock *block = l->data;
for (i = 0; i < GSK_SPV_WRITER_N_BLOCK_SECTIONS; i++)
{
g_array_append_vals (array, block->code[i]->data, block->code[i]->len);
}
}
gsk_spv_writer_clear (writer);
size = array->len * sizeof (guint32);
return g_bytes_new_take (g_array_free (array, FALSE), size);
}
guint32
gsk_spv_writer_get_id_for_extended_instructions (GskSpvWriter *writer)
{
return writer->extended_instructions_id;
}
guint32
gsk_spv_writer_get_id_for_type (GskSpvWriter *writer,
GskSlType *type)
{
guint32 result;
result = GPOINTER_TO_UINT (g_hash_table_lookup (writer->types, type));
if (result != 0)
return result;
result = gsk_sl_type_write_spv (type, writer);
g_hash_table_insert (writer->types, gsk_sl_type_ref (type), GUINT_TO_POINTER (result));
return result;
}
guint32
gsk_spv_writer_get_id_for_image_type (GskSpvWriter *writer,
const GskSlImageType *type)
{
guint32 result;
result = GPOINTER_TO_UINT (g_hash_table_lookup (writer->image_types, type));
if (result != 0)
return result;
result = gsk_sl_image_type_write_spv (type, writer);
g_hash_table_insert (writer->image_types, (gpointer) type, GUINT_TO_POINTER (result));
return result;
}
guint32
gsk_spv_writer_get_id_for_pointer_type (GskSpvWriter *writer,
GskSlType *type,
GskSpvStorageClass storage)
{
GskSpvPointerType pointer_type = { type, storage };
guint32 result;
result = GPOINTER_TO_UINT (g_hash_table_lookup (writer->pointer_types, &pointer_type));
if (result != 0)
return result;
result = gsk_spv_writer_type_pointer (writer,
storage,
gsk_spv_writer_get_id_for_type (writer, type));
gsk_sl_type_ref (type);
g_hash_table_insert (writer->pointer_types, g_memdup (&pointer_type, sizeof (GskSpvPointerType)), GUINT_TO_POINTER (result));
return result;
}
guint32
gsk_spv_writer_get_id_for_value (GskSpvWriter *writer,
GskSlValue *value)
{
guint32 result;
result = GPOINTER_TO_UINT (g_hash_table_lookup (writer->values, value));
if (result != 0)
return result;
result = gsk_sl_value_write_spv (value, writer);
g_hash_table_insert (writer->values, gsk_sl_value_copy (value), GUINT_TO_POINTER (result));
return result;
}
GskSlValue *
gsk_spv_writer_get_value_for_id (GskSpvWriter *writer,
guint32 id)
{
GHashTableIter iter;
gpointer value, value_id;
g_hash_table_iter_init (&iter, writer->values);
while (g_hash_table_iter_next (&iter, &value, &value_id))
{
if (GPOINTER_TO_UINT (value_id) == id)
return value;
}
return NULL;
}
guint32
gsk_spv_writer_get_id_for_zero (GskSpvWriter *writer,
GskSlType *type)
{
GskSlValue *value;
guint32 result_id;
g_return_val_if_fail (gsk_sl_type_is_basic (type), 0);
value = gsk_sl_value_new (type);
result_id = gsk_spv_writer_get_id_for_value (writer, value);
gsk_sl_value_free (value);
return result_id;
}
guint32
gsk_spv_writer_get_id_for_one (GskSpvWriter *writer,
GskSlType *type)
{
GskSlValue *value;
guint32 result_id;
gpointer data;
gsize i;
g_return_val_if_fail (gsk_sl_type_is_basic (type), 0);
value = gsk_sl_value_new (type);
data = gsk_sl_value_get_data (value);
for (i = 0; i < gsk_sl_type_get_n_components (type); i++)
{
switch (gsk_sl_type_get_scalar_type (type))
{
case GSK_SL_INT:
((gint32 *) data)[i] = 1;
break;
case GSK_SL_UINT:
((guint32 *) data)[i] = 1;
break;
case GSK_SL_FLOAT:
((float *) data)[i] = 1;
break;
case GSK_SL_DOUBLE:
((double *) data)[i] = 1;
break;
case GSK_SL_BOOL:
((guint32 *) data)[i] = 1;
break;
case GSK_SL_VOID:
break;
default:
g_assert_not_reached ();
break;
}
}
result_id = gsk_spv_writer_get_id_for_value (writer, value);
gsk_sl_value_free (value);
return result_id;
}
guint32
gsk_spv_writer_get_id_for_variable (GskSpvWriter *writer,
GskSlVariable *variable)
{
guint32 result;
result = GPOINTER_TO_UINT (g_hash_table_lookup (writer->variables, variable));
if (result != 0)
return result;
result = gsk_sl_variable_write_spv (variable, writer);
g_hash_table_insert (writer->variables, gsk_sl_variable_ref (variable), GUINT_TO_POINTER (result));
return result;
}
guint32
gsk_spv_writer_get_id_for_function (GskSpvWriter *writer,
GskSlFunction *function)
{
guint32 result;
result = GPOINTER_TO_UINT (g_hash_table_lookup (writer->functions, function));
if (result != 0)
return result;
return gsk_spv_writer_write_function (writer, function, NULL, NULL);
}
guint32
gsk_spv_writer_get_id_for_function_type (GskSpvWriter *writer,
GskSlFunctionType *function_type)
{
guint32 result;
result = GPOINTER_TO_UINT (g_hash_table_lookup (writer->function_types, function_type));
if (result != 0)
return result;
result = gsk_sl_function_type_write_spv (function_type, writer);
g_hash_table_insert (writer->function_types, gsk_sl_function_type_ref (function_type), GUINT_TO_POINTER (result));
return result;
}
guint32
gsk_spv_writer_make_id (GskSpvWriter *writer)
{
writer->last_id++;
return writer->last_id;
}
GArray *
gsk_spv_writer_get_bytes (GskSpvWriter *writer,
GskSpvWriterSection section)
{
if (section < GSK_SPV_WRITER_SECTION_BLOCK_FIRST)
return writer->code[section];
return ((GskSpvCodeBlock *) writer->blocks->data)->code[section - GSK_SPV_WRITER_SECTION_BLOCK_FIRST];
}
void
gsk_spv_writer_start_code_block (GskSpvWriter *writer,
guint32 label_id,
guint32 continue_id,
guint32 break_id)
{
GskSpvCodeBlock *block;
block = writer->blocks->data;
block->label_id = label_id;
if (continue_id != 0)
block->continue_id = continue_id;
if (break_id != 0)
block->break_id = break_id;
}
guint32
gsk_spv_writer_get_label_id (GskSpvWriter *writer)
{
GskSpvCodeBlock *block = writer->blocks->data;
return block->label_id;
}
guint32
gsk_spv_writer_get_continue_id (GskSpvWriter *writer)
{
GskSpvCodeBlock *block = writer->blocks->data;
return block->continue_id;
}
guint32
gsk_spv_writer_get_break_id (GskSpvWriter *writer)
{
GskSpvCodeBlock *block = writer->blocks->data;
return block->break_id;
}
static void
copy_4_bytes (gpointer dest, gpointer src)
{
memcpy (dest, src, 4);
}
static void
copy_8_bytes (gpointer dest, gpointer src)
{
memcpy (dest, src, 8);
}
guint32
gsk_spv_writer_convert (GskSpvWriter *writer,
guint32 id,
GskSlType *type,
GskSlType *new_type)
{
GskSlScalarType scalar = gsk_sl_type_get_scalar_type (type);
GskSlScalarType new_scalar = gsk_sl_type_get_scalar_type (new_type);
if (scalar == new_scalar)
return id;
if (gsk_sl_type_is_scalar (type) ||
gsk_sl_type_is_vector (type))
{
GskSlValue *value;
guint32 true_id, false_id, zero_id;
switch (new_scalar)
{
case GSK_SL_VOID:
default:
g_assert_not_reached ();
return id;
case GSK_SL_INT:
case GSK_SL_UINT:
switch (scalar)
{
case GSK_SL_INT:
case GSK_SL_UINT:
return gsk_spv_writer_bitcast (writer, new_type, id);
case GSK_SL_FLOAT:
case GSK_SL_DOUBLE:
if (new_scalar == GSK_SL_UINT)
return gsk_spv_writer_convert_f_to_u (writer, new_type, id);
else
return gsk_spv_writer_convert_f_to_s (writer, new_type, id);
case GSK_SL_BOOL:
value = gsk_sl_value_new (new_type);
false_id = gsk_spv_writer_get_id_for_value (writer, value);
gsk_sl_value_componentwise (value, copy_4_bytes, &(gint32) { 1 });
true_id = gsk_spv_writer_get_id_for_value (writer, value);
gsk_sl_value_free (value);
return gsk_spv_writer_select (writer, new_type, id, true_id, false_id);
case GSK_SL_VOID:
default:
g_assert_not_reached ();
return id;
}
g_assert_not_reached ();
case GSK_SL_FLOAT:
case GSK_SL_DOUBLE:
switch (scalar)
{
case GSK_SL_INT:
return gsk_spv_writer_convert_s_to_f (writer, new_type, id);
case GSK_SL_UINT:
return gsk_spv_writer_convert_u_to_f (writer, new_type, id);
case GSK_SL_FLOAT:
case GSK_SL_DOUBLE:
return gsk_spv_writer_f_convert (writer, new_type, id);
case GSK_SL_BOOL:
value = gsk_sl_value_new (new_type);
false_id = gsk_spv_writer_get_id_for_value (writer, value);
if (scalar == GSK_SL_DOUBLE)
gsk_sl_value_componentwise (value, copy_8_bytes, &(double) { 1 });
else
gsk_sl_value_componentwise (value, copy_4_bytes, &(float) { 1 });
true_id = gsk_spv_writer_get_id_for_value (writer, value);
gsk_sl_value_free (value);
return gsk_spv_writer_select (writer,
new_type,
id,
true_id,
false_id);
case GSK_SL_VOID:
default:
g_assert_not_reached ();
return id;
}
g_assert_not_reached ();
case GSK_SL_BOOL:
switch (scalar)
{
case GSK_SL_INT:
case GSK_SL_UINT:
value = gsk_sl_value_new (new_type);
zero_id = gsk_spv_writer_get_id_for_value (writer, value);
gsk_sl_value_free (value);
return gsk_spv_writer_i_not_equal (writer, new_type, id, zero_id);
case GSK_SL_FLOAT:
case GSK_SL_DOUBLE:
value = gsk_sl_value_new (new_type);
zero_id = gsk_spv_writer_get_id_for_value (writer, value);
gsk_sl_value_free (value);
return gsk_spv_writer_f_ord_not_equal (writer, new_type, id, zero_id);
case GSK_SL_BOOL:
case GSK_SL_VOID:
default:
g_assert_not_reached ();
return id;
}
g_assert_not_reached ();
}
}
else if (gsk_sl_type_is_matrix (type))
{
GskSlType *row_type, *new_row_type;
guint i, n = gsk_sl_type_get_length (type);
guint32 ids[n];
row_type = gsk_sl_type_get_index_type (type);
new_row_type = gsk_sl_type_get_index_type (new_type);
for (i = 0; i < n; i++)
{
ids[i] = gsk_spv_writer_composite_extract (writer, row_type, id, (guint32[1]) { i }, 1);
ids[i] = gsk_spv_writer_convert (writer, ids[i], row_type, new_row_type);
}
return gsk_spv_writer_composite_construct (writer, new_type, ids, n);
}
else
{
g_return_val_if_reached (id);
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

107
gsk/gskspvwriterprivate.h Normal file
View File

@@ -0,0 +1,107 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GSK_SPV_WRITER_PRIVATE_H__
#define __GSK_SPV_WRITER_PRIVATE_H__
#include <glib.h>
#include "gsksltypesprivate.h"
#include "gskspvenumsprivate.h"
#include "gskspvenumsglslprivate.h"
G_BEGIN_DECLS
#define GSK_SPV_MAGIC_NUMBER 0x07230203
#define GSK_SPV_VERSION_MAJOR 1
#define GSK_SPV_VERSION_MINOR 0
#define GSK_SPV_GENERATOR 0
typedef enum {
GSK_SPV_WRITER_SECTION_HEADER,
GSK_SPV_WRITER_SECTION_DEBUG,
GSK_SPV_WRITER_SECTION_DECORATE,
GSK_SPV_WRITER_SECTION_DEFINE,
GSK_SPV_WRITER_SECTION_DECLARE,
GSK_SPV_WRITER_SECTION_CODE,
/* add more */
GSK_SPV_WRITER_N_SECTIONS
} GskSpvWriterSection;
#define GSK_SPV_WRITER_SECTION_BLOCK_FIRST GSK_SPV_WRITER_SECTION_DECLARE
#define GSK_SPV_WRITER_N_GLOBAL_SECTIONS GSK_SPV_WRITER_SECTION_BLOCK_FIRST
#define GSK_SPV_WRITER_N_BLOCK_SECTIONS (GSK_SPV_WRITER_N_SECTIONS - GSK_SPV_WRITER_N_GLOBAL_SECTIONS)
GskSpvWriter * gsk_spv_writer_new (GskSlShaderStage stage);
GskSpvWriter * gsk_spv_writer_ref (GskSpvWriter *writer);
void gsk_spv_writer_unref (GskSpvWriter *writer);
GBytes * gsk_spv_writer_write (GskSpvWriter *writer,
GskSlFunction *entry_point,
GskSpvWriterFunc initializer,
gpointer initializer_data);
guint32 gsk_spv_writer_get_id_for_extended_instructions
(GskSpvWriter *writer);
guint32 gsk_spv_writer_get_id_for_type (GskSpvWriter *writer,
GskSlType *type);
guint32 gsk_spv_writer_get_id_for_image_type (GskSpvWriter *writer,
const GskSlImageType *type);
guint32 gsk_spv_writer_get_id_for_pointer_type (GskSpvWriter *writer,
GskSlType *type,
GskSpvStorageClass storage);
guint32 gsk_spv_writer_get_id_for_value (GskSpvWriter *writer,
GskSlValue *value);
GskSlValue * gsk_spv_writer_get_value_for_id (GskSpvWriter *writer,
guint32 id);
guint32 gsk_spv_writer_get_id_for_zero (GskSpvWriter *writer,
GskSlType *type);
guint32 gsk_spv_writer_get_id_for_one (GskSpvWriter *writer,
GskSlType *type);
guint32 gsk_spv_writer_get_id_for_variable (GskSpvWriter *writer,
GskSlVariable *variable);
guint32 gsk_spv_writer_get_id_for_function (GskSpvWriter *writer,
GskSlFunction *function);
guint32 gsk_spv_writer_get_id_for_function_type (GskSpvWriter *writer,
GskSlFunctionType *function_type);
guint32 gsk_spv_writer_make_id (GskSpvWriter *writer);
GArray * gsk_spv_writer_get_bytes (GskSpvWriter *writer,
GskSpvWriterSection section);
guint32 gsk_spv_writer_convert (GskSpvWriter *writer,
guint32 id,
GskSlType *type,
GskSlType *new_type);
guint32 gsk_spv_writer_get_label_id (GskSpvWriter *writer);
guint32 gsk_spv_writer_get_continue_id (GskSpvWriter *writer);
guint32 gsk_spv_writer_get_break_id (GskSpvWriter *writer);
void gsk_spv_writer_start_code_block (GskSpvWriter *writer,
guint32 label_id,
guint32 continue_id,
guint32 break_id);
#include "gskspvwritergeneratedprivate.h"
#include "gskspvwritergeneratedglslprivate.h"
G_END_DECLS
#endif /* __GSK_SPV_WRITER_PRIVATE_H__ */

View File

@@ -26,7 +26,22 @@
#include <gdk/gdk.h>
#include <gsk/gskenums.h>
typedef struct _GskCodeLocation GskCodeLocation;
typedef struct _GskCodeSource GskCodeSource;
typedef struct _GskPixelShader GskPixelShader;
typedef struct _GskRenderer GskRenderer;
typedef struct _GskSlCompiler GskSlCompiler;
typedef struct _GskSlProgram GskSlProgram;
typedef struct _GskTexture GskTexture;
struct _GskCodeLocation
{
GskCodeSource *source;
gsize bytes;
gsize chars;
gsize lines;
gsize line_bytes;
gsize line_chars;
};
#endif /* __GSK_TYPES_H__ */

View File

@@ -14,10 +14,14 @@ gsk_private_source_shaders = [
]
gsk_public_sources = files([
'gskcodesource.c',
'gskpixelshader.c',
'gskrenderer.c',
'gskrendernode.c',
'gskrendernodeimpl.c',
'gskroundedrect.c',
'gskslcompiler.c',
'gskslprogram.c',
'gsktexture.c',
])
@@ -31,10 +35,31 @@ gsk_private_sources = files([
'gskprivate.c',
'gskprofiler.c',
'gskshaderbuilder.c',
'gskslbinary.c',
'gsksldeclaration.c',
'gsksldefine.c',
'gskslenvironment.c',
'gskslexpression.c',
'gskslfunction.c',
'gskslfunctiontype.c',
'gskslimagetype.c',
'gskslnativefunction.c',
'gskslnativevariable.c',
'gskslpreprocessor.c',
'gskslprinter.c',
'gskslqualifier.c',
'gskslscope.c',
'gskslstatement.c',
'gsksltokenizer.c',
'gsksltype.c',
'gskslvalue.c',
'gskslvariable.c',
'gskspvwriter.c'
])
gsk_public_headers = files([
'gskenums.h',
'gskpixelshader.h',
'gskrenderer.h',
'gskrendernode.h',
'gskroundedrect.h',
@@ -42,6 +67,11 @@ gsk_public_headers = files([
'gsktypes.h',
])
gsk_private_headers = files([
'gskspvenumsprivate.h',
'gskspvwritergeneratedprivate.h'
])
install_headers(gsk_public_headers, 'gsk.h', subdir: 'gtk-4.0/gsk')
gsk_private_vulkan_shaders = []

5630
gsk/spirv.core.grammar.json Normal file

File diff suppressed because it is too large Load Diff

757
gsk/spirv.js Normal file
View File

@@ -0,0 +1,757 @@
function usage()
{
print ("usage: gjs spirv.js enums|functions SPIRV_GRAMMAR_FILE");
}
if (ARGV.length != 2)
{
usage();
throw new SyntaxError ("Script needs 2 arguments but got " + ARGV.length);
}
var command = ARGV[0];
var extinst = "";
if (ARGV[0].indexOf("-") > 0)
{
extinst = ARGV[0].substr (0, ARGV[0].indexOf("-"));
command = ARGV[0].substr (extinst.length + 1);
}
var contents = imports.gi.Gio.File.new_for_path(ARGV[1]).load_contents(null);
var spirv = JSON.parse(contents[1]);
if (!String.prototype.format) {
String.prototype.format = function() {
var args = arguments;
return this.replace(/{(\d+)}/g, function(match, number) {
return typeof args[number] != 'undefined'
? args[number]
: match
;
});
};
}
function all_lower(s)
{
let result = "";
let needs_underscore = false;
let had_caps = false;
for (let i = 0; i < s.length; i++)
{
if (s[i] >= 'a' && s[i] <= 'z')
{
needs_underscore = true;
had_caps = false;
result += s[i];
}
else if (s[i] >= "A" && s[i] <= "Z")
{
if (needs_underscore)
result += "_";
else if (s[i+1] && s[i+1] >= "a" && s[i+1] <= "z" && had_caps)
result += "_";
needs_underscore = false;
had_caps = true;
result += s[i].toLowerCase();
}
else if (s[i] >= '0' && s[i] <= '9')
{
needs_underscore = true
had_caps = false;
result += s[i]
}
else
{
needs_underscore = false
had_caps = false;
result += "_";
}
}
return result;
}
function all_upper(s)
{
return all_lower(s).toUpperCase();
}
function sanitize_name (name)
{
name = name.substr(1);
return all_lower(name.substr(0, name.indexOf("'")));
}
var SpecialTypes = {
"OpVariable": { "result_type": "IdResultPointerType" },
"OpImageTexelPointer": { "result_type": "IdResultPointerType" },
"OpAccessChain": { "result_type": "IdResultPointerType" },
"OpInBoundsAccessChain": { "result_type": "IdResultPointerType" },
"OpConvertUToPtr": { "result_type": "IdResultPointerType" },
"OpPtrCastToGeneric": { "result_type": "IdResultPointerType" },
"OpGenericCastToPtr": { "result_type": "IdResultPointerType" },
"OpGenericCastToPtrExplicit": { "result_type": "IdResultPointerType" },
"OpFunctionParameter": { "result_type": "IdRef" },
"OpLabel": { "result": "IdRef" },
"OpImage": { "result_type": "IdRef" }
};
var ExtraOperands = {
"OpDecorate": [ { "kind" : "LiteralContextDependentNumber", "name" : "'Value'" } ],
"OpMemberDecorate": [ { "kind" : "LiteralContextDependentNumber", "name" : "'Value'" } ]
};
/* maps opcodes to section in file they appear in */
var Sections = {
"OpNop": "",
"OpUndef": "",
"OpSourceContinued": "",
"OpSource": "debug",
"OpSourceExtension": "debug",
"OpName": "debug",
"OpMemberName": "debug",
"OpString": "",
"OpLine": "",
"OpExtension": "header",
"OpExtInstImport": "header",
"OpExtInst": "",
"OpMemoryModel": "header",
"OpEntryPoint": "header",
"OpExecutionMode": "header",
"OpCapability": "header",
"OpTypeVoid": "define",
"OpTypeBool": "define",
"OpTypeInt": "define",
"OpTypeFloat": "define",
"OpTypeVector": "define",
"OpTypeMatrix": "define",
"OpTypeImage": "define",
"OpTypeSampler": "define",
"OpTypeSampledImage": "define",
"OpTypeArray": "define",
"OpTypeRuntimeArray": "define",
"OpTypeStruct": "define",
"OpTypeOpaque": "define",
"OpTypePointer": "define",
"OpTypeFunction": "define",
"OpTypeEvent": "define",
"OpTypeDeviceEvent": "define",
"OpTypeReserveId": "define",
"OpTypeQueue": "define",
"OpTypePipe": "define",
"OpTypeForwardPointer": "define",
"OpConstantTrue": "define",
"OpConstantFalse": "define",
"OpConstant": "define",
"OpConstantComposite": "define",
"OpConstantSampler": "define",
"OpConstantNull": "define",
"OpSpecConstantTrue": "define",
"OpSpecConstantFalse": "define",
"OpSpecConstant": "define",
"OpSpecConstantComposite": "define",
"OpSpecConstantOp": "define",
"OpFunction": "declare",
"OpFunctionParameter": "declare",
"OpFunctionEnd": "code",
"OpFunctionCall": "code",
"OpVariable": "",
"OpImageTexelPointer": "code",
"OpLoad": "code",
"OpStore": "code",
"OpCopyMemory": "code",
"OpCopyMemorySized": "code",
"OpAccessChain": "code",
"OpInBoundsAccessChain": "code",
"OpPtrAccessChain": "code",
"OpArrayLength": "code",
"OpGenericPtrMemSemantics": "",
"OpInBoundsPtrAccessChain": "code",
"OpDecorate": "decorate",
"OpMemberDecorate": "decorate",
"OpDecorationGroup": "decorate",
"OpGroupDecorate": "decorate",
"OpGroupMemberDecorate": "decorate",
"OpVectorExtractDynamic": "code",
"OpVectorInsertDynamic": "code",
"OpVectorShuffle": "code",
"OpCompositeConstruct": "code",
"OpCompositeExtract": "code",
"OpCompositeInsert": "code",
"OpCopyObject": "",
"OpTranspose": "code",
"OpSampledImage": "",
"OpImageSampleImplicitLod": "code",
"OpImageSampleExplicitLod": "code",
"OpImageSampleDrefImplicitLod": "code",
"OpImageSampleDrefExplicitLod": "code",
"OpImageSampleProjImplicitLod": "code",
"OpImageSampleProjExplicitLod": "code",
"OpImageSampleProjDrefImplicitLod": "code",
"OpImageSampleProjDrefExplicitLod": "code",
"OpImageFetch": "code",
"OpImageGather": "code",
"OpImageDrefGather": "code",
"OpImageRead": "code",
"OpImageWrite": "code",
"OpImage": "code",
"OpImageQueryFormat": "code",
"OpImageQueryOrder": "code",
"OpImageQuerySizeLod": "code",
"OpImageQuerySize": "code",
"OpImageQueryLod": "code",
"OpImageQueryLevels": "code",
"OpImageQuerySamples": "code",
"OpConvertFToU": "code",
"OpConvertFToS": "code",
"OpConvertSToF": "code",
"OpConvertUToF": "code",
"OpUConvert": "code",
"OpSConvert": "code",
"OpFConvert": "code",
"OpQuantizeToF16": "code",
"OpConvertPtrToU": "code",
"OpSatConvertSToU": "code",
"OpSatConvertUToS": "code",
"OpConvertUToPtr": "code",
"OpPtrCastToGeneric": "code",
"OpGenericCastToPtr": "code",
"OpGenericCastToPtrExplicit": "code",
"OpBitcast": "code",
"OpSNegate": "code",
"OpFNegate": "code",
"OpIAdd": "code",
"OpFAdd": "code",
"OpISub": "code",
"OpFSub": "code",
"OpIMul": "code",
"OpFMul": "code",
"OpUDiv": "code",
"OpSDiv": "code",
"OpFDiv": "code",
"OpUMod": "code",
"OpSRem": "code",
"OpSMod": "code",
"OpFRem": "code",
"OpFMod": "code",
"OpVectorTimesScalar": "code",
"OpMatrixTimesScalar": "code",
"OpVectorTimesMatrix": "code",
"OpMatrixTimesVector": "code",
"OpMatrixTimesMatrix": "code",
"OpOuterProduct": "code",
"OpDot": "code",
"OpIAddCarry": "code",
"OpISubBorrow": "code",
"OpUMulExtended": "code",
"OpSMulExtended": "code",
"OpAny": "code",
"OpAll": "code",
"OpIsNan": "code",
"OpIsInf": "code",
"OpIsFinite": "code",
"OpIsNormal": "code",
"OpSignBitSet": "code",
"OpLessOrGreater": "code",
"OpOrdered": "code",
"OpUnordered": "code",
"OpLogicalEqual": "code",
"OpLogicalNotEqual": "code",
"OpLogicalOr": "code",
"OpLogicalAnd": "code",
"OpLogicalNot": "code",
"OpSelect": "code",
"OpIEqual": "code",
"OpINotEqual": "code",
"OpUGreaterThan": "code",
"OpSGreaterThan": "code",
"OpUGreaterThanEqual": "code",
"OpSGreaterThanEqual": "code",
"OpULessThan": "code",
"OpSLessThan": "code",
"OpULessThanEqual": "code",
"OpSLessThanEqual": "code",
"OpFOrdEqual": "code",
"OpFUnordEqual": "code",
"OpFOrdNotEqual": "code",
"OpFUnordNotEqual": "code",
"OpFOrdLessThan": "code",
"OpFUnordLessThan": "code",
"OpFOrdGreaterThan": "code",
"OpFUnordGreaterThan": "code",
"OpFOrdLessThanEqual": "code",
"OpFUnordLessThanEqual": "code",
"OpFOrdGreaterThanEqual": "code",
"OpFUnordGreaterThanEqual": "code",
"OpShiftRightLogical": "code",
"OpShiftRightArithmetic": "code",
"OpShiftLeftLogical": "code",
"OpBitwiseOr": "code",
"OpBitwiseXor": "code",
"OpBitwiseAnd": "code",
"OpNot": "code",
"OpBitFieldInsert": "code",
"OpBitFieldSExtract": "code",
"OpBitFieldUExtract": "code",
"OpBitReverse": "code",
"OpBitCount": "code",
"OpDPdx": "code",
"OpDPdy": "code",
"OpFwidth": "code",
"OpDPdxFine": "code",
"OpDPdyFine": "code",
"OpFwidthFine": "code",
"OpDPdxCoarse": "code",
"OpDPdyCoarse": "code",
"OpFwidthCoarse": "code",
"OpEmitVertex": "code",
"OpEndPrimitive": "code",
"OpEmitStreamVertex": "code",
"OpEndStreamPrimitive": "code",
"OpControlBarrier": "code",
"OpMemoryBarrier": "code",
"OpAtomicLoad": "code",
"OpAtomicStore": "code",
"OpAtomicExchange": "code",
"OpAtomicCompareExchange": "code",
"OpAtomicCompareExchangeWeak": "code",
"OpAtomicIIncrement": "code",
"OpAtomicIDecrement": "code",
"OpAtomicIAdd": "code",
"OpAtomicISub": "code",
"OpAtomicSMin": "code",
"OpAtomicUMin": "code",
"OpAtomicSMax": "code",
"OpAtomicUMax": "code",
"OpAtomicAnd": "code",
"OpAtomicOr": "code",
"OpAtomicXor": "code",
"OpPhi": "code",
"OpLoopMerge": "code",
"OpSelectionMerge": "code",
"OpLabel": "",
"OpBranch": "code",
"OpBranchConditional": "code",
"OpSwitch": "code",
"OpKill": "code",
"OpReturn": "code",
"OpReturnValue": "code",
"OpUnreachable": "",
"OpLifetimeStart": "",
"OpLifetimeStop": "",
"OpGroupAsyncCopy": "",
"OpGroupWaitEvents": "",
"OpGroupAll": "",
"OpGroupAny": "",
"OpGroupBroadcast": "",
"OpGroupIAdd": "",
"OpGroupFAdd": "",
"OpGroupFMin": "",
"OpGroupUMin": "",
"OpGroupSMin": "",
"OpGroupFMax": "",
"OpGroupUMax": "",
"OpGroupSMax": "",
"OpReadPipe": "",
"OpWritePipe": "",
"OpReservedReadPipe": "",
"OpReservedWritePipe": "",
"OpReserveReadPipePackets": "",
"OpReserveWritePipePackets": "",
"OpCommitReadPipe": "",
"OpCommitWritePipe": "",
"OpIsValidReserveId": "",
"OpGetNumPipePackets": "",
"OpGetMaxPipePackets": "",
"OpGroupReserveReadPipePackets": "",
"OpGroupReserveWritePipePackets": "",
"OpGroupCommitReadPipe": "",
"OpGroupCommitWritePipe": "",
"OpEnqueueMarker": "",
"OpEnqueueKernel": "",
"OpGetKernelNDrangeSubGroupCount": "",
"OpGetKernelNDrangeMaxSubGroupSize": "",
"OpGetKernelWorkGroupSize": "",
"OpGetKernelPreferredWorkGroupSizeMultiple": "",
"OpRetainEvent": "",
"OpReleaseEvent": "",
"OpCreateUserEvent": "",
"OpIsValidEvent": "",
"OpSetUserEventStatus": "",
"OpCaptureEventProfilingInfo": "",
"OpGetDefaultQueue": "",
"OpBuildNDRange": "",
"OpImageSparseSampleImplicitLod": "",
"OpImageSparseSampleExplicitLod": "",
"OpImageSparseSampleDrefImplicitLod": "",
"OpImageSparseSampleDrefExplicitLod": "",
"OpImageSparseSampleProjImplicitLod": "",
"OpImageSparseSampleProjExplicitLod": "",
"OpImageSparseSampleProjDrefImplicitLod": "",
"OpImageSparseSampleProjDrefExplicitLod": "",
"OpImageSparseFetch": "",
"OpImageSparseGather": "",
"OpImageSparseDrefGather": "",
"OpImageSparseTexelsResident": "",
"OpNoLine": "",
"OpAtomicFlagTestAndSet": "",
"OpAtomicFlagClear": "",
"OpImageSparseRead": "",
"OpSubgroupBallotKHR": "",
"OpSubgroupFirstInvocationKHR": "",
"OpSubgroupAllKHR": "",
"OpSubgroupAnyKHR": "",
"OpSubgroupAllEqualKHR": "",
"OpSubgroupReadInvocationKHR": "",
"OpGroupIAddNonUniformAMD": "",
"OpGroupFAddNonUniformAMD": "",
"OpGroupFMinNonUniformAMD": "",
"OpGroupUMinNonUniformAMD": "",
"OpGroupSMinNonUniformAMD": "",
"OpGroupFMaxNonUniformAMD": "",
"OpGroupUMaxNonUniformAMD": "",
"OpGroupSMaxNonUniformAMD": "",
"OpFragmentMaskFetchAMD": "",
"OpFragmentFetchAMD": ""
};
var Operands = {
"IdMemorySemantics": { ctype: "guint32 {0}",
optional_unset: "0",
append_many: "g_array_append_vals ({0}, {1}, {2})",
append_one: "g_array_append_val ({0}, {1})" },
"IdRef": { ctype: "guint32 {0}",
optional_unset: "0",
append_many: "g_array_append_vals ({0}, {1}, {2})",
append_one: "g_array_append_val ({0}, {1})" },
"IdResult": { ctype: "guint32 {0}",
optional_unset: "0",
declare_local: "guint32 {0}_id = gsk_spv_writer_make_id (writer);",
append_one: "g_array_append_val ({0}, {1}_id)" },
"IdResultType": { ctype: "GskSlType *{0}",
optional_unset: "NULL",
declare_local: "guint32 {0}_id = gsk_spv_writer_get_id_for_type (writer, {0});",
append_one: "g_array_append_val ({0}, {1}_id)" },
"IdResultPointerType" : { ctype: "GskSlType *{0}, GskSpvStorageClass {0}_storage",
optional_unset: "NULL",
declare_local: "guint32 {0}_id = gsk_spv_writer_get_id_for_pointer_type (writer, {0}, {0}_storage);",
append_one: "g_array_append_val ({0}, {1}_id)" },
"IdScope": { ctype: "guint32 {0}",
optional_unset: "0",
append_many: "g_array_append_vals ({0}, {1}, {2})",
append_one: "g_array_append_val ({0}, {1})" },
"LiteralContextDependentNumber": { ctype: "guint32 {0}",
is_many: true,
append_many: "g_array_append_vals ({0}, {1}, {2})" },
"LiteralExtInstInteger": { ctype: "guint32 {0}",
append_many: "g_array_append_vals ({0}, {1}, {2})",
append_one: "g_array_append_val ({0}, {1})" },
"LiteralInteger": { ctype: "guint32 {0}",
append_many: "g_array_append_vals ({0}, {1}, {2})",
append_one: "g_array_append_val ({0}, {1})" },
"LiteralString": { ctype: "const char *{0}",
optional_unset: "NULL",
append_one: "append_string ({0}, {1})" },
"LiteralSpecConstantOpInteger": { ctype: "guint32 {0}",
is_many: true,
append_many: "g_array_append_vals ({0}, {1}, {2})" },
"PairIdRefLiteralInteger": { ctype: "guint32 {0}[2]",
append_many: "g_array_append_vals ({0}, {1}, 2 * {2})",
append_one: "g_array_append_vals ({0}, {1}, 2)" },
"PairIdRefIdRef": { ctype: "guint32 {0}[2]",
append_many: "g_array_append_vals ({0}, {1}, 2 * {2})",
append_one: "g_array_append_vals ({0}, {1}, 2)" },
"PairLiteralIntegerIdRef": { ctype: "guint32 {0}[2]",
append_many: "g_array_append_vals ({0}, {1}, 2 * {2})",
append_one: "g_array_append_vals ({0}, {1}, 2)" },
"ImageOperands" : { ctype: "GskSpvImageOperands {0}, guint32 *{0}_args, gsize n_{0}_args",
optional_unset: "0",
append_one: "G_STMT_START{ g_array_append_val ({0}, (guint32) { {1} }); g_array_append_vals ({0}, {1}_args, n_{1}_args); }G_STMT_END" }
};
for (let kind in spirv.operand_kinds)
{
kind = spirv.operand_kinds[kind];
if ((kind.category == "BitEnum" ||
kind.category == "ValueEnum") &&
!Operands[kind.kind])
{
Operands[kind.kind] = { ctype: "GskSpv" + kind.kind + " {0}",
append_one: "g_array_append_val ({0}, (guint32) { {1} })" };
if (kind.category == "BitEnum")
Operands[kind.kind].optional_unset = "0";
if (kind.kind == "AccessQualifier")
Operands[kind.kind].optional_unset = "-1";
}
}
function fix_operand (ins, o)
{
if (o.name)
{
if (o.name == "The name of the opaque type.")
o.varname = "name"
else
o.varname = sanitize_name (o.name);
}
else
{
if (o.kind == "IdResultType")
o.varname = "result_type"
else if (o.kind == "IdResult")
o.varname = "result"
else if (Operands[o.kind])
o.varname = all_lower (o.kind);
}
if (!o.varname)
throw new TypeError (o.name + " of type " + o.kind + " has no variable name");
let operand;
if (SpecialTypes[ins.opname] &&
SpecialTypes[ins.opname][o.varname])
o.kind = SpecialTypes[ins.opname][o.varname];
operand = Operands[o.kind];
if (o.varname == "default")
o.varname += "_";
if (o.kind == "IdResult")
ins.result = true;
o.ctype = operand.ctype;
if (operand.append_one)
o.append_one = operand.append_one;
if (operand.append_many)
o.append_many = operand.append_many;
if (operand.declare_local)
o.declare_local = operand.declare_local;
if (operand.is_many)
{
if (o.quantifier)
throw new SyntaxError ("Can't deal with lists of " + o.kind);
else
o.quantifier = "*";
}
if (!o.quantifier)
o.quantifier = "";
if (o.quantifier == "?")
{
o.varname = "opt_" + o.varname;
if (operand.optional_unset)
o.unset = operand.optional_unset;
}
if (o.quantifier == "*")
{
if (o.varname[o.varname.length - 1] == "1")
o.varname = o.varname.substr(0, o.varname.length - 2);
if (o.varname[o.varname.length - 1] != "s")
o.varname += "s";
}
}
for (let i in spirv.instructions)
{
let ins = spirv.instructions[i];
ins.result = false;
ins.enum_value = "GSK_SPV_OP_" + (extinst ? all_upper(extinst) + "_" + all_upper (ins.opname) : all_upper (ins.opname.substr(2)));
if (!ins.operands)
ins.operands = [];
if (ExtraOperands[ins.opname])
ins.operands = ins.operands.concat (ExtraOperands[ins.opname]);
if (extinst)
{
ins.operands.unshift (
{ "kind" : "IdResultType" },
{ "kind" : "IdResult" }
);
}
for (let o in ins.operands)
{
o = ins.operands[o];
fix_operand (ins, o);
}
if (extinst)
{
ins.section = "code";
ins.section_enum = "GSK_SPV_WRITER_SECTION_CODE";
}
else if (Sections[ins.opname])
{
ins.section = Sections[ins.opname];
ins.section_enum = "GSK_SPV_WRITER_SECTION_" + ins.section.toUpperCase();
}
if (!extinst)
ins.opname = ins.opname.substr(2);
}
function header()
{
print ("/* GTK - The GIMP Toolkit");
print (" * ");
print (" * Copyright © 2017 Benjamin Otte <otte@gnome.org>");
print (" *");
print (" * This library is free software; you can redistribute it and/or");
print (" * modify it under the terms of the GNU Lesser General Public");
print (" * License as published by the Free Software Foundation; either");
print (" * version 2 of the License, or (at your option) any later version.");
print (" *");
print (" * This library is distributed in the hope that it will be useful,");
print (" * but WITHOUT ANY WARRANTY; without even the implied warranty of");
print (" * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU");
print (" * Lesser General Public License for more details.");
print (" *");
print (" * You should have received a copy of the GNU Lesser General Public");
print (" * License along with this library. If not, see <http://www.gnu.org/licenses/>.");
print (" */");
print ("");
print ("/*");
print (" * !!! THIS FILE WAS AUTOGENERATED !!!");
print (" * ");
print (" * This file was created using the command");
print (" * gjs spirv.js " + ARGV.join (" "));
print (" * Apply any changes to those files and then regenerate using above command.");
print (" */");
print ();
}
if (command == "enums")
{
header ();
print ("#ifndef __GSK_SPV_" + (extinst ? all_upper (extinst) + "_" : "") + "ENUMS_H__");
print ("#define __GSK_SPV_" + (extinst ? all_upper (extinst) + "_" : "") + "ENUMS_H__");
print ();
for (let kind in spirv.operand_kinds)
{
kind = spirv.operand_kinds[kind];
if (kind.category == "BitEnum" ||
kind.category == "ValueEnum")
{
print ("typedef enum {");
for (let i = 0; i < kind.enumerants.length; i++)
{
let e = kind.enumerants[i];
//print (Object.keys(e));
print (" GSK_SPV_" + all_upper(kind.kind) + "_" + all_upper (e.enumerant) + " = " + e.value + (i + 1 < kind.enumerants.length ? "," : ""));
}
print ("} GskSpv" + kind.kind + ";");
print ();
}
}
print ("typedef enum {");
for (let i =0; i < spirv.instructions.length; i++)
{
let ins = spirv.instructions[i];
print (" " + ins.enum_value + " = " + ins.opcode + (i + 1 < spirv.instructions.length ? "," : ""));
}
print ("} GskSpvOpcode" + extinst + ";");
print ();
print ("#endif /* __GSK_SPV_" + (extinst ? all_upper (extinst) + "_" : "") + "ENUMS_H__ */");
}
else if (command == "functions")
{
header ();
print ("#include <string.h>");
print ();
print ("#ifndef __GSK_SPV_SEEN_AUTOGENERATED_FUNCTIONS__");
print ("#define __GSK_SPV_SEEN_AUTOGENERATED_FUNCTIONS__");
print ("static inline void");
print ("append_string (GArray *bytes,");
print (" const char *str)");
print ("{");
print (" gsize len = strlen (str);");
print (" guint size = bytes->len;");
print (" g_array_set_size (bytes, size + len / 4 + 1);");
print (" memcpy (&g_array_index (bytes, guint32, size), str, len);");
print ("}");
print ("#endif /* __GSK_SPV_SEEN_AUTOGENERATED_FUNCTIONS__ */");
print ();
for (let i in spirv.instructions)
{
let ins = spirv.instructions[i];
let prefix = "gsk_spv_writer_" + all_lower(ins.opname) + " (";
let len = prefix.length;
if (ins.result)
print ("static inline guint32");
else
print ("static inline void");
if (ins.operands.length > 1 ||
ins.operands.length == 1 && !ins.result)
{
let seen_result = !ins.result;
print (prefix + "GskSpvWriter *writer,");
if (!ins.section)
print (Array(len+1).join(" ") + "GskSpvWriterSection section,");
for (let i = 0; i < ins.operands.length; i++)
{
let o = ins.operands[i];
if (o.kind == "IdResult")
{
seen_result = true;
continue;
}
if (o.quantifier == "*")
{
print (Array(len+1).join(" ") + o.ctype.format ("*" + o.varname) + ",");
print (Array(len+1).join(" ") + "gsize n_" + o.varname + (i + 2 - seen_result < ins.operands.length ? "," : ")"));
}
else
{
print (Array(len+1).join(" ") + o.ctype.format (o.varname) + (i + 2 - seen_result < ins.operands.length ? "," : ")"));
}
}
}
else
{
if (ins.section)
print ("gsk_spv_writer_" + all_lower(ins.opname) + " (GskSpvWriter *writer)");
else
{
print ("gsk_spv_writer_" + all_lower(ins.opname) + " (GskSpvWriter *writer,");
print (Array(len+1).join(" ") + "GskSpvWriterSection section)");
}
}
print ("{");
print (" GArray *bytes = gsk_spv_writer_get_bytes (writer, " + (ins.section_enum ? ins.section_enum : "section" ) + ");");
for (let i = 0; i < ins.operands.length; i++)
{
let o = ins.operands[i];
if (o.declare_local)
print (" " + o.declare_local.format (o.varname));
}
print (" guint start_index = bytes->len;");
print ("");
print (" g_array_append_val (bytes, (guint32) { 0 });");
for (let i = 0; i < ins.operands.length; i++)
{
let o = ins.operands[i];
let indent = " ";
if (o.unset)
{
print (indent + "if (" + o.varname + " != " + o.unset + ")");
indent += " ";
}
if (o.quantifier == "*")
print (indent + o.append_many.format ("bytes", o.varname, "n_" + o.varname) + ";");
else
print (indent + o.append_one.format ("bytes", o.varname) + ";");
if (i == 1 && extinst)
{
print (" g_array_append_val (bytes, (guint32) { gsk_spv_writer_get_id_for_extended_instructions (writer) });");
print (" g_array_append_val (bytes, (guint32) { " + ins.enum_value + " });");
}
}
print (" g_array_index (bytes, guint32, start_index) = (bytes->len - start_index) << 16 | " + (extinst ? "GSK_SPV_OP_EXT_INST" : ins.enum_value) + ";");
if (ins.result)
{
print ("");
print (" return result_id;");
}
print ("}");
print ("");
}
}
else
{
usage ()
}

290
gtk/glsl.c Normal file
View File

@@ -0,0 +1,290 @@
/* GTK - The GIMP Toolkit
*
* Copyright © 2017 Benjamin Otte <otte@gnome.org>
*
* GTK+ is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* GLib is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with GTK+; see the file COPYING. If not,
* see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <gtk/gtk.h>
#ifdef G_IO_WIN32
#include <gio/gwin32outputstream.h>
#include <windows.h>
#else
#include <gio/gunixoutputstream.h>
#include <unistd.h>
#endif
static gboolean
compile (GskSlCompiler *compiler,
GOutputStream *output,
const char *filename)
{
GBytes *bytes;
GskSlProgram *program;
GError *error = NULL;
GFile *file;
file = g_file_new_for_commandline_arg (filename);
program = gsk_sl_compiler_compile_file (compiler,
GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (compiler), "shader-stage")),
file);
g_object_unref (file);
if (program == NULL)
return FALSE;
bytes = gsk_sl_program_to_spirv (program);
if (!g_output_stream_write_all (output, g_bytes_get_data (bytes, NULL), g_bytes_get_size (bytes), NULL, NULL, &error))
{
g_print (error->message);
g_error_free (error);
g_bytes_unref (bytes);
g_object_unref (program);
return FALSE;
}
g_bytes_unref (bytes);
g_object_unref (program);
return TRUE;
}
static gboolean
dump (GskSlCompiler *compiler,
GOutputStream *output,
const char *filename)
{
GString *string;
GskSlProgram *program;
GError *error = NULL;
GFile *file;
file = g_file_new_for_commandline_arg (filename);
program = gsk_sl_compiler_compile_file (compiler,
GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (compiler), "shader-stage")),
file);
g_object_unref (file);
if (program == NULL)
return FALSE;
string = g_string_new (NULL);
gsk_sl_program_print (program, string);
if (!g_output_stream_write_all (output, string->str, string->len, NULL, NULL, &error))
{
g_print (error->message);
g_error_free (error);
g_string_free (string, TRUE);
g_object_unref (program);
return FALSE;
}
g_string_free (string, TRUE);
g_object_unref (program);
return TRUE;
}
static void
usage (GOptionContext *ctx)
{
char *help = g_option_context_get_help (ctx, TRUE, NULL);
g_print ("%s", help);
g_free (help);
exit (EXIT_FAILURE);
}
static gboolean
define (const gchar *option_name,
const gchar *value,
gpointer data,
GError **error)
{
GskSlCompiler *compiler = data;
char **tokens;
gboolean result;
tokens = g_strsplit (value, "=", 2);
result = gsk_sl_compiler_add_define (compiler,
tokens[0],
tokens[1],
error);
g_strfreev (tokens);
return result;
}
static gboolean
undefine (const gchar *option_name,
const gchar *value,
gpointer data,
GError **error)
{
GskSlCompiler *compiler = data;
gsk_sl_compiler_remove_define (compiler, value);
return TRUE;
}
static gboolean
stage (const gchar *option_name,
const gchar *value,
gpointer data,
GError **error)
{
static const struct {
const char *name;
GskSlShaderStage stage;
} stage_names[] = {
{ "f", GSK_SL_SHADER_FRAGMENT },
{ "frag", GSK_SL_SHADER_FRAGMENT },
{ "fragment", GSK_SL_SHADER_FRAGMENT },
{ "v", GSK_SL_SHADER_VERTEX },
{ "vert", GSK_SL_SHADER_VERTEX },
{ "vertex", GSK_SL_SHADER_VERTEX }
};
GskSlCompiler *compiler = data;
GString *str;
gsize i;
for (i = 0; i < G_N_ELEMENTS (stage_names); i++)
{
if (g_ascii_strcasecmp (stage_names[i].name, value) == 0)
{
g_object_set_data (G_OBJECT (compiler), "shader-stage", GUINT_TO_POINTER (stage_names[i].stage));
return TRUE;
}
}
str = g_string_new ("");
for (i = 0; i < G_N_ELEMENTS (stage_names); i++)
{
if (i > 0)
g_string_append (str, ", ");
g_string_append (str, stage_names[i].name);
}
g_set_error (error, G_OPTION_ERROR, G_OPTION_ERROR_BAD_VALUE,
"Unknown value given for shader stage. Valid options are: %s",
str->str);
g_string_free (str, TRUE);
return FALSE;
}
int
main (int argc, char *argv[])
{
GOptionContext *ctx;
char **filenames = NULL;
char *output_file = NULL;
gboolean print = FALSE;
const GOptionEntry entries[] = {
{ "define", 'D', 0, G_OPTION_ARG_CALLBACK, define, "Add a preprocssor definition", "NAME[=VALUE]" },
{ "undef", 'U', 0, G_OPTION_ARG_CALLBACK, undefine, "Cancel previous preprocessor definition", "NAME" },
{ "print", 'p', 0, G_OPTION_ARG_NONE, &print, "Print instead of compiling", NULL },
{ "stage", 's', 0, G_OPTION_ARG_CALLBACK, stage, "Set the shader stage", "STAGE" },
{ "output", 'o', 0, G_OPTION_ARG_FILENAME, &output_file, "Output filename", "FILE" },
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, "List of input files", "FILE [FILE...]" },
{ NULL, }
};
GskSlCompiler *compiler;
GOptionGroup *group;
GError *error = NULL;
GOutputStream *output;
gboolean success = TRUE;
guint i;
g_set_prgname ("gtk-glsl");
gtk_init ();
compiler = gsk_sl_compiler_new ();
g_object_set_data (G_OBJECT (compiler), "shader-stage", GUINT_TO_POINTER (GSK_SL_SHADER_FRAGMENT));
ctx = g_option_context_new (NULL);
group = g_option_group_new (NULL, NULL, NULL, g_object_ref (compiler), g_object_unref);
g_option_group_add_entries (group, entries);
g_option_context_set_main_group (ctx, group);
if (!g_option_context_parse (ctx, &argc, &argv, &error))
{
g_printerr ("%s\n", error->message);
g_error_free (error);
exit (1);
}
if (filenames == NULL)
usage (ctx);
g_option_context_free (ctx);
if (output_file == NULL)
{
#ifdef G_IO_WIN32
HANDLE handle;
handle = GetStdHandle (STD_OUTPUT_HANDLE);
if (handle == NULL)
{
g_printerr ("No standard output. Use -o/--ouput to write to file\n");
exit (1);
}
output = g_win32_output_stream_new (handle, FALSE);
#else
output = g_unix_output_stream_new (STDOUT_FILENO, FALSE);
#endif
}
else
{
GFile *file = g_file_new_for_path (output_file);
output = G_OUTPUT_STREAM (g_file_replace (file,
NULL, FALSE,
G_FILE_CREATE_REPLACE_DESTINATION,
NULL,
&error));
g_object_unref (file);
if (output == NULL)
{
g_printerr ("Error creating output file: %s\n", error->message);
g_error_free (error);
exit (1);
}
}
for (i = 0; success && filenames[i] != NULL; i++)
{
if (print)
success = dump (compiler, output, filenames[i]);
else
success = compile (compiler, output, filenames[i]);
}
if (!g_output_stream_close (output, NULL, &error))
{
g_printerr ("%s\n", error->message);
g_error_free (error);
success = FALSE;
}
g_object_unref (output);
g_object_unref (compiler);
g_strfreev (filenames);
return success ? EXIT_SUCCESS : EXIT_FAILURE;
}

View File

@@ -60,6 +60,8 @@ gtk_inspector_init (void)
g_type_ensure (G_TYPE_LIST_STORE);
g_type_ensure (GSK_TYPE_PIXEL_SHADER);
g_type_ensure (GTK_TYPE_CELL_RENDERER_GRAPH);
g_type_ensure (GTK_TYPE_GRAPH_DATA);
g_type_ensure (GTK_TYPE_INSPECTOR_ACTIONS);

View File

@@ -1024,6 +1024,7 @@ gtk_tools = [
['gtk4-update-icon-cache', ['updateiconcache.c']],
['gtk4-encode-symbolic-svg', ['encodesymbolic.c']],
['gtk4-query-immodules', ['queryimmodules.c', 'gtkutils.c']],
['gtk4-glsl', ['glsl.c']],
]
if os_unix

View File

@@ -0,0 +1,8 @@
void
main ()
{
int x[10];
int y = x[10];
}

View File

@@ -0,0 +1,8 @@
void
main ()
{
float[2][3] x;
float[2] y;
bool b = x[1] == y;
}

View File

@@ -0,0 +1,8 @@
uniform Foo {
int x;
} x[2][3][4];
void main()
{
bool t = x[1] == x[0];
}

View File

@@ -0,0 +1,5 @@
void
main ()
{
break;
}

View File

@@ -0,0 +1,7 @@
void
main ()
{
int b;
int y = b ? 1 : 0;
}

View File

@@ -0,0 +1,6 @@
void
main ()
{
discard;
}

View File

@@ -0,0 +1,7 @@
void
main ()
{
int i;
++++i;
}

View File

@@ -0,0 +1,7 @@
void
main ()
{
int i;
i----;
}

View File

@@ -0,0 +1,8 @@
uniform Foo {
int x;
int x;
};
void main()
{
}

View File

@@ -0,0 +1,10 @@
void
foo (int x, int x)
{
}
void
main ()
{
foo (4, 2);
}

View File

@@ -0,0 +1,6 @@
in flat noperspective int i;
void
main ()
{
}

View File

@@ -0,0 +1,6 @@
#if defined
void
main ()
{
}

View File

@@ -0,0 +1,6 @@
#if defined (
void
main ()
{
}

View File

@@ -0,0 +1,6 @@
#if defined ()
void
main ()
{
}

View File

@@ -0,0 +1,7 @@
void
main ()
{
bool b;
int y = b ? 1 : true;
}

View File

@@ -0,0 +1,6 @@
const int x;
void
main ()
{
}

View File

@@ -0,0 +1,5 @@
void
main ()
{
const int x;
}

View File

@@ -0,0 +1,6 @@
in int i;
void
main ()
{
}

View File

@@ -0,0 +1,11 @@
float
foo ()
{
return vec3(0);
}
void
main ()
{
float f = foo();
}

View File

@@ -0,0 +1,11 @@
void
foo (int x)
{
int x;
}
void main()
{
foo (1);
}

View File

@@ -0,0 +1,5 @@
void main()
{
int x;
int x;
}

View File

@@ -0,0 +1,7 @@
void
main ()
{
bool b;
int y = b ? 1;
}

View File

@@ -0,0 +1,6 @@
#if 0
void
main ()
{
}

View File

@@ -0,0 +1,6 @@
#if 1
void
main ()
{
}

View File

@@ -0,0 +1,8 @@
void
main ()
{
int x[10];
int y = x[-3];
}

View File

@@ -0,0 +1,6 @@
in bool b;
void
main ()
{
}

View File

@@ -0,0 +1,6 @@
in sampler2D t;
void
main ()
{
}

View File

@@ -0,0 +1,6 @@
in struct {int x; int y; } s;
void
main ()
{
}

View File

@@ -0,0 +1,8 @@
#123
void
main ()
{
int x = 1;
}

View File

@@ -0,0 +1,9 @@
int x;
uniform Block {
int x;
};
void
main ()
{
}

View File

@@ -0,0 +1,7 @@
int x;
int x;
void
main ()
{
}

View File

@@ -0,0 +1,11 @@
float
foo ()
{
return;
}
void
main ()
{
float f = foo();
}

Some files were not shown because too many files have changed in this diff Show More