* Allow unconsumed inputs in fragment shaders by removing them from vertex
outputs when generating HLSL.
Fixes https://github.com/gfx-rs/wgpu/issues/3748
* Add naga:🔙:hlsl::FragmentEntryPoint for providing information
about the fragment entry point when generating vertex entry points via
naga:🔙:hlsl::Writer::write. Vertex outputs not consumed by the
fragment entry point are omitted in the final output struct.
* Add naga snapshot test for this new feature,
* Remove Features::SHADER_UNUSED_VERTEX_OUTPUT,
StageError::InputNotConsumed, and associated validation logic.
* Make wgpu dx12 backend pass fragment shader info when generating
vertex HLSL.
* Add wgpu regression test for allowing unconsumed inputs.
* Address review
* Add note that nesting structs for the inter-stage interface can't
happen.
* Remove new TODO notes (some addressed and some transferred to an issue
https://github.com/gfx-rs/wgpu/issues/5577)
* Changed issue that regression test refers to 3748 -> 5553
* Add debug_assert that binding.is_some() in hlsl writer
* Fix typos caught in CI
Also, fix compiling snapshot test when hlsl-out feature is not enabled.
Add `HandleSet` methods `new`, `clear`, `clear_for_arena`, and
`remove`.
Change the type of `naga::valid::Validator::valid_expression_set` from
`BitSet` to `HandleSet`. Adjust uses.
Change `HandleSet::insert` to return `true` if the handle was not
already in the set.
Change uses in `naga::compact` which were taking advantage of the
prior return type of `()` to avoid needing to use semicolons in
`match` arms.
Change `naga::proc::index::find_checked_indexes` to return a
`HandleSet<Expression>`, rather than an untyped `BitSet`.
Fix uses in the Metal Shading Language backend.
Change the `std::fmt::Debug` impl for `naga::arena::Range` to print a
start-inclusive, end-exclusive range.
- This is more consistent with Rust's `std::ops::Range`.
- This is consistent with the serialization form used in snapshots,
which simply uses the serialization of `std::ops::Range`.
- It is not consistent with Naga's constructor function
`Range::new_from_bounds`, which takes an inclusive end value, or
with `Range::first_and_last`, which returns an inclusive end value.
Both of these need to represent ranges' end points as `Handle`s, but
exclusive end values might not be valid `Handle` values. I think
this divergence is tolerable.
This commit is almost entirely code motion. The only meaningful
changes should be:
- changes to imports
- changes to visibility
- changes to use visible associated constructor functions instead of
trying to construct values directly using now-invisible fields
- moving the crate-level "Arena" docs into the `arena` module
In preparation for making `Handle` fields private to another module,
have the `Iterator` implementation for `arena::Range` call
`Handle::new` to construct the handle being produced, rather than
building it using a struct literal.
Use the associated function `Range::from_index_range` to construct the
return value of `Arena::range_from`, rather than constructing the
`Range` directly, in preparation for those fields becoming private.
Change `naga::proc::constant_evaluator::ExpressionKindTracker::inner`
from a `Vec` to a `HandleVec`, for better type-checking and more
convenient indexing. Change uses accordingly.
To support atomic instructions in the SPIR-V front end, observe which
global variables the input accesses using atomic instructions, and
adjust their types from ordinary scalars to atomic values.
See comments in `naga::front::atomic_upgrade`.
Introduce a new type, `HandleVec<T, U>`, which is basically a
`Vec<U>`, except that it's indexed by values of type `Handle<T>`. This
gives us a more strictly typed way to build tables of data parallel to
some other `Arena`.
Change `naga:🔙:pipeline_constants` to use `HandleVec` instead of
`Vec`. This removes many calls to `Handle::index`, and makes the types
more informative.
In `naga:🔙:spv`, change `Writer` and `BlockContext` to use
`HandleVec` instead of `Vec` for various handle-indexed tables.
When the appropriate features are enabled, manually implement
`serde::Serialize` and `serde::Deserialize`, such that the serialized
form of `NonMaxU32::new(n).unwrap()` is the same as that of `n`.
This eliminates the last trace of 1-based indices from Naga's snapshot
tests, and aligns `std::fmt::Debug` with the serialized form.
Remove the phrase "zero-based" from comments and function names. Now
that there is no mix of zero-based and one-based indices, there's no
need to call out the distinction.
Define a new type, `NonMaxU32`, that can represent any `u32` value
except `u32::MAX`, defined such that `Option<NonMaxU32>` is still a
32-bit value.
Change `Handle` to use `NonMaxU32`. Adjust all code that works
directly with handle indices to assume zero-based indices, not
one-based indices.
This replaces all uses of `Handle::index` for generating identifiers
in `naga:🔙:msl` with uses of `Handle::write_prefixed`.
There are still some uses of `Handle::index` remaining.
Make the HLSL backend more like other backends by using `back::Baked`
to generate names for baked expression identifiers. This removes the
final uses of `Handle::index` from the HLSL backend.
This is separated out from the previous commit because it changes lots
of snapshot tests, whereas the previous commit has no effect on Naga's
output.
Introduce a newtype `naga:🔙:Baked` that wraps a
`Handle<Expression>` and formats with `std::fmt::Display` as a baked
expression identifier. Use this in all backends for generating baked
identifiers.
Delete `BAKE_PREFIX`, as it's no longer used outside of `Baked`'s
`Display` implementation.
This is a step towards making `Handle::index` less prominent in the
code base.
Remove `PartialEq` derivations from various Naga IR types on which
equality doesn't really make sense. In some cases, derive only in
`cfg(test)` builds, so tests can check for expected output.
In the GLSL front end, use `append` to add new constants, not
`fetch_or_append`, since the latter requires `PartialEq` yet GLSL
doesn't permit duplicate declarations anyway.
Add the following flags to `wgpu_types::Features`:
- `SHADER_INT64_ATOMIC_ALL_OPS` enables all atomic operations on `atomic<i64>` and
`atomic<u64>` values.
- `SHADER_INT64_ATOMIC_MIN_MAX` is a subset of the above, enabling only
`AtomicFunction::Min` and `AtomicFunction::Max` operations on `atomic<i64>` and
`atomic<u64>` values in the `Storage` address space. These are the only 64-bit
atomic operations available on Metal as of 3.1.
Add corresponding flags to `naga::valid::Capabilities`. These are supported by the
WGSL front end, and all Naga backends.
Platform support:
- On Direct3d 12, in `D3D12_FEATURE_DATA_D3D12_OPTIONS9`, if
`AtomicInt64OnTypedResourceSupported` and `AtomicInt64OnGroupSharedSupported` are
both available, then both wgpu features described above are available.
- On Metal, `SHADER_INT64_ATOMIC_MIN_MAX` is available on Apple9 hardware, and on
hardware that advertises both Apple8 and Mac2 support. This also requires Metal
Shading Language 2.4 or later. Metal does not yet support the more general
`SHADER_INT64_ATOMIC_ALL_OPS`.
- On Vulkan, if the `VK_KHR_shader_atomic_int64` extension is available with both the
`shader_buffer_int64_atomics` and `shader_shared_int64_atomics` features, then both
wgpu features described above are available.
Since `BlockContext::resolve_pointer_type` never returns an error,
change its result type from a `Result` to a `&TypeInner`. Adjust
callers accordingly.
Remove calls (well, there's only one) to `resolve_pointer_type`
entirely when the caller does not need the value, since
`resolve_pointer_type` is now infallible and has no side effects.
Remove `valid::expression::ExpressionError::DoesntExist`. This error is reported
when expression validation encounters an invalid `Handle<Expression>`, but we
have already verified that the module is free of invalid handles in
`Validator::validate_module_handles`, so this condition should never arise.
Fix links in documentation for types defined using the `bitflags!` macro.
As described in [bitflags#407], for some reason, `cargo doc` doesn't
check for broken links in documentation for types or members defined
using `bitflags::bitflags!`.
[bitflags#407]: https://github.com/bitflags/bitflags/issues/407
This proves a flag in msl::PipelineOptions that attempts to write all
Metal vertex entry points to use a vertex pulling technique. It does
this by:
1) Forcing the _buffer_sizes structure to be generated for all vertex
entry points. The structure has additional buffer_size members that
contain the byte sizes of the vertex buffers.
2) Adding new args to vertex entry points for the vertex id and/or
the instance id and for the bound buffers. If there is an existing
@builtin(vertex_index) or @builtin(instance_index) param, then no
duplicate arg is created.
3) Adding code at the beginning of the function for vertex entry points
to compare the vertex id or instance id against the lengths of all the
bound buffers, and force an early-exit if the bounds are violated.
4) Extracting the raw bytes from the vertex buffer(s) and unpacking
those bytes into the bound attributes with the expected types.
5) Replacing the varyings input and instead using the unpacked
attributes to fill any structs-as-args that are rebuilt in the entry
point.
A new naga test is added which exercises this flag and demonstrates the
effect of the transform. The msl generated by this test passes
validation.
Eventually this transformation will be the default, always-on behavior
for Metal pipelines, though the flag may remain so that naga
translation tests can be run with and without the tranformation.