Handling native array types is not really feasible since we need to fuse
the variable declaration with the type declaration.
This is feasible in something like variable_decl, but for plain SSA
pointers, this breaks down.
If we have emitted block IO lowering at the end of vertex shader, we
will end up using the wrong name. Forcing a v_ prefix does not solve any
actual problems since the intentifier already has to be valid.
It is possible in SPIR-V to declare multiple specialization constants
with the same constant ID. The most common cause of this in GLSL is
defining a spec constant, then declaring the workgroup size to use that
spec constant by its ID. But, MSL forbids defining multiple function
constants with the same function constant ID. So, we must only emit one
definition of the actual function constant (with the
`[[function_constant(id)]]` attribute); but we can point the other
variables at this one definition.
Fixes three tests in the Vulkan CTS under
`dEQP-VK.compute.basic.max_local_size_*`.
Some Metal devices have a bug with depth array textures using comparison
with explicit LoD, where the LoD given will be biased by some amount.
For these devices, we can use a gradient instead, which does not exhibit
this problem. As with the fragment demote workaround, this is only
expected to be needed until the bug is fixed in Metal.
Vulkan specifies round-to-nearest-even mode to round array coordinates.
But we were using `round()`, which is round-to-nearest-away-from-zero.
Instead, use `rint()`, which is specified to perform nearest-even
rounding in MSL.
- Add CompilerMSL::Options::argument_buffers_tier as an enumeration to
allow calling app to specify platform argument buffer tier capabilities.
- Support iOS writable images in Tier2 argument buffers when specified.
Tier capabilities based on recommendations from Apple engineering.
Undef values may be of struct type and may be used in constants.
Therefore, they must be interleaved with constants and types.
Fixes the rest of the Vulkan CTS test
`dEQP-VK.spirv_assembly.instruction.compute.opundef.undefined_spec_constant_composite`.
(Please excuse the churn in the reference output; it's an inevitable
result of this change.)
Some Metal devices have a bug where storage resources can still be
written to even if the fragment is discarded. This is obviously a bug in
Metal, but bothering Apple to fix it will only fix it for newer
versions; therefore, a workaround is needed for older versions. I have
made this an option so that, in case the bug is ever fixed, the
workaround can be disabled.
This workaround is simple: if a fragment shader may discard its fragment
and writes to a storage resource, a variable representing the
`HelperInvocation` built-in is created and passed to all functions. The
flag is checked on all resource writes; writes do not occur when
`HelperInvocation` is `true`. This relies on the earlier workaround to
update `HelperInvocation` when the fragment is discarded.
Fixes at least 3 failures in the CTS.
It is possible to pass unsigned integers to `OpSMulExtended`. In that
case, we want to do a signed multiply with sign extension, so make sure
the operands are forced to be interpreted as signed.
This was an oversight on my part when I added these instructions.
Fixes the CTS test
`dEQP-VK.spirv_assembly.instruction.compute.signed_op.uint_smulextended`.
Some Metal devices have a bug where `simd_is_helper_thread()` won't
return true after a fragment has been discarded. We can work around this
by manually setting `gl_HelperInvocation` upon discarding a fragment.
This is fairly unintrusive, so it is enabled by default. I've made it an
option so that, when the bug is fixed, we can disable it.
MSL inherits the behavior of C where arithmetic on small types are
implicitly converted to int. SPIR-V does not have this behavior, so make
sure that arithmetic results are handled correctly.
restrict was supported, but it broke in MSL 3.0. __restrict works on all
versions, so opt for that instead.
Also check for RestrictPointer decoration and refactor to_restrict() to
not take optional parameter to make it more obvious when implied space
character is added.
In tessellation shaders, we call
`add_plain_member_variable_to_interface_block()` on composite types,
since we are using buffers for I/O and can use nested structs/arrays
here. In those cases, we need to make sure the next location is
incremented by the total amount consumed by the entire composite.
Fixes six more tests in the CTS, under
`dEQP-VK.tessellation.user_defined_io.per_vertex_block.*`.
Flattening doesn't play well with dynamic indices. In this case, it's
better to leave it as an array of structs.
(I wanted to do this for named blocks generally. Trouble is, the builtin
`gl_out` block is *also* a named block...)
Fixes six more CTS tests, under
`dEQP-VK.tessellation.user_defined_io.per_patch_block_array.*`.
Using vertex-style stage input is complex, and it doesn't support
nesting of structures or arrays. By using raw buffer input instead, we
get this support "for free," and everything becomes much simpler.
Arguably, this is the way I should've done this in the first place.
Eventually, I'd like to make this the default, and then remove the
option altogether. (And I still need to do that with
`multi_patch_workgroup`...)
Should help fix 66 tests in the Vulkan CTS, under the following trees:
- `dEQP-VK.pipeline.*.interface_matching.*`
- `dEQP-VK.tessellation.user_defined_io.*`
- `dEQP-VK.clipping.user_defined.*`
When storing to local variable (eg. OpCopyLogical), the
default device address space used during casts is illegal.
Determine correct address space based on variable type.
Overall just broken in some cases. And lack of fetch_* variants for a
few opcodes is also broken. When officially supported in some future MSL
version, this can be lifted.
It is allowed to redeclare descriptors with different types in Vulkan.
MSL in general does not allow this, but for raw buffers, we can cast the
reference type at the very least.
For typed resources we are kinda hosed. Without descriptor indexing's
PARTIALLY_BOUND_BIT, descriptors must be valid if they are statically
accessed, so it would not be valid to access differently typed aliases
unless that flag is used. There might be a way to reinterpret cast
descriptors, but that seems very sketchy.
Implements support for:
- Single discrete descriptor
- Single argument buffer descriptor
- Array of argument buffer descriptors
Other cases are unimplemented for now since they are extremely painful
to unroll.