Changes:
(1) Allow clip/cull builtins as both input and output in the same shader stage. Previously,
not enough data was tracked to handle this.
(2) Handle the extra array dimension in GS inputs. The synthesized external variable can
now be created with the extra array dimension if needed, and the form conversion code is
able to handle it as well.
For example, both of these GS inputs would result in the same synthesized external type:
triangle in float4 clip[3] : SV_ClipDistance
triangle in float2 clip[3][2] : SV_ClipDistance
In the second case, the inner array dimension packs with the 2-vector of floats into an array[4],
which there is an array[3] of due to the triangle geometry.
HLSL allows a range of types for clip and cull distances. There are
three dimensions, including arrayness, vectorness, and semantic ID.
SPIR-V requires clip and cull distance be a single array of floats in
all cases.
This code provides input side conversion between the SPIR-V form and
the HLSL form. (Output conversion was added in PR #947 and #997).
This PR extends HlslParseContext::assignClipCullDistance to cope with
the input side conversion. Not as much changed as appears: there was
also a lot of renaming to reflect the fact that the code now handles
either direction.
Currently, non-{frag,vert} stages are not handled, and are explicitly
rejected.
Fixes#1026.
Some languages allow a restricted set of user structure types returned from texture sampling
operations. Restrictions include the total vector size of all components may not exceed 4,
and the basic types of all members must be identical.
This adds underpinnings for that ability. Because storing a whole TType or even a simple
TTypeList in the TSampler would be expensive, the structure definition is held in a
table outside the TType. The TSampler contains a small bitfield index, currently 4 bits
to support up to 15 separate texture template structure types, but that can be adjusted
up or down. Vector returns are handled as before.
There are abstraction methods accepting and returning a TType (such as may have been parsed
from a grammar). The new methods will accept a texture template type and set the
sampler to the structure if possible, checking a range of error conditions such as whether
the total structure vector components exceed 4, or whether their basic types differe, or
whether the struct contains non-vector-or-scalar members. Another query returns the
appropriate TType for the sampler.
High level summary of design:
In the TSampler, this holds an index into the texture structure return type table:
unsigned int structReturnIndex : structReturnIndexBits;
These are the methods to set or get the return type from the TSampler. They work for vector or structure returns, and potentially could be expanded to handle other things (small arrays?) if ever needed.
bool setTextureReturnType(TSampler& sampler, const TType& retType, const TSourceLoc& loc);
void getTextureReturnType(const TSampler& sampler, const TType& retType, const TSourceLoc& loc) const;
The ``convertReturn`` lambda in ``HlslParseContext::decomposeSampleMethods`` is greatly expanded to know how to copy a vec4 sample return to whatever the structure type should be. This is a little awkward since it involves introducing a comma expression to return the proper aggregate value after a set of memberwise copies.
This allows removal of isPerVertexBuiltIn(). It also leads to
removal of addInterstageIoToLinkage(), which is no longer needed.
Includes related name improvements.
Most of this was obsoleted by entry-point wrapping.
Some other is just unnecessary.
Also, includes some spelling/name improvements.
This is to help lay ground work for flattening user I/O.
Two non-functional changes:
1. Remove flattenLevel, which is unneeded since at or around d1be7545c6.
2. Fix build warining about unused variable in executeInitializer.
HLSL allows several variables to be declared. There are packing rules involved:
e.g, a float3 and a float1 can be packed into a single array[4], while for a
float3 and another float3, the second one will skip the third array entry to
avoid straddling
This is implements that ability. Because there can be multiple variables involved,
and the final output array will often be a different type altogether (to fuse
the values into a single destination), a new variable is synthesized, unlike the prior
clip/cull support which used the declared variable. The new variable name is
taken from one of the declared ones, so the old tests are unchanged.
Several new tests are added to test various packing scenarios.
Only two semantic IDs are supported: 0, and 1, per HLSL rules. This is
encapsulated in
static const int maxClipCullRegs = 2;
and the algorithm (probably :) ) generalizes to larger values, although there
are a few issues around how HLSL would pack (e.g, would 4 scalars be packed into
a single HLSL float4 out reg? Probably, and this algorithm assumes so).
Lays the groundwork for fixing issue #954.
Partial flattenings were previously tracked through a stack of active subsets
in the parse context, but full functionality needs AST nodes to represent
this across time, removing the need for parsecontext tracking.
In HLSL, there are three (TODO: ??) dimensions of clip and cull
distance values:
* The semantic's value N, ala SV_ClipDistanceN.
* The array demension, if the value is an array.
* The vector element, if the value is a vector or array of vectors.
In SPIR-V, clip and cull distance are arrays of scalar floats, always.
This PR currently ignores the semantic N axis, and handles the other
two axes by sequentially copying each vector element of each array member
into sequential floats in the output array.
Fixes: #946
For "s.m = t", a sampler member assigned a sampler, make t an alias
for s.m, and when s.m is flattened, it will flatten to the alias t.
Normally, assignments to samplers are disallowed.
This modifies function parameter passing to pass the counter
buffer associated with a struct buffer to a function as a
hidden parameter. Similarly function declarations will have
hidden parameters added to accept the associated counter buffers.
There is a limitation: if a SB type may or may not have an associated
counter, passing it as a function parameter will assume that it does, and
the counter will appear in the linkage whether or not there is a counter
method used on the object.
Marking as WIP since it might deserve discussion or at least explicit consideration.
During type sanitization, the TQualifier's TBuiltInVariable type is lost. However,
sometimes it's needed downstream. There were already two methods in use to track
it through to places it was needed: one in the TParameter, and one in a map in the
HlslParseContext used for structured buffers.
The latter was going to be insufficient when SB types with counters are passed to
user functions, and it's proving awkward to track the data to where it's needed.
This PR holds a proposal: track the original declared builtin type in the TType,
so it's trivially available where needed.
This lets the other two mechanisms be removed (and they are in this PR). There's a
side benefit of not losing certain types of information before the reflection interface.
This PR is only that proposal, so it changes no test results. If it's acceptable,
I'll use it for the last piece of SB counter functionality.
This implements mytex.mips[mip][coord] for texture types. There is
some error testing, but not comprehensive. The constructs can be
nested, e.g in this case the inner .mips is parsed before the completion
of the outer [][] operator.
tx.mips[tx.mips[a][b].x][c]
This adds infrastructure suitable for any front end to create SPIR-V loop
control flags. The only current front end doing so is HLSL.
[unroll] turns into spv::LoopControlUnrollMask
[loop] turns into spv::LoopControlDontUnrollMask
no specification means spv::LoopControlMaskNone
Multisample textures support a GetSamplePosition() method intended to query
positions given a sample index. This cannot be truly implemented in SPIR-V,
but #753 requested returning standard positions for the 1..16 cases, which
this PR adds. Anything besides that returns (0,0). If the standard positions
are not used, this will be wrong.
This should be revisited when there is a real query available.
Some texture and SB operations can take non-integer indexes, which should be
cast to integers before use if they are not already. This adds makeIntegerIndex()
for the purpose. Int types are left alone.
(This was done before for operator[], but needs to apply to some other things
too, hence its extraction into common function now)
This is WIP, heavy on the IP part. There's not yet enough to use in real workloads.
Currently present:
* Creation of separate counter buffers for structured buffer types needing them.
* IncrementCounter / DecrementCounter methods
* Postprocess to remove unused counter buffers from linkage
* Associated counter buffers are given @count suffix (invalid as a user identifier)
Not yet present:
* reflection queries to obtain bindings for counter buffers
* Append/Consume buffers
* Ability to use SB references passed as fn parameters
HLSL requires vec2 tessellation coordinate declarations in some cases
(e.g, isoline topology), where SPIR-V requires the TessCoord qualified
builtin to be a vec3 in all cases. This alters the IO form of the
variable to be a vec3, which will be copied to the shader's declared
type if needed. This is not a validation; the shader type must be correct.
Improves foundation for adding scalar casts.
Makes handle/make names more sane, better commented, uses more
precise subclass typing, and removes mutual recursion between
converting initializer lists and making constructors.
Previously, patch constant functions only accepted OutputPatch. This
adds InputPatch support, via a pseudo-builtin variable type, so that
the patch can be tracked clear through from the qualifier.
The prior implementation of GS did not work with the new EP wrapping architecture.
This fixes it: the Append() method now looks up the actual output rather
than the internal sanitized temporary type, and writes to that.
The SPIR-V generator had assumed tessellation modes such as
primitive type and vertex order would only appear in tess eval
(domain) shaders. SPIR-V allows either, and HLSL allows and
possibly requires them to be in the hull shader.
This change:
1. Passes them through for either tessellation stage, and,
2. Does not set up defaults in the domain stage for HLSl compilation,
to avoid conflicting definitions.
HLSL HS outputs a per ctrl point value, and the DS reads an array
of that type. (It also has a per patch frequency). The per-ctrl-pt
frequency is arrayed on just one side, as opposed to SPIR-V which
is arrayed on both. To match semantics, the compiler creates an
array behind the scenes and indexes it by invocation ID, assigning
the HS return value to it.
SPIR-V requires that tessellation factor arrays be size 4 (outer) or 2 (inner).
HLSL allows other sizes such as 3, or even scalars. This commit converts
between them by forcing the IO types to be the SPIR-V size, and allowing
copies between the internal and IO types to handle these cases.
It would have been possible for globally scoped user functions to collide
with builtin method names. This adds a prefix to avoid polluting the
namespace.
Ideally this would be an invalid character to use in user identifiers, but
as that requires changing the scanner, for the moment it's an unlikely yet
valid prefix.
Also use this to move deferred member-function-body parsing to a better
place.
This should also be well poised for implementing the 'namespace' keyword.