Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
e670f65
docs: texture format profile architecture
cwfitzgerald Jun 8, 2026
15b4bb0
feat(formats): FormatProfile detection, caller formats, and validation
cwfitzgerald Jun 8, 2026
e9f049f
refactor(shaders): mark store-only FSR3 UAVs writeonly
cwfitzgerald Jun 8, 2026
8e81a24
refactor: back FSR3 frame info with a storage buffer
cwfitzgerald Jun 8, 2026
539e347
refactor(xtask): support named permutation variants in perm.toml
cwfitzgerald Jun 9, 2026
3554d4c
feat(formats): per-profile storage formats for non-SPD resources
cwfitzgerald Jun 8, 2026
1279576
refactor: extract create_shader_module helper
cwfitzgerald Jun 9, 2026
271b7df
refactor(shaders): extract shading-change diff metric into a shared h…
cwfitzgerald Jun 9, 2026
d314a89
feat(formats): run SPD pyramids on Core and Tier2 profiles
cwfitzgerald Jun 9, 2026
d96d4b8
ci: add wasm32 build check
cwfitzgerald Jun 9, 2026
96b41cf
feat(validation): mark FsrDispatchError non_exhaustive
cwfitzgerald Jun 9, 2026
3a8790a
docs: changelog for format profiles and wasm support
cwfitzgerald Jun 9, 2026
caddc2c
feat(formats): key Lanczos2 LUT format on TEXTURE_FORMAT_16BIT_NORM
cwfitzgerald Jun 9, 2026
a29d26c
feat(formats): detect FormatProfile from adapter-reported capabilities
cwfitzgerald Jun 9, 2026
11073c8
fix: run FSR3 dispatch on the webgpu backend
cwfitzgerald Jun 16, 2026
a90c713
fix(metal): route SPIR-V through naga and use write-only SPD off the …
cwfitzgerald Jun 29, 2026
aba229e
fix(metal): bind always-32-bit-float point-loaded SRVs unfilterable a…
cwfitzgerald Jun 29, 2026
6e9eb5d
feat(example): FSR3 upscaler demo
cwfitzgerald Jun 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,22 @@ jobs:

- run: cargo doc --workspace --no-deps

wasm:
name: Check WASM
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6

- uses: cwfitzgerald/repo-common/.github/actions/install-rust@trunk
with:
version: ${{ env.CI_RUST_VERSION }}
components: clippy
targets: wasm32-unknown-unknown

- run: cargo clippy -p wgpu-ffx --target wasm32-unknown-unknown --features wgpu/webgpu

- run: cargo doc -p wgpu-ffx --target wasm32-unknown-unknown --features wgpu/webgpu --no-deps

test:
name: Test (${{ matrix.os }})
strategy:
Expand Down
101 changes: 101 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,107 @@ Per Keep a Changelog there are 6 main categories of changes:

## Unreleased

FSR3 no longer requires `TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES`. Devices
are classified into a `FormatProfile` (`Core` | `Tier2` | `Native`),
auto-detected at context creation, and the upscaler selects storage formats
and shader variants the device actually supports:

- **`Core`** — baseline WebGPU (`core-features-and-limits`). Works in the
browser; the crate now builds for `wasm32-unknown-unknown` (CI-verified).
- **`Tier2`** — the `texture-formats-tier2` capability set. Auto-detected on
adapters whose reported capabilities cover the tier-2 set but not
`rg16float` read-write storage — notably Metal.
- **`Native`** — adapter-specific format features with full reported
capabilities; unchanged behavior.

Detection does not trust `TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES` alone:
each profile's required per-format capabilities are verified through
`Adapter::get_texture_format_features` before the profile is selected.

### Added

- `FormatProfile` with `FormatProfile::from_adapter` detection and
`FormatProfile::supported_by`.
- `FsrFormats` — the formats the caller must use for each texture it
provides. Obtainable before a context exists via `FormatProfile::formats()`,
or from a live context via `FsrContext::formats()`.
- `FsrContext::format_profile()` — the profile the context was created with.

### Changed

- Breaking: `FsrContextInfo` gained an `adapter: wgpu::Adapter` field (used to
query per-format capabilities) and a `format_profile: Option<FormatProfile>`
field. `None` auto-detects; `Some` forces a profile (e.g. to exercise
`Core` on a desktop adapter). `FsrContext::new` panics if a forced profile
is unsupported, naming the missing capability.

```diff
FsrContextInfo {
+ adapter,
device,
flags,
+ format_profile: None,
}
```

- Breaking: caller texture formats are profile-dependent and validated.
`dilated_motion_vectors` is `Rg32Float` on `Core` (vs `Rg16Float`
elsewhere). Allocate your textures from `FsrFormats` instead of
hardcoding — it covers all six caller-provided textures (`color`, `depth`,
`motion_vectors`, `output`, `dilated_depth`, `dilated_motion_vectors`).
`FsrContext::dispatch` now validates every caller-provided texture against
the active profile before recording any GPU work.

```diff
+let formats = FormatProfile::from_adapter(&adapter, &device).formats();
+// or, with a live context: context.formats()
device.create_texture(&wgpu::TextureDescriptor {
- format: wgpu::TextureFormat::Rg16Float,
+ format: formats.dilated_motion_vectors,
..
})
```

- The internal Lanczos2 LUT uses `r16snorm` only when the device has the
`TEXTURE_FORMAT_16BIT_NORM` feature enabled (independent of the format
profile); otherwise it widens to filterable `r16float`.

- Breaking: `FsrDispatchError` is now `#[non_exhaustive]` and gained a
`TextureFormatMismatch { texture, expected, actual }` variant. Exhaustive
matches need a wildcard arm.

```diff
match err {
+ FsrDispatchError::TextureFormatMismatch { texture, expected, actual } => ..,
+ _ => ..,
..
}
```

- Internal (no action needed):
- Per-frame metadata moved from a 1×1 read-write storage texture to a
storage buffer.
- On `Core`, the luma / shading-change pyramids run as a write-only
multi-pass chain instead of single-pass SPD; scene-average luma and
auto-exposure match Native closely (covered by comparison tests).
- Store-only storage images are now declared `writeonly` (a correctness
improvement on all profiles).

### Fixed

- `FsrContext::dispatch` now runs on wgpu's `webgpu` backend (Chromium WebGPU),
fixing two runtime panics that only surfaced in the browser:
- Internal textures are zeroed with render-pass clears (`LoadOp::Clear`)
instead of `CommandEncoder::clear_texture`, which is unimplemented on the
`webgpu` backend and required `Features::CLEAR_TEXTURE` natively. The SPD
mips texture gained `RENDER_ATTACHMENT` usage; the clear value is unchanged
(all-zero) and `Features::CLEAR_TEXTURE` is no longer needed.
- The validation error scope around the clears is now popped synchronously
only on native (it surfaces clearing bugs via a panic there). The previous
`pollster::block_on` cannot run on wasm, where error scopes resolve through
JS promises; on wasm the scope is skipped and errors surface through wgpu's
default uncaptured-error handler.

## v0.1.0

Released 2026-04-21
Expand Down
Loading
Loading