Commit Graph

179 Commits

Author SHA1 Message Date
Connor Fitzgerald
5ac906645b Move missing snapshots 2025-03-18 10:26:31 -07:00
Andreas Reich
fedc80eb80 [wgsl-in, wgsl-out, glsl-in] WebGPU compliant dual source blending feature (#7146)
Makes the dual source implementation in wgpu WebGPU spec compliant.
Furthermore, makes the dual source blending extension available when targeting WebGPU.
2025-03-08 21:07:37 +01:00
Samson
424fde1622 [naga] Support local const in ImageSample.offset (#7213)
* [naga] Support local const in ImageSample.offset

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>

* Update test expect

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>

* Update test

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>

* Update test expect

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>

* Remove docs about ImageSample.offset refering to global expr

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>

---------

Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
2025-03-07 19:56:08 +01:00
Jamie Nicol
6a61e62f55 [naga wgsl-in] Handle automatic type conversions for switch selector and case expressions (#7250)
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.
2025-03-07 03:50:36 +00:00
Jim Blandy
1b09a44af5 [naga spv-out] Avoid duplicating SPIR-V OpTypePointer instructions.
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.
2025-03-06 09:58:25 -08:00
Jamie Nicol
7df6e477cf [naga wgsl-in] Do not eagerly concretize local const declarations of abstract types
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.
2025-03-05 20:39:48 -08:00
Jamie Nicol
9853f5988d [naga wgsl-in] Concretize LHS of bitshift operations if RHS is not a const-expression (#7270)
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
2025-03-05 20:30:12 -05:00
Jim Blandy
f59b034153 [naga] Centralize naming of anonymous entry point return types.
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.
2025-03-04 17:46:30 -08:00
Vecvec
5b3266db23 Support getting hit vertex positions (#7183) 2025-03-04 20:06:44 +01:00
Jamie Nicol
7b54f9dfd2 [naga wgsl-in] Concretize base type prior to non-constant indexed access (#7260)
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.
2025-03-03 09:33:08 -05:00
Devon
d6ca412732 Add textureBarrier (#7173) 2025-02-27 20:27:15 +01:00
Jim Blandy
a285ad13f0 [naga spv-out] Don't generate multiple temporaries for spill values. (#7239)
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.
2025-02-27 18:34:52 +01:00
Jamie Nicol
b7d1f4c6cf [naga spv-out] Ensure loops generated by SPIRV backend are bounded (#7080)
If it is undefined behaviour for loops to be infinite, then, when
encountering an infinite loop, downstream compilers are able to make
certain optimizations that may be unsafe. For example, omitting bounds
checks. To prevent this, we must ensure that any loops emitted by our
backends are provably bounded. We already do this for both the MSL and
HLSL backends. This patch makes us do so for SPIRV as well.

The construct used is the same as for HLSL and MSL backends: use a
vec2<u32> to emulate a 64-bit counter, which is incremented every
iteration and breaks after 2^64 iterations.

While the implementation is fairly verbose for the SPIRV backend, the
logic is simple enough. The one point of note is that SPIRV requires
`OpVariable` instructions with a `Function` storage class to be
located at the start of the first block of the function. We therefore
remember the IDs generated for each loop counter variable in a
function whilst generating the function body's code. The instructions
to declare these variables are then emitted in `Function::to_words()`
prior to emitting the function's body.

As this may negatively impact shader performance, this workaround can
be disabled using the same mechanism as for other backends: eg calling
Device::create_shader_module_trusted() and setting the
ShaderRuntimeChecks::force_loop_bounding flag to false.
2025-02-25 15:23:44 +01:00
Jamie Nicol
9f949459f7 [naga wgsl-in] Add additional test cases regarding abstract-typed global consts 2025-02-25 09:25:25 +00:00
Jamie Nicol
dd2d53814d [naga wgsl-in] Do not eagerly concretize global const declarations of abstract types
Instead allow the const to be converted and 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.

A consequence of this is that abstract types may now find their way to
the validation stage, which we don't want. We therefore additionally
now ensure that the compact pass removes global constants of abstract
types. This will have no *functional* effect on shaders generated by
the backends, as the expressions belonging to the abstract consts in
the IR will not actually be used, as any usage in the input shader
will have been const-evaluated away. Certain unused const declarations
will now be removed, however, as can be seen by the effect on the
snapshot outputs.
2025-02-25 09:25:25 +00:00
Kent Slaney
6be5558865 [naga] allow trailing commas in template lists (#7142)
Co-authored-by: Erich Gubler <erichdongubler@gmail.com>
2025-02-25 03:02:55 +00:00
Alexandre Mommers
92a1702c3c [naga wgsl-in] Add support for unsigned types when calling textureLoad with the level parameter. (#7058) 2025-02-24 21:13:06 +00:00
Samson
2f255edc60 [naga] Use const ctx instead of global ctx for type resolution (#6935)
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
2025-02-24 16:24:37 +01:00
Connor Fitzgerald
473dd2fdd9 Refactor Snapshots to Be Fully Configuration Based (#7153)
Co-authored-by: Erich Gubler <erichdongubler@gmail.com>
2025-02-21 18:22:54 -05:00
Jim Blandy
5dad2c4cd4 [naga] Apply module compaction to GLSL tests. (#7186) 2025-02-19 20:59:06 -05:00
Connor Fitzgerald
e590555a8c test: use spirv-as instead of pre-assembled SPIR-V (#7157) 2025-02-17 14:48:09 -05:00
Jamie Nicol
d625d083c3 [naga wgsl-in] Implement any() and all() during const evaluation (#7166) 2025-02-17 14:13:49 -05:00
Jamie Nicol
6cf4b710b8 [naga spv-out] Avoid undefined behaviour for integer division and modulo
Integer division or modulo is undefined behaviour in SPIR-V when the
divisor is zero, or when the dividend is the most negative number
representable by the result type and the divisor is negative one.

This patch makes us avoid this undefined behaviour and instead ensures
we adhere to the WGSL spec in these cases: for divisions the
expression evaluates to the value of the dividend, and for modulos the
expression evaluates to zero.

Similarily to how we handle these cases for the MSL and HLSL backends,
prior to emitting each function we emit code for any helper functions
required by that function's expressions. In this case that is helper
functions for integer division and modulo. Then, when emitting the
actual function's body, if we encounter an expression which needs
wrapped we instead emit a function call to the helper.
2025-02-14 15:17:40 -08:00
Jamie Nicol
b6186ba332 [naga hlsl-out] Avoid undefined behaviour for integer division, modulo, negation, and abs
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, using the negation operator, then bitcasting the result back
to signed. As HLSL's bitcast functions asint() and asuint() only work
for 32-bit types, we only use this workaround in such cases.

Division and Modulo avoid undefined behaviour 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 on operands
of mixed signedness by using the equation from the WGSL spec, using
division, subtraction and multiplication, rather than HLSL's modulus
operator.
2025-02-14 15:17:40 -08:00
Jamie Nicol
88f6e9b8f8 [naga hlsl-out] Avoid undefined behaviour for signed integer addition, subtraction, and multiplication
Though not explicitly specified one way or the other, we have been
informed by DirectX engineers that signed integer overflow may be
undefined behaviour in some cases. To avoid this, we therefore bitcast
signed operands to unsigned prior to performing addition, subtraction,
or multiplication, then bitcast the result back to signed. As signed
types are represented as two's complement, this gives the correct
result whilst avoid any potential undefined behaviour.

Unfortunately HLSL's bitcast functions asint() and asuint() only work
for the 32-bit int and uint types. We therefore only apply this
workaround for 32-bit signed arithmetic. Support for other bit widths
could be added in the future, but extra care must be taken when
converting from unsigned to signed to avoid undefined or
implemented-defined behaviour.
2025-02-14 15:17:40 -08:00
Jamie Nicol
30363ef493 [naga hlsl-out] Wrap int literals in constructor-style cast
There is no literal suffix in HLSL for the integer type. We can,
however, wrap integer literals in a constructor style cast. This
avoids ambiguity when passing literals to overloaded functions, which
we'll make use of in the subsequent patch in this PR.
2025-02-14 15:17:40 -08:00
Jamie Nicol
8807c83363 [naga msl-out] Avoid undefined behaviour for integer division, modulo, negation, and abs
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.
2025-02-14 15:17:40 -08:00
Jamie Nicol
4bb09e1d3c [naga wgsl-in] Ensure constant evaluation correctly handles Composes of vector ZeroValues (#7138) 2025-02-14 13:18:12 -05:00
Vecvec
5af9e30009 Fix HLSL single scalar loads (#7104) 2025-02-12 18:05:32 +00:00
Dzmitry Malyshau
189c97c88a Implement ray query candidate intersection generation and confirmation (#7047) 2025-02-12 16:23:29 +01:00
Jamie Nicol
a546e60d6d [naga wgsl-in] Ensure correct array stride when converting types during const evaluation (#7112)
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.
2025-02-12 15:46:13 +01:00
Jamie Nicol
c07fab2c12 [naga wgsl-in] Allow abstract literals to be used as return values
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.)
2025-02-07 11:44:03 -08:00
Vecvec
d34707ec3f Rename instance_id & instance_custom_index to instance_index & instance_custom_data (#6780) 2025-02-05 18:23:22 +01:00
Jamie Nicol
4e7d892317 [naga msl-out hlsl-out] Improve workaround for infinite loops causing undefined behaviour (#6929)
Co-authored-by: Teodor Tanasoaia <28601907+teoxoy@users.noreply.github.com>
2025-01-31 15:27:52 -05:00
Vecvec
7cde4707ec Fix hlsl storage format generation (#6993) 2025-01-31 16:31:03 +01:00
Jamie Nicol
6c8d0b061c [naga] Restore return statement at end of functions without return types (#7021) 2025-01-29 13:54:49 -05:00
Jamie Nicol
b245b358f5 [naga] Don't treat Emit statements as return statements during ensure_block_returns() (#7013) 2025-01-28 10:48:40 -05:00
Samson
04aff59a14 [naga] implement pointer_composite_access WGSL language extension (#6913)
Co-authored-by: Erich Gubler <erichdongubler@gmail.com>
2025-01-23 13:29:17 -05:00
Teodor Tanasoaia
a8bd1fe1ac [d3d12] bound check dynamic buffers (#6931)
To achieve this for dynamic storage buffers we changed the way we bind them. They now go in root tables and we pass the offset via a root constant.
2025-01-23 17:18:36 +00:00
Jamie Nicol
0282d61f91 [naga hlsl-out] Handle array types for function return values and calls (#6971) 2025-01-23 16:56:18 +01:00
Connor Fitzgerald
436f716715 Unconditionally Generate Bindless Samplers in DX12 (#6766) 2025-01-21 14:24:03 -05:00
the letter L
b626020769 [naga] parse and validate @must_use attribute (#6801)
* feat: parse and enforce `@must_use` attribute

* feat: refuse `@must_use` of void function

* generated naga/tests/out/ir

* revert extraneous changes

* fix clippy

* update repeated attribute error to trunk format

* struct members can't have `@must_use`

* review fixes

* Remove must_use from FunctionResult and revert the related changes

---------

Co-authored-by: turbocrime <turbocrime@users.noreply.github.com>
Co-authored-by: Jamie Nicol <jnicol@mozilla.com>
2025-01-20 18:09:36 +00:00
Jamie Nicol
1f939e1c44 [naga msl-out] Avoid undefined behaviour due to signed integer overflow (#6959)
Signed integer overflow is undefined behaviour in MSL. However, signed
integers are defined to be two's complement. This allows us to cast
signed values to their corresponding unsigned type, perform the
arithmetic on these unsigned values (which has defined overflow
behaviour) then cast the result back to signed.

Care must be taken when emitting the isign polyfill, which uses
metal::select(). We must ensure the -1, 0, and 1 literals used as
inputs to select() have the correct width, else bitcasting the output
of select() will fail due to mismatched widths.
2025-01-20 18:11:27 +01:00
Vecvec
bdef8c0407 [spirv] Stop naga causing undefined behavior in rayQueryGet*Intersection (#6752)
Co-authored-by: Connor Fitzgerald <connorwadefitzgerald@gmail.com>
2025-01-17 00:04:33 +00:00
atlv
be95178709 64 bit image atomics (#5537) 2025-01-15 08:05:13 -05:00
sagudev
ea5d3b953f Add test
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
2025-01-15 11:14:17 +01:00
Vecvec
21de7f7773 Support DXR in wgpu-hal & naga. (#6777)
Co-authored-by: Connor Fitzgerald <connorwadefitzgerald@gmail.com>
2025-01-14 21:28:37 -05:00
atlv
18471d8e78 Image atomics support (#6706)
* Image atomics support

* Address feedback

* fix merge

* Fixes

* Add a couple tests

* Update wgpu-types/src/lib.rs

Co-authored-by: Teodor Tanasoaia <28601907+teoxoy@users.noreply.github.com>

* feedback

* feedback

* glsl

* glsl fix

* fix glsl

* fix fix

* fix fix fic

* fix?

* fix

---------

Co-authored-by: Connor Fitzgerald <connorwadefitzgerald@gmail.com>
Co-authored-by: Teodor Tanasoaia <28601907+teoxoy@users.noreply.github.com>
2025-01-13 15:37:12 +00:00
Asher Jingkong Chen
198762e5cc feat: Add 32-bit floating-point atomics (SHADER_FLOAT32_ATOMIC) (#6234)
* 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>
2025-01-09 16:03:47 +00:00
Connor Fitzgerald
a8a91737b2 Switch Binding Arrays on Metal to Argument Buffers (#6751) 2025-01-07 16:00:56 -05:00