The `#![allow(dead_code)]` on the module was hiding dead code in the
child modules. I changed it to be conditional on actually having no
backends enabled. (Note that with #7349, there would actually be no
warnings and we could remove the `allow(dead_code)` entirely, but I
expect that state of affairs won’t necessarily persist.)
Place the `#[track_caller]` attribute on the `check` and
`validation_error` functions in the Naga `wgsl_errors` test module, so
that panics or assertion failures will point to the actual test,
not to the code in the utility function.
Change the match in the `naga::common::wgsl::TypeContext` trait's
default implementation of `write_type_inner` to be exhaustive, so that
it is more likely to be kept up to date when changes are made to the
IR.
Coincidentally, add support for `TypeInner::RayQuery`.
In `naga::back::wgsl`, move `WriterTypeContext` out of the way, and
coalesce `Writer`'s methods back into a single `impl` block.
This is just code motion; there should be no change in behavior.
Move the `TypeContext` trait from `naga::back::wgsl` into
`naga::common::wgsl`. Adjust imports and publicity markers as needed.
There should be no changes to behavior in this commit, only code
motion.
In `naga::back::wgsl`, introduce a new trait, `TypeContext`, which
provides all the context necessary to generate WGSL code for a type.
`Writer::write_type` and `write_type_inner` become default methods on
`TypeContext`. `Writer` replaces them with functions that simply
create a `TypeContext` from the `Writer` and forward the call.
For simplicity's sake, rather than trying to return errors for Naga IR
that we can't generate WGSL for, just panic. Validation should have
rejected any such values, and it is not practical to expect Naga
backends when given invalid modules: backends need to be free to
assume that handles are valid, that arenas are free of cycles, and so
on.
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.
When the user provides values for a module's overrides, rather than
replacing override-sized array types with ordinary array types (which
could require adjusting type handles throughout the module), instead
edit all overrides to have initializers that are fully-evaluated
constant expressions. Then, change all backends to handle
override-sized arrays by retrieving their overrides' values.
For arrays whose sizes are override expressions, not simple references
to a specific override's value, let front ends built array types that
refer to anonymous overrides whose initializers are the necessary
expression.
This means that all arrays whose sizes are override expressions are
references to some `Override`. Remove `naga::PendingArraySize`, and
let `ArraySize::Pending` hold a `Handle<Override>` in all cases.
Expand `tests/gpu-tests/shader/array_size_overrides.rs` to include the
test case that motivated this approach.
Simplify `naga::back::spv::LocalType` to have only one variant for
representing pointers, and use the SPIR-V type as the base type, so
that `LocalType` values are equal when the SPIR-V pointer types they
map to would be equal as well.
This avoids emitting multiple `OpTypePointer` instructions, which
SPIR-V would interpret as distinct types, for equivalent Naga IR
pointer types.
Change the `get_pointer_type_id` utility function accordingly, and
adjust its callers.
Change `LocalType::from_inner` into `Writer::localtype_from_inner`, so
that it can call `Writer` methods to build base types. Adjust users.
Introduce a new helper function on `back::spv::Writer` and
`BlockContext` that looks up the SPIR-V type id corresponding to a
Naga IR `Handle<Type>`. Use it where appropriate.
Rename utility functions on `back::spv::Writer` for looking up SPIR-V
type ids for common types to better match WGSL precedent. Use lexemes
like `u32` and `vec3u` (the official WGSL abbreviation), rather than
`float` and `uint2` (which I think are GLSL?).
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
Move `back::wgsl::address_space_str` to `common::wgsl`, so that the
front end can use it too. This commit is code motion and `use`
adjustment only; there should be no change in behavior.
Replace `naga::back::wgsl::writer::image_dimension_str` with a
`ToWgsl` implementation for `ImageDimension` in `common::wgsl`. Use
this where needed in the WGSL backend.
Replace `naga::back::wgsl::writer::scalar_kind_str` with a `TryToWgsl`
implementation for `Scalar` in `common::wgsl`. Use this where needed
in the WGSL backend.
Move `back::vector_size_str` to `common`, so that front ends can use
it too. This commit is code motion and `use` adjustment only, there
should be no change in behavior.
Define new traits in `common::wgsl`, `ToWgsl` and `TryToWgsl`, for
getting the WGSL representation of some Naga IR types as `&'static
str` values:
- `MathFunction`
- `BuiltIn`
- `Interpolation`
- `Sampling`
- `StorageFormat`
Use these functions in the WGSL backend, taking advantage of
`TryToWgsl` to consolidate error reporting.
Introduce a new variant of `naga::back::wgsl::Error`, `Unsupported`,
and let it subsume `UnsupportedMathFunction` and various uses of
`Custom`.
Introduce a helper function, `Error::unsupported`, for building these
errors.
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.