In MSL output, avoid undefined behavior due to unbounded loops by
adding an unpredictable, never-actually-taken `break` to the bottom of
each loop body, rather than adding an unpredictable,
never-actually-taken branch over each loop.
This will probably have more of a performance impact, because it
affects each iteration of the loop, but unlike branching over the
loop, which leaves infinite loops (and thus undefined behavior) in the
output, this actually ensures that no loop presented to Metal is
unbounded, so that there is no undefined behavior present that the
optimizer could use to make unwelcome inferences.
Fixes#6528.
Until now we accepted a float, as is the case for non-depth textures.
This makes us compliant with the spec.
The validator is updated to expect an Sint or Uint when the ImageClass
is ImageClass::Depth. The SPIR-V frontend converts the LOD argument
from float to Sint (assuming that it is representable), likewise The
SPIR-V backend now converts the LOD from either Sint or Uint to
Float. HLSL and MSL backends require no changes as they implicitly do
that conversion. GLSL does not support non-compare LOD samples,
therefore no changes are required.
Implement WGSL frontend and WGSL, SPIR-V, HLSL, MSL, and GLSL
backends. WGSL and SPIR-V backends natively support the instruction.
MSL and HLSL emulate it by casting to f16 and back to f32. GLSL does
similar but must (mis)use (un)pack2x16 to do so.
Improve handling of `Access` expressions whose base is an array or
matrix (not a pointer to such), and whose index is not known at
compile time. SPIR-V does not have instructions that can do this
directly, so spill such values to temporary variables, and perform the
accesses using `OpAccessChain` instructions applied to the
temporaries.
When performing chains of accesses like `a[i].x[j]`, do not reify
intermediate values; generate a single `OpAccessChain` for the entire
thing.
Remove special cases for arrays; the same code now handles arrays and
matrices.
Update validation to permit dynamic indexing of matrices.
For details, see the comments on the new tracking structures in
`naga:🔙:spv::Function`.
Add snapshot test `index-by-value.wgsl`.
Fixes#6358.
Fixes#4337.
Alternative to #6362.
Do not neglect to apply bounds checks to indexing operations on
runtime-sized arrays, even when they are accessed via an `AccessIndex`
instruction.
Before this commit, `BlockContext::write_expression_pointer` would not
apply bounds checks to `OpAccessChain` indices provided by an
`AccessIndex` instruction, apparently with the rationale that any
out-of-bounds accesses should have been reported by constant
evaluation.
While it is true that the `index` operand of an `AccessIndex`
expression is known at compile time, and that the WGSL constant
evaluation rules require accesses that can be statically determined to
be out-of-bounds to be shader creation or pipeline creation time
errors, accesses to runtime-sized arrays don't follow this pattern:
even if the index is known, the length with which it must be compared
is not.
Fixes#4441.
Let the SPIR-V backend use `GuardedIndex::try_resolve_to_constant`,
rather than writing out its definition in `write_restricted_index` and
`write_index_comparison`.
Call `try_resolve_to_constant` in one place, in `write_bounds_check`,
and simply pass the `GuardedIndex` into subroutines.
Reduce `write_restricted_index` and `write_index_comparison` to case
analysis and code generation.
Note that this commit does have a benign effect on SPIR-V snapshot
output for programs like this:
let one_i = 1i;
var vec0 = vec3<i32>();
vec0[one_i] = 1;
The value indexing `vec0` here is an `i32`, but after this commit, the
operand to `OpAccessChain` becomes a `u32` constant (with the same
value).
This is because `write_bounds_check` now calls
`try_resolve_to_constant` itself, rather than deferring this work to
its callees, so it may return `BoundsCheckResult::KnownInBounds` even
when the `Unchecked` policy is in force. This directs the caller,
`write_expression_pointer`, to treat the `OpAccessChain` operand as a
fresh `u32` constant, rather than simply passing through the original
`i32` expression.
When generating SPIR-V, avoid generating unreachable blocks following
statements like `break`, `return`, and so on that cause non-local
exits. These unreachable blocks can cause SPIR-V validation to fail.
Fixes#6220.
Bring https://github.com/gfx-rs/naga/pull/723 back from the dead.
Signed-off-by: sagudev <16504129+sagudev@users.noreply.github.com>
Co-authored-by: Dzmitry Malyshau <kvarkus@gmail.com>
Co-authored-by: Jim Blandy <jimb@red-bean.com>
Require `T` to be a struct in `binding_array<T, ...>`; do not permit
arrays.
In #5428, the validator was changed to accept binding array types that
the SPIR-V backend couldn't properly emit. Specifically, the validator
was changed to accept `binding_array<array<T>>`, but the SPIR-V
backend wasn't changed to wrap the binding array elements in a SPIR-V
struct type, as Vulkan requires. So the type would be accepted by the
validator, and then rejected by the backend.
See the comments in the code for details.
This patch emits the definition of the macro only when the first loop
is encountered. This does make that first loop's code look a bit odd:
it would be more natural to define the macro at the top of the
file. (See the modified files in `naga/tests/out/msl`.)
Rejected alternatives:
- We could emit the macro definition unconditionally at the top of the
file. But this changes every MSL snapshot output file, whereas only
eight of them actually contain loops.
- We could have the validator flag modules that contain loops. But the
changes end up being not small, and spread across the validator, so
this seems disproportionate. If we had other consumers of this
information, it might make sense.
- We could change the MSL backend to allow text to be generated out of
order, so that we can decide whether to define the macro after we've
generated all the function bodies. But at the moment this seems like
unnecessary complexity, although it might be worth doing in the
future if we had additional uses for it - say, to conditionally emit
helper function definitions.
Fixes#4972.
* add parsing for spirv::Op::AtomicLoad and spirv::Op::AtomicStore
* spv-in parse AtomicExchange and AtomicCompareExchange
* add atomic i decrement
* bookend atomic store statement with emmitter.finish/emitter.start to suppress a double load expression
bookend atomic result expressions with emitter.finish/start to prevent double defs
* add atomic iadd, isub, smin, umin, smax, umax, and, or, xor
* parse atomic flag test and set, parse atomic flag clear
* remove atomic compare exchange work
* changelog
* moved spirv tests into front/spv/mod.rs
* feature gate atomic spv tests because they require wgsl-[in,out]
* BlockContext::get_contained_global_variable returns Result
* Generate spans covering the entire instruction.
Granted, there is pre-existing code in the SPIR-V front end that gets
this wrong, but:
It doesn't make sense to read `self.data_offset`, and then immediately
pass that to `self.span_from_with_op`. The point of that function is
to make the span cover the entire instruction, operands included.
* Move `From` implementation into spv front end
* doc comments, minor cleanups
* remove parsing of OpAtomicFlagClear and OpAtomicFlagTestAndSet
* sync atomic spvasm files
---------
Co-authored-by: Jim Blandy <jimb@red-bean.com>
Introduce a new module, `naga:🔙:continue_forward`, containing
shared code for rendering Naga `Continue` statements as backend
`break` statements and assignments to introduced `bool` locals.
See the module's documentation for details.
- [hlsl-out] Transform degenerate single body switches into `do-while`
loops. Properly render `Continue` statements enclosed by
`Switch` statements enclosed by `Loop` statements.
- [glsl-out] Transform degenerate single body switches into `do-while`
loops.
Improve `naga xtask validate spv` error message.
Fixes#4485.
Fixes#4514.
In `naga:🔙hlsl`:
- Generate calls to `Interlocked{op}64` when necessary. not
`Interlocked{op}`.
- Make atomic operations that do not produce a value emit their
operands properly.
In the Naga snapshot tests:
- Adapt `atomicOps-int64-min-max.wgsl` to include cases that
cover non-trivial atomic operation operand emitting.
In `wgpu_hal::vulkan::adapter`:
- When retrieving physical device features, be sure to include
the `PhysicalDeviceShaderAtomicInt64Features` extending struct
in the chain whenever the `VK_KHR_shader_atomic_int64` extension
is available.
- Request both `shader_{buffer,shared}_int64_atomics` in the
`PhysicalDeviceShaderAtomicInt64Features` extending struct when either of
`wgpu_types::Features::SHADER_INT64_ATOMIC_{ALL_OPS,MIN_MAX}` is requested.
---------
Co-authored-by: Jim Blandy <jimb@red-bean.com>