Makes the dual source implementation in wgpu WebGPU spec compliant.
Furthermore, makes the dual source blending extension available when targeting WebGPU.
This allows abstract-typed expressions to be used for some or all of
the switch selector and case selectors. If these are all not
convertible to the same concrete scalar integer type we return an
error. If all the selector expressions are abstract then they are
concretized to i32.
The note previously provided by the relevant error message, suggesting
adding or removing the `u` suffix from case values, has been
removed. While useful for simple literal values, it was comically
incorrect for more complex case expressions. The error message should
still be useful enough to allow the user to easily identify the
problem.
Instead allow the const to be converted each time it is const
evaluated as part of another expression. This allows an abstract const
to be used as a different type depending on the context.
As a result, abstract types may now find their way in to the IR, which
we don't want. This occurs because the compact pass treats named
expressions as used, mostly so that our snapshot tests are more
useful, and therefore does not remove them. To prevent this, we avoid
adding abstract-typed local consts to the named expressions list. This
will have no functional effect on any shaders produced by the
backends, but some unused local const declarations will no longer be
present.
Naga currently trips up on shaders containing a bitshift where the
left operand is an AbstractInt and the right operand is *not* a const
expression. This is due to the fact that resulting type of
`AbstractInt << u32` is abstract, and we are unable to evaluate it
away during const evaluation. This results in abstract-typed
expressions in our IR, which causes various issues.
For other binary operations, the type of the left and right operands
would be related, therefore the presence of a concrete right operand
would tell us which type to convert the left operand to. But for shift
operations the right operand's scalar type is always a u32, and does
not influence the left operand's type.
Luckily the WGSL spec[1] tells us how to avoid this problem:
6.1.3. Overload Resolution
2. Eliminate any candidate where one of its subexpressions resolves
to an abstract type after feasible automatic conversions, but
another of the candidate’s subexpressions is not a
const-expression.
This, for example, specifies we eliminate the `AbstractInt << u32:
AbstractInt` overload candidate, leaving `i32 << u32: i32` as the
remaining candidate with the lowest conversion rank. The equivalent
also applies for right-bitshifts, and for `vecN<AbstractInt>`
operands.
[1] https://www.w3.org/TR/WGSL/#overload-resolution-section
When an entry point's return type is anonymous, have
`naga::proc::Namer` assign it a name based on its shader stage.
Remove bespoke logic for this from the WGSL backend.
Fixes#7263.
Parsing currently fails for shaders that attempt to dynamically index
an abstract-typed array (or vector, etc), like so:
var x = array(1, 2, 3)[i];
This is caused by attempting to concretize the Expression::Access
expression, which the ConstantEvaluator fails to do so due to the
presence of a non-constant expression.
To solve this, this patch concretizes the base type *prior* to
indexing it (for non-constant indices), meaning the constant evaluator
never sees any non-constant expressions. This matches the WGSL
specification:
When an abstract array value e is indexed by an expression that is
not a const-expression, then the array is concretized before the
index is applied.
(Similar applies for both vectors and matrices, too.)
This may be somewhat non-optimal in that if there are multiple
accesses of the same abstract expression, we will produce duplicated
concretized versions of that expression. This seems unlikely to be a
major issue in practice, and we can always improve this if and when we
encounter a real issue caused by it.
When spilling arrays and matrices so that we can access them with an
index computed at runtime, if we need to spill the same expression again,
don't wipe out our record of the temporary variable we used the first
time. Just re-use it.
Fixes#7048.
Adds infrastructure to the MSL backend for emitting helper functions,
based upon the existing HLSL backend equivalent. Emit helper functions
for MathFunction::Abs and UnaryOperator::Negate with a signed integer
scalar or vector operand. And for BinaryOperator::Divide and
BinaryOperator::Modulo with signed or unsigned integer scalar or
vector operands.
Abs and Negate are written to avoid signed integer overflow when the
operand equals INT_MIN. This is achieved by bitcasting the value to
unsigned and using the negation operator, then bitcasting the result
back to signed.
Division and Modulo avoid undefined bevaviour for INT_MIN / -1 and
divide-by-zero by using 1 for the divisor instead. Additionally we
avoid undefined behaviour when using the modulo operator when either
or both operands are negative by using the equation from the WGSL
spec, using division, subtraction and multiplication, rather than
MSL's modulus operator.
Lastly, as the usage of the wrapper function for unary integer
negation makes the negation_avoids_prefix_decrement() testcase less
interesting, we extend it to additionally test negating floats.
When converting the underlying scalar type of an array during const
evaluation, we currently use the resulting base type's size as the array
stride for the resulting type. For certain types, this may not match the
required alignment and will therefore result in a validation error.
For example, `array<vec3<f32>, N>` should have a stride of 16. But if
declared with an abstract initializer, eg `array(vec3(0.0))` we will
incorrectly determine the stride to be 12.
To solve this, we use the proc::Layouter struct to determine the
required array stride during const evaluation. To avoid repeating
layouting work, we reuse the Lowerer's layouter, passing it through the
various *Contexts through to the ConstantEvaluator.
When lowering a return statement, call expression_for_abstract()
rather than expression() to avoid concretizing the return value. Then,
if the function has a return type, call try_automatic_conversions() to
attempt to convert our return value to the correct type.
This has the unfortunate side effect that some errors that would have
been caught by the validator are instead encountered as conversion
errors by the parser. This may result in a slightly less descriptive
error message in some cases. (See the change to the invalid_functions()
test, for example.)
* feat: Add 32-bit floating-point atomics
* Current supported platforms: Metal
* Platforms to support in the future: Vulkan
Related issues or PRs:
* gfx-rs/wgpu#1020
* Add changelog
* Edit changelog
* feat: Add 32-bit float atomics support for Vulkan (SPIR-V shaders)
* atomicSub for f32 in the previous commits is removed.
* Update test
* chore: doc type link
* refactor: Revise float atomics on msl and spv
* Make branches tidy
* Also revise old codes
* Ensure the implementations are supported by Metal and Vulkan backends
* refactor: Renaming flt32 atomics to float32 atomics
* chore: Add link to Vulkan feature
* fix: cargo fmt
* chore: hack comment
* Revert changelog
* Fix: Cargo advisory
* Update wgpu-hal/src/metal/adapter.rs
Co-authored-by: Teodor Tanasoaia <28601907+teoxoy@users.noreply.github.com>
* Update naga/src/lib.rs
Co-authored-by: Teodor Tanasoaia <28601907+teoxoy@users.noreply.github.com>
* Adjust feature flag position
---------
Co-authored-by: Teodor Tanasoaia <28601907+teoxoy@users.noreply.github.com>
The WGSL spec only allows named component expressions when the base
type is a vector or a structure, so this patch removes support for it
for matrices. Additionally tests which used this for matrices have
been updated to use indexing expressions instead, and a test has been
added to ensure a named component expression on a matrix results in an
error.
Handle SPIR-V input that performs atomic operations on structs that
have more than one field. Track which fields of which struct types are
used by atomic operations on which global variables, and then give
those global variables new types in which exactly those fields have
had their `Scalar` leaf types changed to `Atomic`.
Add snapshot tests.
Co-authored-by: Jim Blandy <jimb@red-bean.com>
When lowering arguments for a user-defined function call, avoid
concretizing the argument types. Instead make use of the existing
`try_automatic_conversions()` machinery to attempt to convert each
argument to the type expected by the function. This is straightforward
as user-defined functions only have a single overload.
This additionally changes an argument type in the test
parse_pointers() from `ptr<private>` to `ptr<function>`. The former is
invalid code which is indeed caught by the validator, but the test
only asserts that parsing succeeds, not validation. With this patch,
this error is now caught during parsing which caused the test to fail.
Add support for parsing and executing OpAtomicCompareExchange in the SPIR-V frontend.
This concludes the work to support atomics in the SPIR-V frontend,
excluding test clean-up.
Fixes#6296.
Fixes#6590.
Connections:
- [naga spv-in] Support for OpAtomicCompareExchange #6296
- [spv-in] Atomics support #4489
Co-authored-by: Jim Blandy <jimb@red-bean.com>