From 0a15b03addd2c03c47b7b332d70952405921ceaf Mon Sep 17 00:00:00 2001 From: Nicolas Silva Date: Mon, 4 Dec 2023 22:30:03 +0000 Subject: [PATCH] Bug 1868143 - Update `wgpu` to revision 767ac03245ee937d3dc552edc13fe7ab0a860eec. r=webgpu-reviewers,supply-chain-reviewers,ErichDonGubler # Changelog * #4708 Fix max_vertex_buffers validation By nical in https://github.com/gfx-rs/wgpu/pull/4708 * #4729 Remove expected failure on AMD/DX12 from msaa example By teoxoy in https://github.com/gfx-rs/wgpu/pull/4729 * #4711 [naga] Add `Literal::I64`, for signed 64-bit integer literals. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4711 * #4736 Bump serde from 1.0.192 to 1.0.193 By dependabot[bot] in https://github.com/gfx-rs/wgpu/pull/4736 * #4735 [naga]: Let `TypeInner::Matrix` hold a `Scalar`, not just a width. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4735 * #4741 [naga] Fix type error in test. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4741 * #4742 [naga]: Make snapshot tests include paths in errors. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4742 * #4723 Test And Normalize Vertex Behavior on All Backends By cwfitzgerald in https://github.com/gfx-rs/wgpu/pull/4723 * #4746 Skip Flaky Test By cwfitzgerald in https://github.com/gfx-rs/wgpu/pull/4746 * #4744 Ensure DeviceLostClosureC callbacks have null-terminated message strings By bradwerth in https://github.com/gfx-rs/wgpu/pull/4744 * #4745 [naga wgsl-in] Test hex float suffix handling corner case. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4745 * #4737 Make the command_encoder_clear_buffer's size an Option By nical in https://github.com/gfx-rs/wgpu/pull/4737 * #4701 [naga msl-out] Emit and init `struct` member padding always By ErichDonGubler in https://github.com/gfx-rs/wgpu/pull/4701 * #4701 [naga msl-out] Emit and init `struct` member padding always By ErichDonGubler in https://github.com/gfx-rs/wgpu/pull/4701 * #4701 [naga msl-out] Emit and init `struct` member padding always By ErichDonGubler in https://github.com/gfx-rs/wgpu/pull/4701 * #4701 [naga msl-out] Emit and init `struct` member padding always By ErichDonGubler in https://github.com/gfx-rs/wgpu/pull/4701 * #4733 [naga wgsl-in] Preserve type names in `alias` declarations. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4733 * #4734 [naga] Make compaction preserve named types, even if unused. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4734 * #4752 Logging cleanups in device/global.rs By nical in https://github.com/gfx-rs/wgpu/pull/4752 * #4753 Fix Mac Event Loop By cwfitzgerald in https://github.com/gfx-rs/wgpu/pull/4753 * #4754 wgpu-hal(vk): Add WGPU_ALLOW_NONCOMPLIANT_ADAPTER By i509VCB in https://github.com/gfx-rs/wgpu/pull/4754 * #4748 Allow Tests to Expect Certain Panic or Validation Messages By cwfitzgerald in https://github.com/gfx-rs/wgpu/pull/4748 * #4756 Move to A Single Example Executable By cwfitzgerald in https://github.com/gfx-rs/wgpu/pull/4756 * #4747 [naga wgsl-in] Experimental 64-bit floating-point literals. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4747 * #4747 [naga wgsl-in] Experimental 64-bit floating-point literals. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4747 * #4761 [naga] Make the `example_wgsl` test build without `wgsl-in` feature. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4761 * #4769 Conditionally lift API logging from trace to info level By nical in https://github.com/gfx-rs/wgpu/pull/4769 * #4771 Downgrade some of wgpu_core's logging level from info to trace and debug By nical in https://github.com/gfx-rs/wgpu/pull/4771 * #4760 Rename `ALLOW_NONCOMPLIANT_ADAPTER` to `ALLOW_UNDERLYING_NONCOMPLIANT_ADAPTER` By teoxoy in https://github.com/gfx-rs/wgpu/pull/4760 * #4772 Downgrade resource lifetime management log level to trace. By nical in https://github.com/gfx-rs/wgpu/pull/4772 * #4765 Revamp Examples to Match Website By cwfitzgerald in https://github.com/gfx-rs/wgpu/pull/4765 * #4774 Update examples readme files By roffs in https://github.com/gfx-rs/wgpu/pull/4774 * #4781 remove_abandoned fix By gents83 in https://github.com/gfx-rs/wgpu/pull/4781 * #4777 Bump web-sys to 0.3.65 By torokati44 in https://github.com/gfx-rs/wgpu/pull/4777 * #4780 Fixes for Skybox and All Examples By cwfitzgerald in https://github.com/gfx-rs/wgpu/pull/4780 * #4782 Remove resources ONLY when needed inside wgpu and not in user land By gents83 in https://github.com/gfx-rs/wgpu/pull/4782 * #4786 Don't keep a strong ref in storage for destroyed resources By gents83 in https://github.com/gfx-rs/wgpu/pull/4786 * #4795 Fix Arcanization changelog By a1phyr in https://github.com/gfx-rs/wgpu/pull/4795 * #4794 Delete/rename now-unused gpu.rs By exrook in https://github.com/gfx-rs/wgpu/pull/4794 * #4794 Delete/rename now-unused gpu.rs By exrook in https://github.com/gfx-rs/wgpu/pull/4794 * #4573 Support nv12 texture format By xiaopengli89 in https://github.com/gfx-rs/wgpu/pull/4573 * #4789 Bump js-sys from 0.3.65 to 0.3.66 By dependabot[bot] in https://github.com/gfx-rs/wgpu/pull/4789 * #4784 Bump winit from 0.29.3 to 0.29.4 By dependabot[bot] in https://github.com/gfx-rs/wgpu/pull/4784 * #4798 Bump JamesIves/github-pages-deploy-action from 4.4.3 to 4.5.0 By dependabot[bot] in https://github.com/gfx-rs/wgpu/pull/4798 * #4800 Bump web-sys from 0.3.65 to 0.3.66 By dependabot[bot] in https://github.com/gfx-rs/wgpu/pull/4800 * #4743 Implement WGSL abstract types for global `const` declarations and constructor calls. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4743 * #4743 Implement WGSL abstract types for global `const` declarations and constructor calls. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4743 * #4743 Implement WGSL abstract types for global `const` declarations and constructor calls. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4743 * #4743 Implement WGSL abstract types for global `const` declarations and constructor calls. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4743 * #4743 Implement WGSL abstract types for global `const` declarations and constructor calls. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4743 * #4743 Implement WGSL abstract types for global `const` declarations and constructor calls. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4743 * #4743 Implement WGSL abstract types for global `const` declarations and constructor calls. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4743 * #4743 Implement WGSL abstract types for global `const` declarations and constructor calls. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4743 * #4743 Implement WGSL abstract types for global `const` declarations and constructor calls. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4743 * #4799 Bump wasm-bindgen-futures from 0.4.38 to 0.4.39 By dependabot[bot] in https://github.com/gfx-rs/wgpu/pull/4799 * #4796 Remove surface extent validation (and thus fix the annoying `Requested size ... is outside of the supported range` warning) By Wumpf in https://github.com/gfx-rs/wgpu/pull/4796 * #4804 Add space to a comment inside make_spirv_raw By ComfyFluffy in https://github.com/gfx-rs/wgpu/pull/4804 * #4803 `features`/`limits` refactors By teoxoy in https://github.com/gfx-rs/wgpu/pull/4803 * #4803 `features`/`limits` refactors By teoxoy in https://github.com/gfx-rs/wgpu/pull/4803 * #4803 `features`/`limits` refactors By teoxoy in https://github.com/gfx-rs/wgpu/pull/4803 * #4803 `features`/`limits` refactors By teoxoy in https://github.com/gfx-rs/wgpu/pull/4803 * #4803 `features`/`limits` refactors By teoxoy in https://github.com/gfx-rs/wgpu/pull/4803 * #4805 [naga] Improve ConstantEvaluatorError::InvalidCastArg message. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4805 * #4801 update deno By crowlKats in https://github.com/gfx-rs/wgpu/pull/4801 * #4806 Fixes and changes to the documentation for increasing clarity By Blatko1 in https://github.com/gfx-rs/wgpu/pull/4806 * #4809 [naga wgsl-in] Use a better span for errors in constructors. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4809 * #4808 [naga wgsl-in] Drop spanless labels from front-end error messages. By jimblandy in https://github.com/gfx-rs/wgpu/pull/4808 * #4822 Fix expected error message By teoxoy in https://github.com/gfx-rs/wgpu/pull/4822 * #4759 Add feature float32-filterable By almarklein in https://github.com/gfx-rs/wgpu/pull/4759 * #4813 Bump core-graphics-types from 0.1.2 to 0.1.3 By dependabot[bot] in https://github.com/gfx-rs/wgpu/pull/4813 Differential Revision: https://phabricator.services.mozilla.com/D195438 --- .cargo/config.in | 4 +- Cargo.lock | 10 +- dom/webgpu/Adapter.cpp | 12 +- gfx/wgpu_bindings/Cargo.toml | 14 +- gfx/wgpu_bindings/moz.yaml | 4 +- gfx/wgpu_bindings/src/client.rs | 1 + supply-chain/audits.toml | 25 ++ third_party/rust/d3d12/.cargo-checksum.json | 2 +- third_party/rust/d3d12/src/command_list.rs | 14 +- third_party/rust/naga/.cargo-checksum.json | 2 +- third_party/rust/naga/Cargo.toml | 6 + third_party/rust/naga/README.md | 8 +- .../rust/naga/src/back/glsl/features.rs | 54 ++- .../rust/naga/src/back/glsl/keywords.rs | 1 + third_party/rust/naga/src/back/glsl/mod.rs | 121 ++++-- third_party/rust/naga/src/back/hlsl/conv.rs | 5 +- third_party/rust/naga/src/back/hlsl/writer.rs | 23 +- third_party/rust/naga/src/back/msl/writer.rs | 24 +- third_party/rust/naga/src/back/spv/block.rs | 2 +- third_party/rust/naga/src/back/spv/image.rs | 4 + third_party/rust/naga/src/back/spv/writer.rs | 11 + third_party/rust/naga/src/back/wgsl/writer.rs | 9 +- third_party/rust/naga/src/compact/mod.rs | 8 + third_party/rust/naga/src/front/glsl/types.rs | 2 +- third_party/rust/naga/src/front/wgsl/error.rs | 26 +- .../naga/src/front/wgsl/lower/construction.rs | 366 ++++++++++++------ .../naga/src/front/wgsl/lower/conversion.rs | 365 +++++++++++++++++ .../rust/naga/src/front/wgsl/lower/mod.rs | 112 ++++-- .../rust/naga/src/front/wgsl/parse/lexer.rs | 68 +++- .../rust/naga/src/front/wgsl/parse/number.rs | 72 ++-- third_party/rust/naga/src/front/wgsl/tests.rs | 4 +- .../rust/naga/src/front/wgsl/to_wgsl.rs | 2 + third_party/rust/naga/src/lib.rs | 15 + .../rust/naga/src/proc/constant_evaluator.rs | 258 +++++++++++- third_party/rust/naga/src/proc/mod.rs | 27 +- third_party/rust/naga/src/valid/expression.rs | 14 +- third_party/rust/naga/src/valid/function.rs | 2 +- third_party/rust/naga/src/valid/type.rs | 11 +- .../rust/wgpu-core/.cargo-checksum.json | 2 +- third_party/rust/wgpu-core/Cargo.toml | 4 +- .../rust/wgpu-core/src/binding_model.rs | 7 +- .../rust/wgpu-core/src/command/clear.rs | 24 +- third_party/rust/wgpu-core/src/command/mod.rs | 15 +- .../rust/wgpu-core/src/command/render.rs | 45 +-- .../rust/wgpu-core/src/command/transfer.rs | 19 + .../rust/wgpu-core/src/device/global.rs | 172 ++++---- third_party/rust/wgpu-core/src/device/life.rs | 95 +---- third_party/rust/wgpu-core/src/device/mod.rs | 19 +- .../rust/wgpu-core/src/device/queue.rs | 13 +- .../rust/wgpu-core/src/device/resource.rs | 133 +++++-- .../rust/wgpu-core/src/device/trace.rs | 2 +- third_party/rust/wgpu-core/src/global.rs | 3 +- third_party/rust/wgpu-core/src/id.rs | 17 +- third_party/rust/wgpu-core/src/instance.rs | 55 +-- third_party/rust/wgpu-core/src/lib.rs | 20 + third_party/rust/wgpu-core/src/pipeline.rs | 8 +- third_party/rust/wgpu-core/src/present.rs | 9 +- third_party/rust/wgpu-core/src/registry.rs | 3 - third_party/rust/wgpu-core/src/resource.rs | 27 +- third_party/rust/wgpu-core/src/storage.rs | 33 +- .../rust/wgpu-core/src/track/buffer.rs | 22 +- .../rust/wgpu-core/src/track/metadata.rs | 9 +- third_party/rust/wgpu-core/src/track/mod.rs | 2 +- .../rust/wgpu-core/src/track/stateless.rs | 26 +- .../rust/wgpu-core/src/track/texture.rs | 21 +- third_party/rust/wgpu-core/src/validation.rs | 5 +- .../rust/wgpu-hal/.cargo-checksum.json | 2 +- third_party/rust/wgpu-hal/Cargo.toml | 6 +- third_party/rust/wgpu-hal/README.md | 2 +- .../rust/wgpu-hal/examples/halmark/main.rs | 2 + .../rust/wgpu-hal/examples/raw-gles.rs | 1 + .../rust/wgpu-hal/src/auxil/dxgi/conv.rs | 1 + .../rust/wgpu-hal/src/auxil/dxgi/exception.rs | 2 +- third_party/rust/wgpu-hal/src/dx11/adapter.rs | 4 + third_party/rust/wgpu-hal/src/dx11/command.rs | 8 +- third_party/rust/wgpu-hal/src/dx12/adapter.rs | 23 +- third_party/rust/wgpu-hal/src/dx12/command.rs | 58 +-- third_party/rust/wgpu-hal/src/dx12/device.rs | 10 +- third_party/rust/wgpu-hal/src/dx12/mod.rs | 4 +- third_party/rust/wgpu-hal/src/dx12/view.rs | 14 +- third_party/rust/wgpu-hal/src/empty.rs | 8 +- third_party/rust/wgpu-hal/src/gles/adapter.rs | 52 +-- third_party/rust/wgpu-hal/src/gles/command.rs | 49 ++- third_party/rust/wgpu-hal/src/gles/conv.rs | 1 + third_party/rust/wgpu-hal/src/gles/device.rs | 43 +- third_party/rust/wgpu-hal/src/gles/mod.rs | 81 +++- third_party/rust/wgpu-hal/src/gles/queue.rs | 150 +++++-- third_party/rust/wgpu-hal/src/lib.rs | 42 +- .../rust/wgpu-hal/src/metal/adapter.rs | 51 ++- .../rust/wgpu-hal/src/metal/command.rs | 24 +- third_party/rust/wgpu-hal/src/metal/mod.rs | 5 +- .../rust/wgpu-hal/src/vulkan/adapter.rs | 82 ++-- .../rust/wgpu-hal/src/vulkan/command.rs | 16 +- third_party/rust/wgpu-hal/src/vulkan/conv.rs | 24 +- .../rust/wgpu-hal/src/vulkan/device.rs | 2 +- .../rust/wgpu-hal/src/vulkan/instance.rs | 11 +- .../rust/wgpu-types/.cargo-checksum.json | 2 +- third_party/rust/wgpu-types/Cargo.toml | 4 +- third_party/rust/wgpu-types/src/lib.rs | 240 ++++++++++-- 99 files changed, 2506 insertions(+), 1036 deletions(-) create mode 100644 third_party/rust/naga/src/front/wgsl/lower/conversion.rs diff --git a/.cargo/config.in b/.cargo/config.in index bbaa69dcd6e2a..fec8e77b0c2c4 100644 --- a/.cargo/config.in +++ b/.cargo/config.in @@ -25,9 +25,9 @@ git = "https://github.com/franziskuskiefer/cose-rust" rev = "43c22248d136c8b38fe42ea709d08da6355cf04b" replace-with = "vendored-sources" -[source."git+https://github.com/gfx-rs/wgpu?rev=a820a3ffba468cbb87c2a7e7bbe37065ed5207ee"] +[source."git+https://github.com/gfx-rs/wgpu?rev=767ac03245ee937d3dc552edc13fe7ab0a860eec"] git = "https://github.com/gfx-rs/wgpu" -rev = "a820a3ffba468cbb87c2a7e7bbe37065ed5207ee" +rev = "767ac03245ee937d3dc552edc13fe7ab0a860eec" replace-with = "vendored-sources" [source."git+https://github.com/glandium/warp?rev=4af45fae95bc98b0eba1ef0db17e1dac471bb23d"] diff --git a/Cargo.lock b/Cargo.lock index 741ea404eff3e..abf9ff0853183 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1157,7 +1157,7 @@ dependencies = [ [[package]] name = "d3d12" version = "0.7.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=a820a3ffba468cbb87c2a7e7bbe37065ed5207ee#a820a3ffba468cbb87c2a7e7bbe37065ed5207ee" +source = "git+https://github.com/gfx-rs/wgpu?rev=767ac03245ee937d3dc552edc13fe7ab0a860eec#767ac03245ee937d3dc552edc13fe7ab0a860eec" dependencies = [ "bitflags 2.4.0", "libloading", @@ -3793,7 +3793,7 @@ checksum = "a2983372caf4480544083767bf2d27defafe32af49ab4df3a0b7fc90793a3664" [[package]] name = "naga" version = "0.14.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=a820a3ffba468cbb87c2a7e7bbe37065ed5207ee#a820a3ffba468cbb87c2a7e7bbe37065ed5207ee" +source = "git+https://github.com/gfx-rs/wgpu?rev=767ac03245ee937d3dc552edc13fe7ab0a860eec#767ac03245ee937d3dc552edc13fe7ab0a860eec" dependencies = [ "bit-set", "bitflags 2.4.0", @@ -6395,7 +6395,7 @@ dependencies = [ [[package]] name = "wgpu-core" version = "0.18.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=a820a3ffba468cbb87c2a7e7bbe37065ed5207ee#a820a3ffba468cbb87c2a7e7bbe37065ed5207ee" +source = "git+https://github.com/gfx-rs/wgpu?rev=767ac03245ee937d3dc552edc13fe7ab0a860eec#767ac03245ee937d3dc552edc13fe7ab0a860eec" dependencies = [ "arrayvec", "bit-vec", @@ -6418,7 +6418,7 @@ dependencies = [ [[package]] name = "wgpu-hal" version = "0.18.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=a820a3ffba468cbb87c2a7e7bbe37065ed5207ee#a820a3ffba468cbb87c2a7e7bbe37065ed5207ee" +source = "git+https://github.com/gfx-rs/wgpu?rev=767ac03245ee937d3dc552edc13fe7ab0a860eec#767ac03245ee937d3dc552edc13fe7ab0a860eec" dependencies = [ "android_system_properties", "arrayvec", @@ -6455,7 +6455,7 @@ dependencies = [ [[package]] name = "wgpu-types" version = "0.18.0" -source = "git+https://github.com/gfx-rs/wgpu?rev=a820a3ffba468cbb87c2a7e7bbe37065ed5207ee#a820a3ffba468cbb87c2a7e7bbe37065ed5207ee" +source = "git+https://github.com/gfx-rs/wgpu?rev=767ac03245ee937d3dc552edc13fe7ab0a860eec#767ac03245ee937d3dc552edc13fe7ab0a860eec" dependencies = [ "bitflags 2.4.0", "js-sys", diff --git a/dom/webgpu/Adapter.cpp b/dom/webgpu/Adapter.cpp index e50918e2bdd2a..25fc3e2113dcb 100644 --- a/dom/webgpu/Adapter.cpp +++ b/dom/webgpu/Adapter.cpp @@ -130,10 +130,7 @@ static Maybe ToWGPUFeatures( return Some(WGPUFeatures_BGRA8UNORM_STORAGE); case dom::GPUFeatureName::Float32_filterable: -#ifdef WGPUFeatures_FLOAT32_FILTERABLE -# error fix todo -#endif - return Nothing(); // TODO + return Some(WGPUFeatures_FLOAT32_FILTERABLE); case dom::GPUFeatureName::EndGuard_: break; @@ -454,15 +451,16 @@ already_AddRefed Adapter::RequestDevice( // - ffi::WGPUDeviceDescriptor ffiDesc = {}; - ffiDesc.features = *MakeFeatureBits(aDesc.mRequiredFeatures); - ffiDesc.limits = deviceLimits; + ffiDesc.required_features = *MakeFeatureBits(aDesc.mRequiredFeatures); + ffiDesc.required_limits = deviceLimits; auto request = mBridge->AdapterRequestDevice(mId, ffiDesc); if (!request) { promise->MaybeRejectWithNotSupportedError( "Unable to instantiate a Device"); return; } - RefPtr device = new Device(this, request->mId, ffiDesc.limits); + RefPtr device = + new Device(this, request->mId, ffiDesc.required_limits); for (const auto& feature : aDesc.mRequiredFeatures) { device->mFeatures->Add(feature, aRv); } diff --git a/gfx/wgpu_bindings/Cargo.toml b/gfx/wgpu_bindings/Cargo.toml index df6306ab1fdd3..1b76130b635b6 100644 --- a/gfx/wgpu_bindings/Cargo.toml +++ b/gfx/wgpu_bindings/Cargo.toml @@ -17,7 +17,7 @@ default = [] [dependencies.wgc] package = "wgpu-core" git = "https://github.com/gfx-rs/wgpu" -rev = "a820a3ffba468cbb87c2a7e7bbe37065ed5207ee" +rev = "767ac03245ee937d3dc552edc13fe7ab0a860eec" #Note: "replay" shouldn't ideally be needed, # but it allows us to serialize everything across IPC. features = ["replay", "trace", "serial-pass", "strict_asserts", "wgsl"] @@ -27,36 +27,36 @@ features = ["replay", "trace", "serial-pass", "strict_asserts", "wgsl"] [target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies.wgc] package = "wgpu-core" git = "https://github.com/gfx-rs/wgpu" -rev = "a820a3ffba468cbb87c2a7e7bbe37065ed5207ee" +rev = "767ac03245ee937d3dc552edc13fe7ab0a860eec" features = ["metal"] # We want the wgpu-core Direct3D backends on Windows. [target.'cfg(windows)'.dependencies.wgc] package = "wgpu-core" git = "https://github.com/gfx-rs/wgpu" -rev = "a820a3ffba468cbb87c2a7e7bbe37065ed5207ee" +rev = "767ac03245ee937d3dc552edc13fe7ab0a860eec" features = ["dx11", "dx12"] # We want the wgpu-core Vulkan backend on Linux and Windows. [target.'cfg(any(windows, all(unix, not(any(target_os = "macos", target_os = "ios")))))'.dependencies.wgc] package = "wgpu-core" git = "https://github.com/gfx-rs/wgpu" -rev = "a820a3ffba468cbb87c2a7e7bbe37065ed5207ee" +rev = "767ac03245ee937d3dc552edc13fe7ab0a860eec" features = ["vulkan"] [dependencies.wgt] package = "wgpu-types" git = "https://github.com/gfx-rs/wgpu" -rev = "a820a3ffba468cbb87c2a7e7bbe37065ed5207ee" +rev = "767ac03245ee937d3dc552edc13fe7ab0a860eec" [dependencies.wgh] package = "wgpu-hal" git = "https://github.com/gfx-rs/wgpu" -rev = "a820a3ffba468cbb87c2a7e7bbe37065ed5207ee" +rev = "767ac03245ee937d3dc552edc13fe7ab0a860eec" [target.'cfg(windows)'.dependencies.d3d12] git = "https://github.com/gfx-rs/wgpu" -rev = "a820a3ffba468cbb87c2a7e7bbe37065ed5207ee" +rev = "767ac03245ee937d3dc552edc13fe7ab0a860eec" [target.'cfg(windows)'.dependencies] winapi = "0.3" diff --git a/gfx/wgpu_bindings/moz.yaml b/gfx/wgpu_bindings/moz.yaml index 6018fbdfab5c1..055c8377afe80 100644 --- a/gfx/wgpu_bindings/moz.yaml +++ b/gfx/wgpu_bindings/moz.yaml @@ -20,11 +20,11 @@ origin: # Human-readable identifier for this version/release # Generally "version NNN", "tag SSS", "bookmark SSS" - release: commit a820a3ffba468cbb87c2a7e7bbe37065ed5207ee + release: commit 767ac03245ee937d3dc552edc13fe7ab0a860eec # Revision to pull in # Must be a long or short commit SHA (long preferred) - revision: a820a3ffba468cbb87c2a7e7bbe37065ed5207ee + revision: 767ac03245ee937d3dc552edc13fe7ab0a860eec license: ['MIT', 'Apache-2.0'] diff --git a/gfx/wgpu_bindings/src/client.rs b/gfx/wgpu_bindings/src/client.rs index c1c84d8df4613..3f338264cafe1 100644 --- a/gfx/wgpu_bindings/src/client.rs +++ b/gfx/wgpu_bindings/src/client.rs @@ -580,6 +580,7 @@ pub extern "C" fn wgpu_client_create_texture_view( base_array_layer: desc.base_array_layer, array_layer_count: desc.array_layer_count.map(|ptr| *ptr), }, + plane: None, }; let action = TextureAction::CreateView(id, wgpu_desc); diff --git a/supply-chain/audits.toml b/supply-chain/audits.toml index 5ba9bde152d5b..4622388ea0701 100644 --- a/supply-chain/audits.toml +++ b/supply-chain/audits.toml @@ -1201,6 +1201,11 @@ who = "Erich Gubler " criteria = "safe-to-deploy" delta = "0.7.0@git:6e21f7a9291db4395192d6b510d906978ae2d251 -> 0.7.0@git:a820a3ffba468cbb87c2a7e7bbe37065ed5207ee" +[[audits.d3d12]] +who = "Nicolas Silva " +criteria = "safe-to-deploy" +delta = "0.7.0@git:a820a3ffba468cbb87c2a7e7bbe37065ed5207ee -> 0.7.0@git:767ac03245ee937d3dc552edc13fe7ab0a860eec" + [[audits.d3d12]] who = "Teodor Tanasoaia " criteria = "safe-to-deploy" @@ -2492,6 +2497,11 @@ who = "Erich Gubler " criteria = "safe-to-deploy" delta = "0.14.0@git:6e21f7a9291db4395192d6b510d906978ae2d251 -> 0.14.0@git:a820a3ffba468cbb87c2a7e7bbe37065ed5207ee" +[[audits.naga]] +who = "Nicolas Silva " +criteria = "safe-to-deploy" +delta = "0.14.0@git:a820a3ffba468cbb87c2a7e7bbe37065ed5207ee -> 0.14.0@git:767ac03245ee937d3dc552edc13fe7ab0a860eec" + [[audits.naga]] who = "Teodor Tanasoaia " criteria = "safe-to-deploy" @@ -4255,6 +4265,11 @@ who = "Erich Gubler " criteria = "safe-to-deploy" delta = "0.18.0@git:6e21f7a9291db4395192d6b510d906978ae2d251 -> 0.18.0@git:a820a3ffba468cbb87c2a7e7bbe37065ed5207ee" +[[audits.wgpu-core]] +who = "Nicolas Silva " +criteria = "safe-to-deploy" +delta = "0.18.0@git:a820a3ffba468cbb87c2a7e7bbe37065ed5207ee -> 0.18.0@git:767ac03245ee937d3dc552edc13fe7ab0a860eec" + [[audits.wgpu-core]] who = "Teodor Tanasoaia " criteria = "safe-to-deploy" @@ -4323,6 +4338,11 @@ who = "Erich Gubler " criteria = "safe-to-deploy" delta = "0.18.0@git:6e21f7a9291db4395192d6b510d906978ae2d251 -> 0.18.0@git:a820a3ffba468cbb87c2a7e7bbe37065ed5207ee" +[[audits.wgpu-hal]] +who = "Nicolas Silva " +criteria = "safe-to-deploy" +delta = "0.18.0@git:a820a3ffba468cbb87c2a7e7bbe37065ed5207ee -> 0.18.0@git:767ac03245ee937d3dc552edc13fe7ab0a860eec" + [[audits.wgpu-hal]] who = "Teodor Tanasoaia " criteria = "safe-to-deploy" @@ -4391,6 +4411,11 @@ who = "Erich Gubler " criteria = "safe-to-deploy" delta = "0.18.0@git:6e21f7a9291db4395192d6b510d906978ae2d251 -> 0.18.0@git:a820a3ffba468cbb87c2a7e7bbe37065ed5207ee" +[[audits.wgpu-types]] +who = "Nicolas Silva " +criteria = "safe-to-deploy" +delta = "0.18.0@git:a820a3ffba468cbb87c2a7e7bbe37065ed5207ee -> 0.18.0@git:767ac03245ee937d3dc552edc13fe7ab0a860eec" + [[audits.wgpu-types]] who = "Teodor Tanasoaia " criteria = "safe-to-deploy" diff --git a/third_party/rust/d3d12/.cargo-checksum.json b/third_party/rust/d3d12/.cargo-checksum.json index d9e426afc75c8..05ec7820d46db 100644 --- a/third_party/rust/d3d12/.cargo-checksum.json +++ b/third_party/rust/d3d12/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"CHANGELOG.md":"45fa76b0e5bc51721887147000e9e78a5934cb04d1ad628e501ef2082763d353","Cargo.toml":"1b0564721518684589ff305dd77017193ef116cd29c19eb6d92c81a9f9962a4c","README.md":"76cee3209f773a62535de6c9724b53f158406359f35b4d48b17ac3747b6c102e","src/com.rs":"cfc8f5692162b4cbf9bf370959ad0be08a40a7e9026b5511ca0065ffe33f72ab","src/command_allocator.rs":"ef01059a661749470f3772d188fe0fab0f002e1d154facdab4b9b2932f4b2d93","src/command_list.rs":"beb49cf5a4e53e3e5b121ea7c3247fc8e74eaba67f1fb7dee3416174d5a9fa07","src/debug.rs":"67c8eb966cf349038f79c691e42b5d86cd8fc63c40d10cc279172400d56db6dc","src/descriptor.rs":"fea0b820de1566b54d17d8d0c67e6f5a2126eda19526397eb710ff7d6db9db9e","src/device.rs":"c1dd479aabd22bced0d407523d60629ad1da439fb47ad89fe7b48bae1c4b23e5","src/dxgi.rs":"1516186845b91bf3df813a29b4a0e00a85ca5649fb7a2755da43fba984c41a42","src/heap.rs":"dae2380684896c97e97ed022929f79ce2cc4f5418a3ec34883086f7c88f423d0","src/lib.rs":"612e2f471b84502d219da3fb86ee13f3cbd6faf17d77407bab6c84e51ec424d0","src/pso.rs":"ff819c321536695e34a3be9a6051cf3e57765049a4a2035db6ab27add5a7978a","src/query.rs":"ff61a2b76a108afc1f082724bb9b07ac8b52afbe97356e0fcf6df0ff7e53e07d","src/queue.rs":"bd32813d0b8a3bedf3223b69ade9f9c799a138a9e27d970f86435d9ce32d1557","src/resource.rs":"8989cdb7c3ee0687c826047f39f85148459d9219754f20a970bf8aaa09b96e27","src/sync.rs":"5c287fb7498242a397eb1f08887be9cff9b48dc7cb13af5792cce5f7182b55f8"},"package":null} \ No newline at end of file +{"files":{"CHANGELOG.md":"45fa76b0e5bc51721887147000e9e78a5934cb04d1ad628e501ef2082763d353","Cargo.toml":"1b0564721518684589ff305dd77017193ef116cd29c19eb6d92c81a9f9962a4c","README.md":"76cee3209f773a62535de6c9724b53f158406359f35b4d48b17ac3747b6c102e","src/com.rs":"cfc8f5692162b4cbf9bf370959ad0be08a40a7e9026b5511ca0065ffe33f72ab","src/command_allocator.rs":"ef01059a661749470f3772d188fe0fab0f002e1d154facdab4b9b2932f4b2d93","src/command_list.rs":"8723f3b755b721e0dbb234bd604956c1b7922a2368231197495daa3fa6548e63","src/debug.rs":"67c8eb966cf349038f79c691e42b5d86cd8fc63c40d10cc279172400d56db6dc","src/descriptor.rs":"fea0b820de1566b54d17d8d0c67e6f5a2126eda19526397eb710ff7d6db9db9e","src/device.rs":"c1dd479aabd22bced0d407523d60629ad1da439fb47ad89fe7b48bae1c4b23e5","src/dxgi.rs":"1516186845b91bf3df813a29b4a0e00a85ca5649fb7a2755da43fba984c41a42","src/heap.rs":"dae2380684896c97e97ed022929f79ce2cc4f5418a3ec34883086f7c88f423d0","src/lib.rs":"612e2f471b84502d219da3fb86ee13f3cbd6faf17d77407bab6c84e51ec424d0","src/pso.rs":"ff819c321536695e34a3be9a6051cf3e57765049a4a2035db6ab27add5a7978a","src/query.rs":"ff61a2b76a108afc1f082724bb9b07ac8b52afbe97356e0fcf6df0ff7e53e07d","src/queue.rs":"bd32813d0b8a3bedf3223b69ade9f9c799a138a9e27d970f86435d9ce32d1557","src/resource.rs":"8989cdb7c3ee0687c826047f39f85148459d9219754f20a970bf8aaa09b96e27","src/sync.rs":"5c287fb7498242a397eb1f08887be9cff9b48dc7cb13af5792cce5f7182b55f8"},"package":null} \ No newline at end of file diff --git a/third_party/rust/d3d12/src/command_list.rs b/third_party/rust/d3d12/src/command_list.rs index 168d935e30202..1f8c0d53c26fb 100644 --- a/third_party/rust/d3d12/src/command_list.rs +++ b/third_party/rust/d3d12/src/command_list.rs @@ -213,11 +213,11 @@ impl GraphicsCommandList { &self, num_vertices: VertexCount, num_instances: InstanceCount, - start_vertex: VertexCount, - start_instance: InstanceCount, + first_vertex: VertexCount, + first_instance: InstanceCount, ) { unsafe { - self.DrawInstanced(num_vertices, num_instances, start_vertex, start_instance); + self.DrawInstanced(num_vertices, num_instances, first_vertex, first_instance); } } @@ -225,17 +225,17 @@ impl GraphicsCommandList { &self, num_indices: IndexCount, num_instances: InstanceCount, - start_index: IndexCount, + first_index: IndexCount, base_vertex: VertexOffset, - start_instance: InstanceCount, + first_instance: InstanceCount, ) { unsafe { self.DrawIndexedInstanced( num_indices, num_instances, - start_index, + first_index, base_vertex, - start_instance, + first_instance, ); } } diff --git a/third_party/rust/naga/.cargo-checksum.json b/third_party/rust/naga/.cargo-checksum.json index 0fd3d390df865..7d289c0444c20 100644 --- a/third_party/rust/naga/.cargo-checksum.json +++ b/third_party/rust/naga/.cargo-checksum.json @@ -1 +1 @@ -{"files":{".cargo/config.toml":"d7389d2a0c08ec72b79e83a3c76980903e3f9123625c32e69c798721193e2e74","CHANGELOG.md":"772216b2e6d35621ab36c985e8114b54403e2f3fb49bf1f8540c451fd06f8387","Cargo.toml":"26d629b351260272be0812654b139819b7648176e8414636e0780133aa9792e5","README.md":"a8209bed7462de253558ee8b197c0ce706d505243b2d23614f74464f1d62e15f","benches/criterion.rs":"f45e38b26e1323e934d32623572ff5395a53fed06f760eb1e07b22ed07858a38","src/arena.rs":"33ed2ec7b36429b133ed2a7de6fb9735827f69ea8b6c2ce97f64746a24a5bf36","src/back/dot/mod.rs":"a40050a73ac00c8fa43dd0b45a84fca6959d28c8c99ab3046b01f33c02f8c8f4","src/back/glsl/features.rs":"c0988dd960f545c0706f701a5b143fc638330eb2bca6f6e5b9131651da1300be","src/back/glsl/keywords.rs":"fbc6dad7e0da457f682ee21f86f5b9ebf0b080d750e34e5600085e14f07ab1c1","src/back/glsl/mod.rs":"2501ebfcab34af68c6858053d04d92bae12d1a1b93349ccfbc56ec1978c90b73","src/back/hlsl/conv.rs":"487dd2786ab6153c3fc8637ad11cd17dd7015400684ae4daa949b2dc0d9929be","src/back/hlsl/help.rs":"8f4ec24f74f3153a58b04f441bef16ecc8d400466d53187b06fb6b60a934a1ec","src/back/hlsl/keywords.rs":"eb4af8d697fb7f3991859d66339b5b2eac27c9fe41b73146ac838b207f462c9c","src/back/hlsl/mod.rs":"c677ebbb649a1c5f85f350d8da7129457d50ff52b1c88c1f0fac4a9d11eb020c","src/back/hlsl/storage.rs":"3170f165ff68d2482f8a8dbfa4bbf4b65d2446a7f208f33eea9eb187bb57eb09","src/back/hlsl/writer.rs":"41a29d43b2d75bfd5b8d682d5a07be3fc1ff8a54cf4ba4aaa898889010e7200d","src/back/mod.rs":"b941caed50c086f49d25e76228d247ba6c2da6dbeea18d968c02dc68bb97f409","src/back/msl/keywords.rs":"998c0d86a26e5cf031c75f35cde28f2b390fe207a2e7d0eed8516ffdb99c1a8e","src/back/msl/mod.rs":"16d905902e30cf900ec924b66ff496adbbbc54af15c59713f358bfac042a625a","src/back/msl/sampler.rs":"9b01d68669e12ff7123243284b85e1a9d2c4d49140bd74ca32dedc007cbf15af","src/back/msl/writer.rs":"63d7a4fbc0544662549f650af4e10e1ea2f3bb6b0587d0500a01e46cae376fc0","src/back/spv/block.rs":"75fdfd576951f12c0d6da3d6167ae550d89dc50635f97a67cd375285fb441ad1","src/back/spv/helpers.rs":"a4e260130f39c7345decec40dadf1e94419c8f6d236ce7a53b5300aa72952a1b","src/back/spv/image.rs":"d81d770645913fd57725237f6f96cc4d0a6674b7096fab7e620fb58dc0087e64","src/back/spv/index.rs":"26611dd50df5cfd214900e19415f5374dd301d3b7d3bfedbc5ec0f254328287a","src/back/spv/instructions.rs":"d0ced535fdec49323105a7d6ee40a8ed6b4966ac5f0f40b062f0eb11a531b106","src/back/spv/layout.rs":"e263de53cd2f9a03ad94b82b434ce636609bc1ed435a2d1132951663bfaa8ebd","src/back/spv/mod.rs":"31b0229f59b5784b57851fcf6325095add58af6de3afa85d518a4e266c4b99a9","src/back/spv/ray.rs":"a34bf6b26d873f7270caa45841d9ef291aca8d9732ecd086b14d8856038e1e41","src/back/spv/recyclable.rs":"114db0ea12774d6514f995d07295cb9a42631ab75165fc60980c10e9b5ecb832","src/back/spv/selection.rs":"81e404abfa0a977f7c1f76ccb37a78d13ccadbda229048dad53cc67687cc39db","src/back/spv/writer.rs":"a45c9357e097de1c225ea4a36f91a921f6c871140c15a98a2903e6975e46d59c","src/back/wgsl/mod.rs":"2dd12bbea9ace835850192bb68c5760953da6bac6a636073d1eca19381c0c0b6","src/back/wgsl/writer.rs":"27bb426c3726547b4799f1d77befb563bffa9b6086bfc81cb5a507454aedd8ba","src/block.rs":"c69089e5bbb6de6ba24efb15b21d5d434fcabfbc4d48feae948d2a4da135aae7","src/compact/expressions.rs":"7a4c916282a5b484519ed29ab451c7b595d8dea73c83c5c2cf7efc6fbc648fda","src/compact/functions.rs":"174bd9167ecf6353afb8c36d365ba3f9b483233eb4bacf578e50183c7433aa15","src/compact/handle_set_map.rs":"817c5193352d5fd6a61a5c970daba23224e14a65aea15f8f1c8679c99f834ca2","src/compact/mod.rs":"6b171f09fcd9423eecb2865fa854ed5cec725ff30dc572baaee68b3b24cef0eb","src/compact/statements.rs":"4df33ee9589300e769e75c674bdc30578e93704ec3eb2aabc7132121745b55c8","src/compact/types.rs":"18343f2ca2c123eea2531cffc1d54a7798797caccecaa1f9b8c4fd5dd6ca1a05","src/front/glsl/ast.rs":"2ae292c09fed43951e20ec6ce0b7b99efe91726cf90487d6c129137b08618e01","src/front/glsl/builtins.rs":"d35501d5b42b61c261da24436b82eafdf96371b1600d148648d90d041f736ae4","src/front/glsl/context.rs":"2f07a63209258a8459ae6a6ef8277313c4dc771ab96ef6f5ab3a383a0d3599ba","src/front/glsl/error.rs":"08409f8cc13b73c6eda938ff7ebf2b46e9d27c66d718d640ad8d6a33fddbb7a1","src/front/glsl/functions.rs":"60838c34b8295112e5696b52d710acebb93e0a982e05f8eb87d3b80f52eb7793","src/front/glsl/lex.rs":"08736ae8beb955da5b0e6e3e0f45995a824995f7096d516a2910417e9c7afa32","src/front/glsl/mod.rs":"c8e435a894d641e6c92fcd7d357d51e1136af1a69410fbaedb88c7262b2269df","src/front/glsl/offset.rs":"9358602ca4f9ef21d5066d674dae757bf88fdf5c289c4360534354d13bd41dc0","src/front/glsl/parser.rs":"fe5291512db412b33b6c09d5b3dcf7c54ff6ec55b47f0a078dcc11695e78471d","src/front/glsl/parser/declarations.rs":"d637cc52e553910a2e97b70b3366c15aefbe737f413adb11c27efd184c1fbf9d","src/front/glsl/parser/expressions.rs":"520cfc9402d5fbd48e52ef1d36562c6b74794c09ec33ec1ebb10aa48d129b66f","src/front/glsl/parser/functions.rs":"670ca6bba5a56f3919968658966b05ba824c2d76427b8927d4b111f715091629","src/front/glsl/parser/types.rs":"0971bc98cbde1d70c0ced1717c8726a12a5bfafa9a72b127ed242db5435ec8a8","src/front/glsl/parser_tests.rs":"fc2120fff132af850b52f9ac5d19f0c2fce7997b17ba49881b155d173359cfd3","src/front/glsl/token.rs":"42325adbef5bfc9e6f9e40e7ed3cbfa7ef498c05799fdb7694b123e6450410e1","src/front/glsl/types.rs":"e47355199f45cafed16818f73688cebf12a217493a770df7b091b9a5f3058216","src/front/glsl/variables.rs":"fb2a09e386b6e98ca9fb8fb744afac1e8b19d1b67c6ede5c474e3ba860d3d4cb","src/front/interpolator.rs":"9b6ca498d5fbd9bc1515510a04e303a00b324121d7285da3c955cfe18eb4224c","src/front/mod.rs":"6f77ca3ff925cc16e5ae46132bd6196ca4c9c80a7db123f0d2ec09aae93ba51f","src/front/spv/convert.rs":"9b4ecc53131b6250cde4cae93557eb467127e9e8d0536d29a851538684ae5371","src/front/spv/error.rs":"3129fd1fe346441d61d0f641734df7e919919db15df706788d16402ebf480607","src/front/spv/function.rs":"3a3f0c07862750f79f8ebc273c5df11efc67272566458410f776bd8fa271a0f8","src/front/spv/image.rs":"5d55cfbf6752732a594114cd09a9a207216e1ee85d8f2c9bc4310217a55ea321","src/front/spv/mod.rs":"ccbeb4b80959c00323b2459e316b7c5c7e3f313ab94f2151fa44a2dee6255d4e","src/front/spv/null.rs":"e1446d99d04c76a9c3bbd24dd9b20c4711ce8a918a9b403be6cccbde1175b3b4","src/front/type_gen.rs":"b4f1df23380e06c9fdad4140810ce96ab041dbb1d371a07045b4e0069aa8ba55","src/front/wgsl/error.rs":"8b4887c1ede20efb3c1b885ca2a8848856553ac0b8ced26e1285082b620da39b","src/front/wgsl/index.rs":"2b9a4929a46bd822d3ed6f9a150e24d437e5bdca8293eb748aebe80ce7e74153","src/front/wgsl/lower/construction.rs":"1629d80fffc31859328388760fea8572a314152a38b166bde5d1285a33df0bb9","src/front/wgsl/lower/mod.rs":"054dfa8bb76d9f1ec07d0decb1ccd23d86cc55be005a26a1e223104478d4d359","src/front/wgsl/mod.rs":"02b194a0a29ef7281f71b424564e18ada4a8b1a0d8c26ec40b6be195bd4c4904","src/front/wgsl/parse/ast.rs":"c7eaae40179f0889f2b142d3b31968cbfab6d3cfe02e425912c6da8dadac51df","src/front/wgsl/parse/conv.rs":"01b25edbe80b263a3fa51bc980c075630bb31d4af851441323383eb4f3b83360","src/front/wgsl/parse/lexer.rs":"a26d1c6f76b4883a4b79a617f9914eb3f4b05fbae4d4112606a9598d31a46b8e","src/front/wgsl/parse/mod.rs":"3b4895a2baf91c719b95f0afb6441ffac2036c2a9ff817e633882fd257afcc38","src/front/wgsl/parse/number.rs":"64fe5d5f6b1d6a6acf15f4cad3cda8045ad5d82efda179627f848aba9c47e605","src/front/wgsl/tests.rs":"ab26c5c82a21a4e8072fcdc8b3c47c3d6ac1d854047dd88db99e02aa67502e48","src/front/wgsl/to_wgsl.rs":"0ad5ab5662a8538fe238143ea288b8b52fa9f4ce52a3ea4c3ae6353bd9429eca","src/keywords/mod.rs":"0138f3931f8af0b0a05174549d0fd2152945b027dc3febefc1bbd676581d2e45","src/keywords/wgsl.rs":"7c3b364b60ca29cb8a68ef781de9ecd28b76b74bed18bf18a35d2ebffaa855ab","src/lib.rs":"ea60e2bfa334456b1c2572ceacd14b6feb30759f8f06d1f0013c72c74b7de2e1","src/proc/constant_evaluator.rs":"3559cfdce73957eceb1589435aaf1a09514ea0bfd49d1a1092dd7e06f82e9af3","src/proc/emitter.rs":"39ac886c651e2ad33c06a676a7e4826a0e93de0af660c01e8e4b1f7406742f88","src/proc/index.rs":"f4250f6944c2b631e8140979024e8deb86fa8d5352d8641ba954a388b2c0940e","src/proc/layouter.rs":"b3d061c87424f36981c902716f37ab7b72f2bb2d0c2d7e900c51149318ea1a0a","src/proc/mod.rs":"96ade50eefb2541e59b30c7377d97fc5b10c0d03a4d0492541c4db79d1ecfb92","src/proc/namer.rs":"7328fac41e40890c64c7ee2fa985a4395424f18b08d30f30ca2583fdabd2fd35","src/proc/terminator.rs":"13c59bf00f5b26171d971effc421091f5e00dedddd246c2daa44fe65aeda060a","src/proc/typifier.rs":"99de19270d01c12ec49d14323aa1d9b8774f1ee715804af7235deff70739ba3d","src/span.rs":"6560599f20b8bc2de746ee9fd6b05c32bb630af914fce8845d84fdc72f9a636c","src/valid/analyzer.rs":"8472b98f16a4a4a0fa7079197db25696f77ef3e1602a7cddea1930daebd27917","src/valid/compose.rs":"71a86bd4183f358c4ea25e7b512f318413956947c8035d2b8dc1f3fe7db4ecd2","src/valid/expression.rs":"37b9b3ae31fe13d0ae73a53496adc6ce3cc3ae30e617090ffaf8a9cabacc0987","src/valid/function.rs":"9782913bb4d3df874ca976aa86b06bffd6c30401b8861440a9430203fef9852a","src/valid/handles.rs":"0878915e67b16d7c41cf8245d9ab3b3f4a604e7d4e87527ea40e03efcbf1f74a","src/valid/interface.rs":"6ddf5f8d5150342d2e8c754a71c92c85d8533fd1d4c6b7a83a05b508e8e8114d","src/valid/mod.rs":"9e2bafa06bea16db2c5a8f825eed4d008c474b87cda2fc7e82ca7a21229c6f20","src/valid/type.rs":"447d5004f18778dee31df0caa68e5a31351f3aeaec3e4e142107d32d0308cd55"},"package":null} \ No newline at end of file +{"files":{".cargo/config.toml":"d7389d2a0c08ec72b79e83a3c76980903e3f9123625c32e69c798721193e2e74","CHANGELOG.md":"772216b2e6d35621ab36c985e8114b54403e2f3fb49bf1f8540c451fd06f8387","Cargo.toml":"5bd726a75d7177a43e517d27d412ac38879231f79795226ebcd0873ff1255fe9","README.md":"a76b47b656e7390265312709b62b357a4f39c7509ec9ebe0b133c5841a8ab60b","benches/criterion.rs":"f45e38b26e1323e934d32623572ff5395a53fed06f760eb1e07b22ed07858a38","src/arena.rs":"33ed2ec7b36429b133ed2a7de6fb9735827f69ea8b6c2ce97f64746a24a5bf36","src/back/dot/mod.rs":"a40050a73ac00c8fa43dd0b45a84fca6959d28c8c99ab3046b01f33c02f8c8f4","src/back/glsl/features.rs":"90c6a6255d550e9d97a04d6b6660c1a7af8e2433dd9379dc1d527693fa56523b","src/back/glsl/keywords.rs":"1546facbaddf696602102f32e47db7afc875f8ca3fbccc2122e0bcc45e022b53","src/back/glsl/mod.rs":"bba387392e3b9b22835d78a1db7d1490e7199cafcb347d54b22373b7b76b2900","src/back/hlsl/conv.rs":"5e40946f2d5ad6589dd2b0570d2c300dd96f92f0f954b829dc54a822de7774e8","src/back/hlsl/help.rs":"8f4ec24f74f3153a58b04f441bef16ecc8d400466d53187b06fb6b60a934a1ec","src/back/hlsl/keywords.rs":"eb4af8d697fb7f3991859d66339b5b2eac27c9fe41b73146ac838b207f462c9c","src/back/hlsl/mod.rs":"c677ebbb649a1c5f85f350d8da7129457d50ff52b1c88c1f0fac4a9d11eb020c","src/back/hlsl/storage.rs":"3170f165ff68d2482f8a8dbfa4bbf4b65d2446a7f208f33eea9eb187bb57eb09","src/back/hlsl/writer.rs":"8e61501bae6982273a525734d3e446694d4bf7a081419ec312c32b354e89d3ef","src/back/mod.rs":"b941caed50c086f49d25e76228d247ba6c2da6dbeea18d968c02dc68bb97f409","src/back/msl/keywords.rs":"998c0d86a26e5cf031c75f35cde28f2b390fe207a2e7d0eed8516ffdb99c1a8e","src/back/msl/mod.rs":"16d905902e30cf900ec924b66ff496adbbbc54af15c59713f358bfac042a625a","src/back/msl/sampler.rs":"9b01d68669e12ff7123243284b85e1a9d2c4d49140bd74ca32dedc007cbf15af","src/back/msl/writer.rs":"9503df4ae10d1d7b6840cb68e2e2ff4f7ed8761b217faa99e6927d87da546071","src/back/spv/block.rs":"976c0856d25dc0f54f4b5039b5e101088f32a92c373c7449682e9c8d64fc48c0","src/back/spv/helpers.rs":"a4e260130f39c7345decec40dadf1e94419c8f6d236ce7a53b5300aa72952a1b","src/back/spv/image.rs":"5840a6d5cdffbf30cb20a76ddfdb468041fc6b687a476b3b2fc2553bda6f4af7","src/back/spv/index.rs":"26611dd50df5cfd214900e19415f5374dd301d3b7d3bfedbc5ec0f254328287a","src/back/spv/instructions.rs":"d0ced535fdec49323105a7d6ee40a8ed6b4966ac5f0f40b062f0eb11a531b106","src/back/spv/layout.rs":"e263de53cd2f9a03ad94b82b434ce636609bc1ed435a2d1132951663bfaa8ebd","src/back/spv/mod.rs":"31b0229f59b5784b57851fcf6325095add58af6de3afa85d518a4e266c4b99a9","src/back/spv/ray.rs":"a34bf6b26d873f7270caa45841d9ef291aca8d9732ecd086b14d8856038e1e41","src/back/spv/recyclable.rs":"114db0ea12774d6514f995d07295cb9a42631ab75165fc60980c10e9b5ecb832","src/back/spv/selection.rs":"81e404abfa0a977f7c1f76ccb37a78d13ccadbda229048dad53cc67687cc39db","src/back/spv/writer.rs":"a76a73c0692162da24ab5508bc3ca70eb5e01367fe54472d100e237dbd594467","src/back/wgsl/mod.rs":"2dd12bbea9ace835850192bb68c5760953da6bac6a636073d1eca19381c0c0b6","src/back/wgsl/writer.rs":"f996c393aac339139eed8592b5fdd15fc786a49d3542985dc8ecb07f549a77ea","src/block.rs":"c69089e5bbb6de6ba24efb15b21d5d434fcabfbc4d48feae948d2a4da135aae7","src/compact/expressions.rs":"7a4c916282a5b484519ed29ab451c7b595d8dea73c83c5c2cf7efc6fbc648fda","src/compact/functions.rs":"174bd9167ecf6353afb8c36d365ba3f9b483233eb4bacf578e50183c7433aa15","src/compact/handle_set_map.rs":"817c5193352d5fd6a61a5c970daba23224e14a65aea15f8f1c8679c99f834ca2","src/compact/mod.rs":"8abea7a8a9870d953fb628a32bac2bc15e87e077910cb95aa1f26e58a0a35c2a","src/compact/statements.rs":"4df33ee9589300e769e75c674bdc30578e93704ec3eb2aabc7132121745b55c8","src/compact/types.rs":"18343f2ca2c123eea2531cffc1d54a7798797caccecaa1f9b8c4fd5dd6ca1a05","src/front/glsl/ast.rs":"2ae292c09fed43951e20ec6ce0b7b99efe91726cf90487d6c129137b08618e01","src/front/glsl/builtins.rs":"d35501d5b42b61c261da24436b82eafdf96371b1600d148648d90d041f736ae4","src/front/glsl/context.rs":"2f07a63209258a8459ae6a6ef8277313c4dc771ab96ef6f5ab3a383a0d3599ba","src/front/glsl/error.rs":"08409f8cc13b73c6eda938ff7ebf2b46e9d27c66d718d640ad8d6a33fddbb7a1","src/front/glsl/functions.rs":"60838c34b8295112e5696b52d710acebb93e0a982e05f8eb87d3b80f52eb7793","src/front/glsl/lex.rs":"08736ae8beb955da5b0e6e3e0f45995a824995f7096d516a2910417e9c7afa32","src/front/glsl/mod.rs":"c8e435a894d641e6c92fcd7d357d51e1136af1a69410fbaedb88c7262b2269df","src/front/glsl/offset.rs":"9358602ca4f9ef21d5066d674dae757bf88fdf5c289c4360534354d13bd41dc0","src/front/glsl/parser.rs":"fe5291512db412b33b6c09d5b3dcf7c54ff6ec55b47f0a078dcc11695e78471d","src/front/glsl/parser/declarations.rs":"d637cc52e553910a2e97b70b3366c15aefbe737f413adb11c27efd184c1fbf9d","src/front/glsl/parser/expressions.rs":"520cfc9402d5fbd48e52ef1d36562c6b74794c09ec33ec1ebb10aa48d129b66f","src/front/glsl/parser/functions.rs":"670ca6bba5a56f3919968658966b05ba824c2d76427b8927d4b111f715091629","src/front/glsl/parser/types.rs":"0971bc98cbde1d70c0ced1717c8726a12a5bfafa9a72b127ed242db5435ec8a8","src/front/glsl/parser_tests.rs":"fc2120fff132af850b52f9ac5d19f0c2fce7997b17ba49881b155d173359cfd3","src/front/glsl/token.rs":"42325adbef5bfc9e6f9e40e7ed3cbfa7ef498c05799fdb7694b123e6450410e1","src/front/glsl/types.rs":"58c9cf3d570dff8cb68f2931faf5b18e875e510741bf035ec10b9ff6df27c5d8","src/front/glsl/variables.rs":"fb2a09e386b6e98ca9fb8fb744afac1e8b19d1b67c6ede5c474e3ba860d3d4cb","src/front/interpolator.rs":"9b6ca498d5fbd9bc1515510a04e303a00b324121d7285da3c955cfe18eb4224c","src/front/mod.rs":"6f77ca3ff925cc16e5ae46132bd6196ca4c9c80a7db123f0d2ec09aae93ba51f","src/front/spv/convert.rs":"9b4ecc53131b6250cde4cae93557eb467127e9e8d0536d29a851538684ae5371","src/front/spv/error.rs":"3129fd1fe346441d61d0f641734df7e919919db15df706788d16402ebf480607","src/front/spv/function.rs":"3a3f0c07862750f79f8ebc273c5df11efc67272566458410f776bd8fa271a0f8","src/front/spv/image.rs":"5d55cfbf6752732a594114cd09a9a207216e1ee85d8f2c9bc4310217a55ea321","src/front/spv/mod.rs":"ccbeb4b80959c00323b2459e316b7c5c7e3f313ab94f2151fa44a2dee6255d4e","src/front/spv/null.rs":"e1446d99d04c76a9c3bbd24dd9b20c4711ce8a918a9b403be6cccbde1175b3b4","src/front/type_gen.rs":"b4f1df23380e06c9fdad4140810ce96ab041dbb1d371a07045b4e0069aa8ba55","src/front/wgsl/error.rs":"a2abfd483afe46e1e80d47568ea56c2d587de8dd6291739b03de788f37dada0e","src/front/wgsl/index.rs":"2b9a4929a46bd822d3ed6f9a150e24d437e5bdca8293eb748aebe80ce7e74153","src/front/wgsl/lower/construction.rs":"48b2c1b0ef93345bc3cdbf1af29690cc128a4507f0b9d7d908a136f4c0fd48ca","src/front/wgsl/lower/conversion.rs":"6d123e0148fc6d5b8df3d218ce1978a154d0edb86f65ca20fdc91bb4bf9475ce","src/front/wgsl/lower/mod.rs":"d1954f9845fd4fedbf688dbcff85310954eb69ac228a3e2a128bd5759ad8667d","src/front/wgsl/mod.rs":"02b194a0a29ef7281f71b424564e18ada4a8b1a0d8c26ec40b6be195bd4c4904","src/front/wgsl/parse/ast.rs":"c7eaae40179f0889f2b142d3b31968cbfab6d3cfe02e425912c6da8dadac51df","src/front/wgsl/parse/conv.rs":"01b25edbe80b263a3fa51bc980c075630bb31d4af851441323383eb4f3b83360","src/front/wgsl/parse/lexer.rs":"bff1d0e3cd920b2e9342b521bed7483595556b90088dc0b22e1599900585ff8e","src/front/wgsl/parse/mod.rs":"3b4895a2baf91c719b95f0afb6441ffac2036c2a9ff817e633882fd257afcc38","src/front/wgsl/parse/number.rs":"623423471a13cf9a45662ee3ac01554644ac544338c7493cfe6087549bab91f7","src/front/wgsl/tests.rs":"39d0b44d0f073a7599c88b7c4efd1572886f3af074fa2015454623be313b297f","src/front/wgsl/to_wgsl.rs":"2e2e30d86b07f209b866e530d3a882803bf28b39ce379052561a749f628e8e28","src/keywords/mod.rs":"0138f3931f8af0b0a05174549d0fd2152945b027dc3febefc1bbd676581d2e45","src/keywords/wgsl.rs":"7c3b364b60ca29cb8a68ef781de9ecd28b76b74bed18bf18a35d2ebffaa855ab","src/lib.rs":"c5d91c603ae310a7ef9ff8444898959a3dbbc32ba262cabb1fd5682823921d98","src/proc/constant_evaluator.rs":"0f55fb6f8310dee8dc021f27ab5c3c0ed896963f82150346fcdfbefc47b5e4a1","src/proc/emitter.rs":"39ac886c651e2ad33c06a676a7e4826a0e93de0af660c01e8e4b1f7406742f88","src/proc/index.rs":"f4250f6944c2b631e8140979024e8deb86fa8d5352d8641ba954a388b2c0940e","src/proc/layouter.rs":"b3d061c87424f36981c902716f37ab7b72f2bb2d0c2d7e900c51149318ea1a0a","src/proc/mod.rs":"e6ce6a376aa4e3584f0386fdbe95c7ea2a93abe19b03cc261b6152c8fca24842","src/proc/namer.rs":"7328fac41e40890c64c7ee2fa985a4395424f18b08d30f30ca2583fdabd2fd35","src/proc/terminator.rs":"13c59bf00f5b26171d971effc421091f5e00dedddd246c2daa44fe65aeda060a","src/proc/typifier.rs":"99de19270d01c12ec49d14323aa1d9b8774f1ee715804af7235deff70739ba3d","src/span.rs":"6560599f20b8bc2de746ee9fd6b05c32bb630af914fce8845d84fdc72f9a636c","src/valid/analyzer.rs":"8472b98f16a4a4a0fa7079197db25696f77ef3e1602a7cddea1930daebd27917","src/valid/compose.rs":"71a86bd4183f358c4ea25e7b512f318413956947c8035d2b8dc1f3fe7db4ecd2","src/valid/expression.rs":"1cdbd594dbdb33d8473d93c11112cf717e262bb8c35cee10b01db4322b2237d7","src/valid/function.rs":"5ec31146aacf7daae689836ff3e2978f075f2cc62b3fd829d09c760a6e606501","src/valid/handles.rs":"0878915e67b16d7c41cf8245d9ab3b3f4a604e7d4e87527ea40e03efcbf1f74a","src/valid/interface.rs":"6ddf5f8d5150342d2e8c754a71c92c85d8533fd1d4c6b7a83a05b508e8e8114d","src/valid/mod.rs":"9e2bafa06bea16db2c5a8f825eed4d008c474b87cda2fc7e82ca7a21229c6f20","src/valid/type.rs":"09e18bb9510dbb0cfb4a8ac054afee4c4f56063d614159ab5b956aa1e5850468"},"package":null} \ No newline at end of file diff --git a/third_party/rust/naga/Cargo.toml b/third_party/rust/naga/Cargo.toml index b925fcb31d60b..456573e070a4f 100644 --- a/third_party/rust/naga/Cargo.toml +++ b/third_party/rust/naga/Cargo.toml @@ -21,6 +21,7 @@ exclude = [ "Cargo.lock", "target/**/*", ] +autotests = false description = "Shader translation infrastructure" readme = "README.md" keywords = [ @@ -36,6 +37,10 @@ resolver = "2" [package.metadata.docs.rs] all-features = true +[[test]] +name = "naga-test" +path = "tests/root.rs" + [[bench]] name = "criterion" harness = false @@ -143,6 +148,7 @@ spv-out = ["spirv"] wgsl-in = [ "hexf-parse", "unicode-xid", + "compact", ] wgsl-out = [] diff --git a/third_party/rust/naga/README.md b/third_party/rust/naga/README.md index 04ed84ab5ec46..8cce5bc35f7aa 100644 --- a/third_party/rust/naga/README.md +++ b/third_party/rust/naga/README.md @@ -33,7 +33,7 @@ DOT (GraphViz) | :ok: | dot-out | Not a shading language | ## Conversion tool -Naga can be used as a CLI, which allows to test the conversion of different code paths. +Naga can be used as a CLI, which allows testing the conversion of different code paths. First, install `naga-cli` from crates.io or directly from GitHub. @@ -54,7 +54,7 @@ naga my_shader.spv my_shader.metal --flow-dir flow-dir # convert the SPV to Meta naga my_shader.wgsl my_shader.vert --profile es310 # convert the WGSL to GLSL vertex stage under ES 3.20 profile ``` -As naga includes a default binary target, you can also use `cargo run` without installation. This is useful when you develop naga itself, or investigate the behavior of naga at a specific commit (e.g. [wgpu](https://github.com/gfx-rs/wgpu) might pin a different version of naga than the `HEAD` of this repository). +As naga includes a default binary target, you can also use `cargo run` without installation. This is useful when you develop naga itself or investigate the behavior of naga at a specific commit (e.g. [wgpu](https://github.com/gfx-rs/wgpu) might pin a different version of naga than the `HEAD` of this repository). ```bash cargo run my_shader.wgsl @@ -63,7 +63,7 @@ cargo run my_shader.wgsl ## Development workflow The main instrument aiding the development is the good old `cargo test --all-features --workspace`, -which will run the unit tests, and also update all the snapshots. You'll see these +which will run the unit tests and also update all the snapshots. You'll see these changes in git before committing the code. If working on a particular front-end or back-end, it may be convenient to @@ -71,7 +71,7 @@ enable the relevant features in `Cargo.toml`, e.g. ```toml default = ["spv-out"] #TEMP! ``` -This allows IDE basic checks to report errors there, unless your IDE is sufficiently configurable already. +This allows IDE basic checks to report errors there unless your IDE is sufficiently configurable already. Finally, when changes to the snapshots are made, we should verify that the produced shaders are indeed valid for the target platforms they are compiled for: diff --git a/third_party/rust/naga/src/back/glsl/features.rs b/third_party/rust/naga/src/back/glsl/features.rs index 49d028fb0344d..aaebfde9cb720 100644 --- a/third_party/rust/naga/src/back/glsl/features.rs +++ b/third_party/rust/naga/src/back/glsl/features.rs @@ -1,5 +1,6 @@ use super::{BackendResult, Error, Version, Writer}; use crate::{ + back::glsl::{Options, WriterFlags}, AddressSpace, Binding, Expression, Handle, ImageClass, ImageDimension, Interpolation, Sampling, Scalar, ScalarKind, ShaderStage, StorageFormat, Type, TypeInner, }; @@ -43,6 +44,10 @@ bitflags::bitflags! { const IMAGE_SIZE = 1 << 20; /// Dual source blending const DUAL_SOURCE_BLENDING = 1 << 21; + /// Instance index + /// + /// We can always support this, either through the language or a polyfill + const INSTANCE_INDEX = 1 << 22; } } @@ -63,6 +68,11 @@ impl FeaturesManager { self.0 |= features } + /// Checks if the list of features [`Features`] contains the specified [`Features`] + pub fn contains(&mut self, features: Features) -> bool { + self.0.contains(features) + } + /// Checks that all required [`Features`] are available for the specified /// [`Version`] otherwise returns an [`Error::MissingFeatures`]. pub fn check_availability(&self, version: Version) -> BackendResult { @@ -129,13 +139,13 @@ impl FeaturesManager { /// # Notes /// This won't check for feature availability so it might output extensions that aren't even /// supported.[`check_availability`](Self::check_availability) will check feature availability - pub fn write(&self, version: Version, mut out: impl Write) -> BackendResult { - if self.0.contains(Features::COMPUTE_SHADER) && !version.is_es() { + pub fn write(&self, options: &Options, mut out: impl Write) -> BackendResult { + if self.0.contains(Features::COMPUTE_SHADER) && !options.version.is_es() { // https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_compute_shader.txt writeln!(out, "#extension GL_ARB_compute_shader : require")?; } - if self.0.contains(Features::BUFFER_STORAGE) && !version.is_es() { + if self.0.contains(Features::BUFFER_STORAGE) && !options.version.is_es() { // https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_shader_storage_buffer_object.txt writeln!( out, @@ -143,22 +153,22 @@ impl FeaturesManager { )?; } - if self.0.contains(Features::DOUBLE_TYPE) && version < Version::Desktop(400) { + if self.0.contains(Features::DOUBLE_TYPE) && options.version < Version::Desktop(400) { // https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_gpu_shader_fp64.txt writeln!(out, "#extension GL_ARB_gpu_shader_fp64 : require")?; } if self.0.contains(Features::CUBE_TEXTURES_ARRAY) { - if version.is_es() { + if options.version.is_es() { // https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_texture_cube_map_array.txt writeln!(out, "#extension GL_EXT_texture_cube_map_array : require")?; - } else if version < Version::Desktop(400) { + } else if options.version < Version::Desktop(400) { // https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_cube_map_array.txt writeln!(out, "#extension GL_ARB_texture_cube_map_array : require")?; } } - if self.0.contains(Features::MULTISAMPLED_TEXTURE_ARRAYS) && version.is_es() { + if self.0.contains(Features::MULTISAMPLED_TEXTURE_ARRAYS) && options.version.is_es() { // https://www.khronos.org/registry/OpenGL/extensions/OES/OES_texture_storage_multisample_2d_array.txt writeln!( out, @@ -166,49 +176,49 @@ impl FeaturesManager { )?; } - if self.0.contains(Features::ARRAY_OF_ARRAYS) && version < Version::Desktop(430) { + if self.0.contains(Features::ARRAY_OF_ARRAYS) && options.version < Version::Desktop(430) { // https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_arrays_of_arrays.txt writeln!(out, "#extension ARB_arrays_of_arrays : require")?; } if self.0.contains(Features::IMAGE_LOAD_STORE) { - if self.0.contains(Features::FULL_IMAGE_FORMATS) && version.is_es() { + if self.0.contains(Features::FULL_IMAGE_FORMATS) && options.version.is_es() { // https://www.khronos.org/registry/OpenGL/extensions/NV/NV_image_formats.txt writeln!(out, "#extension GL_NV_image_formats : require")?; } - if version < Version::Desktop(420) { + if options.version < Version::Desktop(420) { // https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_shader_image_load_store.txt writeln!(out, "#extension GL_ARB_shader_image_load_store : require")?; } } if self.0.contains(Features::CONSERVATIVE_DEPTH) { - if version.is_es() { + if options.version.is_es() { // https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_conservative_depth.txt writeln!(out, "#extension GL_EXT_conservative_depth : require")?; } - if version < Version::Desktop(420) { + if options.version < Version::Desktop(420) { // https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_conservative_depth.txt writeln!(out, "#extension GL_ARB_conservative_depth : require")?; } } if (self.0.contains(Features::CLIP_DISTANCE) || self.0.contains(Features::CULL_DISTANCE)) - && version.is_es() + && options.version.is_es() { // https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_clip_cull_distance.txt writeln!(out, "#extension GL_EXT_clip_cull_distance : require")?; } - if self.0.contains(Features::SAMPLE_VARIABLES) && version.is_es() { + if self.0.contains(Features::SAMPLE_VARIABLES) && options.version.is_es() { // https://www.khronos.org/registry/OpenGL/extensions/OES/OES_sample_variables.txt writeln!(out, "#extension GL_OES_sample_variables : require")?; } if self.0.contains(Features::MULTI_VIEW) { - if let Version::Embedded { is_webgl: true, .. } = version { + if let Version::Embedded { is_webgl: true, .. } = options.version { // https://www.khronos.org/registry/OpenGL/extensions/OVR/OVR_multiview2.txt writeln!(out, "#extension GL_OVR_multiview2 : require")?; } else { @@ -225,15 +235,22 @@ impl FeaturesManager { )?; } - if self.0.contains(Features::TEXTURE_LEVELS) && version < Version::Desktop(430) { + if self.0.contains(Features::TEXTURE_LEVELS) && options.version < Version::Desktop(430) { // https://www.khronos.org/registry/OpenGL/extensions/ARB/ARB_texture_query_levels.txt writeln!(out, "#extension GL_ARB_texture_query_levels : require")?; } - if self.0.contains(Features::DUAL_SOURCE_BLENDING) && version.is_es() { + if self.0.contains(Features::DUAL_SOURCE_BLENDING) && options.version.is_es() { // https://registry.khronos.org/OpenGL/extensions/EXT/EXT_blend_func_extended.txt writeln!(out, "#extension GL_EXT_blend_func_extended : require")?; } + if self.0.contains(Features::INSTANCE_INDEX) { + if options.writer_flags.contains(WriterFlags::DRAW_PARAMETERS) { + // https://registry.khronos.org/OpenGL/extensions/ARB/ARB_shader_draw_parameters.txt + writeln!(out, "#extension GL_ARB_shader_draw_parameters : require")?; + } + } + Ok(()) } } @@ -490,6 +507,9 @@ impl<'a, W> Writer<'a, W> { crate::BuiltIn::ViewIndex => { self.features.request(Features::MULTI_VIEW) } + crate::BuiltIn::InstanceIndex => { + self.features.request(Features::INSTANCE_INDEX) + } _ => {} }, Binding::Location { diff --git a/third_party/rust/naga/src/back/glsl/keywords.rs b/third_party/rust/naga/src/back/glsl/keywords.rs index afadd6e7f1a8f..857c935e68142 100644 --- a/third_party/rust/naga/src/back/glsl/keywords.rs +++ b/third_party/rust/naga/src/back/glsl/keywords.rs @@ -480,4 +480,5 @@ pub const RESERVED_KEYWORDS: &[&str] = &[ // Naga utilities: super::MODF_FUNCTION, super::FREXP_FUNCTION, + super::FIRST_INSTANCE_BINDING, ]; diff --git a/third_party/rust/naga/src/back/glsl/mod.rs b/third_party/rust/naga/src/back/glsl/mod.rs index d66b606abc0da..e1dc9066305ab 100644 --- a/third_party/rust/naga/src/back/glsl/mod.rs +++ b/third_party/rust/naga/src/back/glsl/mod.rs @@ -76,6 +76,9 @@ const CLAMPED_LOD_SUFFIX: &str = "_clamped_lod"; pub(crate) const MODF_FUNCTION: &str = "naga_modf"; pub(crate) const FREXP_FUNCTION: &str = "naga_frexp"; +// Must match code in glsl_built_in +pub const FIRST_INSTANCE_BINDING: &str = "naga_vs_first_instance"; + /// Mapping between resources and bindings. pub type BindingMap = std::collections::BTreeMap; @@ -235,17 +238,20 @@ bitflags::bitflags! { /// Supports GL_EXT_texture_shadow_lod on the host, which provides /// additional functions on shadows and arrays of shadows. const TEXTURE_SHADOW_LOD = 0x2; + /// Supports ARB_shader_draw_parameters on the host, which provides + /// support for `gl_BaseInstanceARB`, `gl_BaseVertexARB`, and `gl_DrawIDARB`. + const DRAW_PARAMETERS = 0x4; /// Include unused global variables, constants and functions. By default the output will exclude /// global variables that are not used in the specified entrypoint (including indirect use), /// all constant declarations, and functions that use excluded global variables. - const INCLUDE_UNUSED_ITEMS = 0x4; + const INCLUDE_UNUSED_ITEMS = 0x10; /// Emit `PointSize` output builtin to vertex shaders, which is /// required for drawing with `PointList` topology. /// /// https://registry.khronos.org/OpenGL/specs/es/3.2/GLSL_ES_Specification_3.20.html#built-in-language-variables /// The variable gl_PointSize is intended for a shader to write the size of the point to be rasterized. It is measured in pixels. /// If gl_PointSize is not written to, its value is undefined in subsequent pipe stages. - const FORCE_POINT_SIZE = 0x10; + const FORCE_POINT_SIZE = 0x20; } } @@ -388,6 +394,24 @@ impl IdGenerator { } } +/// Assorted options needed for generting varyings. +#[derive(Clone, Copy)] +struct VaryingOptions { + output: bool, + targetting_webgl: bool, + draw_parameters: bool, +} + +impl VaryingOptions { + const fn from_writer_options(options: &Options, output: bool) -> Self { + Self { + output, + targetting_webgl: options.version.is_webgl(), + draw_parameters: options.writer_flags.contains(WriterFlags::DRAW_PARAMETERS), + } + } +} + /// Helper wrapper used to get a name for a varying /// /// Varying have different naming schemes depending on their binding: @@ -398,8 +422,7 @@ impl IdGenerator { struct VaryingName<'a> { binding: &'a crate::Binding, stage: ShaderStage, - output: bool, - targetting_webgl: bool, + options: VaryingOptions, } impl fmt::Display for VaryingName<'_> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { @@ -411,7 +434,7 @@ impl fmt::Display for VaryingName<'_> { write!(f, "_fs2p_location1",) } crate::Binding::Location { location, .. } => { - let prefix = match (self.stage, self.output) { + let prefix = match (self.stage, self.options.output) { (ShaderStage::Compute, _) => unreachable!(), // pipeline to vertex (ShaderStage::Vertex, false) => "p2vs", @@ -423,11 +446,7 @@ impl fmt::Display for VaryingName<'_> { write!(f, "_{prefix}_location{location}",) } crate::Binding::BuiltIn(built_in) => { - write!( - f, - "{}", - glsl_built_in(built_in, self.output, self.targetting_webgl) - ) + write!(f, "{}", glsl_built_in(built_in, self.options)) } } } @@ -569,7 +588,11 @@ impl<'a, W: Write> Writer<'a, W> { keywords::RESERVED_KEYWORDS, &[], &[], - &["gl_"], + &[ + "gl_", // all GL built-in variables + "_group", // all normal bindings + "_push_constant_binding_", // all push constant bindings + ], &mut names, ); @@ -621,7 +644,7 @@ impl<'a, W: Write> Writer<'a, W> { // writing the module saving some loops but some older versions (420 or less) required the // extensions to appear before being used, even though extensions are part of the // preprocessor not the processor ¯\_(ツ)_/¯ - self.features.write(self.options.version, &mut self.out)?; + self.features.write(self.options, &mut self.out)?; // Write the additional extensions if self @@ -652,6 +675,17 @@ impl<'a, W: Write> Writer<'a, W> { writeln!(self.out)?; } + if self.entry_point.stage == ShaderStage::Vertex + && !self + .options + .writer_flags + .contains(WriterFlags::DRAW_PARAMETERS) + && self.features.contains(Features::INSTANCE_INDEX) + { + writeln!(self.out, "uniform uint {FIRST_INSTANCE_BINDING};")?; + writeln!(self.out)?; + } + // Enable early depth tests if needed if let Some(depth_test) = self.entry_point.early_depth_test { // If early depth test is supported for this version of GLSL @@ -1422,7 +1456,10 @@ impl<'a, W: Write> Writer<'a, W> { writeln!( self.out, "invariant {};", - glsl_built_in(built_in, output, self.options.version.is_webgl()) + glsl_built_in( + built_in, + VaryingOptions::from_writer_options(self.options, output) + ) )?; } } @@ -1499,8 +1536,7 @@ impl<'a, W: Write> Writer<'a, W> { second_blend_source, }, stage: self.entry_point.stage, - output, - targetting_webgl: self.options.version.is_webgl(), + options: VaryingOptions::from_writer_options(self.options, output), }; writeln!(self.out, " {vname};")?; @@ -1661,8 +1697,7 @@ impl<'a, W: Write> Writer<'a, W> { let varying_name = VaryingName { binding: member.binding.as_ref().unwrap(), stage, - output: false, - targetting_webgl: self.options.version.is_webgl(), + options: VaryingOptions::from_writer_options(self.options, false), }; if index != 0 { write!(self.out, ", ")?; @@ -1675,8 +1710,7 @@ impl<'a, W: Write> Writer<'a, W> { let varying_name = VaryingName { binding: arg.binding.as_ref().unwrap(), stage, - output: false, - targetting_webgl: self.options.version.is_webgl(), + options: VaryingOptions::from_writer_options(self.options, false), }; writeln!(self.out, "{varying_name};")?; } @@ -2170,8 +2204,10 @@ impl<'a, W: Write> Writer<'a, W> { let varying_name = VaryingName { binding: member.binding.as_ref().unwrap(), stage: ep.stage, - output: true, - targetting_webgl: self.options.version.is_webgl(), + options: VaryingOptions::from_writer_options( + self.options, + true, + ), }; write!(self.out, "{varying_name} = ")?; @@ -2195,8 +2231,10 @@ impl<'a, W: Write> Writer<'a, W> { let name = VaryingName { binding: result.binding.as_ref().unwrap(), stage: ep.stage, - output: true, - targetting_webgl: self.options.version.is_webgl(), + options: VaryingOptions::from_writer_options( + self.options, + true, + ), }; write!(self.out, "{name} = ")?; self.write_expr(value, ctx)?; @@ -2413,6 +2451,11 @@ impl<'a, W: Write> Writer<'a, W> { crate::Literal::I64(_) => { return Err(Error::Custom("GLSL has no 64-bit integer type".into())); } + crate::Literal::AbstractInt(_) | crate::Literal::AbstractFloat(_) => { + return Err(Error::Custom( + "Abstract types should not appear in IR presented to backends".into(), + )); + } } } Expression::Constant(handle) => { @@ -3517,6 +3560,9 @@ impl<'a, W: Write> Writer<'a, W> { (Sk::Sint | Sk::Uint | Sk::Float, Sk::Bool, None) => { write!(self.out, "bool")? } + + (Sk::AbstractInt | Sk::AbstractFloat, _, _) + | (_, Sk::AbstractInt | Sk::AbstractFloat, _) => unreachable!(), }; write!(self.out, "(")?; @@ -4079,6 +4125,11 @@ impl<'a, W: Write> Writer<'a, W> { crate::ScalarKind::Uint => write!(self.out, "0u")?, crate::ScalarKind::Float => write!(self.out, "0.0")?, crate::ScalarKind::Sint => write!(self.out, "0")?, + crate::ScalarKind::AbstractInt | crate::ScalarKind::AbstractFloat => { + return Err(Error::Custom( + "Abstract types should not appear in IR presented to backends".to_string(), + )) + } } Ok(()) @@ -4307,33 +4358,39 @@ const fn glsl_scalar(scalar: crate::Scalar) -> Result, Err prefix: "b", full: "bool", }, + Sk::AbstractInt | Sk::AbstractFloat => { + return Err(Error::UnsupportedScalar(scalar)); + } }) } /// Helper function that returns the glsl variable name for a builtin -const fn glsl_built_in( - built_in: crate::BuiltIn, - output: bool, - targetting_webgl: bool, -) -> &'static str { +const fn glsl_built_in(built_in: crate::BuiltIn, options: VaryingOptions) -> &'static str { use crate::BuiltIn as Bi; match built_in { Bi::Position { .. } => { - if output { + if options.output { "gl_Position" } else { "gl_FragCoord" } } - Bi::ViewIndex if targetting_webgl => "int(gl_ViewID_OVR)", + Bi::ViewIndex if options.targetting_webgl => "int(gl_ViewID_OVR)", Bi::ViewIndex => "gl_ViewIndex", // vertex Bi::BaseInstance => "uint(gl_BaseInstance)", Bi::BaseVertex => "uint(gl_BaseVertex)", Bi::ClipDistance => "gl_ClipDistance", Bi::CullDistance => "gl_CullDistance", - Bi::InstanceIndex => "uint(gl_InstanceID)", + Bi::InstanceIndex => { + if options.draw_parameters { + "(uint(gl_InstanceID) + uint(gl_BaseInstanceARB))" + } else { + // Must match FISRT_INSTANCE_BINDING + "(uint(gl_InstanceID) + naga_vs_first_instance)" + } + } Bi::PointSize => "gl_PointSize", Bi::VertexIndex => "uint(gl_VertexID)", // fragment @@ -4343,7 +4400,7 @@ const fn glsl_built_in( Bi::PrimitiveIndex => "uint(gl_PrimitiveID)", Bi::SampleIndex => "gl_SampleID", Bi::SampleMask => { - if output { + if options.output { "gl_SampleMask" } else { "gl_SampleMaskIn" diff --git a/third_party/rust/naga/src/back/hlsl/conv.rs b/third_party/rust/naga/src/back/hlsl/conv.rs index da17c35704daa..b6918ddc42ff4 100644 --- a/third_party/rust/naga/src/back/hlsl/conv.rs +++ b/third_party/rust/naga/src/back/hlsl/conv.rs @@ -10,7 +10,7 @@ impl crate::ScalarKind { Self::Float => "asfloat", Self::Sint => "asint", Self::Uint => "asuint", - Self::Bool => unreachable!(), + Self::Bool | Self::AbstractInt | Self::AbstractFloat => unreachable!(), } } } @@ -30,6 +30,9 @@ impl crate::Scalar { _ => Err(Error::UnsupportedScalar(self)), }, crate::ScalarKind::Bool => Ok("bool"), + crate::ScalarKind::AbstractInt | crate::ScalarKind::AbstractFloat => { + Err(Error::UnsupportedScalar(self)) + } } } } diff --git a/third_party/rust/naga/src/back/hlsl/writer.rs b/third_party/rust/naga/src/back/hlsl/writer.rs index 70ad516e55225..0dd60c6ad751c 100644 --- a/third_party/rust/naga/src/back/hlsl/writer.rs +++ b/third_party/rust/naga/src/back/hlsl/writer.rs @@ -13,8 +13,8 @@ use std::{fmt, mem}; const LOCATION_SEMANTIC: &str = "LOC"; const SPECIAL_CBUF_TYPE: &str = "NagaConstants"; const SPECIAL_CBUF_VAR: &str = "_NagaConstants"; -const SPECIAL_BASE_VERTEX: &str = "base_vertex"; -const SPECIAL_BASE_INSTANCE: &str = "base_instance"; +const SPECIAL_FIRST_VERTEX: &str = "first_vertex"; +const SPECIAL_FIRST_INSTANCE: &str = "first_instance"; const SPECIAL_OTHER: &str = "other"; pub(crate) const MODF_FUNCTION: &str = "naga_modf"; @@ -189,8 +189,8 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { // Write special constants, if needed if let Some(ref bt) = self.options.special_constants_binding { writeln!(self.out, "struct {SPECIAL_CBUF_TYPE} {{")?; - writeln!(self.out, "{}int {};", back::INDENT, SPECIAL_BASE_VERTEX)?; - writeln!(self.out, "{}int {};", back::INDENT, SPECIAL_BASE_INSTANCE)?; + writeln!(self.out, "{}int {};", back::INDENT, SPECIAL_FIRST_VERTEX)?; + writeln!(self.out, "{}int {};", back::INDENT, SPECIAL_FIRST_INSTANCE)?; writeln!(self.out, "{}uint {};", back::INDENT, SPECIAL_OTHER)?; writeln!(self.out, "}};")?; write!( @@ -2040,6 +2040,11 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { crate::Literal::I32(value) => write!(self.out, "{}", value)?, crate::Literal::I64(value) => write!(self.out, "{}L", value)?, crate::Literal::Bool(value) => write!(self.out, "{}", value)?, + crate::Literal::AbstractInt(_) | crate::Literal::AbstractFloat(_) => { + return Err(Error::Custom( + "Abstract types should not appear in IR presented to backends".into(), + )); + } }, Expression::Constant(handle) => { let constant = &module.constants[handle]; @@ -2102,7 +2107,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { ) -> BackendResult { use crate::Expression; - // Handle the special semantics for base vertex/instance + // Handle the special semantics of vertex_index/instance_index let ff_input = if self.options.special_constants_binding.is_some() { func_ctx.is_fixed_function_input(expr, module) } else { @@ -2110,20 +2115,20 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> { }; let closing_bracket = match ff_input { Some(crate::BuiltIn::VertexIndex) => { - write!(self.out, "({SPECIAL_CBUF_VAR}.{SPECIAL_BASE_VERTEX} + ")?; + write!(self.out, "({SPECIAL_CBUF_VAR}.{SPECIAL_FIRST_VERTEX} + ")?; ")" } Some(crate::BuiltIn::InstanceIndex) => { - write!(self.out, "({SPECIAL_CBUF_VAR}.{SPECIAL_BASE_INSTANCE} + ",)?; + write!(self.out, "({SPECIAL_CBUF_VAR}.{SPECIAL_FIRST_INSTANCE} + ",)?; ")" } Some(crate::BuiltIn::NumWorkGroups) => { - //Note: despite their names (`BASE_VERTEX` and `BASE_INSTANCE`), + // Note: despite their names (`FIRST_VERTEX` and `FIRST_INSTANCE`), // in compute shaders the special constants contain the number // of workgroups, which we are using here. write!( self.out, - "uint3({SPECIAL_CBUF_VAR}.{SPECIAL_BASE_VERTEX}, {SPECIAL_CBUF_VAR}.{SPECIAL_BASE_INSTANCE}, {SPECIAL_CBUF_VAR}.{SPECIAL_OTHER})", + "uint3({SPECIAL_CBUF_VAR}.{SPECIAL_FIRST_VERTEX}, {SPECIAL_CBUF_VAR}.{SPECIAL_FIRST_INSTANCE}, {SPECIAL_CBUF_VAR}.{SPECIAL_OTHER})", )?; return Ok(()); } diff --git a/third_party/rust/naga/src/back/msl/writer.rs b/third_party/rust/naga/src/back/msl/writer.rs index 48c01e4916e2c..f900add71e8f4 100644 --- a/third_party/rust/naga/src/back/msl/writer.rs +++ b/third_party/rust/naga/src/back/msl/writer.rs @@ -338,6 +338,10 @@ impl crate::Scalar { kind: Sk::Bool, width: _, } => "bool", + Self { + kind: Sk::AbstractInt | Sk::AbstractFloat, + width: _, + } => unreachable!(), } } } @@ -357,11 +361,6 @@ fn should_pack_struct_member( module: &crate::Module, ) -> Option { let member = &members[index]; - //Note: this is imperfect - the same structure can be used for host-shared - // things, where packed float would matter. - if member.binding.is_some() { - return None; - } let ty_inner = &module.types[member.ty].inner; let last_offset = member.offset + ty_inner.size(module.to_ctx()); @@ -375,7 +374,7 @@ fn should_pack_struct_member( crate::TypeInner::Vector { size: crate::VectorSize::Tri, scalar: scalar @ crate::Scalar { width: 4, .. }, - } if member.offset & 0xF != 0 || is_tight => Some(scalar), + } if is_tight => Some(scalar), _ => None, } } @@ -1280,6 +1279,9 @@ impl Writer { crate::Literal::Bool(value) => { write!(self.out, "{value}")?; } + crate::Literal::AbstractInt(_) | crate::Literal::AbstractFloat(_) => { + return Err(Error::Validation); + } }, crate::Expression::Constant(handle) => { let constant = &module.constants[handle]; @@ -3307,8 +3309,7 @@ impl Writer { writeln!(self.out, "struct {name} {{")?; let mut last_offset = 0; for (index, member) in members.iter().enumerate() { - // quick and dirty way to figure out if we need this... - if member.binding.is_none() && member.offset > last_offset { + if member.offset > last_offset { self.struct_member_pads.insert((handle, index as u32)); let pad = member.offset - last_offset; writeln!(self.out, "{}char _pad{}[{}];", back::INDENT, index, pad)?; @@ -4275,6 +4276,13 @@ impl Writer { if member_index != 0 { write!(self.out, ", ")?; } + // insert padding initialization, if needed + if self + .struct_member_pads + .contains(&(arg.ty, member_index as u32)) + { + write!(self.out, "{{}}, ")?; + } if let Some(crate::Binding::Location { .. }) = member.binding { write!(self.out, "{varyings_member_name}.")?; } diff --git a/third_party/rust/naga/src/back/spv/block.rs b/third_party/rust/naga/src/back/spv/block.rs index df6ecd00ffa5b..84f8581521876 100644 --- a/third_party/rust/naga/src/back/spv/block.rs +++ b/third_party/rust/naga/src/back/spv/block.rs @@ -1175,7 +1175,7 @@ impl<'w> BlockContext<'w> { let op = match src_scalar.kind { Sk::Sint | Sk::Uint => spirv::Op::INotEqual, Sk::Float => spirv::Op::FUnordNotEqual, - Sk::Bool => unreachable!(), + Sk::Bool | Sk::AbstractInt | Sk::AbstractFloat => unreachable!(), }; let zero_scalar_id = self.writer.get_constant_scalar_with(0, src_scalar)?; diff --git a/third_party/rust/naga/src/back/spv/image.rs b/third_party/rust/naga/src/back/spv/image.rs index fb9d44e7f07e9..460c906d47316 100644 --- a/third_party/rust/naga/src/back/spv/image.rs +++ b/third_party/rust/naga/src/back/spv/image.rs @@ -334,6 +334,10 @@ impl<'w> BlockContext<'w> { (_, crate::ScalarKind::Bool | crate::ScalarKind::Float) => { unreachable!("we don't allow bool or float for array index") } + (crate::ScalarKind::AbstractInt | crate::ScalarKind::AbstractFloat, _) + | (_, crate::ScalarKind::AbstractInt | crate::ScalarKind::AbstractFloat) => { + unreachable!("abstract types should never reach backends") + } }; let reconciled_array_index_id = if let Some(cast) = cast { let component_ty_id = self.get_type_id(LookupType::Local(LocalType::Value { diff --git a/third_party/rust/naga/src/back/spv/writer.rs b/third_party/rust/naga/src/back/spv/writer.rs index ef0532b2ea4c0..4db86c93a725b 100644 --- a/third_party/rust/naga/src/back/spv/writer.rs +++ b/third_party/rust/naga/src/back/spv/writer.rs @@ -824,6 +824,9 @@ impl Writer { Instruction::type_float(id, bits) } Sk::Bool => Instruction::type_bool(id), + Sk::AbstractInt | Sk::AbstractFloat => { + unreachable!("abstract types should never reach the backend"); + } } } @@ -1184,6 +1187,9 @@ impl Writer { } crate::Literal::Bool(true) => Instruction::constant_true(type_id, id), crate::Literal::Bool(false) => Instruction::constant_false(type_id, id), + crate::Literal::AbstractInt(_) | crate::Literal::AbstractFloat(_) => { + unreachable!("Abstract types should not appear in IR presented to backends"); + } }; instruction.to_words(&mut self.logical_layout.declarations); @@ -1591,6 +1597,11 @@ impl Writer { | crate::TypeInner::Vector { scalar, .. } => match scalar.kind { Sk::Uint | Sk::Sint | Sk::Bool => true, Sk::Float => false, + Sk::AbstractInt | Sk::AbstractFloat => { + return Err(Error::Validation( + "Abstract types should not appear in IR presented to backends", + )) + } }, _ => false, }; diff --git a/third_party/rust/naga/src/back/wgsl/writer.rs b/third_party/rust/naga/src/back/wgsl/writer.rs index 1906035e865a9..a356c7e2ad288 100644 --- a/third_party/rust/naga/src/back/wgsl/writer.rs +++ b/third_party/rust/naga/src/back/wgsl/writer.rs @@ -1095,12 +1095,15 @@ impl Writer { crate::Literal::U32(value) => write!(self.out, "{}u", value)?, crate::Literal::I32(value) => write!(self.out, "{}", value)?, crate::Literal::Bool(value) => write!(self.out, "{}", value)?, - crate::Literal::F64(_) => { - return Err(Error::Custom("unsupported f64 literal".to_string())); - } + crate::Literal::F64(value) => write!(self.out, "{:?}lf", value)?, crate::Literal::I64(_) => { return Err(Error::Custom("unsupported i64 literal".to_string())); } + crate::Literal::AbstractInt(_) | crate::Literal::AbstractFloat(_) => { + return Err(Error::Custom( + "Abstract types should not appear in IR presented to backends".into(), + )); + } } } Expression::Constant(handle) => { diff --git a/third_party/rust/naga/src/compact/mod.rs b/third_party/rust/naga/src/compact/mod.rs index 6f6fe3d9da76e..7dfb8ee80d370 100644 --- a/third_party/rust/naga/src/compact/mod.rs +++ b/third_party/rust/naga/src/compact/mod.rs @@ -100,6 +100,14 @@ pub fn compact(module: &mut crate::Module) { } } + // Treat all named types as used. + for (handle, ty) in module.types.iter() { + log::trace!("tracing type {:?}, name {:?}", handle, ty.name); + if ty.name.is_some() { + module_tracer.types_used.insert(handle); + } + } + // Propagate usage through types. module_tracer.as_type().trace_types(); diff --git a/third_party/rust/naga/src/front/glsl/types.rs b/third_party/rust/naga/src/front/glsl/types.rs index f0a2705ad265e..e87d76fffc849 100644 --- a/third_party/rust/naga/src/front/glsl/types.rs +++ b/third_party/rust/naga/src/front/glsl/types.rs @@ -205,7 +205,7 @@ pub const fn type_power(scalar: Scalar) -> Option { ScalarKind::Uint => 1, ScalarKind::Float if scalar.width == 4 => 2, ScalarKind::Float => 3, - ScalarKind::Bool => return None, + ScalarKind::Bool | ScalarKind::AbstractInt | ScalarKind::AbstractFloat => return None, }) } diff --git a/third_party/rust/naga/src/front/wgsl/error.rs b/third_party/rust/naga/src/front/wgsl/error.rs index f5acbe2d6558d..f2db433e81748 100644 --- a/third_party/rust/naga/src/front/wgsl/error.rs +++ b/third_party/rust/naga/src/front/wgsl/error.rs @@ -34,9 +34,9 @@ impl ParseError { .with_labels( self.labels .iter() - .map(|label| { - Label::primary((), label.0.to_range().unwrap()) - .with_message(label.1.to_string()) + .filter_map(|label| label.0.to_range().map(|range| (label, range))) + .map(|(label, range)| { + Label::primary((), range).with_message(label.1.to_string()) }) .collect(), ) @@ -251,6 +251,12 @@ pub enum Error<'a> { ExpectedPositiveArrayLength(Span), MissingWorkgroupSize(Span), ConstantEvaluatorError(ConstantEvaluatorError, Span), + AutoConversion { + dest_span: Span, + dest_type: String, + source_span: Span, + source_type: String, + }, } impl<'a> Error<'a> { @@ -712,6 +718,20 @@ impl<'a> Error<'a> { )], notes: vec![], }, + Error::AutoConversion { dest_span, ref dest_type, source_span, ref source_type } => ParseError { + message: format!("automatic conversions cannot convert `{source_type}` to `{dest_type}`"), + labels: vec![ + ( + dest_span, + format!("a value of type {dest_type} is required here").into(), + ), + ( + source_span, + format!("this expression has type {source_type}").into(), + ) + ], + notes: vec![], + } } } } diff --git a/third_party/rust/naga/src/front/wgsl/lower/construction.rs b/third_party/rust/naga/src/front/wgsl/lower/construction.rs index fafda793c01aa..96cc45bfa53b6 100644 --- a/third_party/rust/naga/src/front/wgsl/lower/construction.rs +++ b/third_party/rust/naga/src/front/wgsl/lower/construction.rs @@ -5,6 +5,7 @@ use crate::{Handle, Span}; use crate::front::wgsl::error::Error; use crate::front::wgsl::lower::{ExpressionContext, Lowerer}; +use crate::front::wgsl::Scalar; /// A cooked form of `ast::ConstructorType` that uses Naga types whenever /// possible. @@ -80,7 +81,6 @@ enum Components<'a> { Many { components: Vec>, spans: Vec, - first_component_ty_inner: &'a crate::TypeInner, }, } @@ -116,13 +116,15 @@ impl<'source, 'temp> Lowerer<'source, 'temp> { components: &[Handle>], ctx: &mut ExpressionContext<'source, '_, '_>, ) -> Result, Error<'source>> { + use crate::proc::TypeResolution as Tr; + let constructor_h = self.constructor(constructor, ctx)?; let components = match *components { [] => Components::None, [component] => { let span = ctx.ast_expressions.get_span(component); - let component = self.expression(component, ctx)?; + let component = self.expression_for_abstract(component, ctx)?; let ty_inner = super::resolve_inner!(ctx, component); Components::One { @@ -131,30 +133,21 @@ impl<'source, 'temp> Lowerer<'source, 'temp> { ty_inner, } } - [component, ref rest @ ..] => { - let span = ctx.ast_expressions.get_span(component); - let component = self.expression(component, ctx)?; - - let components = std::iter::once(Ok(component)) - .chain( - rest.iter() - .map(|&component| self.expression(component, ctx)), - ) + ref ast_components @ [_, _, ..] => { + let components = ast_components + .iter() + .map(|&expr| self.expression_for_abstract(expr, ctx)) .collect::>()?; - let spans = std::iter::once(span) - .chain( - rest.iter() - .map(|&component| ctx.ast_expressions.get_span(component)), - ) + let spans = ast_components + .iter() + .map(|&expr| ctx.ast_expressions.get_span(expr)) .collect(); - let first_component_ty_inner = super::resolve_inner!(ctx, component); - - Components::Many { - components, - spans, - first_component_ty_inner, + for &component in &components { + ctx.grow_types(component)?; } + + Components::Many { components, spans } } }; @@ -163,7 +156,8 @@ impl<'source, 'temp> Lowerer<'source, 'temp> { // above can have mutable access to the type arena. let constructor = constructor_h.borrow_inner(ctx.module); - let expr = match (components, constructor) { + let expr; + match (components, constructor) { // Empty constructor (Components::None, dst_ty) => match dst_ty { Constructor::Type((result_ty, _)) => { @@ -186,11 +180,13 @@ impl<'source, 'temp> Lowerer<'source, 'temp> { .. }, Constructor::Type((_, &crate::TypeInner::Scalar(scalar))), - ) => crate::Expression::As { - expr: component, - kind: scalar.kind, - convert: Some(scalar.width), - }, + ) => { + expr = crate::Expression::As { + expr: component, + kind: scalar.kind, + convert: Some(scalar.width), + }; + } // Vector conversion (vector -> vector) ( @@ -206,11 +202,13 @@ impl<'source, 'temp> Lowerer<'source, 'temp> { scalar: dst_scalar, }, )), - ) if dst_size == src_size => crate::Expression::As { - expr: component, - kind: dst_scalar.kind, - convert: Some(dst_scalar.width), - }, + ) if dst_size == src_size => { + expr = crate::Expression::As { + expr: component, + kind: dst_scalar.kind, + convert: Some(dst_scalar.width), + }; + } // Vector conversion (vector -> vector) - partial ( @@ -247,11 +245,13 @@ impl<'source, 'temp> Lowerer<'source, 'temp> { scalar: dst_scalar, }, )), - ) if dst_columns == src_columns && dst_rows == src_rows => crate::Expression::As { - expr: component, - kind: crate::ScalarKind::Float, - convert: Some(dst_scalar.width), - }, + ) if dst_columns == src_columns && dst_rows == src_rows => { + expr = crate::Expression::As { + expr: component, + kind: dst_scalar.kind, + convert: Some(dst_scalar.width), + }; + } // Matrix conversion (matrix -> matrix) - partial ( @@ -284,69 +284,99 @@ impl<'source, 'temp> Lowerer<'source, 'temp> { .. }, Constructor::PartialVector { size }, - ) => crate::Expression::Splat { - size, - value: component, - }, + ) => { + expr = crate::Expression::Splat { + size, + value: component, + }; + } // Vector constructor (splat) ( Components::One { - component, - ty_inner: &crate::TypeInner::Scalar(src_scalar), + mut component, + ty_inner: &crate::TypeInner::Scalar(_), .. }, - Constructor::Type(( - _, - &crate::TypeInner::Vector { - size, - scalar: dst_scalar, - }, - )), - ) if dst_scalar == src_scalar => crate::Expression::Splat { - size, - value: component, - }, + Constructor::Type((_, &crate::TypeInner::Vector { size, scalar })), + ) => { + ctx.convert_slice_to_common_scalar(std::slice::from_mut(&mut component), scalar)?; + expr = crate::Expression::Splat { + size, + value: component, + }; + } - // Vector constructor (by elements) + // Vector constructor (by elements), partial ( Components::Many { - components, - first_component_ty_inner: - &crate::TypeInner::Scalar(scalar) | &crate::TypeInner::Vector { scalar, .. }, - .. + mut components, + spans, }, Constructor::PartialVector { size }, - ) - | ( - Components::Many { - components, - first_component_ty_inner: - &crate::TypeInner::Scalar { .. } | &crate::TypeInner::Vector { .. }, - .. - }, - Constructor::Type((_, &crate::TypeInner::Vector { size, scalar })), ) => { - let inner = crate::TypeInner::Vector { size, scalar }; + let consensus_scalar = + automatic_conversion_consensus(&components, ctx).map_err(|index| { + Error::InvalidConstructorComponentType(spans[index], index as i32) + })?; + ctx.convert_slice_to_common_scalar(&mut components, consensus_scalar)?; + let inner = consensus_scalar.to_inner_vector(size); let ty = ctx.ensure_type_exists(inner); - crate::Expression::Compose { ty, components } + expr = crate::Expression::Compose { ty, components }; + } + + // Vector constructor (by elements), full type given + ( + Components::Many { mut components, .. }, + Constructor::Type((ty, &crate::TypeInner::Vector { scalar, .. })), + ) => { + ctx.try_automatic_conversions_for_vector(&mut components, scalar, ty_span)?; + expr = crate::Expression::Compose { ty, components }; } - // Matrix constructor (by elements) + // Matrix constructor (by elements), partial ( Components::Many { - components, - first_component_ty_inner: &crate::TypeInner::Scalar(scalar), - .. + mut components, + spans, }, Constructor::PartialMatrix { columns, rows }, - ) - | ( - Components::Many { - components, - first_component_ty_inner: &crate::TypeInner::Scalar { .. }, - .. - }, + ) if components.len() == columns as usize * rows as usize => { + let consensus_scalar = + automatic_conversion_consensus(&components, ctx).map_err(|index| { + Error::InvalidConstructorComponentType(spans[index], index as i32) + })?; + // We actually only accept floating-point elements. + let consensus_scalar = consensus_scalar + .automatic_conversion_combine(crate::Scalar::ABSTRACT_FLOAT) + .unwrap_or(consensus_scalar); + ctx.convert_slice_to_common_scalar(&mut components, consensus_scalar)?; + let vec_ty = ctx.ensure_type_exists(consensus_scalar.to_inner_vector(rows)); + + let components = components + .chunks(rows as usize) + .map(|vec_components| { + ctx.append_expression( + crate::Expression::Compose { + ty: vec_ty, + components: Vec::from(vec_components), + }, + Default::default(), + ) + }) + .collect::, _>>()?; + + let ty = ctx.ensure_type_exists(crate::TypeInner::Matrix { + columns, + rows, + scalar: consensus_scalar, + }); + expr = crate::Expression::Compose { ty, components }; + } + + // Matrix constructor (by elements), type given + ( + Components::Many { mut components, .. }, Constructor::Type(( _, &crate::TypeInner::Matrix { @@ -355,9 +385,10 @@ impl<'source, 'temp> Lowerer<'source, 'temp> { scalar, }, )), - ) => { - let vec_ty = - ctx.ensure_type_exists(crate::TypeInner::Vector { scalar, size: rows }); + ) if components.len() == columns as usize * rows as usize => { + let element = Tr::Value(crate::TypeInner::Scalar(scalar)); + ctx.try_automatic_conversions_slice(&mut components, &element, ty_span)?; + let vec_ty = ctx.ensure_type_exists(scalar.to_inner_vector(rows)); let components = components .chunks(rows as usize) @@ -377,44 +408,74 @@ impl<'source, 'temp> Lowerer<'source, 'temp> { rows, scalar, }); - crate::Expression::Compose { ty, components } + expr = crate::Expression::Compose { ty, components }; } - // Matrix constructor (by columns) + // Matrix constructor (by columns), partial ( Components::Many { - components, - first_component_ty_inner: &crate::TypeInner::Vector { scalar, .. }, - .. + mut components, + spans, }, Constructor::PartialMatrix { columns, rows }, - ) - | ( - Components::Many { - components, - first_component_ty_inner: &crate::TypeInner::Vector { .. }, - .. - }, + ) => { + let consensus_scalar = + automatic_conversion_consensus(&components, ctx).map_err(|index| { + Error::InvalidConstructorComponentType(spans[index], index as i32) + })?; + ctx.convert_slice_to_common_scalar(&mut components, consensus_scalar)?; + let ty = ctx.ensure_type_exists(crate::TypeInner::Matrix { + columns, + rows, + scalar: consensus_scalar, + }); + expr = crate::Expression::Compose { ty, components }; + } + + // Matrix constructor (by columns), type given + ( + Components::Many { mut components, .. }, Constructor::Type(( - _, + ty, &crate::TypeInner::Matrix { - columns, + columns: _, rows, scalar, }, )), ) => { - let ty = ctx.ensure_type_exists(crate::TypeInner::Matrix { - columns, - rows, - scalar, - }); - crate::Expression::Compose { ty, components } + let component_ty = crate::TypeInner::Vector { size: rows, scalar }; + ctx.try_automatic_conversions_slice( + &mut components, + &Tr::Value(component_ty), + ty_span, + )?; + expr = crate::Expression::Compose { ty, components }; } // Array constructor - infer type (components, Constructor::PartialArray) => { - let components = components.into_components_vec(); + let mut components = components.into_components_vec(); + if let Ok(consensus_scalar) = automatic_conversion_consensus(&components, ctx) { + // Note that this will *not* necessarily convert all the + // components to the same type! The `automatic_conversion_consensus` + // function only considers the parameters' leaf scalar + // types; the parameters themselves could be any mix of + // vectors, matrices, and scalars. + // + // But *if* it is possible for this array construction + // expression to be well-typed at all, then all the + // parameters must have the same type constructors (vec, + // matrix, scalar) applied to their leaf scalars, so + // reconciling their scalars is always the right thing to + // do. And if this array construction is not well-typed, + // these conversions will not make it so, and we can let + // validation catch the error. + ctx.convert_slice_to_common_scalar(&mut components, consensus_scalar)?; + } else { + // There's no consensus scalar. Emit the `Compose` + // expression anyway, and let validation catch the problem. + } let base = ctx.register_type(components[0])?; @@ -430,19 +491,34 @@ impl<'source, 'temp> Lowerer<'source, 'temp> { }; let ty = ctx.ensure_type_exists(inner); - crate::Expression::Compose { ty, components } + expr = crate::Expression::Compose { ty, components }; + } + + // Array constructor, explicit type + (components, Constructor::Type((ty, &crate::TypeInner::Array { base, .. }))) => { + let mut components = components.into_components_vec(); + ctx.try_automatic_conversions_slice(&mut components, &Tr::Handle(base), ty_span)?; + expr = crate::Expression::Compose { ty, components }; } - // Array or Struct constructor + // Struct constructor ( components, - Constructor::Type(( - ty, - &crate::TypeInner::Array { .. } | &crate::TypeInner::Struct { .. }, - )), + Constructor::Type((ty, &crate::TypeInner::Struct { ref members, .. })), ) => { - let components = components.into_components_vec(); - crate::Expression::Compose { ty, components } + let mut components = components.into_components_vec(); + let struct_ty_span = ctx.module.types.get_span(ty); + + // Make a vector of the members' type handles in advance, to + // avoid borrowing `members` from `ctx` while we generate + // new code. + let members: Vec> = members.iter().map(|m| m.ty).collect(); + + for (component, &ty) in components.iter_mut().zip(&members) { + *component = + ctx.try_automatic_conversions(*component, &Tr::Handle(ty), struct_ty_span)?; + } + expr = crate::Expression::Compose { ty, components }; } // ERRORS @@ -466,22 +542,9 @@ impl<'source, 'temp> Lowerer<'source, 'temp> { return Err(Error::UnexpectedComponents(span)); } - // Parameters are of the wrong type for vector or matrix constructor - ( - Components::Many { spans, .. }, - Constructor::Type(( - _, - &crate::TypeInner::Vector { .. } | &crate::TypeInner::Matrix { .. }, - )) - | Constructor::PartialVector { .. } - | Constructor::PartialMatrix { .. }, - ) => { - return Err(Error::InvalidConstructorComponentType(spans[0], 0)); - } - // Other types can't be constructed _ => return Err(Error::TypeNotConstructible(ty_span)), - }; + } let expr = ctx.append_expression(expr, span)?; Ok(expr) @@ -546,3 +609,50 @@ impl<'source, 'temp> Lowerer<'source, 'temp> { Ok(handle) } } + +/// Find the consensus scalar of `components` under WGSL's automatic +/// conversions. +/// +/// If `components` can all be converted to any common scalar via +/// WGSL's automatic conversions, return the best such scalar. +/// +/// The `components` slice must not be empty. All elements' types must +/// have been resolved. +/// +/// If `components` are definitely not acceptable as arguments to such +/// constructors, return `Err(i)`, where `i` is the index in +/// `components` of some problematic argument. +/// +/// This function doesn't fully type-check the arguments - it only +/// considers their leaf scalar types. This means it may return `Ok` +/// even when the Naga validator will reject the resulting +/// construction expression later. +fn automatic_conversion_consensus( + components: &[Handle], + ctx: &ExpressionContext<'_, '_, '_>, +) -> Result { + let types = &ctx.module.types; + let mut inners = components + .iter() + .map(|&c| ctx.typifier()[c].inner_with(types)); + log::debug!( + "wgsl automatic_conversion_consensus: {:?}", + inners + .clone() + .map(|inner| inner.to_wgsl(&ctx.module.to_ctx())) + .collect::>() + ); + let mut best = inners.next().unwrap().scalar().ok_or(0_usize)?; + for (inner, i) in inners.zip(1..) { + let scalar = inner.scalar().ok_or(i)?; + match best.automatic_conversion_combine(scalar) { + Some(new_best) => { + best = new_best; + } + None => return Err(i), + } + } + + log::debug!(" consensus: {:?}", best.to_wgsl()); + Ok(best) +} diff --git a/third_party/rust/naga/src/front/wgsl/lower/conversion.rs b/third_party/rust/naga/src/front/wgsl/lower/conversion.rs new file mode 100644 index 0000000000000..0819c13a66d65 --- /dev/null +++ b/third_party/rust/naga/src/front/wgsl/lower/conversion.rs @@ -0,0 +1,365 @@ +//! WGSL's automatic conversions for abstract types. + +use crate::{Handle, Span}; + +impl<'source, 'temp, 'out> super::ExpressionContext<'source, 'temp, 'out> { + /// Try to use WGSL's automatic conversions to convert `expr` to `goal_ty`. + /// + /// If no conversions are necessary, return `expr` unchanged. + /// + /// If automatic conversions cannot convert `expr` to `goal_ty`, return an + /// [`AutoConversion`] error. + /// + /// Although the Load Rule is one of the automatic conversions, this + /// function assumes it has already been applied if appropriate, as + /// indicated by the fact that the Rust type of `expr` is not `Typed<_>`. + /// + /// [`AutoConversion`]: super::Error::AutoConversion + pub fn try_automatic_conversions( + &mut self, + expr: Handle, + goal_ty: &crate::proc::TypeResolution, + goal_span: Span, + ) -> Result, super::Error<'source>> { + let expr_span = self.get_expression_span(expr); + // Keep the TypeResolution so we can get type names for + // structs in error messages. + let expr_resolution = super::resolve!(self, expr); + let types = &self.module.types; + let expr_inner = expr_resolution.inner_with(types); + let goal_inner = goal_ty.inner_with(types); + + // If `expr` already has the requested type, we're done. + if expr_inner.equivalent(goal_inner, types) { + return Ok(expr); + } + + let (_expr_scalar, goal_scalar) = + match expr_inner.automatically_converts_to(goal_inner, types) { + Some(scalars) => scalars, + None => { + let gctx = &self.module.to_ctx(); + let source_type = expr_resolution.to_wgsl(gctx); + let dest_type = goal_ty.to_wgsl(gctx); + + return Err(super::Error::AutoConversion { + dest_span: goal_span, + dest_type, + source_span: expr_span, + source_type, + }); + } + }; + + let converted = if let crate::TypeInner::Array { .. } = *goal_inner { + let span = self.get_expression_span(expr); + self.as_const_evaluator() + .cast_array(expr, goal_scalar, span) + .map_err(|err| super::Error::ConstantEvaluatorError(err, span))? + } else { + let cast = crate::Expression::As { + expr, + kind: goal_scalar.kind, + convert: Some(goal_scalar.width), + }; + self.append_expression(cast, expr_span)? + }; + + Ok(converted) + } + + /// Try to convert `exprs` to `goal_ty` using WGSL's automatic conversions. + pub fn try_automatic_conversions_slice( + &mut self, + exprs: &mut [Handle], + goal_ty: &crate::proc::TypeResolution, + goal_span: Span, + ) -> Result<(), super::Error<'source>> { + for expr in exprs.iter_mut() { + *expr = self.try_automatic_conversions(*expr, goal_ty, goal_span)?; + } + + Ok(()) + } + + /// Apply WGSL's automatic conversions to a vector constructor's arguments. + /// + /// When calling a vector constructor like `vec3(...)`, the parameters + /// can be a mix of scalars and vectors, with the latter being spread out to + /// contribute each of their components as a component of the new value. + /// When the element type is explicit, as with `` in the example above, + /// WGSL's automatic conversions should convert abstract scalar and vector + /// parameters to the constructor's required scalar type. + pub fn try_automatic_conversions_for_vector( + &mut self, + exprs: &mut [Handle], + goal_scalar: crate::Scalar, + goal_span: Span, + ) -> Result<(), super::Error<'source>> { + use crate::proc::TypeResolution as Tr; + use crate::TypeInner as Ti; + let goal_scalar_res = Tr::Value(Ti::Scalar(goal_scalar)); + + for (i, expr) in exprs.iter_mut().enumerate() { + // Keep the TypeResolution so we can get full type names + // in error messages. + let expr_resolution = super::resolve!(self, *expr); + let types = &self.module.types; + let expr_inner = expr_resolution.inner_with(types); + + match *expr_inner { + Ti::Scalar(_) => { + *expr = self.try_automatic_conversions(*expr, &goal_scalar_res, goal_span)?; + } + Ti::Vector { size, scalar: _ } => { + let goal_vector_res = Tr::Value(Ti::Vector { + size, + scalar: goal_scalar, + }); + *expr = self.try_automatic_conversions(*expr, &goal_vector_res, goal_span)?; + } + _ => { + let span = self.get_expression_span(*expr); + return Err(super::Error::InvalidConstructorComponentType( + span, i as i32, + )); + } + } + } + + Ok(()) + } + + /// Convert all expressions in `exprs` to a common scalar type. + /// + /// Note that the caller is responsible for making sure these + /// conversions are actually justified. This function simply + /// generates `As` expressions, regardless of whether they are + /// permitted WGSL automatic conversions. Callers intending to + /// implement automatic conversions need to determine for + /// themselves whether the casts we we generate are justified, + /// perhaps by calling `TypeInner::automatically_converts_to` or + /// `Scalar::automatic_conversion_combine`. + pub fn convert_slice_to_common_scalar( + &mut self, + exprs: &mut [Handle], + goal: crate::Scalar, + ) -> Result<(), super::Error<'source>> { + for expr in exprs.iter_mut() { + let inner = super::resolve_inner!(self, *expr); + // Do nothing if `inner` doesn't even have leaf scalars; + // it's a type error that validation will catch. + if inner.scalar() != Some(goal) { + let cast = crate::Expression::As { + expr: *expr, + kind: goal.kind, + convert: Some(goal.width), + }; + let expr_span = self.get_expression_span(*expr); + *expr = self.append_expression(cast, expr_span)?; + } + } + + Ok(()) + } + + /// Return an expression for the concretized value of `expr`. + /// + /// If `expr` is already concrete, return it unchanged. + pub fn concretize( + &mut self, + mut expr: Handle, + ) -> Result, super::Error<'source>> { + let inner = super::resolve_inner!(self, expr); + if let Some(scalar) = inner.automatically_convertible_scalar(&self.module.types) { + let concretized = scalar.concretize(); + if concretized != scalar { + let span = self.get_expression_span(expr); + expr = self + .as_const_evaluator() + .cast_array(expr, concretized, span) + .map_err(|err| super::Error::ConstantEvaluatorError(err, span))?; + } + } + + Ok(expr) + } +} + +impl crate::TypeInner { + /// Determine whether `self` automatically converts to `goal`. + /// + /// If WGSL's automatic conversions (excluding the Load Rule) will + /// convert `self` to `goal`, then return a pair `(from, to)`, + /// where `from` and `to` are the scalar types of the leaf values + /// of `self` and `goal`. + /// + /// This function assumes that `self` and `goal` are different + /// types. Callers should first check whether any conversion is + /// needed at all. + /// + /// If the automatic conversions cannot convert `self` to `goal`, + /// return `None`. + fn automatically_converts_to( + &self, + goal: &Self, + types: &crate::UniqueArena, + ) -> Option<(crate::Scalar, crate::Scalar)> { + use crate::ScalarKind as Sk; + use crate::TypeInner as Ti; + + // Automatic conversions only change the scalar type of a value's leaves + // (e.g., `vec4` to `vec4`), never the type + // constructors applied to those scalar types (e.g., never scalar to + // `vec4`, or `vec2` to `vec3`). So first we check that the type + // constructors match, extracting the leaf scalar types in the process. + let expr_scalar; + let goal_scalar; + match (self, goal) { + (&Ti::Scalar(expr), &Ti::Scalar(goal)) => { + expr_scalar = expr; + goal_scalar = goal; + } + ( + &Ti::Vector { + size: expr_size, + scalar: expr, + }, + &Ti::Vector { + size: goal_size, + scalar: goal, + }, + ) if expr_size == goal_size => { + expr_scalar = expr; + goal_scalar = goal; + } + ( + &Ti::Matrix { + rows: expr_rows, + columns: expr_columns, + scalar: expr, + }, + &Ti::Matrix { + rows: goal_rows, + columns: goal_columns, + scalar: goal, + }, + ) if expr_rows == goal_rows && expr_columns == goal_columns => { + expr_scalar = expr; + goal_scalar = goal; + } + ( + &Ti::Array { + base: expr_base, + size: expr_size, + stride: _, + }, + &Ti::Array { + base: goal_base, + size: goal_size, + stride: _, + }, + ) if expr_size == goal_size => { + return types[expr_base] + .inner + .automatically_converts_to(&types[goal_base].inner, types); + } + _ => return None, + } + + match (expr_scalar.kind, goal_scalar.kind) { + (Sk::AbstractFloat, Sk::Float) => {} + (Sk::AbstractInt, Sk::Sint | Sk::Uint | Sk::AbstractFloat | Sk::Float) => {} + _ => return None, + } + + log::trace!(" okay: expr {expr_scalar:?}, goal {goal_scalar:?}"); + Some((expr_scalar, goal_scalar)) + } + + fn automatically_convertible_scalar( + &self, + types: &crate::UniqueArena, + ) -> Option { + use crate::TypeInner as Ti; + match *self { + Ti::Scalar(scalar) | Ti::Vector { scalar, .. } | Ti::Matrix { scalar, .. } => { + Some(scalar) + } + Ti::Array { base, .. } => types[base].inner.automatically_convertible_scalar(types), + Ti::Atomic(_) + | Ti::Pointer { .. } + | Ti::ValuePointer { .. } + | Ti::Struct { .. } + | Ti::Image { .. } + | Ti::Sampler { .. } + | Ti::AccelerationStructure + | Ti::RayQuery + | Ti::BindingArray { .. } => None, + } + } +} + +impl crate::Scalar { + /// Find the common type of `self` and `other` under WGSL's + /// automatic conversions. + /// + /// If there are any scalars to which WGSL's automatic conversions + /// will convert both `self` and `other`, return the best such + /// scalar. Otherwise, return `None`. + pub const fn automatic_conversion_combine(self, other: Self) -> Option { + use crate::ScalarKind as Sk; + + match (self.kind, other.kind) { + // When the kinds match... + (Sk::AbstractFloat, Sk::AbstractFloat) + | (Sk::AbstractInt, Sk::AbstractInt) + | (Sk::Sint, Sk::Sint) + | (Sk::Uint, Sk::Uint) + | (Sk::Float, Sk::Float) + | (Sk::Bool, Sk::Bool) => { + if self.width == other.width { + // ... either no conversion is necessary ... + Some(self) + } else { + // ... or no conversion is possible. + // We never convert concrete to concrete, and + // abstract types should have only one size. + None + } + } + + // AbstractInt converts to AbstractFloat. + (Sk::AbstractFloat, Sk::AbstractInt) => Some(self), + (Sk::AbstractInt, Sk::AbstractFloat) => Some(other), + + // AbstractFloat converts to Float. + (Sk::AbstractFloat, Sk::Float) => Some(other), + (Sk::Float, Sk::AbstractFloat) => Some(self), + + // AbstractInt converts to concrete integer or float. + (Sk::AbstractInt, Sk::Uint | Sk::Sint | Sk::Float) => Some(other), + (Sk::Uint | Sk::Sint | Sk::Float, Sk::AbstractInt) => Some(self), + + // AbstractFloat can't be reconciled with concrete integer types. + (Sk::AbstractFloat, Sk::Uint | Sk::Sint) | (Sk::Uint | Sk::Sint, Sk::AbstractFloat) => { + None + } + + // Nothing can be reconciled with `bool`. + (Sk::Bool, _) | (_, Sk::Bool) => None, + + // Different concrete types cannot be reconciled. + (Sk::Sint | Sk::Uint | Sk::Float, Sk::Sint | Sk::Uint | Sk::Float) => None, + } + } + + const fn concretize(self) -> Self { + use crate::ScalarKind as Sk; + match self.kind { + Sk::Sint | Sk::Uint | Sk::Float | Sk::Bool => self, + Sk::AbstractInt => Self::I32, + Sk::AbstractFloat => Self::F32, + } + } +} diff --git a/third_party/rust/naga/src/front/wgsl/lower/mod.rs b/third_party/rust/naga/src/front/wgsl/lower/mod.rs index 34940e4515b1e..b050ffc343d77 100644 --- a/third_party/rust/naga/src/front/wgsl/lower/mod.rs +++ b/third_party/rust/naga/src/front/wgsl/lower/mod.rs @@ -11,6 +11,7 @@ use crate::proc::{ use crate::{Arena, FastHashMap, FastIndexMap, Handle, Span}; mod construction; +mod conversion; /// Resolves the inner type of a given expression. /// @@ -66,6 +67,7 @@ macro_rules! resolve { &$ctx.typifier()[$expr] }}; } +pub(super) use resolve; /// State for constructing a `crate::Module`. pub struct GlobalContext<'source, 'temp, 'out> { @@ -98,10 +100,14 @@ impl<'source> GlobalContext<'source, '_, '_> { } } - fn ensure_type_exists(&mut self, inner: crate::TypeInner) -> Handle { + fn ensure_type_exists( + &mut self, + name: Option, + inner: crate::TypeInner, + ) -> Handle { self.module .types - .insert(crate::Type { inner, name: None }, Span::UNDEFINED) + .insert(crate::Type { inner, name }, Span::UNDEFINED) } } @@ -635,7 +641,7 @@ impl<'source, 'temp, 'out> ExpressionContext<'source, 'temp, 'out> { } fn ensure_type_exists(&mut self, inner: crate::TypeInner) -> Handle { - self.as_global().ensure_type_exists(inner) + self.as_global().ensure_type_exists(None, inner) } } @@ -899,29 +905,39 @@ impl<'source, 'temp> Lowerer<'source, 'temp> { } ast::GlobalDeclKind::Const(ref c) => { let mut ectx = ctx.as_const(); - let init = self.expression(c.init, &mut ectx)?; - let inferred_type = ectx.register_type(init)?; - - let explicit_ty = - c.ty.map(|ty| self.resolve_ast_type(ty, &mut ctx)) - .transpose()?; - - if let Some(explicit) = explicit_ty { - if explicit != inferred_type { - let gctx = ctx.module.to_ctx(); - return Err(Error::InitializationTypeMismatch { - name: c.name.span, - expected: explicit.to_wgsl(&gctx), - got: inferred_type.to_wgsl(&gctx), - }); - } + let mut init = self.expression_for_abstract(c.init, &mut ectx)?; + + let ty; + if let Some(explicit_ty) = c.ty { + let explicit_ty = + self.resolve_ast_type(explicit_ty, &mut ectx.as_global())?; + let explicit_ty_res = crate::proc::TypeResolution::Handle(explicit_ty); + init = ectx + .try_automatic_conversions(init, &explicit_ty_res, c.name.span) + .map_err(|error| match error { + Error::AutoConversion { + dest_span: _, + dest_type, + source_span: _, + source_type, + } => Error::InitializationTypeMismatch { + name: c.name.span, + expected: dest_type, + got: source_type, + }, + other => other, + })?; + ty = explicit_ty; + } else { + init = ectx.concretize(init)?; + ty = ectx.register_type(init)?; } let handle = ctx.module.constants.append( crate::Constant { name: Some(c.name.name.to_string()), r#override: crate::Override::None, - ty: inferred_type, + ty, init, }, span, @@ -936,13 +952,22 @@ impl<'source, 'temp> Lowerer<'source, 'temp> { .insert(s.name.name, LoweredGlobalDecl::Type(handle)); } ast::GlobalDeclKind::Type(ref alias) => { - let ty = self.resolve_ast_type(alias.ty, &mut ctx)?; + let ty = self.resolve_named_ast_type( + alias.ty, + Some(alias.name.name.to_string()), + &mut ctx, + )?; ctx.globals .insert(alias.name.name, LoweredGlobalDecl::Type(ty)); } } } + // Constant evaluation may leave abstract-typed literals and + // compositions in expression arenas, so we need to compact the module + // to remove unused expressions and types. + crate::compact::compact(&mut module); + Ok(module) } @@ -1441,10 +1466,25 @@ impl<'source, 'temp> Lowerer<'source, 'temp> { } /// Lower `expr` and apply the Load Rule if possible. + /// + /// For the time being, this concretizes abstract values, to support + /// consumers that haven't been adapted to consume them yet. Consumers + /// prepared for abstract values can call [`expression_for_abstract`]. + /// + /// [`expression_for_abstract`]: Lowerer::expression_for_abstract fn expression( &mut self, expr: Handle>, ctx: &mut ExpressionContext<'source, '_, '_>, + ) -> Result, Error<'source>> { + let expr = self.expression_for_abstract(expr, ctx)?; + ctx.concretize(expr) + } + + fn expression_for_abstract( + &mut self, + expr: Handle>, + ctx: &mut ExpressionContext<'source, '_, '_>, ) -> Result, Error<'source>> { let expr = self.expression_for_reference(expr, ctx)?; ctx.apply_load_rule(expr) @@ -1464,8 +1504,10 @@ impl<'source, 'temp> Lowerer<'source, 'temp> { ast::Literal::Number(Number::F32(f)) => crate::Literal::F32(f), ast::Literal::Number(Number::I32(i)) => crate::Literal::I32(i), ast::Literal::Number(Number::U32(u)) => crate::Literal::U32(u), - ast::Literal::Number(_) => { - unreachable!("got abstract numeric type when not expected"); + ast::Literal::Number(Number::F64(f)) => crate::Literal::F64(f), + ast::Literal::Number(Number::AbstractInt(i)) => crate::Literal::AbstractInt(i), + ast::Literal::Number(Number::AbstractFloat(f)) => { + crate::Literal::AbstractFloat(f) } ast::Literal::Bool(b) => crate::Literal::Bool(b), }; @@ -2513,10 +2555,19 @@ impl<'source, 'temp> Lowerer<'source, 'temp> { }) } - /// Return a Naga `Handle` representing the front-end type `handle`. - fn resolve_ast_type( + /// Build the Naga equivalent of a named AST type. + /// + /// Return a Naga `Handle` representing the front-end type + /// `handle`, which should be named `name`, if given. + /// + /// If `handle` refers to a type cached in [`SpecialTypes`], + /// `name` may be ignored. + /// + /// [`SpecialTypes`]: crate::SpecialTypes + fn resolve_named_ast_type( &mut self, handle: Handle>, + name: Option, ctx: &mut GlobalContext<'source, '_, '_>, ) -> Result, Error<'source>> { let inner = match ctx.types[handle] { @@ -2577,7 +2628,16 @@ impl<'source, 'temp> Lowerer<'source, 'temp> { } }; - Ok(ctx.ensure_type_exists(inner)) + Ok(ctx.ensure_type_exists(name, inner)) + } + + /// Return a Naga `Handle` representing the front-end type `handle`. + fn resolve_ast_type( + &mut self, + handle: Handle>, + ctx: &mut GlobalContext<'source, '_, '_>, + ) -> Result, Error<'source>> { + self.resolve_named_ast_type(handle, None, ctx) } fn binding( diff --git a/third_party/rust/naga/src/front/wgsl/parse/lexer.rs b/third_party/rust/naga/src/front/wgsl/parse/lexer.rs index dc229bb5fa309..9fa9416f111c3 100644 --- a/third_party/rust/naga/src/front/wgsl/parse/lexer.rs +++ b/third_party/rust/naga/src/front/wgsl/parse/lexer.rs @@ -448,6 +448,7 @@ impl<'a> Lexer<'a> { } #[cfg(test)] +#[track_caller] fn sub_test(source: &str, expected_tokens: &[Token]) { let mut lex = Lexer::new(source); for &token in expected_tokens { @@ -464,13 +465,13 @@ fn test_numbers() { sub_test( "0x123 0X123u 1u 123 0 0i 0x3f", &[ - Token::Number(Ok(Number::I32(291))), + Token::Number(Ok(Number::AbstractInt(291))), Token::Number(Ok(Number::U32(291))), Token::Number(Ok(Number::U32(1))), - Token::Number(Ok(Number::I32(123))), + Token::Number(Ok(Number::AbstractInt(123))), + Token::Number(Ok(Number::AbstractInt(0))), Token::Number(Ok(Number::I32(0))), - Token::Number(Ok(Number::I32(0))), - Token::Number(Ok(Number::I32(63))), + Token::Number(Ok(Number::AbstractInt(63))), ], ); // decimal floating point @@ -478,17 +479,17 @@ fn test_numbers() { "0.e+4f 01. .01 12.34 .0f 0h 1e-3 0xa.fp+2 0x1P+4f 0X.3 0x3p+2h 0X1.fp-4 0x3.2p+2h", &[ Token::Number(Ok(Number::F32(0.))), - Token::Number(Ok(Number::F32(1.))), - Token::Number(Ok(Number::F32(0.01))), - Token::Number(Ok(Number::F32(12.34))), + Token::Number(Ok(Number::AbstractFloat(1.))), + Token::Number(Ok(Number::AbstractFloat(0.01))), + Token::Number(Ok(Number::AbstractFloat(12.34))), Token::Number(Ok(Number::F32(0.))), Token::Number(Err(NumberError::UnimplementedF16)), - Token::Number(Ok(Number::F32(0.001))), - Token::Number(Ok(Number::F32(43.75))), + Token::Number(Ok(Number::AbstractFloat(0.001))), + Token::Number(Ok(Number::AbstractFloat(43.75))), Token::Number(Ok(Number::F32(16.))), - Token::Number(Ok(Number::F32(0.1875))), + Token::Number(Ok(Number::AbstractFloat(0.1875))), Token::Number(Err(NumberError::UnimplementedF16)), - Token::Number(Ok(Number::F32(0.12109375))), + Token::Number(Ok(Number::AbstractFloat(0.12109375))), Token::Number(Err(NumberError::UnimplementedF16)), ], ); @@ -624,18 +625,37 @@ fn test_numbers() { ); } +#[test] +fn double_floats() { + sub_test( + "0x1.2p4lf 0x1p8lf 0.0625lf 625e-4lf 10lf 10l", + &[ + Token::Number(Ok(Number::F64(18.0))), + Token::Number(Ok(Number::F64(256.0))), + Token::Number(Ok(Number::F64(0.0625))), + Token::Number(Ok(Number::F64(0.0625))), + Token::Number(Ok(Number::F64(10.0))), + Token::Number(Ok(Number::AbstractInt(10))), + Token::Word("l"), + ], + ) +} + #[test] fn test_tokens() { sub_test("id123_OK", &[Token::Word("id123_OK")]); sub_test( "92No", - &[Token::Number(Ok(Number::I32(92))), Token::Word("No")], + &[ + Token::Number(Ok(Number::AbstractInt(92))), + Token::Word("No"), + ], ); sub_test( "2u3o", &[ Token::Number(Ok(Number::U32(2))), - Token::Number(Ok(Number::I32(3))), + Token::Number(Ok(Number::AbstractInt(3))), Token::Word("o"), ], ); @@ -643,7 +663,7 @@ fn test_tokens() { "2.4f44po", &[ Token::Number(Ok(Number::F32(2.4))), - Token::Number(Ok(Number::I32(44))), + Token::Number(Ok(Number::AbstractInt(44))), Token::Word("po"), ], ); @@ -674,6 +694,24 @@ fn test_tokens() { Token::Operation('/'), ], ); + + // Type suffixes are only allowed on hex float literals + // if you provided an exponent. + sub_test( + "0x1.2f 0x1.2f 0x1.2h 0x1.2H 0x1.2lf", + &[ + // The 'f' suffixes are taken as a hex digit: + // the fractional part is 0x2f / 256. + Token::Number(Ok(Number::AbstractFloat(1.0 + 0x2f as f64 / 256.0))), + Token::Number(Ok(Number::AbstractFloat(1.0 + 0x2f as f64 / 256.0))), + Token::Number(Ok(Number::AbstractFloat(1.125))), + Token::Word("h"), + Token::Number(Ok(Number::AbstractFloat(1.125))), + Token::Word("H"), + Token::Number(Ok(Number::AbstractFloat(1.125))), + Token::Word("lf"), + ], + ) } #[test] @@ -684,7 +722,7 @@ fn test_variable_decl() { Token::Attribute, Token::Word("group"), Token::Paren('('), - Token::Number(Ok(Number::I32(0))), + Token::Number(Ok(Number::AbstractInt(0))), Token::Paren(')'), Token::Word("var"), Token::Paren('<'), diff --git a/third_party/rust/naga/src/front/wgsl/parse/number.rs b/third_party/rust/naga/src/front/wgsl/parse/number.rs index 57a2be61422a8..fde5e3cee6d47 100644 --- a/third_party/rust/naga/src/front/wgsl/parse/number.rs +++ b/third_party/rust/naga/src/front/wgsl/parse/number.rs @@ -16,39 +16,15 @@ pub enum Number { U32(u32), /// Concrete f32 F32(f32), -} - -impl Number { - /// Convert abstract numbers to a plausible concrete counterpart. - /// - /// Return concrete numbers unchanged. If the conversion would be - /// lossy, return an error. - fn abstract_to_concrete(self) -> Result { - match self { - Number::AbstractInt(num) => i32::try_from(num) - .map(Number::I32) - .map_err(|_| NumberError::NotRepresentable), - Number::AbstractFloat(num) => { - let num = num as f32; - if num.is_finite() { - Ok(Number::F32(num)) - } else { - Err(NumberError::NotRepresentable) - } - } - num => Ok(num), - } - } + /// Concrete f64 + F64(f64), } // TODO: when implementing Creation-Time Expressions, remove the ability to match the minus sign pub(in crate::front::wgsl) fn consume_number(input: &str) -> (Token<'_>, &str) { let (result, rest) = parse(input); - ( - Token::Number(result.and_then(Number::abstract_to_concrete)), - rest, - ) + (Token::Number(result), rest) } enum Kind { @@ -61,9 +37,11 @@ enum IntKind { U32, } +#[derive(Debug)] enum FloatKind { - F32, F16, + F32, + F64, } // The following regexes (from the WGSL spec) will be matched: @@ -104,9 +82,9 @@ fn parse(input: &str) -> (Result, &str) { /// if one of the given patterns are found at the start of the buffer /// returning the corresponding expr for the matched pattern macro_rules! consume_map { - ($bytes:ident, [$($pattern:pat_param => $to:expr),*]) => { + ($bytes:ident, [$( $($pattern:pat_param),* => $to:expr),* $(,)?]) => { match $bytes { - $( &[$pattern, ref rest @ ..] => { $bytes = rest; Some($to) }, )* + $( &[ $($pattern),*, ref rest @ ..] => { $bytes = rest; Some($to) }, )* _ => None, } }; @@ -136,6 +114,16 @@ fn parse(input: &str) -> (Result, &str) { }}; } + macro_rules! consume_float_suffix { + ($bytes:ident) => { + consume_map!($bytes, [ + b'h' => FloatKind::F16, + b'f' => FloatKind::F32, + b'l', b'f' => FloatKind::F64, + ]) + }; + } + /// maps the given `&[u8]` (tail of the initial `input: &str`) to a `&str` macro_rules! rest_to_str { ($bytes:ident) => { @@ -190,7 +178,7 @@ fn parse(input: &str) -> (Result, &str) { let number = general_extract.end(bytes); - let kind = consume_map!(bytes, [b'f' => FloatKind::F32, b'h' => FloatKind::F16]); + let kind = consume_float_suffix!(bytes); (parse_hex_float(number, kind), rest_to_str!(bytes)) } else { @@ -219,7 +207,7 @@ fn parse(input: &str) -> (Result, &str) { let exponent = exp_extract.end(bytes); - let kind = consume_map!(bytes, [b'f' => FloatKind::F32, b'h' => FloatKind::F16]); + let kind = consume_float_suffix!(bytes); ( parse_hex_float_missing_period(significand, exponent, kind), @@ -257,7 +245,7 @@ fn parse(input: &str) -> (Result, &str) { let number = general_extract.end(bytes); - let kind = consume_map!(bytes, [b'f' => FloatKind::F32, b'h' => FloatKind::F16]); + let kind = consume_float_suffix!(bytes); (parse_dec_float(number, kind), rest_to_str!(bytes)) } else { @@ -275,7 +263,7 @@ fn parse(input: &str) -> (Result, &str) { let number = general_extract.end(bytes); - let kind = consume_map!(bytes, [b'f' => FloatKind::F32, b'h' => FloatKind::F16]); + let kind = consume_float_suffix!(bytes); (parse_dec_float(number, kind), rest_to_str!(bytes)) } else { @@ -289,8 +277,9 @@ fn parse(input: &str) -> (Result, &str) { let kind = consume_map!(bytes, [ b'i' => Kind::Int(IntKind::I32), b'u' => Kind::Int(IntKind::U32), + b'h' => Kind::Float(FloatKind::F16), b'f' => Kind::Float(FloatKind::F32), - b'h' => Kind::Float(FloatKind::F16) + b'l', b'f' => Kind::Float(FloatKind::F64), ]); ( @@ -382,12 +371,17 @@ fn parse_hex_float(input: &str, kind: Option) -> Result Err(NumberError::NotRepresentable), }, + Some(FloatKind::F16) => Err(NumberError::UnimplementedF16), Some(FloatKind::F32) => match hexf_parse::parse_hexf32(input, false) { Ok(num) => Ok(Number::F32(num)), // can only be ParseHexfErrorKind::Inexact but we can't check since it's private _ => Err(NumberError::NotRepresentable), }, - Some(FloatKind::F16) => Err(NumberError::UnimplementedF16), + Some(FloatKind::F64) => match hexf_parse::parse_hexf64(input, false) { + Ok(num) => Ok(Number::F64(num)), + // can only be ParseHexfErrorKind::Inexact but we can't check since it's private + _ => Err(NumberError::NotRepresentable), + }, } } @@ -407,6 +401,12 @@ fn parse_dec_float(input: &str, kind: Option) -> Result { + let num = input.parse::().unwrap(); // will never fail + num.is_finite() + .then_some(Number::F64(num)) + .ok_or(NumberError::NotRepresentable) + } Some(FloatKind::F16) => Err(NumberError::UnimplementedF16), } } diff --git a/third_party/rust/naga/src/front/wgsl/tests.rs b/third_party/rust/naga/src/front/wgsl/tests.rs index 9e3ba2fab696f..eb2f8a2eb3680 100644 --- a/third_party/rust/naga/src/front/wgsl/tests.rs +++ b/third_party/rust/naga/src/front/wgsl/tests.rs @@ -76,7 +76,7 @@ fn parse_type_cast() { assert!(parse_str( " fn main() { - let x: vec2 = vec2(0); + let x: vec2 = vec2(0i, 0i); } ", ) @@ -313,7 +313,7 @@ fn parse_texture_load() { " var t: texture_3d; fn foo() { - let r: vec4 = textureLoad(t, vec3(0.0, 1.0, 2.0), 1); + let r: vec4 = textureLoad(t, vec3(0u, 1u, 2u), 1); } ", ) diff --git a/third_party/rust/naga/src/front/wgsl/to_wgsl.rs b/third_party/rust/naga/src/front/wgsl/to_wgsl.rs index cdfa1f0b1fdf9..c8331ace0959d 100644 --- a/third_party/rust/naga/src/front/wgsl/to_wgsl.rs +++ b/third_party/rust/naga/src/front/wgsl/to_wgsl.rs @@ -140,6 +140,8 @@ impl crate::Scalar { crate::ScalarKind::Uint => "u", crate::ScalarKind::Float => "f", crate::ScalarKind::Bool => return "bool".to_string(), + crate::ScalarKind::AbstractInt => return "{AbstractInt}".to_string(), + crate::ScalarKind::AbstractFloat => return "{AbstractFloat}".to_string(), }; format!("{}{}", prefix, self.width * 8) } diff --git a/third_party/rust/naga/src/lib.rs b/third_party/rust/naga/src/lib.rs index e140ad6aef220..b27ebc6764761 100644 --- a/third_party/rust/naga/src/lib.rs +++ b/third_party/rust/naga/src/lib.rs @@ -300,6 +300,9 @@ use serde::Serialize; /// Width of a boolean type, in bytes. pub const BOOL_WIDTH: Bytes = 1; +/// Width of abstract types, in bytes. +pub const ABSTRACT_WIDTH: Bytes = 8; + /// Hash map that is faster but not resilient to DoS attacks. pub type FastHashMap = rustc_hash::FxHashMap; /// Hash set that is faster but not resilient to DoS attacks. @@ -470,6 +473,16 @@ pub enum ScalarKind { Float, /// Boolean type. Bool, + + /// WGSL abstract integer type. + /// + /// These are forbidden by validation, and should never reach backends. + AbstractInt, + + /// Abstract floating-point type. + /// + /// These are forbidden by validation, and should never reach backends. + AbstractFloat, } /// Characteristics of a scalar type. @@ -871,6 +884,8 @@ pub enum Literal { I32(i32), I64(i64), Bool(bool), + AbstractInt(i64), + AbstractFloat(f64), } #[derive(Debug, PartialEq)] diff --git a/third_party/rust/naga/src/proc/constant_evaluator.rs b/third_party/rust/naga/src/proc/constant_evaluator.rs index d401b1e4de8a8..826cb1da0dc10 100644 --- a/third_party/rust/naga/src/proc/constant_evaluator.rs +++ b/third_party/rust/naga/src/proc/constant_evaluator.rs @@ -141,8 +141,8 @@ pub enum ConstantEvaluatorError { InvalidAccessIndexTy, #[error("Constants don't support array length expressions")] ArrayLength, - #[error("Cannot cast type")] - InvalidCastArg, + #[error("Cannot cast type `{from}` to `{to}`")] + InvalidCastArg { from: String, to: String }, #[error("Cannot apply the unary op to the argument")] InvalidUnaryOpArg, #[error("Cannot apply the binary op to the arguments")] @@ -167,6 +167,15 @@ pub enum ConstantEvaluatorError { NotImplemented(String), #[error("{0} operation overflowed")] Overflow(String), + #[error( + "the concrete type `{to_type}` cannot represent the abstract value `{value}` accurately" + )] + AutomaticConversionLossy { + value: String, + to_type: &'static str, + }, + #[error("abstract floating-point values cannot be automatically converted to integers")] + AutomaticConversionFloatToInt { to_type: &'static str }, #[error("Division by zero")] DivisionByZero, #[error("Remainder by zero")] @@ -268,6 +277,17 @@ impl<'a> ConstantEvaluator<'a> { } } + pub fn to_ctx(&self) -> crate::proc::GlobalCtx { + crate::proc::GlobalCtx { + types: self.types, + constants: self.constants, + const_expressions: match self.function_local_data { + Some(ref data) => data.const_expressions, + None => self.expressions, + }, + } + } + fn check(&self, expr: Handle) -> Result<(), ConstantEvaluatorError> { if let Some(ref function_local_data) = self.function_local_data { if !function_local_data.expression_constness.is_const(expr) { @@ -968,6 +988,22 @@ impl<'a> ConstantEvaluator<'a> { let expr = self.eval_zero_value(expr, span)?; + let make_error = || -> Result<_, ConstantEvaluatorError> { + let ty = self.resolve_type(expr)?; + + #[cfg(feature = "wgsl-in")] + let from = ty.to_wgsl(&self.to_ctx()); + #[cfg(feature = "wgsl-in")] + let to = target.to_wgsl(); + + #[cfg(not(feature = "wgsl-in"))] + let from = format!("{ty:?}"); + #[cfg(not(feature = "wgsl-in"))] + let to = format!("{target:?}"); + + Err(ConstantEvaluatorError::InvalidCastArg { from, to }) + }; + let expr = match self.expressions[expr] { Expression::Literal(literal) => { let literal = match target { @@ -977,8 +1013,10 @@ impl<'a> ConstantEvaluator<'a> { Literal::F32(v) => v as i32, Literal::Bool(v) => v as i32, Literal::F64(_) | Literal::I64(_) => { - return Err(ConstantEvaluatorError::InvalidCastArg) + return make_error(); } + Literal::AbstractInt(v) => i32::try_from_abstract(v)?, + Literal::AbstractFloat(v) => i32::try_from_abstract(v)?, }), Sc::U32 => Literal::U32(match literal { Literal::I32(v) => v as u32, @@ -986,8 +1024,10 @@ impl<'a> ConstantEvaluator<'a> { Literal::F32(v) => v as u32, Literal::Bool(v) => v as u32, Literal::F64(_) | Literal::I64(_) => { - return Err(ConstantEvaluatorError::InvalidCastArg) + return make_error(); } + Literal::AbstractInt(v) => u32::try_from_abstract(v)?, + Literal::AbstractFloat(v) => u32::try_from_abstract(v)?, }), Sc::F32 => Literal::F32(match literal { Literal::I32(v) => v as f32, @@ -995,19 +1035,48 @@ impl<'a> ConstantEvaluator<'a> { Literal::F32(v) => v, Literal::Bool(v) => v as u32 as f32, Literal::F64(_) | Literal::I64(_) => { - return Err(ConstantEvaluatorError::InvalidCastArg) + return make_error(); } + Literal::AbstractInt(v) => f32::try_from_abstract(v)?, + Literal::AbstractFloat(v) => f32::try_from_abstract(v)?, + }), + Sc::F64 => Literal::F64(match literal { + Literal::I32(v) => v as f64, + Literal::U32(v) => v as f64, + Literal::F32(v) => v as f64, + Literal::F64(v) => v, + Literal::Bool(v) => v as u32 as f64, + Literal::I64(_) => return make_error(), + Literal::AbstractInt(v) => f64::try_from_abstract(v)?, + Literal::AbstractFloat(v) => f64::try_from_abstract(v)?, }), Sc::BOOL => Literal::Bool(match literal { Literal::I32(v) => v != 0, Literal::U32(v) => v != 0, Literal::F32(v) => v != 0.0, Literal::Bool(v) => v, - Literal::F64(_) | Literal::I64(_) => { - return Err(ConstantEvaluatorError::InvalidCastArg) + Literal::F64(_) + | Literal::I64(_) + | Literal::AbstractInt(_) + | Literal::AbstractFloat(_) => { + return make_error(); + } + }), + Sc::ABSTRACT_FLOAT => Literal::AbstractFloat(match literal { + Literal::AbstractInt(v) => { + // Overflow is forbidden, but inexact conversions + // are fine. The range of f64 is far larger than + // that of i64, so we don't have to check anything + // here. + v as f64 } + Literal::AbstractFloat(v) => v, + _ => return make_error(), }), - _ => return Err(ConstantEvaluatorError::InvalidCastArg), + _ => { + log::debug!("Constant evaluator refused to convert value to {target:?}"); + return make_error(); + } }; Expression::Literal(literal) } @@ -1025,7 +1094,7 @@ impl<'a> ConstantEvaluator<'a> { rows, scalar: target, }, - _ => return Err(ConstantEvaluatorError::InvalidCastArg), + _ => return make_error(), }; let mut components = src_components.clone(); @@ -1051,12 +1120,70 @@ impl<'a> ConstantEvaluator<'a> { value: cast_value, } } - _ => return Err(ConstantEvaluatorError::InvalidCastArg), + _ => return make_error(), }; self.register_evaluated_expr(expr, span) } + /// Convert the scalar leaves of `expr` to `target`, handling arrays. + /// + /// `expr` must be a `Compose` expression whose type is a scalar, vector, + /// matrix, or nested arrays of such. + /// + /// This is basically the same as the [`cast`] method, except that that + /// should only handle Naga [`As`] expressions, which cannot convert arrays. + /// + /// Treat `span` as the location of the resulting expression. + /// + /// [`cast`]: ConstantEvaluator::cast + /// [`As`]: crate::Expression::As + pub fn cast_array( + &mut self, + expr: Handle, + target: crate::Scalar, + span: Span, + ) -> Result, ConstantEvaluatorError> { + let Expression::Compose { ty, ref components } = self.expressions[expr] else { + return self.cast(expr, target, span); + }; + + let crate::TypeInner::Array { base: _, size, stride: _ } = self.types[ty].inner else { + return self.cast(expr, target, span); + }; + + let mut components = components.clone(); + for component in &mut components { + *component = self.cast_array(*component, target, span)?; + } + + let first = components.first().unwrap(); + let new_base = match self.resolve_type(*first)? { + crate::proc::TypeResolution::Handle(ty) => ty, + crate::proc::TypeResolution::Value(inner) => { + self.types.insert(Type { name: None, inner }, span) + } + }; + let new_base_stride = self.types[new_base].inner.size(self.to_ctx()); + let new_array_ty = self.types.insert( + Type { + name: None, + inner: TypeInner::Array { + base: new_base, + size, + stride: new_base_stride, + }, + }, + span, + ); + + let compose = Expression::Compose { + ty: new_array_ty, + components, + }; + self.register_evaluated_expr(compose, span) + } + fn unary_op( &mut self, op: UnaryOperator, @@ -1311,6 +1438,28 @@ impl<'a> ConstantEvaluator<'a> { Ok(self.expressions.append(expr, span)) } } + + fn resolve_type( + &self, + expr: Handle, + ) -> Result { + use crate::proc::TypeResolution as Tr; + use crate::Expression as Ex; + let resolution = match self.expressions[expr] { + Ex::Literal(ref literal) => Tr::Value(literal.ty_inner()), + Ex::Constant(c) => Tr::Handle(self.constants[c].ty), + Ex::ZeroValue(ty) | Ex::Compose { ty, .. } => Tr::Handle(ty), + Ex::Splat { size, value } => { + let Tr::Value(TypeInner::Scalar(scalar)) = self.resolve_type(value)? else { + return Err(ConstantEvaluatorError::SplatScalarOnly); + }; + Tr::Value(TypeInner::Vector { scalar, size }) + } + _ => return Err(ConstantEvaluatorError::SubexpressionsAreNotConstant), + }; + + Ok(resolution) + } } #[cfg(test)] @@ -1820,3 +1969,92 @@ mod tests { } } } + +/// Trait for conversions of abstract values to concrete types. +trait TryFromAbstract: Sized { + /// Convert an abstract literal `value` to `Self`. + /// + /// Since Naga's `AbstractInt` and `AbstractFloat` exist to support + /// WGSL, we follow WGSL's conversion rules here: + /// + /// - WGSL §6.1.2. Conversion Rank says that automatic conversions + /// to integers are either lossless or an error. + /// + /// - WGSL §14.6.4 Floating Point Conversion says that conversions + /// to floating point in constant expressions and override + /// expressions are errors if the value is out of range for the + /// destination type, but rounding is okay. + /// + /// [`AbstractInt`]: crate::Literal::AbstractInt + /// [`Float`]: crate::Literal::Float + fn try_from_abstract(value: T) -> Result; +} + +impl TryFromAbstract for i32 { + fn try_from_abstract(value: i64) -> Result { + i32::try_from(value).map_err(|_| ConstantEvaluatorError::AutomaticConversionLossy { + value: format!("{value:?}"), + to_type: "i32", + }) + } +} + +impl TryFromAbstract for u32 { + fn try_from_abstract(value: i64) -> Result { + u32::try_from(value).map_err(|_| ConstantEvaluatorError::AutomaticConversionLossy { + value: format!("{value:?}"), + to_type: "u32", + }) + } +} + +impl TryFromAbstract for f32 { + fn try_from_abstract(value: i64) -> Result { + let f = value as f32; + // The range of `i64` is roughly ±18 × 10¹⁸, whereas the range of + // `f32` is roughly ±3.4 × 10³⁸, so there's no opportunity for + // overflow here. + Ok(f) + } +} + +impl TryFromAbstract for f32 { + fn try_from_abstract(value: f64) -> Result { + let f = value as f32; + if f.is_infinite() { + return Err(ConstantEvaluatorError::AutomaticConversionLossy { + value: format!("{value:?}"), + to_type: "f32", + }); + } + Ok(f) + } +} + +impl TryFromAbstract for f64 { + fn try_from_abstract(value: i64) -> Result { + let f = value as f64; + // The range of `i64` is roughly ±18 × 10¹⁸, whereas the range of + // `f64` is roughly ±1.8 × 10³⁰⁸, so there's no opportunity for + // overflow here. + Ok(f) + } +} + +impl TryFromAbstract for f64 { + fn try_from_abstract(value: f64) -> Result { + Ok(value) + } +} + +impl TryFromAbstract for i32 { + fn try_from_abstract(_: f64) -> Result { + Err(ConstantEvaluatorError::AutomaticConversionFloatToInt { to_type: "i32" }) + } +} + +impl TryFromAbstract for u32 { + fn try_from_abstract(_: f64) -> Result { + Err(ConstantEvaluatorError::AutomaticConversionFloatToInt { to_type: "u32" }) + } +} diff --git a/third_party/rust/naga/src/proc/mod.rs b/third_party/rust/naga/src/proc/mod.rs index 4f2f5c705d162..e375bb1af3120 100644 --- a/third_party/rust/naga/src/proc/mod.rs +++ b/third_party/rust/naga/src/proc/mod.rs @@ -71,7 +71,11 @@ impl From for super::ScalarKind { impl super::ScalarKind { pub const fn is_numeric(self) -> bool { match self { - crate::ScalarKind::Sint | crate::ScalarKind::Uint | crate::ScalarKind::Float => true, + crate::ScalarKind::Sint + | crate::ScalarKind::Uint + | crate::ScalarKind::Float + | crate::ScalarKind::AbstractInt + | crate::ScalarKind::AbstractFloat => true, crate::ScalarKind::Bool => false, } } @@ -102,6 +106,14 @@ impl super::Scalar { kind: crate::ScalarKind::Bool, width: crate::BOOL_WIDTH, }; + pub const ABSTRACT_INT: Self = Self { + kind: crate::ScalarKind::AbstractInt, + width: crate::ABSTRACT_WIDTH, + }; + pub const ABSTRACT_FLOAT: Self = Self { + kind: crate::ScalarKind::AbstractFloat, + width: crate::ABSTRACT_WIDTH, + }; /// Construct a float `Scalar` with the given width. /// @@ -144,7 +156,7 @@ impl Eq for crate::Literal {} impl std::hash::Hash for crate::Literal { fn hash(&self, hasher: &mut H) { match *self { - Self::F64(v) => { + Self::F64(v) | Self::AbstractFloat(v) => { hasher.write_u8(0); v.to_bits().hash(hasher); } @@ -164,7 +176,7 @@ impl std::hash::Hash for crate::Literal { hasher.write_u8(4); v.hash(hasher); } - Self::I64(v) => { + Self::I64(v) | Self::AbstractInt(v) => { hasher.write_u8(5); v.hash(hasher); } @@ -198,7 +210,8 @@ impl crate::Literal { match *self { Self::F64(_) | Self::I64(_) => 8, Self::F32(_) | Self::U32(_) | Self::I32(_) => 4, - Self::Bool(_) => 1, + Self::Bool(_) => crate::BOOL_WIDTH, + Self::AbstractInt(_) | Self::AbstractFloat(_) => crate::ABSTRACT_WIDTH, } } pub const fn scalar(&self) -> crate::Scalar { @@ -209,6 +222,8 @@ impl crate::Literal { Self::I32(_) => crate::Scalar::I32, Self::I64(_) => crate::Scalar::I64, Self::Bool(_) => crate::Scalar::BOOL, + Self::AbstractInt(_) => crate::Scalar::ABSTRACT_INT, + Self::AbstractFloat(_) => crate::Scalar::ABSTRACT_FLOAT, } } pub const fn scalar_kind(&self) -> crate::ScalarKind { @@ -222,6 +237,10 @@ impl crate::Literal { pub const POINTER_SPAN: u32 = 4; impl super::TypeInner { + /// Return the scalar type of `self`. + /// + /// If `inner` is a scalar, vector, or matrix type, return + /// its scalar type. Otherwise, return `None`. pub const fn scalar(&self) -> Option { use crate::TypeInner as Ti; match *self { diff --git a/third_party/rust/naga/src/valid/expression.rs b/third_party/rust/naga/src/valid/expression.rs index 1f57c55441f9c..c82d60f062870 100644 --- a/third_party/rust/naga/src/valid/expression.rs +++ b/third_party/rust/naga/src/valid/expression.rs @@ -671,7 +671,7 @@ impl super::Validator { Bo::Add | Bo::Subtract => match *left_inner { Ti::Scalar(scalar) | Ti::Vector { scalar, .. } => match scalar.kind { Sk::Uint | Sk::Sint | Sk::Float => left_inner == right_inner, - Sk::Bool => false, + Sk::Bool | Sk::AbstractInt | Sk::AbstractFloat => false, }, Ti::Matrix { .. } => left_inner == right_inner, _ => false, @@ -679,14 +679,14 @@ impl super::Validator { Bo::Divide | Bo::Modulo => match *left_inner { Ti::Scalar(scalar) | Ti::Vector { scalar, .. } => match scalar.kind { Sk::Uint | Sk::Sint | Sk::Float => left_inner == right_inner, - Sk::Bool => false, + Sk::Bool | Sk::AbstractInt | Sk::AbstractFloat => false, }, _ => false, }, Bo::Multiply => { let kind_allowed = match left_inner.scalar_kind() { Some(Sk::Uint | Sk::Sint | Sk::Float) => true, - Some(Sk::Bool) | None => false, + Some(Sk::Bool | Sk::AbstractInt | Sk::AbstractFloat) | None => false, }; let types_match = match (left_inner, right_inner) { // Straight scalar and mixed scalar/vector. @@ -763,7 +763,7 @@ impl super::Validator { match *left_inner { Ti::Scalar(scalar) | Ti::Vector { scalar, .. } => match scalar.kind { Sk::Uint | Sk::Sint | Sk::Float => left_inner == right_inner, - Sk::Bool => false, + Sk::Bool | Sk::AbstractInt | Sk::AbstractFloat => false, }, ref other => { log::error!("Op {:?} left type {:?}", op, other); @@ -785,7 +785,7 @@ impl super::Validator { Bo::And | Bo::InclusiveOr => match *left_inner { Ti::Scalar(scalar) | Ti::Vector { scalar, .. } => match scalar.kind { Sk::Bool | Sk::Sint | Sk::Uint => left_inner == right_inner, - Sk::Float => false, + Sk::Float | Sk::AbstractInt | Sk::AbstractFloat => false, }, ref other => { log::error!("Op {:?} left type {:?}", op, other); @@ -795,7 +795,7 @@ impl super::Validator { Bo::ExclusiveOr => match *left_inner { Ti::Scalar(scalar) | Ti::Vector { scalar, .. } => match scalar.kind { Sk::Sint | Sk::Uint => left_inner == right_inner, - Sk::Bool | Sk::Float => false, + Sk::Bool | Sk::Float | Sk::AbstractInt | Sk::AbstractFloat => false, }, ref other => { log::error!("Op {:?} left type {:?}", op, other); @@ -824,7 +824,7 @@ impl super::Validator { }; match base_scalar.kind { Sk::Sint | Sk::Uint => base_size.is_ok() && base_size == shift_size, - Sk::Float | Sk::Bool => false, + Sk::Float | Sk::AbstractInt | Sk::AbstractFloat | Sk::Bool => false, } } }; diff --git a/third_party/rust/naga/src/valid/function.rs b/third_party/rust/naga/src/valid/function.rs index f5da7d0764f59..3b12e59067671 100644 --- a/third_party/rust/naga/src/valid/function.rs +++ b/third_party/rust/naga/src/valid/function.rs @@ -112,7 +112,7 @@ pub enum FunctionError { InvalidStorePointer(Handle), #[error("The value {0:?} can not be stored")] InvalidStoreValue(Handle), - #[error("Store of {value:?} into {pointer:?} doesn't have matching types")] + #[error("The type of {value:?} doesn't match the type stored in {pointer:?}")] InvalidStoreTypes { pointer: Handle, value: Handle, diff --git a/third_party/rust/naga/src/valid/type.rs b/third_party/rust/naga/src/valid/type.rs index 53462fe80130f..1e3e03fe198a4 100644 --- a/third_party/rust/naga/src/valid/type.rs +++ b/third_party/rust/naga/src/valid/type.rs @@ -143,6 +143,9 @@ pub enum WidthError { #[error("64-bit integers are not yet supported")] Unsupported64Bit, + + #[error("Abstract types may only appear in constant expressions")] + Abstract, } // Only makes sense if `flags.contains(HOST_SHAREABLE)` @@ -248,6 +251,9 @@ impl super::Validator { } scalar.width == 4 } + crate::ScalarKind::AbstractInt | crate::ScalarKind::AbstractFloat => { + return Err(WidthError::Abstract); + } }; if good { Ok(()) @@ -325,7 +331,10 @@ impl super::Validator { } Ti::Atomic(crate::Scalar { kind, width }) => { let good = match kind { - crate::ScalarKind::Bool | crate::ScalarKind::Float => false, + crate::ScalarKind::Bool + | crate::ScalarKind::Float + | crate::ScalarKind::AbstractInt + | crate::ScalarKind::AbstractFloat => false, crate::ScalarKind::Sint | crate::ScalarKind::Uint => width == 4, }; if !good { diff --git a/third_party/rust/wgpu-core/.cargo-checksum.json b/third_party/rust/wgpu-core/.cargo-checksum.json index 3c05ea383dda5..cdc6e2013d442 100644 --- a/third_party/rust/wgpu-core/.cargo-checksum.json +++ b/third_party/rust/wgpu-core/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"bde42e04a69f912ac871368e202df8af116ea0ef010a2f08a62388b6985ca61f","LICENSE.APACHE":"a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9","LICENSE.MIT":"c7fea58d1cfe49634cd92e54fc10a9d871f4b275321a4cd8c09e449122caaeb4","src/any_surface.rs":"1afed4e5e2cc1726c9887bfbf8805f9141f859615c1eaf90f4ef3e49850caf06","src/binding_model.rs":"d7add33189aa453ad19acd8ac38465f44e233d0e8da42be5a3aadfc50a87a491","src/command/bind.rs":"85bbab812222f9bc11893059304cac850616818b00857fadac4885b978e4cfe2","src/command/bundle.rs":"7836b3740ad32168fdfb4241dbc91839d695c019abd3c38e3decec332b7e82c2","src/command/clear.rs":"65499812d269e23efb12a12a455f58f52f3014f8db224d02951b7331638f6ad4","src/command/compute.rs":"296864d4f9e9a98f368d64910146480e38e2f895eee98a97d947dd593033f87c","src/command/draw.rs":"3687cbde422a29f28c1c3d17e132d912b3b4b2bcc98efca68d1ee0d563a5bf56","src/command/memory_init.rs":"ffe5c301f19a17285523ee8fd5e7bf5abd5e50e9a3716f5713ac99ab135d9f5e","src/command/mod.rs":"e7c5e83a1b6398e68279b10910f426d7dde1ce3c800752bb88688b37f69b7872","src/command/query.rs":"f31db3f1282109baa59e6dcd7b2e674c7858a2c64f58fc6eb3a4d0c546935af5","src/command/render.rs":"0b9a8804de0a85d3b4c593df2da78ce5d6c3e53169b05ca9babd3ec984cbe9f7","src/command/transfer.rs":"49dd1261e3ad1effc4ebdad1bc3061f4330f991b8291df75591a1e2bc5eaa257","src/conv.rs":"7e3ffe33b47a6fd3617aabf9f11cc68f1ccbee2c7343b8dbbcd0e8f3447e1ad8","src/device/any_device.rs":"2cb2be0fd078d65039692d309d8688cf4a02fb768579cf22c93cfa514d20ad7f","src/device/global.rs":"3be88717a7d164ea73842f90b93c359f8ea06bbae253af9a195734640d5a830d","src/device/life.rs":"6c2b2e7f98f71231c97f19cf19c4d8ff254ee9862a8422f973270656658aed96","src/device/mod.rs":"9bae0d30eaf51af5545eea10d5c8af6ca3ced2518d24c42880ec3c8f1f7664b2","src/device/queue.rs":"aec77faebaa750f843f2f04ea9a2021598098783f16f95e739bc64fabcc29619","src/device/resource.rs":"0e707723d58cecfb402fe35eb9944278de96a95496bd2e62b50a71ef3e44d079","src/device/trace.rs":"21408dfd2c99e3ce36a77d08ba86cf52f32bb376ed82690bbbf74937bfd42cbe","src/error.rs":"32680e922acfb1f1d6842177179768d365c575a8baa402da9d5a43a2357b0dbf","src/global.rs":"fd2a7995bdb64f1186fd71c4f6b59f34c543ee695912b1fad7931c88ec024584","src/hal_api.rs":"bb380df266fa9754c93d55c24b1a3535629710eb04bc6858a40c38a5f02aae68","src/hub.rs":"d9435f5b12f47e0b57599dce1d38e6eb4ef2477ab634806cfccefa4c1541f87b","src/id.rs":"4684c40d56ad8f49f36455ea84f2901df587fc3574274ac132b8236ece6926a3","src/identity.rs":"0701f6f41e754dde2bebc567a87c25b353dfab40b79a322990dbfa477739ab8c","src/init_tracker/buffer.rs":"61eb9cfaa312135b7a937ff6a3117f531b5b7323fae6553a41d6de9bc106d7e0","src/init_tracker/mod.rs":"0867f79f83555390d0982d1dc6dcf0d4340e10cb89aa633d3c3ecc45deb3c78c","src/init_tracker/texture.rs":"030fd594bf9948fad391390d85c5e1fec7eaf67b6e812c60f2dd59bc4fda8fd5","src/instance.rs":"643ce09d9a623f00e66e1eb50b2facc4d072f4149c9953343c1b0e8c4a5f6915","src/lib.rs":"23ac375edd02c7808ccb901b392bb34960339027b2e068b9009f89d413946515","src/pipeline.rs":"e09adc811a7553daa4d826fd6001be14a7d21222fc8ba76040d4fd5c0f017787","src/present.rs":"5a15e583ee2b4c1afcf596c8429437a50e9fd1e17f8fbf4fafb482928940815e","src/registry.rs":"52a52b0ed41abbed3c6a84f0fb01c5f45c75953bacaa7a9b9bdb95a8825eb573","src/resource.rs":"14a3fedcf422688dc484c91abc5b2522c388fd5587c61e11a4b0bd882284fb24","src/storage.rs":"343811d28ed0926ef2d7f116d5ad8b4b6b6f530d7dfb5b9afbb90f2bb3ccfbc1","src/track/buffer.rs":"2e37fdae4e3b81f4e9d4bc35d71849ce82846afbb55c3de75c5db101c888e216","src/track/metadata.rs":"8ef7af1d0152a3a8d706402a416c2e74c9282354cad055d2c0c527486cb3019e","src/track/mod.rs":"028b04676f8a42a1f67bb9f6ffb809f56fa6349596b52561bce5b78c176e51e7","src/track/range.rs":"5bbfed6e103b3234d9de8e42057022da6d628c2cc1db6bb51b88f87f2d8adf8b","src/track/stateless.rs":"57f13386f0829cd6e1a894e454f69929eea7494565e530ed9f80bd7d50a4ba2d","src/track/texture.rs":"ea8ba2089e72401dcd37738d0583c411ec100a7436626f738d8d81bc188cbd99","src/validation.rs":"0ca7fe772c06f788bd758e720d35e5664ffe69188922c7a1981f3855206e200b"},"package":null} \ No newline at end of file +{"files":{"Cargo.toml":"5119648ea52e97ad3fa2f0f24cc30e0b305fe81f710a33396bdadaf7397d41b9","LICENSE.APACHE":"a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9","LICENSE.MIT":"c7fea58d1cfe49634cd92e54fc10a9d871f4b275321a4cd8c09e449122caaeb4","src/any_surface.rs":"1afed4e5e2cc1726c9887bfbf8805f9141f859615c1eaf90f4ef3e49850caf06","src/binding_model.rs":"b709658ed6b9af2ed07ff77b8da64912cd26a9d7caaecee26c77a92efdc615d4","src/command/bind.rs":"85bbab812222f9bc11893059304cac850616818b00857fadac4885b978e4cfe2","src/command/bundle.rs":"7836b3740ad32168fdfb4241dbc91839d695c019abd3c38e3decec332b7e82c2","src/command/clear.rs":"8929095abd1508fdbc4b51db1bcfe513f77954fcfb269888c91b47c90b943c03","src/command/compute.rs":"296864d4f9e9a98f368d64910146480e38e2f895eee98a97d947dd593033f87c","src/command/draw.rs":"3687cbde422a29f28c1c3d17e132d912b3b4b2bcc98efca68d1ee0d563a5bf56","src/command/memory_init.rs":"ffe5c301f19a17285523ee8fd5e7bf5abd5e50e9a3716f5713ac99ab135d9f5e","src/command/mod.rs":"9ffa26b0306067ad63fc61fbde985ad98d495a2ad739f51bf54a39f702f45d3a","src/command/query.rs":"f31db3f1282109baa59e6dcd7b2e674c7858a2c64f58fc6eb3a4d0c546935af5","src/command/render.rs":"61a9f34d813700606b49224d9de19773c49eb3dd42fa4027357a334dc63e2579","src/command/transfer.rs":"60969f020bddfb88a0c3b459b72b94d3a9a96cc635d20e88d016765d0fb94ba5","src/conv.rs":"7e3ffe33b47a6fd3617aabf9f11cc68f1ccbee2c7343b8dbbcd0e8f3447e1ad8","src/device/any_device.rs":"2cb2be0fd078d65039692d309d8688cf4a02fb768579cf22c93cfa514d20ad7f","src/device/global.rs":"33c47e5aaa44ad4a485a996af52247e765bedfa18724ab7662ce34c78754448b","src/device/life.rs":"bbda212777bf5156feb9ee4c46d7c7621888c11544903a26bf86e7b708590f5a","src/device/mod.rs":"4ec88e037307e597fc661c85c9fa28f2d70a82a222a5fec5c97c450d33224f37","src/device/queue.rs":"9525b939e49b4c2860928c04a660a4556b34bfbed23e00318635a5ad46bce061","src/device/resource.rs":"a47f4d8b605c477fc6a63058e1340872590631c9a1a7f4e454bbbbe01aada757","src/device/trace.rs":"9a8ec674567a8866a6bd1ed2ad06e474bd2504ed91f228d3040cb6db18fe5f2b","src/error.rs":"32680e922acfb1f1d6842177179768d365c575a8baa402da9d5a43a2357b0dbf","src/global.rs":"9aa9448791477007b850c5eb1584e7c74c14fe43ac47ab3b5f29373850f463ee","src/hal_api.rs":"bb380df266fa9754c93d55c24b1a3535629710eb04bc6858a40c38a5f02aae68","src/hub.rs":"d9435f5b12f47e0b57599dce1d38e6eb4ef2477ab634806cfccefa4c1541f87b","src/id.rs":"0aa4258f93e05f6991385980a553e67892a0f1769e37624ae0466f83161af697","src/identity.rs":"0701f6f41e754dde2bebc567a87c25b353dfab40b79a322990dbfa477739ab8c","src/init_tracker/buffer.rs":"61eb9cfaa312135b7a937ff6a3117f531b5b7323fae6553a41d6de9bc106d7e0","src/init_tracker/mod.rs":"0867f79f83555390d0982d1dc6dcf0d4340e10cb89aa633d3c3ecc45deb3c78c","src/init_tracker/texture.rs":"030fd594bf9948fad391390d85c5e1fec7eaf67b6e812c60f2dd59bc4fda8fd5","src/instance.rs":"46b13911e15310a7ced4e5f13eeaa5d2cde7762b8ffa282a28d0c812e7036458","src/lib.rs":"9408b33250c7062599045cc11dd1f52d6036415f0e5c568b37c73348b330bb7c","src/pipeline.rs":"1d615e582254cfa108dd1925df7b6b0ae0c9845714b1351b8bcd4c7aa4b4dd69","src/present.rs":"1c28d6dbc3125b5eebd12265013618d8585d5c90f3fd1d3529c20e41e1ddecb3","src/registry.rs":"e93369ae372b133649b554a3d0338d74823cfded8b7e84d01bf1f000b670f471","src/resource.rs":"be6b9b648911c2277d9f88ca9e9a2811ec28fdf8118e009a47de0c16179f28aa","src/storage.rs":"6ba6416522ba2f1d2a279c220960aabdfb071c4e0ade888c8cbc2b91325c4203","src/track/buffer.rs":"a6762fad8bf5b257d37fb8844f0ee44ecb04f052c58655404b8af0036ac929e5","src/track/metadata.rs":"f8994ad91db7f3bb1b7f8b8b0f6884753d733ce28238b36f31da2230706f848e","src/track/mod.rs":"5fdef0bcf20999fda97342e261341809394dcad3ee97e2bc2429c5a1e41d48d5","src/track/range.rs":"5bbfed6e103b3234d9de8e42057022da6d628c2cc1db6bb51b88f87f2d8adf8b","src/track/stateless.rs":"65142de8e8425eee26e32bfef8169af3ed0e98455d5e470517717a3c15e8036c","src/track/texture.rs":"d4e92ef3400cf48b2e76d8b7c1e4c6a1cef0d3d060c6abdb46b9a3b386bc9dc9","src/validation.rs":"4bd36b7b02ad0122fda719790d40cc68058e0f8e3ba3cd622f1d76db377320f9"},"package":null} \ No newline at end of file diff --git a/third_party/rust/wgpu-core/Cargo.toml b/third_party/rust/wgpu-core/Cargo.toml index 206e1304e18d8..40858e00e4fff 100644 --- a/third_party/rust/wgpu-core/Cargo.toml +++ b/third_party/rust/wgpu-core/Cargo.toml @@ -81,6 +81,7 @@ path = "../wgpu-types" package = "wgpu-types" [features] +api_log_info = [] default = ["link"] dx11 = ["hal/dx11"] dx12 = ["hal/dx12"] @@ -99,6 +100,7 @@ replay = [ "arrayvec/serde", "naga/deserialize", ] +resource_log_info = [] serial-pass = [ "serde", "wgt/serde", @@ -116,7 +118,7 @@ vulkan = ["hal/vulkan"] wgsl = ["naga/wgsl-in"] [target."cfg(all(target_arch = \"wasm32\", not(target_os = \"emscripten\")))".dependencies.web-sys] -version = "0.3.64" +version = "0.3.66" features = [ "HtmlCanvasElement", "OffscreenCanvas", diff --git a/third_party/rust/wgpu-core/src/binding_model.rs b/third_party/rust/wgpu-core/src/binding_model.rs index 5f973da66237a..826e4c9bc8b2f 100644 --- a/third_party/rust/wgpu-core/src/binding_model.rs +++ b/third_party/rust/wgpu-core/src/binding_model.rs @@ -8,6 +8,7 @@ use crate::{ }, init_tracker::{BufferInitTrackerAction, TextureInitTrackerAction}, resource::{Resource, ResourceInfo, ResourceType}, + resource_log, track::{BindGroupStates, UsageConflict}, validation::{MissingBufferUsageError, MissingTextureUsageError}, FastHashMap, Label, @@ -465,8 +466,8 @@ pub struct BindGroupLayout { impl Drop for BindGroupLayout { fn drop(&mut self) { - log::info!("Destroying BindGroupLayout {:?}", self.info.label()); if let Some(raw) = self.raw.take() { + resource_log!("Destroy raw BindGroupLayout {}", self.info.label()); unsafe { use hal::Device; self.device.raw().destroy_bind_group_layout(raw); @@ -606,8 +607,8 @@ pub struct PipelineLayout { impl Drop for PipelineLayout { fn drop(&mut self) { - log::info!("Destroying PipelineLayout {:?}", self.info.label()); if let Some(raw) = self.raw.take() { + resource_log!("Destroy raw PipelineLayout {}", self.info.label()); unsafe { use hal::Device; self.device.raw().destroy_pipeline_layout(raw); @@ -827,8 +828,8 @@ pub struct BindGroup { impl Drop for BindGroup { fn drop(&mut self) { - log::info!("Destroying BindGroup {:?}", self.info.label()); if let Some(raw) = self.raw.take() { + resource_log!("Destroy raw BindGroup {}", self.info.label()); unsafe { use hal::Device; self.device.raw().destroy_bind_group(raw); diff --git a/third_party/rust/wgpu-core/src/command/clear.rs b/third_party/rust/wgpu-core/src/command/clear.rs index b702c25c67f3b..620911c181dad 100644 --- a/third_party/rust/wgpu-core/src/command/clear.rs +++ b/third_party/rust/wgpu-core/src/command/clear.rs @@ -3,6 +3,7 @@ use std::{ops::Range, sync::Arc}; #[cfg(feature = "trace")] use crate::device::trace::Command as TraceCommand; use crate::{ + api_log, command::CommandBuffer, get_lowest_common_denom, global::Global, @@ -16,9 +17,7 @@ use crate::{ use hal::CommandEncoder as _; use thiserror::Error; -use wgt::{ - math::align_to, BufferAddress, BufferSize, BufferUsages, ImageSubresourceRange, TextureAspect, -}; +use wgt::{math::align_to, BufferAddress, BufferUsages, ImageSubresourceRange, TextureAspect}; /// Error encountered while attempting a clear. #[derive(Clone, Debug, Error)] @@ -37,7 +36,7 @@ pub enum ClearError { #[error("Texture {0:?} can not be cleared")] NoValidTextureClearMode(TextureId), #[error("Buffer clear size {0:?} is not a multiple of `COPY_BUFFER_ALIGNMENT`")] - UnalignedFillSize(BufferSize), + UnalignedFillSize(BufferAddress), #[error("Buffer offset {0:?} is not a multiple of `COPY_BUFFER_ALIGNMENT`")] UnalignedBufferOffset(BufferAddress), #[error("Clear of {start_offset}..{end_offset} would end up overrunning the bounds of the buffer of size {buffer_size}")] @@ -75,10 +74,10 @@ impl Global { command_encoder_id: CommandEncoderId, dst: BufferId, offset: BufferAddress, - size: Option, + size: Option, ) -> Result<(), ClearError> { profiling::scope!("CommandEncoder::clear_buffer"); - log::trace!("CommandEncoder::clear_buffer {dst:?}"); + api_log!("CommandEncoder::clear_buffer {dst:?}"); let hub = A::hub(self); @@ -116,10 +115,10 @@ impl Global { return Err(ClearError::UnalignedBufferOffset(offset)); } if let Some(size) = size { - if size.get() % wgt::COPY_BUFFER_ALIGNMENT != 0 { + if size % wgt::COPY_BUFFER_ALIGNMENT != 0 { return Err(ClearError::UnalignedFillSize(size)); } - let destination_end_offset = offset + size.get(); + let destination_end_offset = offset + size; if destination_end_offset > dst_buffer.size { return Err(ClearError::BufferOverrun { start_offset: offset, @@ -130,7 +129,7 @@ impl Global { } let end = match size { - Some(size) => offset + size.get(), + Some(size) => offset + size, None => dst_buffer.size, }; if offset == end { @@ -163,7 +162,7 @@ impl Global { subresource_range: &ImageSubresourceRange, ) -> Result<(), ClearError> { profiling::scope!("CommandEncoder::clear_texture"); - log::trace!("CommandEncoder::clear_texture {dst:?}"); + api_log!("CommandEncoder::clear_texture {dst:?}"); let hub = A::hub(self); @@ -338,6 +337,11 @@ fn clear_texture_via_buffer_copies( hal::FormatAspects::COLOR ); + if texture_desc.format == wgt::TextureFormat::NV12 { + // TODO: Currently COPY_DST for NV12 textures is unsupported. + return; + } + // Gather list of zero_buffer copies and issue a single command then to perform them let mut zero_buffer_copy_regions = Vec::new(); let buffer_copy_pitch = alignments.buffer_copy_pitch.get() as u32; diff --git a/third_party/rust/wgpu-core/src/command/mod.rs b/third_party/rust/wgpu-core/src/command/mod.rs index 2c088b7a37eaa..fce9d2c6a100c 100644 --- a/third_party/rust/wgpu-core/src/command/mod.rs +++ b/third_party/rust/wgpu-core/src/command/mod.rs @@ -26,7 +26,10 @@ use crate::id::CommandBufferId; use crate::init_tracker::BufferInitTrackerAction; use crate::resource::{Resource, ResourceInfo, ResourceType}; use crate::track::{Tracker, UsageScope}; -use crate::{global::Global, hal_api::HalApi, id, identity::GlobalIdentityHandlerFactory, Label}; +use crate::{ + api_log, global::Global, hal_api::HalApi, id, identity::GlobalIdentityHandlerFactory, + resource_log, Label, +}; use hal::CommandEncoder as _; use parking_lot::Mutex; @@ -135,7 +138,7 @@ impl Drop for CommandBuffer { if self.data.lock().is_none() { return; } - log::info!("Destroying CommandBuffer {:?}", self.info.label()); + resource_log!("resource::CommandBuffer::drop {}", self.info.label()); let mut baked = self.extract_baked_commands(); unsafe { baked.encoder.reset_all(baked.list.into_iter()); @@ -253,7 +256,7 @@ impl CommandBuffer { } pub(crate) fn extract_baked_commands(&mut self) -> BakedCommands { - log::info!( + log::trace!( "Extracting BakedCommands from CommandBuffer {:?}", self.info.label() ); @@ -435,7 +438,7 @@ impl Global { label: &str, ) -> Result<(), CommandEncoderError> { profiling::scope!("CommandEncoder::push_debug_group"); - log::trace!("CommandEncoder::push_debug_group {label}"); + api_log!("CommandEncoder::push_debug_group {label}"); let hub = A::hub(self); @@ -466,7 +469,7 @@ impl Global { label: &str, ) -> Result<(), CommandEncoderError> { profiling::scope!("CommandEncoder::insert_debug_marker"); - log::trace!("CommandEncoder::insert_debug_marker {label}"); + api_log!("CommandEncoder::insert_debug_marker {label}"); let hub = A::hub(self); @@ -497,7 +500,7 @@ impl Global { encoder_id: id::CommandEncoderId, ) -> Result<(), CommandEncoderError> { profiling::scope!("CommandEncoder::pop_debug_marker"); - log::trace!("CommandEncoder::pop_debug_group"); + api_log!("CommandEncoder::pop_debug_group"); let hub = A::hub(self); diff --git a/third_party/rust/wgpu-core/src/command/render.rs b/third_party/rust/wgpu-core/src/command/render.rs index 59246d00babd5..a2bb291a00dac 100644 --- a/third_party/rust/wgpu-core/src/command/render.rs +++ b/third_party/rust/wgpu-core/src/command/render.rs @@ -1,5 +1,6 @@ use crate::resource::Resource; use crate::{ + api_log, binding_model::BindError, command::{ self, @@ -1410,7 +1411,7 @@ impl Global { num_dynamic_offsets, bind_group_id, } => { - log::trace!("RenderPass::set_bind_group {index} {bind_group_id:?}"); + api_log!("RenderPass::set_bind_group {index} {bind_group_id:?}"); let scope = PassErrorScope::SetBindGroup(bind_group_id); let max_bind_groups = device.limits.max_bind_groups; @@ -1493,7 +1494,7 @@ impl Global { } } RenderCommand::SetPipeline(pipeline_id) => { - log::trace!("RenderPass::set_pipeline {pipeline_id:?}"); + api_log!("RenderPass::set_pipeline {pipeline_id:?}"); let scope = PassErrorScope::SetPipelineRender(pipeline_id); state.pipeline = Some(pipeline_id); @@ -1621,7 +1622,7 @@ impl Global { offset, size, } => { - log::trace!("RenderPass::set_index_buffer {buffer_id:?}"); + api_log!("RenderPass::set_index_buffer {buffer_id:?}"); let scope = PassErrorScope::SetIndexBuffer(buffer_id); let buffer = info @@ -1674,7 +1675,7 @@ impl Global { offset, size, } => { - log::trace!("RenderPass::set_vertex_buffer {slot} {buffer_id:?}"); + api_log!("RenderPass::set_vertex_buffer {slot} {buffer_id:?}"); let scope = PassErrorScope::SetVertexBuffer(buffer_id); let buffer = info @@ -1737,7 +1738,7 @@ impl Global { state.vertex.update_limits(); } RenderCommand::SetBlendConstant(ref color) => { - log::trace!("RenderPass::set_blend_constant"); + api_log!("RenderPass::set_blend_constant"); state.blend_constant = OptionalState::Set; let array = [ @@ -1751,7 +1752,7 @@ impl Global { } } RenderCommand::SetStencilReference(value) => { - log::trace!("RenderPass::set_stencil_reference {value}"); + api_log!("RenderPass::set_stencil_reference {value}"); state.stencil_reference = value; if state @@ -1768,7 +1769,7 @@ impl Global { depth_min, depth_max, } => { - log::trace!("RenderPass::set_viewport {rect:?}"); + api_log!("RenderPass::set_viewport {rect:?}"); let scope = PassErrorScope::SetViewport; if rect.x < 0.0 @@ -1806,7 +1807,7 @@ impl Global { size_bytes, values_offset, } => { - log::trace!("RenderPass::set_push_constants"); + api_log!("RenderPass::set_push_constants"); let scope = PassErrorScope::SetPushConstant; let values_offset = values_offset @@ -1841,7 +1842,7 @@ impl Global { } } RenderCommand::SetScissor(ref rect) => { - log::trace!("RenderPass::set_scissor_rect {rect:?}"); + api_log!("RenderPass::set_scissor_rect {rect:?}"); let scope = PassErrorScope::SetScissorRect; if rect.x + rect.w > info.extent.width @@ -1866,7 +1867,7 @@ impl Global { first_vertex, first_instance, } => { - log::trace!( + api_log!( "RenderPass::draw {vertex_count} {instance_count} {first_vertex} {first_instance}" ); @@ -1910,7 +1911,7 @@ impl Global { base_vertex, first_instance, } => { - log::trace!("RenderPass::draw_indexed {index_count} {instance_count} {first_index} {base_vertex} {first_instance}"); + api_log!("RenderPass::draw_indexed {index_count} {instance_count} {first_index} {base_vertex} {first_instance}"); let indexed = true; let scope = PassErrorScope::Draw { @@ -1958,7 +1959,7 @@ impl Global { count, indexed, } => { - log::trace!("RenderPass::draw_indirect (indexed:{indexed}) {buffer_id:?} {offset} {count:?}"); + api_log!("RenderPass::draw_indirect (indexed:{indexed}) {buffer_id:?} {offset} {count:?}"); let scope = PassErrorScope::Draw { indexed, @@ -2032,7 +2033,7 @@ impl Global { max_count, indexed, } => { - log::trace!("RenderPass::multi_draw_indirect_count (indexed:{indexed}) {buffer_id:?} {offset} {count_buffer_id:?} {count_buffer_offset:?} {max_count:?}"); + api_log!("RenderPass::multi_draw_indirect_count (indexed:{indexed}) {buffer_id:?} {offset} {count_buffer_id:?} {count_buffer_offset:?} {max_count:?}"); let scope = PassErrorScope::Draw { indexed, @@ -2148,7 +2149,7 @@ impl Global { ) .unwrap(); - log::trace!("RenderPass::push_debug_group {label:?}"); + api_log!("RenderPass::push_debug_group {label:?}"); unsafe { raw.begin_debug_marker(label); } @@ -2156,7 +2157,7 @@ impl Global { string_offset += len; } RenderCommand::PopDebugGroup => { - log::trace!("RenderPass::pop_debug_group"); + api_log!("RenderPass::pop_debug_group"); let scope = PassErrorScope::PopDebugGroup; if state.debug_scope_depth == 0 { @@ -2176,7 +2177,7 @@ impl Global { &base.string_data[string_offset..string_offset + len], ) .unwrap(); - log::trace!("RenderPass::insert_debug_marker {label:?}"); + api_log!("RenderPass::insert_debug_marker {label:?}"); unsafe { raw.insert_debug_marker(label); } @@ -2187,7 +2188,7 @@ impl Global { query_set_id, query_index, } => { - log::trace!("RenderPass::write_timestamps {query_set_id:?} {query_index}"); + api_log!("RenderPass::write_timestamps {query_set_id:?} {query_index}"); let scope = PassErrorScope::WriteTimestamp; device @@ -2210,7 +2211,7 @@ impl Global { .map_pass_err(scope)?; } RenderCommand::BeginOcclusionQuery { query_index } => { - log::trace!("RenderPass::begin_occlusion_query {query_index}"); + api_log!("RenderPass::begin_occlusion_query {query_index}"); let scope = PassErrorScope::BeginOcclusionQuery; let query_set_id = occlusion_query_set_id @@ -2234,7 +2235,7 @@ impl Global { .map_pass_err(scope)?; } RenderCommand::EndOcclusionQuery => { - log::trace!("RenderPass::end_occlusion_query"); + api_log!("RenderPass::end_occlusion_query"); let scope = PassErrorScope::EndOcclusionQuery; end_occlusion_query(raw, &*query_set_guard, &mut active_query) @@ -2244,7 +2245,7 @@ impl Global { query_set_id, query_index, } => { - log::trace!("RenderPass::begin_pipeline_statistics_query {query_set_id:?} {query_index}"); + api_log!("RenderPass::begin_pipeline_statistics_query {query_set_id:?} {query_index}"); let scope = PassErrorScope::BeginPipelineStatisticsQuery; let query_set = tracker @@ -2264,14 +2265,14 @@ impl Global { .map_pass_err(scope)?; } RenderCommand::EndPipelineStatisticsQuery => { - log::trace!("RenderPass::end_pipeline_statistics_query"); + api_log!("RenderPass::end_pipeline_statistics_query"); let scope = PassErrorScope::EndPipelineStatisticsQuery; end_pipeline_statistics_query(raw, &*query_set_guard, &mut active_query) .map_pass_err(scope)?; } RenderCommand::ExecuteBundle(bundle_id) => { - log::trace!("RenderPass::execute_bundle {bundle_id:?}"); + api_log!("RenderPass::execute_bundle {bundle_id:?}"); let scope = PassErrorScope::ExecuteBundle; let bundle: &command::RenderBundle = tracker .bundles diff --git a/third_party/rust/wgpu-core/src/command/transfer.rs b/third_party/rust/wgpu-core/src/command/transfer.rs index dbb5be98de35a..7ec1bcaebdce5 100644 --- a/third_party/rust/wgpu-core/src/command/transfer.rs +++ b/third_party/rust/wgpu-core/src/command/transfer.rs @@ -1,6 +1,7 @@ #[cfg(feature = "trace")] use crate::device::trace::Command as TraceCommand; use crate::{ + api_log, command::{clear_texture, CommandBuffer, CommandEncoderError}, conv, device::{Device, MissingDownlevelFlags}, @@ -567,6 +568,9 @@ impl Global { size: BufferAddress, ) -> Result<(), CopyError> { profiling::scope!("CommandEncoder::copy_buffer_to_buffer"); + api_log!( + "CommandEncoder::copy_buffer_to_buffer {source:?} -> {destination:?} {size:?}bytes" + ); if source == destination { return Err(TransferError::SameSourceDestinationBuffer.into()); @@ -727,6 +731,11 @@ impl Global { copy_size: &Extent3d, ) -> Result<(), CopyError> { profiling::scope!("CommandEncoder::copy_buffer_to_texture"); + api_log!( + "CommandEncoder::copy_buffer_to_texture {:?} -> {:?} {copy_size:?}", + source.buffer, + destination.texture + ); let hub = A::hub(self); @@ -885,6 +894,11 @@ impl Global { copy_size: &Extent3d, ) -> Result<(), CopyError> { profiling::scope!("CommandEncoder::copy_texture_to_buffer"); + api_log!( + "CommandEncoder::copy_texture_to_buffer {:?} -> {:?} {copy_size:?}", + source.texture, + destination.buffer + ); let hub = A::hub(self); @@ -1055,6 +1069,11 @@ impl Global { copy_size: &Extent3d, ) -> Result<(), CopyError> { profiling::scope!("CommandEncoder::copy_texture_to_texture"); + api_log!( + "CommandEncoder::copy_texture_to_texture {:?} -> {:?} {copy_size:?}", + source.texture, + destination.texture + ); let hub = A::hub(self); diff --git a/third_party/rust/wgpu-core/src/device/global.rs b/third_party/rust/wgpu-core/src/device/global.rs index d7cf7fbceabfd..b043e2106cbf8 100644 --- a/third_party/rust/wgpu-core/src/device/global.rs +++ b/third_party/rust/wgpu-core/src/device/global.rs @@ -1,7 +1,7 @@ #[cfg(feature = "trace")] use crate::device::trace; use crate::{ - binding_model, command, conv, + api_log, binding_model, command, conv, device::{ life::WaitIdleError, map_buffer, queue, DeviceError, DeviceLostClosure, HostMap, IMPLICIT_FAILURE, @@ -185,7 +185,7 @@ impl Global { }; let (id, resource) = fid.assign(buffer); - log::info!("Created Buffer {:?} with {:?}", id, desc); + api_log!("Device::create_buffer({desc:?}) -> {id:?}"); let buffer_use = if !desc.mapped_at_creation { hal::BufferUses::empty() @@ -481,10 +481,10 @@ impl Global { buffer_id: id::BufferId, ) -> Result<(), resource::DestroyError> { profiling::scope!("Buffer::destroy"); + api_log!("Buffer::destroy {buffer_id:?}"); let hub = A::hub(self); - log::debug!("Buffer {:?} is asked to be dropped", buffer_id); let mut buffer_guard = hub.buffers.write(); let buffer = buffer_guard .get_and_mark_destroyed(buffer_id) @@ -494,8 +494,7 @@ impl Global { pub fn buffer_drop(&self, buffer_id: id::BufferId, wait: bool) { profiling::scope!("Buffer::drop"); - - log::debug!("Buffer {:?} is asked to be dropped", buffer_id); + api_log!("Buffer::drop {buffer_id:?}"); let hub = A::hub(self); @@ -564,7 +563,7 @@ impl Global { }; let (id, resource) = fid.assign(texture); - log::info!("Created Texture {:?} with {:?}", id, desc); + api_log!("Device::create_texture({desc:?}) -> {id:?}"); device.trackers.lock().textures.insert_single( id, @@ -575,6 +574,8 @@ impl Global { return (id, None); }; + log::error!("Device::create_texture error {error:?}"); + let id = fid.assign_error(desc.label.borrow_or_default()); (id, Some(error)) } @@ -636,7 +637,7 @@ impl Global { RwLock::new(TextureInitTracker::new(desc.mip_level_count, 0)); let (id, resource) = fid.assign(texture); - log::info!("Created Texture {:?} with {:?}", id, desc); + api_log!("Device::create_texture -> {id:?}"); device.trackers.lock().textures.insert_single( id, @@ -647,6 +648,8 @@ impl Global { return (id, None); }; + log::error!("Device::create_texture error {error:?}"); + let id = fid.assign_error(desc.label.borrow_or_default()); (id, Some(error)) } @@ -688,7 +691,7 @@ impl Global { let buffer = device.create_buffer_from_hal(hal_buffer, desc); let (id, buffer) = fid.assign(buffer); - log::info!("Created buffer {:?} with {:?}", id, desc); + api_log!("Device::create_buffer -> {id:?}"); device .trackers @@ -699,6 +702,8 @@ impl Global { return (id, None); }; + log::error!("Device::create_buffer error {error:?}"); + let id = fid.assign_error(desc.label.borrow_or_default()); (id, Some(error)) } @@ -712,11 +717,10 @@ impl Global { texture_id: id::TextureId, ) -> Result<(), resource::DestroyError> { profiling::scope!("Texture::destroy"); - log::trace!("Texture::destroy {texture_id:?}"); + api_log!("Texture::destroy {texture_id:?}"); let hub = A::hub(self); - log::debug!("Texture {:?} is destroyed", texture_id); let mut texture_guard = hub.textures.write(); let texture = texture_guard .get_and_mark_destroyed(texture_id) @@ -754,8 +758,7 @@ impl Global { pub fn texture_drop(&self, texture_id: id::TextureId, wait: bool) { profiling::scope!("Texture::drop"); - - log::debug!("Texture {:?} is asked to be dropped", texture_id); + api_log!("Texture::drop {texture_id:?}"); let hub = A::hub(self); @@ -827,12 +830,12 @@ impl Global { }; let (id, resource) = fid.assign(view); - log::info!("Created TextureView {:?}", id); + api_log!("Texture::create_view({texture_id:?}) -> {id:?}"); device.trackers.lock().views.insert_single(id, resource); return (id, None); }; - log::error!("Texture::create_view {:?} error {:?}", texture_id, error); + log::error!("Texture::create_view({texture_id:?}) error {error:?}"); let id = fid.assign_error(desc.label.borrow_or_default()); (id, Some(error)) } @@ -847,8 +850,7 @@ impl Global { wait: bool, ) -> Result<(), resource::TextureViewDestroyError> { profiling::scope!("TextureView::drop"); - - log::debug!("TextureView {:?} is asked to be dropped", texture_view_id); + api_log!("TextureView::drop {texture_view_id:?}"); let hub = A::hub(self); @@ -905,7 +907,7 @@ impl Global { }; let (id, resource) = fid.assign(sampler); - log::info!("Created Sampler {:?}", id); + api_log!("Device::create_sampler -> {id:?}"); device.trackers.lock().samplers.insert_single(id, resource); return (id, None); @@ -921,7 +923,7 @@ impl Global { pub fn sampler_drop(&self, sampler_id: id::SamplerId) { profiling::scope!("Sampler::drop"); - log::debug!("Sampler {:?} is asked to be dropped", sampler_id); + api_log!("Sampler::drop {sampler_id:?}"); let hub = A::hub(self); @@ -981,7 +983,7 @@ impl Global { let bgl_guard = hub.bind_group_layouts.read(); device.deduplicate_bind_group_layout(&entry_map, &*bgl_guard) } { - log::info!("Reusing BindGroupLayout {layout:?} -> {:?}", id); + api_log!("Reusing BindGroupLayout {layout:?} -> {:?}", id); let id = fid.assign_existing(&layout); return (id, None); } @@ -992,7 +994,7 @@ impl Global { }; let (id, _layout) = fid.assign(layout); - log::info!("Created BindGroupLayout {:?}", id); + api_log!("Device::create_bind_group_layout -> {id:?}"); return (id, None); }; @@ -1007,11 +1009,7 @@ impl Global { pub fn bind_group_layout_drop(&self, bind_group_layout_id: id::BindGroupLayoutId) { profiling::scope!("BindGroupLayout::drop"); - - log::debug!( - "BindGroupLayout {:?} is asked to be dropped", - bind_group_layout_id - ); + api_log!("BindGroupLayout::drop {bind_group_layout_id:?}"); let hub = A::hub(self); @@ -1061,7 +1059,7 @@ impl Global { }; let (id, _) = fid.assign(layout); - log::info!("Created PipelineLayout {:?}", id); + api_log!("Device::create_pipeline_layout -> {id:?}"); return (id, None); }; @@ -1075,11 +1073,7 @@ impl Global { pub fn pipeline_layout_drop(&self, pipeline_layout_id: id::PipelineLayoutId) { profiling::scope!("PipelineLayout::drop"); - - log::debug!( - "PipelineLayout {:?} is asked to be dropped", - pipeline_layout_id - ); + api_log!("PipelineLayout::drop {pipeline_layout_id:?}"); let hub = A::hub(self); if let Some(layout) = hub.pipeline_layouts.unregister(pipeline_layout_id) { @@ -1132,7 +1126,7 @@ impl Global { }; let (id, resource) = fid.assign(bind_group); - log::info!("Created BindGroup {:?}", id,); + api_log!("Device::create_bind_group -> {id:?}"); device .trackers @@ -1152,8 +1146,7 @@ impl Global { pub fn bind_group_drop(&self, bind_group_id: id::BindGroupId) { profiling::scope!("BindGroup::drop"); - - log::debug!("BindGroup {:?} is asked to be dropped", bind_group_id); + api_log!("BindGroup::drop {bind_group_id:?}"); let hub = A::hub(self); @@ -1220,10 +1213,12 @@ impl Global { }; let (id, _) = fid.assign(shader); - log::info!("Created ShaderModule {:?} with {:?}", id, desc); + api_log!("Device::create_shader_module -> {id:?}"); return (id, None); }; + log::error!("Device::create_shader_module error: {error:?}"); + let id = fid.assign_error(desc.label.borrow_or_default()); (id, Some(error)) } @@ -1275,10 +1270,12 @@ impl Global { Err(e) => break e, }; let (id, _) = fid.assign(shader); - log::info!("Created ShaderModule {:?} with {:?}", id, desc); + api_log!("Device::create_shader_module_spirv -> {id:?}"); return (id, None); }; + log::error!("Device::create_shader_module_spirv error: {error:?}"); + let id = fid.assign_error(desc.label.borrow_or_default()); (id, Some(error)) } @@ -1289,8 +1286,7 @@ impl Global { pub fn shader_module_drop(&self, shader_module_id: id::ShaderModuleId) { profiling::scope!("ShaderModule::drop"); - - log::debug!("ShaderModule {:?} is asked to be dropped", shader_module_id); + api_log!("ShaderModule::drop {shader_module_id:?}"); let hub = A::hub(self); hub.shader_modules.unregister(shader_module_id); @@ -1340,7 +1336,7 @@ impl Global { ); let (id, _) = fid.assign(command_buffer); - log::info!("Created CommandBuffer {:?} with {:?}", id, desc); + api_log!("Device::create_command_encoder -> {id:?}"); return (id, None); }; @@ -1354,11 +1350,7 @@ impl Global { pub fn command_encoder_drop(&self, command_encoder_id: id::CommandEncoderId) { profiling::scope!("CommandEncoder::drop"); - - log::debug!( - "CommandEncoder {:?} is asked to be dropped", - command_encoder_id - ); + api_log!("CommandEncoder::drop {command_encoder_id:?}"); let hub = A::hub(self); @@ -1371,11 +1363,7 @@ impl Global { pub fn command_buffer_drop(&self, command_buffer_id: id::CommandBufferId) { profiling::scope!("CommandBuffer::drop"); - - log::debug!( - "CommandBuffer {:?} is asked to be dropped", - command_buffer_id - ); + api_log!("CommandBuffer::drop {command_buffer_id:?}"); self.command_encoder_drop::(command_buffer_id) } @@ -1388,7 +1376,7 @@ impl Global { Option, ) { profiling::scope!("Device::create_render_bundle_encoder"); - log::trace!("Device::device_create_render_bundle_encoder"); + api_log!("Device::device_create_render_bundle_encoder"); let (encoder, error) = match command::RenderBundleEncoder::new(desc, device_id, None) { Ok(encoder) => (encoder, None), Err(e) => (command::RenderBundleEncoder::dummy(device_id), Some(e)), @@ -1437,7 +1425,7 @@ impl Global { }; let (id, resource) = fid.assign(render_bundle); - log::info!("Created RenderBundle {:?}", id); + api_log!("RenderBundleEncoder::finish -> {id:?}"); device.trackers.lock().bundles.insert_single(id, resource); return (id, None); }; @@ -1452,8 +1440,7 @@ impl Global { pub fn render_bundle_drop(&self, render_bundle_id: id::RenderBundleId) { profiling::scope!("RenderBundle::drop"); - - log::debug!("RenderBundle {:?} is asked to be dropped", render_bundle_id); + api_log!("RenderBundle::drop {render_bundle_id:?}"); let hub = A::hub(self); @@ -1500,7 +1487,7 @@ impl Global { }; let (id, resource) = fid.assign(query_set); - log::info!("Created QuerySet {:?}", id); + api_log!("Device::create_query_set -> {id:?}"); device .trackers .lock() @@ -1516,8 +1503,7 @@ impl Global { pub fn query_set_drop(&self, query_set_id: id::QuerySetId) { profiling::scope!("QuerySet::drop"); - - log::debug!("QuerySet {:?} is asked to be dropped", query_set_id); + api_log!("QuerySet::drop {query_set_id:?}"); let hub = A::hub(self); @@ -1582,7 +1568,7 @@ impl Global { }; let (id, resource) = fid.assign(pipeline); - log::info!("Created RenderPipeline {:?} with {:?}", id, desc); + api_log!("Device::create_render_pipeline -> {id:?}"); device .trackers @@ -1612,6 +1598,8 @@ impl Global { } } + log::error!("Device::create_render_pipeline error {error:?}"); + (id, Some(error)) } @@ -1656,11 +1644,7 @@ impl Global { pub fn render_pipeline_drop(&self, render_pipeline_id: id::RenderPipelineId) { profiling::scope!("RenderPipeline::drop"); - - log::debug!( - "RenderPipeline {:?} is asked to be dropped", - render_pipeline_id - ); + api_log!("RenderPipeline::drop {render_pipeline_id:?}"); let hub = A::hub(self); @@ -1719,7 +1703,7 @@ impl Global { }; let (id, resource) = fid.assign(pipeline); - log::info!("Created ComputePipeline {:?} with {:?}", id, desc); + api_log!("Device::create_compute_pipeline -> {id:?}"); device .trackers @@ -1795,11 +1779,7 @@ impl Global { pub fn compute_pipeline_drop(&self, compute_pipeline_id: id::ComputePipelineId) { profiling::scope!("ComputePipeline::drop"); - - log::debug!( - "ComputePipeline {:?} is asked to be dropped", - compute_pipeline_id - ); + api_log!("ComputePipeline::drop {compute_pipeline_id:?}"); let hub = A::hub(self); @@ -1829,21 +1809,19 @@ impl Global { fn validate_surface_configuration( config: &mut hal::SurfaceConfiguration, caps: &hal::SurfaceCapabilities, + max_texture_dimension_2d: u32, ) -> Result<(), E> { let width = config.extent.width; let height = config.extent.height; - if width < caps.extents.start().width - || width > caps.extents.end().width - || height < caps.extents.start().height - || height > caps.extents.end().height - { - log::warn!( - "Requested size {}x{} is outside of the supported range: {:?}", + + if width > max_texture_dimension_2d || height > max_texture_dimension_2d { + return Err(E::TooLarge { width, height, - caps.extents - ); + max_texture_dimension_2d, + }); } + if !caps.present_modes.contains(&config.present_mode) { let new_mode = 'b: loop { // Automatic present mode checks. @@ -1876,7 +1854,7 @@ impl Global { unreachable!("Fallback system failed to choose present mode. This is a bug. Mode: {:?}, Options: {:?}", config.present_mode, &caps.present_modes); }; - log::info!( + api_log!( "Automatically choosing presentation mode by rule {:?}. Chose {new_mode:?}", config.present_mode ); @@ -1920,7 +1898,7 @@ impl Global { ); }; - log::info!( + api_log!( "Automatically choosing alpha mode by rule {:?}. Chose {new_alpha_mode:?}", config.composite_alpha_mode ); @@ -2017,14 +1995,18 @@ impl Global { view_formats: hal_view_formats, }; - if let Err(error) = validate_surface_configuration(&mut hal_config, &caps) { + if let Err(error) = validate_surface_configuration( + &mut hal_config, + &caps, + device.limits.max_texture_dimension_2d, + ) { break error; } // Wait for all work to finish before configuring the surface. let fence = device.fence.read(); let fence = fence.as_ref().unwrap(); - match device.maintain(hub, fence, wgt::Maintain::Wait) { + match device.maintain(fence, wgt::Maintain::Wait) { Ok((closures, _)) => { user_callbacks = closures; } @@ -2094,7 +2076,6 @@ impl Global { return Err(InvalidDevice); } device.lock_life().triage_suspected( - hub, &device.trackers, #[cfg(feature = "trace")] None, @@ -2110,7 +2091,7 @@ impl Global { device_id: DeviceId, maintain: wgt::Maintain, ) -> Result { - log::trace!("Device::poll"); + api_log!("Device::poll"); let (closures, queue_empty) = { if let wgt::Maintain::WaitForSubmissionIndex(submission_index) = maintain { @@ -2129,7 +2110,7 @@ impl Global { .map_err(|_| DeviceError::Invalid)?; let fence = device.fence.read(); let fence = fence.as_ref().unwrap(); - device.maintain(hub, fence, maintain)? + device.maintain(fence, maintain)? }; closures.fire(); @@ -2163,7 +2144,7 @@ impl Global { }; let fence = device.fence.read(); let fence = fence.as_ref().unwrap(); - let (cbs, queue_empty) = device.maintain(hub, fence, maintain)?; + let (cbs, queue_empty) = device.maintain(fence, maintain)?; all_queue_empty = all_queue_empty && queue_empty; closures.extend(cbs); @@ -2180,6 +2161,7 @@ impl Global { /// Return `all_queue_empty` indicating whether there are more queue /// submissions still in flight. pub fn poll_all_devices(&self, force_wait: bool) -> Result { + api_log!("poll_all_devices"); let mut closures = UserClosures::default(); let mut all_queue_empty = true; @@ -2219,7 +2201,7 @@ impl Global { } pub fn device_start_capture(&self, id: DeviceId) { - log::trace!("Device::start_capture"); + api_log!("Device::start_capture"); let hub = A::hub(self); @@ -2232,7 +2214,7 @@ impl Global { } pub fn device_stop_capture(&self, id: DeviceId) { - log::trace!("Device::stop_capture"); + api_log!("Device::stop_capture"); let hub = A::hub(self); @@ -2246,7 +2228,7 @@ impl Global { pub fn device_drop(&self, device_id: DeviceId) { profiling::scope!("Device::drop"); - log::debug!("Device {:?} is asked to be dropped", device_id); + api_log!("Device::drop {device_id:?}"); let hub = A::hub(self); if let Some(device) = hub.devices.unregister(device_id) { @@ -2279,7 +2261,7 @@ impl Global { } pub fn device_destroy(&self, device_id: DeviceId) { - log::trace!("Device::destroy {device_id:?}"); + api_log!("Device::destroy {device_id:?}"); let hub = A::hub(self); @@ -2305,7 +2287,7 @@ impl Global { } pub fn device_mark_lost(&self, device_id: DeviceId, message: &str) { - log::trace!("Device::mark_lost {device_id:?}"); + api_log!("Device::mark_lost {device_id:?}"); let hub = A::hub(self); @@ -2316,7 +2298,7 @@ impl Global { pub fn queue_drop(&self, queue_id: QueueId) { profiling::scope!("Queue::drop"); - log::debug!("Queue {:?} is asked to be dropped", queue_id); + api_log!("Queue::drop {queue_id:?}"); let hub = A::hub(self); if let Some(queue) = hub.queues.unregister(queue_id) { @@ -2330,7 +2312,7 @@ impl Global { range: Range, op: BufferMapOperation, ) -> BufferAccessResult { - log::trace!("Buffer::map_async {buffer_id:?}"); + api_log!("Buffer::map_async {buffer_id:?}"); // User callbacks must not be called while holding buffer_map_async_inner's locks, so we // defer the error callback if it needs to be called immediately (typically when running @@ -2339,6 +2321,7 @@ impl Global { if let Some(callback) = operation.callback.take() { callback.call(Err(err.clone())); } + log::error!("Buffer::map_async error {err:?}"); return Err(err); } @@ -2425,7 +2408,6 @@ impl Global { } }; } - log::debug!("Buffer {:?} map state -> Waiting", buffer_id); { let mut trackers = buffer.device.as_ref().trackers.lock(); @@ -2449,7 +2431,7 @@ impl Global { size: Option, ) -> Result<(*mut u8, u64), BufferAccessError> { profiling::scope!("Buffer::get_mapped_range"); - log::trace!("Buffer::get_mapped_range {buffer_id:?}"); + api_log!("Buffer::get_mapped_range {buffer_id:?}"); let hub = A::hub(self); @@ -2511,7 +2493,7 @@ impl Global { } pub fn buffer_unmap(&self, buffer_id: id::BufferId) -> BufferAccessResult { profiling::scope!("unmap", "Buffer"); - log::trace!("Buffer::unmap {buffer_id:?}"); + api_log!("Buffer::unmap {buffer_id:?}"); let closure; { diff --git a/third_party/rust/wgpu-core/src/device/life.rs b/third_party/rust/wgpu-core/src/device/life.rs index 5a2eff0cfc6a5..8b421c11af56d 100644 --- a/third_party/rust/wgpu-core/src/device/life.rs +++ b/third_party/rust/wgpu-core/src/device/life.rs @@ -8,14 +8,12 @@ use crate::{ DeviceError, DeviceLostClosure, }, hal_api::HalApi, - hub::Hub, id::{ self, BindGroupId, BindGroupLayoutId, BufferId, ComputePipelineId, PipelineLayoutId, QuerySetId, RenderBundleId, RenderPipelineId, SamplerId, StagingBufferId, TextureId, TextureViewId, }, pipeline::{ComputePipeline, RenderPipeline}, - registry::Registry, resource::{ self, Buffer, QuerySet, Resource, ResourceType, Sampler, StagingBuffer, Texture, TextureView, @@ -77,16 +75,6 @@ impl ResourceMaps { self.maps.insert(R::TYPE, Box::new(map)); self } - fn map(&self) -> &FastHashMap> - where - Id: id::TypedId, - R: Resource, - { - let map = self.maps.get(R::TYPE).unwrap(); - let any_map = map.as_ref().as_any(); - let map = any_map.downcast_ref::>>().unwrap(); - map - } fn map_mut(&mut self) -> &mut FastHashMap> where Id: id::TypedId, @@ -132,13 +120,6 @@ impl ResourceMaps { self.map_mut().insert(id, r); self } - pub(crate) fn contains(&mut self, id: &Id) -> bool - where - Id: id::TypedId, - R: Resource, - { - self.map::().contains_key(id) - } } /// Resources used by a queue submission, and work to be done once it completes. @@ -369,7 +350,7 @@ impl LifetimeTracker { let mut work_done_closures: SmallVec<_> = self.work_done_closures.drain(..).collect(); for a in self.active.drain(..done_count) { - log::info!("Active submission {} is done", a.index); + log::debug!("Active submission {} is done", a.index); self.free_resources.extend(a.last_resources); self.ready_to_map.extend(a.mapped); for encoder in a.encoders { @@ -424,35 +405,27 @@ impl LifetimeTracker { } impl LifetimeTracker { - fn triage_resources( + fn triage_resources( resources_map: &mut FastHashMap>, active: &mut [ActiveSubmission], free_resources: &mut ResourceMaps, trackers: &mut impl ResourceTracker, - registry: &Registry, - count_fn: F, mut on_remove: T, ) -> Vec> where Id: id::TypedId, R: Resource, - F: Fn(u64, &[ActiveSubmission], &Id) -> usize, T: FnMut(&Id, &Arc), { let mut removed_resources = Vec::new(); resources_map.retain(|&id, resource| { let submit_index = resource.as_info().submission_index(); - let mut count = 1; - count += count_fn(submit_index, active, &id); - count += registry.contains(id) as usize; - let non_referenced_resources = active .iter_mut() .find(|a| a.index == submit_index) .map_or(&mut *free_resources, |a| &mut a.last_resources); - count += non_referenced_resources.contains::(&id) as usize; - let is_removed = trackers.remove_abandoned(id, count); + let is_removed = trackers.remove_abandoned(id); if is_removed { on_remove(&id, resource); removed_resources.push(resource.clone()); @@ -465,7 +438,6 @@ impl LifetimeTracker { fn triage_suspected_render_bundles( &mut self, - hub: &Hub, trackers: &Mutex>, #[cfg(feature = "trace")] trace: &mut Option<&mut trace::Trace>, ) -> &mut Self { @@ -476,8 +448,6 @@ impl LifetimeTracker { self.active.as_mut_slice(), &mut self.free_resources, &mut trackers.bundles, - &hub.render_bundles, - |_submit_index, _active, _id| 0, |_bundle_id, _bundle| { #[cfg(feature = "trace")] if let Some(ref mut t) = *trace { @@ -507,7 +477,6 @@ impl LifetimeTracker { fn triage_suspected_bind_groups( &mut self, - hub: &Hub, trackers: &Mutex>, #[cfg(feature = "trace")] trace: &mut Option<&mut trace::Trace>, ) -> &mut Self { @@ -518,8 +487,6 @@ impl LifetimeTracker { self.active.as_mut_slice(), &mut self.free_resources, &mut trackers.bind_groups, - &hub.bind_groups, - |_submit_index, _active, _id| 0, |_bind_group_id, _bind_group| { #[cfg(feature = "trace")] if let Some(ref mut t) = *trace { @@ -553,7 +520,6 @@ impl LifetimeTracker { fn triage_suspected_texture_views( &mut self, - hub: &Hub, trackers: &Mutex>, #[cfg(feature = "trace")] trace: &mut Option<&mut trace::Trace>, ) -> &mut Self { @@ -564,8 +530,6 @@ impl LifetimeTracker { self.active.as_mut_slice(), &mut self.free_resources, &mut trackers.views, - &hub.texture_views, - |_submit_index, _active, _id| 0, |_texture_view_id, _texture_view| { #[cfg(feature = "trace")] if let Some(ref mut t) = *trace { @@ -585,7 +549,6 @@ impl LifetimeTracker { fn triage_suspected_textures( &mut self, - hub: &Hub, trackers: &Mutex>, #[cfg(feature = "trace")] trace: &mut Option<&mut trace::Trace>, ) -> &mut Self { @@ -596,8 +559,6 @@ impl LifetimeTracker { self.active.as_mut_slice(), &mut self.free_resources, &mut trackers.textures, - &hub.textures, - |_submit_index, _active, _id| 0, |_texture_id, _texture| { #[cfg(feature = "trace")] if let Some(ref mut t) = *trace { @@ -610,7 +571,6 @@ impl LifetimeTracker { fn triage_suspected_samplers( &mut self, - hub: &Hub, trackers: &Mutex>, #[cfg(feature = "trace")] trace: &mut Option<&mut trace::Trace>, ) -> &mut Self { @@ -621,8 +581,6 @@ impl LifetimeTracker { self.active.as_mut_slice(), &mut self.free_resources, &mut trackers.samplers, - &hub.samplers, - |_submit_index, _active, _id| 0, |_sampler_id, _sampler| { #[cfg(feature = "trace")] if let Some(ref mut t) = *trace { @@ -635,7 +593,6 @@ impl LifetimeTracker { fn triage_suspected_buffers( &mut self, - hub: &Hub, trackers: &Mutex>, #[cfg(feature = "trace")] trace: &mut Option<&mut trace::Trace>, ) -> &mut Self { @@ -646,20 +603,6 @@ impl LifetimeTracker { self.active.as_mut_slice(), &mut self.free_resources, &mut trackers.buffers, - &hub.buffers, - |submit_index, active, buffer_id| { - let mut count = 0; - let mapped = active - .iter() - .find(|a| a.index == submit_index) - .map_or(&self.mapped, |a| &a.mapped); - mapped.iter().for_each(|b| { - if b.as_info().id() == *buffer_id { - count += 1; - } - }); - count - }, |_buffer_id, _buffer| { #[cfg(feature = "trace")] if let Some(ref mut t) = *trace { @@ -681,7 +624,6 @@ impl LifetimeTracker { fn triage_suspected_compute_pipelines( &mut self, - hub: &Hub, trackers: &Mutex>, #[cfg(feature = "trace")] trace: &mut Option<&mut trace::Trace>, ) -> &mut Self { @@ -692,8 +634,6 @@ impl LifetimeTracker { self.active.as_mut_slice(), &mut self.free_resources, &mut trackers.compute_pipelines, - &hub.compute_pipelines, - |_submit_index, _active, _id| 0, |_compute_pipeline_id, _compute_pipeline| { #[cfg(feature = "trace")] if let Some(ref mut t) = *trace { @@ -712,7 +652,6 @@ impl LifetimeTracker { fn triage_suspected_render_pipelines( &mut self, - hub: &Hub, trackers: &Mutex>, #[cfg(feature = "trace")] trace: &mut Option<&mut trace::Trace>, ) -> &mut Self { @@ -723,8 +662,6 @@ impl LifetimeTracker { self.active.as_mut_slice(), &mut self.free_resources, &mut trackers.render_pipelines, - &hub.render_pipelines, - |_submit_index, _active, _id| 0, |_render_pipeline_id, _render_pipeline| { #[cfg(feature = "trace")] if let Some(ref mut t) = *trace { @@ -787,11 +724,7 @@ impl LifetimeTracker { self } - fn triage_suspected_query_sets( - &mut self, - hub: &Hub, - trackers: &Mutex>, - ) -> &mut Self { + fn triage_suspected_query_sets(&mut self, trackers: &Mutex>) -> &mut Self { let mut trackers = trackers.lock(); let resource_map = self.suspected_resources.map_mut(); Self::triage_resources( @@ -799,8 +732,6 @@ impl LifetimeTracker { self.active.as_mut_slice(), &mut self.free_resources, &mut trackers.query_sets, - &hub.query_sets, - |_submit_index, _active, _id| 0, |_query_set_id, _query_set| {}, ); self @@ -858,7 +789,6 @@ impl LifetimeTracker { /// [`self.free_resources`]: LifetimeTracker::free_resources pub(crate) fn triage_suspected( &mut self, - hub: &Hub, trackers: &Mutex>, #[cfg(feature = "trace")] mut trace: Option<&mut trace::Trace>, ) { @@ -866,25 +796,21 @@ impl LifetimeTracker { //NOTE: the order is important to release resources that depends between each other! self.triage_suspected_render_bundles( - hub, trackers, #[cfg(feature = "trace")] &mut trace, ); self.triage_suspected_compute_pipelines( - hub, trackers, #[cfg(feature = "trace")] &mut trace, ); self.triage_suspected_render_pipelines( - hub, trackers, #[cfg(feature = "trace")] &mut trace, ); self.triage_suspected_bind_groups( - hub, trackers, #[cfg(feature = "trace")] &mut trace, @@ -897,28 +823,24 @@ impl LifetimeTracker { #[cfg(feature = "trace")] &mut trace, ); - self.triage_suspected_query_sets(hub, trackers); + self.triage_suspected_query_sets(trackers); self.triage_suspected_samplers( - hub, trackers, #[cfg(feature = "trace")] &mut trace, ); self.triage_suspected_staging_buffers(); self.triage_suspected_texture_views( - hub, trackers, #[cfg(feature = "trace")] &mut trace, ); self.triage_suspected_textures( - hub, trackers, #[cfg(feature = "trace")] &mut trace, ); self.triage_suspected_buffers( - hub, trackers, #[cfg(feature = "trace")] &mut trace, @@ -959,7 +881,6 @@ impl LifetimeTracker { #[must_use] pub(crate) fn handle_mapping( &mut self, - hub: &Hub, raw: &A::Device, trackers: &Mutex>, ) -> Vec { @@ -973,13 +894,11 @@ impl LifetimeTracker { let buffer_id = buffer.info.id(); let is_removed = { let mut trackers = trackers.lock(); - let mut count = 1; - count += hub.buffers.contains(buffer_id) as usize; - trackers.buffers.remove_abandoned(buffer_id, count) + trackers.buffers.remove_abandoned(buffer_id) }; if is_removed { *buffer.map_state.lock() = resource::BufferMapState::Idle; - log::info!("Buffer ready to map {:?} is not tracked anymore", buffer_id); + log::trace!("Buffer ready to map {:?} is not tracked anymore", buffer_id); self.free_resources.insert(buffer_id, buffer.clone()); } else { let mapping = match std::mem::replace( diff --git a/third_party/rust/wgpu-core/src/device/mod.rs b/third_party/rust/wgpu-core/src/device/mod.rs index 269c8304af823..ad34876ebe2ae 100644 --- a/third_party/rust/wgpu-core/src/device/mod.rs +++ b/third_party/rust/wgpu-core/src/device/mod.rs @@ -6,7 +6,7 @@ use crate::{ identity::{GlobalIdentityHandlerFactory, Input}, resource::{Buffer, BufferAccessResult}, resource::{BufferAccessError, BufferMapOperation}, - Label, DOWNLEVEL_ERROR_MESSAGE, + resource_log, Label, DOWNLEVEL_ERROR_MESSAGE, }; use arrayvec::ArrayVec; @@ -273,19 +273,15 @@ impl DeviceLostClosure { } } - #[allow(trivial_casts)] pub(crate) fn call(self, reason: DeviceLostReason, message: String) { match self.inner { DeviceLostClosureInner::Rust { callback } => callback(reason, message), // SAFETY: the contract of the call to from_c says that this unsafe is sound. DeviceLostClosureInner::C { inner } => unsafe { - // We need to pass message as a c_char typed pointer. To avoid trivial - // conversion warnings on some platforms, we use the allow lint. - (inner.callback)( - inner.user_data, - reason as u8, - message.as_ptr() as *const c_char, - ) + // Ensure message is structured as a null-terminated C string. It only + // needs to live as long as the callback invocation. + let message = std::ffi::CString::new(message).unwrap(); + (inner.callback)(inner.user_data, reason as u8, message.as_ptr()) }, } } @@ -376,7 +372,10 @@ impl CommandAllocator { } fn dispose(self, device: &A::Device) { - log::info!("Destroying {} command encoders", self.free_encoders.len()); + resource_log!( + "CommandAllocator::dispose encoders {}", + self.free_encoders.len() + ); for cmd_encoder in self.free_encoders { unsafe { device.destroy_command_encoder(cmd_encoder); diff --git a/third_party/rust/wgpu-core/src/device/queue.rs b/third_party/rust/wgpu-core/src/device/queue.rs index 3902d6190c9b2..9a1918c0a14cf 100644 --- a/third_party/rust/wgpu-core/src/device/queue.rs +++ b/third_party/rust/wgpu-core/src/device/queue.rs @@ -1,6 +1,7 @@ #[cfg(feature = "trace")] use crate::device::trace::Action; use crate::{ + api_log, command::{ extract_texture_selector, validate_linear_texture_data, validate_texture_copy_range, ClearError, CommandBuffer, CopySide, ImageCopyTexture, TransferError, @@ -18,7 +19,7 @@ use crate::{ Buffer, BufferAccessError, BufferMapState, Resource, ResourceInfo, ResourceType, StagingBuffer, Texture, TextureInner, }, - track, FastHashMap, SubmissionIndex, + resource_log, track, FastHashMap, SubmissionIndex, }; use hal::{CommandEncoder as _, Device as _, Queue as _}; @@ -385,6 +386,7 @@ impl Global { data: &[u8], ) -> Result<(), QueueWriteError> { profiling::scope!("Queue::write_buffer"); + api_log!("Queue::write_buffer {buffer_id:?} {}bytes", data.len()); let hub = A::hub(self); @@ -466,7 +468,7 @@ impl Global { let fid = hub.staging_buffers.prepare::(id_in); let (id, _) = fid.assign(staging_buffer); - log::info!("Created StagingBuffer {:?}", id); + resource_log!("Queue::create_staging_buffer {id:?}"); Ok((id, staging_buffer_ptr)) } @@ -649,6 +651,7 @@ impl Global { size: &wgt::Extent3d, ) -> Result<(), QueueWriteError> { profiling::scope!("Queue::write_texture"); + api_log!("Queue::write_texture {:?} {size:?}", destination.texture); let hub = A::hub(self); @@ -1115,7 +1118,7 @@ impl Global { command_buffer_ids: &[id::CommandBufferId], ) -> Result { profiling::scope!("Queue::submit"); - log::trace!("Queue::submit {queue_id:?}"); + api_log!("Queue::submit {queue_id:?}"); let (submit_index, callbacks) = { let hub = A::hub(self); @@ -1484,7 +1487,7 @@ impl Global { // This will schedule destruction of all resources that are no longer needed // by the user but used in the command stream, among other things. - let (closures, _) = match device.maintain(hub, fence, wgt::Maintain::Poll) { + let (closures, _) = match device.maintain(fence, wgt::Maintain::Poll) { Ok(closures) => closures, Err(WaitIdleError::Device(err)) => return Err(QueueSubmitError::Queue(err)), Err(WaitIdleError::StuckGpu) => return Err(QueueSubmitError::StuckGpu), @@ -1524,7 +1527,7 @@ impl Global { queue_id: QueueId, closure: SubmittedWorkDoneClosure, ) -> Result<(), InvalidQueue> { - log::trace!("Queue::on_submitted_work_done {queue_id:?}"); + api_log!("Queue::on_submitted_work_done {queue_id:?}"); //TODO: flush pending writes let hub = A::hub(self); diff --git a/third_party/rust/wgpu-core/src/device/resource.rs b/third_party/rust/wgpu-core/src/device/resource.rs index 035b2ea55416b..b6ee9aec073d4 100644 --- a/third_party/rust/wgpu-core/src/device/resource.rs +++ b/third_party/rust/wgpu-core/src/device/resource.rs @@ -25,6 +25,7 @@ use crate::{ self, Buffer, QuerySet, Resource, ResourceType, Sampler, Texture, TextureView, TextureViewNotRenderableReason, }, + resource_log, storage::Storage, track::{BindGroupStates, TextureSelector, Tracker}, validation::{self, check_buffer_usage, check_texture_usage}, @@ -140,7 +141,7 @@ impl std::fmt::Debug for Device { impl Drop for Device { fn drop(&mut self) { - log::info!("Destroying Device {:?}", self.info.label()); + resource_log!("Destroy raw Device {}", self.info.label()); let raw = self.raw.take().unwrap(); let pending_writes = self.pending_writes.lock().take().unwrap(); pending_writes.dispose(&raw); @@ -191,8 +192,6 @@ impl Device { raw_device: A::Device, raw_queue: &A::Queue, adapter: &Arc>, - alignments: hal::Alignments, - downlevel: wgt::DownlevelCapabilities, desc: &DeviceDescriptor, trace_path: Option<&std::path::Path>, instance_flags: wgt::InstanceFlags, @@ -242,6 +241,9 @@ impl Device { })); } + let alignments = adapter.raw.capabilities.alignments.clone(); + let downlevel = adapter.raw.capabilities.downlevel.clone(); + Ok(Self { raw: Some(raw_device), adapter: adapter.clone(), @@ -271,8 +273,8 @@ impl Device { } })), alignments, - limits: desc.limits.clone(), - features: desc.features, + limits: desc.required_limits.clone(), + features: desc.required_features, downlevel, instance_flags, pending_writes: Mutex::new(Some(pending_writes)), @@ -306,7 +308,6 @@ impl Device { /// return it to our callers.) pub(crate) fn maintain<'this>( &'this self, - hub: &Hub, fence: &A::Fence, maintain: wgt::Maintain, ) -> Result<(UserClosures, bool), WaitIdleError> { @@ -327,7 +328,6 @@ impl Device { life_tracker.suspected_resources.extend(temp_suspected); life_tracker.triage_suspected( - hub, &self.trackers, #[cfg(feature = "trace")] self.trace.lock().as_mut(), @@ -367,7 +367,7 @@ impl Device { last_done_index, self.command_allocator.lock().as_mut().unwrap(), ); - let mapping_closures = life_tracker.handle_mapping(hub, self.raw(), &self.trackers); + let mapping_closures = life_tracker.handle_mapping(self.raw(), &self.trackers); //Cleaning up resources and released all unused suspected ones life_tracker.cleanup(); @@ -751,7 +751,8 @@ impl Device { if desc.format == *format { continue; } - if desc.format.remove_srgb_suffix() != format.remove_srgb_suffix() { + + if !check_texture_view_format_compatible(desc.format, *format) { return Err(CreateTextureError::InvalidViewFormat(*format, desc.format)); } hal_view_formats.push(*format); @@ -804,23 +805,35 @@ impl Device { let mut clear_views = SmallVec::new(); for mip_level in 0..desc.mip_level_count { for array_layer in 0..desc.size.depth_or_array_layers { - let desc = hal::TextureViewDescriptor { - label: clear_label, - format: desc.format, - dimension, - usage, - range: wgt::ImageSubresourceRange { - aspect: wgt::TextureAspect::All, - base_mip_level: mip_level, - mip_level_count: Some(1), - base_array_layer: array_layer, - array_layer_count: Some(1), - }, - }; - clear_views.push(Some( - unsafe { self.raw().create_texture_view(&raw_texture, &desc) } - .map_err(DeviceError::from)?, - )); + macro_rules! push_clear_view { + ($format:expr, $plane:expr) => { + let desc = hal::TextureViewDescriptor { + label: clear_label, + format: $format, + dimension, + usage, + range: wgt::ImageSubresourceRange { + aspect: wgt::TextureAspect::All, + base_mip_level: mip_level, + mip_level_count: Some(1), + base_array_layer: array_layer, + array_layer_count: Some(1), + }, + plane: $plane, + }; + clear_views.push(Some( + unsafe { self.raw().create_texture_view(&raw_texture, &desc) } + .map_err(DeviceError::from)?, + )); + }; + } + + if desc.format == wgt::TextureFormat::NV12 { + push_clear_view!(wgt::TextureFormat::R8Unorm, Some(0)); + push_clear_view!(wgt::TextureFormat::Rg8Unorm, Some(1)); + } else { + push_clear_view!(desc.format, None); + } } } resource::TextureClearMode::RenderPass { @@ -1015,6 +1028,8 @@ impl Device { }); }; + validate_texture_view_plane(texture.desc.format, resolved_format, desc.plane)?; + // https://gpuweb.github.io/gpuweb/#abstract-opdef-renderable-texture-view let render_extent = 'b: loop { if !texture @@ -1106,6 +1121,7 @@ impl Device { dimension: resolved_dimension, usage, range: resolved_range, + plane: desc.plane, }; let raw = unsafe { @@ -2048,7 +2064,7 @@ impl Device { .views .add_single(&*texture_view_guard, id) .ok_or(Error::InvalidTextureView(id))?; - let (pub_usage, internal_use) = Self::texture_use_parameters( + let (pub_usage, internal_use) = self.texture_use_parameters( binding, decl, view, @@ -2079,7 +2095,7 @@ impl Device { .add_single(&*texture_view_guard, id) .ok_or(Error::InvalidTextureView(id))?; let (pub_usage, internal_use) = - Self::texture_use_parameters(binding, decl, view, + self.texture_use_parameters(binding, decl, view, "SampledTextureArray, ReadonlyStorageTextureArray or WriteonlyStorageTextureArray")?; Self::create_texture_binding( view, @@ -2181,6 +2197,7 @@ impl Device { } pub(crate) fn texture_use_parameters( + self: &Arc, binding: u32, decl: &wgt::BindGroupLayoutEntry, view: &TextureView, @@ -2211,7 +2228,7 @@ impl Device { let compat_sample_type = view .desc .format - .sample_type(Some(view.desc.range.aspect)) + .sample_type(Some(view.desc.range.aspect), Some(self.features)) .unwrap(); match (sample_type, compat_sample_type) { (Tst::Uint, Tst::Uint) | @@ -2389,7 +2406,7 @@ impl Device { .collect::>(); let hal_desc = hal::PipelineLayoutDescriptor { label: desc.label.to_hal(self.instance_flags), - flags: hal::PipelineLayoutFlags::BASE_VERTEX_INSTANCE, + flags: hal::PipelineLayoutFlags::FIRST_VERTEX_INSTANCE, bind_group_layouts: &bgl_vec, push_constant_ranges: desc.push_constant_ranges.as_ref(), }; @@ -3182,6 +3199,24 @@ impl Device { Ok(pipeline) } + pub(crate) fn get_texture_format_features( + &self, + adapter: &Adapter, + format: TextureFormat, + ) -> wgt::TextureFormatFeatures { + // Variant of adapter.get_texture_format_features that takes device features into account + use wgt::TextureFormatFeatureFlags as tfsc; + let mut format_features = adapter.get_texture_format_features(format); + if (format == TextureFormat::R32Float + || format == TextureFormat::Rg32Float + || format == TextureFormat::Rgba32Float) + && !self.features.contains(wgt::Features::FLOAT32_FILTERABLE) + { + format_features.flags.set(tfsc::FILTERABLE, false); + } + format_features + } + pub(crate) fn describe_format_features( &self, adapter: &Adapter, @@ -3197,7 +3232,7 @@ impl Device { let downlevel = !self.downlevel.is_webgpu_compliant(); if using_device_features || downlevel { - Ok(adapter.get_texture_format_features(format)) + Ok(self.get_texture_format_features(adapter, format)) } else { Ok(format.guaranteed_format_features(self.features)) } @@ -3349,3 +3384,39 @@ impl Resource for Device { &mut self.info } } + +fn check_texture_view_format_compatible( + texture_format: TextureFormat, + view_format: TextureFormat, +) -> bool { + use TextureFormat::*; + + match (texture_format, view_format) { + (NV12, R8Unorm | R8Uint | Rg8Unorm | Rg8Uint) => true, + _ => texture_format.remove_srgb_suffix() == view_format.remove_srgb_suffix(), + } +} + +fn validate_texture_view_plane( + texture_format: TextureFormat, + view_format: TextureFormat, + plane: Option, +) -> Result<(), resource::CreateTextureViewError> { + use TextureFormat::*; + + match (texture_format, view_format, plane) { + (NV12, R8Unorm | R8Uint, Some(0)) => Ok(()), + (NV12, Rg8Unorm | Rg8Uint, Some(1)) => Ok(()), + (NV12, _, _) => { + Err(resource::CreateTextureViewError::InvalidTextureViewPlane { plane, view_format }) + } + + (_, _, Some(_)) => Err( + resource::CreateTextureViewError::InvalidTextureViewPlaneOnNonplanarTexture { + plane, + texture_format, + }, + ), + _ => Ok(()), + } +} diff --git a/third_party/rust/wgpu-core/src/device/trace.rs b/third_party/rust/wgpu-core/src/device/trace.rs index ab5806bb903fc..315b7e8e849d1 100644 --- a/third_party/rust/wgpu-core/src/device/trace.rs +++ b/third_party/rust/wgpu-core/src/device/trace.rs @@ -154,7 +154,7 @@ pub enum Command { ClearBuffer { dst: id::BufferId, offset: wgt::BufferAddress, - size: Option, + size: Option, }, ClearTexture { dst: id::TextureId, diff --git a/third_party/rust/wgpu-core/src/global.rs b/third_party/rust/wgpu-core/src/global.rs index 3cb0e84b2b190..5de766f61f3a3 100644 --- a/third_party/rust/wgpu-core/src/global.rs +++ b/third_party/rust/wgpu-core/src/global.rs @@ -9,6 +9,7 @@ use crate::{ identity::GlobalIdentityHandlerFactory, instance::{Instance, Surface}, registry::{Registry, RegistryReport}, + resource_log, storage::Element, }; @@ -150,7 +151,7 @@ impl Global { impl Drop for Global { fn drop(&mut self) { profiling::scope!("Global::drop"); - log::info!("Destroying Global"); + resource_log!("Global::drop"); let mut surfaces_locked = self.surfaces.write(); // destroy hubs before the instance gets dropped diff --git a/third_party/rust/wgpu-core/src/id.rs b/third_party/rust/wgpu-core/src/id.rs index 97c119af5ce2d..9daa0ef56c714 100644 --- a/third_party/rust/wgpu-core/src/id.rs +++ b/third_party/rust/wgpu-core/src/id.rs @@ -155,12 +155,17 @@ where { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { let (index, epoch, backend) = self.unzip(); - formatter - .debug_struct("Id") - .field("index", &index) - .field("epoch", &epoch) - .field("backend", &backend) - .finish() + let backend = match backend { + Backend::Vulkan => "vk", + Backend::Metal => "mtl", + Backend::Dx12 => "d3d12", + Backend::Dx11 => "d3d11", + Backend::Gl => "gl", + Backend::BrowserWebGpu => "webgpu", + Backend::Empty => "_", + }; + write!(formatter, "Id({index},{epoch},{backend})")?; + Ok(()) } } diff --git a/third_party/rust/wgpu-core/src/instance.rs b/third_party/rust/wgpu-core/src/instance.rs index 37428aeae9738..b8340cd659881 100644 --- a/third_party/rust/wgpu-core/src/instance.rs +++ b/third_party/rust/wgpu-core/src/instance.rs @@ -2,6 +2,7 @@ use std::sync::Arc; use crate::{ any_surface::AnySurface, + api_log, device::{queue::Queue, resource::Device, DeviceDescriptor}, global::Global, hal_api::HalApi, @@ -9,7 +10,7 @@ use crate::{ identity::{GlobalIdentityHandlerFactory, Input}, present::Presentation, resource::{Resource, ResourceInfo, ResourceType}, - LabelHelpers, DOWNLEVEL_WARNING_MESSAGE, + resource_log, LabelHelpers, DOWNLEVEL_WARNING_MESSAGE, }; use parking_lot::Mutex; @@ -306,15 +307,12 @@ impl Adapter { instance_flags: wgt::InstanceFlags, trace_path: Option<&std::path::Path>, ) -> Result<(Device, Queue), RequestDeviceError> { - log::info!("Adapter::create_device"); + api_log!("Adapter::create_device"); - let caps = &self.raw.capabilities; if let Ok(device) = Device::new( hal_device.device, &hal_device.queue, self, - caps.alignments.clone(), - caps.downlevel.clone(), desc, trace_path, instance_flags, @@ -336,9 +334,9 @@ impl Adapter { trace_path: Option<&std::path::Path>, ) -> Result<(Device, Queue), RequestDeviceError> { // Verify all features were exposed by the adapter - if !self.raw.features.contains(desc.features) { + if !self.raw.features.contains(desc.required_features) { return Err(RequestDeviceError::UnsupportedFeature( - desc.features - self.raw.features, + desc.required_features - self.raw.features, )); } @@ -357,7 +355,7 @@ impl Adapter { // Verify feature preconditions if desc - .features + .required_features .contains(wgt::Features::MAPPABLE_PRIMARY_BUFFERS) && self.raw.info.device_type == wgt::DeviceType::DiscreteGpu { @@ -371,17 +369,20 @@ impl Adapter { //TODO } - if let Some(failed) = check_limits(&desc.limits, &caps.limits).pop() { + if let Some(failed) = check_limits(&desc.required_limits, &caps.limits).pop() { return Err(RequestDeviceError::LimitsExceeded(failed)); } - let open = unsafe { self.raw.adapter.open(desc.features, &desc.limits) }.map_err( - |err| match err { - hal::DeviceError::Lost => RequestDeviceError::DeviceLost, - hal::DeviceError::OutOfMemory => RequestDeviceError::OutOfMemory, - hal::DeviceError::ResourceCreationFailed => RequestDeviceError::Internal, - }, - )?; + let open = unsafe { + self.raw + .adapter + .open(desc.required_features, &desc.required_limits) + } + .map_err(|err| match err { + hal::DeviceError::Lost => RequestDeviceError::DeviceLost, + hal::DeviceError::OutOfMemory => RequestDeviceError::OutOfMemory, + hal::DeviceError::ResourceCreationFailed => RequestDeviceError::Internal, + })?; self.create_device_and_queue_from_hal(open, desc, instance_flags, trace_path) } @@ -762,7 +763,7 @@ impl Global { pub fn surface_drop(&self, id: SurfaceId) { profiling::scope!("Surface::drop"); - log::info!("Surface::drop {id:?}"); + api_log!("Surface::drop {id:?}"); fn unconfigure( global: &Global, @@ -828,7 +829,7 @@ impl Global { pub fn enumerate_adapters(&self, inputs: AdapterInputs>) -> Vec { profiling::scope!("Instance::enumerate_adapters"); - log::trace!("Instance::enumerate_adapters"); + api_log!("Instance::enumerate_adapters"); let mut adapters = Vec::new(); @@ -884,8 +885,8 @@ impl Global { desc: &RequestAdapterOptions, inputs: AdapterInputs>, ) -> Result { - profiling::scope!("Instance::pick_adapter"); - log::trace!("Instance::pick_adapter"); + profiling::scope!("Instance::request_adapter"); + api_log!("Instance::request_adapter"); fn gather( _: A, @@ -1081,7 +1082,7 @@ impl Global { Backend::Gl => fid.assign(Adapter::new(hal_adapter)), _ => unreachable!(), }; - log::info!("Created Adapter {:?}", id); + resource_log!("Created Adapter {:?}", id); id } @@ -1159,7 +1160,7 @@ impl Global { pub fn adapter_drop(&self, adapter_id: AdapterId) { profiling::scope!("Adapter::drop"); - log::trace!("Adapter::drop {adapter_id:?}"); + api_log!("Adapter::drop {adapter_id:?}"); let hub = A::hub(self); let mut adapters_locked = hub.adapters.write(); @@ -1185,7 +1186,7 @@ impl Global { queue_id_in: Input, ) -> (DeviceId, QueueId, Option) { profiling::scope!("Adapter::request_device"); - log::trace!("Adapter::request_device"); + api_log!("Adapter::request_device"); let hub = A::hub(self); let device_fid = hub.devices.prepare::(device_id_in); @@ -1202,13 +1203,13 @@ impl Global { Err(e) => break e, }; let (device_id, _) = device_fid.assign(device); - log::info!("Created Device {:?}", device_id); + resource_log!("Created Device {:?}", device_id); let device = hub.devices.get(device_id).unwrap(); queue.device = Some(device.clone()); let (queue_id, _) = queue_fid.assign(queue); - log::info!("Created Queue {:?}", queue_id); + resource_log!("Created Queue {:?}", queue_id); device.queue_id.write().replace(queue_id); @@ -1254,13 +1255,13 @@ impl Global { Err(e) => break e, }; let (device_id, _) = devices_fid.assign(device); - log::info!("Created Device {:?}", device_id); + resource_log!("Created Device {:?}", device_id); let device = hub.devices.get(device_id).unwrap(); queue.device = Some(device.clone()); let (queue_id, _) = queues_fid.assign(queue); - log::info!("Created Queue {:?}", queue_id); + resource_log!("Created Queue {:?}", queue_id); device.queue_id.write().replace(queue_id); diff --git a/third_party/rust/wgpu-core/src/lib.rs b/third_party/rust/wgpu-core/src/lib.rs index 6a3377a13212c..944d7eff46232 100644 --- a/third_party/rust/wgpu-core/src/lib.rs +++ b/third_party/rust/wgpu-core/src/lib.rs @@ -279,6 +279,26 @@ macro_rules! gfx_select { }; } +#[cfg(feature = "api_log_info")] +macro_rules! api_log { + ($($arg:tt)+) => (log::info!($($arg)+)) +} +#[cfg(not(feature = "api_log_info"))] +macro_rules! api_log { + ($($arg:tt)+) => (log::trace!($($arg)+)) +} +pub(crate) use api_log; + +#[cfg(feature = "resource_log_info")] +macro_rules! resource_log { + ($($arg:tt)+) => (log::info!($($arg)+)) +} +#[cfg(not(feature = "resource_log_info"))] +macro_rules! resource_log { + ($($arg:tt)+) => (log::trace!($($arg)+)) +} +pub(crate) use resource_log; + /// Fast hash map used internally. type FastHashMap = std::collections::HashMap>; diff --git a/third_party/rust/wgpu-core/src/pipeline.rs b/third_party/rust/wgpu-core/src/pipeline.rs index e02cb45786a70..50b5c91ce8d94 100644 --- a/third_party/rust/wgpu-core/src/pipeline.rs +++ b/third_party/rust/wgpu-core/src/pipeline.rs @@ -7,7 +7,7 @@ use crate::{ hal_api::HalApi, id::{ComputePipelineId, PipelineLayoutId, RenderPipelineId, ShaderModuleId}, resource::{Resource, ResourceInfo, ResourceType}, - validation, Label, + resource_log, validation, Label, }; use arrayvec::ArrayVec; use std::{borrow::Cow, error::Error, fmt, marker::PhantomData, num::NonZeroU32, sync::Arc}; @@ -54,8 +54,8 @@ pub struct ShaderModule { impl Drop for ShaderModule { fn drop(&mut self) { - log::info!("Destroying ShaderModule {:?}", self.info.label()); if let Some(raw) = self.raw.take() { + resource_log!("Destroy raw ShaderModule {}", self.info.label()); #[cfg(feature = "trace")] if let Some(ref mut trace) = *self.device.trace.lock() { trace.add(trace::Action::DestroyShaderModule(self.info.id())); @@ -253,8 +253,8 @@ pub struct ComputePipeline { impl Drop for ComputePipeline { fn drop(&mut self) { - log::info!("Destroying ComputePipeline {:?}", self.info.label()); if let Some(raw) = self.raw.take() { + resource_log!("Destroy raw ComputePipeline {}", self.info.label()); unsafe { use hal::Device; self.device.raw().destroy_compute_pipeline(raw); @@ -494,8 +494,8 @@ pub struct RenderPipeline { impl Drop for RenderPipeline { fn drop(&mut self) { - log::info!("Destroying RenderPipeline {:?}", self.info.label()); if let Some(raw) = self.raw.take() { + resource_log!("Destroy raw RenderPipeline {}", self.info.label()); unsafe { use hal::Device; self.device.raw().destroy_render_pipeline(raw); diff --git a/third_party/rust/wgpu-core/src/present.rs b/third_party/rust/wgpu-core/src/present.rs index 7d0b980574f58..0e0ca9a1a6009 100644 --- a/third_party/rust/wgpu-core/src/present.rs +++ b/third_party/rust/wgpu-core/src/present.rs @@ -77,6 +77,12 @@ pub enum ConfigureSurfaceError { PreviousOutputExists, #[error("Both `Surface` width and height must be non-zero. Wait to recreate the `Surface` until the window has non-zero area.")] ZeroArea, + #[error("`Surface` width and height must be within the maximum supported texture size. Requested was ({width}, height), maximum extent is {max_texture_dimension_2d}.")] + TooLarge { + width: u32, + height: u32, + max_texture_dimension_2d: u32, + }, #[error("Surface does not support the adapter's queue family")] UnsupportedQueueFamily, #[error("Requested format {requested:?} is not in list of supported formats: {available:?}")] @@ -196,6 +202,7 @@ impl Global { dimension: wgt::TextureViewDimension::D2, usage: hal::TextureUses::COLOR_TARGET, range: wgt::ImageSubresourceRange::default(), + plane: None, }; let clear_view = unsafe { hal::Device::create_texture_view( @@ -230,7 +237,7 @@ impl Global { }; let (id, resource) = fid.assign(texture); - log::info!("Created CURRENT Surface Texture {:?}", id); + log::debug!("Created CURRENT Surface Texture {:?}", id); { // register it in the device tracker as uninitialized diff --git a/third_party/rust/wgpu-core/src/registry.rs b/third_party/rust/wgpu-core/src/registry.rs index 3c93bb31cbf38..3e9003621ff05 100644 --- a/third_party/rust/wgpu-core/src/registry.rs +++ b/third_party/rust/wgpu-core/src/registry.rs @@ -122,9 +122,6 @@ impl> Registry { data: &self.storage, } } - pub(crate) fn contains(&self, id: I) -> bool { - self.read().contains(id) - } pub(crate) fn try_get(&self, id: I) -> Result>, InvalidId> { self.read().try_get(id).map(|o| o.cloned()) } diff --git a/third_party/rust/wgpu-core/src/resource.rs b/third_party/rust/wgpu-core/src/resource.rs index 30deff80c2d5d..49d36a7acc2ed 100644 --- a/third_party/rust/wgpu-core/src/resource.rs +++ b/third_party/rust/wgpu-core/src/resource.rs @@ -13,7 +13,7 @@ use crate::{ }, identity::{GlobalIdentityHandlerFactory, IdentityManager}, init_tracker::{BufferInitTracker, TextureInitTracker}, - resource, + resource, resource_log, track::TextureSelector, validation::MissingBufferUsageError, Label, SubmissionIndex, @@ -79,7 +79,6 @@ impl Drop for ResourceInfo { if let Some(identity) = self.identity.as_ref() { let id = self.id.as_ref().unwrap(); identity.free(*id); - log::info!("Freeing {:?}", self.label()); } } } @@ -418,8 +417,8 @@ pub struct Buffer { impl Drop for Buffer { fn drop(&mut self) { - log::info!("Destroying Buffer {:?}", self.info.label()); if let Some(raw) = self.raw.take() { + resource_log!("Destroy raw Buffer {}", self.info.label()); unsafe { use hal::Device; self.device.raw().destroy_buffer(raw); @@ -639,8 +638,8 @@ pub struct StagingBuffer { impl Drop for StagingBuffer { fn drop(&mut self) { - log::info!("Destroying StagingBuffer {:?}", self.info.label()); if let Some(raw) = self.raw.lock().take() { + resource_log!("Destroy raw StagingBuffer {}", self.info.label()); unsafe { use hal::Device; self.device.raw().destroy_buffer(raw); @@ -722,7 +721,7 @@ pub struct Texture { impl Drop for Texture { fn drop(&mut self) { - log::info!("Destroying Texture {:?}", self.info.label()); + resource_log!("Destroy raw Texture {}", self.info.label()); use hal::Device; let mut clear_mode = self.clear_mode.write(); let clear_mode = &mut *clear_mode; @@ -989,6 +988,8 @@ pub struct TextureViewDescriptor<'a> { pub dimension: Option, /// Range within the texture that is accessible via this view. pub range: wgt::ImageSubresourceRange, + /// The plane of the texture view. + pub plane: Option, } #[derive(Debug)] @@ -1038,8 +1039,8 @@ pub struct TextureView { impl Drop for TextureView { fn drop(&mut self) { - log::info!("Destroying TextureView {:?}", self.info.label()); if let Some(raw) = self.raw.take() { + resource_log!("Destroy raw TextureView {}", self.info.label()); unsafe { use hal::Device; self.device.raw().destroy_texture_view(raw); @@ -1099,6 +1100,16 @@ pub enum CreateTextureViewError { texture: wgt::TextureFormat, view: wgt::TextureFormat, }, + #[error("Invalid texture view plane `{plane:?}` with view format `{view_format:?}`")] + InvalidTextureViewPlane { + plane: Option, + view_format: wgt::TextureFormat, + }, + #[error("Invalid texture view plane `{plane:?}` on non-planar texture `{texture_format:?}`")] + InvalidTextureViewPlaneOnNonplanarTexture { + plane: Option, + texture_format: wgt::TextureFormat, + }, } #[derive(Clone, Debug, Error)] @@ -1160,7 +1171,7 @@ pub struct Sampler { impl Drop for Sampler { fn drop(&mut self) { - log::info!("Destroying Sampler {:?}", self.info.label()); + resource_log!("Destroy raw Sampler {}", self.info.label()); if let Some(raw) = self.raw.take() { unsafe { use hal::Device; @@ -1257,7 +1268,7 @@ pub struct QuerySet { impl Drop for QuerySet { fn drop(&mut self) { - log::info!("Destroying QuerySet {:?}", self.info.label()); + resource_log!("Destroy raw QuerySet {}", self.info.label()); if let Some(raw) = self.raw.take() { unsafe { use hal::Device; diff --git a/third_party/rust/wgpu-core/src/storage.rs b/third_party/rust/wgpu-core/src/storage.rs index 0135f6ba49fe6..9b928839179d6 100644 --- a/third_party/rust/wgpu-core/src/storage.rs +++ b/third_party/rust/wgpu-core/src/storage.rs @@ -16,7 +16,7 @@ pub(crate) enum Element { /// Like `Occupied`, but the resource has been marked as destroyed /// and hasn't been dropped yet. - Destroyed(Arc, Epoch), + Destroyed(Epoch), /// Like `Occupied`, but an error occurred when creating the /// resource. @@ -80,7 +80,7 @@ where Some(&Element::Vacant) => false, Some( &Element::Occupied(_, storage_epoch) - | &Element::Destroyed(_, storage_epoch) + | &Element::Destroyed(storage_epoch) | &Element::Error(storage_epoch, _), ) => storage_epoch == epoch, None => false, @@ -145,7 +145,7 @@ where } match std::mem::replace(&mut self.map[index], element) { Element::Vacant => {} - Element::Destroyed(_, storage_epoch) => { + Element::Destroyed(storage_epoch) => { assert_ne!( epoch, storage_epoch, @@ -173,13 +173,13 @@ where } pub(crate) fn insert(&mut self, id: I, value: Arc) { - log::info!("User is inserting {}{:?}", T::TYPE, id); + log::trace!("User is inserting {}{:?}", T::TYPE, id); let (index, epoch, _backend) = id.unzip(); self.insert_impl(index as usize, epoch, Element::Occupied(value, epoch)) } pub(crate) fn insert_error(&mut self, id: I, label: &str) { - log::info!("User is insering as error {}{:?}", T::TYPE, id); + log::trace!("User is insering as error {}{:?}", T::TYPE, id); let (index, epoch, _) = id.unzip(); self.insert_impl( index as usize, @@ -208,36 +208,35 @@ where let slot = &mut self.map[index as usize]; // borrowck dance: we have to move the element out before we can replace it // with another variant with the same value. - if let &mut Element::Occupied(..) = slot { + if let &mut Element::Occupied(_, e) = slot { if let Element::Occupied(value, storage_epoch) = - std::mem::replace(slot, Element::Vacant) + std::mem::replace(slot, Element::Destroyed(e)) { debug_assert_eq!(storage_epoch, epoch); - *slot = Element::Destroyed(value, storage_epoch); + return Ok(value); } } - - if let Element::Destroyed(ref value, ..) = *slot { - Ok(value.clone()) - } else { - Err(InvalidId) - } + Err(InvalidId) } pub(crate) fn force_replace(&mut self, id: I, value: T) { - log::info!("User is replacing {}{:?}", T::TYPE, id); + log::trace!("User is replacing {}{:?}", T::TYPE, id); let (index, epoch, _) = id.unzip(); self.map[index as usize] = Element::Occupied(Arc::new(value), epoch); } pub(crate) fn remove(&mut self, id: I) -> Option> { - log::info!("User is removing {}{:?}", T::TYPE, id); + log::trace!("User is removing {}{:?}", T::TYPE, id); let (index, epoch, _) = id.unzip(); match std::mem::replace(&mut self.map[index as usize], Element::Vacant) { - Element::Occupied(value, storage_epoch) | Element::Destroyed(value, storage_epoch) => { + Element::Occupied(value, storage_epoch) => { assert_eq!(epoch, storage_epoch); Some(value) } + Element::Destroyed(storage_epoch) => { + assert_eq!(epoch, storage_epoch); + None + } Element::Error(..) => None, Element::Vacant => panic!("Cannot remove a vacant resource"), } diff --git a/third_party/rust/wgpu-core/src/track/buffer.rs b/third_party/rust/wgpu-core/src/track/buffer.rs index 932993681a0fe..4b2a9a8abe2c8 100644 --- a/third_party/rust/wgpu-core/src/track/buffer.rs +++ b/third_party/rust/wgpu-core/src/track/buffer.rs @@ -293,7 +293,7 @@ pub(crate) struct BufferTracker { } impl ResourceTracker> for BufferTracker { - /// Removes the buffer `id` from this tracker if it is otherwise unused. + /// Try to remove the buffer `id` from this tracker if it is otherwise unused. /// /// A buffer is 'otherwise unused' when the only references to it are: /// @@ -308,13 +308,12 @@ impl ResourceTracker> for BufferTracker { /// `triage_suspected` will remove 3), leaving 1) as the sole /// remaining reference. /// - /// Return `true` if this tracker contained the buffer `id`. This - /// implies that we removed it. + /// Returns true if the resource was removed or if not existing in metadata. /// /// [`Device::trackers`]: crate::device::Device /// [`self.metadata`]: BufferTracker::metadata /// [`Hub::buffers`]: crate::hub::Hub::buffers - fn remove_abandoned(&mut self, id: BufferId, external_count: usize) -> bool { + fn remove_abandoned(&mut self, id: BufferId) -> bool { let index = id.unzip().0 as usize; if index > self.metadata.size() { @@ -326,24 +325,23 @@ impl ResourceTracker> for BufferTracker { unsafe { if self.metadata.contains_unchecked(index) { let existing_ref_count = self.metadata.get_ref_count_unchecked(index); - //2 ref count if only in Device Tracker and suspected resource itself and already released from user - //so not appearing in Registry - let min_ref_count = 1 + external_count; - if existing_ref_count <= min_ref_count { + //RefCount 2 means that resource is hold just by DeviceTracker and this suspected resource itself + //so it's already been released from user and so it's not inside Registry\Storage + if existing_ref_count <= 2 { self.metadata.remove(index); - log::info!("Buffer {:?} is not tracked anymore", id,); + log::trace!("Buffer {:?} is not tracked anymore", id,); return true; } else { - log::info!( + log::trace!( "Buffer {:?} is still referenced from {}", id, existing_ref_count ); + return false; } } } - - false + true } } diff --git a/third_party/rust/wgpu-core/src/track/metadata.rs b/third_party/rust/wgpu-core/src/track/metadata.rs index 8001776e8c6e9..3464170ebfc63 100644 --- a/third_party/rust/wgpu-core/src/track/metadata.rs +++ b/third_party/rust/wgpu-core/src/track/metadata.rs @@ -122,14 +122,7 @@ impl> ResourceMetadata { /// existing tables. See `tracker_assert_in_bounds`. #[inline(always)] pub(super) unsafe fn get_ref_count_unchecked(&self, index: usize) -> usize { - unsafe { - Arc::strong_count( - self.resources - .get_unchecked(index) - .as_ref() - .unwrap_unchecked(), - ) - } + unsafe { Arc::strong_count(self.get_resource_unchecked(index)) } } /// Returns an iterator over the resources owned by `self`. diff --git a/third_party/rust/wgpu-core/src/track/mod.rs b/third_party/rust/wgpu-core/src/track/mod.rs index bd8d3a5580e0c..c2d5dc3c200e3 100644 --- a/third_party/rust/wgpu-core/src/track/mod.rs +++ b/third_party/rust/wgpu-core/src/track/mod.rs @@ -489,7 +489,7 @@ where Id: TypedId, R: resource::Resource, { - fn remove_abandoned(&mut self, id: Id, external_count: usize) -> bool; + fn remove_abandoned(&mut self, id: Id) -> bool; } /// A full double sided tracker used by CommandBuffers and the Device. diff --git a/third_party/rust/wgpu-core/src/track/stateless.rs b/third_party/rust/wgpu-core/src/track/stateless.rs index e88c0c0c61a77..747a55db6d8e9 100644 --- a/third_party/rust/wgpu-core/src/track/stateless.rs +++ b/third_party/rust/wgpu-core/src/track/stateless.rs @@ -9,7 +9,8 @@ use std::{marker::PhantomData, sync::Arc}; use parking_lot::Mutex; use crate::{ - hal_api::HalApi, id::TypedId, resource::Resource, storage::Storage, track::ResourceMetadata, + hal_api::HalApi, id::TypedId, resource::Resource, resource_log, storage::Storage, + track::ResourceMetadata, }; use super::ResourceTracker; @@ -77,44 +78,45 @@ pub(crate) struct StatelessTracker> { impl> ResourceTracker for StatelessTracker { - /// Removes the given resource from the tracker iff we have the last reference to the + /// Try to remove the given resource from the tracker iff we have the last reference to the /// resource and the epoch matches. /// - /// Returns true if the resource was removed. + /// Returns true if the resource was removed or if not existing in metadata. /// /// If the ID is higher than the length of internal vectors, /// false will be returned. - fn remove_abandoned(&mut self, id: Id, external_count: usize) -> bool { + fn remove_abandoned(&mut self, id: Id) -> bool { let index = id.unzip().0 as usize; if index > self.metadata.size() { return false; } + resource_log!("StatelessTracker::remove_abandoned {id:?}"); + self.tracker_assert_in_bounds(index); unsafe { if self.metadata.contains_unchecked(index) { let existing_ref_count = self.metadata.get_ref_count_unchecked(index); - //2 ref count if only in Device Tracker and suspected resource itself and already released from user - //so not appearing in Registry - let min_ref_count = 1 + external_count; - if existing_ref_count <= min_ref_count { + //RefCount 2 means that resource is hold just by DeviceTracker and this suspected resource itself + //so it's already been released from user and so it's not inside Registry\Storage + if existing_ref_count <= 2 { self.metadata.remove(index); - log::info!("{} {:?} is not tracked anymore", T::TYPE, id,); + log::trace!("{} {:?} is not tracked anymore", T::TYPE, id,); return true; } else { - log::info!( + log::trace!( "{} {:?} is still referenced from {}", T::TYPE, id, existing_ref_count ); + return false; } } } - - false + true } } diff --git a/third_party/rust/wgpu-core/src/track/texture.rs b/third_party/rust/wgpu-core/src/track/texture.rs index bda2b9f850743..46e3fada0cf5d 100644 --- a/third_party/rust/wgpu-core/src/track/texture.rs +++ b/third_party/rust/wgpu-core/src/track/texture.rs @@ -394,14 +394,14 @@ pub(crate) struct TextureTracker { } impl ResourceTracker> for TextureTracker { - /// Removes the given resource from the tracker iff we have the last reference to the + /// Try to remove the given resource from the tracker iff we have the last reference to the /// resource and the epoch matches. /// - /// Returns true if the resource was removed. + /// Returns true if the resource was removed or if not existing in metadata. /// /// If the ID is higher than the length of internal vectors, /// false will be returned. - fn remove_abandoned(&mut self, id: TextureId, external_count: usize) -> bool { + fn remove_abandoned(&mut self, id: TextureId) -> bool { let index = id.unzip().0 as usize; if index > self.metadata.size() { @@ -413,26 +413,25 @@ impl ResourceTracker> for TextureTracker { unsafe { if self.metadata.contains_unchecked(index) { let existing_ref_count = self.metadata.get_ref_count_unchecked(index); - //2 ref count if only in Device Tracker and suspected resource itself and already released from user - //so not appearing in Registry - let min_ref_count = 1 + external_count; - if existing_ref_count <= min_ref_count { + //RefCount 2 means that resource is hold just by DeviceTracker and this suspected resource itself + //so it's already been released from user and so it's not inside Registry\Storage + if existing_ref_count <= 2 { self.start_set.complex.remove(&index); self.end_set.complex.remove(&index); self.metadata.remove(index); - log::info!("Texture {:?} is not tracked anymore", id,); + log::trace!("Texture {:?} is not tracked anymore", id,); return true; } else { - log::info!( + log::trace!( "Texture {:?} is still referenced from {}", id, existing_ref_count ); + return false; } } } - - false + true } } diff --git a/third_party/rust/wgpu-core/src/validation.rs b/third_party/rust/wgpu-core/src/validation.rs index b523bf9a7385a..6eb52376b8021 100644 --- a/third_party/rust/wgpu-core/src/validation.rs +++ b/third_party/rust/wgpu-core/src/validation.rs @@ -560,7 +560,9 @@ impl Resource { } naga::ScalarKind::Sint => wgt::TextureSampleType::Sint, naga::ScalarKind::Uint => wgt::TextureSampleType::Uint, - naga::ScalarKind::Bool => unreachable!(), + naga::ScalarKind::AbstractInt + | naga::ScalarKind::AbstractFloat + | naga::ScalarKind::Bool => unreachable!(), }, view_dimension, multisampled: multi, @@ -690,6 +692,7 @@ impl NumericType { | Tf::Depth24PlusStencil8 => { panic!("Unexpected depth format") } + Tf::NV12 => panic!("Unexpected nv12 format"), Tf::Rgb9e5Ufloat => (NumericDimension::Vector(Vs::Tri), Scalar::F32), Tf::Bc1RgbaUnorm | Tf::Bc1RgbaUnormSrgb diff --git a/third_party/rust/wgpu-hal/.cargo-checksum.json b/third_party/rust/wgpu-hal/.cargo-checksum.json index e9d819cb73847..11b0a2337c73a 100644 --- a/third_party/rust/wgpu-hal/.cargo-checksum.json +++ b/third_party/rust/wgpu-hal/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"af8f5b97c66922b8f68e5214102cc79befc3a3a86984a611a3bdc01fae168523","LICENSE.APACHE":"a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9","LICENSE.MIT":"c7fea58d1cfe49634cd92e54fc10a9d871f4b275321a4cd8c09e449122caaeb4","README.md":"78377f5876fafd77963eff7e3c2ba3a7e3ad5cf9201b09ed5612e49c2288eb18","examples/halmark/main.rs":"360828f6f103ce966a152ceaff50087b59d0eac580fac12c8f89850024ccc233","examples/halmark/shader.wgsl":"26c256ec36d6f0e9a1647431ca772766bee4382d64eaa718ba7b488dcfb6bcca","examples/raw-gles.em.html":"70fbe68394a1a4522192de1dcfaf7d399f60d7bdf5de70b708f9bb0417427546","examples/raw-gles.rs":"33f536693b08a9f00b0358416be8f368894bf92a2e673b16622fa9c244854c91","src/auxil/dxgi/conv.rs":"536a6ff638ce32bdbf7cd697270f563c14f2c8cc013bb0e9565e06dc5127730a","src/auxil/dxgi/exception.rs":"baad31f4529f1cf9d10519c4cceccbb21ed9bba7d7ea99e4789c1d5ddf3a450b","src/auxil/dxgi/factory.rs":"65c758d6583c2fdac0b3d48d1a0a2a414ff913efc4f3913a38bd660819c3a2e2","src/auxil/dxgi/mod.rs":"a202564d9ac97530b16a234b87d180cd345aae705e082a9b1177dcde813645f9","src/auxil/dxgi/result.rs":"20c8eb03d738062dff198feca6327addb9882ed0462be842c789eadf7dca0573","src/auxil/dxgi/time.rs":"b6f966b250e9424d5d7e4065f2108cba87197c1e30baae6d87083055d1bc5a4b","src/auxil/mod.rs":"c38f0d3b10804d1c1d7e3b8e4a975fcb87271f8b1904f2f4a3153cceddafb56b","src/auxil/renderdoc.rs":"c2f849f70f576b0c9b0d32dd155b6a6353f74dff59cbeeaa994a12789d047c0f","src/dx11/adapter.rs":"cacb8243f9107f63bc3247a76b3d28adc3b87d79ffee0af90214a483ab51285b","src/dx11/command.rs":"e4959ec3dc6f8494844e01b56ba162ba91270c9c9a52e83315c8730fcfe188b9","src/dx11/device.rs":"4ee1880b0d48ed054654e936c76b3e7b7e370fbf79c2f0af370f8de350fd94ff","src/dx11/instance.rs":"206b38346de245e315e762b8de81ca26c74d10aad26a488713945d0e1c802e2b","src/dx11/library.rs":"1b4c3575fd8fd30d07a61ce68ec3c930305c4df5aa5dcf54dd1fdd4edff590d4","src/dx11/mod.rs":"1f2e7f04801b4e65aa27183bc0ddeee0dd3aa686bac4056649dbd97ddef142e1","src/dx12/adapter.rs":"03763cc928b38a4153ab91d7a6ab7d38e2f64c7590f2e17a29c56e0a93b1284f","src/dx12/command.rs":"8a99d028ce379f14c19d88069c91a58d6fd7b1957e0a114c369f51a0bfaee1e9","src/dx12/conv.rs":"24d6ac9808f7534f3480ba2eb563f98f1441c8ad2b4c6e86b2700f5ac812e99a","src/dx12/descriptor.rs":"d9e295c48dc7d1759fd121c927c2218c1bde90e9f1b35f2ad01b610b184b614e","src/dx12/device.rs":"0ac995a92acd8cbe160f58f7347ed50ce5c0d16a3da496127aff66eecca765e7","src/dx12/instance.rs":"719125a6adb69f16df1a0069c8a1ccb5792169a00abdf2e38cc26b633b15768a","src/dx12/mod.rs":"9c5c3babcdfc0daa81ba85a2729020e102e5bcc7c2ec35d3d228ccf477775edf","src/dx12/shader_compilation.rs":"0589ed592cbd939f821d2801c82ee973c28844292682d37db84048ba21e6c72b","src/dx12/suballocation.rs":"eec45b2d23e979f7d7f33d982a89ae2f92e528b22f1bb7d2e5dd52582a25a601","src/dx12/types.rs":"9573736baaa0ef607367c3b72144556d24faf677a26bb8df49a4372a1348e06b","src/dx12/view.rs":"c09241520377e6a47ad8822c69075e6e16e6c558e18bb64398c8d7424fc57dcf","src/empty.rs":"8288689e0016c60e58d1c3e24fe3a9ef247bb23961c9f01482a0bf21870379a0","src/gles/adapter.rs":"6e38936a7a3f01f9aa13b6568e495499b320d009f33146cf978cf57bcd795013","src/gles/command.rs":"9c4f2e474d0fd512f4d8da2a42ca309f9ec3c7bbf472d043b59a180cb3b0f459","src/gles/conv.rs":"23f7f82b74fb01dc09cf9b696a6977d993e65c4f700b3029984ff2dbdc9b3dda","src/gles/device.rs":"8e13133b398f25850e342777edd06076188644a1013004b2a08e00845d62e6a6","src/gles/egl.rs":"89212bdacbb9dc43eebcc7b74fb612a69d35ffc1dfe2b626820c44c61256c4c9","src/gles/emscripten.rs":"19bb73a9d140645f3f32cd48b002151711a9b8456e213eab5f3a2be79239e147","src/gles/mod.rs":"43b3e9d03f9eca064832dd307e4b8b8f1d2d3bbcdad21c87af3854f9bd479e3d","src/gles/queue.rs":"ee8e9673b4856baa23026009ee41fe92c5c91503b07c484199229334a99f9e0c","src/gles/shaders/clear.frag":"9133ed8ed97d3641fbb6b5f5ea894a3554c629ccc1b80a5fc9221d7293aa1954","src/gles/shaders/clear.vert":"a543768725f4121ff2e9e1fb5b00644931e9d6f2f946c0ef01968afb5a135abd","src/gles/shaders/srgb_present.frag":"dd9a43c339a2fa4ccf7f6a1854c6f400cabf271a7d5e9230768e9f39d47f3ff5","src/gles/shaders/srgb_present.vert":"6e85d489403d80b81cc94790730bb53b309dfc5eeede8f1ea3412a660f31d357","src/gles/web.rs":"5623c8c78584c5e9182502e0997bd11e627e67ccd23d516e65526f415215de2f","src/gles/wgl.rs":"ec1c958acc903af43c29e60059c2c71257b5735312c15679647daed774ad01a1","src/lib.rs":"04b61b4d07fc001fd3c2d95d7577bc485e7ac67406e7052681222d32233cc0ae","src/metal/adapter.rs":"9d200608a3f931ee2d37f085809c761eb809bae2058f8caa25c592c7d2c19752","src/metal/command.rs":"95512642ff903a57b661b10b72b44c065a760a3096bcb2aabbd9977e6dba0d5b","src/metal/conv.rs":"0bce6a8d0ccef16783475803d70d35e03ab7938c19374e22c9d253abe1f8b111","src/metal/device.rs":"d2fb16e8d7cfc0c9e3141dcf1245a1f0ea8a891962c0cd83c0cd4450e7acaf36","src/metal/mod.rs":"3c49207a7cc88b75785aa4886147121192d19d01cdc621319aff36b3659fa98c","src/metal/surface.rs":"01539fa9f22c26fdcca5ee915ca97cf76cecc7fae237347dfc9a813ae13e98cd","src/metal/time.rs":"c32d69f30e846dfcc0e39e01097fb80df63b2bebb6586143bb62494999850246","src/vulkan/adapter.rs":"d9af751f16d30b3d129a7481d1f529ef53cc7c6e0ca0b6f25181f8449f23b6fd","src/vulkan/command.rs":"e10346068cdf97f50b98b5d7481b09f601319843cf843206c95c597fad36144e","src/vulkan/conv.rs":"63abaed541f7f5263f5e3a27e3e7fad419cb32c7b8af25081aa547add12087a8","src/vulkan/device.rs":"1557ee3b93a085b1704b858a42a7b3b8c742c20b87ab325e9f0096ec5b97bc59","src/vulkan/instance.rs":"e16d2e849b2ead8d83d354946bbffd03c26e2b024b07fe8b59c3ea47093a0a12","src/vulkan/mod.rs":"7ed5c34156d70808e7845575d93a8c2a07bfa989d455c3848e93e8ae372b99ff"},"package":null} \ No newline at end of file +{"files":{"Cargo.toml":"f472b730bbef76aa4770fd53b53535c1d0773145c8a40aac2deb6e7465ff70bc","LICENSE.APACHE":"a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9","LICENSE.MIT":"c7fea58d1cfe49634cd92e54fc10a9d871f4b275321a4cd8c09e449122caaeb4","README.md":"099ee611a911dc19330a61bffcde13663929a51b25ac528ee33ea796d695491e","examples/halmark/main.rs":"c74696fd871200a46e3592ce5a662c42d9587c13b7def75c5cac4c34d9685ad5","examples/halmark/shader.wgsl":"26c256ec36d6f0e9a1647431ca772766bee4382d64eaa718ba7b488dcfb6bcca","examples/raw-gles.em.html":"70fbe68394a1a4522192de1dcfaf7d399f60d7bdf5de70b708f9bb0417427546","examples/raw-gles.rs":"81210e7603f5304fa1dc294f984eacf27e18df7d3f228063f6acb0d7985c37cd","src/auxil/dxgi/conv.rs":"3cd184da7712d1cea10cad740afb4c9dbdb40b69d7386d56dbaa15f4853c6ac7","src/auxil/dxgi/exception.rs":"fc68c6211c82a912b454c3004185f46a1416bce38ddc5b0555e0def6539cfb27","src/auxil/dxgi/factory.rs":"65c758d6583c2fdac0b3d48d1a0a2a414ff913efc4f3913a38bd660819c3a2e2","src/auxil/dxgi/mod.rs":"a202564d9ac97530b16a234b87d180cd345aae705e082a9b1177dcde813645f9","src/auxil/dxgi/result.rs":"20c8eb03d738062dff198feca6327addb9882ed0462be842c789eadf7dca0573","src/auxil/dxgi/time.rs":"b6f966b250e9424d5d7e4065f2108cba87197c1e30baae6d87083055d1bc5a4b","src/auxil/mod.rs":"c38f0d3b10804d1c1d7e3b8e4a975fcb87271f8b1904f2f4a3153cceddafb56b","src/auxil/renderdoc.rs":"c2f849f70f576b0c9b0d32dd155b6a6353f74dff59cbeeaa994a12789d047c0f","src/dx11/adapter.rs":"173e99507610282a7858c142ffe2b9755dac0d61bcaed7ae69394002d476c4f6","src/dx11/command.rs":"3a329369bbd9deeb2fbe3c274a5a5d5f0d2da9eeb64b76592e922446e52c5a51","src/dx11/device.rs":"4ee1880b0d48ed054654e936c76b3e7b7e370fbf79c2f0af370f8de350fd94ff","src/dx11/instance.rs":"206b38346de245e315e762b8de81ca26c74d10aad26a488713945d0e1c802e2b","src/dx11/library.rs":"1b4c3575fd8fd30d07a61ce68ec3c930305c4df5aa5dcf54dd1fdd4edff590d4","src/dx11/mod.rs":"1f2e7f04801b4e65aa27183bc0ddeee0dd3aa686bac4056649dbd97ddef142e1","src/dx12/adapter.rs":"33c4b790c22115d68db11883a8fb8da194fba0937636a56cc779b7bf48a5ce44","src/dx12/command.rs":"9c6b24f7a09c54b61ac36d0cbd74b2ff8e5c5474ee834f06f39cf18caf95b7d2","src/dx12/conv.rs":"24d6ac9808f7534f3480ba2eb563f98f1441c8ad2b4c6e86b2700f5ac812e99a","src/dx12/descriptor.rs":"d9e295c48dc7d1759fd121c927c2218c1bde90e9f1b35f2ad01b610b184b614e","src/dx12/device.rs":"6baf4b32df1f91a7d2060b00a14850530b857de1147c8cf1d85abd6f5e90e4c2","src/dx12/instance.rs":"719125a6adb69f16df1a0069c8a1ccb5792169a00abdf2e38cc26b633b15768a","src/dx12/mod.rs":"fe9e7ed1786c7142fa5bf04e9ad2ee729fdd92c926bb734afa75651206cf737d","src/dx12/shader_compilation.rs":"0589ed592cbd939f821d2801c82ee973c28844292682d37db84048ba21e6c72b","src/dx12/suballocation.rs":"eec45b2d23e979f7d7f33d982a89ae2f92e528b22f1bb7d2e5dd52582a25a601","src/dx12/types.rs":"9573736baaa0ef607367c3b72144556d24faf677a26bb8df49a4372a1348e06b","src/dx12/view.rs":"7db9595d0f67c441605ef5830555c27fc2e9c9c6aa0151baf52c9d04fc536617","src/empty.rs":"de72a7dcbd2b562195a3a49a4065008cb4402381b8dbb83ef348398c3f9d920e","src/gles/adapter.rs":"32f658df60a226fb4f3ff242267f442945c9c9670d7a5692301c3f90cdd1f5cf","src/gles/command.rs":"7d6a760c721e759c6c32998b5a42466fe35bcff5ecc109af42b2aaec85e444ea","src/gles/conv.rs":"9cd65b70c1a2f92f22a83dda825e175f367cbb3d6201a31d90e84aaf63e63d9b","src/gles/device.rs":"b19f2437e403e08511ff341efc63e55c78fcdeffa3785d02a892a743a26a3663","src/gles/egl.rs":"89212bdacbb9dc43eebcc7b74fb612a69d35ffc1dfe2b626820c44c61256c4c9","src/gles/emscripten.rs":"19bb73a9d140645f3f32cd48b002151711a9b8456e213eab5f3a2be79239e147","src/gles/mod.rs":"e9a232ffb9331cd3873ea7afd4bd39e07503873d592bacd576efebd58e452323","src/gles/queue.rs":"fe795add7b32ae4cd89e40db93e5bae62b6c7bc5741c71f21d292bd0a511de58","src/gles/shaders/clear.frag":"9133ed8ed97d3641fbb6b5f5ea894a3554c629ccc1b80a5fc9221d7293aa1954","src/gles/shaders/clear.vert":"a543768725f4121ff2e9e1fb5b00644931e9d6f2f946c0ef01968afb5a135abd","src/gles/shaders/srgb_present.frag":"dd9a43c339a2fa4ccf7f6a1854c6f400cabf271a7d5e9230768e9f39d47f3ff5","src/gles/shaders/srgb_present.vert":"6e85d489403d80b81cc94790730bb53b309dfc5eeede8f1ea3412a660f31d357","src/gles/web.rs":"5623c8c78584c5e9182502e0997bd11e627e67ccd23d516e65526f415215de2f","src/gles/wgl.rs":"ec1c958acc903af43c29e60059c2c71257b5735312c15679647daed774ad01a1","src/lib.rs":"072e3f2a781b9cba47d17e7fe3954697d6328cb48ecd2dd0f0f2f500efefe51a","src/metal/adapter.rs":"9ae2496b3a2df3263f2f5a53a6bd4245800c53072673c3444c274c7fffa2a8dc","src/metal/command.rs":"702edebb7aff60acc67d6e183f2dad999f2528b0f00bccc25197fb01911a3b6e","src/metal/conv.rs":"0bce6a8d0ccef16783475803d70d35e03ab7938c19374e22c9d253abe1f8b111","src/metal/device.rs":"d2fb16e8d7cfc0c9e3141dcf1245a1f0ea8a891962c0cd83c0cd4450e7acaf36","src/metal/mod.rs":"e248de570dddfad70a83ef1788d1a15b037b0e861937c8eff00dd0c09dfae82d","src/metal/surface.rs":"01539fa9f22c26fdcca5ee915ca97cf76cecc7fae237347dfc9a813ae13e98cd","src/metal/time.rs":"c32d69f30e846dfcc0e39e01097fb80df63b2bebb6586143bb62494999850246","src/vulkan/adapter.rs":"5a8d9a2757c9ec86ba7f1ac7b79cf577830908c6fd9935ea1af7519457d85562","src/vulkan/command.rs":"5f0da371d3189ce42c141039a3a435717c12077f5d09226af61b5c51e4bde68c","src/vulkan/conv.rs":"ee41a6d5a17c9474296b8e850b5dcb10452c8077e3ff70a68351a374726115b6","src/vulkan/device.rs":"c83be51f540e5a3294eb755ec8c787edc204aaea727d62b66887d7f88775a041","src/vulkan/instance.rs":"d9a084ac91a2b541b14d8ea565a7a581d281e54ec2828b64e5be2989e0113ed7","src/vulkan/mod.rs":"7ed5c34156d70808e7845575d93a8c2a07bfa989d455c3848e93e8ae372b99ff"},"package":null} \ No newline at end of file diff --git a/third_party/rust/wgpu-hal/Cargo.toml b/third_party/rust/wgpu-hal/Cargo.toml index a0ca474f13e84..6151e4d7665dc 100644 --- a/third_party/rust/wgpu-hal/Cargo.toml +++ b/third_party/rust/wgpu-hal/Cargo.toml @@ -88,7 +88,7 @@ path = "../naga" features = ["wgsl-in"] [dev-dependencies.winit] -version = "0.29.2" +version = "0.29.4" features = ["android-native-activity"] [features] @@ -146,11 +146,11 @@ vulkan = [ windows_rs = ["gpu-allocator"] [target."cfg(all(target_arch = \"wasm32\", not(target_os = \"emscripten\")))".dependencies] -js-sys = "0.3.65" +js-sys = "0.3.66" wasm-bindgen = "0.2.87" [target."cfg(all(target_arch = \"wasm32\", not(target_os = \"emscripten\")))".dependencies.web-sys] -version = "0.3.64" +version = "0.3.66" features = [ "Window", "HtmlCanvasElement", diff --git a/third_party/rust/wgpu-hal/README.md b/third_party/rust/wgpu-hal/README.md index 0ab7a0283a81a..588baa3cf5074 100644 --- a/third_party/rust/wgpu-hal/README.md +++ b/third_party/rust/wgpu-hal/README.md @@ -15,7 +15,7 @@ such as running out-of-memory, or losing the device. For the counter-example, there is no error for mapping a buffer that's not mappable. As the buffer creator, the user should already know if they can map it. -The API accept iterators in order to avoid forcing the user to store data in particular containers. The implementation doesn't guarantee that any of the iterators are drained, unless stated otherwise by the function documentation. +The API accepts iterators in order to avoid forcing the user to store data in particular containers. The implementation doesn't guarantee that any of the iterators are drained, unless stated otherwise by the function documentation. For this reason, we recommend that iterators don't do any mutating work. # Debugging diff --git a/third_party/rust/wgpu-hal/examples/halmark/main.rs b/third_party/rust/wgpu-hal/examples/halmark/main.rs index 609146454a715..60b2c144f274b 100644 --- a/third_party/rust/wgpu-hal/examples/halmark/main.rs +++ b/third_party/rust/wgpu-hal/examples/halmark/main.rs @@ -422,6 +422,7 @@ impl Example { dimension: wgt::TextureViewDimension::D2, usage: hal::TextureUses::RESOURCE, range: wgt::ImageSubresourceRange::default(), + plane: None, }; let texture_view = unsafe { device.create_texture_view(&texture, &view_desc).unwrap() }; @@ -658,6 +659,7 @@ impl Example { dimension: wgt::TextureViewDimension::D2, usage: hal::TextureUses::COLOR_TARGET, range: wgt::ImageSubresourceRange::default(), + plane: None, }; let surface_tex_view = unsafe { self.device diff --git a/third_party/rust/wgpu-hal/examples/raw-gles.rs b/third_party/rust/wgpu-hal/examples/raw-gles.rs index 81ab4171e3dd2..71e08443eaf74 100644 --- a/third_party/rust/wgpu-hal/examples/raw-gles.rs +++ b/third_party/rust/wgpu-hal/examples/raw-gles.rs @@ -142,6 +142,7 @@ fn fill_screen(exposed: &hal::ExposedAdapter, width: u32, height dimension: wgt::TextureViewDimension::D2, usage: hal::TextureUses::COLOR_TARGET, range: wgt::ImageSubresourceRange::default(), + plane: None, }, ) .unwrap() diff --git a/third_party/rust/wgpu-hal/src/auxil/dxgi/conv.rs b/third_party/rust/wgpu-hal/src/auxil/dxgi/conv.rs index f3f4a18317b88..eb74b5adf86cd 100644 --- a/third_party/rust/wgpu-hal/src/auxil/dxgi/conv.rs +++ b/third_party/rust/wgpu-hal/src/auxil/dxgi/conv.rs @@ -62,6 +62,7 @@ pub fn map_texture_format_failable(format: wgt::TextureFormat) -> Option DXGI_FORMAT_D24_UNORM_S8_UINT, Tf::Depth32Float => DXGI_FORMAT_D32_FLOAT, Tf::Depth32FloatStencil8 => DXGI_FORMAT_D32_FLOAT_S8X24_UINT, + Tf::NV12 => DXGI_FORMAT_NV12, Tf::Bc1RgbaUnorm => DXGI_FORMAT_BC1_UNORM, Tf::Bc1RgbaUnormSrgb => DXGI_FORMAT_BC1_UNORM_SRGB, Tf::Bc2RgbaUnorm => DXGI_FORMAT_BC2_UNORM, diff --git a/third_party/rust/wgpu-hal/src/auxil/dxgi/exception.rs b/third_party/rust/wgpu-hal/src/auxil/dxgi/exception.rs index 1636989b171ae..a7cab7fe55baa 100644 --- a/third_party/rust/wgpu-hal/src/auxil/dxgi/exception.rs +++ b/third_party/rust/wgpu-hal/src/auxil/dxgi/exception.rs @@ -98,7 +98,7 @@ unsafe extern "system" fn output_debug_string_handler( if cfg!(debug_assertions) && level == log::Level::Error { // Set canary and continue - crate::VALIDATION_CANARY.set(); + crate::VALIDATION_CANARY.add(message.to_string()); } excpt::EXCEPTION_CONTINUE_EXECUTION diff --git a/third_party/rust/wgpu-hal/src/dx11/adapter.rs b/third_party/rust/wgpu-hal/src/dx11/adapter.rs index 41b4b4e573d1d..3d465ae21f8a6 100644 --- a/third_party/rust/wgpu-hal/src/dx11/adapter.rs +++ b/third_party/rust/wgpu-hal/src/dx11/adapter.rs @@ -155,6 +155,10 @@ impl super::Adapter { // bgra8unorm-storage is never supported on dx11 according to: // https://learn.microsoft.com/en-us/windows/win32/direct3ddxgi/format-support-for-direct3d-11-0-feature-level-hardware#dxgi_format_b8g8r8a8_unormfcs-87 + // float32-filterable should always be available on dx11 + // https://learn.microsoft.com/en-us/windows/win32/direct3ddxgi/format-support-for-direct3d-11-0-feature-level-hardware#dxgi_format_r32g32b32a32_floatfcs-2 + features.set(wgt::Features::FLOAT32_FILTERABLE, true); + // // Fill out limits and alignments // diff --git a/third_party/rust/wgpu-hal/src/dx11/command.rs b/third_party/rust/wgpu-hal/src/dx11/command.rs index 3bbdf0a7eed1d..e5cc92bff9619 100644 --- a/third_party/rust/wgpu-hal/src/dx11/command.rs +++ b/third_party/rust/wgpu-hal/src/dx11/command.rs @@ -187,9 +187,9 @@ impl crate::CommandEncoder for super::CommandEncoder { unsafe fn draw( &mut self, - start_vertex: u32, + first_vertex: u32, vertex_count: u32, - start_instance: u32, + first_instance: u32, instance_count: u32, ) { todo!() @@ -197,10 +197,10 @@ impl crate::CommandEncoder for super::CommandEncoder { unsafe fn draw_indexed( &mut self, - start_index: u32, + first_index: u32, index_count: u32, base_vertex: i32, - start_instance: u32, + first_instance: u32, instance_count: u32, ) { todo!() diff --git a/third_party/rust/wgpu-hal/src/dx12/adapter.rs b/third_party/rust/wgpu-hal/src/dx12/adapter.rs index 9d66fd2653c62..1db9b0877da46 100644 --- a/third_party/rust/wgpu-hal/src/dx12/adapter.rs +++ b/third_party/rust/wgpu-hal/src/dx12/adapter.rs @@ -249,7 +249,8 @@ impl super::Adapter { | wgt::Features::PUSH_CONSTANTS | wgt::Features::SHADER_PRIMITIVE_INDEX | wgt::Features::RG11B10UFLOAT_RENDERABLE - | wgt::Features::DUAL_SOURCE_BLENDING; + | wgt::Features::DUAL_SOURCE_BLENDING + | wgt::Features::TEXTURE_FORMAT_NV12; //TODO: in order to expose this, we need to run a compute shader // that extract the necessary statistics out of the D3D12 result. @@ -293,11 +294,19 @@ impl super::Adapter { bgra8unorm_storage_supported, ); + // float32-filterable should always be available on d3d12 + features.set(wgt::Features::FLOAT32_FILTERABLE, true); + // TODO: Determine if IPresentationManager is supported let presentation_timer = auxil::dxgi::time::PresentationTimer::new_dxgi(); let base = wgt::Limits::default(); + let mut downlevel = wgt::DownlevelCapabilities::default(); + // https://github.com/gfx-rs/wgpu/issues/2471 + downlevel.flags -= + wgt::DownlevelFlags::VERTEX_AND_INSTANCE_INDEX_RESPECTS_RESPECTIVE_FIRST_VALUE_IN_INDIRECT_DRAW; + Some(crate::ExposedAdapter { adapter: super::Adapter { raw: adapter, @@ -392,7 +401,7 @@ impl super::Adapter { ) .unwrap(), }, - downlevel: wgt::DownlevelCapabilities::default(), + downlevel, }, }) } @@ -620,16 +629,6 @@ impl crate::Adapter for super::Adapter { // we currently use a flip effect which supports 2..=16 buffers swap_chain_sizes: 2..=16, current_extent, - // TODO: figure out the exact bounds - extents: wgt::Extent3d { - width: 16, - height: 16, - depth_or_array_layers: 1, - }..=wgt::Extent3d { - width: 4096, - height: 4096, - depth_or_array_layers: 1, - }, usage: crate::TextureUses::COLOR_TARGET | crate::TextureUses::COPY_SRC | crate::TextureUses::COPY_DST, diff --git a/third_party/rust/wgpu-hal/src/dx12/command.rs b/third_party/rust/wgpu-hal/src/dx12/command.rs index 2ea6ad4ab278f..5bbd0d4ba5cc4 100644 --- a/third_party/rust/wgpu-hal/src/dx12/command.rs +++ b/third_party/rust/wgpu-hal/src/dx12/command.rs @@ -85,7 +85,7 @@ impl super::CommandEncoder { self.pass.clear(); } - unsafe fn prepare_draw(&mut self, base_vertex: i32, base_instance: u32) { + unsafe fn prepare_draw(&mut self, first_vertex: i32, first_instance: u32) { while self.pass.dirty_vertex_buffers != 0 { let list = self.list.as_ref().unwrap(); let index = self.pass.dirty_vertex_buffers.trailing_zeros(); @@ -101,18 +101,18 @@ impl super::CommandEncoder { if let Some(root_index) = self.pass.layout.special_constants_root_index { let needs_update = match self.pass.root_elements[root_index as usize] { super::RootElement::SpecialConstantBuffer { - base_vertex: other_vertex, - base_instance: other_instance, + first_vertex: other_vertex, + first_instance: other_instance, other: _, - } => base_vertex != other_vertex || base_instance != other_instance, + } => first_vertex != other_vertex || first_instance != other_instance, _ => true, }; if needs_update { self.pass.dirty_root_elements |= 1 << root_index; self.pass.root_elements[root_index as usize] = super::RootElement::SpecialConstantBuffer { - base_vertex, - base_instance, + first_vertex, + first_instance, other: 0, }; } @@ -124,18 +124,18 @@ impl super::CommandEncoder { if let Some(root_index) = self.pass.layout.special_constants_root_index { let needs_update = match self.pass.root_elements[root_index as usize] { super::RootElement::SpecialConstantBuffer { - base_vertex, - base_instance, + first_vertex, + first_instance, other, - } => [base_vertex as u32, base_instance, other] != count, + } => [first_vertex as u32, first_instance, other] != count, _ => true, }; if needs_update { self.pass.dirty_root_elements |= 1 << root_index; self.pass.root_elements[root_index as usize] = super::RootElement::SpecialConstantBuffer { - base_vertex: count[0] as i32, - base_instance: count[1], + first_vertex: count[0] as i32, + first_instance: count[1], other: count[2], }; } @@ -168,17 +168,17 @@ impl super::CommandEncoder { } } super::RootElement::SpecialConstantBuffer { - base_vertex, - base_instance, + first_vertex, + first_instance, other, } => match self.pass.kind { Pk::Render => { - list.set_graphics_root_constant(index, base_vertex as u32, 0); - list.set_graphics_root_constant(index, base_instance, 1); + list.set_graphics_root_constant(index, first_vertex as u32, 0); + list.set_graphics_root_constant(index, first_instance, 1); } Pk::Compute => { - list.set_compute_root_constant(index, base_vertex as u32, 0); - list.set_compute_root_constant(index, base_instance, 1); + list.set_compute_root_constant(index, first_vertex as u32, 0); + list.set_compute_root_constant(index, first_instance, 1); list.set_compute_root_constant(index, other, 2); } Pk::Transfer => (), @@ -220,8 +220,8 @@ impl super::CommandEncoder { if let Some(root_index) = layout.special_constants_root_index { self.pass.root_elements[root_index as usize] = super::RootElement::SpecialConstantBuffer { - base_vertex: 0, - base_instance: 0, + first_vertex: 0, + first_instance: 0, other: 0, }; } @@ -1031,34 +1031,34 @@ impl crate::CommandEncoder for super::CommandEncoder { unsafe fn draw( &mut self, - start_vertex: u32, + first_vertex: u32, vertex_count: u32, - start_instance: u32, + first_instance: u32, instance_count: u32, ) { - unsafe { self.prepare_draw(start_vertex as i32, start_instance) }; + unsafe { self.prepare_draw(first_vertex as i32, first_instance) }; self.list.as_ref().unwrap().draw( vertex_count, instance_count, - start_vertex, - start_instance, + first_vertex, + first_instance, ); } unsafe fn draw_indexed( &mut self, - start_index: u32, + first_index: u32, index_count: u32, base_vertex: i32, - start_instance: u32, + first_instance: u32, instance_count: u32, ) { - unsafe { self.prepare_draw(base_vertex, start_instance) }; + unsafe { self.prepare_draw(base_vertex, first_instance) }; self.list.as_ref().unwrap().draw_indexed( index_count, instance_count, - start_index, + first_index, base_vertex, - start_instance, + first_instance, ); } unsafe fn draw_indirect( diff --git a/third_party/rust/wgpu-hal/src/dx12/device.rs b/third_party/rust/wgpu-hal/src/dx12/device.rs index 06e1b59a21bc8..90af93661e9e1 100644 --- a/third_party/rust/wgpu-hal/src/dx12/device.rs +++ b/third_party/rust/wgpu-hal/src/dx12/device.rs @@ -467,7 +467,11 @@ impl crate::Device for super::Device { aspects: view_desc.aspects, target_base: ( texture.resource.clone(), - texture.calc_subresource(desc.range.base_mip_level, desc.range.base_array_layer, 0), + texture.calc_subresource( + desc.range.base_mip_level, + desc.range.base_array_layer, + desc.plane.unwrap_or(0), + ), ), handle_srv: if desc.usage.intersects(crate::TextureUses::RESOURCE) { let raw_desc = unsafe { view_desc.to_srv() }; @@ -983,7 +987,7 @@ impl crate::Device for super::Device { debug_assert_eq!(ranges.len(), total_non_dynamic_entries); let (special_constants_root_index, special_constants_binding) = if desc.flags.intersects( - crate::PipelineLayoutFlags::BASE_VERTEX_INSTANCE + crate::PipelineLayoutFlags::FIRST_VERTEX_INSTANCE | crate::PipelineLayoutFlags::NUM_WORK_GROUPS, ) { let parameter_index = parameters.len(); @@ -991,7 +995,7 @@ impl crate::Device for super::Device { parameters.push(d3d12::RootParameter::constants( d3d12::ShaderVisibility::All, // really needed for VS and CS only native_binding(&bind_cbv), - 3, // 0 = base vertex, 1 = base instance, 2 = other + 3, // 0 = first_vertex, 1 = first_instance, 2 = other )); let binding = bind_cbv.clone(); bind_cbv.register += 1; diff --git a/third_party/rust/wgpu-hal/src/dx12/mod.rs b/third_party/rust/wgpu-hal/src/dx12/mod.rs index 0de992cf910ce..c50b0af16520d 100644 --- a/third_party/rust/wgpu-hal/src/dx12/mod.rs +++ b/third_party/rust/wgpu-hal/src/dx12/mod.rs @@ -291,8 +291,8 @@ enum RootElement { Empty, Constant, SpecialConstantBuffer { - base_vertex: i32, - base_instance: u32, + first_vertex: i32, + first_instance: u32, other: u32, }, /// Descriptor table. diff --git a/third_party/rust/wgpu-hal/src/dx12/view.rs b/third_party/rust/wgpu-hal/src/dx12/view.rs index e7a051b53531f..9a597e464ce27 100644 --- a/third_party/rust/wgpu-hal/src/dx12/view.rs +++ b/third_party/rust/wgpu-hal/src/dx12/view.rs @@ -14,6 +14,7 @@ pub(super) struct ViewDescriptor { array_layer_count: u32, mip_level_base: u32, mip_level_count: u32, + plane: u32, } impl crate::TextureViewDescriptor<'_> { @@ -30,6 +31,7 @@ impl crate::TextureViewDescriptor<'_> { mip_level_count: self.range.mip_level_count.unwrap_or(!0), array_layer_base: self.range.base_array_layer, array_layer_count: self.range.array_layer_count.unwrap_or(!0), + plane: self.plane.unwrap_or(0), } } } @@ -79,7 +81,7 @@ impl ViewDescriptor { *desc.u.Texture2D_mut() = d3d12_ty::D3D12_TEX2D_SRV { MostDetailedMip: self.mip_level_base, MipLevels: self.mip_level_count, - PlaneSlice: 0, + PlaneSlice: self.plane, ResourceMinLODClamp: 0.0, } } @@ -103,7 +105,7 @@ impl ViewDescriptor { MipLevels: self.mip_level_count, FirstArraySlice: self.array_layer_base, ArraySize: self.array_layer_count, - PlaneSlice: 0, + PlaneSlice: self.plane, ResourceMinLODClamp: 0.0, } } @@ -179,7 +181,7 @@ impl ViewDescriptor { unsafe { *desc.u.Texture2D_mut() = d3d12_ty::D3D12_TEX2D_UAV { MipSlice: self.mip_level_base, - PlaneSlice: 0, + PlaneSlice: self.plane, } } } @@ -190,7 +192,7 @@ impl ViewDescriptor { MipSlice: self.mip_level_base, FirstArraySlice: self.array_layer_base, ArraySize: self.array_layer_count, - PlaneSlice: 0, + PlaneSlice: self.plane, } } } @@ -250,7 +252,7 @@ impl ViewDescriptor { unsafe { *desc.u.Texture2D_mut() = d3d12_ty::D3D12_TEX2D_RTV { MipSlice: self.mip_level_base, - PlaneSlice: 0, + PlaneSlice: self.plane, } } } @@ -272,7 +274,7 @@ impl ViewDescriptor { MipSlice: self.mip_level_base, FirstArraySlice: self.array_layer_base, ArraySize: self.array_layer_count, - PlaneSlice: 0, + PlaneSlice: self.plane, } } } diff --git a/third_party/rust/wgpu-hal/src/empty.rs b/third_party/rust/wgpu-hal/src/empty.rs index a2a8c57c994e7..487d317870892 100644 --- a/third_party/rust/wgpu-hal/src/empty.rs +++ b/third_party/rust/wgpu-hal/src/empty.rs @@ -353,18 +353,18 @@ impl crate::CommandEncoder for Encoder { unsafe fn draw( &mut self, - start_vertex: u32, + first_vertex: u32, vertex_count: u32, - start_instance: u32, + first_instance: u32, instance_count: u32, ) { } unsafe fn draw_indexed( &mut self, - start_index: u32, + first_index: u32, index_count: u32, base_vertex: i32, - start_instance: u32, + first_instance: u32, instance_count: u32, ) { } diff --git a/third_party/rust/wgpu-hal/src/gles/adapter.rs b/third_party/rust/wgpu-hal/src/gles/adapter.rs index 34e61ce915786..8c35e452c1c45 100644 --- a/third_party/rust/wgpu-hal/src/gles/adapter.rs +++ b/third_party/rust/wgpu-hal/src/gles/adapter.rs @@ -379,7 +379,8 @@ impl super::Adapter { let mut downlevel_flags = wgt::DownlevelFlags::empty() | wgt::DownlevelFlags::NON_POWER_OF_TWO_MIPMAPPED_TEXTURES | wgt::DownlevelFlags::CUBE_ARRAY_TEXTURES - | wgt::DownlevelFlags::COMPARISON_SAMPLERS; + | wgt::DownlevelFlags::COMPARISON_SAMPLERS + | wgt::DownlevelFlags::VERTEX_AND_INSTANCE_INDEX_RESPECTS_RESPECTIVE_FIRST_VALUE_IN_INDIRECT_DRAW; downlevel_flags.set(wgt::DownlevelFlags::COMPUTE_SHADERS, supports_compute); downlevel_flags.set( wgt::DownlevelFlags::FRAGMENT_WRITABLE_STORAGE, @@ -389,8 +390,6 @@ impl super::Adapter { wgt::DownlevelFlags::INDIRECT_EXECUTION, supported((3, 1), (4, 3)) || extensions.contains("GL_ARB_multi_draw_indirect"), ); - //TODO: we can actually support positive `base_vertex` in the same way - // as we emulate the `start_instance`. But we can't deal with negatives... downlevel_flags.set(wgt::DownlevelFlags::BASE_VERTEX, supported((3, 2), (3, 2))); downlevel_flags.set( wgt::DownlevelFlags::INDEPENDENT_BLEND, @@ -550,6 +549,13 @@ impl super::Adapter { ); } + features.set( + wgt::Features::FLOAT32_FILTERABLE, + extensions.contains("GL_ARB_color_buffer_float") + || extensions.contains("GL_EXT_color_buffer_float") + || extensions.contains("OES_texture_float_linear"), + ); + // We *might* be able to emulate bgra8unorm-storage but currently don't attempt to. let mut private_caps = super::PrivateCapabilities::empty(); @@ -595,15 +601,8 @@ impl super::Adapter { super::PrivateCapabilities::COLOR_BUFFER_FLOAT, color_buffer_float, ); - private_caps.set( - super::PrivateCapabilities::TEXTURE_FLOAT_LINEAR, - if full_ver.is_some() { - color_buffer_float - } else { - extensions.contains("OES_texture_float_linear") - }, - ); private_caps.set(super::PrivateCapabilities::QUERY_BUFFERS, query_buffers); + private_caps.set(super::PrivateCapabilities::QUERY_64BIT, full_ver.is_some()); private_caps.set( super::PrivateCapabilities::TEXTURE_STORAGE, supported((3, 0), (4, 2)), @@ -616,6 +615,21 @@ impl super::Adapter { super::PrivateCapabilities::INVALIDATE_FRAMEBUFFER, supported((3, 0), (4, 3)), ); + if let Some(full_ver) = full_ver { + let supported = + full_ver >= (4, 2) && extensions.contains("GL_ARB_shader_draw_parameters"); + private_caps.set( + super::PrivateCapabilities::FULLY_FEATURED_INSTANCING, + supported, + ); + // Desktop 4.2 and greater specify the first instance parameter. + // + // For all other versions, the behavior is undefined. + // + // We only support indirect first instance when we also have ARB_shader_draw_parameters as + // that's the only way to get gl_InstanceID to work correctly. + features.set(wgt::Features::INDIRECT_FIRST_INSTANCE, supported); + } let max_texture_size = unsafe { gl.get_parameter_i32(glow::MAX_TEXTURE_SIZE) } as u32; let max_texture_3d_size = unsafe { gl.get_parameter_i32(glow::MAX_3D_TEXTURE_SIZE) } as u32; @@ -772,7 +786,7 @@ impl super::Adapter { // Drop the GL guard so we can move the context into AdapterShared // ( on Wasm the gl handle is just a ref so we tell clippy to allow // dropping the ref ) - #[cfg_attr(target_arch = "wasm32", allow(clippy::drop_ref))] + #[cfg_attr(target_arch = "wasm32", allow(dropping_references))] drop(gl); Some(crate::ExposedAdapter { @@ -783,7 +797,6 @@ impl super::Adapter { workarounds, features, shading_language_version, - max_texture_size, next_shader_id: Default::default(), program_cache: Default::default(), es: es_ver.is_some(), @@ -1008,8 +1021,7 @@ impl crate::Adapter for super::Adapter { | Tfc::MULTISAMPLE_RESOLVE, ); - let texture_float_linear = - private_caps_fn(super::PrivateCapabilities::TEXTURE_FLOAT_LINEAR, filterable); + let texture_float_linear = feature_fn(wgt::Features::FLOAT32_FILTERABLE, filterable); match format { Tf::R8Unorm => filterable_renderable, @@ -1058,6 +1070,7 @@ impl crate::Adapter for super::Adapter { | Tf::Depth32FloatStencil8 | Tf::Depth24Plus | Tf::Depth24PlusStencil8 => depth, + Tf::NV12 => unreachable!(), Tf::Rgb9e5Ufloat => filterable, Tf::Bc1RgbaUnorm | Tf::Bc1RgbaUnormSrgb @@ -1129,15 +1142,6 @@ impl crate::Adapter for super::Adapter { composite_alpha_modes: vec![wgt::CompositeAlphaMode::Opaque], //TODO swap_chain_sizes: 2..=2, current_extent: None, - extents: wgt::Extent3d { - width: 4, - height: 4, - depth_or_array_layers: 1, - }..=wgt::Extent3d { - width: self.shared.max_texture_size, - height: self.shared.max_texture_size, - depth_or_array_layers: 1, - }, usage: crate::TextureUses::COLOR_TARGET, }) } else { diff --git a/third_party/rust/wgpu-hal/src/gles/command.rs b/third_party/rust/wgpu-hal/src/gles/command.rs index abbbe8d42747d..28dbf1688de73 100644 --- a/third_party/rust/wgpu-hal/src/gles/command.rs +++ b/third_party/rust/wgpu-hal/src/gles/command.rs @@ -29,6 +29,7 @@ pub(super) struct State { instance_vbuf_mask: usize, dirty_vbuf_mask: usize, active_first_instance: u32, + first_instance_location: Option, push_constant_descs: ArrayVec, // The current state of the push constant data block. current_push_constant_data: [u32; super::MAX_PUSH_CONSTANTS], @@ -57,6 +58,7 @@ impl Default for State { instance_vbuf_mask: Default::default(), dirty_vbuf_mask: Default::default(), active_first_instance: Default::default(), + first_instance_location: Default::default(), push_constant_descs: Default::default(), current_push_constant_data: [0; super::MAX_PUSH_CONSTANTS], end_of_pass_timestamp: Default::default(), @@ -193,19 +195,32 @@ impl super::CommandEncoder { } fn prepare_draw(&mut self, first_instance: u32) { - if first_instance != self.state.active_first_instance { + // If we support fully featured instancing, we want to bind everything as normal + // and let the draw call sort it out. + let emulated_first_instance_value = if self + .private_caps + .contains(super::PrivateCapabilities::FULLY_FEATURED_INSTANCING) + { + 0 + } else { + first_instance + }; + + if emulated_first_instance_value != self.state.active_first_instance { // rebind all per-instance buffers on first-instance change self.state.dirty_vbuf_mask |= self.state.instance_vbuf_mask; - self.state.active_first_instance = first_instance; + self.state.active_first_instance = emulated_first_instance_value; } if self.state.dirty_vbuf_mask != 0 { - self.rebind_vertex_data(first_instance); + self.rebind_vertex_data(emulated_first_instance_value); } } + #[allow(clippy::clone_on_copy)] // False positive when cloning glow::UniformLocation fn set_pipeline_inner(&mut self, inner: &super::PipelineInner) { self.cmd_buffer.commands.push(C::SetProgram(inner.program)); + self.state.first_instance_location = inner.first_instance_location.clone(); self.state.push_constant_descs = inner.push_constant_descs.clone(); // rebind textures, if needed @@ -590,7 +605,7 @@ impl crate::CommandEncoder for super::CommandEncoder { if !cat.ops.contains(crate::AttachmentOps::LOAD) { let c = &cat.clear_value; self.cmd_buffer.commands.push( - match cat.target.view.format.sample_type(None).unwrap() { + match cat.target.view.format.sample_type(None, None).unwrap() { wgt::TextureSampleType::Float { .. } => C::ClearColorF { draw_buffer: i as u32, color: [c.r as f32, c.g as f32, c.b as f32, c.a as f32], @@ -1002,40 +1017,46 @@ impl crate::CommandEncoder for super::CommandEncoder { unsafe fn draw( &mut self, - start_vertex: u32, + first_vertex: u32, vertex_count: u32, - start_instance: u32, + first_instance: u32, instance_count: u32, ) { - self.prepare_draw(start_instance); + self.prepare_draw(first_instance); + #[allow(clippy::clone_on_copy)] // False positive when cloning glow::UniformLocation self.cmd_buffer.commands.push(C::Draw { topology: self.state.topology, - start_vertex, + first_vertex, vertex_count, + first_instance, instance_count, + first_instance_location: self.state.first_instance_location.clone(), }); } unsafe fn draw_indexed( &mut self, - start_index: u32, + first_index: u32, index_count: u32, base_vertex: i32, - start_instance: u32, + first_instance: u32, instance_count: u32, ) { - self.prepare_draw(start_instance); + self.prepare_draw(first_instance); let (index_size, index_type) = match self.state.index_format { wgt::IndexFormat::Uint16 => (2, glow::UNSIGNED_SHORT), wgt::IndexFormat::Uint32 => (4, glow::UNSIGNED_INT), }; - let index_offset = self.state.index_offset + index_size * start_index as wgt::BufferAddress; + let index_offset = self.state.index_offset + index_size * first_index as wgt::BufferAddress; + #[allow(clippy::clone_on_copy)] // False positive when cloning glow::UniformLocation self.cmd_buffer.commands.push(C::DrawIndexed { topology: self.state.topology, index_type, index_offset, index_count, base_vertex, + first_instance, instance_count, + first_instance_location: self.state.first_instance_location.clone(), }); } unsafe fn draw_indirect( @@ -1048,10 +1069,12 @@ impl crate::CommandEncoder for super::CommandEncoder { for draw in 0..draw_count as wgt::BufferAddress { let indirect_offset = offset + draw * mem::size_of::() as wgt::BufferAddress; + #[allow(clippy::clone_on_copy)] // False positive when cloning glow::UniformLocation self.cmd_buffer.commands.push(C::DrawIndirect { topology: self.state.topology, indirect_buf: buffer.raw.unwrap(), indirect_offset, + first_instance_location: self.state.first_instance_location.clone(), }); } } @@ -1069,11 +1092,13 @@ impl crate::CommandEncoder for super::CommandEncoder { for draw in 0..draw_count as wgt::BufferAddress { let indirect_offset = offset + draw * mem::size_of::() as wgt::BufferAddress; + #[allow(clippy::clone_on_copy)] // False positive when cloning glow::UniformLocation self.cmd_buffer.commands.push(C::DrawIndexedIndirect { topology: self.state.topology, index_type, indirect_buf: buffer.raw.unwrap(), indirect_offset, + first_instance_location: self.state.first_instance_location.clone(), }); } } diff --git a/third_party/rust/wgpu-hal/src/gles/conv.rs b/third_party/rust/wgpu-hal/src/gles/conv.rs index 3fb8383a511b9..ebf0c65f5219f 100644 --- a/third_party/rust/wgpu-hal/src/gles/conv.rs +++ b/third_party/rust/wgpu-hal/src/gles/conv.rs @@ -87,6 +87,7 @@ impl super::AdapterShared { glow::DEPTH_STENCIL, glow::UNSIGNED_INT_24_8, ), + Tf::NV12 => unreachable!(), Tf::Rgb9e5Ufloat => (glow::RGB9_E5, glow::RGB, glow::UNSIGNED_INT_5_9_9_9_REV), Tf::Bc1RgbaUnorm => (glow::COMPRESSED_RGBA_S3TC_DXT1_EXT, glow::RGBA, 0), Tf::Bc1RgbaUnormSrgb => (glow::COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, glow::RGBA, 0), diff --git a/third_party/rust/wgpu-hal/src/gles/device.rs b/third_party/rust/wgpu-hal/src/gles/device.rs index 64f47788eb1fb..35c6f910de6ba 100644 --- a/third_party/rust/wgpu-hal/src/gles/device.rs +++ b/third_party/rust/wgpu-hal/src/gles/device.rs @@ -467,9 +467,17 @@ impl super::Device { } } + let first_instance_location = if has_stages.contains(wgt::ShaderStages::VERTEX) { + // If this returns none (the uniform isn't active), that's fine, we just won't set it. + unsafe { gl.get_uniform_location(program, naga::back::glsl::FIRST_INSTANCE_BINDING) } + } else { + None + }; + Ok(Arc::new(super::PipelineInner { program, sampler_map, + first_instance_location, push_constant_descs: uniforms, })) } @@ -738,7 +746,7 @@ impl crate::Device for super::Device { unsafe { gl.bind_texture(target, Some(raw)) }; //Note: this has to be done before defining the storage! - match desc.format.sample_type(None) { + match desc.format.sample_type(None, Some(self.shared.features)) { Some( wgt::TextureSampleType::Float { filterable: false } | wgt::TextureSampleType::Uint @@ -1082,6 +1090,12 @@ impl crate::Device for super::Device { .private_caps .contains(super::PrivateCapabilities::SHADER_TEXTURE_SHADOW_LOD), ); + writer_flags.set( + glsl::WriterFlags::DRAW_PARAMETERS, + self.shared + .private_caps + .contains(super::PrivateCapabilities::FULLY_FEATURED_INSTANCING), + ); // We always force point size to be written and it will be ignored by the driver if it's not a point list primitive. // https://github.com/gfx-rs/wgpu/pull/3440/files#r1095726950 writer_flags.set(glsl::WriterFlags::FORCE_POINT_SIZE, true); @@ -1343,31 +1357,18 @@ impl crate::Device for super::Device { desc: &wgt::QuerySetDescriptor, ) -> Result { let gl = &self.shared.context.lock(); - let mut temp_string = String::new(); let mut queries = Vec::with_capacity(desc.count as usize); - for i in 0..desc.count { + for _ in 0..desc.count { let query = unsafe { gl.create_query() }.map_err(|_| crate::DeviceError::OutOfMemory)?; - #[cfg(not(target_arch = "wasm32"))] - if gl.supports_debug() { - use std::fmt::Write; - - // Initialize the query so we can label it - match desc.ty { - wgt::QueryType::Timestamp => unsafe { - gl.query_counter(query, glow::TIMESTAMP) - }, - _ => (), - } - if let Some(label) = desc.label { - temp_string.clear(); - let _ = write!(temp_string, "{label}[{i}]"); - let name = unsafe { mem::transmute(query) }; - unsafe { gl.object_label(glow::QUERY, name, Some(&temp_string)) }; - } - } + // We aren't really able to, in general, label queries. + // + // We could take a timestamp here to "initialize" the query, + // but that's a bit of a hack, and we don't want to insert + // random timestamps into the command stream of we don't have to. + queries.push(query); } diff --git a/third_party/rust/wgpu-hal/src/gles/mod.rs b/third_party/rust/wgpu-hal/src/gles/mod.rs index 7b9a694b7dc9f..9525e45d1395b 100644 --- a/third_party/rust/wgpu-hal/src/gles/mod.rs +++ b/third_party/rust/wgpu-hal/src/gles/mod.rs @@ -34,7 +34,7 @@ will be minimal, if any. Generally, vertex buffers are marked as dirty and lazily bound on draw. -GLES3 doesn't support "base instance" semantics. However, it's easy to support, +GLES3 doesn't support `first_instance` semantics. However, it's easy to support, since we are forced to do late binding anyway. We just adjust the offsets into the vertex data. @@ -51,9 +51,34 @@ from the vertex data itself. This mostly matches WebGPU, however there is a catc `stride` needs to be specified with the data, not as a part of the layout. To address this, we invalidate the vertex buffers based on: - - whether or not `start_instance` is used + - whether or not `first_instance` is used - stride has changed +## Handling of `base_vertex`, `first_instance`, and `first_vertex` + +Between indirect, the lack of `first_instance` semantics, and the availability of `gl_BaseInstance` +in shaders, getting buffers and builtins to work correctly is a bit tricky. + +We never emulate `base_vertex` and gl_VertexID behaves as `@builtin(vertex_index)` does, so we +never need to do anything about that. + +We always advertise support for `VERTEX_AND_INSTANCE_INDEX_RESPECTS_RESPECTIVE_FIRST_VALUE_IN_INDIRECT_DRAW`. + +### GL 4.2+ with ARB_shader_draw_parameters + +- `@builtin(instance_index)` translates to `gl_InstanceID + gl_BaseInstance` +- We bind instance buffers without any offset emulation. +- We advertise support for the `INDIRECT_FIRST_INSTANCE` feature. + +While we can theoretically have a card with 4.2+ support but without ARB_shader_draw_parameters, +we don't bother with that combination. + +### GLES & GL 4.1 + +- `@builtin(instance_index)` translates to `gl_InstanceID + naga_vs_first_instance` +- We bind instance buffers with offset emulation. +- We _do not_ advertise support for `INDIRECT_FIRST_INSTANCE` and cpu-side pretend the `first_instance` is 0 on indirect calls. + */ ///cbindgen:ignore @@ -161,16 +186,20 @@ bitflags::bitflags! { const COLOR_BUFFER_HALF_FLOAT = 1 << 8; /// Supports `f11/f10` and `f32` color buffers const COLOR_BUFFER_FLOAT = 1 << 9; - /// Supports linear flitering `f32` textures. - const TEXTURE_FLOAT_LINEAR = 1 << 10; /// Supports query buffer objects. const QUERY_BUFFERS = 1 << 11; + /// Supports 64 bit queries via `glGetQueryObjectui64v` + const QUERY_64BIT = 1 << 12; /// Supports `glTexStorage2D`, etc. - const TEXTURE_STORAGE = 1 << 12; + const TEXTURE_STORAGE = 1 << 13; /// Supports `push_debug_group`, `pop_debug_group` and `debug_message_insert`. - const DEBUG_FNS = 1 << 13; + const DEBUG_FNS = 1 << 14; /// Supports framebuffer invalidation. - const INVALIDATE_FRAMEBUFFER = 1 << 14; + const INVALIDATE_FRAMEBUFFER = 1 << 15; + /// Indicates support for `glDrawElementsInstancedBaseVertexBaseInstance` and `ARB_shader_draw_parameters` + /// + /// When this is true, instance offset emulation via vertex buffer rebinding and a shader uniform will be disabled. + const FULLY_FEATURED_INSTANCING = 1 << 16; } } @@ -218,7 +247,6 @@ struct AdapterShared { features: wgt::Features, workarounds: Workarounds, shading_language_version: naga::back::glsl::Version, - max_texture_size: u32, next_shader_id: AtomicU32, program_cache: Mutex, es: bool, @@ -516,6 +544,7 @@ type SamplerBindMap = [Option; MAX_TEXTURE_SLOTS]; struct PipelineInner { program: glow::Program, sampler_map: SamplerBindMap, + first_instance_location: Option, push_constant_descs: ArrayVec, } @@ -715,9 +744,11 @@ type InvalidatedAttachments = ArrayVec, }, DrawIndexed { topology: u32, @@ -725,18 +756,22 @@ enum Command { index_count: u32, index_offset: wgt::BufferAddress, base_vertex: i32, + first_instance: u32, instance_count: u32, + first_instance_location: Option, }, DrawIndirect { topology: u32, indirect_buf: glow::Buffer, indirect_offset: wgt::BufferAddress, + first_instance_location: Option, }, DrawIndexedIndirect { topology: u32, index_type: u32, indirect_buf: glow::Buffer, indirect_offset: wgt::BufferAddress, + first_instance_location: Option, }, Dispatch([u32; 3]), DispatchIndirect { @@ -914,6 +949,19 @@ impl fmt::Debug for CommandBuffer { } } +#[cfg(all( + target_arch = "wasm32", + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") +))] +unsafe impl Sync for CommandBuffer {} +#[cfg(all( + target_arch = "wasm32", + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") +))] +unsafe impl Send for CommandBuffer {} + //TODO: we would have something like `Arc` // here and in the command buffers. So that everything grows // inside the encoder and stays there until `reset_all`. @@ -932,6 +980,19 @@ impl fmt::Debug for CommandEncoder { } } +#[cfg(all( + target_arch = "wasm32", + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") +))] +unsafe impl Sync for CommandEncoder {} +#[cfg(all( + target_arch = "wasm32", + feature = "fragile-send-sync-non-atomic-wasm", + not(target_feature = "atomics") +))] +unsafe impl Send for CommandEncoder {} + #[cfg(not(all(target_arch = "wasm32", not(target_os = "emscripten"))))] fn gl_debug_message_callback(source: u32, gltype: u32, id: u32, severity: u32, message: &str) { let source_str = match source { @@ -978,6 +1039,6 @@ fn gl_debug_message_callback(source: u32, gltype: u32, id: u32, severity: u32, m if cfg!(debug_assertions) && log_severity == log::Level::Error { // Set canary and continue - crate::VALIDATION_CANARY.set(); + crate::VALIDATION_CANARY.add(message.to_string()); } } diff --git a/third_party/rust/wgpu-hal/src/gles/queue.rs b/third_party/rust/wgpu-hal/src/gles/queue.rs index 04bc1725c752d..0ab88c91cacfd 100644 --- a/third_party/rust/wgpu-hal/src/gles/queue.rs +++ b/third_party/rust/wgpu-hal/src/gles/queue.rs @@ -160,20 +160,43 @@ impl super::Queue { match *command { C::Draw { topology, - start_vertex, + first_vertex, vertex_count, instance_count, + first_instance, + ref first_instance_location, } => { - // Don't use `gl.draw_arrays` for `instance_count == 1`. - // Angle has a bug where it doesn't consider the instance divisor when `DYNAMIC_DRAW` is used in `draw_arrays`. - // See https://github.com/gfx-rs/wgpu/issues/3578 - unsafe { - gl.draw_arrays_instanced( - topology, - start_vertex as i32, - vertex_count as i32, - instance_count as i32, - ) + let supports_full_instancing = self + .shared + .private_caps + .contains(PrivateCapabilities::FULLY_FEATURED_INSTANCING); + + if supports_full_instancing { + unsafe { + gl.draw_arrays_instanced_base_instance( + topology, + first_vertex as i32, + vertex_count as i32, + instance_count as i32, + first_instance, + ) + } + } else { + unsafe { + gl.uniform_1_u32(first_instance_location.as_ref(), first_instance); + } + + // Don't use `gl.draw_arrays` for `instance_count == 1`. + // Angle has a bug where it doesn't consider the instance divisor when `DYNAMIC_DRAW` is used in `draw_arrays`. + // See https://github.com/gfx-rs/wgpu/issues/3578 + unsafe { + gl.draw_arrays_instanced( + topology, + first_vertex as i32, + vertex_count as i32, + instance_count as i32, + ) + } }; } C::DrawIndexed { @@ -182,38 +205,75 @@ impl super::Queue { index_count, index_offset, base_vertex, + first_instance, instance_count, + ref first_instance_location, } => { match base_vertex { - // Don't use `gl.draw_elements`/`gl.draw_elements_base_vertex` for `instance_count == 1`. - // Angle has a bug where it doesn't consider the instance divisor when `DYNAMIC_DRAW` is used in `gl.draw_elements`/`gl.draw_elements_base_vertex`. - // See https://github.com/gfx-rs/wgpu/issues/3578 - 0 => unsafe { - gl.draw_elements_instanced( - topology, - index_count as i32, - index_type, - index_offset as i32, - instance_count as i32, - ) - }, - _ => unsafe { - gl.draw_elements_instanced_base_vertex( - topology, - index_count as _, - index_type, - index_offset as i32, - instance_count as i32, - base_vertex, - ) - }, + 0 => { + unsafe { + gl.uniform_1_u32(first_instance_location.as_ref(), first_instance) + }; + + unsafe { + // Don't use `gl.draw_elements`/`gl.draw_elements_base_vertex` for `instance_count == 1`. + // Angle has a bug where it doesn't consider the instance divisor when `DYNAMIC_DRAW` is used in `gl.draw_elements`/`gl.draw_elements_base_vertex`. + // See https://github.com/gfx-rs/wgpu/issues/3578 + gl.draw_elements_instanced( + topology, + index_count as i32, + index_type, + index_offset as i32, + instance_count as i32, + ) + } + } + _ => { + let supports_full_instancing = self + .shared + .private_caps + .contains(PrivateCapabilities::FULLY_FEATURED_INSTANCING); + + if supports_full_instancing { + unsafe { + gl.draw_elements_instanced_base_vertex_base_instance( + topology, + index_count as i32, + index_type, + index_offset as i32, + instance_count as i32, + base_vertex, + first_instance, + ) + } + } else { + unsafe { + gl.uniform_1_u32(first_instance_location.as_ref(), first_instance) + }; + + // If we've gotten here, wgpu-core has already validated that this function exists via the DownlevelFlags::BASE_VERTEX feature. + unsafe { + gl.draw_elements_instanced_base_vertex( + topology, + index_count as _, + index_type, + index_offset as i32, + instance_count as i32, + base_vertex, + ) + } + } + } } } C::DrawIndirect { topology, indirect_buf, indirect_offset, + ref first_instance_location, } => { + unsafe { gl.uniform_1_u32(first_instance_location.as_ref(), 0) }; + unsafe { gl.bind_buffer(glow::DRAW_INDIRECT_BUFFER, Some(indirect_buf)) }; unsafe { gl.draw_arrays_indirect_offset(topology, indirect_offset as i32) }; } @@ -222,7 +282,10 @@ impl super::Queue { index_type, indirect_buf, indirect_offset, + ref first_instance_location, } => { + unsafe { gl.uniform_1_u32(first_instance_location.as_ref(), 0) }; + unsafe { gl.bind_buffer(glow::DRAW_INDIRECT_BUFFER, Some(indirect_buf)) }; unsafe { gl.draw_elements_indirect_offset(topology, index_type, indirect_offset as i32) @@ -877,12 +940,21 @@ impl super::Queue { { let mut result: u64 = 0; unsafe { - let result: *mut u64 = &mut result; - gl.get_query_parameter_u64_with_offset( - query, - glow::QUERY_RESULT, - result as usize, - ) + if self + .shared + .private_caps + .contains(PrivateCapabilities::QUERY_64BIT) + { + let result: *mut u64 = &mut result; + gl.get_query_parameter_u64_with_offset( + query, + glow::QUERY_RESULT, + result as usize, + ) + } else { + result = + gl.get_query_parameter_u32(query, glow::QUERY_RESULT) as u64; + } }; temp_query_results.push(result); } diff --git a/third_party/rust/wgpu-hal/src/lib.rs b/third_party/rust/wgpu-hal/src/lib.rs index b0b1120dbb476..6a03b32a7281e 100644 --- a/third_party/rust/wgpu-hal/src/lib.rs +++ b/third_party/rust/wgpu-hal/src/lib.rs @@ -90,10 +90,11 @@ use std::{ num::NonZeroU32, ops::{Range, RangeInclusive}, ptr::NonNull, - sync::{atomic::AtomicBool, Arc}, + sync::Arc, }; use bitflags::bitflags; +use parking_lot::Mutex; use thiserror::Error; use wgt::WasmNotSendSync; @@ -565,17 +566,17 @@ pub trait CommandEncoder: WasmNotSendSync + fmt::Debug { unsafe fn draw( &mut self, - start_vertex: u32, + first_vertex: u32, vertex_count: u32, - start_instance: u32, + first_instance: u32, instance_count: u32, ); unsafe fn draw_indexed( &mut self, - start_index: u32, + first_index: u32, index_count: u32, base_vertex: i32, - start_instance: u32, + first_instance: u32, instance_count: u32, ); unsafe fn draw_indirect( @@ -623,8 +624,8 @@ bitflags!( /// Pipeline layout creation flags. #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] pub struct PipelineLayoutFlags: u32 { - /// Include support for base vertex/instance drawing. - const BASE_VERTEX_INSTANCE = 1 << 0; + /// Include support for `first_vertex` / `first_instance` drawing. + const FIRST_VERTEX_INSTANCE = 1 << 0; /// Include support for num work groups builtin. const NUM_WORK_GROUPS = 1 << 1; } @@ -881,11 +882,6 @@ pub struct SurfaceCapabilities { /// Current extent of the surface, if known. pub current_extent: Option, - /// Range of supported extents. - /// - /// `current_extent` must be inside this range. - pub extents: RangeInclusive, - /// Supported texture usage flags. /// /// Must have at least `TextureUses::COLOR_TARGET` @@ -980,6 +976,7 @@ pub struct TextureViewDescriptor<'a> { pub dimension: wgt::TextureViewDimension, pub usage: TextureUses, pub range: wgt::ImageSubresourceRange, + pub plane: Option, } #[derive(Clone, Debug)] @@ -1384,8 +1381,11 @@ pub struct ComputePassDescriptor<'a, A: Api> { pub timestamp_writes: Option>, } -/// Stores if any API validation error has occurred in this process -/// since it was last reset. +/// Stores the text of any validation errors that have occurred since +/// the last call to `get_and_reset`. +/// +/// Each value is a validation error and a message associated with it, +/// or `None` if the error has no message from the api. /// /// This is used for internal wgpu testing only and _must not_ be used /// as a way to check for errors. @@ -1396,24 +1396,24 @@ pub struct ComputePassDescriptor<'a, A: Api> { /// This prevents the issue of one validation error terminating the /// entire process. pub static VALIDATION_CANARY: ValidationCanary = ValidationCanary { - inner: AtomicBool::new(false), + inner: Mutex::new(Vec::new()), }; /// Flag for internal testing. pub struct ValidationCanary { - inner: AtomicBool, + inner: Mutex>, } impl ValidationCanary { #[allow(dead_code)] // in some configurations this function is dead - fn set(&self) { - self.inner.store(true, std::sync::atomic::Ordering::SeqCst); + fn add(&self, msg: String) { + self.inner.lock().push(msg); } - /// Returns true if any API validation error has occurred in this process + /// Returns any API validation errors that hav occurred in this process /// since the last call to this function. - pub fn get_and_reset(&self) -> bool { - self.inner.swap(false, std::sync::atomic::Ordering::SeqCst) + pub fn get_and_reset(&self) -> Vec { + self.inner.lock().drain(..).collect() } } diff --git a/third_party/rust/wgpu-hal/src/metal/adapter.rs b/third_party/rust/wgpu-hal/src/metal/adapter.rs index fe7122f425b56..c398b28583ff2 100644 --- a/third_party/rust/wgpu-hal/src/metal/adapter.rs +++ b/third_party/rust/wgpu-hal/src/metal/adapter.rs @@ -232,6 +232,7 @@ impl crate::Adapter for super::Adapter { } flags } + Tf::NV12 => return Tfc::empty(), Tf::Rgb9e5Ufloat => { if pc.msaa_apple3 { all_caps @@ -338,15 +339,6 @@ impl crate::Adapter for super::Adapter { ], current_extent, - extents: wgt::Extent3d { - width: 4, - height: 4, - depth_or_array_layers: 1, - }..=wgt::Extent3d { - width: pc.max_texture_size as u32, - height: pc.max_texture_size as u32, - depth_or_array_layers: 1, - }, usage: crate::TextureUses::COLOR_TARGET | crate::TextureUses::COPY_DST, //TODO: expose more }) } @@ -427,17 +419,17 @@ const BGR10A2_ALL: &[MTLFeatureSet] = &[ MTLFeatureSet::macOS_GPUFamily2_v1, ]; -const BASE_INSTANCE_SUPPORT: &[MTLFeatureSet] = &[ +/// "Indirect draw & dispatch arguments" in the Metal feature set tables +const INDIRECT_DRAW_DISPATCH_SUPPORT: &[MTLFeatureSet] = &[ MTLFeatureSet::iOS_GPUFamily3_v1, MTLFeatureSet::tvOS_GPUFamily2_v1, MTLFeatureSet::macOS_GPUFamily1_v1, ]; -const BASE_VERTEX_INSTANCE_SUPPORT: &[MTLFeatureSet] = &[ - MTLFeatureSet::iOS_GPUFamily3_v1, - MTLFeatureSet::tvOS_GPUFamily2_v1, - MTLFeatureSet::macOS_GPUFamily1_v1, -]; +/// "Base vertex/instance drawing" in the Metal feature set tables +/// +/// in our terms, `base_vertex` and `first_instance` must be 0 +const BASE_VERTEX_FIRST_INSTANCE_SUPPORT: &[MTLFeatureSet] = INDIRECT_DRAW_DISPATCH_SUPPORT; const TEXTURE_CUBE_ARRAY_SUPPORT: &[MTLFeatureSet] = &[ MTLFeatureSet::iOS_GPUFamily4_v1, @@ -600,8 +592,11 @@ impl super::PrivateCapabilities { MUTABLE_COMPARISON_SAMPLER_SUPPORT, ), sampler_clamp_to_border: Self::supports_any(device, SAMPLER_CLAMP_TO_BORDER_SUPPORT), - base_instance: Self::supports_any(device, BASE_INSTANCE_SUPPORT), - base_vertex_instance_drawing: Self::supports_any(device, BASE_VERTEX_INSTANCE_SUPPORT), + indirect_draw_dispatch: Self::supports_any(device, INDIRECT_DRAW_DISPATCH_SUPPORT), + base_vertex_first_instance_drawing: Self::supports_any( + device, + BASE_VERTEX_FIRST_INSTANCE_SUPPORT, + ), dual_source_blending: Self::supports_any(device, DUAL_SOURCE_BLEND_SUPPORT), low_power: !os_is_mac || device.is_low_power(), headless: os_is_mac && device.is_headless(), @@ -609,6 +604,9 @@ impl super::PrivateCapabilities { function_specialization: Self::supports_any(device, FUNCTION_SPECIALIZATION_SUPPORT), depth_clip_mode: Self::supports_any(device, DEPTH_CLIP_MODE), texture_cube_array: Self::supports_any(device, TEXTURE_CUBE_ARRAY_SUPPORT), + supports_float_filtering: os_is_mac + || (version.at_least((11, 0), (14, 0), os_is_mac) + && device.supports_32bit_float_filtering()), format_depth24_stencil8: os_is_mac && device.d24_s8_supported(), format_depth32_stencil8_filter: os_is_mac, format_depth32_stencil8_none: !os_is_mac, @@ -815,7 +813,6 @@ impl super::PrivateCapabilities { use wgt::Features as F; let mut features = F::empty() - | F::INDIRECT_FIRST_INSTANCE | F::MAPPABLE_PRIMARY_BUFFERS | F::VERTEX_WRITABLE_STORAGE | F::TEXTURE_ADAPTER_SPECIFIC_FORMAT_FEATURES @@ -825,9 +822,13 @@ impl super::PrivateCapabilities { | F::TEXTURE_FORMAT_16BIT_NORM | F::SHADER_F16 | F::DEPTH32FLOAT_STENCIL8 - | F::MULTI_DRAW_INDIRECT | F::BGRA8UNORM_STORAGE; + features.set(F::FLOAT32_FILTERABLE, self.supports_float_filtering); + features.set( + F::INDIRECT_FIRST_INSTANCE | F::MULTI_DRAW_INDIRECT, + self.indirect_draw_dispatch, + ); features.set( F::TIMESTAMP_QUERY, self.timestamp_query_support @@ -891,11 +892,20 @@ impl super::PrivateCapabilities { wgt::DownlevelFlags::CUBE_ARRAY_TEXTURES, self.texture_cube_array, ); - //TODO: separate the mutable comparisons from immutable ones + // TODO: separate the mutable comparisons from immutable ones downlevel.flags.set( wgt::DownlevelFlags::COMPARISON_SAMPLERS, self.mutable_comparison_samplers, ); + downlevel.flags.set( + wgt::DownlevelFlags::INDIRECT_EXECUTION, + self.indirect_draw_dispatch, + ); + // TODO: add another flag for `first_instance` + downlevel.flags.set( + wgt::DownlevelFlags::BASE_VERTEX, + self.base_vertex_first_instance_drawing, + ); downlevel .flags .set(wgt::DownlevelFlags::ANISOTROPIC_FILTERING, true); @@ -1008,6 +1018,7 @@ impl super::PrivateCapabilities { Depth32Float_Stencil8 } } + Tf::NV12 => unreachable!(), Tf::Rgb9e5Ufloat => RGB9E5Float, Tf::Bc1RgbaUnorm => BC1_RGBA, Tf::Bc1RgbaUnormSrgb => BC1_RGBA_sRGB, diff --git a/third_party/rust/wgpu-hal/src/metal/command.rs b/third_party/rust/wgpu-hal/src/metal/command.rs index 5196e0447d42c..b06f46e8a95ee 100644 --- a/third_party/rust/wgpu-hal/src/metal/command.rs +++ b/third_party/rust/wgpu-hal/src/metal/command.rs @@ -965,31 +965,31 @@ impl crate::CommandEncoder for super::CommandEncoder { unsafe fn draw( &mut self, - start_vertex: u32, + first_vertex: u32, vertex_count: u32, - start_instance: u32, + first_instance: u32, instance_count: u32, ) { let encoder = self.state.render.as_ref().unwrap(); - if start_instance != 0 { + if first_instance != 0 { encoder.draw_primitives_instanced_base_instance( self.state.raw_primitive_type, - start_vertex as _, + first_vertex as _, vertex_count as _, instance_count as _, - start_instance as _, + first_instance as _, ); } else if instance_count != 1 { encoder.draw_primitives_instanced( self.state.raw_primitive_type, - start_vertex as _, + first_vertex as _, vertex_count as _, instance_count as _, ); } else { encoder.draw_primitives( self.state.raw_primitive_type, - start_vertex as _, + first_vertex as _, vertex_count as _, ); } @@ -997,16 +997,16 @@ impl crate::CommandEncoder for super::CommandEncoder { unsafe fn draw_indexed( &mut self, - start_index: u32, + first_index: u32, index_count: u32, base_vertex: i32, - start_instance: u32, + first_instance: u32, instance_count: u32, ) { let encoder = self.state.render.as_ref().unwrap(); let index = self.state.index.as_ref().unwrap(); - let offset = index.offset + index.stride * start_index as wgt::BufferAddress; - if base_vertex != 0 || start_instance != 0 { + let offset = index.offset + index.stride * first_index as wgt::BufferAddress; + if base_vertex != 0 || first_instance != 0 { encoder.draw_indexed_primitives_instanced_base_instance( self.state.raw_primitive_type, index_count as _, @@ -1015,7 +1015,7 @@ impl crate::CommandEncoder for super::CommandEncoder { offset, instance_count as _, base_vertex as _, - start_instance as _, + first_instance as _, ); } else if instance_count != 1 { encoder.draw_indexed_primitives_instanced( diff --git a/third_party/rust/wgpu-hal/src/metal/mod.rs b/third_party/rust/wgpu-hal/src/metal/mod.rs index 360c648daf69e..8890092d31b2b 100644 --- a/third_party/rust/wgpu-hal/src/metal/mod.rs +++ b/third_party/rust/wgpu-hal/src/metal/mod.rs @@ -182,8 +182,8 @@ struct PrivateCapabilities { shared_textures: bool, mutable_comparison_samplers: bool, sampler_clamp_to_border: bool, - base_instance: bool, - base_vertex_instance_drawing: bool, + indirect_draw_dispatch: bool, + base_vertex_first_instance_drawing: bool, dual_source_blending: bool, low_power: bool, headless: bool, @@ -191,6 +191,7 @@ struct PrivateCapabilities { function_specialization: bool, depth_clip_mode: bool, texture_cube_array: bool, + supports_float_filtering: bool, format_depth24_stencil8: bool, format_depth32_stencil8_filter: bool, format_depth32_stencil8_none: bool, diff --git a/third_party/rust/wgpu-hal/src/vulkan/adapter.rs b/third_party/rust/wgpu-hal/src/vulkan/adapter.rs index 6fcb7b7df6dd2..dc67e85a5ea30 100644 --- a/third_party/rust/wgpu-hal/src/vulkan/adapter.rs +++ b/third_party/rust/wgpu-hal/src/vulkan/adapter.rs @@ -301,6 +301,7 @@ impl PhysicalDeviceFeatures { fn to_wgpu( &self, + adapter_info: &wgt::AdapterInfo, instance: &ash::Instance, phd: vk::PhysicalDevice, caps: &PhysicalDeviceCapabilities, @@ -331,7 +332,8 @@ impl PhysicalDeviceFeatures { | Df::INDIRECT_EXECUTION | Df::VIEW_FORMATS | Df::UNRESTRICTED_EXTERNAL_TEXTURE_COPIES - | Df::NONBLOCKING_QUERY_RESOLVE; + | Df::NONBLOCKING_QUERY_RESOLVE + | Df::VERTEX_AND_INSTANCE_INDEX_RESPECTS_RESPECTIVE_FIRST_VALUE_IN_INDIRECT_DRAW; dl_flags.set( Df::SURFACE_VIEW_FORMATS, @@ -534,6 +536,26 @@ impl PhysicalDeviceFeatures { supports_bgra8unorm_storage(instance, phd, caps.device_api_version), ); + features.set( + F::FLOAT32_FILTERABLE, + is_float32_filterable_supported(instance, phd), + ); + features.set( + F::TEXTURE_FORMAT_NV12, + (caps.device_api_version >= vk::API_VERSION_1_1 + || caps.supports_extension(vk::KhrSamplerYcbcrConversionFn::name())) + && supports_format( + instance, + phd, + vk::Format::G8_B8R8_2PLANE_420_UNORM, + vk::ImageTiling::OPTIMAL, + vk::FormatFeatureFlags::SAMPLED_IMAGE + | vk::FormatFeatureFlags::TRANSFER_SRC + | vk::FormatFeatureFlags::TRANSFER_DST, + ) + && !adapter_info.driver.contains("MoltenVK"), + ); + (features, dl_flags) } @@ -968,7 +990,7 @@ impl super::Instance { }; let (available_features, downlevel_flags) = - phd_features.to_wgpu(&self.shared.raw, phd, &phd_capabilities); + phd_features.to_wgpu(&info, &self.shared.raw, phd, &phd_capabilities); let mut workarounds = super::Workarounds::empty(); { // see https://github.com/gfx-rs/gfx/issues/1930 @@ -992,11 +1014,21 @@ impl super::Instance { if let Some(driver) = phd_capabilities.driver { if driver.conformance_version.major == 0 { - log::warn!( - "Adapter is not Vulkan compliant, hiding adapter: {}", - info.name - ); - return None; + if driver.driver_id == ash::vk::DriverId::MOLTENVK { + log::debug!("Adapter is not Vulkan compliant, but is MoltenVK, continuing"); + } else if self + .shared + .flags + .contains(wgt::InstanceFlags::ALLOW_UNDERLYING_NONCOMPLIANT_ADAPTER) + { + log::warn!("Adapter is not Vulkan compliant: {}", info.name); + } else { + log::warn!( + "Adapter is not Vulkan compliant, hiding adapter: {}", + info.name + ); + return None; + } } } if phd_capabilities.device_api_version == vk::API_VERSION_1_0 @@ -1540,14 +1572,14 @@ impl crate::Adapter for super::Adapter { .framebuffer_stencil_sample_counts .min(limits.sampled_image_stencil_sample_counts) } else { - match format.sample_type(None).unwrap() { - wgt::TextureSampleType::Float { filterable: _ } => limits + match format.sample_type(None, None) { + Some(wgt::TextureSampleType::Float { .. }) => limits .framebuffer_color_sample_counts .min(limits.sampled_image_color_sample_counts), - wgt::TextureSampleType::Sint | wgt::TextureSampleType::Uint => { + Some(wgt::TextureSampleType::Sint) | Some(wgt::TextureSampleType::Uint) => { limits.sampled_image_integer_sample_counts } - _ => unreachable!(), + _ => vk::SampleCountFlags::TYPE_1, } }; @@ -1631,18 +1663,6 @@ impl crate::Adapter for super::Adapter { None }; - let min_extent = wgt::Extent3d { - width: caps.min_image_extent.width, - height: caps.min_image_extent.height, - depth_or_array_layers: 1, - }; - - let max_extent = wgt::Extent3d { - width: caps.max_image_extent.width, - height: caps.max_image_extent.height, - depth_or_array_layers: caps.max_image_array_layers, - }; - let raw_present_modes = { profiling::scope!("vkGetPhysicalDeviceSurfacePresentModesKHR"); match unsafe { @@ -1681,7 +1701,6 @@ impl crate::Adapter for super::Adapter { formats, swap_chain_sizes: caps.min_image_count..=max_image_count, current_extent, - extents: min_extent..=max_extent, usage: conv::map_vk_image_usage(caps.supported_usage_flags), present_modes: raw_present_modes .into_iter() @@ -1745,6 +1764,21 @@ fn is_format_16bit_norm_supported(instance: &ash::Instance, phd: vk::PhysicalDev r16unorm && r16snorm && rg16unorm && rg16snorm && rgba16unorm && rgba16snorm } +fn is_float32_filterable_supported(instance: &ash::Instance, phd: vk::PhysicalDevice) -> bool { + let tiling = vk::ImageTiling::OPTIMAL; + let features = vk::FormatFeatureFlags::SAMPLED_IMAGE_FILTER_LINEAR; + let r_float = supports_format(instance, phd, vk::Format::R32_SFLOAT, tiling, features); + let rg_float = supports_format(instance, phd, vk::Format::R32G32_SFLOAT, tiling, features); + let rgba_float = supports_format( + instance, + phd, + vk::Format::R32G32B32A32_SFLOAT, + tiling, + features, + ); + r_float && rg_float && rgba_float +} + fn supports_format( instance: &ash::Instance, phd: vk::PhysicalDevice, diff --git a/third_party/rust/wgpu-hal/src/vulkan/command.rs b/third_party/rust/wgpu-hal/src/vulkan/command.rs index 52226f34ebd75..c31da9e2c867a 100644 --- a/third_party/rust/wgpu-hal/src/vulkan/command.rs +++ b/third_party/rust/wgpu-hal/src/vulkan/command.rs @@ -722,9 +722,9 @@ impl crate::CommandEncoder for super::CommandEncoder { unsafe fn draw( &mut self, - start_vertex: u32, + first_vertex: u32, vertex_count: u32, - start_instance: u32, + first_instance: u32, instance_count: u32, ) { unsafe { @@ -732,17 +732,17 @@ impl crate::CommandEncoder for super::CommandEncoder { self.active, vertex_count, instance_count, - start_vertex, - start_instance, + first_vertex, + first_instance, ) }; } unsafe fn draw_indexed( &mut self, - start_index: u32, + first_index: u32, index_count: u32, base_vertex: i32, - start_instance: u32, + first_instance: u32, instance_count: u32, ) { unsafe { @@ -750,9 +750,9 @@ impl crate::CommandEncoder for super::CommandEncoder { self.active, index_count, instance_count, - start_index, + first_index, base_vertex, - start_instance, + first_instance, ) }; } diff --git a/third_party/rust/wgpu-hal/src/vulkan/conv.rs b/third_party/rust/wgpu-hal/src/vulkan/conv.rs index c27fdf9f72f7e..70dbb5714d848 100644 --- a/third_party/rust/wgpu-hal/src/vulkan/conv.rs +++ b/third_party/rust/wgpu-hal/src/vulkan/conv.rs @@ -74,6 +74,7 @@ impl super::PrivateCapabilities { } } Tf::Depth16Unorm => F::D16_UNORM, + Tf::NV12 => F::G8_B8R8_2PLANE_420_UNORM, Tf::Rgb9e5Ufloat => F::E5B9G9R9_UFLOAT_PACK32, Tf::Bc1RgbaUnorm => F::BC1_RGBA_UNORM_BLOCK, Tf::Bc1RgbaUnormSrgb => F::BC1_RGBA_SRGB_BLOCK, @@ -199,7 +200,7 @@ impl crate::ColorAttachment<'_, super::Api> { .view .attachment .view_format - .sample_type(None) + .sample_type(None, None) .unwrap() { wgt::TextureSampleType::Float { .. } => vk::ClearColorValue { @@ -401,10 +402,18 @@ pub fn map_vertex_format(vertex_format: wgt::VertexFormat) -> vk::Format { } } -pub fn map_aspects(aspects: crate::FormatAspects) -> vk::ImageAspectFlags { +pub fn map_aspects(aspects: crate::FormatAspects, plane: Option) -> vk::ImageAspectFlags { let mut flags = vk::ImageAspectFlags::empty(); - if aspects.contains(crate::FormatAspects::COLOR) { - flags |= vk::ImageAspectFlags::COLOR; + match plane { + Some(0) => flags |= vk::ImageAspectFlags::PLANE_0, + Some(1) => flags |= vk::ImageAspectFlags::PLANE_1, + Some(2) => flags |= vk::ImageAspectFlags::PLANE_2, + Some(plane) => panic!("Unexpected plane {}", plane), + None => { + if aspects.contains(crate::FormatAspects::COLOR) { + flags |= vk::ImageAspectFlags::COLOR; + } + } } if aspects.contains(crate::FormatAspects::DEPTH) { flags |= vk::ImageAspectFlags::DEPTH; @@ -586,9 +595,10 @@ pub fn map_copy_extent(extent: &crate::CopyExtent) -> vk::Extent3D { pub fn map_subresource_range( range: &wgt::ImageSubresourceRange, format: wgt::TextureFormat, + plane: Option, ) -> vk::ImageSubresourceRange { vk::ImageSubresourceRange { - aspect_mask: map_aspects(crate::FormatAspects::new(format, range.aspect)), + aspect_mask: map_aspects(crate::FormatAspects::new(format, range.aspect), plane), base_mip_level: range.base_mip_level, level_count: range.mip_level_count.unwrap_or(vk::REMAINING_MIP_LEVELS), base_array_layer: range.base_array_layer, @@ -605,7 +615,7 @@ pub(super) fn map_subresource_range_combined_aspect( format: wgt::TextureFormat, private_caps: &super::PrivateCapabilities, ) -> vk::ImageSubresourceRange { - let mut range = map_subresource_range(range, format); + let mut range = map_subresource_range(range, format, None); if !private_caps.texture_s8 && format == wgt::TextureFormat::Stencil8 { range.aspect_mask |= vk::ImageAspectFlags::DEPTH; } @@ -621,7 +631,7 @@ pub fn map_subresource_layers( z: base.origin.z as i32, }; let subresource = vk::ImageSubresourceLayers { - aspect_mask: map_aspects(base.aspect), + aspect_mask: map_aspects(base.aspect, None), mip_level: base.mip_level, base_array_layer: base.array_layer, layer_count: 1, diff --git a/third_party/rust/wgpu-hal/src/vulkan/device.rs b/third_party/rust/wgpu-hal/src/vulkan/device.rs index 5f7fbac47af32..d9aba5028187d 100644 --- a/third_party/rust/wgpu-hal/src/vulkan/device.rs +++ b/third_party/rust/wgpu-hal/src/vulkan/device.rs @@ -1062,7 +1062,7 @@ impl crate::Device for super::Device { texture: &super::Texture, desc: &crate::TextureViewDescriptor, ) -> Result { - let subresource_range = conv::map_subresource_range(&desc.range, desc.format); + let subresource_range = conv::map_subresource_range(&desc.range, desc.format, desc.plane); let mut vk_info = vk::ImageViewCreateInfo::builder() .flags(vk::ImageViewCreateFlags::empty()) .image(texture.raw) diff --git a/third_party/rust/wgpu-hal/src/vulkan/instance.rs b/third_party/rust/wgpu-hal/src/vulkan/instance.rs index a72c6e848b075..8eb136b2cb63b 100644 --- a/third_party/rust/wgpu-hal/src/vulkan/instance.rs +++ b/third_party/rust/wgpu-hal/src/vulkan/instance.rs @@ -41,10 +41,11 @@ unsafe extern "system" fn debug_utils_messenger_callback( } } - // Silence Vulkan Validation error "VUID-VkSwapchainCreateInfoKHR-imageExtent-01274" - // - it's a false positive due to the inherent racy-ness of surface resizing - const VUID_VKSWAPCHAINCREATEINFOKHR_IMAGEEXTENT_01274: i32 = 0x7cd0911d; - if cd.message_id_number == VUID_VKSWAPCHAINCREATEINFOKHR_IMAGEEXTENT_01274 { + // Silence Vulkan Validation error "VUID-VkSwapchainCreateInfoKHR-pNext-07781" + // This happens when a surface is configured with a size outside the allowed extent. + // It's s false positive due to the inherent racy-ness of surface resizing. + const VUID_VKSWAPCHAINCREATEINFOKHR_PNEXT_07781: i32 = 0x4c8929c1; + if cd.message_id_number == VUID_VKSWAPCHAINCREATEINFOKHR_PNEXT_07781 { return vk::FALSE; } @@ -146,7 +147,7 @@ unsafe extern "system" fn debug_utils_messenger_callback( if cfg!(debug_assertions) && level == log::Level::Error { // Set canary and continue - crate::VALIDATION_CANARY.set(); + crate::VALIDATION_CANARY.add(message.to_string()); } vk::FALSE diff --git a/third_party/rust/wgpu-types/.cargo-checksum.json b/third_party/rust/wgpu-types/.cargo-checksum.json index 3a6107dedaaba..cb5969179c49d 100644 --- a/third_party/rust/wgpu-types/.cargo-checksum.json +++ b/third_party/rust/wgpu-types/.cargo-checksum.json @@ -1 +1 @@ -{"files":{"Cargo.toml":"e45ee369c8f91526056ba7f46504e270da1d8b2de65431bbaf36426bcd54da68","LICENSE.APACHE":"a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9","LICENSE.MIT":"c7fea58d1cfe49634cd92e54fc10a9d871f4b275321a4cd8c09e449122caaeb4","src/assertions.rs":"3fe98027aa73970c8ab7874a3e13dbfd6faa87df2081beb5c83aeec4c60f372f","src/lib.rs":"6c3886f27653eee4359a8d150a6091a7d6e0ff1abab44c9afff2d54a0d0a474b","src/math.rs":"4d03039736dd6926feb139bc68734cb59df34ede310427bbf059e5c925e0af3b"},"package":null} \ No newline at end of file +{"files":{"Cargo.toml":"18549fb7d7de2ea2481f30292dca63889856a33bd1b3698e16cee6631ab65df4","LICENSE.APACHE":"a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9","LICENSE.MIT":"c7fea58d1cfe49634cd92e54fc10a9d871f4b275321a4cd8c09e449122caaeb4","src/assertions.rs":"3fe98027aa73970c8ab7874a3e13dbfd6faa87df2081beb5c83aeec4c60f372f","src/lib.rs":"61f4f46533468f82e3d22e42d6e8b3d8b68504ccd4f9b4b9ea67b0664c42a34e","src/math.rs":"4d03039736dd6926feb139bc68734cb59df34ede310427bbf059e5c925e0af3b"},"package":null} \ No newline at end of file diff --git a/third_party/rust/wgpu-types/Cargo.toml b/third_party/rust/wgpu-types/Cargo.toml index b07aad32c0bc9..c1e36af8c5994 100644 --- a/third_party/rust/wgpu-types/Cargo.toml +++ b/third_party/rust/wgpu-types/Cargo.toml @@ -58,10 +58,10 @@ strict_asserts = [] trace = ["serde"] [target."cfg(target_arch = \"wasm32\")".dependencies] -js-sys = "0.3.65" +js-sys = "0.3.66" [target."cfg(target_arch = \"wasm32\")".dependencies.web-sys] -version = "0.3.64" +version = "0.3.66" features = [ "ImageBitmap", "HtmlVideoElement", diff --git a/third_party/rust/wgpu-types/src/lib.rs b/third_party/rust/wgpu-types/src/lib.rs index 56a42b4ba7f48..bdef49a60cdae 100644 --- a/third_party/rust/wgpu-types/src/lib.rs +++ b/third_party/rust/wgpu-types/src/lib.rs @@ -280,12 +280,21 @@ bitflags::bitflags! { /// /// This is a web and native feature. const TIMESTAMP_QUERY = 1 << 1; - /// Allows non-zero value for the "first instance" in indirect draw calls. + /// Allows non-zero value for the `first_instance` member in indirect draw calls. + /// + /// If this feature is not enabled, and the `first_instance` member is non-zero, the behavior may be: + /// - The draw call is ignored. + /// - The draw call is executed as if the `first_instance` is zero. + /// - The draw call is executed with the correct `first_instance` value. /// /// Supported Platforms: /// - Vulkan (mostly) /// - DX12 - /// - Metal + /// - Metal on Apple3+ or Mac1+ + /// - OpenGL (Desktop 4.2+ with ARB_shader_draw_parameters only) + /// + /// Not Supported: + /// - OpenGL ES / WebGL /// /// This is a web and native feature. const INDIRECT_FIRST_INSTANCE = 1 << 2; @@ -328,7 +337,18 @@ bitflags::bitflags! { // ? const NORM16_FILTERABLE = 1 << 17; (https://github.com/gpuweb/gpuweb/issues/3839) // ? const NORM16_RESOLVE = 1 << 18; (https://github.com/gpuweb/gpuweb/issues/3839) - // TODO const FLOAT32_FILTERABLE = 1 << 19; + + /// Allows textures with formats "r32float", "rg32float", and "rgba32float" to be filterable. + /// + /// Supported Platforms: + /// - Vulkan (mainly on Desktop GPUs) + /// - DX12 + /// - Metal on macOS or Apple9+ GPUs, optional on iOS/iPadOS with Apple7/8 GPUs + /// - GL with one of `GL_ARB_color_buffer_float`/`GL_EXT_color_buffer_float`/`OES_texture_float_linear` + /// + /// This is a web and native feature. + const FLOAT32_FILTERABLE = 1 << 19; + // ? const FLOAT32_BLENDABLE = 1 << 20; (https://github.com/gpuweb/gpuweb/issues/3556) // ? const 32BIT_FORMAT_MULTISAMPLE = 1 << 21; (https://github.com/gpuweb/gpuweb/issues/3844) // ? const 32BIT_FORMAT_RESOLVE = 1 << 22; (https://github.com/gpuweb/gpuweb/issues/3844) @@ -613,7 +633,7 @@ bitflags::bitflags! { /// Supported platforms: /// - DX12 /// - Vulkan - /// - Metal (Emulated on top of `draw_indirect` and `draw_indexed_indirect`) + /// - Metal on Apple3+ or Mac1+ (Emulated on top of `draw_indirect` and `draw_indexed_indirect`) /// /// This is a native only feature. /// @@ -762,7 +782,16 @@ bitflags::bitflags! { /// - OpenGL const SHADER_UNUSED_VERTEX_OUTPUT = 1 << 54; - // 54..59 available + /// Allows for creation of textures of format [`TextureFormat::NV12`] + /// + /// Supported platforms: + /// - DX12 + /// - Vulkan + /// + /// This is a native only feature. + const TEXTURE_FORMAT_NV12 = 1 << 55; + + // 55..59 available // Shader: @@ -849,6 +878,16 @@ bitflags::bitflags! { const VALIDATION = 1 << 1; /// Don't pass labels to wgpu-hal. const DISCARD_HAL_LABELS = 1 << 2; + /// Whether wgpu should expose adapters that run on top of non-compliant adapters. + /// + /// Turning this on might mean that some of the functionality provided by the wgpu + /// adapter/device is not working or is broken. It could be that all the functionality + /// wgpu currently exposes works but we can't tell for sure since we have no additional + /// transparency into what is working and what is not on the underlying adapter. + /// + /// This mainly applies to a Vulkan driver's compliance version. If the major compliance version + /// is `0`, then the driver is ignored. This flag allows that driver to be enabled for testing. + const ALLOW_UNDERLYING_NONCOMPLIANT_ADAPTER = 1 << 3; } } @@ -901,6 +940,9 @@ impl InstanceFlags { if let Some(bit) = env("WGPU_DEBUG") { self.set(Self::DEBUG, bit); } + if let Some(bit) = env("WGPU_ALLOW_UNDERLYING_NONCOMPLIANT_ADAPTER") { + self.set(Self::ALLOW_UNDERLYING_NONCOMPLIANT_ADAPTER, bit); + } self } @@ -1385,9 +1427,18 @@ bitflags::bitflags! { const FRAGMENT_WRITABLE_STORAGE = 1 << 1; /// Supports indirect drawing and dispatching. /// - /// DX11 on FL10 level hardware, WebGL2, and GLES 3.0 devices do not support indirect. + /// DX11 on FL10 level hardware, WebGL2, GLES 3.0, and Metal on Apple1/Apple2 GPUs do not support indirect. const INDIRECT_EXECUTION = 1 << 2; - /// Supports non-zero `base_vertex` parameter to indexed draw calls. + /// Supports non-zero `base_vertex` parameter to direct indexed draw calls. + /// + /// Indirect calls, if supported, always support non-zero `base_vertex`. + /// + /// Supported by: + /// - Vulkan + /// - DX12 + /// - Metal on Apple3+ or Mac1+ + /// - OpenGL 3.2+ + /// - OpenGL ES 3.2 const BASE_VERTEX = 1 << 3; /// Supports reading from a depth/stencil texture while using it as a read-only /// depth/stencil attachment. @@ -1486,6 +1537,34 @@ bitflags::bitflags! { /// Not Supported by: /// - GL ES / WebGL const NONBLOCKING_QUERY_RESOLVE = 1 << 22; + + /// If this is true, use of `@builtin(vertex_index)` and `@builtin(instance_index)` will properly take into consideration + /// the `first_vertex` and `first_instance` parameters of indirect draw calls. + /// + /// If this is false, `@builtin(vertex_index)` and `@builtin(instance_index)` will start by counting from 0, ignoring the + /// `first_vertex` and `first_instance` parameters. + /// + /// For example, if you had a draw call like this: + /// - `first_vertex: 4,` + /// - `vertex_count: 12,` + /// + /// When this flag is present, `@builtin(vertex_index)` will start at 4 and go up to 15 (12 invocations). + /// + /// When this flag is not present, `@builtin(vertex_index)` will start at 0 and go up to 11 (12 invocations). + /// + /// This only affects the builtins in the shaders, + /// vertex buffers and instance rate vertex buffers will behave like expected with this flag disabled. + /// + /// See also [`Features::`] + /// + /// Supported By: + /// - Vulkan + /// - Metal + /// - OpenGL + /// + /// Will be implemented in the future by: + /// - DX12 ([#2471](https://github.com/gfx-rs/wgpu/issues/2471)) + const VERTEX_AND_INSTANCE_INDEX_RESPECTS_RESPECTIVE_FIRST_VALUE_IN_INDIRECT_DRAW = 1 << 23; } } @@ -1583,12 +1662,18 @@ pub struct AdapterInfo { pub struct DeviceDescriptor { /// Debug label for the device. pub label: L, - /// Features that the device should support. If any feature is not supported by - /// the adapter, creating a device will panic. - pub features: Features, - /// Limits that the device should support. If any limit is "better" than the limit exposed by - /// the adapter, creating a device will panic. - pub limits: Limits, + /// Specifies the features that are required by the device request. + /// The request will fail if the adapter cannot provide these features. + /// + /// Exactly the specified set of features, and no more or less, + /// will be allowed in validation of API calls on the resulting device. + pub required_features: Features, + /// Specifies the limits that are required by the device request. + /// The request will fail if the adapter cannot provide these limits. + /// + /// Exactly the specified limits, and no better or worse, + /// will be allowed in validation of API calls on the resulting device. + pub required_limits: Limits, } impl DeviceDescriptor { @@ -1596,8 +1681,8 @@ impl DeviceDescriptor { pub fn map_label(&self, fun: impl FnOnce(&L) -> K) -> DeviceDescriptor { DeviceDescriptor { label: fun(&self.label), - features: self.features, - limits: self.limits.clone(), + required_features: self.required_features, + required_limits: self.required_limits.clone(), } } } @@ -2318,6 +2403,21 @@ pub enum TextureFormat { /// [`Features::DEPTH32FLOAT_STENCIL8`] must be enabled to use this texture format. Depth32FloatStencil8, + /// YUV 4:2:0 chroma subsampled format. + /// + /// Contains two planes: + /// - 0: Single 8 bit channel luminance. + /// - 1: Dual 8 bit channel chrominance at half width and half height. + /// + /// Valid view formats for luminance are [`TextureFormat::R8Unorm`] and [`TextureFormat::R8Uint`]. + /// + /// Valid view formats for chrominance are [`TextureFormat::Rg8Unorm`] and [`TextureFormat::Rg8Uint`]. + /// + /// Width and height must be even. + /// + /// [`Features::TEXTURE_FORMAT_NV12`] must be enabled to use this texture format. + NV12, + // Compressed textures usable with `TEXTURE_COMPRESSION_BC` feature. /// 4x4 block compressed texture. 8 bytes per block (4 bit/px). 4 color + alpha pallet. 5 bit R + 6 bit G + 5 bit B + 1 bit alpha. /// [0, 63] ([0, 1] for alpha) converted to/from float [0, 1] in shader. @@ -2547,6 +2647,7 @@ impl<'de> Deserialize<'de> for TextureFormat { "depth16unorm" => TextureFormat::Depth16Unorm, "depth24plus" => TextureFormat::Depth24Plus, "depth24plus-stencil8" => TextureFormat::Depth24PlusStencil8, + "nv12" => TextureFormat::NV12, "rgb9e5ufloat" => TextureFormat::Rgb9e5Ufloat, "bc1-rgba-unorm" => TextureFormat::Bc1RgbaUnorm, "bc1-rgba-unorm-srgb" => TextureFormat::Bc1RgbaUnormSrgb, @@ -2674,6 +2775,7 @@ impl Serialize for TextureFormat { TextureFormat::Depth32FloatStencil8 => "depth32float-stencil8", TextureFormat::Depth24Plus => "depth24plus", TextureFormat::Depth24PlusStencil8 => "depth24plus-stencil8", + TextureFormat::NV12 => "nv12", TextureFormat::Rgb9e5Ufloat => "rgb9e5ufloat", TextureFormat::Bc1RgbaUnorm => "bc1-rgba-unorm", TextureFormat::Bc1RgbaUnormSrgb => "bc1-rgba-unorm-srgb", @@ -2868,6 +2970,8 @@ impl TextureFormat { | Self::Depth32Float | Self::Depth32FloatStencil8 => (1, 1), + Self::NV12 => (2, 2), + Self::Bc1RgbaUnorm | Self::Bc1RgbaUnormSrgb | Self::Bc2RgbaUnorm @@ -2966,6 +3070,8 @@ impl TextureFormat { Self::Depth32FloatStencil8 => Features::DEPTH32FLOAT_STENCIL8, + Self::NV12 => Features::TEXTURE_FORMAT_NV12, + Self::R16Unorm | Self::R16Snorm | Self::Rg16Unorm @@ -3020,6 +3126,7 @@ impl TextureFormat { TextureUsages::COPY_SRC | TextureUsages::COPY_DST | TextureUsages::TEXTURE_BINDING; let attachment = basic | TextureUsages::RENDER_ATTACHMENT; let storage = basic | TextureUsages::STORAGE_BINDING; + let binding = TextureUsages::TEXTURE_BINDING; let all_flags = TextureUsages::all(); let rg11b10f = if device_features.contains(Features::RG11B10UFLOAT_RENDERABLE) { attachment @@ -3081,6 +3188,9 @@ impl TextureFormat { Self::Depth32Float => ( msaa, attachment), Self::Depth32FloatStencil8 => ( msaa, attachment), + // We only support sampling nv12 textures until we implement transfer plane data. + Self::NV12 => ( noaa, binding), + Self::R16Unorm => ( msaa, storage), Self::R16Snorm => ( msaa, storage), Self::Rg16Unorm => ( msaa, storage), @@ -3119,10 +3229,16 @@ impl TextureFormat { Self::Astc { .. } => ( noaa, basic), }; - let is_filterable = - self.sample_type(None) == Some(TextureSampleType::Float { filterable: true }); + // Get whether the format is filterable, taking features into account + let sample_type1 = self.sample_type(None, Some(device_features)); + let is_filterable = sample_type1 == Some(TextureSampleType::Float { filterable: true }); + + // Features that enable filtering don't affect blendability + let sample_type2 = self.sample_type(None, None); + let is_blendable = sample_type2 == Some(TextureSampleType::Float { filterable: true }); + flags.set(TextureFormatFeatureFlags::FILTERABLE, is_filterable); - flags.set(TextureFormatFeatureFlags::BLENDABLE, is_filterable); + flags.set(TextureFormatFeatureFlags::BLENDABLE, is_blendable); TextureFormatFeatures { allowed_usages, @@ -3134,9 +3250,17 @@ impl TextureFormat { /// /// Returns `None` only if the format is combined depth-stencil /// and `TextureAspect::All` or no `aspect` was provided - pub fn sample_type(&self, aspect: Option) -> Option { + pub fn sample_type( + &self, + aspect: Option, + device_features: Option, + ) -> Option { let float = TextureSampleType::Float { filterable: true }; - let unfilterable_float = TextureSampleType::Float { filterable: false }; + let float32_sample_type = TextureSampleType::Float { + filterable: device_features + .unwrap_or(Features::empty()) + .contains(Features::FLOAT32_FILTERABLE), + }; let depth = TextureSampleType::Depth; let uint = TextureSampleType::Uint; let sint = TextureSampleType::Sint; @@ -3157,7 +3281,7 @@ impl TextureFormat { | Self::Rgb10a2Unorm | Self::Rg11b10Float => Some(float), - Self::R32Float | Self::Rg32Float | Self::Rgba32Float => Some(unfilterable_float), + Self::R32Float | Self::Rg32Float | Self::Rgba32Float => Some(float32_sample_type), Self::R8Uint | Self::Rg8Uint @@ -3188,6 +3312,8 @@ impl TextureFormat { Some(TextureAspect::StencilOnly) => Some(uint), }, + Self::NV12 => None, + Self::R16Unorm | Self::R16Snorm | Self::Rg16Unorm @@ -3304,6 +3430,8 @@ impl TextureFormat { Some(TextureAspect::StencilOnly) => Some(1), }, + Self::NV12 => None, + Self::Bc1RgbaUnorm | Self::Bc1RgbaUnormSrgb | Self::Bc4RUnorm | Self::Bc4RSnorm => { Some(8) } @@ -3395,6 +3523,8 @@ impl TextureFormat { TextureAspect::DepthOnly | TextureAspect::StencilOnly => 1, }, + Self::NV12 => 3, + Self::Bc4RUnorm | Self::Bc4RSnorm => 1, Self::Bc5RgUnorm | Self::Bc5RgSnorm => 2, Self::Bc6hRgbUfloat | Self::Bc6hRgbFloat => 3, @@ -6507,44 +6637,84 @@ impl_bitflags!(PipelineStatisticsTypes); /// Argument buffer layout for draw_indirect commands. #[repr(C)] -#[derive(Clone, Copy, Debug)] +#[derive(Copy, Clone, Debug, Default)] pub struct DrawIndirectArgs { /// The number of vertices to draw. pub vertex_count: u32, /// The number of instances to draw. pub instance_count: u32, - /// Offset into the vertex buffers, in vertices, to begin drawing from. + /// The Index of the first vertex to draw. pub first_vertex: u32, - /// First instance to draw. + /// The instance ID of the first instance to draw. + /// + /// Has to be 0, unless [`Features::INDIRECT_FIRST_INSTANCE`](crate::Features::INDIRECT_FIRST_INSTANCE) is enabled. pub first_instance: u32, } +impl DrawIndirectArgs { + /// Returns the bytes representation of the struct, ready to be written in a buffer. + pub fn as_bytes(&self) -> &[u8] { + unsafe { + std::mem::transmute(std::slice::from_raw_parts( + self as *const _ as *const u8, + std::mem::size_of::(), + )) + } + } +} + /// Argument buffer layout for draw_indexed_indirect commands. #[repr(C)] -#[derive(Clone, Copy, Debug)] +#[derive(Copy, Clone, Debug, Default)] pub struct DrawIndexedIndirectArgs { /// The number of indices to draw. pub index_count: u32, /// The number of instances to draw. pub instance_count: u32, - /// Offset into the index buffer, in indices, begin drawing from. + /// The first index within the index buffer. pub first_index: u32, - /// Added to each index value before indexing into the vertex buffers. + /// The value added to the vertex index before indexing into the vertex buffer. pub base_vertex: i32, - /// First instance to draw. + /// The instance ID of the first instance to draw. + /// + /// Has to be 0, unless [`Features::INDIRECT_FIRST_INSTANCE`](crate::Features::INDIRECT_FIRST_INSTANCE) is enabled. pub first_instance: u32, } +impl DrawIndexedIndirectArgs { + /// Returns the bytes representation of the struct, ready to be written in a buffer. + pub fn as_bytes(&self) -> &[u8] { + unsafe { + std::mem::transmute(std::slice::from_raw_parts( + self as *const _ as *const u8, + std::mem::size_of::(), + )) + } + } +} + /// Argument buffer layout for dispatch_indirect commands. #[repr(C)] -#[derive(Clone, Copy, Debug)] +#[derive(Copy, Clone, Debug, Default)] pub struct DispatchIndirectArgs { - /// X dimension of the grid of workgroups to dispatch. - pub group_size_x: u32, - /// Y dimension of the grid of workgroups to dispatch. - pub group_size_y: u32, - /// Z dimension of the grid of workgroups to dispatch. - pub group_size_z: u32, + /// The number of work groups in X dimension. + pub x: u32, + /// The number of work groups in Y dimension. + pub y: u32, + /// The number of work groups in Z dimension. + pub z: u32, +} + +impl DispatchIndirectArgs { + /// Returns the bytes representation of the struct, ready to be written into a buffer. + pub fn as_bytes(&self) -> &[u8] { + unsafe { + std::mem::transmute(std::slice::from_raw_parts( + self as *const _ as *const u8, + std::mem::size_of::(), + )) + } + } } /// Describes how shader bound checks should be performed.