The grammar now accepts type casts, like "(int)x", but that
has to be disambiguated from "(a + b)", needed deeper lookahead
and backing up than what existed so far.
This checkin implements about half of the HLSL intrinsics for a subset of their
entire type support (but a useful subset). The uncommented lines in
TBuiltInParseablesHlsl::identifyBuiltIns shows which are connected.
The test result should only give one error about linking
ES and non-ES shading language compilation units:
- empty.frag: No version info, interpreted as 100, ES
- empty2.frag: No version info, interpreted as 100, ES
- empty3.frag: Version declared as 110, non-ES
Previously, because the new intermediate is always created
without version/profile information, there would be two
linker errors:
1.) When merging the new intermediate with empty.frag
2.) When merging (new intermediate + empty.frag + empty2.frag) with empty3.frag
Now, there is only one error; as the error with merging the
new intermediate with empty.frag has been removed.
Note: This required adding a new test mode to see the AST for vulkan tests.
This also required reworking some deeper parts of type creation, regarding
when storage qualification and constness is deduced bottom-up or dictated
top-down.
GLSL interpolation qualifiers and auxiliary storage qualifiers are not
mutually exclusive. So when they are translated to SPIR-V decorations, two
independent utility methods should be employed to do this job.
Spec for decorating the OpVariable:
"The remaining variables listed by OpEntryPoint with the Input or Output storage class form the user-defined variable interface. These variables must be identified with a Location decoration"
Spec for decorating struct type:
"The layout of a structure type used as an Input or Output depends on whether it is also a Block (i.e. has a Block decoration).
If it is a not a Block, then the structure type must have a Location decoration"
These capabalities were added on declaration of the members, but
that is considered too aggressive, as those members are automatically
declared in some shaders that don't use them. Now, actual access
is needed to make the capabalities be declared.
This change causes ES shaders to precision qualifiers for build-in functions as defined in ESSL spec. It especially mattersfor functions that are defined as highp or taking a highp.
Fixes vulkanCTS dEQP-VK.glsl.builtin.function.integer.bitfieldreverse.*, where bitfieldReverse() retval was wrongly marked as RelaxedPrecision.
Note: floatBitsToInt/floatBitsToUInt precision is also broken, but in different way - so it is not addressed here.
Reimplement the whole workflow to make that: precise'ness of struct
members won't spread to other non-precise members of the same struct
instance.
Approach:
1. Build the map from symbols to their defining nodes. And for each
object node (StructIndex, DirectIndex, Symbol nodes, etc), generates an
accesschain path. Different AST nodes that indicating a same object
should have the same accesschain path.
2. Along the building phase in step 1, collect the initial set of
'precise' (AST qualifier: 'noContraction') objects' accesschain paths.
3. Start with the initial set of 'precise' accesschain paths, use it as
a worklist, do as the following steps until the worklist is empty:
1) Pop an accesschain path from worklist.
2) Get the symbol part from the accesschain path.
3) Find the defining nodes of that symbol.
4) For each defining node, check whether it is defining a 'precise'
object, or its assignee has nested 'precise' object. Get the
incremental path from assignee to its nested 'precise' object (if
any).
5) Traverse the right side of the defining node, obtain the
accesschain paths of the corresponding involved 'precise' objects.
Update the worklist with those new objects' accesschain paths.
Label involved operations with 'noContraction'.
In each step, whenever we find the parent object of an nested object is
'precise' (has 'noContraction' qualifier), we let the nested object
inherit the 'precise'ness from its parent object.
This fixes some vulkanCTS tests that use struct arrays as a member of in/out interface blocks.
From Vulkan spec:
"If it is a not a Block, then the structure type must have a Location decoration. Its members are assigned consecutive locations in their declaration order, with the first member assigned to the location specified for the structure type. >>>>> The members, and their nested types, must not themselves have Location decorations <<<<"
From SPIR-V spec:
"When applied to structure-type members, the Decorations Noperspective, Flat, Patch, Centroid, and Sample can only be applied to the top-level members of the structure type. (Nested objects' types cannot be structures whose members are decorated with these decorations.)"