Bug 1910150: Update wgpu to 9c6ae1be (2024-7-31) r=webgpu-reviewers,supply-chain-reviewers,ErichDonGubler
Update the following crates in `third_party/rust` to commit 9c6ae1be from `github.com/gfx-rs/wgpu`: - d3d12 - naga - wgpu-core - wgpu-hal - wgpu-types Update dependencies: - bit-set 0.8.0 - bit-vec 0.8.0 - gpu-allocator 0.27 Make necessary minor changes to `gfx/wgpu_bindings`. Add appropriate audits to `supply-chain/audits.toml`. Differential Revision: https://phabricator.services.mozilla.com/D218695
This commit is contained 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=aeb2067e8120c1ff480625c00b9571db8d01d5a4"]
|
||||
[source."git+https://github.com/gfx-rs/wgpu?rev=9c6ae1beae2490ce44d99034f7f1faada936f3d8"]
|
||||
git = "https://github.com/gfx-rs/wgpu"
|
||||
rev = "aeb2067e8120c1ff480625c00b9571db8d01d5a4"
|
||||
rev = "9c6ae1beae2490ce44d99034f7f1faada936f3d8"
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
[source."git+https://github.com/hsivonen/any_all_workaround?rev=7fb1b7034c9f172aade21ee1c8554e8d8a48af80"]
|
||||
|
||||
32
Cargo.lock
generated
32
Cargo.lock
generated
@@ -460,18 +460,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "bit-set"
|
||||
version = "0.6.0"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0481a0e032742109b1133a095184ee93d88f3dc9e0d28a5d033dc77a073f44f"
|
||||
checksum = "08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3"
|
||||
dependencies = [
|
||||
"bit-vec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bit-vec"
|
||||
version = "0.7.0"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2c54ff287cfc0a34f38a6b832ea1bd8e448a330b3e40a50859e6488bee07f22"
|
||||
checksum = "5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
@@ -1241,8 +1241,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "d3d12"
|
||||
version = "0.20.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=aeb2067e8120c1ff480625c00b9571db8d01d5a4#aeb2067e8120c1ff480625c00b9571db8d01d5a4"
|
||||
version = "22.0.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=9c6ae1beae2490ce44d99034f7f1faada936f3d8#9c6ae1beae2490ce44d99034f7f1faada936f3d8"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"libloading",
|
||||
@@ -2553,9 +2553,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "gpu-allocator"
|
||||
version = "0.26.0"
|
||||
version = "0.27.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fdd4240fc91d3433d5e5b0fc5b67672d771850dc19bbee03c1381e19322803d7"
|
||||
checksum = "c151a2a5ef800297b4e79efa4f4bec035c5f51d5ae587287c9b952bdf734cacd"
|
||||
dependencies = [
|
||||
"log",
|
||||
"presser",
|
||||
@@ -4022,8 +4022,8 @@ checksum = "a2983372caf4480544083767bf2d27defafe32af49ab4df3a0b7fc90793a3664"
|
||||
|
||||
[[package]]
|
||||
name = "naga"
|
||||
version = "0.20.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=aeb2067e8120c1ff480625c00b9571db8d01d5a4#aeb2067e8120c1ff480625c00b9571db8d01d5a4"
|
||||
version = "22.0.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=9c6ae1beae2490ce44d99034f7f1faada936f3d8#9c6ae1beae2490ce44d99034f7f1faada936f3d8"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bit-set",
|
||||
@@ -6768,8 +6768,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wgpu-core"
|
||||
version = "0.20.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=aeb2067e8120c1ff480625c00b9571db8d01d5a4#aeb2067e8120c1ff480625c00b9571db8d01d5a4"
|
||||
version = "22.0.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=9c6ae1beae2490ce44d99034f7f1faada936f3d8#9c6ae1beae2490ce44d99034f7f1faada936f3d8"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bit-vec",
|
||||
@@ -6793,8 +6793,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wgpu-hal"
|
||||
version = "0.20.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=aeb2067e8120c1ff480625c00b9571db8d01d5a4#aeb2067e8120c1ff480625c00b9571db8d01d5a4"
|
||||
version = "22.0.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=9c6ae1beae2490ce44d99034f7f1faada936f3d8#9c6ae1beae2490ce44d99034f7f1faada936f3d8"
|
||||
dependencies = [
|
||||
"android_system_properties",
|
||||
"arrayvec",
|
||||
@@ -6832,8 +6832,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wgpu-types"
|
||||
version = "0.20.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=aeb2067e8120c1ff480625c00b9571db8d01d5a4#aeb2067e8120c1ff480625c00b9571db8d01d5a4"
|
||||
version = "22.0.0"
|
||||
source = "git+https://github.com/gfx-rs/wgpu?rev=9c6ae1beae2490ce44d99034f7f1faada936f3d8#9c6ae1beae2490ce44d99034f7f1faada936f3d8"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"js-sys",
|
||||
|
||||
@@ -17,7 +17,7 @@ default = []
|
||||
[dependencies.wgc]
|
||||
package = "wgpu-core"
|
||||
git = "https://github.com/gfx-rs/wgpu"
|
||||
rev = "aeb2067e8120c1ff480625c00b9571db8d01d5a4"
|
||||
rev = "9c6ae1beae2490ce44d99034f7f1faada936f3d8"
|
||||
# TODO: remove the replay feature on the next update containing https://github.com/gfx-rs/wgpu/pull/5182
|
||||
features = ["serde", "replay", "trace", "strict_asserts", "wgsl", "api_log_info"]
|
||||
|
||||
@@ -26,37 +26,37 @@ features = ["serde", "replay", "trace", "strict_asserts", "wgsl", "api_log_info"
|
||||
[target.'cfg(any(target_os = "macos", target_os = "ios"))'.dependencies.wgc]
|
||||
package = "wgpu-core"
|
||||
git = "https://github.com/gfx-rs/wgpu"
|
||||
rev = "aeb2067e8120c1ff480625c00b9571db8d01d5a4"
|
||||
rev = "9c6ae1beae2490ce44d99034f7f1faada936f3d8"
|
||||
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 = "aeb2067e8120c1ff480625c00b9571db8d01d5a4"
|
||||
rev = "9c6ae1beae2490ce44d99034f7f1faada936f3d8"
|
||||
features = ["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 = "aeb2067e8120c1ff480625c00b9571db8d01d5a4"
|
||||
rev = "9c6ae1beae2490ce44d99034f7f1faada936f3d8"
|
||||
features = ["vulkan"]
|
||||
|
||||
[dependencies.wgt]
|
||||
package = "wgpu-types"
|
||||
git = "https://github.com/gfx-rs/wgpu"
|
||||
rev = "aeb2067e8120c1ff480625c00b9571db8d01d5a4"
|
||||
rev = "9c6ae1beae2490ce44d99034f7f1faada936f3d8"
|
||||
|
||||
[dependencies.wgh]
|
||||
package = "wgpu-hal"
|
||||
git = "https://github.com/gfx-rs/wgpu"
|
||||
rev = "aeb2067e8120c1ff480625c00b9571db8d01d5a4"
|
||||
rev = "9c6ae1beae2490ce44d99034f7f1faada936f3d8"
|
||||
features = ["windows_rs", "oom_panic", "device_lost_panic", "internal_error_panic"]
|
||||
|
||||
[target.'cfg(windows)'.dependencies.d3d12]
|
||||
git = "https://github.com/gfx-rs/wgpu"
|
||||
rev = "aeb2067e8120c1ff480625c00b9571db8d01d5a4"
|
||||
rev = "9c6ae1beae2490ce44d99034f7f1faada936f3d8"
|
||||
|
||||
[target.'cfg(windows)'.dependencies]
|
||||
winapi = "0.3"
|
||||
|
||||
@@ -20,11 +20,11 @@ origin:
|
||||
|
||||
# Human-readable identifier for this version/release
|
||||
# Generally "version NNN", "tag SSS", "bookmark SSS"
|
||||
release: aeb2067e8120c1ff480625c00b9571db8d01d5a4 (2024-07-17T23:11:04Z).
|
||||
release: 9c6ae1beae2490ce44d99034f7f1faada936f3d8 (2024-7-31).
|
||||
|
||||
# Revision to pull in
|
||||
# Must be a long or short commit SHA (long preferred)
|
||||
revision: aeb2067e8120c1ff480625c00b9571db8d01d5a4
|
||||
revision: 9c6ae1beae2490ce44d99034f7f1faada936f3d8
|
||||
|
||||
license: ['MIT', 'Apache-2.0']
|
||||
|
||||
|
||||
@@ -69,7 +69,6 @@ impl ProgrammableStageDescriptor {
|
||||
entry_point: cow_label(&self.entry_point),
|
||||
constants: Cow::Owned(constants),
|
||||
zero_initialize_workgroup_memory: true,
|
||||
vertex_pulling_transform: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -586,7 +586,7 @@ pub extern "C" fn wgpu_server_buffer_destroy(global: &Global, self_id: id::Buffe
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wgpu_server_buffer_drop(global: &Global, self_id: id::BufferId) {
|
||||
gfx_select!(self_id => global.buffer_drop(self_id, false));
|
||||
gfx_select!(self_id => global.buffer_drop(self_id));
|
||||
}
|
||||
|
||||
#[allow(unused_variables)]
|
||||
@@ -1317,12 +1317,12 @@ pub extern "C" fn wgpu_server_texture_destroy(global: &Global, self_id: id::Text
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wgpu_server_texture_drop(global: &Global, self_id: id::TextureId) {
|
||||
gfx_select!(self_id => global.texture_drop(self_id, false));
|
||||
gfx_select!(self_id => global.texture_drop(self_id));
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn wgpu_server_texture_view_drop(global: &Global, self_id: id::TextureViewId) {
|
||||
gfx_select!(self_id => global.texture_view_drop(self_id, false)).unwrap();
|
||||
gfx_select!(self_id => global.texture_view_drop(self_id)).unwrap();
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
|
||||
@@ -870,6 +870,11 @@ who = "Teodor Tanasoaia <ttanasoaia@mozilla.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.5.3 -> 0.6.0"
|
||||
|
||||
[[audits.bit-set]]
|
||||
who = "Jim Blandy <jimb@red-bean.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.6.0 -> 0.8.0"
|
||||
|
||||
[[audits.bit-vec]]
|
||||
who = "Aria Beingessner <a.beingessner@gmail.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
@@ -881,6 +886,11 @@ who = "Teodor Tanasoaia <ttanasoaia@mozilla.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.6.3 -> 0.7.0"
|
||||
|
||||
[[audits.bit-vec]]
|
||||
who = "Jim Blandy <jimb@red-bean.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.7.0 -> 0.8.0"
|
||||
|
||||
[[audits.bitflags]]
|
||||
who = "Alex Franchuk <afranchuk@mozilla.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
@@ -1477,13 +1487,14 @@ criteria = "safe-to-deploy"
|
||||
delta = "0.19.0 -> 0.20.0"
|
||||
|
||||
[[audits.d3d12]]
|
||||
who = [
|
||||
"Jim Blandy <jimb@red-bean.com>",
|
||||
"Teodor Tanasoaia <ttanasoaia@mozilla.com>",
|
||||
"Erich Gubler <erichdongubler@gmail.com>",
|
||||
]
|
||||
who = "Jim Blandy <jimb@red-bean.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.20.0 -> 0.20.0@git:aeb2067e8120c1ff480625c00b9571db8d01d5a4"
|
||||
delta = "0.20.0 -> 22.0.0"
|
||||
|
||||
[[audits.d3d12]]
|
||||
who = "Jim Blandy <jimb@red-bean.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "22.0.0 -> 22.0.0@git:9c6ae1beae2490ce44d99034f7f1faada936f3d8"
|
||||
importable = false
|
||||
|
||||
[[audits.darling]]
|
||||
@@ -2268,6 +2279,11 @@ criteria = "safe-to-deploy"
|
||||
delta = "0.25.0 -> 0.26.0"
|
||||
notes = "New Metal backend is written with no `unsafe`. New `unsafe` usage of DX12's platform APIs appear correct and safe. Otherwise, minimal changes."
|
||||
|
||||
[[audits.gpu-allocator]]
|
||||
who = "Jim Blandy <jimb@red-bean.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.26.0 -> 0.27.0"
|
||||
|
||||
[[audits.gpu-descriptor]]
|
||||
who = "Mike Hommey <mh+mozilla@glandium.org>"
|
||||
criteria = "safe-to-deploy"
|
||||
@@ -3084,13 +3100,14 @@ criteria = "safe-to-deploy"
|
||||
delta = "0.19.2 -> 0.20.0"
|
||||
|
||||
[[audits.naga]]
|
||||
who = [
|
||||
"Jim Blandy <jimb@red-bean.com>",
|
||||
"Teodor Tanasoaia <ttanasoaia@mozilla.com>",
|
||||
"Erich Gubler <erichdongubler@gmail.com>",
|
||||
]
|
||||
who = "Jim Blandy <jimb@red-bean.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.20.0 -> 0.20.0@git:aeb2067e8120c1ff480625c00b9571db8d01d5a4"
|
||||
delta = "0.20.0 -> 22.0.0"
|
||||
|
||||
[[audits.naga]]
|
||||
who = "Jim Blandy <jimb@red-bean.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "22.0.0 -> 22.0.0@git:9c6ae1beae2490ce44d99034f7f1faada936f3d8"
|
||||
importable = false
|
||||
|
||||
[[audits.net2]]
|
||||
@@ -5043,13 +5060,14 @@ criteria = "safe-to-deploy"
|
||||
delta = "0.19.3 -> 0.20.0"
|
||||
|
||||
[[audits.wgpu-core]]
|
||||
who = [
|
||||
"Jim Blandy <jimb@red-bean.com>",
|
||||
"Teodor Tanasoaia <ttanasoaia@mozilla.com>",
|
||||
"Erich Gubler <erichdongubler@gmail.com>",
|
||||
]
|
||||
who = "Jim Blandy <jimb@red-bean.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.20.0 -> 0.20.0@git:aeb2067e8120c1ff480625c00b9571db8d01d5a4"
|
||||
delta = "0.20.0 -> 22.0.0"
|
||||
|
||||
[[audits.wgpu-core]]
|
||||
who = "Jim Blandy <jimb@red-bean.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "22.0.0 -> 22.0.0@git:9c6ae1beae2490ce44d99034f7f1faada936f3d8"
|
||||
importable = false
|
||||
|
||||
[[audits.wgpu-hal]]
|
||||
@@ -5111,13 +5129,14 @@ criteria = "safe-to-deploy"
|
||||
delta = "0.19.3 -> 0.20.0"
|
||||
|
||||
[[audits.wgpu-hal]]
|
||||
who = [
|
||||
"Jim Blandy <jimb@red-bean.com>",
|
||||
"Teodor Tanasoaia <ttanasoaia@mozilla.com>",
|
||||
"Erich Gubler <erichdongubler@gmail.com>",
|
||||
]
|
||||
who = "Jim Blandy <jimb@red-bean.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.20.0 -> 0.20.0@git:aeb2067e8120c1ff480625c00b9571db8d01d5a4"
|
||||
delta = "0.20.0 -> 22.0.0"
|
||||
|
||||
[[audits.wgpu-hal]]
|
||||
who = "Jim Blandy <jimb@red-bean.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "22.0.0 -> 22.0.0@git:9c6ae1beae2490ce44d99034f7f1faada936f3d8"
|
||||
importable = false
|
||||
|
||||
[[audits.wgpu-types]]
|
||||
@@ -5179,13 +5198,14 @@ criteria = "safe-to-deploy"
|
||||
delta = "0.19.2 -> 0.20.0"
|
||||
|
||||
[[audits.wgpu-types]]
|
||||
who = [
|
||||
"Jim Blandy <jimb@red-bean.com>",
|
||||
"Teodor Tanasoaia <ttanasoaia@mozilla.com>",
|
||||
"Erich Gubler <erichdongubler@gmail.com>",
|
||||
]
|
||||
who = "Jim Blandy <jimb@red-bean.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.20.0 -> 0.20.0@git:aeb2067e8120c1ff480625c00b9571db8d01d5a4"
|
||||
delta = "0.20.0 -> 22.0.0"
|
||||
|
||||
[[audits.wgpu-types]]
|
||||
who = "Jim Blandy <jimb@red-bean.com>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "22.0.0 -> 22.0.0@git:9c6ae1beae2490ce44d99034f7f1faada936f3d8"
|
||||
importable = false
|
||||
|
||||
[[audits.whatsys]]
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"072bebcdc135cd08bf1fc8b1d6098fde8174868fbfe316261150861748a4bea0","LICENSE-APACHE":"8173d5c29b4f956d532781d2b86e4e30f83e6b7878dce18c919451d6ba707c90","LICENSE-MIT":"f51ac2c59a222f7476ce507ca879960e2b64ea64bb2786eefdbeb7b0b538d1b7","README.md":"3722445d55d05fa0095b68ccce1b17972584ce8bfcddb911a7e1071cdcb0ef77","deploy-docs.sh":"7b66111b124c1c7e59cb84cf110d98b5cb783bd35a676e970d9b3035e55f7dfd","src/lib.rs":"33dd2f06f955acede0dd632b11e622eba87b84264cd43381d4a6099d45255a9e"},"package":"f0481a0e032742109b1133a095184ee93d88f3dc9e0d28a5d033dc77a073f44f"}
|
||||
{"files":{"Cargo.toml":"f718d1e3b585881b737a689fdcc34b7df64818b14093907d5c4546e29692ea8f","LICENSE-APACHE":"8173d5c29b4f956d532781d2b86e4e30f83e6b7878dce18c919451d6ba707c90","LICENSE-MIT":"f51ac2c59a222f7476ce507ca879960e2b64ea64bb2786eefdbeb7b0b538d1b7","README.md":"b2301e8a7953cc006062459041fc9edaa9e31ad5fc2aa2009ed742380624e4c5","RELEASES.md":"78721919b25f13b36004ff40acde09fb1beaaa4e1d721fe30c7b1eb6f9325190","benches/bench.rs":"b044b6aa529e73d921ade54b85dd1c07543a588999ba69192714774abf80edbf","src/lib.rs":"c090ea3ef7cd0367c8e157418c5d51072a474f660b1c74c94fa68be696a079e0"},"package":"08807e080ed7f9d5433fa9b275196cfc35414f66a0c79d864dc51a0d825231a3"}
|
||||
26
third_party/rust/bit-set/Cargo.toml
vendored
26
third_party/rust/bit-set/Cargo.toml
vendored
@@ -10,8 +10,9 @@
|
||||
# See Cargo.toml.orig for the original contents.
|
||||
|
||||
[package]
|
||||
edition = "2015"
|
||||
name = "bit-set"
|
||||
version = "0.6.0"
|
||||
version = "0.8.0"
|
||||
authors = ["Alexis Beingessner <a.beingessner@gmail.com>"]
|
||||
build = false
|
||||
autobins = false
|
||||
@@ -20,27 +21,42 @@ autotests = false
|
||||
autobenches = false
|
||||
description = "A set of bits"
|
||||
homepage = "https://github.com/contain-rs/bit-set"
|
||||
documentation = "https://contain-rs.github.io/bit-set/bit_set"
|
||||
documentation = "https://docs.rs/bit-set/"
|
||||
readme = "README.md"
|
||||
keywords = [
|
||||
"data-structures",
|
||||
"bitset",
|
||||
]
|
||||
license = "MIT/Apache-2.0"
|
||||
license = "Apache-2.0 OR MIT"
|
||||
repository = "https://github.com/contain-rs/bit-set"
|
||||
|
||||
[lib]
|
||||
name = "bit_set"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[[bench]]
|
||||
name = "bench"
|
||||
path = "benches/bench.rs"
|
||||
|
||||
[dependencies.bit-vec]
|
||||
version = "0.7.0"
|
||||
version = "0.8.0"
|
||||
default-features = false
|
||||
|
||||
[dependencies.serde]
|
||||
version = "1.0"
|
||||
features = ["derive"]
|
||||
optional = true
|
||||
|
||||
[dev-dependencies.rand]
|
||||
version = "0.8"
|
||||
|
||||
[dev-dependencies.serde_json]
|
||||
version = "1.0"
|
||||
|
||||
[features]
|
||||
bench = []
|
||||
default = ["std"]
|
||||
serde = [
|
||||
"dep:serde",
|
||||
"bit-vec/serde",
|
||||
]
|
||||
std = ["bit-vec/std"]
|
||||
|
||||
19
third_party/rust/bit-set/README.md
vendored
19
third_party/rust/bit-set/README.md
vendored
@@ -19,13 +19,13 @@
|
||||
|
||||
[crates.io shield]: https://img.shields.io/crates/v/bit-set?label=latest
|
||||
[crates.io link]: https://crates.io/crates/bit-set
|
||||
[docs.rs badge]: https://docs.rs/bit-set/badge.svg?version=0.6.0
|
||||
[docs.rs link]: https://docs.rs/bit-set/0.6.0/bit_set/
|
||||
[docs.rs badge]: https://docs.rs/bit-set/badge.svg?version=0.8.0
|
||||
[docs.rs link]: https://docs.rs/bit-set/0.8.0/bit_set/
|
||||
[github ci badge]: https://github.com/contain-rs/linked-hash-map/workflows/Rust/badge.svg?branch=master
|
||||
[rustc 1.0+]: https://img.shields.io/badge/rustc-1.0%2B-blue.svg
|
||||
[Rust 1.0]: https://blog.rust-lang.org/2015/05/15/Rust-1.0.html
|
||||
[deps.rs status]: https://deps.rs/crate/bit-set/0.6.0/status.svg
|
||||
[deps.rs link]: https://deps.rs/crate/bit-set/0.6.0
|
||||
[deps.rs status]: https://deps.rs/crate/bit-set/0.8.0/status.svg
|
||||
[deps.rs link]: https://deps.rs/crate/bit-set/0.8.0
|
||||
[shields.io download count]: https://img.shields.io/crates/d/bit-set.svg
|
||||
|
||||
## Usage
|
||||
@@ -34,7 +34,7 @@ Add this to your Cargo.toml:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
bit-set = "0.5"
|
||||
bit-set = "0.8"
|
||||
```
|
||||
|
||||
Since Rust 2018, `extern crate` is no longer mandatory. If your edition is old (Rust 2015),
|
||||
@@ -44,11 +44,18 @@ add this to your crate root:
|
||||
extern crate bit_set;
|
||||
```
|
||||
|
||||
If you want to use `serde`, enable it with the `serde` feature:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
bit-set = { version = "0.8", features = ["serde"] }
|
||||
```
|
||||
|
||||
If you want to use bit-set in a program that has `#![no_std]`, just drop default features:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
bit-set = { version = "0.5", default-features = false }
|
||||
bit-set = { version = "0.8", default-features = false }
|
||||
```
|
||||
|
||||
<!-- cargo-rdme start -->
|
||||
|
||||
10
third_party/rust/bit-set/RELEASES.md
vendored
Normal file
10
third_party/rust/bit-set/RELEASES.md
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
Version 0.7.0 (not yet released) (ZERO BREAKING CHANGES)
|
||||
========================================================
|
||||
|
||||
<a id="v0.7.0"></a>
|
||||
|
||||
- `serde::Serialize`, `Deserialize` is derived under the `serde` optional feature
|
||||
- `impl Display` is implemented
|
||||
- `impl Debug` has different output (we do not promise stable `Debug` output)
|
||||
- `fn truncate` is implemented
|
||||
- `fn get_mut` is implemented
|
||||
65
third_party/rust/bit-set/benches/bench.rs
vendored
Normal file
65
third_party/rust/bit-set/benches/bench.rs
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
// Copyright 2012-2024 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![feature(test)]
|
||||
|
||||
extern crate bit_set;
|
||||
extern crate bit_vec;
|
||||
extern crate rand;
|
||||
extern crate test;
|
||||
|
||||
use bit_set::BitSet;
|
||||
use bit_vec::BitVec;
|
||||
use rand::{rngs::ThreadRng, thread_rng, RngCore};
|
||||
|
||||
use test::{black_box, Bencher};
|
||||
|
||||
const BENCH_BITS: usize = 1 << 14;
|
||||
const BITS: usize = 32;
|
||||
|
||||
fn rng() -> ThreadRng {
|
||||
thread_rng()
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_bit_vecset_small(b: &mut Bencher) {
|
||||
let mut r = rng();
|
||||
let mut bit_vec = BitSet::new();
|
||||
b.iter(|| {
|
||||
for _ in 0..100 {
|
||||
bit_vec.insert((r.next_u32() as usize) % BITS);
|
||||
}
|
||||
black_box(&bit_vec);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_bit_vecset_big(b: &mut Bencher) {
|
||||
let mut r = rng();
|
||||
let mut bit_vec = BitSet::new();
|
||||
b.iter(|| {
|
||||
for _ in 0..100 {
|
||||
bit_vec.insert((r.next_u32() as usize) % BENCH_BITS);
|
||||
}
|
||||
black_box(&bit_vec);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_bit_vecset_iter(b: &mut Bencher) {
|
||||
let bit_vec = BitSet::from_bit_vec(BitVec::from_fn(BENCH_BITS, |idx| idx % 3 == 0));
|
||||
b.iter(|| {
|
||||
let mut sum = 0;
|
||||
for idx in &bit_vec {
|
||||
sum += idx as usize;
|
||||
}
|
||||
sum
|
||||
})
|
||||
}
|
||||
20
third_party/rust/bit-set/deploy-docs.sh
vendored
20
third_party/rust/bit-set/deploy-docs.sh
vendored
@@ -1,20 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -o errexit -o nounset
|
||||
|
||||
rev=$(git rev-parse --short HEAD)
|
||||
|
||||
cd target/doc
|
||||
|
||||
git init
|
||||
git config user.email 'FlashCat@users.noreply.github.com'
|
||||
git config user.name 'FlashCat'
|
||||
git remote add upstream "https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git"
|
||||
git fetch upstream gh-pages
|
||||
git reset upstream/gh-pages
|
||||
|
||||
touch .
|
||||
|
||||
git add -A .
|
||||
git commit -m "rebuild pages at ${rev}"
|
||||
git push -q upstream HEAD:gh-pages
|
||||
224
third_party/rust/bit-set/src/lib.rs
vendored
224
third_party/rust/bit-set/src/lib.rs
vendored
@@ -48,15 +48,13 @@
|
||||
//! let bv = s.into_bit_vec();
|
||||
//! assert!(bv[3]);
|
||||
//! ```
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/bit-set/0.8.0")]
|
||||
#![no_std]
|
||||
#![cfg_attr(feature = "bench", feature(test))]
|
||||
|
||||
extern crate bit_vec;
|
||||
#[cfg(test)]
|
||||
extern crate rand;
|
||||
#[cfg(feature = "bench")]
|
||||
extern crate test;
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
extern crate serde;
|
||||
|
||||
#[cfg(any(test, feature = "std"))]
|
||||
extern crate std;
|
||||
@@ -119,6 +117,7 @@ fn match_words<'a, 'b, B: BitBlock>(
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg_attr(feature = "serde", derive(serde::Deserialize, serde::Serialize))]
|
||||
pub struct BitSet<B = u32> {
|
||||
bit_vec: BitVec<B>,
|
||||
}
|
||||
@@ -341,10 +340,10 @@ impl<B: BitBlock> BitSet<B> {
|
||||
/// ```
|
||||
/// use bit_set::BitSet;
|
||||
///
|
||||
/// let mut s = BitSet::new();
|
||||
/// s.insert(0);
|
||||
/// let mut set = BitSet::new();
|
||||
/// set.insert(0);
|
||||
///
|
||||
/// let bv = s.get_ref();
|
||||
/// let bv = set.get_ref();
|
||||
/// assert_eq!(bv[0], true);
|
||||
/// ```
|
||||
#[inline]
|
||||
@@ -352,6 +351,31 @@ impl<B: BitBlock> BitSet<B> {
|
||||
&self.bit_vec
|
||||
}
|
||||
|
||||
/// Returns a mutable reference to the underlying bit vector.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// use bit_set::BitSet;
|
||||
///
|
||||
/// let mut set = BitSet::new();
|
||||
/// set.insert(0);
|
||||
/// set.insert(3);
|
||||
///
|
||||
/// {
|
||||
/// let bv = set.get_mut();
|
||||
/// bv.set(1, true);
|
||||
/// }
|
||||
///
|
||||
/// assert!(set.contains(0));
|
||||
/// assert!(set.contains(1));
|
||||
/// assert!(set.contains(3));
|
||||
/// ```
|
||||
#[inline]
|
||||
pub fn get_mut(&mut self) -> &mut BitVec<B> {
|
||||
&mut self.bit_vec
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn other_op<F>(&mut self, other: &Self, mut f: F)
|
||||
where
|
||||
@@ -421,8 +445,8 @@ impl<B: BitBlock> BitSet<B> {
|
||||
unsafe {
|
||||
bit_vec.storage_mut().truncate(trunc_len);
|
||||
bit_vec.set_len(trunc_len * B::bits());
|
||||
bit_vec.shrink_to_fit();
|
||||
}
|
||||
bit_vec.shrink_to_fit();
|
||||
}
|
||||
|
||||
/// Iterator over each usize stored in the `BitSet`.
|
||||
@@ -445,7 +469,7 @@ impl<B: BitBlock> BitSet<B> {
|
||||
}
|
||||
|
||||
/// Iterator over each usize stored in `self` union `other`.
|
||||
/// See [union_with](#method.union_with) for an efficient in-place version.
|
||||
/// See [`union_with`] for an efficient in-place version.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@@ -460,6 +484,8 @@ impl<B: BitBlock> BitSet<B> {
|
||||
/// println!("{}", x);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [`union_with`]: Self::union_with
|
||||
#[inline]
|
||||
pub fn union<'a>(&'a self, other: &'a Self) -> Union<'a, B> {
|
||||
fn or<B: BitBlock>(w1: B, w2: B) -> B {
|
||||
@@ -474,7 +500,7 @@ impl<B: BitBlock> BitSet<B> {
|
||||
}
|
||||
|
||||
/// Iterator over each usize stored in `self` intersect `other`.
|
||||
/// See [intersect_with](#method.intersect_with) for an efficient in-place version.
|
||||
/// See [`intersect_with`] for an efficient in-place version.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@@ -489,6 +515,8 @@ impl<B: BitBlock> BitSet<B> {
|
||||
/// println!("{}", x);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [`intersect_with`]: Self::intersect_with
|
||||
#[inline]
|
||||
pub fn intersection<'a>(&'a self, other: &'a Self) -> Intersection<'a, B> {
|
||||
fn bitand<B: BitBlock>(w1: B, w2: B) -> B {
|
||||
@@ -496,18 +524,18 @@ impl<B: BitBlock> BitSet<B> {
|
||||
}
|
||||
let min = cmp::min(self.bit_vec.len(), other.bit_vec.len());
|
||||
|
||||
Intersection(
|
||||
BlockIter::from_blocks(TwoBitPositions {
|
||||
Intersection {
|
||||
iter: BlockIter::from_blocks(TwoBitPositions {
|
||||
set: self.bit_vec.blocks(),
|
||||
other: other.bit_vec.blocks(),
|
||||
merge: bitand,
|
||||
})
|
||||
.take(min),
|
||||
)
|
||||
}),
|
||||
n: min,
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterator over each usize stored in the `self` setminus `other`.
|
||||
/// See [difference_with](#method.difference_with) for an efficient in-place version.
|
||||
/// See [`difference_with`] for an efficient in-place version.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@@ -529,6 +557,8 @@ impl<B: BitBlock> BitSet<B> {
|
||||
/// println!("{}", x);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [`difference_with`]: Self::difference_with
|
||||
#[inline]
|
||||
pub fn difference<'a>(&'a self, other: &'a Self) -> Difference<'a, B> {
|
||||
fn diff<B: BitBlock>(w1: B, w2: B) -> B {
|
||||
@@ -543,8 +573,7 @@ impl<B: BitBlock> BitSet<B> {
|
||||
}
|
||||
|
||||
/// Iterator over each usize stored in the symmetric difference of `self` and `other`.
|
||||
/// See [symmetric_difference_with](#method.symmetric_difference_with) for
|
||||
/// an efficient in-place version.
|
||||
/// See [`symmetric_difference_with`] for an efficient in-place version.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@@ -559,6 +588,8 @@ impl<B: BitBlock> BitSet<B> {
|
||||
/// println!("{}", x);
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// [`symmetric_difference_with`]: Self::symmetric_difference_with
|
||||
#[inline]
|
||||
pub fn symmetric_difference<'a>(&'a self, other: &'a Self) -> SymmetricDifference<'a, B> {
|
||||
fn bitxor<B: BitBlock>(w1: B, w2: B) -> B {
|
||||
@@ -815,7 +846,7 @@ impl<B: BitBlock> BitSet<B> {
|
||||
// Ensure we have enough space to hold the new element
|
||||
let len = self.bit_vec.len();
|
||||
if value >= len {
|
||||
self.bit_vec.grow(value - len + 1, false)
|
||||
self.bit_vec.grow(value - len + 1, false);
|
||||
}
|
||||
|
||||
self.bit_vec.set(value, true);
|
||||
@@ -833,6 +864,11 @@ impl<B: BitBlock> BitSet<B> {
|
||||
|
||||
true
|
||||
}
|
||||
|
||||
/// Excludes `element` and all greater elements from the `BitSet`.
|
||||
pub fn truncate(&mut self, element: usize) {
|
||||
self.bit_vec.truncate(element);
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: BitBlock> fmt::Debug for BitSet<B> {
|
||||
@@ -884,7 +920,14 @@ pub struct Iter<'a, B: 'a>(BlockIter<Blocks<'a, B>, B>);
|
||||
#[derive(Clone)]
|
||||
pub struct Union<'a, B: 'a>(BlockIter<TwoBitPositions<'a, B>, B>);
|
||||
#[derive(Clone)]
|
||||
pub struct Intersection<'a, B: 'a>(Take<BlockIter<TwoBitPositions<'a, B>, B>>);
|
||||
pub struct Intersection<'a, B: 'a> {
|
||||
iter: BlockIter<TwoBitPositions<'a, B>, B>,
|
||||
// as an optimization, we compute the maximum possible
|
||||
// number of elements in the intersection, and count it
|
||||
// down as we return elements. If we reach zero, we can
|
||||
// stop.
|
||||
n: usize,
|
||||
}
|
||||
#[derive(Clone)]
|
||||
pub struct Difference<'a, B: 'a>(BlockIter<TwoBitPositions<'a, B>, B>);
|
||||
#[derive(Clone)]
|
||||
@@ -916,10 +959,14 @@ where
|
||||
Some(self.head_offset + (B::count_ones(k)))
|
||||
}
|
||||
|
||||
fn count(self) -> usize {
|
||||
self.head.count_ones() + self.tail.map(|block| block.count_ones()).sum::<usize>()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
match self.tail.size_hint() {
|
||||
(_, Some(h)) => (0, Some(1 + h * B::bits())),
|
||||
(_, Some(h)) => (0, Some((1 + h) * B::bits())),
|
||||
_ => (0, None),
|
||||
}
|
||||
}
|
||||
@@ -962,6 +1009,10 @@ impl<'a, B: BitBlock> Iterator for Iter<'a, B> {
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.0.size_hint()
|
||||
}
|
||||
#[inline]
|
||||
fn count(self) -> usize {
|
||||
self.0.count()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, B: BitBlock> Iterator for Union<'a, B> {
|
||||
@@ -975,6 +1026,10 @@ impl<'a, B: BitBlock> Iterator for Union<'a, B> {
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.0.size_hint()
|
||||
}
|
||||
#[inline]
|
||||
fn count(self) -> usize {
|
||||
self.0.count()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, B: BitBlock> Iterator for Intersection<'a, B> {
|
||||
@@ -982,11 +1037,25 @@ impl<'a, B: BitBlock> Iterator for Intersection<'a, B> {
|
||||
|
||||
#[inline]
|
||||
fn next(&mut self) -> Option<usize> {
|
||||
self.0.next()
|
||||
if self.n != 0 {
|
||||
self.n -= 1;
|
||||
self.iter.next()
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
#[inline]
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.0.size_hint()
|
||||
// We could invoke self.iter.size_hint() and incorporate that into the hint.
|
||||
// In practice, that does not seem worthwhile because the lower bound will
|
||||
// always be zero and the upper bound could only possibly less then n in a
|
||||
// partially iterated iterator. However, it makes little sense ask for size_hint
|
||||
// in a partially iterated iterator, so it did not seem worthwhile.
|
||||
(0, Some(self.n))
|
||||
}
|
||||
#[inline]
|
||||
fn count(self) -> usize {
|
||||
self.iter.count()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1001,6 +1070,10 @@ impl<'a, B: BitBlock> Iterator for Difference<'a, B> {
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.0.size_hint()
|
||||
}
|
||||
#[inline]
|
||||
fn count(self) -> usize {
|
||||
self.0.count()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, B: BitBlock> Iterator for SymmetricDifference<'a, B> {
|
||||
@@ -1014,6 +1087,10 @@ impl<'a, B: BitBlock> Iterator for SymmetricDifference<'a, B> {
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.0.size_hint()
|
||||
}
|
||||
#[inline]
|
||||
fn count(self) -> usize {
|
||||
self.0.count()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, B: BitBlock> IntoIterator for &'a BitSet<B> {
|
||||
@@ -1061,12 +1138,14 @@ mod tests {
|
||||
|
||||
let idxs: Vec<_> = bit_vec.iter().collect();
|
||||
assert_eq!(idxs, [0, 2, 3]);
|
||||
assert_eq!(bit_vec.iter().count(), 3);
|
||||
|
||||
let long: BitSet = (0..10000).filter(|&n| n % 2 == 0).collect();
|
||||
let real: Vec<_> = (0..10000 / 2).map(|x| x * 2).collect();
|
||||
|
||||
let idxs: Vec<_> = long.iter().collect();
|
||||
assert_eq!(idxs, real);
|
||||
assert_eq!(long.iter().count(), real.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1132,6 +1211,7 @@ mod tests {
|
||||
let expected = [3, 5, 11, 77];
|
||||
let actual: Vec<_> = a.intersection(&b).collect();
|
||||
assert_eq!(actual, expected);
|
||||
assert_eq!(a.intersection(&b).count(), expected.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1151,6 +1231,7 @@ mod tests {
|
||||
let expected = [1, 5, 500];
|
||||
let actual: Vec<_> = a.difference(&b).collect();
|
||||
assert_eq!(actual, expected);
|
||||
assert_eq!(a.difference(&b).count(), expected.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1172,6 +1253,7 @@ mod tests {
|
||||
let expected = [1, 5, 11, 14, 220];
|
||||
let actual: Vec<_> = a.symmetric_difference(&b).collect();
|
||||
assert_eq!(actual, expected);
|
||||
assert_eq!(a.symmetric_difference(&b).count(), expected.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1197,6 +1279,7 @@ mod tests {
|
||||
let expected = [1, 3, 5, 9, 11, 13, 19, 24, 160, 200];
|
||||
let actual: Vec<_> = a.union(&b).collect();
|
||||
assert_eq!(actual, expected);
|
||||
assert_eq!(a.union(&b).count(), expected.len());
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1494,6 +1577,45 @@ mod tests {
|
||||
assert!(b.contains(1000));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_truncate() {
|
||||
let bytes = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF];
|
||||
|
||||
let mut s = BitSet::from_bytes(&bytes);
|
||||
s.truncate(5 * 8);
|
||||
|
||||
assert_eq!(s, BitSet::from_bytes(&bytes[..5]));
|
||||
assert_eq!(s.len(), 5 * 8);
|
||||
s.truncate(4 * 8);
|
||||
assert_eq!(s, BitSet::from_bytes(&bytes[..4]));
|
||||
assert_eq!(s.len(), 4 * 8);
|
||||
// Truncating to a size > s.len() should be a noop
|
||||
s.truncate(5 * 8);
|
||||
assert_eq!(s, BitSet::from_bytes(&bytes[..4]));
|
||||
assert_eq!(s.len(), 4 * 8);
|
||||
s.truncate(8);
|
||||
assert_eq!(s, BitSet::from_bytes(&bytes[..1]));
|
||||
assert_eq!(s.len(), 8);
|
||||
s.truncate(0);
|
||||
assert_eq!(s, BitSet::from_bytes(&[]));
|
||||
assert_eq!(s.len(), 0);
|
||||
}
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
#[test]
|
||||
fn test_serialization() {
|
||||
let bset: BitSet = BitSet::new();
|
||||
let serialized = serde_json::to_string(&bset).unwrap();
|
||||
let unserialized: BitSet = serde_json::from_str(&serialized).unwrap();
|
||||
assert_eq!(bset, unserialized);
|
||||
|
||||
let elems: Vec<usize> = vec![11, 42, 100, 101];
|
||||
let bset: BitSet = elems.iter().map(|n| *n).collect();
|
||||
let serialized = serde_json::to_string(&bset).unwrap();
|
||||
let unserialized = serde_json::from_str(&serialized).unwrap();
|
||||
assert_eq!(bset, unserialized);
|
||||
}
|
||||
|
||||
/*
|
||||
#[test]
|
||||
fn test_bit_set_append() {
|
||||
@@ -1557,55 +1679,3 @@ mod tests {
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
#[cfg(feature = "bench")]
|
||||
mod bench {
|
||||
use super::BitSet;
|
||||
use bit_vec::BitVec;
|
||||
use rand::{rngs::ThreadRng, thread_rng, RngCore};
|
||||
|
||||
use test::{black_box, Bencher};
|
||||
|
||||
const BENCH_BITS: usize = 1 << 14;
|
||||
const BITS: usize = 32;
|
||||
|
||||
fn rng() -> ThreadRng {
|
||||
thread_rng()
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_bit_vecset_small(b: &mut Bencher) {
|
||||
let mut r = rng();
|
||||
let mut bit_vec = BitSet::new();
|
||||
b.iter(|| {
|
||||
for _ in 0..100 {
|
||||
bit_vec.insert((r.next_u32() as usize) % BITS);
|
||||
}
|
||||
black_box(&bit_vec);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_bit_vecset_big(b: &mut Bencher) {
|
||||
let mut r = rng();
|
||||
let mut bit_vec = BitSet::new();
|
||||
b.iter(|| {
|
||||
for _ in 0..100 {
|
||||
bit_vec.insert((r.next_u32() as usize) % BENCH_BITS);
|
||||
}
|
||||
black_box(&bit_vec);
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_bit_vecset_iter(b: &mut Bencher) {
|
||||
let bit_vec = BitSet::from_bit_vec(BitVec::from_fn(BENCH_BITS, |idx| idx % 3 == 0));
|
||||
b.iter(|| {
|
||||
let mut sum = 0;
|
||||
for idx in &bit_vec {
|
||||
sum += idx as usize;
|
||||
}
|
||||
sum
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"files":{"Cargo.toml":"4b0b92b08b6e3ccc92da0a88ae49203b43429879f83c37a79cbeb17a9cd9fd2e","LICENSE-APACHE":"8173d5c29b4f956d532781d2b86e4e30f83e6b7878dce18c919451d6ba707c90","LICENSE-MIT":"f51ac2c59a222f7476ce507ca879960e2b64ea64bb2786eefdbeb7b0b538d1b7","README.md":"115294791cc85dd20010ce6854e230f585a87992e8e76c7af2a9b7a28b2cac8b","benches/bench.rs":"b0f3cd80ea37456a4ba7dee46f3aef0a143c7ab88418b8ca8e0661b9bb741d2a","crusader.sh":"e656dcb62d5122a64d55f837992e63cfd3beee37cf74c5ab6ff178a3c7ef943e","src/lib.rs":"2176d15b2dac5eb53d835705512d787dac646b2fa824b6bbff672e9ab7c7aec6"},"package":"d2c54ff287cfc0a34f38a6b832ea1bd8e448a330b3e40a50859e6488bee07f22"}
|
||||
{"files":{"Cargo.toml":"3ffdb0eaead44d902d6db061fec67c139107b79a1044b974fa56560644cb3a92","LICENSE-APACHE":"8173d5c29b4f956d532781d2b86e4e30f83e6b7878dce18c919451d6ba707c90","LICENSE-MIT":"f51ac2c59a222f7476ce507ca879960e2b64ea64bb2786eefdbeb7b0b538d1b7","README.md":"5fc245f9be5f4c99931ca018b09603d29f9e376d8f9bc77cb7b156a4bdc7926a","RELEASES.md":"19717f09fe2af669be80801a5702ecd166e6001194c935e81669f72619e4144a","benches/bench.rs":"b0f3cd80ea37456a4ba7dee46f3aef0a143c7ab88418b8ca8e0661b9bb741d2a","crusader.sh":"e656dcb62d5122a64d55f837992e63cfd3beee37cf74c5ab6ff178a3c7ef943e","src/lib.rs":"2c570ee7e33315cb8f1cbb33bbb91aee9b4b9dc8521f488837414e890a149084"},"package":"5e764a1d40d510daf35e07be9eb06e75770908c27d411ee6c92109c9840eaaf7"}
|
||||
8
third_party/rust/bit-vec/Cargo.toml
vendored
8
third_party/rust/bit-vec/Cargo.toml
vendored
@@ -12,7 +12,7 @@
|
||||
[package]
|
||||
edition = "2015"
|
||||
name = "bit-vec"
|
||||
version = "0.7.0"
|
||||
version = "0.8.0"
|
||||
authors = ["Alexis Beingessner <a.beingessner@gmail.com>"]
|
||||
build = false
|
||||
autobins = false
|
||||
@@ -21,7 +21,7 @@ autotests = false
|
||||
autobenches = false
|
||||
description = "A vector of bits"
|
||||
homepage = "https://github.com/contain-rs/bit-vec"
|
||||
documentation = "https://contain-rs.github.io/bit-vec/bit_vec"
|
||||
documentation = "https://docs.rs/bit-vec/"
|
||||
readme = "README.md"
|
||||
keywords = [
|
||||
"data-structures",
|
||||
@@ -30,7 +30,7 @@ keywords = [
|
||||
"bitmap",
|
||||
"bit",
|
||||
]
|
||||
license = "MIT/Apache-2.0"
|
||||
license = "Apache-2.0 OR MIT"
|
||||
repository = "https://github.com/contain-rs/bit-vec"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
@@ -50,7 +50,7 @@ name = "bench"
|
||||
path = "benches/bench.rs"
|
||||
|
||||
[dependencies.borsh]
|
||||
version = "1.5.0"
|
||||
version = "1.5"
|
||||
features = ["derive"]
|
||||
optional = true
|
||||
default-features = false
|
||||
|
||||
18
third_party/rust/bit-vec/README.md
vendored
18
third_party/rust/bit-vec/README.md
vendored
@@ -20,15 +20,15 @@
|
||||
|
||||
[crates.io shield]: https://img.shields.io/crates/v/bit-vec?label=latest
|
||||
[crates.io link]: https://crates.io/crates/bit-vec
|
||||
[docs.rs badge]: https://docs.rs/bit-vec/badge.svg?version=0.7.0
|
||||
[docs.rs link]: https://docs.rs/bit-vec/0.7.0/bit_vec/
|
||||
[docs.rs badge]: https://docs.rs/bit-vec/badge.svg?version=0.8.0
|
||||
[docs.rs link]: https://docs.rs/bit-vec/0.8.0/bit_vec/
|
||||
[github ci badge]: https://github.com/contain-rs/linked-hash-map/workflows/Rust/badge.svg?branch=master
|
||||
[rustc 1.0+]: https://img.shields.io/badge/rustc-1.0%2B-blue.svg
|
||||
[serde_derive: rustc 1.31+]: https://img.shields.io/badge/serde_derive-rustc_1.31+-lightgray.svg
|
||||
[Rust 1.0]: https://blog.rust-lang.org/2015/05/15/Rust-1.0.html
|
||||
[Rust 1.31]: https://blog.rust-lang.org/2018/12/06/Rust-1.31-and-rust-2018.html
|
||||
[deps.rs status]: https://deps.rs/crate/bit-vec/0.7.0/status.svg
|
||||
[deps.rs link]: https://deps.rs/crate/bit-vec/0.7.0
|
||||
[deps.rs status]: https://deps.rs/crate/bit-vec/0.8.0/status.svg
|
||||
[deps.rs link]: https://deps.rs/crate/bit-vec/0.8.0
|
||||
[shields.io download count]: https://img.shields.io/crates/d/bit-vec.svg
|
||||
|
||||
## Usage
|
||||
@@ -37,7 +37,7 @@ Add this to your Cargo.toml:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
bit-vec = "0.6"
|
||||
bit-vec = "0.8"
|
||||
```
|
||||
|
||||
Since Rust 2018, `extern crate` is no longer mandatory. If your edition is old (Rust 2015),
|
||||
@@ -51,28 +51,28 @@ If you want [serde](https://github.com/serde-rs/serde) support, include the feat
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
bit-vec = { version = "0.6", features = ["serde"] }
|
||||
bit-vec = { version = "0.8", features = ["serde"] }
|
||||
```
|
||||
|
||||
If you want to use bit-vec in a program that has `#![no_std]`, just drop default features:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
bit-vec = { version = "0.6", default-features = false }
|
||||
bit-vec = { version = "0.8", default-features = false }
|
||||
```
|
||||
|
||||
If you want to use serde with the alloc crate instead of std, just use the `serde_no_std` feature:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
bit-vec = { version = "0.6", default-features = false, features = ["serde", "serde_no_std"] }
|
||||
bit-vec = { version = "0.8", default-features = false, features = ["serde", "serde_no_std"] }
|
||||
```
|
||||
|
||||
If you want [borsh-rs](https://github.com/near/borsh-rs) support, include it like this:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
bit-vec = { version = "0.6", features = ["borsh"] }
|
||||
bit-vec = { version = "0.8", features = ["borsh"] }
|
||||
```
|
||||
|
||||
Other available serialization libraries can be enabled with the
|
||||
|
||||
8
third_party/rust/bit-vec/RELEASES.md
vendored
Normal file
8
third_party/rust/bit-vec/RELEASES.md
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
Version 0.8.0 (2024-07-16)
|
||||
==========================
|
||||
|
||||
<a id="v0.8.0"></a>
|
||||
|
||||
- `fn insert` is implemented
|
||||
- `impl Display` is implemented
|
||||
- `impl Debug` has different output
|
||||
214
third_party/rust/bit-vec/src/lib.rs
vendored
214
third_party/rust/bit-vec/src/lib.rs
vendored
@@ -82,7 +82,7 @@
|
||||
//! assert_eq!(num_primes, 1_229);
|
||||
//! ```
|
||||
|
||||
#![doc(html_root_url = "https://docs.rs/bit-vec/0.6.3")]
|
||||
#![doc(html_root_url = "https://docs.rs/bit-vec/0.8.0")]
|
||||
#![no_std]
|
||||
|
||||
#[cfg(any(test, feature = "std"))]
|
||||
@@ -91,6 +91,8 @@ extern crate std;
|
||||
#[cfg(feature = "std")]
|
||||
use std::rc::Rc;
|
||||
#[cfg(feature = "std")]
|
||||
use std::string::String;
|
||||
#[cfg(feature = "std")]
|
||||
use std::vec::Vec;
|
||||
|
||||
#[cfg(feature = "serde")]
|
||||
@@ -112,12 +114,14 @@ extern crate alloc;
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::rc::Rc;
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::string::String;
|
||||
#[cfg(not(feature = "std"))]
|
||||
use alloc::vec::Vec;
|
||||
|
||||
use core::cell::RefCell;
|
||||
use core::cmp;
|
||||
use core::cmp::Ordering;
|
||||
use core::fmt;
|
||||
use core::fmt::{self, Write};
|
||||
use core::hash;
|
||||
use core::iter::repeat;
|
||||
use core::iter::FromIterator;
|
||||
@@ -447,19 +451,19 @@ impl<B: BitBlock> BitVec<B> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Exposes the raw block storage of this BitVec
|
||||
/// Exposes the raw block storage of this `BitVec`.
|
||||
///
|
||||
/// Only really intended for BitSet.
|
||||
/// Only really intended for `BitSet`.
|
||||
#[inline]
|
||||
pub fn storage(&self) -> &[B] {
|
||||
&self.storage
|
||||
}
|
||||
|
||||
/// Exposes the raw block storage of this BitVec
|
||||
/// Exposes the raw block storage of this `BitVec`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Can probably cause unsafety. Only really intended for BitSet.
|
||||
/// Can probably cause unsafety. Only really intended for `BitSet`.
|
||||
#[inline]
|
||||
pub unsafe fn storage_mut(&mut self) -> &mut Vec<B> {
|
||||
&mut self.storage
|
||||
@@ -1521,7 +1525,7 @@ impl<B: BitBlock> BitVec<B> {
|
||||
self.fix_last_block();
|
||||
}
|
||||
|
||||
/// Removes the last bit from the BitVec, and returns it. Returns None if the BitVec is empty.
|
||||
/// Removes the last bit from the `BitVec`, and returns it. Returns `None` if the `BitVec` is empty.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@@ -1581,11 +1585,11 @@ impl<B: BitBlock> BitVec<B> {
|
||||
self.nbits
|
||||
}
|
||||
|
||||
/// Sets the number of bits that this BitVec considers initialized.
|
||||
/// Sets the number of bits that this `BitVec` considers initialized.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// Almost certainly can cause bad stuff. Only really intended for BitSet.
|
||||
/// Almost certainly can cause bad stuff. Only really intended for `BitSet`.
|
||||
#[inline]
|
||||
pub unsafe fn set_len(&mut self, len: usize) {
|
||||
self.nbits = len;
|
||||
@@ -1615,6 +1619,61 @@ impl<B: BitBlock> BitVec<B> {
|
||||
pub fn shrink_to_fit(&mut self) {
|
||||
self.storage.shrink_to_fit();
|
||||
}
|
||||
|
||||
/// Inserts a given bit at index `at`, shifting all bits after by one
|
||||
///
|
||||
/// # Panics
|
||||
/// Panics if `at` is out of bounds for `BitVec`'s length (that is, if `at > BitVec::len()`)
|
||||
///
|
||||
/// # Examples
|
||||
///```
|
||||
/// use bit_vec::BitVec;
|
||||
///
|
||||
/// let mut b = BitVec::new();
|
||||
///
|
||||
/// b.push(true);
|
||||
/// b.push(true);
|
||||
/// b.insert(1, false);
|
||||
///
|
||||
/// assert!(b.eq_vec(&[true, false, true]));
|
||||
///```
|
||||
///
|
||||
/// # Time complexity
|
||||
/// Takes O([`len`]) time. All items after the insertion index must be
|
||||
/// shifted to the right. In the worst case, all elements are shifted when
|
||||
/// the insertion index is 0.
|
||||
///
|
||||
/// [`len`]: Self::len
|
||||
pub fn insert(&mut self, at: usize, bit: bool) {
|
||||
assert!(
|
||||
at <= self.nbits,
|
||||
"insertion index (is {at}) should be <= nbits (is {nbits})",
|
||||
nbits = self.nbits
|
||||
);
|
||||
|
||||
let last_block_bits = self.nbits % B::bits();
|
||||
let block_at = at / B::bits(); // needed block
|
||||
let bit_at = at % B::bits(); // index within the block
|
||||
|
||||
if last_block_bits == 0 {
|
||||
self.storage.push(B::zero());
|
||||
}
|
||||
|
||||
self.nbits += 1;
|
||||
|
||||
let mut carry = self.storage[block_at] >> (B::bits() - 1);
|
||||
let lsbits_mask = (B::one() << bit_at) - B::one();
|
||||
let set_bit = if bit { B::one() } else { B::zero() } << bit_at;
|
||||
self.storage[block_at] = (self.storage[block_at] & lsbits_mask)
|
||||
| ((self.storage[block_at] & !lsbits_mask) << 1)
|
||||
| set_bit;
|
||||
|
||||
for block_ref in &mut self.storage[block_at + 1..] {
|
||||
let curr_carry = *block_ref >> (B::bits() - 1);
|
||||
*block_ref = *block_ref << 1 | carry;
|
||||
carry = curr_carry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: BitBlock> Default for BitVec<B> {
|
||||
@@ -1695,16 +1754,33 @@ impl<B: BitBlock> Ord for BitVec<B> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: BitBlock> fmt::Debug for BitVec<B> {
|
||||
impl<B: BitBlock> fmt::Display for BitVec<B> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.ensure_invariant();
|
||||
for bit in self {
|
||||
write!(fmt, "{}", if bit { 1 } else { 0 })?;
|
||||
fmt.write_char(if bit { '1' } else { '0' })?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: BitBlock> fmt::Debug for BitVec<B> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.ensure_invariant();
|
||||
let mut storage = String::with_capacity(self.len() + self.len() / B::bits());
|
||||
for (i, bit) in self.iter().enumerate() {
|
||||
if i != 0 && i % B::bits() == 0 {
|
||||
storage.push(' ');
|
||||
}
|
||||
storage.push(if bit { '1' } else { '0' });
|
||||
}
|
||||
fmt.debug_struct("BitVec")
|
||||
.field("storage", &storage)
|
||||
.field("nbits", &self.nbits)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl<B: BitBlock> hash::Hash for BitVec<B> {
|
||||
#[inline]
|
||||
fn hash<H: hash::Hasher>(&self, state: &mut H) {
|
||||
@@ -1925,12 +2001,37 @@ mod tests {
|
||||
const U32_BITS: usize = 32;
|
||||
|
||||
#[test]
|
||||
fn test_to_str() {
|
||||
let zerolen = BitVec::new();
|
||||
assert_eq!(format!("{:?}", zerolen), "");
|
||||
fn test_display_output() {
|
||||
assert_eq!(format!("{}", BitVec::new()), "");
|
||||
assert_eq!(format!("{}", BitVec::from_elem(1, true)), "1");
|
||||
assert_eq!(format!("{}", BitVec::from_elem(8, false)), "00000000")
|
||||
}
|
||||
|
||||
let eightbits = BitVec::from_elem(8, false);
|
||||
assert_eq!(format!("{:?}", eightbits), "00000000")
|
||||
#[test]
|
||||
fn test_debug_output() {
|
||||
assert_eq!(
|
||||
format!("{:?}", BitVec::new()),
|
||||
"BitVec { storage: \"\", nbits: 0 }"
|
||||
);
|
||||
assert_eq!(
|
||||
format!("{:?}", BitVec::from_elem(1, true)),
|
||||
"BitVec { storage: \"1\", nbits: 1 }"
|
||||
);
|
||||
assert_eq!(
|
||||
format!("{:?}", BitVec::from_elem(8, false)),
|
||||
"BitVec { storage: \"00000000\", nbits: 8 }"
|
||||
);
|
||||
assert_eq!(
|
||||
format!("{:?}", BitVec::from_elem(33, true)),
|
||||
"BitVec { storage: \"11111111111111111111111111111111 1\", nbits: 33 }"
|
||||
);
|
||||
assert_eq!(
|
||||
format!(
|
||||
"{:?}",
|
||||
BitVec::from_bytes(&[0b111, 0b000, 0b1110, 0b0001, 0b11111111, 0b00000000])
|
||||
),
|
||||
"BitVec { storage: \"00000111000000000000111000000001 1111111100000000\", nbits: 48 }"
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -1956,7 +2057,7 @@ mod tests {
|
||||
let mut b = BitVec::from_elem(2, false);
|
||||
b.set(0, true);
|
||||
b.set(1, false);
|
||||
assert_eq!(format!("{:?}", b), "10");
|
||||
assert_eq!(format!("{}", b), "10");
|
||||
assert!(!b.none() && !b.all());
|
||||
}
|
||||
|
||||
@@ -2306,7 +2407,7 @@ mod tests {
|
||||
fn test_from_bytes() {
|
||||
let bit_vec = BitVec::from_bytes(&[0b10110110, 0b00000000, 0b11111111]);
|
||||
let str = concat!("10110110", "00000000", "11111111");
|
||||
assert_eq!(format!("{:?}", bit_vec), str);
|
||||
assert_eq!(format!("{}", bit_vec), str);
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -2325,7 +2426,7 @@ mod tests {
|
||||
fn test_from_bools() {
|
||||
let bools = [true, false, true, true];
|
||||
let bit_vec: BitVec = bools.iter().copied().collect();
|
||||
assert_eq!(format!("{:?}", bit_vec), "1011");
|
||||
assert_eq!(format!("{}", bit_vec), "1011");
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -3007,4 +3108,79 @@ mod tests {
|
||||
});
|
||||
assert!(a.eq_vec(&[false, true, false, true, false, true, false, true]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_insert_at_zero() {
|
||||
let mut v = BitVec::new();
|
||||
|
||||
v.insert(0, false);
|
||||
v.insert(0, true);
|
||||
v.insert(0, false);
|
||||
v.insert(0, true);
|
||||
v.insert(0, false);
|
||||
v.insert(0, true);
|
||||
|
||||
assert_eq!(v.len(), 6);
|
||||
assert_eq!(v.storage().len(), 1);
|
||||
assert!(v.eq_vec(&[true, false, true, false, true, false]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_insert_at_end() {
|
||||
let mut v = BitVec::new();
|
||||
|
||||
v.insert(v.len(), true);
|
||||
v.insert(v.len(), false);
|
||||
v.insert(v.len(), true);
|
||||
v.insert(v.len(), false);
|
||||
v.insert(v.len(), true);
|
||||
v.insert(v.len(), false);
|
||||
|
||||
assert_eq!(v.storage().len(), 1);
|
||||
assert_eq!(v.len(), 6);
|
||||
assert!(v.eq_vec(&[true, false, true, false, true, false]));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_insert_at_block_boundaries() {
|
||||
let mut v = BitVec::from_elem(32, false);
|
||||
|
||||
assert_eq!(v.storage().len(), 1);
|
||||
|
||||
v.insert(31, true);
|
||||
|
||||
assert_eq!(v.len(), 33);
|
||||
|
||||
assert!(matches!(v.get(31), Some(true)));
|
||||
assert!(v.eq_vec(&[
|
||||
false, false, false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, true, false
|
||||
]));
|
||||
|
||||
assert_eq!(v.storage().len(), 2);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_insert_at_block_boundaries_1() {
|
||||
let mut v = BitVec::from_elem(64, false);
|
||||
|
||||
assert_eq!(v.storage().len(), 2);
|
||||
|
||||
v.insert(63, true);
|
||||
|
||||
assert_eq!(v.len(), 65);
|
||||
|
||||
assert!(matches!(v.get(63), Some(true)));
|
||||
assert!(v.eq_vec(&[
|
||||
false, false, false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, false, false, false, false, false, false, false, false, false,
|
||||
false, false, false, true, false
|
||||
]));
|
||||
|
||||
assert_eq!(v.storage().len(), 3);
|
||||
}
|
||||
}
|
||||
|
||||
2
third_party/rust/d3d12/.cargo-checksum.json
vendored
2
third_party/rust/d3d12/.cargo-checksum.json
vendored
@@ -1 +1 @@
|
||||
{"files":{"CHANGELOG.md":"45fa76b0e5bc51721887147000e9e78a5934cb04d1ad628e501ef2082763d353","Cargo.toml":"9938addd7ce2c7785a9ca11eb0049271317f9b05fdf0d7330d4a80f0e07ab500","README.md":"76cee3209f773a62535de6c9724b53f158406359f35b4d48b17ac3747b6c102e","src/com.rs":"cfd6556a7abf38cba57559038f9f2cf86274418448fb2745436c251a99575e05","src/command_allocator.rs":"ef01059a661749470f3772d188fe0fab0f002e1d154facdab4b9b2932f4b2d93","src/command_list.rs":"8723f3b755b721e0dbb234bd604956c1b7922a2368231197495daa3fa6548e63","src/debug.rs":"aa33b98f7c3e71cba75fc42c6ca9af72d96b45122422c16e48525e24590c57bf","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":"b046b922f48e817fe252d9b2f859c036f54635779e84103ca53d1b2ca9c18e02","src/queue.rs":"bd32813d0b8a3bedf3223b69ade9f9c799a138a9e27d970f86435d9ce32d1557","src/resource.rs":"931c255c845eb621fc1b9e807b0effd92a2cd20e624c2beaa88506019a7a43a4","src/sync.rs":"5c287fb7498242a397eb1f08887be9cff9b48dc7cb13af5792cce5f7182b55f8"},"package":null}
|
||||
{"files":{"CHANGELOG.md":"45fa76b0e5bc51721887147000e9e78a5934cb04d1ad628e501ef2082763d353","Cargo.toml":"18e881193dc6cc4c61d3fe0c2938867da2801f93e650d2c7ee12d9d465edd909","README.md":"76cee3209f773a62535de6c9724b53f158406359f35b4d48b17ac3747b6c102e","src/com.rs":"cfd6556a7abf38cba57559038f9f2cf86274418448fb2745436c251a99575e05","src/command_allocator.rs":"ef01059a661749470f3772d188fe0fab0f002e1d154facdab4b9b2932f4b2d93","src/command_list.rs":"8723f3b755b721e0dbb234bd604956c1b7922a2368231197495daa3fa6548e63","src/debug.rs":"aa33b98f7c3e71cba75fc42c6ca9af72d96b45122422c16e48525e24590c57bf","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":"b046b922f48e817fe252d9b2f859c036f54635779e84103ca53d1b2ca9c18e02","src/queue.rs":"bd32813d0b8a3bedf3223b69ade9f9c799a138a9e27d970f86435d9ce32d1557","src/resource.rs":"931c255c845eb621fc1b9e807b0effd92a2cd20e624c2beaa88506019a7a43a4","src/sync.rs":"5c287fb7498242a397eb1f08887be9cff9b48dc7cb13af5792cce5f7182b55f8"},"package":null}
|
||||
2
third_party/rust/d3d12/Cargo.toml
vendored
2
third_party/rust/d3d12/Cargo.toml
vendored
@@ -12,7 +12,7 @@
|
||||
[package]
|
||||
edition = "2018"
|
||||
name = "d3d12"
|
||||
version = "0.20.0"
|
||||
version = "22.0.0"
|
||||
authors = ["gfx-rs developers"]
|
||||
description = "Low level D3D12 API wrapper"
|
||||
documentation = "https://docs.rs/d3d12"
|
||||
|
||||
@@ -1 +1 @@
|
||||
{"files":{"Cargo.lock":"7dffc5e93a0c3ff20a743e47d81da0baea4436153d5700be93805f3e0e982deb","Cargo.toml":"0b3005bccdea36f58aa260d17393d97fcdc2d80b86d39af2b7dd6828777524af","LICENSE-APACHE":"0178e21322b0e88aa3aeb3146f6a9611bc1f8df6d98bdfb34be28b9dd56a8107","LICENSE-MIT":"ad41be6cc6538b29b9346648f41432b5e460bad6be073b5eeaa41320ea2921dc","README.md":"0830d3914152fa9afa9ffe48651cbbbb31d34fe330785dee98ef747078a92079","examples/d3d12-buffer-winrs.rs":"c2c66ace6e41d302f244b95dbe38f2272ac59357a1c717a767dac3df89ea4718","examples/d3d12-buffer.rs":"abd9acc233a45c44f421dcaa4109f5a408de5335979654b1acbb55c73197ed5b","examples/metal-buffer.rs":"0fbd65a5a8381013199ff98f76c3830b96eb5e46591d4043f54614d582f26523","examples/vulkan-buffer.rs":"8097b361074302cf294d09a309e0cb8bfa8fbc586096f77a1cca9f7ba1f735dc","src/allocator/dedicated_block_allocator/mod.rs":"184ab11fcb52d3438586d10909277b54f1dbec9aeafb29ea338fd4df0e025e76","src/allocator/dedicated_block_allocator/visualizer.rs":"5b9019dd73ebe7bb9e9d103c48368014b73cdd4ae7f36a706ae047919f56fac6","src/allocator/free_list_allocator/mod.rs":"cab1d7e451c08978e67163ad45006cf8fdf2bdbb40e205c04bfec17490ca605f","src/allocator/free_list_allocator/visualizer.rs":"46214d07285d72a0a29c8d7e76322243853eba7d25d87ebfbb17c75e7815d07f","src/allocator/mod.rs":"09a560d3f4b0ba174bceea6d71bc201afcbea2b8170430c21365cbea8ca315f9","src/d3d12/mod.rs":"8fddd0755bd804cfcedf89c9a0a1f9686b6f0f728ff094cf3cb42a2ba12dc3d6","src/d3d12/visualizer.rs":"955c587a0d676e7e67fe02a3c3d4a59e8857e323c316ab7c352ef8d1a247193d","src/lib.rs":"4e19cd56ceaeb38f3fcaa71619c0fb180306cd79b25db583a05c8954b766c3da","src/metal/mod.rs":"5d156324aaaa054745054ae612056da5e854f18893756d86563b0f05ecd98bb2","src/result.rs":"6c7d85ee13afbd0b17c1b81ed0b6d7094247dd693444b62c28daf4d9f2248846","src/visualizer/allocation_reports.rs":"8e848f56503ee9b1a0b744804ac68a415dd5d761b20b0be0b15f9d4a5299607b","src/visualizer/memory_chunks.rs":"7d07c01f1471d25ff5702b53f5ccda09d6135888f6a77d1eaf06c541b4cafd5e","src/visualizer/mod.rs":"7d56c956abba968400aa6794e399db4b7ec10135a948beef21ea13ba3bd1fd9e","src/vulkan/mod.rs":"e14cfa043c938d9da3171bf9e9cbe7e4c0132e02c5c20af2726307ad40179491","src/vulkan/visualizer.rs":"7d6c113c70fa36f1a85a989d7020bd8e9814584f11c43bc151606be643a07c6c"},"package":"fdd4240fc91d3433d5e5b0fc5b67672d771850dc19bbee03c1381e19322803d7"}
|
||||
{"files":{"Cargo.lock":"3ca79349a9d9a4636c763d35a0caad53c655a13ff0612020ae8ec8fe3b42b4ff","Cargo.toml":"4d6d3bb1f8fe80fe67f31bf41d3469cc311e14daa295f42d0e7944b287b9f8d3","LICENSE-APACHE":"0178e21322b0e88aa3aeb3146f6a9611bc1f8df6d98bdfb34be28b9dd56a8107","LICENSE-MIT":"ad41be6cc6538b29b9346648f41432b5e460bad6be073b5eeaa41320ea2921dc","README.md":"d51d23364f3944098ca4b6118d46b5b353c2bfcd0cce0b3ade317537bdf69143","examples/d3d12-buffer-winrs.rs":"e7bb5565a26c1608ed57bcf5895e7e45bed5af85040f5a572049e6b74c99631c","examples/d3d12-buffer.rs":"c84cfdeae3a347fe561529b60963daaccc10880a9aeb64ae992689c30e16ea11","examples/metal-buffer.rs":"0fbd65a5a8381013199ff98f76c3830b96eb5e46591d4043f54614d582f26523","examples/vulkan-buffer.rs":"49f57f1f4542126047e217c81083b08ed798637fd90d6b7560bc9fab21732953","src/allocator/dedicated_block_allocator/mod.rs":"ec52728fb0c9d40173472640f8005ee7eca450170b7c3113adfd2e887e387f29","src/allocator/dedicated_block_allocator/visualizer.rs":"5b9019dd73ebe7bb9e9d103c48368014b73cdd4ae7f36a706ae047919f56fac6","src/allocator/free_list_allocator/mod.rs":"afe3417f40cdf71ec99c5885066d715e56d8d6c19662b17846cc8ce54222b1e2","src/allocator/free_list_allocator/visualizer.rs":"46214d07285d72a0a29c8d7e76322243853eba7d25d87ebfbb17c75e7815d07f","src/allocator/mod.rs":"86a95a58a30ec59aa7a9bc5822deca4c2a82c737e5633008400c2b291683a024","src/d3d12/mod.rs":"3cb8289c2effe1430c70cbb87b705fcaca7915d36b441f7d8a9a591bca18be25","src/d3d12/visualizer.rs":"41d1b5b897ff7b0a3fda359cee3f6b5c921617a4e1fefe7ddd2341bb1da87691","src/lib.rs":"36c8bf74f77da2113651e4e13d2bd9dbb7f6c854c089573461aaea8378c4d02c","src/metal/mod.rs":"f55592a96135da25785df21d8057fe5c1843b38f1a99d817cadba17d9d036ab7","src/result.rs":"6c7d85ee13afbd0b17c1b81ed0b6d7094247dd693444b62c28daf4d9f2248846","src/visualizer/allocation_reports.rs":"441a85fd68a8903fd9e1413756730e3e5cf9aa61803983e61f7cbca27ee39071","src/visualizer/memory_chunks.rs":"f521a4ce056d610d095c7fd65b110b8c046e84850746ec38b4d66f27b0ec70ae","src/visualizer/mod.rs":"7d56c956abba968400aa6794e399db4b7ec10135a948beef21ea13ba3bd1fd9e","src/vulkan/mod.rs":"e6dd3e67aea9f321e7c53bf87448a645bc83e3bbc92e6aef76223b18dd610fe5","src/vulkan/visualizer.rs":"6357703e89e3f5e9b78649eb16af907c107d0d121c23a4094dc0794a38fd4929"},"package":"c151a2a5ef800297b4e79efa4f4bec035c5f51d5ae587287c9b952bdf734cacd"}
|
||||
213
third_party/rust/gpu-allocator/Cargo.lock
generated
vendored
213
third_party/rust/gpu-allocator/Cargo.lock
generated
vendored
@@ -4,9 +4,9 @@ version = 3
|
||||
|
||||
[[package]]
|
||||
name = "ab_glyph"
|
||||
version = "0.2.25"
|
||||
version = "0.2.28"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f90148830dac590fac7ccfe78ec4a8ea404c60f75a24e16407a71f0f40de775"
|
||||
checksum = "79faae4620f45232f599d9bc7b290f88247a0834162c4495ab2f02d60004adfb"
|
||||
dependencies = [
|
||||
"ab_glyph_rasterizer",
|
||||
"owned_ttf_parser",
|
||||
@@ -52,18 +52,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ash"
|
||||
version = "0.37.3+1.3.251"
|
||||
version = "0.38.0+1.3.281"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39e9c3835d686b0a6084ab4234fcd1b07dbf6e4767dce60874b12356a25ecd4a"
|
||||
checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f"
|
||||
dependencies = [
|
||||
"libloading",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.2.0"
|
||||
version = "1.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
|
||||
checksum = "0c4b4d0bd25bd0b74681c0ad21497610ce1b7c91b1022cd21c80c6fbdd9476b0"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
@@ -73,9 +73,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.5.0"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
|
||||
checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de"
|
||||
|
||||
[[package]]
|
||||
name = "block"
|
||||
@@ -83,12 +83,6 @@ version = "0.1.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.96"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "065a29261d53ba54260972629f9ca6bffa69bac13cd1fed61420f7fa68b9f8bd"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
@@ -260,7 +254,7 @@ checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b"
|
||||
|
||||
[[package]]
|
||||
name = "gpu-allocator"
|
||||
version = "0.26.0"
|
||||
version = "0.27.0"
|
||||
dependencies = [
|
||||
"ash",
|
||||
"egui",
|
||||
@@ -299,18 +293,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.154"
|
||||
version = "0.2.155"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae743338b92ff9146ce83992f766a31066a91a8c84a45e0e9f21e7cf6de6d346"
|
||||
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
version = "0.7.4"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
|
||||
checksum = "e310b3a6b5907f99202fcdb4960ff45b93735d7c7d96b760fcff8db2dc0e103d"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"winapi",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -325,9 +319,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.21"
|
||||
version = "0.4.22"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
|
||||
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24"
|
||||
|
||||
[[package]]
|
||||
name = "malloc_buf"
|
||||
@@ -340,17 +334,17 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "memchr"
|
||||
version = "2.7.2"
|
||||
version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c8640c5d730cb13ebd907d8d04b52f55ac9a2eec55b440c8892f40d56c76c1d"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "metal"
|
||||
version = "0.27.0"
|
||||
version = "0.29.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c43f73953f8cbe511f021b58f18c3ce1c3d1ae13fe953293e13345bf83217f25"
|
||||
checksum = "7ecfd3296f8c56b7c1f6fbac3c71cefa9d78ce009850c45000015f206dc7fa21"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
"block",
|
||||
"core-graphics-types",
|
||||
"dispatch",
|
||||
@@ -373,16 +367,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
|
||||
dependencies = [
|
||||
"malloc_buf",
|
||||
"objc_exception",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "objc_exception"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad970fb455818ad6cba4c122ad012fae53ae8b4795f86378bce65e4f6bab2ca4"
|
||||
dependencies = [
|
||||
"cc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -393,18 +377,18 @@ checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92"
|
||||
|
||||
[[package]]
|
||||
name = "owned_ttf_parser"
|
||||
version = "0.20.0"
|
||||
version = "0.24.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d4586edfe4c648c71797a74c84bacb32b52b212eff5dfe2bb9f2c599844023e7"
|
||||
checksum = "490d3a563d3122bf7c911a59b0add9389e5ec0f5f0c3ac6b91ff235a0e6a7f90"
|
||||
dependencies = [
|
||||
"ttf-parser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "parking_lot"
|
||||
version = "0.12.2"
|
||||
version = "0.12.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e4af0ca4f6caed20e900d564c242b8e5d4903fdacf31d3daf527b66fe6f42fb"
|
||||
checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27"
|
||||
dependencies = [
|
||||
"lock_api",
|
||||
"parking_lot_core",
|
||||
@@ -425,9 +409,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "paste"
|
||||
version = "1.0.14"
|
||||
version = "1.0.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c"
|
||||
checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a"
|
||||
|
||||
[[package]]
|
||||
name = "presser"
|
||||
@@ -437,9 +421,9 @@ checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa"
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.81"
|
||||
version = "1.0.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"
|
||||
checksum = "5e719e8df665df0d1c8fbfd238015744736151d4445ec0836b8e628aae103b77"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
@@ -455,18 +439,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.1"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "469052894dcb553421e483e4209ee581a45100d31b4018de03e5a7ad86374a7e"
|
||||
checksum = "2a908a6e00f1fdd0dfd9c0eb08ce85126f6d8bbda50017e74bc4a4b7d4a926a4"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.6.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "regex"
|
||||
version = "1.10.4"
|
||||
version = "1.10.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c117dbdfde9c8308975b6a18d71f3f385c89461f7b3fb054288ecf2a2058ba4c"
|
||||
checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
@@ -476,9 +460,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.6"
|
||||
version = "0.4.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86b83b8b9847f9bf95ef68afb0b8e6cdb80f498442f5179a29fad448fcc1eaea"
|
||||
checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
@@ -487,9 +471,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "regex-syntax"
|
||||
version = "0.8.3"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "adad44e29e4c806119491a7f06f03de4d1af22c3a680dd47f1e6e179439d1f56"
|
||||
checksum = "7a66a03ae7c801facd77a29370b4faec201768915ac14a721ba36f20bc9c209b"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
@@ -499,18 +483,18 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.199"
|
||||
version = "1.0.204"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0c9f6e76df036c77cd94996771fb40db98187f096dd0b9af39c6c6e452ba966a"
|
||||
checksum = "bc76f558e0cbb2a839d37354c575f1dc3fdc6546b5be373ba43d95f231bf7c12"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.199"
|
||||
version = "1.0.204"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "11bd257a6541e141e42ca6d24ae26f7714887b47e89aa739099104c7e4d3b7fc"
|
||||
checksum = "e0cd7e117be63d3c3678776753929474f3b04a43a080c744d6b0ae2a8c28e222"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -525,9 +509,9 @@ checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.60"
|
||||
version = "2.0.71"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3"
|
||||
checksum = "b146dcf730474b4bcd16c311627b31ede9ab149045db4d6088b3becaea046462"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -545,18 +529,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.59"
|
||||
version = "1.0.62"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f0126ad08bff79f29fc3ae6a55cc72352056dfff61e3ff8bb7129476d44b23aa"
|
||||
checksum = "f2675633b1499176c2dff06b0856a27976a8f9d436737b4cf4f312d4d91d8bbb"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.59"
|
||||
version = "1.0.62"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d1cd413b5d558b4c5bf3680e324a6fa5014e7b7c067a51e69dbdf47eb7148b66"
|
||||
checksum = "d20468752b09f49e909e55a5d338caa8bedf615594e9d80bc4c565d30faf798c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -565,9 +549,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "ttf-parser"
|
||||
version = "0.20.0"
|
||||
version = "0.24.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "17f77d76d837a7830fe1d4f12b7b4ba4192c1888001c7164257e4bc6d21d96b4"
|
||||
checksum = "8686b91785aff82828ed725225925b33b4fde44c4bb15876e5f7c832724c420a"
|
||||
|
||||
[[package]]
|
||||
name = "unicode-ident"
|
||||
@@ -614,9 +598,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||
|
||||
[[package]]
|
||||
name = "windows"
|
||||
version = "0.52.0"
|
||||
version = "0.58.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be"
|
||||
checksum = "dd04d41d93c4992d421894c18c8b43496aa748dd4c081bac0dc93eb0489272b6"
|
||||
dependencies = [
|
||||
"windows-core",
|
||||
"windows-targets",
|
||||
@@ -624,10 +608,55 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows-core"
|
||||
version = "0.52.0"
|
||||
version = "0.58.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "33ab640c8d7e35bf8ba19b884ba838ceb4fba93a4e8c65a9059d08afcfc683d9"
|
||||
checksum = "6ba6d44ec8c2591c134257ce647b7ea6b20335bf6379a27dac5f1641fcf59f99"
|
||||
dependencies = [
|
||||
"windows-implement",
|
||||
"windows-interface",
|
||||
"windows-result",
|
||||
"windows-strings",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-implement"
|
||||
version = "0.58.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2bbd5b46c938e506ecbce286b6628a02171d56153ba733b6c741fc627ec9579b"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-interface"
|
||||
version = "0.58.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "053c4c462dc91d3b1504c6fe5a726dd15e216ba718e84a0e46a88fbe5ded3515"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-result"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d1043d8214f791817bab27572aaa8af63732e11bf84aa21a45a78d6c317ae0e"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-strings"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10"
|
||||
dependencies = [
|
||||
"windows-result",
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
@@ -642,9 +671,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.5"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
|
||||
checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
@@ -658,66 +687,66 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.5"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
|
||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.5"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
|
||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.5"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
|
||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.5"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
|
||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.5"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
|
||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.5"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
|
||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.5"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
|
||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.5"
|
||||
version = "0.52.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
|
||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
version = "0.7.32"
|
||||
version = "0.7.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be"
|
||||
checksum = "1b9b4fd18abc82b8136838da5d50bae7bdea537c574d8dc1a34ed098d6c166f0"
|
||||
dependencies = [
|
||||
"zerocopy-derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy-derive"
|
||||
version = "0.7.32"
|
||||
version = "0.7.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
|
||||
checksum = "fa4f8080344d4671fb4e831a13ad1e68092748387dfc4f55e356242fae12ce3e"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
||||
21
third_party/rust/gpu-allocator/Cargo.toml
vendored
21
third_party/rust/gpu-allocator/Cargo.toml
vendored
@@ -11,9 +11,9 @@
|
||||
|
||||
[package]
|
||||
edition = "2021"
|
||||
rust-version = "1.65"
|
||||
rust-version = "1.70"
|
||||
name = "gpu-allocator"
|
||||
version = "0.26.0"
|
||||
version = "0.27.0"
|
||||
authors = ["Traverse Research <opensource@traverseresearch.nl>"]
|
||||
include = [
|
||||
"/README.md",
|
||||
@@ -63,7 +63,7 @@ name = "metal-buffer"
|
||||
required-features = ["metal"]
|
||||
|
||||
[dependencies.ash]
|
||||
version = ">=0.34, <=0.37"
|
||||
version = "0.38"
|
||||
features = ["debug"]
|
||||
optional = true
|
||||
default-features = false
|
||||
@@ -88,7 +88,7 @@ version = "0.3"
|
||||
version = "1.0"
|
||||
|
||||
[dev-dependencies.ash]
|
||||
version = ">=0.34,<=0.37"
|
||||
version = "0.38"
|
||||
features = [
|
||||
"debug",
|
||||
"loaded",
|
||||
@@ -113,7 +113,7 @@ visualizer = [
|
||||
vulkan = ["dep:ash"]
|
||||
|
||||
[target."cfg(any(target_os = \"macos\", target_os = \"ios\"))".dependencies.metal]
|
||||
version = "0.27.0"
|
||||
version = "0.29.0"
|
||||
features = [
|
||||
"link",
|
||||
"dispatch",
|
||||
@@ -132,13 +132,9 @@ features = [
|
||||
optional = true
|
||||
|
||||
[target."cfg(windows)".dependencies.windows]
|
||||
version = ">=0.51,<=0.52"
|
||||
version = ">=0.53,<=0.58"
|
||||
features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_Graphics",
|
||||
"Win32_Graphics_Direct3D",
|
||||
"Win32_Graphics_Direct3D12",
|
||||
"Win32_Graphics_Dxgi",
|
||||
"Win32_Graphics_Dxgi_Common",
|
||||
]
|
||||
optional = true
|
||||
@@ -158,12 +154,9 @@ features = [
|
||||
]
|
||||
|
||||
[target."cfg(windows)".dev-dependencies.windows]
|
||||
version = ">=0.51,<=0.52"
|
||||
version = "0.58"
|
||||
features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_Graphics",
|
||||
"Win32_Graphics_Direct3D",
|
||||
"Win32_Graphics_Direct3D12",
|
||||
"Win32_Graphics_Dxgi",
|
||||
"Win32_Graphics_Dxgi_Common",
|
||||
]
|
||||
|
||||
8
third_party/rust/gpu-allocator/README.md
vendored
8
third_party/rust/gpu-allocator/README.md
vendored
@@ -6,13 +6,13 @@
|
||||
[](LICENSE-MIT)
|
||||
[](LICENSE-APACHE)
|
||||
[](../main/CODE_OF_CONDUCT.md)
|
||||
[](https://blog.rust-lang.org/2022/11/03/Rust-1.65.0.html)
|
||||
[](https://blog.rust-lang.org/2023/06/01/Rust-1.70.0.html)
|
||||
|
||||
[](https://traverseresearch.nl)
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
gpu-allocator = "0.26.0"
|
||||
gpu-allocator = "0.27.0"
|
||||
```
|
||||
|
||||

|
||||
@@ -48,7 +48,7 @@ use gpu_allocator::vulkan::*;
|
||||
use gpu_allocator::MemoryLocation;
|
||||
|
||||
// Setup vulkan info
|
||||
let vk_info = vk::BufferCreateInfo::builder()
|
||||
let vk_info = vk::BufferCreateInfo::default()
|
||||
.size(512)
|
||||
.usage(vk::BufferUsageFlags::STORAGE_BUFFER);
|
||||
|
||||
@@ -163,7 +163,7 @@ allocator.free(&allocation).unwrap();
|
||||
|
||||
## Minimum Supported Rust Version
|
||||
|
||||
The MSRV for this crate and the `vulkan`, `d3d12` and `metal` features is Rust 1.65. Any other features such as the `visualizer` (with all the `egui` dependencies) may have a higher requirement and are not tested in our CI.
|
||||
The MSRV for this crate and the `vulkan`, `d3d12` and `metal` features is Rust 1.70. Any other features such as the `visualizer` (with all the `egui` dependencies) may have a higher requirement and are not tested in our CI.
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -1,24 +1,28 @@
|
||||
//! Example showcasing [`gpu-allocator`] with types and functions from the [`windows`] crate.
|
||||
use gpu_allocator::d3d12::{
|
||||
AllocationCreateDesc, Allocator, AllocatorCreateDesc, ID3D12DeviceVersion, ResourceCategory,
|
||||
use gpu_allocator::{
|
||||
d3d12::{
|
||||
AllocationCreateDesc, Allocator, AllocatorCreateDesc, ID3D12DeviceVersion, ResourceCategory,
|
||||
},
|
||||
MemoryLocation,
|
||||
};
|
||||
use gpu_allocator::MemoryLocation;
|
||||
use log::*;
|
||||
use windows::core::{ComInterface, Result};
|
||||
use windows::Win32::{
|
||||
Foundation::E_NOINTERFACE,
|
||||
Graphics::{
|
||||
Direct3D::{D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_12_0},
|
||||
Direct3D12::{
|
||||
D3D12CreateDevice, ID3D12Device, ID3D12Resource,
|
||||
D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT, D3D12_RESOURCE_DESC,
|
||||
D3D12_RESOURCE_DIMENSION_BUFFER, D3D12_RESOURCE_FLAG_NONE, D3D12_RESOURCE_STATE_COMMON,
|
||||
D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
|
||||
},
|
||||
Dxgi::{
|
||||
Common::{DXGI_FORMAT_UNKNOWN, DXGI_SAMPLE_DESC},
|
||||
CreateDXGIFactory2, IDXGIAdapter4, IDXGIFactory6, DXGI_ADAPTER_FLAG3_SOFTWARE,
|
||||
DXGI_ERROR_NOT_FOUND,
|
||||
use windows::{
|
||||
core::{Interface, Result},
|
||||
Win32::{
|
||||
Foundation::E_NOINTERFACE,
|
||||
Graphics::{
|
||||
Direct3D::{D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_11_1, D3D_FEATURE_LEVEL_12_0},
|
||||
Direct3D12::{
|
||||
D3D12CreateDevice, ID3D12Device, ID3D12Resource,
|
||||
D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT, D3D12_RESOURCE_DESC,
|
||||
D3D12_RESOURCE_DIMENSION_BUFFER, D3D12_RESOURCE_FLAG_NONE,
|
||||
D3D12_RESOURCE_STATE_COMMON, D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
|
||||
},
|
||||
Dxgi::{
|
||||
Common::{DXGI_FORMAT_UNKNOWN, DXGI_SAMPLE_DESC},
|
||||
CreateDXGIFactory2, IDXGIAdapter4, IDXGIFactory6, DXGI_ADAPTER_FLAG3_SOFTWARE,
|
||||
DXGI_ERROR_NOT_FOUND,
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -33,8 +37,7 @@ fn create_d3d12_device(dxgi_factory: &IDXGIFactory6) -> Option<ID3D12Device> {
|
||||
};
|
||||
let adapter4: IDXGIAdapter4 = adapter1.cast().unwrap();
|
||||
|
||||
let mut desc = Default::default();
|
||||
unsafe { adapter4.GetDesc3(&mut desc) }.unwrap();
|
||||
let desc = unsafe { adapter4.GetDesc3() }.unwrap();
|
||||
// Skip software adapters
|
||||
// Vote for https://github.com/microsoft/windows-rs/issues/793!
|
||||
if (desc.Flags & DXGI_ADAPTER_FLAG3_SOFTWARE) == DXGI_ADAPTER_FLAG3_SOFTWARE {
|
||||
@@ -82,7 +85,9 @@ fn create_d3d12_device(dxgi_factory: &IDXGIFactory6) -> Option<ID3D12Device> {
|
||||
fn main() -> Result<()> {
|
||||
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("trace")).init();
|
||||
|
||||
let dxgi_factory = unsafe { CreateDXGIFactory2(0) }?;
|
||||
let dxgi_factory = unsafe {
|
||||
CreateDXGIFactory2(windows::Win32::Graphics::Dxgi::DXGI_CREATE_FACTORY_FLAGS::default())
|
||||
}?;
|
||||
|
||||
let device = create_d3d12_device(&dxgi_factory).expect("Failed to create D3D12 device.");
|
||||
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
//! Example showcasing [`winapi`] interop with [`gpu-allocator`] which is driven by the [`windows`] crate.
|
||||
use winapi::shared::{dxgiformat, winerror};
|
||||
use winapi::um::{d3d12, d3dcommon};
|
||||
use winapi::Interface;
|
||||
use winapi::{
|
||||
shared::{dxgiformat, winerror},
|
||||
um::{d3d12, d3dcommon},
|
||||
Interface,
|
||||
};
|
||||
|
||||
mod all_dxgi {
|
||||
pub use winapi::shared::{dxgi1_3::*, dxgi1_6::*, dxgitype::*};
|
||||
}
|
||||
|
||||
use log::*;
|
||||
|
||||
use gpu_allocator::d3d12::{
|
||||
AllocationCreateDesc, Allocator, AllocatorCreateDesc, ID3D12DeviceVersion, ResourceCategory,
|
||||
ToWinapi, ToWindows,
|
||||
use gpu_allocator::{
|
||||
d3d12::{
|
||||
AllocationCreateDesc, Allocator, AllocatorCreateDesc, ID3D12DeviceVersion,
|
||||
ResourceCategory, ToWinapi, ToWindows,
|
||||
},
|
||||
MemoryLocation,
|
||||
};
|
||||
use gpu_allocator::MemoryLocation;
|
||||
use log::*;
|
||||
|
||||
fn create_d3d12_device(
|
||||
dxgi_factory: *mut all_dxgi::IDXGIFactory6,
|
||||
@@ -68,11 +71,11 @@ fn create_d3d12_device(
|
||||
)
|
||||
};
|
||||
match hr {
|
||||
winapi::shared::winerror::S_OK => {
|
||||
winerror::S_OK => {
|
||||
info!("Using D3D12 feature level: {}.", feature_level_name);
|
||||
Some(device)
|
||||
}
|
||||
winapi::shared::winerror::E_NOINTERFACE => {
|
||||
winerror::E_NOINTERFACE => {
|
||||
error!("ID3D12Device interface not supported.");
|
||||
None
|
||||
}
|
||||
@@ -106,11 +109,7 @@ fn main() {
|
||||
)
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
hr,
|
||||
winapi::shared::winerror::S_OK,
|
||||
"Failed to create DXGI factory",
|
||||
);
|
||||
assert_eq!(hr, winerror::S_OK, "Failed to create DXGI factory");
|
||||
dxgi_factory
|
||||
};
|
||||
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
use std::default::Default;
|
||||
use std::ffi::CStr;
|
||||
|
||||
use ash::vk;
|
||||
use log::info;
|
||||
|
||||
use gpu_allocator::vulkan::{
|
||||
AllocationCreateDesc, AllocationScheme, Allocator, AllocatorCreateDesc,
|
||||
use gpu_allocator::{
|
||||
vulkan::{AllocationCreateDesc, AllocationScheme, Allocator, AllocatorCreateDesc},
|
||||
MemoryLocation,
|
||||
};
|
||||
use gpu_allocator::MemoryLocation;
|
||||
use log::info;
|
||||
|
||||
fn main() {
|
||||
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("trace")).init();
|
||||
@@ -16,20 +14,18 @@ fn main() {
|
||||
|
||||
// Create Vulkan instance
|
||||
let instance = {
|
||||
let app_name = CStr::from_bytes_with_nul(b"Vulkan gpu-allocator test\0").unwrap();
|
||||
let app_name = c"Vulkan gpu-allocator test";
|
||||
|
||||
let appinfo = vk::ApplicationInfo::builder()
|
||||
let appinfo = vk::ApplicationInfo::default()
|
||||
.application_name(app_name)
|
||||
.application_version(0)
|
||||
.engine_name(app_name)
|
||||
.engine_version(0)
|
||||
.api_version(vk::make_api_version(0, 1, 0, 0));
|
||||
|
||||
let layer_names_raw = [CStr::from_bytes_with_nul(b"VK_LAYER_KHRONOS_validation\0")
|
||||
.unwrap()
|
||||
.as_ptr()];
|
||||
let layer_names_raw = [c"VK_LAYER_KHRONOS_validation".as_ptr()];
|
||||
|
||||
let create_info = vk::InstanceCreateInfo::builder()
|
||||
let create_info = vk::InstanceCreateInfo::default()
|
||||
.application_info(&appinfo)
|
||||
.enabled_layer_names(&layer_names_raw);
|
||||
|
||||
@@ -74,11 +70,11 @@ fn main() {
|
||||
};
|
||||
let priorities = [1.0];
|
||||
|
||||
let queue_info = vk::DeviceQueueCreateInfo::builder()
|
||||
let queue_info = vk::DeviceQueueCreateInfo::default()
|
||||
.queue_family_index(queue_family_index as u32)
|
||||
.queue_priorities(&priorities);
|
||||
|
||||
let create_info = vk::DeviceCreateInfo::builder()
|
||||
let create_info = vk::DeviceCreateInfo::default()
|
||||
.queue_create_infos(std::slice::from_ref(&queue_info))
|
||||
.enabled_extension_names(&device_extension_names_raw)
|
||||
.enabled_features(&features);
|
||||
@@ -99,7 +95,7 @@ fn main() {
|
||||
|
||||
// Test allocating Gpu Only memory
|
||||
{
|
||||
let test_buffer_info = vk::BufferCreateInfo::builder()
|
||||
let test_buffer_info = vk::BufferCreateInfo::default()
|
||||
.size(512)
|
||||
.usage(vk::BufferUsageFlags::STORAGE_BUFFER)
|
||||
.sharing_mode(vk::SharingMode::EXCLUSIVE);
|
||||
@@ -132,7 +128,7 @@ fn main() {
|
||||
|
||||
// Test allocating Cpu to Gpu memory
|
||||
{
|
||||
let test_buffer_info = vk::BufferCreateInfo::builder()
|
||||
let test_buffer_info = vk::BufferCreateInfo::default()
|
||||
.size(512)
|
||||
.usage(vk::BufferUsageFlags::STORAGE_BUFFER)
|
||||
.sharing_mode(vk::SharingMode::EXCLUSIVE);
|
||||
@@ -165,7 +161,7 @@ fn main() {
|
||||
|
||||
// Test allocating Gpu to Cpu memory
|
||||
{
|
||||
let test_buffer_info = vk::BufferCreateInfo::builder()
|
||||
let test_buffer_info = vk::BufferCreateInfo::default()
|
||||
.size(512)
|
||||
.usage(vk::BufferUsageFlags::STORAGE_BUFFER)
|
||||
.sharing_mode(vk::SharingMode::EXCLUSIVE);
|
||||
|
||||
@@ -116,16 +116,13 @@ impl SubAllocator for DedicatedBlockAllocator {
|
||||
.name
|
||||
.clone()
|
||||
.unwrap_or_else(|| "<Unnamed Dedicated allocation>".to_owned()),
|
||||
offset: 0,
|
||||
size: self.size,
|
||||
#[cfg(feature = "visualizer")]
|
||||
backtrace: self.backtrace.clone(),
|
||||
}]
|
||||
}
|
||||
|
||||
fn size(&self) -> u64 {
|
||||
self.size
|
||||
}
|
||||
|
||||
fn allocated(&self) -> u64 {
|
||||
self.allocated
|
||||
}
|
||||
|
||||
@@ -398,6 +398,7 @@ impl SubAllocator for FreeListAllocator {
|
||||
.name
|
||||
.clone()
|
||||
.unwrap_or_else(|| "<Unnamed FreeList allocation>".to_owned()),
|
||||
offset: chunk.offset,
|
||||
size: chunk.size,
|
||||
#[cfg(feature = "visualizer")]
|
||||
backtrace: chunk.backtrace.clone(),
|
||||
@@ -405,10 +406,6 @@ impl SubAllocator for FreeListAllocator {
|
||||
.collect::<Vec<_>>()
|
||||
}
|
||||
|
||||
fn size(&self) -> u64 {
|
||||
self.size
|
||||
}
|
||||
|
||||
fn allocated(&self) -> u64 {
|
||||
self.allocated
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::{backtrace::Backtrace, sync::Arc};
|
||||
use std::{backtrace::Backtrace, fmt, ops::Range, sync::Arc};
|
||||
|
||||
use log::*;
|
||||
|
||||
@@ -29,20 +29,83 @@ impl AllocationType {
|
||||
}
|
||||
}
|
||||
|
||||
/// Describes an allocation in the [`AllocatorReport`].
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct AllocationReport {
|
||||
pub(crate) name: String,
|
||||
pub(crate) size: u64,
|
||||
pub struct AllocationReport {
|
||||
/// The name provided to the `allocate()` function.
|
||||
pub name: String,
|
||||
/// The offset in bytes of the allocation in its memory block.
|
||||
pub offset: u64,
|
||||
/// The size in bytes of the allocation.
|
||||
pub size: u64,
|
||||
#[cfg(feature = "visualizer")]
|
||||
pub(crate) backtrace: Arc<Backtrace>,
|
||||
}
|
||||
|
||||
/// Describes a memory block in the [`AllocatorReport`].
|
||||
#[derive(Clone)]
|
||||
pub struct MemoryBlockReport {
|
||||
/// The size in bytes of this memory block.
|
||||
pub size: u64,
|
||||
/// The range of allocations in [`AllocatorReport::allocations`] that are associated
|
||||
/// to this memory block.
|
||||
pub allocations: Range<usize>,
|
||||
}
|
||||
|
||||
/// A report that can be generated for informational purposes using `Allocator::generate_report()`.
|
||||
#[derive(Clone)]
|
||||
pub struct AllocatorReport {
|
||||
/// All live allocations, sub-allocated from memory blocks.
|
||||
pub allocations: Vec<AllocationReport>,
|
||||
/// All memory blocks.
|
||||
pub blocks: Vec<MemoryBlockReport>,
|
||||
/// Sum of the memory used by all allocations, in bytes.
|
||||
pub total_allocated_bytes: u64,
|
||||
/// Sum of the memory reserved by all memory blocks including unallocated regions, in bytes.
|
||||
pub total_reserved_bytes: u64,
|
||||
}
|
||||
|
||||
impl fmt::Debug for AllocationReport {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let name = if !self.name.is_empty() {
|
||||
self.name.as_str()
|
||||
} else {
|
||||
"--"
|
||||
};
|
||||
write!(f, "{name:?}: {}", fmt_bytes(self.size))
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for AllocatorReport {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut allocations = self.allocations.clone();
|
||||
allocations.sort_by_key(|alloc| std::cmp::Reverse(alloc.size));
|
||||
|
||||
let max_num_allocations_to_print = f.precision().unwrap_or(usize::MAX);
|
||||
allocations.truncate(max_num_allocations_to_print);
|
||||
|
||||
f.debug_struct("AllocatorReport")
|
||||
.field(
|
||||
"summary",
|
||||
&std::format_args!(
|
||||
"{} / {}",
|
||||
fmt_bytes(self.total_allocated_bytes),
|
||||
fmt_bytes(self.total_reserved_bytes)
|
||||
),
|
||||
)
|
||||
.field("blocks", &self.blocks.len())
|
||||
.field("allocations", &self.allocations.len())
|
||||
.field("largest", &allocations.as_slice())
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "visualizer")]
|
||||
pub(crate) trait SubAllocatorBase: crate::visualizer::SubAllocatorVisualizer {}
|
||||
#[cfg(not(feature = "visualizer"))]
|
||||
pub(crate) trait SubAllocatorBase {}
|
||||
|
||||
pub(crate) trait SubAllocator: SubAllocatorBase + std::fmt::Debug + Sync + Send {
|
||||
pub(crate) trait SubAllocator: SubAllocatorBase + fmt::Debug + Sync + Send {
|
||||
fn allocate(
|
||||
&mut self,
|
||||
size: u64,
|
||||
@@ -73,16 +136,8 @@ pub(crate) trait SubAllocator: SubAllocatorBase + std::fmt::Debug + Sync + Send
|
||||
#[must_use]
|
||||
fn supports_general_allocations(&self) -> bool;
|
||||
#[must_use]
|
||||
fn size(&self) -> u64;
|
||||
#[must_use]
|
||||
fn allocated(&self) -> u64;
|
||||
|
||||
/// Helper function: reports how much memory is available in this suballocator
|
||||
#[must_use]
|
||||
fn available_memory(&self) -> u64 {
|
||||
self.size() - self.allocated()
|
||||
}
|
||||
|
||||
/// Helper function: reports if the suballocator is empty (meaning, having no allocations).
|
||||
#[must_use]
|
||||
fn is_empty(&self) -> bool {
|
||||
@@ -90,8 +145,6 @@ pub(crate) trait SubAllocator: SubAllocatorBase + std::fmt::Debug + Sync + Send
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) const VISUALIZER_TABLE_MAX_ENTRY_NAME_LEN: usize = 40;
|
||||
|
||||
pub(crate) fn fmt_bytes(mut amount: u64) -> String {
|
||||
const SUFFIX: [&str; 5] = ["B", "KB", "MB", "GB", "TB"];
|
||||
|
||||
|
||||
103
third_party/rust/gpu-allocator/src/d3d12/mod.rs
vendored
103
third_party/rust/gpu-allocator/src/d3d12/mod.rs
vendored
@@ -1,9 +1,6 @@
|
||||
#![deny(clippy::unimplemented, clippy::unwrap_used, clippy::ok_expect)]
|
||||
|
||||
use std::{backtrace::Backtrace, fmt, sync::Arc};
|
||||
|
||||
use log::{debug, warn, Level};
|
||||
|
||||
use windows::Win32::{
|
||||
Foundation::E_OUTOFMEMORY,
|
||||
Graphics::{Direct3D12::*, Dxgi::Common::DXGI_FORMAT},
|
||||
@@ -11,9 +8,10 @@ use windows::Win32::{
|
||||
|
||||
#[cfg(feature = "public-winapi")]
|
||||
mod public_winapi {
|
||||
use super::*;
|
||||
pub use winapi::um::d3d12 as winapi_d3d12;
|
||||
|
||||
use super::*;
|
||||
|
||||
/// Trait similar to [`AsRef`]/[`AsMut`],
|
||||
pub trait ToWinapi<T> {
|
||||
fn as_winapi(&self) -> *const T;
|
||||
@@ -84,12 +82,10 @@ mod visualizer;
|
||||
#[cfg(feature = "visualizer")]
|
||||
pub use visualizer::AllocatorVisualizer;
|
||||
|
||||
use super::allocator;
|
||||
use super::allocator::AllocationType;
|
||||
|
||||
use super::{allocator, allocator::AllocationType};
|
||||
use crate::{
|
||||
allocator::fmt_bytes, AllocationError, AllocationSizes, AllocatorDebugSettings, MemoryLocation,
|
||||
Result,
|
||||
allocator::{AllocatorReport, MemoryBlockReport},
|
||||
AllocationError, AllocationSizes, AllocatorDebugSettings, MemoryLocation, Result,
|
||||
};
|
||||
|
||||
/// [`ResourceCategory`] is used for supporting [`D3D12_RESOURCE_HEAP_TIER_1`].
|
||||
@@ -197,10 +193,12 @@ impl<'a> AllocationCreateDesc<'a> {
|
||||
desc: &winapi_d3d12::D3D12_RESOURCE_DESC,
|
||||
name: &'a str,
|
||||
location: MemoryLocation,
|
||||
) -> AllocationCreateDesc<'a> {
|
||||
) -> Self {
|
||||
let device = device.as_windows();
|
||||
// Raw structs are binary-compatible
|
||||
let desc = unsafe { std::mem::transmute(desc) };
|
||||
let desc = unsafe {
|
||||
std::mem::transmute::<&winapi_d3d12::D3D12_RESOURCE_DESC, &D3D12_RESOURCE_DESC>(desc)
|
||||
};
|
||||
let allocation_info =
|
||||
unsafe { device.GetResourceAllocationInfo(0, std::slice::from_ref(desc)) };
|
||||
let resource_category: ResourceCategory = desc.into();
|
||||
@@ -223,7 +221,7 @@ impl<'a> AllocationCreateDesc<'a> {
|
||||
desc: &D3D12_RESOURCE_DESC,
|
||||
name: &'a str,
|
||||
location: MemoryLocation,
|
||||
) -> AllocationCreateDesc<'a> {
|
||||
) -> Self {
|
||||
let allocation_info =
|
||||
unsafe { device.GetResourceAllocationInfo(0, std::slice::from_ref(desc)) };
|
||||
let resource_category: ResourceCategory = desc.into();
|
||||
@@ -256,9 +254,8 @@ impl std::ops::Deref for ID3D12DeviceVersion {
|
||||
fn deref(&self) -> &Self::Target {
|
||||
match self {
|
||||
Self::Device(device) => device,
|
||||
// Windows-rs hides CanInto, we know that Device10/Device12 is a subclass of Device but there's not even a Deref.
|
||||
Self::Device10(device10) => windows::core::CanInto::can_into(device10),
|
||||
Self::Device12(device12) => windows::core::CanInto::can_into(device12),
|
||||
Self::Device10(device10) => device10.into(),
|
||||
Self::Device12(device12) => device12.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -271,12 +268,16 @@ pub struct AllocatorCreateDesc {
|
||||
}
|
||||
|
||||
pub enum ResourceType<'a> {
|
||||
/// Allocation equivalent to Dx12's CommittedResource.
|
||||
/// Create a D3D12 [`CommittedResource`].
|
||||
///
|
||||
/// [`CommittedResource`]: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12device-createcommittedresource
|
||||
Committed {
|
||||
heap_properties: &'a D3D12_HEAP_PROPERTIES,
|
||||
heap_flags: D3D12_HEAP_FLAGS,
|
||||
},
|
||||
/// Allocation equivalent to Dx12's PlacedResource.
|
||||
/// Create a D3D12 [`PlacedResource`].
|
||||
///
|
||||
/// [`PlacedResource`]: https://learn.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12device-createplacedresource
|
||||
Placed,
|
||||
}
|
||||
|
||||
@@ -1099,50 +1100,38 @@ impl Allocator {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_report(&self) -> AllocatorReport {
|
||||
let mut allocations = vec![];
|
||||
let mut blocks = vec![];
|
||||
let mut total_reserved_bytes = 0;
|
||||
|
||||
for memory_type in &self.memory_types {
|
||||
for block in memory_type.memory_blocks.iter().flatten() {
|
||||
total_reserved_bytes += block.size;
|
||||
let first_allocation = allocations.len();
|
||||
allocations.extend(block.sub_allocator.report_allocations());
|
||||
blocks.push(MemoryBlockReport {
|
||||
size: block.size,
|
||||
allocations: first_allocation..allocations.len(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let total_allocated_bytes = allocations.iter().map(|report| report.size).sum();
|
||||
|
||||
AllocatorReport {
|
||||
allocations,
|
||||
blocks,
|
||||
total_allocated_bytes,
|
||||
total_reserved_bytes,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for Allocator {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut allocation_report = vec![];
|
||||
let mut total_reserved_size_in_bytes = 0;
|
||||
|
||||
for memory_type in &self.memory_types {
|
||||
for block in memory_type.memory_blocks.iter().flatten() {
|
||||
total_reserved_size_in_bytes += block.size;
|
||||
allocation_report.extend(block.sub_allocator.report_allocations())
|
||||
}
|
||||
}
|
||||
|
||||
let total_used_size_in_bytes = allocation_report.iter().map(|report| report.size).sum();
|
||||
|
||||
allocation_report.sort_by_key(|alloc| std::cmp::Reverse(alloc.size));
|
||||
|
||||
writeln!(
|
||||
f,
|
||||
"================================================================",
|
||||
)?;
|
||||
writeln!(
|
||||
f,
|
||||
"ALLOCATION BREAKDOWN ({} / {})",
|
||||
fmt_bytes(total_used_size_in_bytes),
|
||||
fmt_bytes(total_reserved_size_in_bytes),
|
||||
)?;
|
||||
|
||||
let max_num_allocations_to_print = f.precision().map_or(usize::MAX, |n| n);
|
||||
for (idx, alloc) in allocation_report.iter().enumerate() {
|
||||
if idx >= max_num_allocations_to_print {
|
||||
break;
|
||||
}
|
||||
writeln!(
|
||||
f,
|
||||
"{:max_len$.max_len$}\t- {}",
|
||||
alloc.name,
|
||||
fmt_bytes(alloc.size),
|
||||
max_len = allocator::VISUALIZER_TABLE_MAX_ENTRY_NAME_LEN,
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
self.generate_report().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
#![allow(clippy::new_without_default)]
|
||||
|
||||
use windows::Win32::Graphics::Direct3D12::*;
|
||||
|
||||
use super::Allocator;
|
||||
use crate::visualizer::{
|
||||
render_allocation_reports_ui, AllocationReportVisualizeSettings, ColorScheme,
|
||||
MemoryChunksVisualizationSettings,
|
||||
};
|
||||
|
||||
use windows::Win32::Graphics::Direct3D12::*;
|
||||
|
||||
struct AllocatorVisualizerBlockWindow {
|
||||
memory_type_index: usize,
|
||||
block_index: usize,
|
||||
@@ -92,7 +92,7 @@ impl AllocatorVisualizer {
|
||||
let mut total_allocated = 0;
|
||||
|
||||
for block in mem_type.memory_blocks.iter().flatten() {
|
||||
total_block_size += block.sub_allocator.size();
|
||||
total_block_size += block.size;
|
||||
total_allocated += block.sub_allocator.allocated();
|
||||
}
|
||||
|
||||
@@ -134,10 +134,7 @@ impl AllocatorVisualizer {
|
||||
let Some(block) = block else { continue };
|
||||
|
||||
ui.collapsing(format!("Block: {}", block_idx), |ui| {
|
||||
ui.label(format!(
|
||||
"size: {} KiB",
|
||||
block.sub_allocator.size() / 1024
|
||||
));
|
||||
ui.label(format!("size: {} KiB", block.size / 1024));
|
||||
ui.label(format!(
|
||||
"allocated: {} KiB",
|
||||
block.sub_allocator.allocated() / 1024
|
||||
@@ -147,7 +144,7 @@ impl AllocatorVisualizer {
|
||||
|
||||
if block.sub_allocator.supports_visualization()
|
||||
&& ui.button("visualize").clicked()
|
||||
&& !self.selected_blocks.iter().enumerate().any(|(_, x)| {
|
||||
&& !self.selected_blocks.iter().any(|x| {
|
||||
x.memory_type_index == mem_type_idx
|
||||
&& x.block_index == block_idx
|
||||
})
|
||||
@@ -205,7 +202,7 @@ impl AllocatorVisualizer {
|
||||
"Memory type {}, Memory block {}, Block size: {} KiB",
|
||||
window.memory_type_index,
|
||||
window.block_index,
|
||||
memblock.sub_allocator.size() / 1024
|
||||
memblock.size / 1024
|
||||
));
|
||||
|
||||
window
|
||||
|
||||
4
third_party/rust/gpu-allocator/src/lib.rs
vendored
4
third_party/rust/gpu-allocator/src/lib.rs
vendored
@@ -52,7 +52,7 @@
|
||||
//! # }).unwrap();
|
||||
//!
|
||||
//! // Setup vulkan info
|
||||
//! let vk_info = vk::BufferCreateInfo::builder()
|
||||
//! let vk_info = vk::BufferCreateInfo::default()
|
||||
//! .size(512)
|
||||
//! .usage(vk::BufferUsageFlags::STORAGE_BUFFER);
|
||||
//!
|
||||
@@ -212,6 +212,8 @@ pub use result::*;
|
||||
|
||||
pub(crate) mod allocator;
|
||||
|
||||
pub use allocator::{AllocationReport, AllocatorReport, MemoryBlockReport};
|
||||
|
||||
#[cfg(feature = "visualizer")]
|
||||
pub mod visualizer;
|
||||
|
||||
|
||||
92
third_party/rust/gpu-allocator/src/metal/mod.rs
vendored
92
third_party/rust/gpu-allocator/src/metal/mod.rs
vendored
@@ -1,10 +1,12 @@
|
||||
#![deny(clippy::unimplemented, clippy::unwrap_used, clippy::ok_expect)]
|
||||
use std::{backtrace::Backtrace, sync::Arc};
|
||||
|
||||
use log::debug;
|
||||
|
||||
use crate::{
|
||||
allocator, AllocationError, AllocationSizes, AllocatorDebugSettings, MemoryLocation, Result,
|
||||
allocator::{self, AllocatorReport, MemoryBlockReport},
|
||||
AllocationError, AllocationSizes, AllocatorDebugSettings, MemoryLocation, Result,
|
||||
};
|
||||
use log::{debug, Level};
|
||||
|
||||
fn memory_location_to_metal(location: MemoryLocation) -> metal::MTLResourceOptions {
|
||||
match location {
|
||||
@@ -15,6 +17,7 @@ fn memory_location_to_metal(location: MemoryLocation) -> metal::MTLResourceOptio
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Allocation {
|
||||
chunk_id: Option<std::num::NonZeroU64>,
|
||||
offset: u64,
|
||||
@@ -69,6 +72,7 @@ impl Allocation {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct AllocationCreateDesc<'a> {
|
||||
/// Name of the allocation, for tracking and debugging purposes
|
||||
pub name: &'a str,
|
||||
@@ -84,7 +88,7 @@ impl<'a> AllocationCreateDesc<'a> {
|
||||
name: &'a str,
|
||||
length: u64,
|
||||
location: MemoryLocation,
|
||||
) -> AllocationCreateDesc<'a> {
|
||||
) -> Self {
|
||||
let size_and_align =
|
||||
device.heap_buffer_size_and_align(length, memory_location_to_metal(location));
|
||||
Self {
|
||||
@@ -95,11 +99,7 @@ impl<'a> AllocationCreateDesc<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn texture(
|
||||
device: &metal::Device,
|
||||
name: &'a str,
|
||||
desc: &metal::TextureDescriptor,
|
||||
) -> AllocationCreateDesc<'a> {
|
||||
pub fn texture(device: &metal::Device, name: &'a str, desc: &metal::TextureDescriptor) -> Self {
|
||||
let size_and_align = device.heap_texture_size_and_align(desc);
|
||||
Self {
|
||||
name,
|
||||
@@ -119,7 +119,7 @@ impl<'a> AllocationCreateDesc<'a> {
|
||||
name: &'a str,
|
||||
size: u64,
|
||||
location: MemoryLocation,
|
||||
) -> AllocationCreateDesc<'a> {
|
||||
) -> Self {
|
||||
let size_and_align = device.heap_acceleration_structure_size_and_align_with_size(size);
|
||||
Self {
|
||||
name,
|
||||
@@ -129,24 +129,31 @@ impl<'a> AllocationCreateDesc<'a> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Allocator {
|
||||
device: Arc<metal::Device>,
|
||||
debug_settings: AllocatorDebugSettings,
|
||||
memory_types: Vec<MemoryType>,
|
||||
allocation_sizes: AllocationSizes,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AllocatorCreateDesc {
|
||||
pub device: Arc<metal::Device>,
|
||||
pub debug_settings: AllocatorDebugSettings,
|
||||
pub allocation_sizes: AllocationSizes,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CommittedAllocationStatistics {
|
||||
pub num_allocations: usize,
|
||||
pub total_size: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct MemoryBlock {
|
||||
heap: Arc<metal::Heap>,
|
||||
_size: u64,
|
||||
size: u64,
|
||||
sub_allocator: Box<dyn allocator::SubAllocator>,
|
||||
}
|
||||
|
||||
@@ -156,10 +163,12 @@ impl MemoryBlock {
|
||||
size: u64,
|
||||
heap_descriptor: &metal::HeapDescriptor,
|
||||
dedicated: bool,
|
||||
memory_location: MemoryLocation,
|
||||
) -> Result<Self> {
|
||||
heap_descriptor.set_size(size);
|
||||
|
||||
let heap = Arc::new(device.new_heap(heap_descriptor));
|
||||
heap.set_label(&format!("MemoryBlock {memory_location:?}"));
|
||||
|
||||
let sub_allocator: Box<dyn allocator::SubAllocator> = if dedicated {
|
||||
Box::new(allocator::DedicatedBlockAllocator::new(size))
|
||||
@@ -169,12 +178,13 @@ impl MemoryBlock {
|
||||
|
||||
Ok(Self {
|
||||
heap,
|
||||
_size: size,
|
||||
size,
|
||||
sub_allocator,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct MemoryType {
|
||||
memory_blocks: Vec<Option<MemoryBlock>>,
|
||||
_committed_allocations: CommittedAllocationStatistics,
|
||||
@@ -206,7 +216,13 @@ impl MemoryType {
|
||||
|
||||
// Create a dedicated block for large memory allocations
|
||||
if size > memblock_size {
|
||||
let mem_block = MemoryBlock::new(device, size, &self.heap_properties, true)?;
|
||||
let mem_block = MemoryBlock::new(
|
||||
device,
|
||||
size,
|
||||
&self.heap_properties,
|
||||
true,
|
||||
self.memory_location,
|
||||
)?;
|
||||
|
||||
let block_index = self.memory_blocks.iter().position(|block| block.is_none());
|
||||
let block_index = match block_index {
|
||||
@@ -276,8 +292,13 @@ impl MemoryType {
|
||||
}
|
||||
}
|
||||
|
||||
let new_memory_block =
|
||||
MemoryBlock::new(device, memblock_size, &self.heap_properties, false)?;
|
||||
let new_memory_block = MemoryBlock::new(
|
||||
device,
|
||||
memblock_size,
|
||||
&self.heap_properties,
|
||||
false,
|
||||
self.memory_location,
|
||||
)?;
|
||||
|
||||
let new_block_index = if let Some(block_index) = empty_block_index {
|
||||
self.memory_blocks[block_index] = Some(new_memory_block);
|
||||
@@ -355,14 +376,7 @@ impl MemoryType {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ResourceCreateDesc {}
|
||||
pub struct Resource {}
|
||||
|
||||
impl Allocator {
|
||||
pub fn device(&self) -> &metal::Device {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub fn new(desc: &AllocatorCreateDesc) -> Result<Self> {
|
||||
let heap_types = [
|
||||
(MemoryLocation::GpuOnly, {
|
||||
@@ -389,7 +403,7 @@ impl Allocator {
|
||||
];
|
||||
|
||||
let memory_types = heap_types
|
||||
.iter()
|
||||
.into_iter()
|
||||
.enumerate()
|
||||
.map(|(i, (memory_location, heap_descriptor))| MemoryType {
|
||||
memory_blocks: vec![],
|
||||
@@ -397,8 +411,8 @@ impl Allocator {
|
||||
num_allocations: 0,
|
||||
total_size: 0,
|
||||
},
|
||||
memory_location: *memory_location,
|
||||
heap_properties: heap_descriptor.clone(),
|
||||
memory_location,
|
||||
heap_properties: heap_descriptor,
|
||||
memory_type_index: i,
|
||||
active_general_blocks: 0,
|
||||
})
|
||||
@@ -479,10 +493,30 @@ impl Allocator {
|
||||
heaps
|
||||
}
|
||||
|
||||
pub fn rename_allocation(&mut self, _allocation: &mut Allocation, _name: &str) -> Result<()> {
|
||||
todo!()
|
||||
}
|
||||
pub fn report_memory_leaks(&self, _log_level: Level) {
|
||||
todo!()
|
||||
pub fn generate_report(&self) -> AllocatorReport {
|
||||
let mut allocations = vec![];
|
||||
let mut blocks = vec![];
|
||||
let mut total_reserved_bytes = 0;
|
||||
|
||||
for memory_type in &self.memory_types {
|
||||
for block in memory_type.memory_blocks.iter().flatten() {
|
||||
total_reserved_bytes += block.size;
|
||||
let first_allocation = allocations.len();
|
||||
allocations.extend(block.sub_allocator.report_allocations());
|
||||
blocks.push(MemoryBlockReport {
|
||||
size: block.size,
|
||||
allocations: first_allocation..allocations.len(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let total_allocated_bytes = allocations.iter().map(|report| report.size).sum();
|
||||
|
||||
AllocatorReport {
|
||||
allocations,
|
||||
blocks,
|
||||
total_allocated_bytes,
|
||||
total_reserved_bytes,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,6 +115,7 @@ pub(crate) fn render_allocation_reports_ui(
|
||||
name,
|
||||
size,
|
||||
backtrace,
|
||||
..
|
||||
} = alloc;
|
||||
|
||||
row.col(|ui| {
|
||||
|
||||
@@ -2,9 +2,8 @@ use std::backtrace::BacktraceStatus;
|
||||
|
||||
use egui::{Color32, DragValue, Rect, ScrollArea, Sense, Ui, Vec2};
|
||||
|
||||
use crate::allocator::free_list_allocator::MemoryChunk;
|
||||
|
||||
use super::ColorScheme;
|
||||
use crate::allocator::free_list_allocator::MemoryChunk;
|
||||
|
||||
pub(crate) struct MemoryChunksVisualizationSettings {
|
||||
pub width_in_bytes: u64,
|
||||
|
||||
96
third_party/rust/gpu-allocator/src/vulkan/mod.rs
vendored
96
third_party/rust/gpu-allocator/src/vulkan/mod.rs
vendored
@@ -2,18 +2,17 @@
|
||||
|
||||
#[cfg(feature = "visualizer")]
|
||||
mod visualizer;
|
||||
#[cfg(feature = "visualizer")]
|
||||
pub use visualizer::AllocatorVisualizer;
|
||||
|
||||
use std::{backtrace::Backtrace, fmt, marker::PhantomData, sync::Arc};
|
||||
|
||||
use ash::vk;
|
||||
use log::{debug, Level};
|
||||
#[cfg(feature = "visualizer")]
|
||||
pub use visualizer::AllocatorVisualizer;
|
||||
|
||||
use super::allocator;
|
||||
use crate::{
|
||||
allocator::fmt_bytes, AllocationError, AllocationSizes, AllocatorDebugSettings, MemoryLocation,
|
||||
Result,
|
||||
allocator::{AllocatorReport, MemoryBlockReport},
|
||||
AllocationError, AllocationSizes, AllocatorDebugSettings, MemoryLocation, Result,
|
||||
};
|
||||
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
|
||||
@@ -58,7 +57,7 @@ unsafe impl Sync for SendSyncPtr {}
|
||||
pub struct AllocatorCreateDesc {
|
||||
pub instance: ash::Instance,
|
||||
pub device: ash::Device,
|
||||
pub physical_device: ash::vk::PhysicalDevice,
|
||||
pub physical_device: vk::PhysicalDevice,
|
||||
pub debug_settings: AllocatorDebugSettings,
|
||||
pub buffer_device_address: bool,
|
||||
pub allocation_sizes: AllocationSizes,
|
||||
@@ -105,7 +104,7 @@ pub struct AllocatorCreateDesc {
|
||||
/// let my_gpu_data: Vec<MyGpuData> = make_vertex_data();
|
||||
/// ```
|
||||
///
|
||||
/// Depending on how the data we're copying will be used, the vulkan device may have a minimum
|
||||
/// Depending on how the data we're copying will be used, the Vulkan device may have a minimum
|
||||
/// alignment requirement for that data:
|
||||
///
|
||||
/// ```ignore
|
||||
@@ -180,7 +179,7 @@ impl Allocation {
|
||||
///
|
||||
/// [`Slab`]: presser::Slab
|
||||
// best to be explicit where the lifetime is coming from since we're doing unsafe things
|
||||
// and relying on an inferred liftime type in the PhantomData below
|
||||
// and relying on an inferred lifetime type in the PhantomData below
|
||||
#[allow(clippy::needless_lifetimes)]
|
||||
pub fn try_as_mapped_slab<'a>(&'a mut self) -> Option<MappedAllocationSlab<'a>> {
|
||||
let mapped_ptr = self.mapped_ptr()?.cast().as_ptr();
|
||||
@@ -352,12 +351,12 @@ impl MemoryBlock {
|
||||
requires_personal_block: bool,
|
||||
) -> Result<Self> {
|
||||
let device_memory = {
|
||||
let alloc_info = vk::MemoryAllocateInfo::builder()
|
||||
let alloc_info = vk::MemoryAllocateInfo::default()
|
||||
.allocation_size(size)
|
||||
.memory_type_index(mem_type_index as u32);
|
||||
|
||||
let allocation_flags = vk::MemoryAllocateFlags::DEVICE_ADDRESS;
|
||||
let mut flags_info = vk::MemoryAllocateFlagsInfo::builder().flags(allocation_flags);
|
||||
let mut flags_info = vk::MemoryAllocateFlagsInfo::default().flags(allocation_flags);
|
||||
// TODO(manon): Test this based on if the device has this feature enabled or not
|
||||
let alloc_info = if buffer_device_address {
|
||||
alloc_info.push_next(&mut flags_info)
|
||||
@@ -366,7 +365,7 @@ impl MemoryBlock {
|
||||
};
|
||||
|
||||
// Flag the memory as dedicated if required.
|
||||
let mut dedicated_memory_info = vk::MemoryDedicatedAllocateInfo::builder();
|
||||
let mut dedicated_memory_info = vk::MemoryDedicatedAllocateInfo::default();
|
||||
let alloc_info = match allocation_scheme {
|
||||
AllocationScheme::DedicatedBuffer(buffer) => {
|
||||
dedicated_memory_info = dedicated_memory_info.buffer(buffer);
|
||||
@@ -691,53 +690,13 @@ pub struct Allocator {
|
||||
|
||||
impl fmt::Debug for Allocator {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut allocation_report = vec![];
|
||||
let mut total_reserved_size_in_bytes = 0;
|
||||
|
||||
for memory_type in &self.memory_types {
|
||||
for block in memory_type.memory_blocks.iter().flatten() {
|
||||
total_reserved_size_in_bytes += block.size;
|
||||
allocation_report.extend(block.sub_allocator.report_allocations())
|
||||
}
|
||||
}
|
||||
|
||||
let total_used_size_in_bytes = allocation_report.iter().map(|report| report.size).sum();
|
||||
|
||||
allocation_report.sort_by_key(|alloc| std::cmp::Reverse(alloc.size));
|
||||
|
||||
writeln!(
|
||||
f,
|
||||
"================================================================",
|
||||
)?;
|
||||
writeln!(
|
||||
f,
|
||||
"ALLOCATION BREAKDOWN ({} / {})",
|
||||
fmt_bytes(total_used_size_in_bytes),
|
||||
fmt_bytes(total_reserved_size_in_bytes),
|
||||
)?;
|
||||
|
||||
let max_num_allocations_to_print = f.precision().map_or(usize::MAX, |n| n);
|
||||
for (idx, alloc) in allocation_report.iter().enumerate() {
|
||||
if idx >= max_num_allocations_to_print {
|
||||
break;
|
||||
}
|
||||
|
||||
writeln!(
|
||||
f,
|
||||
"{:max_len$.max_len$}\t- {}",
|
||||
alloc.name,
|
||||
fmt_bytes(alloc.size),
|
||||
max_len = allocator::VISUALIZER_TABLE_MAX_ENTRY_NAME_LEN,
|
||||
)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
self.generate_report().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl Allocator {
|
||||
pub fn new(desc: &AllocatorCreateDesc) -> Result<Self> {
|
||||
if desc.physical_device == ash::vk::PhysicalDevice::null() {
|
||||
if desc.physical_device == vk::PhysicalDevice::null() {
|
||||
return Err(AllocationError::InvalidAllocatorCreateDesc(
|
||||
"AllocatorCreateDesc field `physical_device` is null.".into(),
|
||||
));
|
||||
@@ -748,8 +707,8 @@ impl Allocator {
|
||||
.get_physical_device_memory_properties(desc.physical_device)
|
||||
};
|
||||
|
||||
let memory_types = &mem_props.memory_types[..mem_props.memory_type_count as _];
|
||||
let memory_heaps = mem_props.memory_heaps[..mem_props.memory_heap_count as _].to_vec();
|
||||
let memory_types = &mem_props.memory_types_as_slice();
|
||||
let memory_heaps = mem_props.memory_heaps_as_slice().to_vec();
|
||||
|
||||
if desc.debug_settings.log_memory_information {
|
||||
debug!("memory type count: {}", mem_props.memory_type_count);
|
||||
@@ -972,6 +931,33 @@ impl Allocator {
|
||||
})
|
||||
.map(|memory_type| memory_type.memory_type_index as _)
|
||||
}
|
||||
|
||||
pub fn generate_report(&self) -> AllocatorReport {
|
||||
let mut allocations = vec![];
|
||||
let mut blocks = vec![];
|
||||
let mut total_reserved_bytes = 0;
|
||||
|
||||
for memory_type in &self.memory_types {
|
||||
for block in memory_type.memory_blocks.iter().flatten() {
|
||||
total_reserved_bytes += block.size;
|
||||
let first_allocation = allocations.len();
|
||||
allocations.extend(block.sub_allocator.report_allocations());
|
||||
blocks.push(MemoryBlockReport {
|
||||
size: block.size,
|
||||
allocations: first_allocation..allocations.len(),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let total_allocated_bytes = allocations.iter().map(|report| report.size).sum();
|
||||
|
||||
AllocatorReport {
|
||||
allocations,
|
||||
blocks,
|
||||
total_allocated_bytes,
|
||||
total_reserved_bytes,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Allocator {
|
||||
|
||||
@@ -121,7 +121,7 @@ impl AllocatorVisualizer {
|
||||
|
||||
if block.sub_allocator.supports_visualization()
|
||||
&& ui.button("visualize").clicked()
|
||||
&& !self.selected_blocks.iter().enumerate().any(|(_, x)| {
|
||||
&& !self.selected_blocks.iter().any(|x| {
|
||||
x.memory_type_index == mem_type_idx
|
||||
&& x.block_index == block_idx
|
||||
})
|
||||
|
||||
2
third_party/rust/naga/.cargo-checksum.json
vendored
2
third_party/rust/naga/.cargo-checksum.json
vendored
File diff suppressed because one or more lines are too long
1
third_party/rust/naga/CHANGELOG.md
vendored
1
third_party/rust/naga/CHANGELOG.md
vendored
@@ -81,6 +81,7 @@ For changelogs after v0.14, see [the wgpu changelog](../CHANGELOG.md).
|
||||
- Make varyings' struct members unique. ([#2521](https://github.com/gfx-rs/naga/pull/2521)) **@evahop**
|
||||
- Add experimental vertex pulling transform flag. ([#5254](https://github.com/gfx-rs/wgpu/pull/5254)) **@bradwerth**
|
||||
- Fixup some generated MSL for vertex buffer unpack functions. ([#5829](https://github.com/gfx-rs/wgpu/pull/5829)) **@bradwerth**
|
||||
- Make vertex pulling transform on by default. ([#5773](https://github.com/gfx-rs/wgpu/pull/5773)) **@bradwerth**
|
||||
|
||||
#### GLSL-OUT
|
||||
|
||||
|
||||
15
third_party/rust/naga/Cargo.toml
vendored
15
third_party/rust/naga/Cargo.toml
vendored
@@ -11,9 +11,9 @@
|
||||
|
||||
[package]
|
||||
edition = "2021"
|
||||
rust-version = "1.74"
|
||||
rust-version = "1.76"
|
||||
name = "naga"
|
||||
version = "0.20.0"
|
||||
version = "22.0.0"
|
||||
authors = ["gfx-rs developers"]
|
||||
exclude = [
|
||||
"bin/**/*",
|
||||
@@ -43,11 +43,12 @@ path = "tests/root.rs"
|
||||
|
||||
[dependencies]
|
||||
arrayvec = "0.7"
|
||||
bit-set = "0.6"
|
||||
bit-set = "0.8"
|
||||
bitflags = "2.6"
|
||||
indexmap = "2"
|
||||
log = "0.4"
|
||||
rustc-hash = "1.1.0"
|
||||
thiserror = "1.0.62"
|
||||
thiserror = "1.0.63"
|
||||
|
||||
[dependencies.arbitrary]
|
||||
version = "1.3"
|
||||
@@ -61,10 +62,6 @@ version = "0.11.0"
|
||||
version = "0.2.1"
|
||||
optional = true
|
||||
|
||||
[dependencies.indexmap]
|
||||
version = "2"
|
||||
features = ["std"]
|
||||
|
||||
[dependencies.petgraph]
|
||||
version = "0.6"
|
||||
optional = true
|
||||
@@ -103,7 +100,7 @@ git = "https://github.com/gfx-rs/rspirv"
|
||||
rev = "b969f175d5663258b4891e44b76c1544da9661ab"
|
||||
|
||||
[dev-dependencies.serde]
|
||||
version = "1.0"
|
||||
version = "1"
|
||||
features = ["derive"]
|
||||
|
||||
[dev-dependencies.spirv]
|
||||
|
||||
2
third_party/rust/naga/README.md
vendored
2
third_party/rust/naga/README.md
vendored
@@ -4,7 +4,7 @@
|
||||
[](https://crates.io/crates/naga)
|
||||
[](https://docs.rs/naga)
|
||||
[](https://github.com/gfx-rs/naga/actions)
|
||||

|
||||

|
||||
[](https://codecov.io/gh/gfx-rs/naga)
|
||||
|
||||
The shader translation library for the needs of [wgpu](https://github.com/gfx-rs/wgpu).
|
||||
|
||||
311
third_party/rust/naga/src/back/continue_forward.rs
vendored
Normal file
311
third_party/rust/naga/src/back/continue_forward.rs
vendored
Normal file
@@ -0,0 +1,311 @@
|
||||
//! Workarounds for platform bugs and limitations in switches and loops.
|
||||
//!
|
||||
//! In these docs, we use CamelCase links for Naga IR concepts, and ordinary
|
||||
//! `code` formatting for HLSL or GLSL concepts.
|
||||
//!
|
||||
//! ## Avoiding `continue` within `switch`
|
||||
//!
|
||||
//! As described in <https://github.com/gfx-rs/wgpu/issues/4485>, the FXC HLSL
|
||||
//! compiler doesn't allow `continue` statements within `switch` statements, but
|
||||
//! Naga IR does. We work around this by introducing synthetic boolean local
|
||||
//! variables and branches.
|
||||
//!
|
||||
//! Specifically:
|
||||
//!
|
||||
//! - We generate code for [`Continue`] statements within [`SwitchCase`]s that
|
||||
//! sets an introduced `bool` local to `true` and does a `break`, jumping to
|
||||
//! immediately after the generated `switch`.
|
||||
//!
|
||||
//! - When generating code for a [`Switch`] statement, we conservatively assume
|
||||
//! it might contain such a [`Continue`] statement, so:
|
||||
//!
|
||||
//! - If it's the outermost such [`Switch`] within a [`Loop`], we declare the
|
||||
//! `bool` local ahead of the switch, initialized to `false`. Immediately
|
||||
//! after the `switch`, we check the local and do a `continue` if it's set.
|
||||
//!
|
||||
//! - If the [`Switch`] is nested within other [`Switch`]es, then after the
|
||||
//! generated `switch`, we check the local (which we know was declared
|
||||
//! before the surrounding `switch`) and do a `break` if it's set.
|
||||
//!
|
||||
//! - As an optimization, we only generate the check of the local if a
|
||||
//! [`Continue`] statement is encountered within the [`Switch`]. This may
|
||||
//! help drivers more easily identify that the `bool` is unused.
|
||||
//!
|
||||
//! So while we "weaken" the [`Continue`] statement by rendering it as a `break`
|
||||
//! statement, we also place checks immediately at the locations to which those
|
||||
//! `break` statements will jump, until we can be sure we've reached the
|
||||
//! intended target of the original [`Continue`].
|
||||
//!
|
||||
//! In the case of nested [`Loop`] and [`Switch`] statements, there may be
|
||||
//! multiple introduced `bool` locals in scope, but there's no problem knowing
|
||||
//! which one to operate on. At any point, there is at most one [`Loop`]
|
||||
//! statement that could be targeted by a [`Continue`] statement, so the correct
|
||||
//! `bool` local to set and test is always the one introduced for the innermost
|
||||
//! enclosing [`Loop`]'s outermost [`Switch`].
|
||||
//!
|
||||
//! # Avoiding single body `switch` statements
|
||||
//!
|
||||
//! As described in <https://github.com/gfx-rs/wgpu/issues/4514>, some language
|
||||
//! front ends miscompile `switch` statements where all cases branch to the same
|
||||
//! body. Our HLSL and GLSL backends render [`Switch`] statements with a single
|
||||
//! [`SwitchCase`] as `do {} while(false);` loops.
|
||||
//!
|
||||
//! However, this rewriting introduces a new loop that could "capture"
|
||||
//! `continue` statements in its body. To avoid doing so, we apply the
|
||||
//! [`Continue`]-to-`break` transformation described above.
|
||||
//!
|
||||
//! [`Continue`]: crate::Statement::Continue
|
||||
//! [`Loop`]: crate::Statement::Loop
|
||||
//! [`Switch`]: crate::Statement::Switch
|
||||
//! [`SwitchCase`]: crate::SwitchCase
|
||||
|
||||
use crate::proc::Namer;
|
||||
use std::rc::Rc;
|
||||
|
||||
/// A summary of the code surrounding a statement.
|
||||
enum Nesting {
|
||||
/// Currently nested in at least one [`Loop`] statement.
|
||||
///
|
||||
/// [`Continue`] should apply to the innermost loop.
|
||||
///
|
||||
/// When this entry is on the top of the stack:
|
||||
///
|
||||
/// * When entering an inner [`Loop`] statement, push a [`Loop`][nl] state
|
||||
/// onto the stack.
|
||||
///
|
||||
/// * When entering a nested [`Switch`] statement, push a [`Switch`][ns]
|
||||
/// state onto the stack with a new variable name. Before the generated
|
||||
/// `switch`, introduce a `bool` local with that name, initialized to
|
||||
/// `false`.
|
||||
///
|
||||
/// When exiting the [`Loop`] for which this entry was pushed, pop it from
|
||||
/// the stack.
|
||||
///
|
||||
/// [`Continue`]: crate::Statement::Continue
|
||||
/// [`Loop`]: crate::Statement::Loop
|
||||
/// [`Switch`]: crate::Statement::Switch
|
||||
/// [ns]: Nesting::Switch
|
||||
/// [nl]: Nesting::Loop
|
||||
Loop,
|
||||
|
||||
/// Currently nested in at least one [`Switch`] that may need to forward
|
||||
/// [`Continue`]s.
|
||||
///
|
||||
/// This includes [`Switch`]es rendered as `do {} while(false)` loops, but
|
||||
/// doesn't need to include regular [`Switch`]es in backends that can
|
||||
/// support `continue` within switches.
|
||||
///
|
||||
/// [`Continue`] should be forwarded to the innermost surrounding [`Loop`].
|
||||
///
|
||||
/// When this entry is on the top of the stack:
|
||||
///
|
||||
/// * When entering a nested [`Loop`], push a [`Loop`][nl] state onto the
|
||||
/// stack.
|
||||
///
|
||||
/// * When entering a nested [`Switch`], push a [`Switch`][ns] state onto
|
||||
/// the stack with a clone of the introduced `bool` variable's name.
|
||||
///
|
||||
/// * When encountering a [`Continue`] statement, render it as code to set
|
||||
/// the introduced `bool` local (whose name is held in [`variable`]) to
|
||||
/// `true`, and then `break`. Set [`continue_encountered`] to `true` to
|
||||
/// record that the [`Switch`] contains a [`Continue`].
|
||||
///
|
||||
/// * When exiting this [`Switch`], pop its entry from the stack. If
|
||||
/// [`continue_encountered`] is set, then we have rendered [`Continue`]
|
||||
/// statements as `break` statements that jump to this point. Generate
|
||||
/// code to check `variable`, and if it is `true`:
|
||||
///
|
||||
/// * If there is another [`Switch`][ns] left on top of the stack, set
|
||||
/// its `continue_encountered` flag, and generate a `break`. (Both
|
||||
/// [`Switch`][ns]es are within the same [`Loop`] and share the same
|
||||
/// introduced variable, so there's no need to set another flag to
|
||||
/// continue to exit the `switch`es.)
|
||||
///
|
||||
/// * Otherwise, `continue`.
|
||||
///
|
||||
/// When we exit the [`Switch`] for which this entry was pushed, pop it.
|
||||
///
|
||||
/// [`Continue`]: crate::Statement::Continue
|
||||
/// [`Loop`]: crate::Statement::Loop
|
||||
/// [`Switch`]: crate::Statement::Switch
|
||||
/// [`variable`]: Nesting::Switch::variable
|
||||
/// [`continue_encountered`]: Nesting::Switch::continue_encountered
|
||||
/// [ns]: Nesting::Switch
|
||||
/// [nl]: Nesting::Loop
|
||||
Switch {
|
||||
variable: Rc<String>,
|
||||
|
||||
/// Set if we've generated code for a [`Continue`] statement with this
|
||||
/// entry on the top of the stack.
|
||||
///
|
||||
/// If this is still clear when we finish rendering the [`Switch`], then
|
||||
/// we know we don't need to generate branch forwarding code. Omitting
|
||||
/// that may make it easier for drivers to tell that the `bool` we
|
||||
/// introduced ahead of the [`Switch`] is actually unused.
|
||||
///
|
||||
/// [`Continue`]: crate::Statement::Continue
|
||||
/// [`Switch`]: crate::Statement::Switch
|
||||
continue_encountered: bool,
|
||||
},
|
||||
}
|
||||
|
||||
/// A micro-IR for code a backend should generate after a [`Switch`].
|
||||
///
|
||||
/// [`Switch`]: crate::Statement::Switch
|
||||
pub(super) enum ExitControlFlow {
|
||||
None,
|
||||
/// Emit `if (continue_variable) { continue; }`
|
||||
Continue {
|
||||
variable: Rc<String>,
|
||||
},
|
||||
/// Emit `if (continue_variable) { break; }`
|
||||
///
|
||||
/// Used after a [`Switch`] to exit from an enclosing [`Switch`].
|
||||
///
|
||||
/// After the enclosing switch, its associated check will consult this same
|
||||
/// variable, see that it is set, and exit early.
|
||||
///
|
||||
/// [`Switch`]: crate::Statement::Switch
|
||||
Break {
|
||||
variable: Rc<String>,
|
||||
},
|
||||
}
|
||||
|
||||
/// Utility for tracking nesting of loops and switches to orchestrate forwarding
|
||||
/// of continue statements inside of a switch to the enclosing loop.
|
||||
///
|
||||
/// See [module docs](self) for why we need this.
|
||||
#[derive(Default)]
|
||||
pub(super) struct ContinueCtx {
|
||||
stack: Vec<Nesting>,
|
||||
}
|
||||
|
||||
impl ContinueCtx {
|
||||
/// Resets internal state.
|
||||
///
|
||||
/// Use this to reuse memory between writing sessions.
|
||||
pub fn clear(&mut self) {
|
||||
self.stack.clear();
|
||||
}
|
||||
|
||||
/// Updates internal state to record entering a [`Loop`] statement.
|
||||
///
|
||||
/// [`Loop`]: crate::Statement::Loop
|
||||
pub fn enter_loop(&mut self) {
|
||||
self.stack.push(Nesting::Loop);
|
||||
}
|
||||
|
||||
/// Updates internal state to record exiting a [`Loop`] statement.
|
||||
///
|
||||
/// [`Loop`]: crate::Statement::Loop
|
||||
pub fn exit_loop(&mut self) {
|
||||
if !matches!(self.stack.pop(), Some(Nesting::Loop)) {
|
||||
unreachable!("ContinueCtx stack out of sync");
|
||||
}
|
||||
}
|
||||
|
||||
/// Updates internal state to record entering a [`Switch`] statement.
|
||||
///
|
||||
/// Return `Some(variable)` if this [`Switch`] is nested within a [`Loop`],
|
||||
/// and the caller should introcue a new `bool` local variable named
|
||||
/// `variable` above the `switch`, for forwarding [`Continue`] statements.
|
||||
///
|
||||
/// `variable` is guaranteed not to conflict with any names used by the
|
||||
/// program itself.
|
||||
///
|
||||
/// [`Continue`]: crate::Statement::Continue
|
||||
/// [`Loop`]: crate::Statement::Loop
|
||||
/// [`Switch`]: crate::Statement::Switch
|
||||
pub fn enter_switch(&mut self, namer: &mut Namer) -> Option<Rc<String>> {
|
||||
match self.stack.last() {
|
||||
// If the stack is empty, we are not in loop, so we don't need to
|
||||
// forward continue statements within this `Switch`. We can leave
|
||||
// the stack empty.
|
||||
None => None,
|
||||
Some(&Nesting::Loop { .. }) => {
|
||||
let variable = Rc::new(namer.call("should_continue"));
|
||||
self.stack.push(Nesting::Switch {
|
||||
variable: Rc::clone(&variable),
|
||||
continue_encountered: false,
|
||||
});
|
||||
Some(variable)
|
||||
}
|
||||
Some(&Nesting::Switch { ref variable, .. }) => {
|
||||
self.stack.push(Nesting::Switch {
|
||||
variable: Rc::clone(variable),
|
||||
continue_encountered: false,
|
||||
});
|
||||
// We have already declared the variable before some enclosing
|
||||
// `Switch`.
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Update internal state to record leaving a [`Switch`] statement.
|
||||
///
|
||||
/// Return an [`ExitControlFlow`] value indicating what code should be
|
||||
/// introduced after the generated `switch` to forward continues.
|
||||
///
|
||||
/// [`Switch`]: crate::Statement::Switch
|
||||
pub fn exit_switch(&mut self) -> ExitControlFlow {
|
||||
match self.stack.pop() {
|
||||
// This doesn't indicate a problem: we don't start pushing entries
|
||||
// for `Switch` statements unless we have an enclosing `Loop`.
|
||||
None => ExitControlFlow::None,
|
||||
Some(Nesting::Loop { .. }) => {
|
||||
unreachable!("Unexpected loop state when exiting switch");
|
||||
}
|
||||
Some(Nesting::Switch {
|
||||
variable,
|
||||
continue_encountered: inner_continue,
|
||||
}) => {
|
||||
if !inner_continue {
|
||||
// No `Continue` statement was encountered, so we didn't
|
||||
// introduce any `break`s jumping to this point.
|
||||
ExitControlFlow::None
|
||||
} else if let Some(&mut Nesting::Switch {
|
||||
continue_encountered: ref mut outer_continue,
|
||||
..
|
||||
}) = self.stack.last_mut()
|
||||
{
|
||||
// This is nested in another `Switch`. Propagate upwards
|
||||
// that there is a continue statement present.
|
||||
*outer_continue = true;
|
||||
ExitControlFlow::Break { variable }
|
||||
} else {
|
||||
ExitControlFlow::Continue { variable }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Determine what to generate for a [`Continue`] statement.
|
||||
///
|
||||
/// If we can generate an ordinary `continue` statement, return `None`.
|
||||
///
|
||||
/// Otherwise, we're enclosed by a [`Switch`] that is itself enclosed by a
|
||||
/// [`Loop`]. Return `Some(variable)` to indicate that the [`Continue`]
|
||||
/// should be rendered as setting `variable` to `true`, and then doing a
|
||||
/// `break`.
|
||||
///
|
||||
/// This also notes that we've encountered a [`Continue`] statement, so that
|
||||
/// we can generate the right code to forward the branch following the
|
||||
/// enclosing `switch`.
|
||||
///
|
||||
/// [`Continue`]: crate::Statement::Continue
|
||||
/// [`Loop`]: crate::Statement::Loop
|
||||
/// [`Switch`]: crate::Statement::Switch
|
||||
pub fn continue_encountered(&mut self) -> Option<&str> {
|
||||
if let Some(&mut Nesting::Switch {
|
||||
ref variable,
|
||||
ref mut continue_encountered,
|
||||
}) = self.stack.last_mut()
|
||||
{
|
||||
*continue_encountered = true;
|
||||
Some(variable)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -447,7 +447,7 @@ impl<'a, W> Writer<'a, W> {
|
||||
..
|
||||
} = self;
|
||||
|
||||
// Loop trough all expressions in both functions and the entry point
|
||||
// Loop through all expressions in both functions and the entry point
|
||||
// to check for needed features
|
||||
for (expressions, info) in module
|
||||
.functions
|
||||
|
||||
148
third_party/rust/naga/src/back/glsl/mod.rs
vendored
148
third_party/rust/naga/src/back/glsl/mod.rs
vendored
@@ -545,6 +545,11 @@ pub struct Writer<'a, W> {
|
||||
named_expressions: crate::NamedExpressions,
|
||||
/// Set of expressions that need to be baked to avoid unnecessary repetition in output
|
||||
need_bake_expressions: back::NeedBakeExpressions,
|
||||
/// Information about nesting of loops and switches.
|
||||
///
|
||||
/// Used for forwarding continue statements in switches that have been
|
||||
/// transformed to `do {} while(false);` loops.
|
||||
continue_ctx: back::continue_forward::ContinueCtx,
|
||||
/// How many views to render to, if doing multiview rendering.
|
||||
multiview: Option<std::num::NonZeroU32>,
|
||||
/// Mapping of varying variables to their location. Needed for reflections.
|
||||
@@ -619,6 +624,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
block_id: IdGenerator::default(),
|
||||
named_expressions: Default::default(),
|
||||
need_bake_expressions: Default::default(),
|
||||
continue_ctx: back::continue_forward::ContinueCtx::default(),
|
||||
varying: Default::default(),
|
||||
};
|
||||
|
||||
@@ -1869,7 +1875,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
// with different precedences from applying earlier.
|
||||
write!(self.out, "(")?;
|
||||
|
||||
// Cycle trough all the components of the vector
|
||||
// Cycle through all the components of the vector
|
||||
for index in 0..size {
|
||||
let component = back::COMPONENTS[index];
|
||||
// Write the addition to the previous product
|
||||
@@ -2082,42 +2088,94 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
selector,
|
||||
ref cases,
|
||||
} => {
|
||||
// Start the switch
|
||||
write!(self.out, "{level}")?;
|
||||
write!(self.out, "switch(")?;
|
||||
self.write_expr(selector, ctx)?;
|
||||
writeln!(self.out, ") {{")?;
|
||||
|
||||
// Write all cases
|
||||
let l2 = level.next();
|
||||
for case in cases {
|
||||
match case.value {
|
||||
crate::SwitchValue::I32(value) => write!(self.out, "{l2}case {value}:")?,
|
||||
crate::SwitchValue::U32(value) => write!(self.out, "{l2}case {value}u:")?,
|
||||
crate::SwitchValue::Default => write!(self.out, "{l2}default:")?,
|
||||
// Some GLSL consumers may not handle switches with a single
|
||||
// body correctly: See wgpu#4514. Write such switch statements
|
||||
// as a `do {} while(false);` loop instead.
|
||||
//
|
||||
// Since doing so may inadvertently capture `continue`
|
||||
// statements in the switch body, we must apply continue
|
||||
// forwarding. See the `naga::back::continue_forward` module
|
||||
// docs for details.
|
||||
let one_body = cases
|
||||
.iter()
|
||||
.rev()
|
||||
.skip(1)
|
||||
.all(|case| case.fall_through && case.body.is_empty());
|
||||
if one_body {
|
||||
// Unlike HLSL, in GLSL `continue_ctx` only needs to know
|
||||
// about [`Switch`] statements that are being rendered as
|
||||
// `do-while` loops.
|
||||
if let Some(variable) = self.continue_ctx.enter_switch(&mut self.namer) {
|
||||
writeln!(self.out, "{level}bool {variable} = false;",)?;
|
||||
};
|
||||
writeln!(self.out, "{level}do {{")?;
|
||||
// Note: Expressions have no side-effects so we don't need to emit selector expression.
|
||||
|
||||
// Body
|
||||
if let Some(case) = cases.last() {
|
||||
for sta in case.body.iter() {
|
||||
self.write_stmt(sta, ctx, l2)?;
|
||||
}
|
||||
}
|
||||
// End do-while
|
||||
writeln!(self.out, "{level}}} while(false);")?;
|
||||
|
||||
// Handle any forwarded continue statements.
|
||||
use back::continue_forward::ExitControlFlow;
|
||||
let op = match self.continue_ctx.exit_switch() {
|
||||
ExitControlFlow::None => None,
|
||||
ExitControlFlow::Continue { variable } => Some(("continue", variable)),
|
||||
ExitControlFlow::Break { variable } => Some(("break", variable)),
|
||||
};
|
||||
if let Some((control_flow, variable)) = op {
|
||||
writeln!(self.out, "{level}if ({variable}) {{")?;
|
||||
writeln!(self.out, "{l2}{control_flow};")?;
|
||||
writeln!(self.out, "{level}}}")?;
|
||||
}
|
||||
} else {
|
||||
// Start the switch
|
||||
write!(self.out, "{level}")?;
|
||||
write!(self.out, "switch(")?;
|
||||
self.write_expr(selector, ctx)?;
|
||||
writeln!(self.out, ") {{")?;
|
||||
|
||||
// Write all cases
|
||||
for case in cases {
|
||||
match case.value {
|
||||
crate::SwitchValue::I32(value) => {
|
||||
write!(self.out, "{l2}case {value}:")?
|
||||
}
|
||||
crate::SwitchValue::U32(value) => {
|
||||
write!(self.out, "{l2}case {value}u:")?
|
||||
}
|
||||
crate::SwitchValue::Default => write!(self.out, "{l2}default:")?,
|
||||
}
|
||||
|
||||
let write_block_braces = !(case.fall_through && case.body.is_empty());
|
||||
if write_block_braces {
|
||||
writeln!(self.out, " {{")?;
|
||||
} else {
|
||||
writeln!(self.out)?;
|
||||
}
|
||||
|
||||
for sta in case.body.iter() {
|
||||
self.write_stmt(sta, ctx, l2.next())?;
|
||||
}
|
||||
|
||||
if !case.fall_through
|
||||
&& case.body.last().map_or(true, |s| !s.is_terminator())
|
||||
{
|
||||
writeln!(self.out, "{}break;", l2.next())?;
|
||||
}
|
||||
|
||||
if write_block_braces {
|
||||
writeln!(self.out, "{l2}}}")?;
|
||||
}
|
||||
}
|
||||
|
||||
let write_block_braces = !(case.fall_through && case.body.is_empty());
|
||||
if write_block_braces {
|
||||
writeln!(self.out, " {{")?;
|
||||
} else {
|
||||
writeln!(self.out)?;
|
||||
}
|
||||
|
||||
for sta in case.body.iter() {
|
||||
self.write_stmt(sta, ctx, l2.next())?;
|
||||
}
|
||||
|
||||
if !case.fall_through && case.body.last().map_or(true, |s| !s.is_terminator()) {
|
||||
writeln!(self.out, "{}break;", l2.next())?;
|
||||
}
|
||||
|
||||
if write_block_braces {
|
||||
writeln!(self.out, "{l2}}}")?;
|
||||
}
|
||||
writeln!(self.out, "{level}}}")?
|
||||
}
|
||||
|
||||
writeln!(self.out, "{level}}}")?
|
||||
}
|
||||
// Loops in naga IR are based on wgsl loops, glsl can emulate the behaviour by using a
|
||||
// while true loop and appending the continuing block to the body resulting on:
|
||||
@@ -2134,6 +2192,7 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
ref continuing,
|
||||
break_if,
|
||||
} => {
|
||||
self.continue_ctx.enter_loop();
|
||||
if !continuing.is_empty() || break_if.is_some() {
|
||||
let gate_name = self.namer.call("loop_init");
|
||||
writeln!(self.out, "{level}bool {gate_name} = true;")?;
|
||||
@@ -2159,7 +2218,8 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
for sta in body {
|
||||
self.write_stmt(sta, ctx, level.next())?;
|
||||
}
|
||||
writeln!(self.out, "{level}}}")?
|
||||
writeln!(self.out, "{level}}}")?;
|
||||
self.continue_ctx.exit_loop();
|
||||
}
|
||||
// Break, continue and return as written as in C
|
||||
// `break;`
|
||||
@@ -2169,8 +2229,14 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
}
|
||||
// `continue;`
|
||||
Statement::Continue => {
|
||||
write!(self.out, "{level}")?;
|
||||
writeln!(self.out, "continue;")?
|
||||
// Sometimes we must render a `Continue` statement as a `break`.
|
||||
// See the docs for the `back::continue_forward` module.
|
||||
if let Some(variable) = self.continue_ctx.continue_encountered() {
|
||||
writeln!(self.out, "{level}{variable} = true;",)?;
|
||||
writeln!(self.out, "{level}break;")?
|
||||
} else {
|
||||
writeln!(self.out, "{level}continue;")?
|
||||
}
|
||||
}
|
||||
// `return expr;`, `expr` is optional
|
||||
Statement::Return { value } => {
|
||||
@@ -3581,8 +3647,8 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
|
||||
return Ok(());
|
||||
}
|
||||
Mf::FindLsb => "findLSB",
|
||||
Mf::FindMsb => "findMSB",
|
||||
Mf::FirstTrailingBit => "findLSB",
|
||||
Mf::FirstLeadingBit => "findMSB",
|
||||
// data packing
|
||||
Mf::Pack4x8snorm => "packSnorm4x8",
|
||||
Mf::Pack4x8unorm => "packUnorm4x8",
|
||||
@@ -3656,8 +3722,10 @@ impl<'a, W: Write> Writer<'a, W> {
|
||||
|
||||
// Some GLSL functions always return signed integers (like findMSB),
|
||||
// so they need to be cast to uint if the argument is also an uint.
|
||||
let ret_might_need_int_to_uint =
|
||||
matches!(fun, Mf::FindLsb | Mf::FindMsb | Mf::CountOneBits | Mf::Abs);
|
||||
let ret_might_need_int_to_uint = matches!(
|
||||
fun,
|
||||
Mf::FirstTrailingBit | Mf::FirstLeadingBit | Mf::CountOneBits | Mf::Abs
|
||||
);
|
||||
|
||||
// Some GLSL functions only accept signed integers (like abs),
|
||||
// so they need their argument cast from uint to int.
|
||||
|
||||
1
third_party/rust/naga/src/back/hlsl/mod.rs
vendored
1
third_party/rust/naga/src/back/hlsl/mod.rs
vendored
@@ -327,6 +327,7 @@ pub struct Writer<'a, W> {
|
||||
/// Set of expressions that have associated temporary variables
|
||||
named_expressions: crate::NamedExpressions,
|
||||
wrapped: Wrapped,
|
||||
continue_ctx: back::continue_forward::ContinueCtx,
|
||||
|
||||
/// A reference to some part of a global variable, lowered to a series of
|
||||
/// byte offset calculations.
|
||||
|
||||
259
third_party/rust/naga/src/back/hlsl/writer.rs
vendored
259
third_party/rust/naga/src/back/hlsl/writer.rs
vendored
@@ -104,6 +104,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
||||
entry_point_io: Vec::new(),
|
||||
named_expressions: crate::NamedExpressions::default(),
|
||||
wrapped: super::Wrapped::default(),
|
||||
continue_ctx: back::continue_forward::ContinueCtx::default(),
|
||||
temp_access_chain: Vec::new(),
|
||||
need_bake_expressions: Default::default(),
|
||||
}
|
||||
@@ -122,6 +123,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
||||
self.entry_point_io.clear();
|
||||
self.named_expressions.clear();
|
||||
self.wrapped.clear();
|
||||
self.continue_ctx.clear();
|
||||
self.need_bake_expressions.clear();
|
||||
}
|
||||
|
||||
@@ -1439,6 +1441,151 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
||||
self.write_barrier(crate::Barrier::WORK_GROUP, level)
|
||||
}
|
||||
|
||||
/// Helper method used to write switches
|
||||
fn write_switch(
|
||||
&mut self,
|
||||
module: &Module,
|
||||
func_ctx: &back::FunctionCtx<'_>,
|
||||
level: back::Level,
|
||||
selector: Handle<crate::Expression>,
|
||||
cases: &[crate::SwitchCase],
|
||||
) -> BackendResult {
|
||||
// Write all cases
|
||||
let indent_level_1 = level.next();
|
||||
let indent_level_2 = indent_level_1.next();
|
||||
|
||||
// See docs of `back::continue_forward` module.
|
||||
if let Some(variable) = self.continue_ctx.enter_switch(&mut self.namer) {
|
||||
writeln!(self.out, "{level}bool {variable} = false;",)?;
|
||||
};
|
||||
|
||||
// Check if there is only one body, by seeing if all except the last case are fall through
|
||||
// with empty bodies. FXC doesn't handle these switches correctly, so
|
||||
// we generate a `do {} while(false);` loop instead. There must be a default case, so there
|
||||
// is no need to check if one of the cases would have matched.
|
||||
let one_body = cases
|
||||
.iter()
|
||||
.rev()
|
||||
.skip(1)
|
||||
.all(|case| case.fall_through && case.body.is_empty());
|
||||
if one_body {
|
||||
// Start the do-while
|
||||
writeln!(self.out, "{level}do {{")?;
|
||||
// Note: Expressions have no side-effects so we don't need to emit selector expression.
|
||||
|
||||
// Body
|
||||
if let Some(case) = cases.last() {
|
||||
for sta in case.body.iter() {
|
||||
self.write_stmt(module, sta, func_ctx, indent_level_1)?;
|
||||
}
|
||||
}
|
||||
// End do-while
|
||||
writeln!(self.out, "{level}}} while(false);")?;
|
||||
} else {
|
||||
// Start the switch
|
||||
write!(self.out, "{level}")?;
|
||||
write!(self.out, "switch(")?;
|
||||
self.write_expr(module, selector, func_ctx)?;
|
||||
writeln!(self.out, ") {{")?;
|
||||
|
||||
for (i, case) in cases.iter().enumerate() {
|
||||
match case.value {
|
||||
crate::SwitchValue::I32(value) => {
|
||||
write!(self.out, "{indent_level_1}case {value}:")?
|
||||
}
|
||||
crate::SwitchValue::U32(value) => {
|
||||
write!(self.out, "{indent_level_1}case {value}u:")?
|
||||
}
|
||||
crate::SwitchValue::Default => write!(self.out, "{indent_level_1}default:")?,
|
||||
}
|
||||
|
||||
// The new block is not only stylistic, it plays a role here:
|
||||
// We might end up having to write the same case body
|
||||
// multiple times due to FXC not supporting fallthrough.
|
||||
// Therefore, some `Expression`s written by `Statement::Emit`
|
||||
// will end up having the same name (`_expr<handle_index>`).
|
||||
// So we need to put each case in its own scope.
|
||||
let write_block_braces = !(case.fall_through && case.body.is_empty());
|
||||
if write_block_braces {
|
||||
writeln!(self.out, " {{")?;
|
||||
} else {
|
||||
writeln!(self.out)?;
|
||||
}
|
||||
|
||||
// Although FXC does support a series of case clauses before
|
||||
// a block[^yes], it does not support fallthrough from a
|
||||
// non-empty case block to the next[^no]. If this case has a
|
||||
// non-empty body with a fallthrough, emulate that by
|
||||
// duplicating the bodies of all the cases it would fall
|
||||
// into as extensions of this case's own body. This makes
|
||||
// the HLSL output potentially quadratic in the size of the
|
||||
// Naga IR.
|
||||
//
|
||||
// [^yes]: ```hlsl
|
||||
// case 1:
|
||||
// case 2: do_stuff()
|
||||
// ```
|
||||
// [^no]: ```hlsl
|
||||
// case 1: do_this();
|
||||
// case 2: do_that();
|
||||
// ```
|
||||
if case.fall_through && !case.body.is_empty() {
|
||||
let curr_len = i + 1;
|
||||
let end_case_idx = curr_len
|
||||
+ cases
|
||||
.iter()
|
||||
.skip(curr_len)
|
||||
.position(|case| !case.fall_through)
|
||||
.unwrap();
|
||||
let indent_level_3 = indent_level_2.next();
|
||||
for case in &cases[i..=end_case_idx] {
|
||||
writeln!(self.out, "{indent_level_2}{{")?;
|
||||
let prev_len = self.named_expressions.len();
|
||||
for sta in case.body.iter() {
|
||||
self.write_stmt(module, sta, func_ctx, indent_level_3)?;
|
||||
}
|
||||
// Clear all named expressions that were previously inserted by the statements in the block
|
||||
self.named_expressions.truncate(prev_len);
|
||||
writeln!(self.out, "{indent_level_2}}}")?;
|
||||
}
|
||||
|
||||
let last_case = &cases[end_case_idx];
|
||||
if last_case.body.last().map_or(true, |s| !s.is_terminator()) {
|
||||
writeln!(self.out, "{indent_level_2}break;")?;
|
||||
}
|
||||
} else {
|
||||
for sta in case.body.iter() {
|
||||
self.write_stmt(module, sta, func_ctx, indent_level_2)?;
|
||||
}
|
||||
if !case.fall_through && case.body.last().map_or(true, |s| !s.is_terminator()) {
|
||||
writeln!(self.out, "{indent_level_2}break;")?;
|
||||
}
|
||||
}
|
||||
|
||||
if write_block_braces {
|
||||
writeln!(self.out, "{indent_level_1}}}")?;
|
||||
}
|
||||
}
|
||||
|
||||
writeln!(self.out, "{level}}}")?;
|
||||
}
|
||||
|
||||
// Handle any forwarded continue statements.
|
||||
use back::continue_forward::ExitControlFlow;
|
||||
let op = match self.continue_ctx.exit_switch() {
|
||||
ExitControlFlow::None => None,
|
||||
ExitControlFlow::Continue { variable } => Some(("continue", variable)),
|
||||
ExitControlFlow::Break { variable } => Some(("break", variable)),
|
||||
};
|
||||
if let Some((control_flow, variable)) = op {
|
||||
writeln!(self.out, "{level}if ({variable}) {{")?;
|
||||
writeln!(self.out, "{indent_level_1}{control_flow};")?;
|
||||
writeln!(self.out, "{level}}}")?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Helper method used to write statements
|
||||
///
|
||||
/// # Notes
|
||||
@@ -1882,6 +2029,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
||||
ref continuing,
|
||||
break_if,
|
||||
} => {
|
||||
self.continue_ctx.enter_loop();
|
||||
let l2 = level.next();
|
||||
if !continuing.is_empty() || break_if.is_some() {
|
||||
let gate_name = self.namer.call("loop_init");
|
||||
@@ -1908,10 +2056,18 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
||||
for sta in body.iter() {
|
||||
self.write_stmt(module, sta, func_ctx, l2)?;
|
||||
}
|
||||
writeln!(self.out, "{level}}}")?
|
||||
writeln!(self.out, "{level}}}")?;
|
||||
self.continue_ctx.exit_loop();
|
||||
}
|
||||
Statement::Break => writeln!(self.out, "{level}break;")?,
|
||||
Statement::Continue => writeln!(self.out, "{level}continue;")?,
|
||||
Statement::Continue => {
|
||||
if let Some(variable) = self.continue_ctx.continue_encountered() {
|
||||
writeln!(self.out, "{level}{variable} = true;")?;
|
||||
writeln!(self.out, "{level}break;")?
|
||||
} else {
|
||||
writeln!(self.out, "{level}continue;")?
|
||||
}
|
||||
}
|
||||
Statement::Barrier(barrier) => {
|
||||
self.write_barrier(barrier, level)?;
|
||||
}
|
||||
@@ -2063,100 +2219,7 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
||||
selector,
|
||||
ref cases,
|
||||
} => {
|
||||
// Start the switch
|
||||
write!(self.out, "{level}")?;
|
||||
write!(self.out, "switch(")?;
|
||||
self.write_expr(module, selector, func_ctx)?;
|
||||
writeln!(self.out, ") {{")?;
|
||||
|
||||
// Write all cases
|
||||
let indent_level_1 = level.next();
|
||||
let indent_level_2 = indent_level_1.next();
|
||||
|
||||
for (i, case) in cases.iter().enumerate() {
|
||||
match case.value {
|
||||
crate::SwitchValue::I32(value) => {
|
||||
write!(self.out, "{indent_level_1}case {value}:")?
|
||||
}
|
||||
crate::SwitchValue::U32(value) => {
|
||||
write!(self.out, "{indent_level_1}case {value}u:")?
|
||||
}
|
||||
crate::SwitchValue::Default => {
|
||||
write!(self.out, "{indent_level_1}default:")?
|
||||
}
|
||||
}
|
||||
|
||||
// The new block is not only stylistic, it plays a role here:
|
||||
// We might end up having to write the same case body
|
||||
// multiple times due to FXC not supporting fallthrough.
|
||||
// Therefore, some `Expression`s written by `Statement::Emit`
|
||||
// will end up having the same name (`_expr<handle_index>`).
|
||||
// So we need to put each case in its own scope.
|
||||
let write_block_braces = !(case.fall_through && case.body.is_empty());
|
||||
if write_block_braces {
|
||||
writeln!(self.out, " {{")?;
|
||||
} else {
|
||||
writeln!(self.out)?;
|
||||
}
|
||||
|
||||
// Although FXC does support a series of case clauses before
|
||||
// a block[^yes], it does not support fallthrough from a
|
||||
// non-empty case block to the next[^no]. If this case has a
|
||||
// non-empty body with a fallthrough, emulate that by
|
||||
// duplicating the bodies of all the cases it would fall
|
||||
// into as extensions of this case's own body. This makes
|
||||
// the HLSL output potentially quadratic in the size of the
|
||||
// Naga IR.
|
||||
//
|
||||
// [^yes]: ```hlsl
|
||||
// case 1:
|
||||
// case 2: do_stuff()
|
||||
// ```
|
||||
// [^no]: ```hlsl
|
||||
// case 1: do_this();
|
||||
// case 2: do_that();
|
||||
// ```
|
||||
if case.fall_through && !case.body.is_empty() {
|
||||
let curr_len = i + 1;
|
||||
let end_case_idx = curr_len
|
||||
+ cases
|
||||
.iter()
|
||||
.skip(curr_len)
|
||||
.position(|case| !case.fall_through)
|
||||
.unwrap();
|
||||
let indent_level_3 = indent_level_2.next();
|
||||
for case in &cases[i..=end_case_idx] {
|
||||
writeln!(self.out, "{indent_level_2}{{")?;
|
||||
let prev_len = self.named_expressions.len();
|
||||
for sta in case.body.iter() {
|
||||
self.write_stmt(module, sta, func_ctx, indent_level_3)?;
|
||||
}
|
||||
// Clear all named expressions that were previously inserted by the statements in the block
|
||||
self.named_expressions.truncate(prev_len);
|
||||
writeln!(self.out, "{indent_level_2}}}")?;
|
||||
}
|
||||
|
||||
let last_case = &cases[end_case_idx];
|
||||
if last_case.body.last().map_or(true, |s| !s.is_terminator()) {
|
||||
writeln!(self.out, "{indent_level_2}break;")?;
|
||||
}
|
||||
} else {
|
||||
for sta in case.body.iter() {
|
||||
self.write_stmt(module, sta, func_ctx, indent_level_2)?;
|
||||
}
|
||||
if !case.fall_through
|
||||
&& case.body.last().map_or(true, |s| !s.is_terminator())
|
||||
{
|
||||
writeln!(self.out, "{indent_level_2}break;")?;
|
||||
}
|
||||
}
|
||||
|
||||
if write_block_braces {
|
||||
writeln!(self.out, "{indent_level_1}}}")?;
|
||||
}
|
||||
}
|
||||
|
||||
writeln!(self.out, "{level}}}")?
|
||||
self.write_switch(module, func_ctx, level, selector, cases)?;
|
||||
}
|
||||
Statement::RayQuery { .. } => unreachable!(),
|
||||
Statement::SubgroupBallot { result, predicate } => {
|
||||
@@ -3000,8 +3063,8 @@ impl<'a, W: fmt::Write> super::Writer<'a, W> {
|
||||
Mf::CountLeadingZeros => Function::CountLeadingZeros,
|
||||
Mf::CountOneBits => Function::MissingIntOverload("countbits"),
|
||||
Mf::ReverseBits => Function::MissingIntOverload("reversebits"),
|
||||
Mf::FindLsb => Function::MissingIntReturnType("firstbitlow"),
|
||||
Mf::FindMsb => Function::MissingIntReturnType("firstbithigh"),
|
||||
Mf::FirstTrailingBit => Function::MissingIntReturnType("firstbitlow"),
|
||||
Mf::FirstLeadingBit => Function::MissingIntReturnType("firstbithigh"),
|
||||
Mf::ExtractBits => Function::Regular(EXTRACT_BITS_FUNCTION),
|
||||
Mf::InsertBits => Function::Regular(INSERT_BITS_FUNCTION),
|
||||
// Data Packing
|
||||
|
||||
3
third_party/rust/naga/src/back/mod.rs
vendored
3
third_party/rust/naga/src/back/mod.rs
vendored
@@ -19,6 +19,9 @@ pub mod wgsl;
|
||||
#[cfg(any(hlsl_out, msl_out, spv_out, glsl_out))]
|
||||
pub mod pipeline_constants;
|
||||
|
||||
#[cfg(any(hlsl_out, glsl_out))]
|
||||
mod continue_forward;
|
||||
|
||||
/// Names of vector components.
|
||||
pub const COMPONENTS: &[char] = &['x', 'y', 'z', 'w'];
|
||||
/// Indent for backends.
|
||||
|
||||
4
third_party/rust/naga/src/back/msl/mod.rs
vendored
4
third_party/rust/naga/src/back/msl/mod.rs
vendored
@@ -354,7 +354,9 @@ pub struct PipelineOptions {
|
||||
/// to receive the vertex buffers, lengths, and vertex id as args,
|
||||
/// and bounds-check the vertex id and use the index into the
|
||||
/// vertex buffers to access attributes, rather than using Metal's
|
||||
/// [[stage-in]] assembled attribute data.
|
||||
/// [[stage-in]] assembled attribute data. This is true by default,
|
||||
/// but remains configurable for use by tests via deserialization
|
||||
/// of this struct. There is no user-facing way to set this value.
|
||||
pub vertex_pulling_transform: bool,
|
||||
|
||||
/// vertex_buffer_mappings are used during shader translation to
|
||||
|
||||
117
third_party/rust/naga/src/back/msl/writer.rs
vendored
117
third_party/rust/naga/src/back/msl/writer.rs
vendored
@@ -1063,43 +1063,6 @@ impl<W: Write> Writer<W> {
|
||||
address: &TexelAddress,
|
||||
value: Handle<crate::Expression>,
|
||||
context: &StatementContext,
|
||||
) -> BackendResult {
|
||||
match context.expression.policies.image_store {
|
||||
proc::BoundsCheckPolicy::Restrict => {
|
||||
// We don't have a restricted level value, because we don't
|
||||
// support writes to mipmapped textures.
|
||||
debug_assert!(address.level.is_none());
|
||||
|
||||
write!(self.out, "{level}")?;
|
||||
self.put_expression(image, &context.expression, false)?;
|
||||
write!(self.out, ".write(")?;
|
||||
self.put_expression(value, &context.expression, true)?;
|
||||
write!(self.out, ", ")?;
|
||||
self.put_restricted_texel_address(image, address, &context.expression)?;
|
||||
writeln!(self.out, ");")?;
|
||||
}
|
||||
proc::BoundsCheckPolicy::ReadZeroSkipWrite => {
|
||||
write!(self.out, "{level}if (")?;
|
||||
self.put_image_access_bounds_check(image, address, &context.expression)?;
|
||||
writeln!(self.out, ") {{")?;
|
||||
self.put_unchecked_image_store(level.next(), image, address, value, context)?;
|
||||
writeln!(self.out, "{level}}}")?;
|
||||
}
|
||||
proc::BoundsCheckPolicy::Unchecked => {
|
||||
self.put_unchecked_image_store(level, image, address, value, context)?;
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn put_unchecked_image_store(
|
||||
&mut self,
|
||||
level: back::Level,
|
||||
image: Handle<crate::Expression>,
|
||||
address: &TexelAddress,
|
||||
value: Handle<crate::Expression>,
|
||||
context: &StatementContext,
|
||||
) -> BackendResult {
|
||||
write!(self.out, "{level}")?;
|
||||
self.put_expression(image, &context.expression, false)?;
|
||||
@@ -1235,7 +1198,7 @@ impl<W: Write> Writer<W> {
|
||||
// with different precedences from applying earlier.
|
||||
write!(self.out, "(")?;
|
||||
|
||||
// Cycle trough all the components of the vector
|
||||
// Cycle through all the components of the vector
|
||||
for index in 0..size {
|
||||
let component = back::COMPONENTS[index];
|
||||
// Write the addition to the previous product
|
||||
@@ -1875,8 +1838,8 @@ impl<W: Write> Writer<W> {
|
||||
Mf::ReverseBits => "reverse_bits",
|
||||
Mf::ExtractBits => "",
|
||||
Mf::InsertBits => "",
|
||||
Mf::FindLsb => "",
|
||||
Mf::FindMsb => "",
|
||||
Mf::FirstTrailingBit => "",
|
||||
Mf::FirstLeadingBit => "",
|
||||
// data packing
|
||||
Mf::Pack4x8snorm => "pack_float_to_snorm4x8",
|
||||
Mf::Pack4x8unorm => "pack_float_to_unorm4x8",
|
||||
@@ -1920,7 +1883,7 @@ impl<W: Write> Writer<W> {
|
||||
self.put_expression(arg1.unwrap(), context, false)?;
|
||||
write!(self.out, ")")?;
|
||||
}
|
||||
Mf::FindLsb => {
|
||||
Mf::FirstTrailingBit => {
|
||||
let scalar = context.resolve_type(arg).scalar().unwrap();
|
||||
let constant = scalar.width * 8 + 1;
|
||||
|
||||
@@ -1928,7 +1891,7 @@ impl<W: Write> Writer<W> {
|
||||
self.put_expression(arg, context, true)?;
|
||||
write!(self.out, ") + 1) % {constant}) - 1)")?;
|
||||
}
|
||||
Mf::FindMsb => {
|
||||
Mf::FirstLeadingBit => {
|
||||
let inner = context.resolve_type(arg);
|
||||
let scalar = inner.scalar().unwrap();
|
||||
let constant = scalar.width * 8 - 1;
|
||||
@@ -2702,7 +2665,7 @@ impl<W: Write> Writer<W> {
|
||||
}
|
||||
}
|
||||
}
|
||||
crate::MathFunction::FindMsb
|
||||
crate::MathFunction::FirstLeadingBit
|
||||
| crate::MathFunction::Pack4xI8
|
||||
| crate::MathFunction::Pack4xU8
|
||||
| crate::MathFunction::Unpack4xI8
|
||||
@@ -3953,8 +3916,8 @@ impl<W: Write> Writer<W> {
|
||||
)?;
|
||||
writeln!(
|
||||
self.out,
|
||||
"{}return metal::float2((float(b0) - 128.0f) / 255.0f, \
|
||||
(float(b1) - 128.0f) / 255.0f);",
|
||||
"{}return metal::float2(metal::max(-1.0f, as_type<char>(b0) / 127.0f), \
|
||||
metal::max(-1.0f, as_type<char>(b1) / 127.0f));",
|
||||
back::INDENT
|
||||
)?;
|
||||
writeln!(self.out, "}}")?;
|
||||
@@ -3971,10 +3934,10 @@ impl<W: Write> Writer<W> {
|
||||
)?;
|
||||
writeln!(
|
||||
self.out,
|
||||
"{}return metal::float4((float(b0) - 128.0f) / 255.0f, \
|
||||
(float(b1) - 128.0f) / 255.0f, \
|
||||
(float(b2) - 128.0f) / 255.0f, \
|
||||
(float(b3) - 128.0f) / 255.0f);",
|
||||
"{}return metal::float4(metal::max(-1.0f, as_type<char>(b0) / 127.0f), \
|
||||
metal::max(-1.0f, as_type<char>(b1) / 127.0f), \
|
||||
metal::max(-1.0f, as_type<char>(b2) / 127.0f), \
|
||||
metal::max(-1.0f, as_type<char>(b3) / 127.0f));",
|
||||
back::INDENT
|
||||
)?;
|
||||
writeln!(self.out, "}}")?;
|
||||
@@ -4033,8 +3996,8 @@ impl<W: Write> Writer<W> {
|
||||
)?;
|
||||
writeln!(
|
||||
self.out,
|
||||
"{}return metal::int2(as_type<metal::short>(b1 << 8 | b0), \
|
||||
as_type<metal::short>(b3 << 8 | b2));",
|
||||
"{}return metal::int2(as_type<short>(metal::ushort(b1 << 8 | b0)), \
|
||||
as_type<short>(metal::ushort(b3 << 8 | b2)));",
|
||||
back::INDENT
|
||||
)?;
|
||||
writeln!(self.out, "}}")?;
|
||||
@@ -4055,10 +4018,10 @@ impl<W: Write> Writer<W> {
|
||||
)?;
|
||||
writeln!(
|
||||
self.out,
|
||||
"{}return metal::int4(as_type<metal::short>(b1 << 8 | b0), \
|
||||
as_type<metal::short>(b3 << 8 | b2), \
|
||||
as_type<metal::short>(b5 << 8 | b4), \
|
||||
as_type<metal::short>(b7 << 8 | b6));",
|
||||
"{}return metal::int4(as_type<short>(metal::ushort(b1 << 8 | b0)), \
|
||||
as_type<short>(metal::ushort(b3 << 8 | b2)), \
|
||||
as_type<short>(metal::ushort(b5 << 8 | b4)), \
|
||||
as_type<short>(metal::ushort(b7 << 8 | b6)));",
|
||||
back::INDENT
|
||||
)?;
|
||||
writeln!(self.out, "}}")?;
|
||||
@@ -4117,8 +4080,7 @@ impl<W: Write> Writer<W> {
|
||||
)?;
|
||||
writeln!(
|
||||
self.out,
|
||||
"{}return metal::float2((float(b1 << 8 | b0) - 32767.0f) / 65535.0f, \
|
||||
(float(b3 << 8 | b2) - 32767.0f) / 65535.0f);",
|
||||
"{}return metal::unpack_snorm2x16_to_float(b1 << 24 | b0 << 16 | b3 << 8 | b2);",
|
||||
back::INDENT
|
||||
)?;
|
||||
writeln!(self.out, "}}")?;
|
||||
@@ -4139,10 +4101,8 @@ impl<W: Write> Writer<W> {
|
||||
)?;
|
||||
writeln!(
|
||||
self.out,
|
||||
"{}return metal::float4((float(b1 << 8 | b0) - 32767.0f) / 65535.0f, \
|
||||
(float(b3 << 8 | b2) - 32767.0f) / 65535.0f, \
|
||||
(float(b5 << 8 | b4) - 32767.0f) / 65535.0f, \
|
||||
(float(b7 << 8 | b6) - 32767.0f) / 65535.0f);",
|
||||
"{}return metal::float4(metal::unpack_snorm2x16_to_float(b1 << 24 | b0 << 16 | b3 << 8 | b2), \
|
||||
metal::unpack_snorm2x16_to_float(b5 << 24 | b4 << 16 | b7 << 8 | b6));",
|
||||
back::INDENT
|
||||
)?;
|
||||
writeln!(self.out, "}}")?;
|
||||
@@ -4159,8 +4119,8 @@ impl<W: Write> Writer<W> {
|
||||
)?;
|
||||
writeln!(
|
||||
self.out,
|
||||
"{}return metal::float2(as_type<metal::half>(b1 << 8 | b0), \
|
||||
as_type<metal::half>(b3 << 8 | b2));",
|
||||
"{}return metal::float2(as_type<half>(metal::ushort(b1 << 8 | b0)), \
|
||||
as_type<half>(metal::ushort(b3 << 8 | b2)));",
|
||||
back::INDENT
|
||||
)?;
|
||||
writeln!(self.out, "}}")?;
|
||||
@@ -4170,7 +4130,7 @@ impl<W: Write> Writer<W> {
|
||||
let name = self.namer.call("unpackFloat16x4");
|
||||
writeln!(
|
||||
self.out,
|
||||
"metal::int4 {name}(metal::ushort b0, \
|
||||
"metal::float4 {name}(metal::ushort b0, \
|
||||
metal::ushort b1, \
|
||||
metal::ushort b2, \
|
||||
metal::ushort b3, \
|
||||
@@ -4181,10 +4141,10 @@ impl<W: Write> Writer<W> {
|
||||
)?;
|
||||
writeln!(
|
||||
self.out,
|
||||
"{}return metal::int4(as_type<metal::half>(b1 << 8 | b0), \
|
||||
as_type<metal::half>(b3 << 8 | b2), \
|
||||
as_type<metal::half>(b5 << 8 | b4), \
|
||||
as_type<metal::half>(b7 << 8 | b6));",
|
||||
"{}return metal::float4(as_type<half>(metal::ushort(b1 << 8 | b0)), \
|
||||
as_type<half>(metal::ushort(b3 << 8 | b2)), \
|
||||
as_type<half>(metal::ushort(b5 << 8 | b4)), \
|
||||
as_type<half>(metal::ushort(b7 << 8 | b6)));",
|
||||
back::INDENT
|
||||
)?;
|
||||
writeln!(self.out, "}}")?;
|
||||
@@ -4390,10 +4350,10 @@ impl<W: Write> Writer<W> {
|
||||
let name = self.namer.call("unpackSint32");
|
||||
writeln!(
|
||||
self.out,
|
||||
"metal::int {name}(uint b0, \
|
||||
uint b1, \
|
||||
uint b2, \
|
||||
uint b3) {{"
|
||||
"int {name}(uint b0, \
|
||||
uint b1, \
|
||||
uint b2, \
|
||||
uint b3) {{"
|
||||
)?;
|
||||
writeln!(
|
||||
self.out,
|
||||
@@ -4495,7 +4455,18 @@ impl<W: Write> Writer<W> {
|
||||
)?;
|
||||
writeln!(
|
||||
self.out,
|
||||
"{}return unpack_unorm10a2_to_float(b3 << 24 | b2 << 16 | b1 << 8 | b0);",
|
||||
// The following is correct for RGBA packing, but our format seems to
|
||||
// match ABGR, which can be fed into the Metal builtin function
|
||||
// unpack_unorm10a2_to_float.
|
||||
/*
|
||||
"{}uint v = (b3 << 24 | b2 << 16 | b1 << 8 | b0); \
|
||||
uint r = (v & 0xFFC00000) >> 22; \
|
||||
uint g = (v & 0x003FF000) >> 12; \
|
||||
uint b = (v & 0x00000FFC) >> 2; \
|
||||
uint a = (v & 0x00000003); \
|
||||
return metal::float4(float(r) / 1023.0f, float(g) / 1023.0f, float(b) / 1023.0f, float(a) / 3.0f);",
|
||||
*/
|
||||
"{}return metal::unpack_unorm10a2_to_float(b3 << 24 | b2 << 16 | b1 << 8 | b0);",
|
||||
back::INDENT
|
||||
)?;
|
||||
writeln!(self.out, "}}")?;
|
||||
|
||||
6
third_party/rust/naga/src/back/spv/block.rs
vendored
6
third_party/rust/naga/src/back/spv/block.rs
vendored
@@ -1183,13 +1183,13 @@ impl<'w> BlockContext<'w> {
|
||||
count_id,
|
||||
))
|
||||
}
|
||||
Mf::FindLsb => MathOp::Ext(spirv::GLOp::FindILsb),
|
||||
Mf::FindMsb => {
|
||||
Mf::FirstTrailingBit => MathOp::Ext(spirv::GLOp::FindILsb),
|
||||
Mf::FirstLeadingBit => {
|
||||
if arg_ty.scalar_width() == Some(4) {
|
||||
let thing = match arg_scalar_kind {
|
||||
Some(crate::ScalarKind::Uint) => spirv::GLOp::FindUMsb,
|
||||
Some(crate::ScalarKind::Sint) => spirv::GLOp::FindSMsb,
|
||||
other => unimplemented!("Unexpected findMSB({:?})", other),
|
||||
other => unimplemented!("Unexpected firstLeadingBit({:?})", other),
|
||||
};
|
||||
MathOp::Ext(thing)
|
||||
} else {
|
||||
|
||||
33
third_party/rust/naga/src/back/spv/image.rs
vendored
33
third_party/rust/naga/src/back/spv/image.rs
vendored
@@ -1178,32 +1178,13 @@ impl<'w> BlockContext<'w> {
|
||||
_ => {}
|
||||
}
|
||||
|
||||
match self.writer.bounds_check_policies.image_store {
|
||||
crate::proc::BoundsCheckPolicy::Restrict => {
|
||||
let (coords, _, _) =
|
||||
self.write_restricted_coordinates(image_id, coordinates, None, None, block)?;
|
||||
write.generate(&mut self.writer.id_gen, coords, None, None, block);
|
||||
}
|
||||
crate::proc::BoundsCheckPolicy::ReadZeroSkipWrite => {
|
||||
self.write_conditional_image_access(
|
||||
image_id,
|
||||
coordinates,
|
||||
None,
|
||||
None,
|
||||
block,
|
||||
&write,
|
||||
)?;
|
||||
}
|
||||
crate::proc::BoundsCheckPolicy::Unchecked => {
|
||||
write.generate(
|
||||
&mut self.writer.id_gen,
|
||||
coordinates.value_id,
|
||||
None,
|
||||
None,
|
||||
block,
|
||||
);
|
||||
}
|
||||
}
|
||||
write.generate(
|
||||
&mut self.writer.id_gen,
|
||||
coordinates.value_id,
|
||||
None,
|
||||
None,
|
||||
block,
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1710,8 +1710,8 @@ impl<W: Write> Writer<W> {
|
||||
Mf::ReverseBits => Function::Regular("reverseBits"),
|
||||
Mf::ExtractBits => Function::Regular("extractBits"),
|
||||
Mf::InsertBits => Function::Regular("insertBits"),
|
||||
Mf::FindLsb => Function::Regular("firstTrailingBit"),
|
||||
Mf::FindMsb => Function::Regular("firstLeadingBit"),
|
||||
Mf::FirstTrailingBit => Function::Regular("firstTrailingBit"),
|
||||
Mf::FirstLeadingBit => Function::Regular("firstLeadingBit"),
|
||||
// data packing
|
||||
Mf::Pack4x8snorm => Function::Regular("pack4x8snorm"),
|
||||
Mf::Pack4x8unorm => Function::Regular("pack4x8unorm"),
|
||||
|
||||
@@ -3,7 +3,6 @@ use crate::arena::{Arena, Handle};
|
||||
|
||||
pub struct ExpressionTracer<'tracer> {
|
||||
pub constants: &'tracer Arena<crate::Constant>,
|
||||
pub overrides: &'tracer Arena<crate::Override>,
|
||||
|
||||
/// The arena in which we are currently tracing expressions.
|
||||
pub expressions: &'tracer Arena<crate::Expression>,
|
||||
|
||||
@@ -4,7 +4,6 @@ use super::{FunctionMap, ModuleMap};
|
||||
pub struct FunctionTracer<'a> {
|
||||
pub function: &'a crate::Function,
|
||||
pub constants: &'a crate::Arena<crate::Constant>,
|
||||
pub overrides: &'a crate::Arena<crate::Override>,
|
||||
|
||||
pub types_used: &'a mut HandleSet<crate::Type>,
|
||||
pub constants_used: &'a mut HandleSet<crate::Constant>,
|
||||
@@ -48,7 +47,6 @@ impl<'a> FunctionTracer<'a> {
|
||||
fn as_expression(&mut self) -> super::expressions::ExpressionTracer {
|
||||
super::expressions::ExpressionTracer {
|
||||
constants: self.constants,
|
||||
overrides: self.overrides,
|
||||
expressions: &self.function.expressions,
|
||||
|
||||
types_used: self.types_used,
|
||||
|
||||
2
third_party/rust/naga/src/compact/mod.rs
vendored
2
third_party/rust/naga/src/compact/mod.rs
vendored
@@ -253,7 +253,6 @@ impl<'module> ModuleTracer<'module> {
|
||||
expressions::ExpressionTracer {
|
||||
expressions: &self.module.global_expressions,
|
||||
constants: &self.module.constants,
|
||||
overrides: &self.module.overrides,
|
||||
types_used: &mut self.types_used,
|
||||
constants_used: &mut self.constants_used,
|
||||
expressions_used: &mut self.global_expressions_used,
|
||||
@@ -268,7 +267,6 @@ impl<'module> ModuleTracer<'module> {
|
||||
FunctionTracer {
|
||||
function,
|
||||
constants: &self.module.constants,
|
||||
overrides: &self.module.overrides,
|
||||
types_used: &mut self.types_used,
|
||||
constants_used: &mut self.constants_used,
|
||||
global_expressions_used: &mut self.global_expressions_used,
|
||||
|
||||
16
third_party/rust/naga/src/front/glsl/builtins.rs
vendored
16
third_party/rust/naga/src/front/glsl/builtins.rs
vendored
@@ -646,8 +646,8 @@ fn inject_standard_builtins(
|
||||
"bitfieldReverse" => MathFunction::ReverseBits,
|
||||
"bitfieldExtract" => MathFunction::ExtractBits,
|
||||
"bitfieldInsert" => MathFunction::InsertBits,
|
||||
"findLSB" => MathFunction::FindLsb,
|
||||
"findMSB" => MathFunction::FindMsb,
|
||||
"findLSB" => MathFunction::FirstTrailingBit,
|
||||
"findMSB" => MathFunction::FirstLeadingBit,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
@@ -695,8 +695,12 @@ fn inject_standard_builtins(
|
||||
// we need to cast the return type of findLsb / findMsb
|
||||
let mc = if scalar.kind == Sk::Uint {
|
||||
match mc {
|
||||
MacroCall::MathFunction(MathFunction::FindLsb) => MacroCall::FindLsbUint,
|
||||
MacroCall::MathFunction(MathFunction::FindMsb) => MacroCall::FindMsbUint,
|
||||
MacroCall::MathFunction(MathFunction::FirstTrailingBit) => {
|
||||
MacroCall::FindLsbUint
|
||||
}
|
||||
MacroCall::MathFunction(MathFunction::FirstLeadingBit) => {
|
||||
MacroCall::FindMsbUint
|
||||
}
|
||||
mc => mc,
|
||||
}
|
||||
} else {
|
||||
@@ -1787,8 +1791,8 @@ impl MacroCall {
|
||||
)?,
|
||||
mc @ (MacroCall::FindLsbUint | MacroCall::FindMsbUint) => {
|
||||
let fun = match mc {
|
||||
MacroCall::FindLsbUint => MathFunction::FindLsb,
|
||||
MacroCall::FindMsbUint => MathFunction::FindMsb,
|
||||
MacroCall::FindLsbUint => MathFunction::FirstTrailingBit,
|
||||
MacroCall::FindMsbUint => MathFunction::FirstLeadingBit,
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let res = ctx.add_expression(
|
||||
|
||||
2
third_party/rust/naga/src/front/mod.rs
vendored
2
third_party/rust/naga/src/front/mod.rs
vendored
@@ -275,7 +275,7 @@ where
|
||||
Name: std::borrow::Borrow<Q>,
|
||||
Q: std::hash::Hash + Eq + ?Sized,
|
||||
{
|
||||
// Iterate backwards trough the scopes and try to find the variable
|
||||
// Iterate backwards through the scopes and try to find the variable
|
||||
for scope in self.scopes[..self.cursor].iter().rev() {
|
||||
if let Some(var) = scope.get(name) {
|
||||
return Some(var);
|
||||
|
||||
6
third_party/rust/naga/src/front/spv/mod.rs
vendored
6
third_party/rust/naga/src/front/spv/mod.rs
vendored
@@ -3026,8 +3026,8 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
|
||||
Glo::UnpackHalf2x16 => Mf::Unpack2x16float,
|
||||
Glo::UnpackUnorm2x16 => Mf::Unpack2x16unorm,
|
||||
Glo::UnpackSnorm2x16 => Mf::Unpack2x16snorm,
|
||||
Glo::FindILsb => Mf::FindLsb,
|
||||
Glo::FindUMsb | Glo::FindSMsb => Mf::FindMsb,
|
||||
Glo::FindILsb => Mf::FirstTrailingBit,
|
||||
Glo::FindUMsb | Glo::FindSMsb => Mf::FirstLeadingBit,
|
||||
// TODO: https://github.com/gfx-rs/naga/issues/2526
|
||||
Glo::Modf | Glo::Frexp => return Err(Error::UnsupportedExtInst(inst_id)),
|
||||
Glo::IMix
|
||||
@@ -3460,7 +3460,7 @@ impl<I: Iterator<Item = u32>> Frontend<I> {
|
||||
.insert(target, (case_body_idx, vec![literal as i32]));
|
||||
}
|
||||
|
||||
// Loop trough the collected target blocks creating a new case for each
|
||||
// Loop through the collected target blocks creating a new case for each
|
||||
// literal pointing to it, only one case will have the true body and all the
|
||||
// others will be empty fallthrough so that they all execute the same body
|
||||
// without duplicating code.
|
||||
|
||||
@@ -117,33 +117,6 @@ pub struct Function<'a> {
|
||||
pub name: Ident<'a>,
|
||||
pub arguments: Vec<FunctionArgument<'a>>,
|
||||
pub result: Option<FunctionResult<'a>>,
|
||||
|
||||
/// Local variable and function argument arena.
|
||||
///
|
||||
/// Note that the `Local` here is actually a zero-sized type. The AST keeps
|
||||
/// all the detailed information about locals - names, types, etc. - in
|
||||
/// [`LocalDecl`] statements. For arguments, that information is kept in
|
||||
/// [`arguments`]. This `Arena`'s only role is to assign a unique `Handle`
|
||||
/// to each of them, and track their definitions' spans for use in
|
||||
/// diagnostics.
|
||||
///
|
||||
/// In the AST, when an [`Ident`] expression refers to a local variable or
|
||||
/// argument, its [`IdentExpr`] holds the referent's `Handle<Local>` in this
|
||||
/// arena.
|
||||
///
|
||||
/// During lowering, [`LocalDecl`] statements add entries to a per-function
|
||||
/// table that maps `Handle<Local>` values to their Naga representations,
|
||||
/// accessed via [`StatementContext::local_table`] and
|
||||
/// [`RuntimeExpressionContext::local_table`]. This table is then consulted when
|
||||
/// lowering subsequent [`Ident`] expressions.
|
||||
///
|
||||
/// [`LocalDecl`]: StatementKind::LocalDecl
|
||||
/// [`arguments`]: Function::arguments
|
||||
/// [`Ident`]: Expression::Ident
|
||||
/// [`StatementContext::local_table`]: StatementContext::local_table
|
||||
/// [`RuntimeExpressionContext::local_table`]: RuntimeExpressionContext::local_table
|
||||
pub locals: Arena<Local>,
|
||||
|
||||
pub body: Block<'a>,
|
||||
}
|
||||
|
||||
|
||||
@@ -235,8 +235,8 @@ pub fn map_standard_fun(word: &str) -> Option<crate::MathFunction> {
|
||||
"reverseBits" => Mf::ReverseBits,
|
||||
"extractBits" => Mf::ExtractBits,
|
||||
"insertBits" => Mf::InsertBits,
|
||||
"firstTrailingBit" => Mf::FindLsb,
|
||||
"firstLeadingBit" => Mf::FindMsb,
|
||||
"firstTrailingBit" => Mf::FirstTrailingBit,
|
||||
"firstLeadingBit" => Mf::FirstLeadingBit,
|
||||
// data packing
|
||||
"pack4x8snorm" => Mf::Pack4x8snorm,
|
||||
"pack4x8unorm" => Mf::Pack4x8unorm,
|
||||
|
||||
@@ -37,9 +37,30 @@ struct ExpressionContext<'input, 'temp, 'out> {
|
||||
/// [`Function::locals`]: ast::Function::locals
|
||||
local_table: &'temp mut SymbolTable<&'input str, Handle<ast::Local>>,
|
||||
|
||||
/// The [`Function::locals`] arena for the function we're building.
|
||||
/// Local variable and function argument arena for the function we're building.
|
||||
///
|
||||
/// [`Function::locals`]: ast::Function::locals
|
||||
/// Note that the `Local` here is actually a zero-sized type. The AST keeps
|
||||
/// all the detailed information about locals - names, types, etc. - in
|
||||
/// [`LocalDecl`] statements. For arguments, that information is kept in
|
||||
/// [`arguments`]. This `Arena`'s only role is to assign a unique `Handle`
|
||||
/// to each of them, and track their definitions' spans for use in
|
||||
/// diagnostics.
|
||||
///
|
||||
/// In the AST, when an [`Ident`] expression refers to a local variable or
|
||||
/// argument, its [`IdentExpr`] holds the referent's `Handle<Local>` in this
|
||||
/// arena.
|
||||
///
|
||||
/// During lowering, [`LocalDecl`] statements add entries to a per-function
|
||||
/// table that maps `Handle<Local>` values to their Naga representations,
|
||||
/// accessed via [`StatementContext::local_table`] and
|
||||
/// [`RuntimeExpressionContext::local_table`]. This table is then consulted when
|
||||
/// lowering subsequent [`Ident`] expressions.
|
||||
///
|
||||
/// [`LocalDecl`]: StatementKind::LocalDecl
|
||||
/// [`arguments`]: Function::arguments
|
||||
/// [`Ident`]: Expression::Ident
|
||||
/// [`StatementContext::local_table`]: StatementContext::local_table
|
||||
/// [`RuntimeExpressionContext::local_table`]: RuntimeExpressionContext::local_table
|
||||
locals: &'out mut Arena<ast::Local>,
|
||||
|
||||
/// Identifiers used by the current global declaration that have no local definition.
|
||||
@@ -2158,7 +2179,6 @@ impl Parser {
|
||||
arguments,
|
||||
result,
|
||||
body,
|
||||
locals,
|
||||
};
|
||||
|
||||
// done
|
||||
|
||||
16
third_party/rust/naga/src/lib.rs
vendored
16
third_party/rust/naga/src/lib.rs
vendored
@@ -873,7 +873,7 @@ pub enum Literal {
|
||||
}
|
||||
|
||||
/// Pipeline-overridable constant.
|
||||
#[derive(Debug, Clone)]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
#[cfg_attr(feature = "serialize", derive(Serialize))]
|
||||
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
|
||||
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
|
||||
@@ -891,8 +891,7 @@ pub struct Override {
|
||||
}
|
||||
|
||||
/// Constant value.
|
||||
#[derive(Debug, Clone)]
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
#[cfg_attr(feature = "serialize", derive(Serialize))]
|
||||
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
|
||||
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
|
||||
@@ -954,7 +953,7 @@ pub struct ResourceBinding {
|
||||
}
|
||||
|
||||
/// Variable defined at module level.
|
||||
#[derive(Clone, Debug)]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
#[cfg_attr(feature = "serialize", derive(Serialize))]
|
||||
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
|
||||
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
|
||||
@@ -1198,8 +1197,8 @@ pub enum MathFunction {
|
||||
ReverseBits,
|
||||
ExtractBits,
|
||||
InsertBits,
|
||||
FindLsb,
|
||||
FindMsb,
|
||||
FirstTrailingBit,
|
||||
FirstLeadingBit,
|
||||
// data packing
|
||||
Pack4x8snorm,
|
||||
Pack4x8unorm,
|
||||
@@ -1337,7 +1336,7 @@ bitflags::bitflags! {
|
||||
const STORAGE = 1 << 0;
|
||||
/// Barrier affects all [`AddressSpace::WorkGroup`] accesses.
|
||||
const WORK_GROUP = 1 << 1;
|
||||
/// Barrier synchronizes execution across all invocations within a subgroup that exectue this instruction.
|
||||
/// Barrier synchronizes execution across all invocations within a subgroup that execute this instruction.
|
||||
const SUB_GROUP = 1 << 2;
|
||||
}
|
||||
}
|
||||
@@ -1354,8 +1353,7 @@ bitflags::bitflags! {
|
||||
///
|
||||
/// [`Constant`]: Expression::Constant
|
||||
/// [`Override`]: Expression::Override
|
||||
#[derive(Clone, Debug)]
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
#[cfg_attr(feature = "serialize", derive(Serialize))]
|
||||
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
|
||||
#[cfg_attr(feature = "arbitrary", derive(Arbitrary))]
|
||||
|
||||
176
third_party/rust/naga/src/proc/constant_evaluator.rs
vendored
176
third_party/rust/naga/src/proc/constant_evaluator.rs
vendored
@@ -27,6 +27,8 @@ macro_rules! gen_component_wise_extractor {
|
||||
scalar_kinds: [$( $scalar_kind:ident ),* $(,)?],
|
||||
) => {
|
||||
/// A subset of [`Literal`]s intended to be used for implementing numeric built-ins.
|
||||
#[derive(Debug)]
|
||||
#[cfg_attr(test, derive(PartialEq))]
|
||||
enum $target<const N: usize> {
|
||||
$(
|
||||
#[doc = concat!(
|
||||
@@ -1231,6 +1233,12 @@ impl<'a> ConstantEvaluator<'a> {
|
||||
crate::MathFunction::ReverseBits => {
|
||||
component_wise_concrete_int!(self, span, [arg], |e| { Ok([e.reverse_bits()]) })
|
||||
}
|
||||
crate::MathFunction::FirstTrailingBit => {
|
||||
component_wise_concrete_int(self, span, [arg], |ci| Ok(first_trailing_bit(ci)))
|
||||
}
|
||||
crate::MathFunction::FirstLeadingBit => {
|
||||
component_wise_concrete_int(self, span, [arg], |ci| Ok(first_leading_bit(ci)))
|
||||
}
|
||||
|
||||
fun => Err(ConstantEvaluatorError::NotImplemented(format!(
|
||||
"{fun:?} built-in function"
|
||||
@@ -2096,6 +2104,174 @@ impl<'a> ConstantEvaluator<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
fn first_trailing_bit(concrete_int: ConcreteInt<1>) -> ConcreteInt<1> {
|
||||
// NOTE: Bit indices for this built-in start at 0 at the "right" (or LSB). For example, a value
|
||||
// of 1 means the least significant bit is set. Therefore, an input of `0x[80 00…]` would
|
||||
// return a right-to-left bit index of 0.
|
||||
let trailing_zeros_to_bit_idx = |e: u32| -> u32 {
|
||||
match e {
|
||||
idx @ 0..=31 => idx,
|
||||
32 => u32::MAX,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
};
|
||||
match concrete_int {
|
||||
ConcreteInt::U32([e]) => ConcreteInt::U32([trailing_zeros_to_bit_idx(e.trailing_zeros())]),
|
||||
ConcreteInt::I32([e]) => {
|
||||
ConcreteInt::I32([trailing_zeros_to_bit_idx(e.trailing_zeros()) as i32])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn first_trailing_bit_smoke() {
|
||||
assert_eq!(
|
||||
first_trailing_bit(ConcreteInt::I32([0])),
|
||||
ConcreteInt::I32([-1])
|
||||
);
|
||||
assert_eq!(
|
||||
first_trailing_bit(ConcreteInt::I32([1])),
|
||||
ConcreteInt::I32([0])
|
||||
);
|
||||
assert_eq!(
|
||||
first_trailing_bit(ConcreteInt::I32([2])),
|
||||
ConcreteInt::I32([1])
|
||||
);
|
||||
assert_eq!(
|
||||
first_trailing_bit(ConcreteInt::I32([-1])),
|
||||
ConcreteInt::I32([0]),
|
||||
);
|
||||
assert_eq!(
|
||||
first_trailing_bit(ConcreteInt::I32([i32::MIN])),
|
||||
ConcreteInt::I32([31]),
|
||||
);
|
||||
assert_eq!(
|
||||
first_trailing_bit(ConcreteInt::I32([i32::MAX])),
|
||||
ConcreteInt::I32([0]),
|
||||
);
|
||||
for idx in 0..32 {
|
||||
assert_eq!(
|
||||
first_trailing_bit(ConcreteInt::I32([1 << idx])),
|
||||
ConcreteInt::I32([idx])
|
||||
)
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
first_trailing_bit(ConcreteInt::U32([0])),
|
||||
ConcreteInt::U32([u32::MAX])
|
||||
);
|
||||
assert_eq!(
|
||||
first_trailing_bit(ConcreteInt::U32([1])),
|
||||
ConcreteInt::U32([0])
|
||||
);
|
||||
assert_eq!(
|
||||
first_trailing_bit(ConcreteInt::U32([2])),
|
||||
ConcreteInt::U32([1])
|
||||
);
|
||||
assert_eq!(
|
||||
first_trailing_bit(ConcreteInt::U32([1 << 31])),
|
||||
ConcreteInt::U32([31]),
|
||||
);
|
||||
assert_eq!(
|
||||
first_trailing_bit(ConcreteInt::U32([u32::MAX])),
|
||||
ConcreteInt::U32([0]),
|
||||
);
|
||||
for idx in 0..32 {
|
||||
assert_eq!(
|
||||
first_trailing_bit(ConcreteInt::U32([1 << idx])),
|
||||
ConcreteInt::U32([idx])
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn first_leading_bit(concrete_int: ConcreteInt<1>) -> ConcreteInt<1> {
|
||||
// NOTE: Bit indices for this built-in start at 0 at the "right" (or LSB). For example, 1 means
|
||||
// the least significant bit is set. Therefore, an input of 1 would return a right-to-left bit
|
||||
// index of 0.
|
||||
let rtl_to_ltr_bit_idx = |e: u32| -> u32 {
|
||||
match e {
|
||||
idx @ 0..=31 => 31 - idx,
|
||||
32 => u32::MAX,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
};
|
||||
match concrete_int {
|
||||
ConcreteInt::I32([e]) => ConcreteInt::I32([{
|
||||
let rtl_bit_index = if e.is_negative() {
|
||||
e.leading_ones()
|
||||
} else {
|
||||
e.leading_zeros()
|
||||
};
|
||||
rtl_to_ltr_bit_idx(rtl_bit_index) as i32
|
||||
}]),
|
||||
ConcreteInt::U32([e]) => ConcreteInt::U32([rtl_to_ltr_bit_idx(e.leading_zeros())]),
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn first_leading_bit_smoke() {
|
||||
assert_eq!(
|
||||
first_leading_bit(ConcreteInt::I32([-1])),
|
||||
ConcreteInt::I32([-1])
|
||||
);
|
||||
assert_eq!(
|
||||
first_leading_bit(ConcreteInt::I32([0])),
|
||||
ConcreteInt::I32([-1])
|
||||
);
|
||||
assert_eq!(
|
||||
first_leading_bit(ConcreteInt::I32([1])),
|
||||
ConcreteInt::I32([0])
|
||||
);
|
||||
assert_eq!(
|
||||
first_leading_bit(ConcreteInt::I32([-2])),
|
||||
ConcreteInt::I32([0])
|
||||
);
|
||||
assert_eq!(
|
||||
first_leading_bit(ConcreteInt::I32([1234 + 4567])),
|
||||
ConcreteInt::I32([12])
|
||||
);
|
||||
assert_eq!(
|
||||
first_leading_bit(ConcreteInt::I32([i32::MAX])),
|
||||
ConcreteInt::I32([30])
|
||||
);
|
||||
assert_eq!(
|
||||
first_leading_bit(ConcreteInt::I32([i32::MIN])),
|
||||
ConcreteInt::I32([30])
|
||||
);
|
||||
// NOTE: Ignore the sign bit, which is a separate (above) case.
|
||||
for idx in 0..(32 - 1) {
|
||||
assert_eq!(
|
||||
first_leading_bit(ConcreteInt::I32([1 << idx])),
|
||||
ConcreteInt::I32([idx])
|
||||
);
|
||||
}
|
||||
for idx in 1..(32 - 1) {
|
||||
assert_eq!(
|
||||
first_leading_bit(ConcreteInt::I32([-(1 << idx)])),
|
||||
ConcreteInt::I32([idx - 1])
|
||||
);
|
||||
}
|
||||
|
||||
assert_eq!(
|
||||
first_leading_bit(ConcreteInt::U32([0])),
|
||||
ConcreteInt::U32([u32::MAX])
|
||||
);
|
||||
assert_eq!(
|
||||
first_leading_bit(ConcreteInt::U32([1])),
|
||||
ConcreteInt::U32([0])
|
||||
);
|
||||
assert_eq!(
|
||||
first_leading_bit(ConcreteInt::U32([u32::MAX])),
|
||||
ConcreteInt::U32([31])
|
||||
);
|
||||
for idx in 0..32 {
|
||||
assert_eq!(
|
||||
first_leading_bit(ConcreteInt::U32([1 << idx])),
|
||||
ConcreteInt::U32([idx])
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/// Trait for conversions of abstract values to concrete types.
|
||||
trait TryFromAbstract<T>: Sized {
|
||||
/// Convert an abstract literal `value` to `Self`.
|
||||
|
||||
23
third_party/rust/naga/src/proc/index.rs
vendored
23
third_party/rust/naga/src/proc/index.rs
vendored
@@ -112,22 +112,16 @@ pub struct BoundsCheckPolicies {
|
||||
/// This controls the behavior of [`ImageLoad`] expressions when a coordinate,
|
||||
/// texture array index, level of detail, or multisampled sample number is out of range.
|
||||
///
|
||||
/// There is no corresponding policy for [`ImageStore`] statements. All the
|
||||
/// platforms we support already discard out-of-bounds image stores,
|
||||
/// effectively implementing the "skip write" part of [`ReadZeroSkipWrite`].
|
||||
///
|
||||
/// [`ImageLoad`]: crate::Expression::ImageLoad
|
||||
/// [`ImageStore`]: crate::Statement::ImageStore
|
||||
/// [`ReadZeroSkipWrite`]: BoundsCheckPolicy::ReadZeroSkipWrite
|
||||
#[cfg_attr(feature = "deserialize", serde(default))]
|
||||
pub image_load: BoundsCheckPolicy,
|
||||
|
||||
/// How should the generated code handle image texel stores that are out
|
||||
/// of range?
|
||||
///
|
||||
/// This controls the behavior of [`ImageStore`] statements when a coordinate,
|
||||
/// texture array index, level of detail, or multisampled sample number is out of range.
|
||||
///
|
||||
/// This policy should't be needed since all backends should ignore OOB writes.
|
||||
///
|
||||
/// [`ImageStore`]: crate::Statement::ImageStore
|
||||
#[cfg_attr(feature = "deserialize", serde(default))]
|
||||
pub image_store: BoundsCheckPolicy,
|
||||
|
||||
/// How should the generated code handle binding array indexes that are out of bounds.
|
||||
#[cfg_attr(feature = "deserialize", serde(default))]
|
||||
pub binding_array: BoundsCheckPolicy,
|
||||
@@ -173,10 +167,7 @@ impl BoundsCheckPolicies {
|
||||
|
||||
/// Return `true` if any of `self`'s policies are `policy`.
|
||||
pub fn contains(&self, policy: BoundsCheckPolicy) -> bool {
|
||||
self.index == policy
|
||||
|| self.buffer == policy
|
||||
|| self.image_load == policy
|
||||
|| self.image_store == policy
|
||||
self.index == policy || self.buffer == policy || self.image_load == policy
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
4
third_party/rust/naga/src/proc/mod.rs
vendored
4
third_party/rust/naga/src/proc/mod.rs
vendored
@@ -484,8 +484,8 @@ impl super::MathFunction {
|
||||
Self::ReverseBits => 1,
|
||||
Self::ExtractBits => 3,
|
||||
Self::InsertBits => 4,
|
||||
Self::FindLsb => 1,
|
||||
Self::FindMsb => 1,
|
||||
Self::FirstTrailingBit => 1,
|
||||
Self::FirstLeadingBit => 1,
|
||||
// data packing
|
||||
Self::Pack4x8snorm => 1,
|
||||
Self::Pack4x8unorm => 1,
|
||||
|
||||
4
third_party/rust/naga/src/proc/typifier.rs
vendored
4
third_party/rust/naga/src/proc/typifier.rs
vendored
@@ -788,8 +788,8 @@ impl<'a> ResolveContext<'a> {
|
||||
Mf::ReverseBits |
|
||||
Mf::ExtractBits |
|
||||
Mf::InsertBits |
|
||||
Mf::FindLsb |
|
||||
Mf::FindMsb => match *res_arg.inner_with(types) {
|
||||
Mf::FirstTrailingBit |
|
||||
Mf::FirstLeadingBit => match *res_arg.inner_with(types) {
|
||||
Ti::Scalar(scalar @ crate::Scalar {
|
||||
kind: crate::ScalarKind::Sint | crate::ScalarKind::Uint,
|
||||
..
|
||||
|
||||
@@ -1350,8 +1350,8 @@ impl super::Validator {
|
||||
| Mf::CountTrailingZeros
|
||||
| Mf::CountOneBits
|
||||
| Mf::ReverseBits
|
||||
| Mf::FindMsb
|
||||
| Mf::FindLsb => {
|
||||
| Mf::FirstLeadingBit
|
||||
| Mf::FirstTrailingBit => {
|
||||
if arg1_ty.is_some() || arg2_ty.is_some() || arg3_ty.is_some() {
|
||||
return Err(ExpressionError::WrongArgumentCount(fun));
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
21
third_party/rust/wgpu-core/Cargo.toml
vendored
21
third_party/rust/wgpu-core/Cargo.toml
vendored
@@ -11,9 +11,9 @@
|
||||
|
||||
[package]
|
||||
edition = "2021"
|
||||
rust-version = "1.74"
|
||||
rust-version = "1.76"
|
||||
name = "wgpu-core"
|
||||
version = "0.20.0"
|
||||
version = "22.0.0"
|
||||
authors = ["gfx-rs developers"]
|
||||
description = "WebGPU core logic on wgpu-hal"
|
||||
homepage = "https://wgpu.rs/"
|
||||
@@ -41,29 +41,30 @@ targets = [
|
||||
|
||||
[dependencies]
|
||||
arrayvec = "0.7"
|
||||
bit-vec = "0.7"
|
||||
bitflags = "2"
|
||||
bit-vec = "0.8"
|
||||
bitflags = "2.6"
|
||||
document-features = "0.2.10"
|
||||
indexmap = "2"
|
||||
log = "0.4"
|
||||
once_cell = "1"
|
||||
once_cell = "1.19.0"
|
||||
parking_lot = ">=0.11, <0.13"
|
||||
rustc-hash = "1.1"
|
||||
rustc-hash = "1.1.0"
|
||||
smallvec = "1"
|
||||
thiserror = "1"
|
||||
thiserror = "1.0.63"
|
||||
|
||||
[dependencies.bytemuck]
|
||||
version = "1.16"
|
||||
features = ["derive"]
|
||||
optional = true
|
||||
|
||||
[dependencies.hal]
|
||||
version = "0.20.0"
|
||||
version = "22.0.0"
|
||||
path = "../wgpu-hal"
|
||||
default-features = false
|
||||
package = "wgpu-hal"
|
||||
|
||||
[dependencies.naga]
|
||||
version = "0.20.0"
|
||||
version = "22.0.0"
|
||||
path = "../naga"
|
||||
|
||||
[dependencies.profiling]
|
||||
@@ -84,7 +85,7 @@ features = ["derive"]
|
||||
optional = true
|
||||
|
||||
[dependencies.wgt]
|
||||
version = "0.20.0"
|
||||
version = "22.0.0"
|
||||
path = "../wgpu-types"
|
||||
package = "wgpu-types"
|
||||
|
||||
|
||||
66
third_party/rust/wgpu-core/src/command/bind.rs
vendored
66
third_party/rust/wgpu-core/src/command/bind.rs
vendored
@@ -142,43 +142,38 @@ mod compat {
|
||||
|
||||
let mut errors = Vec::new();
|
||||
|
||||
let mut expected_bgl_entries = expected_bgl.entries.iter();
|
||||
let mut assigned_bgl_entries = assigned_bgl.entries.iter();
|
||||
let zipped = crate::utils::ZipWithProperAdvance::new(
|
||||
&mut expected_bgl_entries,
|
||||
&mut assigned_bgl_entries,
|
||||
);
|
||||
|
||||
for ((&binding, expected_entry), (_, assigned_entry)) in zipped {
|
||||
if assigned_entry.visibility != expected_entry.visibility {
|
||||
errors.push(EntryError::Visibility {
|
||||
binding,
|
||||
expected: expected_entry.visibility,
|
||||
assigned: assigned_entry.visibility,
|
||||
});
|
||||
}
|
||||
if assigned_entry.ty != expected_entry.ty {
|
||||
errors.push(EntryError::Type {
|
||||
binding,
|
||||
expected: expected_entry.ty,
|
||||
assigned: assigned_entry.ty,
|
||||
});
|
||||
}
|
||||
if assigned_entry.count != expected_entry.count {
|
||||
errors.push(EntryError::Count {
|
||||
binding,
|
||||
expected: expected_entry.count,
|
||||
assigned: assigned_entry.count,
|
||||
});
|
||||
for (&binding, expected_entry) in expected_bgl.entries.iter() {
|
||||
if let Some(assigned_entry) = assigned_bgl.entries.get(binding) {
|
||||
if assigned_entry.visibility != expected_entry.visibility {
|
||||
errors.push(EntryError::Visibility {
|
||||
binding,
|
||||
expected: expected_entry.visibility,
|
||||
assigned: assigned_entry.visibility,
|
||||
});
|
||||
}
|
||||
if assigned_entry.ty != expected_entry.ty {
|
||||
errors.push(EntryError::Type {
|
||||
binding,
|
||||
expected: expected_entry.ty,
|
||||
assigned: assigned_entry.ty,
|
||||
});
|
||||
}
|
||||
if assigned_entry.count != expected_entry.count {
|
||||
errors.push(EntryError::Count {
|
||||
binding,
|
||||
expected: expected_entry.count,
|
||||
assigned: assigned_entry.count,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
errors.push(EntryError::ExtraExpected { binding });
|
||||
}
|
||||
}
|
||||
|
||||
for (&binding, _) in expected_bgl_entries {
|
||||
errors.push(EntryError::ExtraExpected { binding });
|
||||
}
|
||||
|
||||
for (&binding, _) in assigned_bgl_entries {
|
||||
errors.push(EntryError::ExtraAssigned { binding });
|
||||
for (&binding, _) in assigned_bgl.entries.iter() {
|
||||
if !expected_bgl.entries.contains_key(binding) {
|
||||
errors.push(EntryError::ExtraAssigned { binding });
|
||||
}
|
||||
}
|
||||
|
||||
Err(Error::Incompatible {
|
||||
@@ -253,6 +248,7 @@ mod compat {
|
||||
.filter_map(|(i, e)| if e.is_active() { Some(i) } else { None })
|
||||
}
|
||||
|
||||
#[allow(clippy::result_large_err)]
|
||||
pub fn get_invalid(&self) -> Result<(), (usize, Error)> {
|
||||
for (index, entry) in self.entries.iter().enumerate() {
|
||||
entry.check().map_err(|e| (index, e))?;
|
||||
@@ -387,8 +383,6 @@ impl<A: HalApi> Binder<A> {
|
||||
bind_group: &Arc<BindGroup<A>>,
|
||||
offsets: &[wgt::DynamicOffset],
|
||||
) -> &'a [EntryPayload<A>] {
|
||||
log::trace!("\tBinding [{}] = group {}", index, bind_group.error_ident());
|
||||
|
||||
let payload = &mut self.payloads[index];
|
||||
payload.group = Some(bind_group.clone());
|
||||
payload.dynamic_offsets.clear();
|
||||
|
||||
@@ -269,8 +269,6 @@ impl<'scope, 'snatch_guard, 'cmd_buf, 'raw_encoder, A: HalApi>
|
||||
.set_and_remove_from_usage_scope_sparse(&mut self.scope.buffers, indirect_buffer);
|
||||
}
|
||||
|
||||
log::trace!("Encoding dispatch barriers");
|
||||
|
||||
CommandBuffer::drain_barriers(
|
||||
self.raw_encoder,
|
||||
&mut self.intermediate_trackers,
|
||||
@@ -321,10 +319,6 @@ impl Global {
|
||||
);
|
||||
};
|
||||
|
||||
if let Err(e) = query_set.same_device_as(cmd_buf.as_ref()) {
|
||||
return make_err(e.into(), arc_desc);
|
||||
}
|
||||
|
||||
Some(ArcPassTimestampWrites {
|
||||
query_set,
|
||||
beginning_of_pass_write_index: tw.beginning_of_pass_write_index,
|
||||
@@ -501,6 +495,10 @@ impl Global {
|
||||
state.tracker.query_sets.set_size(indices.query_sets.size());
|
||||
|
||||
let timestamp_writes = if let Some(tw) = timestamp_writes.take() {
|
||||
tw.query_set
|
||||
.same_device_as(cmd_buf)
|
||||
.map_pass_err(pass_scope)?;
|
||||
|
||||
let query_set = state.tracker.query_sets.insert_single(tw.query_set);
|
||||
|
||||
// Unlike in render passes we can't delay resetting the query sets since
|
||||
|
||||
@@ -506,7 +506,6 @@ impl<A: HalApi> CommandBuffer<A> {
|
||||
}
|
||||
|
||||
pub(crate) fn extract_baked_commands(&mut self) -> BakedCommands<A> {
|
||||
log::trace!("Extracting BakedCommands from {}", self.error_ident());
|
||||
let data = self.data.lock().take().unwrap();
|
||||
BakedCommands {
|
||||
encoder: data.encoder.raw,
|
||||
@@ -626,7 +625,6 @@ impl Global {
|
||||
cmd_buf_data.status = CommandEncoderStatus::Finished;
|
||||
//Note: if we want to stop tracking the swapchain texture view,
|
||||
// this is the place to do it.
|
||||
log::trace!("Command buffer {:?}", encoder_id);
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
52
third_party/rust/wgpu-core/src/command/render.rs
vendored
52
third_party/rust/wgpu-core/src/command/render.rs
vendored
@@ -817,7 +817,7 @@ impl<'d, A: HalApi> RenderPassInfo<'d, A> {
|
||||
}
|
||||
|
||||
fn start(
|
||||
device: &'d Device<A>,
|
||||
device: &'d Arc<Device<A>>,
|
||||
hal_label: Option<&str>,
|
||||
color_attachments: ArrayVec<
|
||||
Option<ArcRenderPassColorAttachment<A>>,
|
||||
@@ -919,6 +919,7 @@ impl<'d, A: HalApi> RenderPassInfo<'d, A> {
|
||||
|
||||
if let Some(at) = depth_stencil_attachment.as_ref() {
|
||||
let view = &at.view;
|
||||
view.same_device(device)?;
|
||||
check_multiview(view)?;
|
||||
add_view(view, AttachmentErrorLocation::Depth)?;
|
||||
|
||||
@@ -1049,6 +1050,7 @@ impl<'d, A: HalApi> RenderPassInfo<'d, A> {
|
||||
continue;
|
||||
};
|
||||
let color_view: &TextureView<A> = &at.view;
|
||||
color_view.same_device(device)?;
|
||||
check_multiview(color_view)?;
|
||||
add_view(
|
||||
color_view,
|
||||
@@ -1079,6 +1081,7 @@ impl<'d, A: HalApi> RenderPassInfo<'d, A> {
|
||||
|
||||
let mut hal_resolve_target = None;
|
||||
if let Some(resolve_view) = &at.resolve_target {
|
||||
resolve_view.same_device(device)?;
|
||||
check_multiview(resolve_view)?;
|
||||
|
||||
let resolve_location = AttachmentErrorLocation::Color {
|
||||
@@ -1178,8 +1181,9 @@ impl<'d, A: HalApi> RenderPassInfo<'d, A> {
|
||||
multiview,
|
||||
};
|
||||
|
||||
let timestamp_writes_hal = timestamp_writes.as_ref().map(|tw| {
|
||||
let timestamp_writes_hal = if let Some(tw) = timestamp_writes.as_ref() {
|
||||
let query_set = &tw.query_set;
|
||||
query_set.same_device(device)?;
|
||||
|
||||
if let Some(index) = tw.beginning_of_pass_write_index {
|
||||
pending_query_resets.use_query_set(query_set, index);
|
||||
@@ -1188,16 +1192,21 @@ impl<'d, A: HalApi> RenderPassInfo<'d, A> {
|
||||
pending_query_resets.use_query_set(query_set, index);
|
||||
}
|
||||
|
||||
hal::RenderPassTimestampWrites {
|
||||
Some(hal::RenderPassTimestampWrites {
|
||||
query_set: query_set.raw.as_ref().unwrap(),
|
||||
beginning_of_pass_write_index: tw.beginning_of_pass_write_index,
|
||||
end_of_pass_write_index: tw.end_of_pass_write_index,
|
||||
}
|
||||
});
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let occlusion_query_set_hal = occlusion_query_set
|
||||
.as_ref()
|
||||
.map(|query_set| query_set.raw.as_ref().unwrap());
|
||||
let occlusion_query_set_hal = if let Some(query_set) = occlusion_query_set.as_ref() {
|
||||
query_set.same_device(device)?;
|
||||
Some(query_set.raw.as_ref().unwrap())
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let hal_desc = hal::RenderPassDescriptor {
|
||||
label: hal_label,
|
||||
@@ -1331,7 +1340,6 @@ impl Global {
|
||||
) -> (RenderPass<A>, Option<CommandEncoderError>) {
|
||||
fn fill_arc_desc<A: HalApi>(
|
||||
hub: &crate::hub::Hub<A>,
|
||||
device: &Arc<Device<A>>,
|
||||
desc: &RenderPassDescriptor<'_>,
|
||||
arc_desc: &mut ArcRenderPassDescriptor<A>,
|
||||
) -> Result<(), CommandEncoderError> {
|
||||
@@ -1348,13 +1356,11 @@ impl Global {
|
||||
let view = texture_views
|
||||
.get_owned(*view_id)
|
||||
.map_err(|_| CommandEncoderError::InvalidAttachmentId(*view_id))?;
|
||||
view.same_device(device)?;
|
||||
|
||||
let resolve_target = if let Some(resolve_target_id) = resolve_target {
|
||||
let rt_arc = texture_views.get_owned(*resolve_target_id).map_err(|_| {
|
||||
CommandEncoderError::InvalidResolveTargetId(*resolve_target_id)
|
||||
})?;
|
||||
rt_arc.same_device(device)?;
|
||||
|
||||
Some(rt_arc)
|
||||
} else {
|
||||
@@ -1382,7 +1388,6 @@ impl Global {
|
||||
depth_stencil_attachment.view,
|
||||
)
|
||||
})?;
|
||||
view.same_device(device)?;
|
||||
|
||||
Some(ArcRenderPassDepthStencilAttachment {
|
||||
view,
|
||||
@@ -1397,7 +1402,6 @@ impl Global {
|
||||
let query_set = query_sets.get_owned(tw.query_set).map_err(|_| {
|
||||
CommandEncoderError::InvalidTimestampWritesQuerySetId(tw.query_set)
|
||||
})?;
|
||||
query_set.same_device(device)?;
|
||||
|
||||
Some(ArcPassTimestampWrites {
|
||||
query_set,
|
||||
@@ -1413,7 +1417,6 @@ impl Global {
|
||||
let query_set = query_sets.get_owned(occlusion_query_set).map_err(|_| {
|
||||
CommandEncoderError::InvalidOcclusionQuerySetId(occlusion_query_set)
|
||||
})?;
|
||||
query_set.same_device(device)?;
|
||||
|
||||
Some(query_set)
|
||||
} else {
|
||||
@@ -1444,7 +1447,7 @@ impl Global {
|
||||
Err(e) => return make_err(e, arc_desc),
|
||||
};
|
||||
|
||||
let err = fill_arc_desc(hub, &cmd_buf.device, desc, &mut arc_desc).err();
|
||||
let err = fill_arc_desc(hub, desc, &mut arc_desc).err();
|
||||
|
||||
(RenderPass::new(Some(cmd_buf), arc_desc), err)
|
||||
}
|
||||
@@ -1563,7 +1566,7 @@ impl Global {
|
||||
|
||||
profiling::scope!(
|
||||
"CommandEncoder::run_render_pass {}",
|
||||
base.label.unwrap_or("")
|
||||
base.label.as_deref().unwrap_or("")
|
||||
);
|
||||
|
||||
let Some(cmd_buf) = pass.parent.as_ref() else {
|
||||
@@ -1597,8 +1600,6 @@ impl Global {
|
||||
*status = CommandEncoderStatus::Error;
|
||||
encoder.open_pass(hal_label).map_pass_err(pass_scope)?;
|
||||
|
||||
log::trace!("Encoding render pass begin in {}", cmd_buf.error_ident());
|
||||
|
||||
let info = RenderPassInfo::start(
|
||||
device,
|
||||
hal_label,
|
||||
@@ -1788,7 +1789,7 @@ impl Global {
|
||||
},
|
||||
indexed,
|
||||
};
|
||||
multi_draw_indirect(&mut state, buffer, offset, count, indexed)
|
||||
multi_draw_indirect(&mut state, cmd_buf, buffer, offset, count, indexed)
|
||||
.map_pass_err(scope)?;
|
||||
}
|
||||
ArcRenderCommand::MultiDrawIndirectCount {
|
||||
@@ -1805,6 +1806,7 @@ impl Global {
|
||||
};
|
||||
multi_draw_indirect_count(
|
||||
&mut state,
|
||||
cmd_buf,
|
||||
buffer,
|
||||
offset,
|
||||
count_buffer,
|
||||
@@ -1831,6 +1833,7 @@ impl Global {
|
||||
let scope = PassErrorScope::WriteTimestamp;
|
||||
write_timestamp(
|
||||
&mut state,
|
||||
cmd_buf,
|
||||
&mut cmd_buf_data.pending_query_resets,
|
||||
query_set,
|
||||
query_index,
|
||||
@@ -1902,7 +1905,6 @@ impl Global {
|
||||
}
|
||||
}
|
||||
|
||||
log::trace!("Merging renderpass into {}", cmd_buf.error_ident());
|
||||
let (trackers, pending_discard_init_fixups) = state
|
||||
.info
|
||||
.finish(state.raw_encoder, state.snatch_guard)
|
||||
@@ -2445,6 +2447,7 @@ fn draw_indexed<A: HalApi>(
|
||||
|
||||
fn multi_draw_indirect<A: HalApi>(
|
||||
state: &mut State<A>,
|
||||
cmd_buf: &Arc<CommandBuffer<A>>,
|
||||
indirect_buffer: Arc<crate::resource::Buffer<A>>,
|
||||
offset: u64,
|
||||
count: Option<NonZeroU32>,
|
||||
@@ -2471,6 +2474,8 @@ fn multi_draw_indirect<A: HalApi>(
|
||||
.device
|
||||
.require_downlevel_flags(wgt::DownlevelFlags::INDIRECT_EXECUTION)?;
|
||||
|
||||
indirect_buffer.same_device_as(cmd_buf.as_ref())?;
|
||||
|
||||
state
|
||||
.info
|
||||
.usage_scope
|
||||
@@ -2517,6 +2522,7 @@ fn multi_draw_indirect<A: HalApi>(
|
||||
|
||||
fn multi_draw_indirect_count<A: HalApi>(
|
||||
state: &mut State<A>,
|
||||
cmd_buf: &Arc<CommandBuffer<A>>,
|
||||
indirect_buffer: Arc<crate::resource::Buffer<A>>,
|
||||
offset: u64,
|
||||
count_buffer: Arc<crate::resource::Buffer<A>>,
|
||||
@@ -2544,6 +2550,9 @@ fn multi_draw_indirect_count<A: HalApi>(
|
||||
.device
|
||||
.require_downlevel_flags(wgt::DownlevelFlags::INDIRECT_EXECUTION)?;
|
||||
|
||||
indirect_buffer.same_device_as(cmd_buf.as_ref())?;
|
||||
count_buffer.same_device_as(cmd_buf.as_ref())?;
|
||||
|
||||
state
|
||||
.info
|
||||
.usage_scope
|
||||
@@ -2674,6 +2683,7 @@ fn insert_debug_marker<A: HalApi>(state: &mut State<A>, string_data: &[u8], len:
|
||||
|
||||
fn write_timestamp<A: HalApi>(
|
||||
state: &mut State<A>,
|
||||
cmd_buf: &CommandBuffer<A>,
|
||||
pending_query_resets: &mut QueryResetMap<A>,
|
||||
query_set: Arc<QuerySet<A>>,
|
||||
query_index: u32,
|
||||
@@ -2683,6 +2693,8 @@ fn write_timestamp<A: HalApi>(
|
||||
query_set.error_ident()
|
||||
);
|
||||
|
||||
query_set.same_device_as(cmd_buf)?;
|
||||
|
||||
state
|
||||
.device
|
||||
.require_features(wgt::Features::TIMESTAMP_QUERY_INSIDE_PASSES)?;
|
||||
|
||||
@@ -225,7 +225,7 @@ pub(crate) fn validate_linear_texture_data(
|
||||
// the copy size before calling this function (for example via `validate_texture_copy_range`).
|
||||
let copy_width = copy_size.width as BufferAddress;
|
||||
let copy_height = copy_size.height as BufferAddress;
|
||||
let copy_depth = copy_size.depth_or_array_layers as BufferAddress;
|
||||
let depth_or_array_layers = copy_size.depth_or_array_layers as BufferAddress;
|
||||
|
||||
let offset = layout.offset;
|
||||
|
||||
@@ -253,19 +253,19 @@ pub(crate) fn validate_linear_texture_data(
|
||||
}
|
||||
bytes_per_row
|
||||
} else {
|
||||
if copy_depth > 1 || height_in_blocks > 1 {
|
||||
if depth_or_array_layers > 1 || height_in_blocks > 1 {
|
||||
return Err(TransferError::UnspecifiedBytesPerRow);
|
||||
}
|
||||
0
|
||||
};
|
||||
let block_rows_per_image = if let Some(rows_per_image) = layout.rows_per_image {
|
||||
let rows_per_image = if let Some(rows_per_image) = layout.rows_per_image {
|
||||
let rows_per_image = rows_per_image as BufferAddress;
|
||||
if rows_per_image < height_in_blocks {
|
||||
return Err(TransferError::InvalidRowsPerImage);
|
||||
}
|
||||
rows_per_image
|
||||
} else {
|
||||
if copy_depth > 1 {
|
||||
if depth_or_array_layers > 1 {
|
||||
return Err(TransferError::UnspecifiedRowsPerImage);
|
||||
}
|
||||
0
|
||||
@@ -287,12 +287,12 @@ pub(crate) fn validate_linear_texture_data(
|
||||
}
|
||||
}
|
||||
|
||||
let bytes_per_image = bytes_per_row * block_rows_per_image;
|
||||
let bytes_per_image = bytes_per_row * rows_per_image;
|
||||
|
||||
let required_bytes_in_copy = if copy_depth == 0 {
|
||||
let required_bytes_in_copy = if depth_or_array_layers == 0 {
|
||||
0
|
||||
} else {
|
||||
let mut required_bytes_in_copy = bytes_per_image * (copy_depth - 1);
|
||||
let mut required_bytes_in_copy = bytes_per_image * (depth_or_array_layers - 1);
|
||||
if height_in_blocks > 0 {
|
||||
required_bytes_in_copy += bytes_per_row * (height_in_blocks - 1) + bytes_in_last_row;
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ impl AnyDevice {
|
||||
unsafe fn drop_glue<A: HalApi>(ptr: *mut ()) {
|
||||
// Drop the arc this instance is holding.
|
||||
unsafe {
|
||||
_ = Arc::from_raw(ptr.cast::<A::Device>());
|
||||
_ = Arc::from_raw(ptr.cast::<Device<A>>());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
5
third_party/rust/wgpu-core/src/device/bgl.rs
vendored
5
third_party/rust/wgpu-core/src/device/bgl.rs
vendored
@@ -126,4 +126,9 @@ impl EntryMap {
|
||||
self.sorted = false;
|
||||
self.inner.entry(key)
|
||||
}
|
||||
|
||||
pub fn sort(&mut self) {
|
||||
self.inner.sort_unstable_keys();
|
||||
self.sorted = true;
|
||||
}
|
||||
}
|
||||
|
||||
166
third_party/rust/wgpu-core/src/device/global.rs
vendored
166
third_party/rust/wgpu-core/src/device/global.rs
vendored
@@ -19,7 +19,6 @@ use crate::{
|
||||
present,
|
||||
resource::{
|
||||
self, BufferAccessError, BufferAccessResult, BufferMapOperation, CreateBufferError,
|
||||
Trackable,
|
||||
},
|
||||
storage::Storage,
|
||||
Label,
|
||||
@@ -31,8 +30,7 @@ use wgt::{BufferAddress, TextureFormat};
|
||||
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
iter,
|
||||
ptr::{self, NonNull},
|
||||
ptr::NonNull,
|
||||
sync::{atomic::Ordering, Arc},
|
||||
};
|
||||
|
||||
@@ -253,120 +251,46 @@ impl Global {
|
||||
}
|
||||
|
||||
#[cfg(feature = "replay")]
|
||||
pub fn device_wait_for_buffer<A: HalApi>(
|
||||
pub fn device_set_buffer_data<A: HalApi>(
|
||||
&self,
|
||||
device_id: DeviceId,
|
||||
buffer_id: id::BufferId,
|
||||
) -> Result<(), WaitIdleError> {
|
||||
let hub = A::hub(self);
|
||||
|
||||
let last_submission = match hub.buffers.read().get(buffer_id) {
|
||||
Ok(buffer) => buffer.submission_index(),
|
||||
Err(_) => return Ok(()),
|
||||
};
|
||||
|
||||
hub.devices
|
||||
.get(device_id)
|
||||
.map_err(|_| DeviceError::InvalidDeviceId)?
|
||||
.wait_for_submit(last_submission)
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn device_set_buffer_sub_data<A: HalApi>(
|
||||
&self,
|
||||
device_id: DeviceId,
|
||||
buffer_id: id::BufferId,
|
||||
offset: BufferAddress,
|
||||
data: &[u8],
|
||||
) -> BufferAccessResult {
|
||||
profiling::scope!("Device::set_buffer_sub_data");
|
||||
|
||||
let hub = A::hub(self);
|
||||
|
||||
let device = hub
|
||||
.devices
|
||||
.get(device_id)
|
||||
.map_err(|_| DeviceError::InvalidDeviceId)?;
|
||||
|
||||
let buffer = hub
|
||||
.buffers
|
||||
.get(buffer_id)
|
||||
.map_err(|_| BufferAccessError::InvalidBufferId(buffer_id))?;
|
||||
|
||||
#[cfg(feature = "trace")]
|
||||
if let Some(ref mut trace) = *device.trace.lock() {
|
||||
let data_path = trace.make_binary("bin", data);
|
||||
trace.add(trace::Action::WriteBuffer {
|
||||
id: buffer_id,
|
||||
data: data_path,
|
||||
range: offset..offset + data.len() as BufferAddress,
|
||||
queued: false,
|
||||
});
|
||||
}
|
||||
let device = &buffer.device;
|
||||
|
||||
device.check_is_valid()?;
|
||||
buffer.check_usage(wgt::BufferUsages::MAP_WRITE)?;
|
||||
//assert!(buffer isn't used by the GPU);
|
||||
|
||||
let snatch_guard = device.snatchable_lock.read();
|
||||
let raw_buf = buffer.try_raw(&snatch_guard)?;
|
||||
unsafe {
|
||||
let mapping = device
|
||||
.raw()
|
||||
.map_buffer(raw_buf, offset..offset + data.len() as u64)
|
||||
.map_err(DeviceError::from)?;
|
||||
ptr::copy_nonoverlapping(data.as_ptr(), mapping.ptr.as_ptr(), data.len());
|
||||
if !mapping.is_coherent {
|
||||
device
|
||||
.raw()
|
||||
.flush_mapped_ranges(raw_buf, iter::once(offset..offset + data.len() as u64));
|
||||
}
|
||||
device.raw().unmap_buffer(raw_buf);
|
||||
let last_submission = device
|
||||
.lock_life()
|
||||
.get_buffer_latest_submission_index(&buffer);
|
||||
|
||||
if let Some(last_submission) = last_submission {
|
||||
device.wait_for_submit(last_submission)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn device_get_buffer_sub_data<A: HalApi>(
|
||||
&self,
|
||||
device_id: DeviceId,
|
||||
buffer_id: id::BufferId,
|
||||
offset: BufferAddress,
|
||||
data: &mut [u8],
|
||||
) -> BufferAccessResult {
|
||||
profiling::scope!("Device::get_buffer_sub_data");
|
||||
|
||||
let hub = A::hub(self);
|
||||
|
||||
let device = hub
|
||||
.devices
|
||||
.get(device_id)
|
||||
.map_err(|_| DeviceError::InvalidDeviceId)?;
|
||||
device.check_is_valid()?;
|
||||
|
||||
let snatch_guard = device.snatchable_lock.read();
|
||||
|
||||
let buffer = hub
|
||||
.buffers
|
||||
.get(buffer_id)
|
||||
.map_err(|_| BufferAccessError::InvalidBufferId(buffer_id))?;
|
||||
buffer.check_usage(wgt::BufferUsages::MAP_READ)?;
|
||||
//assert!(buffer isn't used by the GPU);
|
||||
|
||||
let raw_buf = buffer.try_raw(&snatch_guard)?;
|
||||
unsafe {
|
||||
let mapping = device
|
||||
.raw()
|
||||
.map_buffer(raw_buf, offset..offset + data.len() as u64)
|
||||
.map_err(DeviceError::from)?;
|
||||
std::ptr::copy_nonoverlapping(data.as_ptr(), mapping.ptr.as_ptr(), data.len());
|
||||
if !mapping.is_coherent {
|
||||
device.raw().invalidate_mapped_ranges(
|
||||
device.raw().flush_mapped_ranges(
|
||||
raw_buf,
|
||||
iter::once(offset..offset + data.len() as u64),
|
||||
std::iter::once(offset..offset + data.len() as u64),
|
||||
);
|
||||
}
|
||||
ptr::copy_nonoverlapping(mapping.ptr.as_ptr(), data.as_mut_ptr(), data.len());
|
||||
device.raw().unmap_buffer(raw_buf);
|
||||
}
|
||||
|
||||
@@ -400,7 +324,7 @@ impl Global {
|
||||
buffer.destroy()
|
||||
}
|
||||
|
||||
pub fn buffer_drop<A: HalApi>(&self, buffer_id: id::BufferId, wait: bool) {
|
||||
pub fn buffer_drop<A: HalApi>(&self, buffer_id: id::BufferId) {
|
||||
profiling::scope!("Buffer::drop");
|
||||
api_log!("Buffer::drop {buffer_id:?}");
|
||||
|
||||
@@ -422,14 +346,6 @@ impl Global {
|
||||
#[cfg(feature = "trace")]
|
||||
buffer_id,
|
||||
);
|
||||
|
||||
if wait {
|
||||
let last_submit_index = buffer.submission_index();
|
||||
match buffer.device.wait_for_submit(last_submit_index) {
|
||||
Ok(()) => (),
|
||||
Err(e) => log::error!("Failed to wait for buffer {:?}: {}", buffer_id, e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn device_create_texture<A: HalApi>(
|
||||
@@ -586,25 +502,17 @@ impl Global {
|
||||
texture.destroy()
|
||||
}
|
||||
|
||||
pub fn texture_drop<A: HalApi>(&self, texture_id: id::TextureId, wait: bool) {
|
||||
pub fn texture_drop<A: HalApi>(&self, texture_id: id::TextureId) {
|
||||
profiling::scope!("Texture::drop");
|
||||
api_log!("Texture::drop {texture_id:?}");
|
||||
|
||||
let hub = A::hub(self);
|
||||
|
||||
if let Some(texture) = hub.textures.unregister(texture_id) {
|
||||
if let Some(_texture) = hub.textures.unregister(texture_id) {
|
||||
#[cfg(feature = "trace")]
|
||||
if let Some(t) = texture.device.trace.lock().as_mut() {
|
||||
if let Some(t) = _texture.device.trace.lock().as_mut() {
|
||||
t.add(trace::Action::DestroyTexture(texture_id));
|
||||
}
|
||||
|
||||
if wait {
|
||||
let last_submit_index = texture.submission_index();
|
||||
match texture.device.wait_for_submit(last_submit_index) {
|
||||
Ok(()) => (),
|
||||
Err(e) => log::error!("Failed to wait for texture {texture_id:?}: {e}"),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -658,28 +566,17 @@ impl Global {
|
||||
pub fn texture_view_drop<A: HalApi>(
|
||||
&self,
|
||||
texture_view_id: id::TextureViewId,
|
||||
wait: bool,
|
||||
) -> Result<(), resource::TextureViewDestroyError> {
|
||||
profiling::scope!("TextureView::drop");
|
||||
api_log!("TextureView::drop {texture_view_id:?}");
|
||||
|
||||
let hub = A::hub(self);
|
||||
|
||||
if let Some(view) = hub.texture_views.unregister(texture_view_id) {
|
||||
if let Some(_view) = hub.texture_views.unregister(texture_view_id) {
|
||||
#[cfg(feature = "trace")]
|
||||
if let Some(t) = view.device.trace.lock().as_mut() {
|
||||
if let Some(t) = _view.device.trace.lock().as_mut() {
|
||||
t.add(trace::Action::DestroyTextureView(texture_view_id));
|
||||
}
|
||||
|
||||
if wait {
|
||||
let last_submit_index = view.submission_index();
|
||||
match view.device.wait_for_submit(last_submit_index) {
|
||||
Ok(()) => (),
|
||||
Err(e) => {
|
||||
log::error!("Failed to wait for texture view {texture_view_id:?}: {e}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -1143,7 +1040,7 @@ impl Global {
|
||||
#[cfg(feature = "trace")]
|
||||
if let Some(ref mut trace) = *device.trace.lock() {
|
||||
let data = trace.make_binary("spv", unsafe {
|
||||
std::slice::from_raw_parts(source.as_ptr() as *const u8, source.len() * 4)
|
||||
std::slice::from_raw_parts(source.as_ptr().cast::<u8>(), source.len() * 4)
|
||||
});
|
||||
trace.add(trace::Action::CreateShaderModule {
|
||||
id: fid.id(),
|
||||
@@ -1457,7 +1354,6 @@ impl Global {
|
||||
.vertex
|
||||
.stage
|
||||
.zero_initialize_workgroup_memory,
|
||||
vertex_pulling_transform: desc.vertex.stage.vertex_pulling_transform,
|
||||
};
|
||||
ResolvedVertexState {
|
||||
stage,
|
||||
@@ -1484,7 +1380,6 @@ impl Global {
|
||||
.vertex
|
||||
.stage
|
||||
.zero_initialize_workgroup_memory,
|
||||
vertex_pulling_transform: state.stage.vertex_pulling_transform,
|
||||
};
|
||||
Some(ResolvedFragmentState {
|
||||
stage,
|
||||
@@ -1693,7 +1588,6 @@ impl Global {
|
||||
entry_point: desc.stage.entry_point.clone(),
|
||||
constants: desc.stage.constants.clone(),
|
||||
zero_initialize_workgroup_memory: desc.stage.zero_initialize_workgroup_memory,
|
||||
vertex_pulling_transform: desc.stage.vertex_pulling_transform,
|
||||
};
|
||||
|
||||
let desc = ResolvedComputePipelineDescriptor {
|
||||
@@ -1985,7 +1879,10 @@ impl Global {
|
||||
config.composite_alpha_mode = new_alpha_mode;
|
||||
}
|
||||
if !caps.usage.contains(config.usage) {
|
||||
return Err(E::UnsupportedUsage);
|
||||
return Err(E::UnsupportedUsage {
|
||||
requested: config.usage,
|
||||
available: caps.usage,
|
||||
});
|
||||
}
|
||||
if width == 0 || height == 0 {
|
||||
return Err(E::ZeroArea);
|
||||
@@ -2347,11 +2244,7 @@ impl Global {
|
||||
// need to wait for submissions or triage them. We know we were
|
||||
// just polled, so `life_tracker.free_resources` is empty.
|
||||
debug_assert!(device.lock_life().queue_empty());
|
||||
{
|
||||
let mut pending_writes = device.pending_writes.lock();
|
||||
let pending_writes = pending_writes.as_mut().unwrap();
|
||||
pending_writes.deactivate();
|
||||
}
|
||||
device.pending_writes.lock().deactivate();
|
||||
|
||||
drop(device);
|
||||
}
|
||||
@@ -2435,6 +2328,17 @@ impl Global {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn device_generate_allocator_report<A: HalApi>(
|
||||
&self,
|
||||
device_id: DeviceId,
|
||||
) -> Option<wgt::AllocatorReport> {
|
||||
let hub = A::hub(self);
|
||||
hub.devices
|
||||
.get(device_id)
|
||||
.ok()
|
||||
.and_then(|device| device.generate_allocator_report())
|
||||
}
|
||||
|
||||
pub fn queue_drop<A: HalApi>(&self, queue_id: QueueId) {
|
||||
profiling::scope!("Queue::drop");
|
||||
api_log!("Queue::drop {queue_id:?}");
|
||||
|
||||
110
third_party/rust/wgpu-core/src/device/life.rs
vendored
110
third_party/rust/wgpu-core/src/device/life.rs
vendored
@@ -5,7 +5,7 @@ use crate::{
|
||||
},
|
||||
hal_api::HalApi,
|
||||
id,
|
||||
resource::{self, Buffer, Labeled, Trackable},
|
||||
resource::{self, Buffer, Texture, Trackable},
|
||||
snatch::SnatchGuard,
|
||||
SubmissionIndex,
|
||||
};
|
||||
@@ -55,6 +55,58 @@ struct ActiveSubmission<A: HalApi> {
|
||||
work_done_closures: SmallVec<[SubmittedWorkDoneClosure; 1]>,
|
||||
}
|
||||
|
||||
impl<A: HalApi> ActiveSubmission<A> {
|
||||
/// Returns true if this submission contains the given buffer.
|
||||
///
|
||||
/// This only uses constant-time operations.
|
||||
pub fn contains_buffer(&self, buffer: &Buffer<A>) -> bool {
|
||||
for encoder in &self.encoders {
|
||||
// The ownership location of buffers depends on where the command encoder
|
||||
// came from. If it is the staging command encoder on the queue, it is
|
||||
// in the pending buffer list. If it came from a user command encoder,
|
||||
// it is in the tracker.
|
||||
|
||||
if encoder.trackers.buffers.contains(buffer) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if encoder
|
||||
.pending_buffers
|
||||
.contains_key(&buffer.tracker_index())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
|
||||
/// Returns true if this submission contains the given texture.
|
||||
///
|
||||
/// This only uses constant-time operations.
|
||||
pub fn contains_texture(&self, texture: &Texture<A>) -> bool {
|
||||
for encoder in &self.encoders {
|
||||
// The ownership location of textures depends on where the command encoder
|
||||
// came from. If it is the staging command encoder on the queue, it is
|
||||
// in the pending buffer list. If it came from a user command encoder,
|
||||
// it is in the tracker.
|
||||
|
||||
if encoder.trackers.textures.contains(texture) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if encoder
|
||||
.pending_textures
|
||||
.contains_key(&texture.tracker_index())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Error)]
|
||||
#[non_exhaustive]
|
||||
pub enum WaitIdleError {
|
||||
@@ -165,6 +217,40 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
self.mapped.push(value.clone());
|
||||
}
|
||||
|
||||
/// Returns the submission index of the most recent submission that uses the
|
||||
/// given buffer.
|
||||
pub fn get_buffer_latest_submission_index(
|
||||
&self,
|
||||
buffer: &Buffer<A>,
|
||||
) -> Option<SubmissionIndex> {
|
||||
// We iterate in reverse order, so that we can bail out early as soon
|
||||
// as we find a hit.
|
||||
self.active.iter().rev().find_map(|submission| {
|
||||
if submission.contains_buffer(buffer) {
|
||||
Some(submission.index)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns the submission index of the most recent submission that uses the
|
||||
/// given texture.
|
||||
pub fn get_texture_latest_submission_index(
|
||||
&self,
|
||||
texture: &Texture<A>,
|
||||
) -> Option<SubmissionIndex> {
|
||||
// We iterate in reverse order, so that we can bail out early as soon
|
||||
// as we find a hit.
|
||||
self.active.iter().rev().find_map(|submission| {
|
||||
if submission.contains_texture(texture) {
|
||||
Some(submission.index)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/// Sort out the consequences of completed submissions.
|
||||
///
|
||||
/// Assume that all submissions up through `last_done` have completed.
|
||||
@@ -197,7 +283,6 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
|
||||
let mut work_done_closures: SmallVec<_> = self.work_done_closures.drain(..).collect();
|
||||
for a in self.active.drain(..done_count) {
|
||||
log::debug!("Active submission {} is done", a.index);
|
||||
self.ready_to_map.extend(a.mapped);
|
||||
for encoder in a.encoders {
|
||||
let raw = unsafe { encoder.land() };
|
||||
@@ -236,9 +321,7 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: HalApi> LifetimeTracker<A> {
|
||||
/// Determine which buffers are ready to map, and which must wait for the
|
||||
/// GPU.
|
||||
///
|
||||
@@ -249,17 +332,13 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
}
|
||||
|
||||
for buffer in self.mapped.drain(..) {
|
||||
let submit_index = buffer.submission_index();
|
||||
log::trace!(
|
||||
"Mapping of {} at submission {:?} gets assigned to active {:?}",
|
||||
buffer.error_ident(),
|
||||
submit_index,
|
||||
self.active.iter().position(|a| a.index == submit_index)
|
||||
);
|
||||
|
||||
self.active
|
||||
let submission = self
|
||||
.active
|
||||
.iter_mut()
|
||||
.find(|a| a.index == submit_index)
|
||||
.rev()
|
||||
.find(|a| a.contains_buffer(&buffer));
|
||||
|
||||
submission
|
||||
.map_or(&mut self.ready_to_map, |a| &mut a.mapped)
|
||||
.push(buffer);
|
||||
}
|
||||
@@ -283,8 +362,6 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
Vec::with_capacity(self.ready_to_map.len());
|
||||
|
||||
for buffer in self.ready_to_map.drain(..) {
|
||||
let tracker_index = buffer.tracker_index();
|
||||
|
||||
// This _cannot_ be inlined into the match. If it is, the lock will be held
|
||||
// open through the whole match, resulting in a deadlock when we try to re-lock
|
||||
// the buffer back to active.
|
||||
@@ -305,7 +382,6 @@ impl<A: HalApi> LifetimeTracker<A> {
|
||||
_ => panic!("No pending mapping."),
|
||||
};
|
||||
let status = if pending_mapping.range.start != pending_mapping.range.end {
|
||||
log::debug!("Buffer {tracker_index:?} map state -> Active");
|
||||
let host = pending_mapping.op.host;
|
||||
let size = pending_mapping.range.end - pending_mapping.range.start;
|
||||
match super::map_buffer(
|
||||
|
||||
2
third_party/rust/wgpu-core/src/device/mod.rs
vendored
2
third_party/rust/wgpu-core/src/device/mod.rs
vendored
@@ -364,6 +364,7 @@ fn map_buffer<A: HalApi>(
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct DeviceMismatch {
|
||||
pub(super) res: ResourceErrorIdent,
|
||||
pub(super) res_device: ResourceErrorIdent,
|
||||
@@ -388,6 +389,7 @@ impl std::fmt::Display for DeviceMismatch {
|
||||
impl std::error::Error for DeviceMismatch {}
|
||||
|
||||
#[derive(Clone, Debug, Error)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[non_exhaustive]
|
||||
pub enum DeviceError {
|
||||
#[error("{0} is invalid.")]
|
||||
|
||||
230
third_party/rust/wgpu-core/src/device/queue.rs
vendored
230
third_party/rust/wgpu-core/src/device/queue.rs
vendored
@@ -30,7 +30,7 @@ use smallvec::SmallVec;
|
||||
|
||||
use std::{
|
||||
iter,
|
||||
mem::{self},
|
||||
mem::{self, ManuallyDrop},
|
||||
ptr::NonNull,
|
||||
sync::{atomic::Ordering, Arc},
|
||||
};
|
||||
@@ -39,10 +39,23 @@ use thiserror::Error;
|
||||
use super::Device;
|
||||
|
||||
pub struct Queue<A: HalApi> {
|
||||
pub(crate) raw: Option<A::Queue>,
|
||||
raw: ManuallyDrop<A::Queue>,
|
||||
pub(crate) device: Arc<Device<A>>,
|
||||
}
|
||||
|
||||
impl<A: HalApi> Queue<A> {
|
||||
pub(crate) fn new(device: Arc<Device<A>>, raw: A::Queue) -> Self {
|
||||
Queue {
|
||||
raw: ManuallyDrop::new(raw),
|
||||
device,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn raw(&self) -> &A::Queue {
|
||||
&self.raw
|
||||
}
|
||||
}
|
||||
|
||||
crate::impl_resource_type!(Queue);
|
||||
// TODO: https://github.com/gfx-rs/wgpu/issues/4014
|
||||
impl<A: HalApi> Labeled for Queue<A> {
|
||||
@@ -56,7 +69,8 @@ crate::impl_storage_item!(Queue);
|
||||
impl<A: HalApi> Drop for Queue<A> {
|
||||
fn drop(&mut self) {
|
||||
resource_log!("Drop {}", self.error_ident());
|
||||
let queue = self.raw.take().unwrap();
|
||||
// SAFETY: we never access `self.raw` beyond this point.
|
||||
let queue = unsafe { ManuallyDrop::take(&mut self.raw) };
|
||||
self.device.release_queue(queue);
|
||||
}
|
||||
}
|
||||
@@ -149,12 +163,12 @@ pub enum TempResource<A: HalApi> {
|
||||
pub(crate) struct EncoderInFlight<A: HalApi> {
|
||||
raw: A::CommandEncoder,
|
||||
cmd_buffers: Vec<A::CommandBuffer>,
|
||||
trackers: Tracker<A>,
|
||||
pub(crate) trackers: Tracker<A>,
|
||||
|
||||
/// These are the buffers that have been tracked by `PendingWrites`.
|
||||
pending_buffers: Vec<Arc<Buffer<A>>>,
|
||||
pub(crate) pending_buffers: FastHashMap<TrackerIndex, Arc<Buffer<A>>>,
|
||||
/// These are the textures that have been tracked by `PendingWrites`.
|
||||
pending_textures: Vec<Arc<Texture<A>>>,
|
||||
pub(crate) pending_textures: FastHashMap<TrackerIndex, Arc<Texture<A>>>,
|
||||
}
|
||||
|
||||
impl<A: HalApi> EncoderInFlight<A> {
|
||||
@@ -268,8 +282,8 @@ impl<A: HalApi> PendingWrites<A> {
|
||||
queue: &A::Queue,
|
||||
) -> Result<Option<EncoderInFlight<A>>, DeviceError> {
|
||||
if self.is_recording {
|
||||
let pending_buffers = self.dst_buffers.drain().map(|(_, b)| b).collect();
|
||||
let pending_textures = self.dst_textures.drain().map(|(_, t)| t).collect();
|
||||
let pending_buffers = mem::take(&mut self.dst_buffers);
|
||||
let pending_textures = mem::take(&mut self.dst_textures);
|
||||
|
||||
let cmd_buf = unsafe { self.command_encoder.end_encoding()? };
|
||||
self.is_recording = false;
|
||||
@@ -407,7 +421,6 @@ impl Global {
|
||||
// `device.pending_writes.consume`.
|
||||
let mut staging_buffer = StagingBuffer::new(device, data_size)?;
|
||||
let mut pending_writes = device.pending_writes.lock();
|
||||
let pending_writes = pending_writes.as_mut().unwrap();
|
||||
|
||||
let staging_buffer = {
|
||||
profiling::scope!("copy");
|
||||
@@ -418,7 +431,7 @@ impl Global {
|
||||
let result = self.queue_write_staging_buffer_impl(
|
||||
&queue,
|
||||
device,
|
||||
pending_writes,
|
||||
&mut pending_writes,
|
||||
&staging_buffer,
|
||||
buffer_id,
|
||||
buffer_offset,
|
||||
@@ -478,7 +491,6 @@ impl Global {
|
||||
.ok_or_else(|| QueueWriteError::Transfer(TransferError::InvalidBufferId(buffer_id)))?;
|
||||
|
||||
let mut pending_writes = device.pending_writes.lock();
|
||||
let pending_writes = pending_writes.as_mut().unwrap();
|
||||
|
||||
// At this point, we have taken ownership of the staging_buffer from the
|
||||
// user. Platform validation requires that the staging buffer always
|
||||
@@ -489,7 +501,7 @@ impl Global {
|
||||
let result = self.queue_write_staging_buffer_impl(
|
||||
&queue,
|
||||
device,
|
||||
pending_writes,
|
||||
&mut pending_writes,
|
||||
&staging_buffer,
|
||||
buffer_id,
|
||||
buffer_offset,
|
||||
@@ -572,8 +584,6 @@ impl Global {
|
||||
|
||||
self.queue_validate_write_buffer_impl(&dst, buffer_offset, staging_buffer.size)?;
|
||||
|
||||
dst.use_at(device.active_submission_index.load(Ordering::Relaxed) + 1);
|
||||
|
||||
let region = hal::BufferCopy {
|
||||
src_offset: 0,
|
||||
dst_offset: buffer_offset,
|
||||
@@ -670,7 +680,7 @@ impl Global {
|
||||
|
||||
// Note: `_source_bytes_per_array_layer` is ignored since we
|
||||
// have a staging copy, and it can have a different value.
|
||||
let (_, _source_bytes_per_array_layer) = validate_linear_texture_data(
|
||||
let (required_bytes_in_copy, _source_bytes_per_array_layer) = validate_linear_texture_data(
|
||||
data_layout,
|
||||
dst.desc.format,
|
||||
destination.aspect,
|
||||
@@ -686,34 +696,7 @@ impl Global {
|
||||
.map_err(TransferError::from)?;
|
||||
}
|
||||
|
||||
let (block_width, block_height) = dst.desc.format.block_dimensions();
|
||||
let width_blocks = size.width / block_width;
|
||||
let height_blocks = size.height / block_height;
|
||||
|
||||
let block_rows_per_image = data_layout.rows_per_image.unwrap_or(
|
||||
// doesn't really matter because we need this only if we copy
|
||||
// more than one layer, and then we validate for this being not
|
||||
// None
|
||||
height_blocks,
|
||||
);
|
||||
|
||||
let block_size = dst
|
||||
.desc
|
||||
.format
|
||||
.block_copy_size(Some(destination.aspect))
|
||||
.unwrap();
|
||||
let bytes_per_row_alignment =
|
||||
get_lowest_common_denom(device.alignments.buffer_copy_pitch.get() as u32, block_size);
|
||||
let stage_bytes_per_row =
|
||||
wgt::math::align_to(block_size * width_blocks, bytes_per_row_alignment);
|
||||
|
||||
let block_rows_in_copy =
|
||||
(size.depth_or_array_layers - 1) * block_rows_per_image + height_blocks;
|
||||
let stage_size =
|
||||
wgt::BufferSize::new(stage_bytes_per_row as u64 * block_rows_in_copy as u64).unwrap();
|
||||
|
||||
let mut pending_writes = device.pending_writes.lock();
|
||||
let pending_writes = pending_writes.as_mut().unwrap();
|
||||
let encoder = pending_writes.activate();
|
||||
|
||||
// If the copy does not fully cover the layers, we need to initialize to
|
||||
@@ -765,37 +748,50 @@ impl Global {
|
||||
// call above. Since we've held `texture_guard` the whole time, we know
|
||||
// the texture hasn't gone away in the mean time, so we can unwrap.
|
||||
let dst = hub.textures.get(destination.texture).unwrap();
|
||||
dst.use_at(device.active_submission_index.load(Ordering::Relaxed) + 1);
|
||||
|
||||
let dst_raw = dst.try_raw(&snatch_guard)?;
|
||||
|
||||
let bytes_per_row = data_layout
|
||||
.bytes_per_row
|
||||
.unwrap_or(width_blocks * block_size);
|
||||
let (block_width, block_height) = dst.desc.format.block_dimensions();
|
||||
let width_in_blocks = size.width / block_width;
|
||||
let height_in_blocks = size.height / block_height;
|
||||
|
||||
let block_size = dst
|
||||
.desc
|
||||
.format
|
||||
.block_copy_size(Some(destination.aspect))
|
||||
.unwrap();
|
||||
let bytes_in_last_row = width_in_blocks * block_size;
|
||||
|
||||
let bytes_per_row = data_layout.bytes_per_row.unwrap_or(bytes_in_last_row);
|
||||
let rows_per_image = data_layout.rows_per_image.unwrap_or(height_in_blocks);
|
||||
|
||||
let bytes_per_row_alignment =
|
||||
get_lowest_common_denom(device.alignments.buffer_copy_pitch.get() as u32, block_size);
|
||||
let stage_bytes_per_row = wgt::math::align_to(bytes_in_last_row, bytes_per_row_alignment);
|
||||
|
||||
// Platform validation requires that the staging buffer always be
|
||||
// freed, even if an error occurs. All paths from here must call
|
||||
// `device.pending_writes.consume`.
|
||||
let mut staging_buffer = StagingBuffer::new(device, stage_size)?;
|
||||
|
||||
if stage_bytes_per_row == bytes_per_row {
|
||||
let staging_buffer = if stage_bytes_per_row == bytes_per_row {
|
||||
profiling::scope!("copy aligned");
|
||||
// Fast path if the data is already being aligned optimally.
|
||||
unsafe {
|
||||
staging_buffer.write_with_offset(
|
||||
data,
|
||||
data_layout.offset as isize,
|
||||
0,
|
||||
(data.len() as u64 - data_layout.offset) as usize,
|
||||
);
|
||||
}
|
||||
let stage_size = wgt::BufferSize::new(required_bytes_in_copy).unwrap();
|
||||
let mut staging_buffer = StagingBuffer::new(device, stage_size)?;
|
||||
staging_buffer.write(&data[data_layout.offset as usize..]);
|
||||
staging_buffer
|
||||
} else {
|
||||
profiling::scope!("copy chunked");
|
||||
// Copy row by row into the optimal alignment.
|
||||
let block_rows_in_copy =
|
||||
(size.depth_or_array_layers - 1) * rows_per_image + height_in_blocks;
|
||||
let stage_size =
|
||||
wgt::BufferSize::new(stage_bytes_per_row as u64 * block_rows_in_copy as u64)
|
||||
.unwrap();
|
||||
let mut staging_buffer = StagingBuffer::new(device, stage_size)?;
|
||||
let copy_bytes_per_row = stage_bytes_per_row.min(bytes_per_row) as usize;
|
||||
for layer in 0..size.depth_or_array_layers {
|
||||
let rows_offset = layer * block_rows_per_image;
|
||||
for row in rows_offset..rows_offset + height_blocks {
|
||||
let rows_offset = layer * rows_per_image;
|
||||
for row in rows_offset..rows_offset + height_in_blocks {
|
||||
let src_offset = data_layout.offset as u32 + row * bytes_per_row;
|
||||
let dst_offset = row * stage_bytes_per_row;
|
||||
unsafe {
|
||||
@@ -808,20 +804,21 @@ impl Global {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
staging_buffer
|
||||
};
|
||||
|
||||
let staging_buffer = staging_buffer.flush();
|
||||
|
||||
let regions = (0..array_layer_count).map(|rel_array_layer| {
|
||||
let regions = (0..array_layer_count).map(|array_layer_offset| {
|
||||
let mut texture_base = dst_base.clone();
|
||||
texture_base.array_layer += rel_array_layer;
|
||||
texture_base.array_layer += array_layer_offset;
|
||||
hal::BufferTextureCopy {
|
||||
buffer_layout: wgt::ImageDataLayout {
|
||||
offset: rel_array_layer as u64
|
||||
* block_rows_per_image as u64
|
||||
offset: array_layer_offset as u64
|
||||
* rows_per_image as u64
|
||||
* stage_bytes_per_row as u64,
|
||||
bytes_per_row: Some(stage_bytes_per_row),
|
||||
rows_per_image: Some(block_rows_per_image),
|
||||
rows_per_image: Some(rows_per_image),
|
||||
},
|
||||
texture_base,
|
||||
size: hal_copy_size,
|
||||
@@ -967,7 +964,7 @@ impl Global {
|
||||
extract_texture_selector(&destination.to_untagged(), &size, &dst)?;
|
||||
|
||||
let mut pending_writes = device.pending_writes.lock();
|
||||
let encoder = pending_writes.as_mut().unwrap().activate();
|
||||
let encoder = pending_writes.activate();
|
||||
|
||||
// If the copy does not fully cover the layers, we need to initialize to
|
||||
// zero *first* as we don't keep track of partial texture layer inits.
|
||||
@@ -1010,7 +1007,6 @@ impl Global {
|
||||
.drain(init_layer_range);
|
||||
}
|
||||
}
|
||||
dst.use_at(device.active_submission_index.load(Ordering::Relaxed) + 1);
|
||||
|
||||
let snatch_guard = device.snatchable_lock.read();
|
||||
let dst_raw = dst.try_raw(&snatch_guard)?;
|
||||
@@ -1129,7 +1125,7 @@ impl Global {
|
||||
}
|
||||
|
||||
{
|
||||
profiling::scope!("update submission ids");
|
||||
profiling::scope!("check resource state");
|
||||
|
||||
let cmd_buf_data = cmdbuf.data.lock();
|
||||
let cmd_buf_trackers = &cmd_buf_data.as_ref().unwrap().trackers;
|
||||
@@ -1139,7 +1135,6 @@ impl Global {
|
||||
profiling::scope!("buffers");
|
||||
for buffer in cmd_buf_trackers.buffers.used_resources() {
|
||||
buffer.check_destroyed(&snatch_guard)?;
|
||||
buffer.use_at(submit_index);
|
||||
|
||||
match *buffer.map_state.lock() {
|
||||
BufferMapState::Idle => (),
|
||||
@@ -1166,7 +1161,6 @@ impl Global {
|
||||
true
|
||||
}
|
||||
};
|
||||
texture.use_at(submit_index);
|
||||
if should_extend {
|
||||
unsafe {
|
||||
used_surface_textures
|
||||
@@ -1180,69 +1174,6 @@ impl Global {
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
profiling::scope!("views");
|
||||
for texture_view in cmd_buf_trackers.views.used_resources() {
|
||||
texture_view.use_at(submit_index);
|
||||
}
|
||||
}
|
||||
{
|
||||
profiling::scope!("bind groups (+ referenced views/samplers)");
|
||||
for bg in cmd_buf_trackers.bind_groups.used_resources() {
|
||||
bg.use_at(submit_index);
|
||||
// We need to update the submission indices for the contained
|
||||
// state-less (!) resources as well, so that they don't get
|
||||
// deleted too early if the parent bind group goes out of scope.
|
||||
for view in bg.used.views.used_resources() {
|
||||
view.use_at(submit_index);
|
||||
}
|
||||
for sampler in bg.used.samplers.used_resources() {
|
||||
sampler.use_at(submit_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
profiling::scope!("compute pipelines");
|
||||
for compute_pipeline in
|
||||
cmd_buf_trackers.compute_pipelines.used_resources()
|
||||
{
|
||||
compute_pipeline.use_at(submit_index);
|
||||
}
|
||||
}
|
||||
{
|
||||
profiling::scope!("render pipelines");
|
||||
for render_pipeline in
|
||||
cmd_buf_trackers.render_pipelines.used_resources()
|
||||
{
|
||||
render_pipeline.use_at(submit_index);
|
||||
}
|
||||
}
|
||||
{
|
||||
profiling::scope!("query sets");
|
||||
for query_set in cmd_buf_trackers.query_sets.used_resources() {
|
||||
query_set.use_at(submit_index);
|
||||
}
|
||||
}
|
||||
{
|
||||
profiling::scope!(
|
||||
"render bundles (+ referenced pipelines/query sets)"
|
||||
);
|
||||
for bundle in cmd_buf_trackers.bundles.used_resources() {
|
||||
bundle.use_at(submit_index);
|
||||
// We need to update the submission indices for the contained
|
||||
// state-less (!) resources as well, excluding the bind groups.
|
||||
// They don't get deleted too early if the bundle goes out of scope.
|
||||
for render_pipeline in
|
||||
bundle.used.render_pipelines.read().used_resources()
|
||||
{
|
||||
render_pipeline.use_at(submit_index);
|
||||
}
|
||||
for query_set in bundle.used.query_sets.read().used_resources()
|
||||
{
|
||||
query_set.use_at(submit_index);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut baked = cmdbuf.from_arc_into_baked();
|
||||
|
||||
@@ -1256,7 +1187,6 @@ impl Global {
|
||||
))
|
||||
.map_err(DeviceError::from)?
|
||||
};
|
||||
log::trace!("Stitching command buffer {:?} before submission", cmb_id);
|
||||
|
||||
//Note: locking the trackers has to be done after the storages
|
||||
let mut trackers = device.trackers.lock();
|
||||
@@ -1306,17 +1236,14 @@ impl Global {
|
||||
raw: baked.encoder,
|
||||
cmd_buffers: baked.list,
|
||||
trackers: baked.trackers,
|
||||
pending_buffers: Vec::new(),
|
||||
pending_textures: Vec::new(),
|
||||
pending_buffers: FastHashMap::default(),
|
||||
pending_textures: FastHashMap::default(),
|
||||
});
|
||||
}
|
||||
|
||||
log::trace!("Device after submission {}", submit_index);
|
||||
}
|
||||
}
|
||||
|
||||
let mut pending_writes_guard = device.pending_writes.lock();
|
||||
let pending_writes = pending_writes_guard.as_mut().unwrap();
|
||||
let mut pending_writes = device.pending_writes.lock();
|
||||
|
||||
{
|
||||
used_surface_textures.set_size(hub.textures.read().len());
|
||||
@@ -1356,11 +1283,9 @@ impl Global {
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(pending_execution) = pending_writes.pre_submit(
|
||||
&device.command_allocator,
|
||||
device.raw(),
|
||||
queue.raw.as_ref().unwrap(),
|
||||
)? {
|
||||
if let Some(pending_execution) =
|
||||
pending_writes.pre_submit(&device.command_allocator, device.raw(), queue.raw())?
|
||||
{
|
||||
active_executions.insert(0, pending_execution);
|
||||
}
|
||||
|
||||
@@ -1382,9 +1307,7 @@ impl Global {
|
||||
|
||||
unsafe {
|
||||
queue
|
||||
.raw
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.raw()
|
||||
.submit(
|
||||
&hal_command_buffers,
|
||||
&submit_surface_textures,
|
||||
@@ -1402,17 +1325,12 @@ impl Global {
|
||||
profiling::scope!("cleanup");
|
||||
|
||||
// this will register the new submission to the life time tracker
|
||||
let mut pending_write_resources = mem::take(&mut pending_writes.temp_resources);
|
||||
device.lock_life().track_submission(
|
||||
submit_index,
|
||||
pending_write_resources.drain(..),
|
||||
pending_writes.temp_resources.drain(..),
|
||||
active_executions,
|
||||
);
|
||||
|
||||
// pending_write_resources has been drained, so it's empty, but we
|
||||
// want to retain its heap allocation.
|
||||
pending_writes.temp_resources = pending_write_resources;
|
||||
drop(pending_writes_guard);
|
||||
drop(pending_writes);
|
||||
|
||||
// This will schedule destruction of all resources that are no longer needed
|
||||
// by the user but used in the command stream, among other things.
|
||||
@@ -1445,7 +1363,7 @@ impl Global {
|
||||
) -> Result<f32, InvalidQueue> {
|
||||
let hub = A::hub(self);
|
||||
match hub.queues.get(queue_id) {
|
||||
Ok(queue) => Ok(unsafe { queue.raw.as_ref().unwrap().get_timestamp_period() }),
|
||||
Ok(queue) => Ok(unsafe { queue.raw().get_timestamp_period() }),
|
||||
Err(_) => Err(InvalidQueue),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ use crate::{
|
||||
UsageScopePool,
|
||||
},
|
||||
validation::{self, validate_color_attachment_bytes_per_sample},
|
||||
FastHashMap, LabelHelpers as _, SubmissionIndex,
|
||||
FastHashMap, LabelHelpers as _, PreHashedKey, PreHashedMap,
|
||||
};
|
||||
|
||||
use arrayvec::ArrayVec;
|
||||
@@ -46,6 +46,7 @@ use wgt::{DeviceLostReason, TextureFormat, TextureSampleType, TextureViewDimensi
|
||||
use std::{
|
||||
borrow::Cow,
|
||||
iter,
|
||||
mem::ManuallyDrop,
|
||||
num::NonZeroU32,
|
||||
sync::{
|
||||
atomic::{AtomicBool, AtomicU64, Ordering},
|
||||
@@ -142,7 +143,7 @@ pub struct Device<A: HalApi> {
|
||||
pub(crate) features: wgt::Features,
|
||||
pub(crate) downlevel: wgt::DownlevelCapabilities,
|
||||
pub(crate) instance_flags: wgt::InstanceFlags,
|
||||
pub(crate) pending_writes: Mutex<Option<PendingWrites<A>>>,
|
||||
pub(crate) pending_writes: Mutex<ManuallyDrop<PendingWrites<A>>>,
|
||||
pub(crate) deferred_destroy: Mutex<Vec<DeferredDestroy<A>>>,
|
||||
#[cfg(feature = "trace")]
|
||||
pub(crate) trace: Mutex<Option<trace::Trace>>,
|
||||
@@ -169,7 +170,8 @@ impl<A: HalApi> Drop for Device<A> {
|
||||
fn drop(&mut self) {
|
||||
resource_log!("Drop {}", self.error_ident());
|
||||
let raw = self.raw.take().unwrap();
|
||||
let pending_writes = self.pending_writes.lock().take().unwrap();
|
||||
// SAFETY: We are in the Drop impl and we don't use self.pending_writes anymore after this point.
|
||||
let pending_writes = unsafe { ManuallyDrop::take(&mut self.pending_writes.lock()) };
|
||||
pending_writes.dispose(&raw);
|
||||
self.command_allocator.dispose(&raw);
|
||||
unsafe {
|
||||
@@ -307,7 +309,10 @@ impl<A: HalApi> Device<A> {
|
||||
features: desc.required_features,
|
||||
downlevel,
|
||||
instance_flags,
|
||||
pending_writes: Mutex::new(rank::DEVICE_PENDING_WRITES, Some(pending_writes)),
|
||||
pending_writes: Mutex::new(
|
||||
rank::DEVICE_PENDING_WRITES,
|
||||
ManuallyDrop::new(pending_writes),
|
||||
),
|
||||
deferred_destroy: Mutex::new(rank::DEVICE_DEFERRED_DESTROY, Vec::new()),
|
||||
usage_scopes: Mutex::new(rank::DEVICE_USAGE_SCOPES, Default::default()),
|
||||
})
|
||||
@@ -438,7 +443,7 @@ impl<A: HalApi> Device<A> {
|
||||
.map_err(DeviceError::from)?
|
||||
};
|
||||
}
|
||||
log::info!("Device::maintain: waiting for submission index {submission_index}");
|
||||
log::trace!("Device::maintain: waiting for submission index {submission_index}");
|
||||
|
||||
let mut life_tracker = self.lock_life();
|
||||
let submission_closures =
|
||||
@@ -991,6 +996,8 @@ impl<A: HalApi> Device<A> {
|
||||
texture: &Arc<Texture<A>>,
|
||||
desc: &resource::TextureViewDescriptor,
|
||||
) -> Result<Arc<TextureView<A>>, resource::CreateTextureViewError> {
|
||||
self.check_is_valid()?;
|
||||
|
||||
let snatch_guard = texture.device.snatchable_lock.read();
|
||||
|
||||
let texture_raw = texture.try_raw(&snatch_guard)?;
|
||||
@@ -1223,12 +1230,6 @@ impl<A: HalApi> Device<A> {
|
||||
texture.hal_usage & mask_copy & mask_dimension & mask_mip_level
|
||||
};
|
||||
|
||||
log::debug!(
|
||||
"Create view for {} filters usages to {:?}",
|
||||
texture.error_ident(),
|
||||
usage
|
||||
);
|
||||
|
||||
// use the combined depth-stencil format for the view
|
||||
let format = if resolved_format.is_depth_stencil_component(texture.desc.format) {
|
||||
texture.desc.format
|
||||
@@ -1594,7 +1595,7 @@ impl<A: HalApi> Device<A> {
|
||||
|
||||
let encoder = self
|
||||
.command_allocator
|
||||
.acquire_encoder(self.raw(), queue.raw.as_ref().unwrap())?;
|
||||
.acquire_encoder(self.raw(), queue.raw())?;
|
||||
|
||||
Ok(command::CommandBuffer::new(
|
||||
encoder,
|
||||
@@ -2069,8 +2070,6 @@ impl<A: HalApi> Device<A> {
|
||||
used.textures
|
||||
.add_single(texture, Some(view.selector.clone()), internal_use);
|
||||
|
||||
texture.same_device_as(view.as_ref())?;
|
||||
|
||||
texture.check_usage(pub_usage)?;
|
||||
|
||||
used_texture_ranges.push(TextureInitTrackerAction {
|
||||
@@ -2587,11 +2586,29 @@ impl<A: HalApi> Device<A> {
|
||||
derived_group_layouts.pop();
|
||||
}
|
||||
|
||||
let mut unique_bind_group_layouts = PreHashedMap::default();
|
||||
|
||||
let bind_group_layouts = derived_group_layouts
|
||||
.into_iter()
|
||||
.map(|bgl_entry_map| {
|
||||
self.create_bind_group_layout(&None, bgl_entry_map, bgl::Origin::Derived)
|
||||
.map(Arc::new)
|
||||
.map(|mut bgl_entry_map| {
|
||||
bgl_entry_map.sort();
|
||||
match unique_bind_group_layouts.entry(PreHashedKey::from_key(&bgl_entry_map)) {
|
||||
std::collections::hash_map::Entry::Occupied(v) => Ok(Arc::clone(v.get())),
|
||||
std::collections::hash_map::Entry::Vacant(e) => {
|
||||
match self.create_bind_group_layout(
|
||||
&None,
|
||||
bgl_entry_map,
|
||||
bgl::Origin::Derived,
|
||||
) {
|
||||
Ok(bgl) => {
|
||||
let bgl = Arc::new(bgl);
|
||||
e.insert(bgl.clone());
|
||||
Ok(bgl)
|
||||
}
|
||||
Err(e) => Err(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.collect::<Result<Vec<_>, _>>()?;
|
||||
|
||||
@@ -2689,7 +2706,6 @@ impl<A: HalApi> Device<A> {
|
||||
entry_point: final_entry_point_name.as_ref(),
|
||||
constants: desc.stage.constants.as_ref(),
|
||||
zero_initialize_workgroup_memory: desc.stage.zero_initialize_workgroup_memory,
|
||||
vertex_pulling_transform: false,
|
||||
},
|
||||
cache: cache.as_ref().and_then(|it| it.raw.as_ref()),
|
||||
};
|
||||
@@ -2726,11 +2742,12 @@ impl<A: HalApi> Device<A> {
|
||||
|
||||
if is_auto_layout {
|
||||
for bgl in pipeline.layout.bind_group_layouts.iter() {
|
||||
bgl.exclusive_pipeline
|
||||
// `bind_group_layouts` might contain duplicate entries, so we need to ignore the result.
|
||||
let _ = bgl
|
||||
.exclusive_pipeline
|
||||
.set(binding_model::ExclusivePipeline::Compute(Arc::downgrade(
|
||||
&pipeline,
|
||||
)))
|
||||
.unwrap();
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2773,7 +2790,6 @@ impl<A: HalApi> Device<A> {
|
||||
.iter()
|
||||
.any(|ct| ct.write_mask != first.write_mask || ct.blend != first.blend)
|
||||
} {
|
||||
log::debug!("Color targets: {:?}", color_targets);
|
||||
self.require_downlevel_flags(wgt::DownlevelFlags::INDEPENDENT_BLEND)?;
|
||||
}
|
||||
}
|
||||
@@ -3109,7 +3125,6 @@ impl<A: HalApi> Device<A> {
|
||||
entry_point: &vertex_entry_point_name,
|
||||
constants: stage_desc.constants.as_ref(),
|
||||
zero_initialize_workgroup_memory: stage_desc.zero_initialize_workgroup_memory,
|
||||
vertex_pulling_transform: stage_desc.vertex_pulling_transform,
|
||||
}
|
||||
};
|
||||
|
||||
@@ -3119,6 +3134,7 @@ impl<A: HalApi> Device<A> {
|
||||
let stage = wgt::ShaderStages::FRAGMENT;
|
||||
|
||||
let shader_module = &fragment_state.stage.module;
|
||||
shader_module.same_device(self)?;
|
||||
|
||||
let stage_err = |error| pipeline::CreateRenderPipelineError::Stage { stage, error };
|
||||
|
||||
@@ -3165,7 +3181,6 @@ impl<A: HalApi> Device<A> {
|
||||
zero_initialize_workgroup_memory: fragment_state
|
||||
.stage
|
||||
.zero_initialize_workgroup_memory,
|
||||
vertex_pulling_transform: false,
|
||||
})
|
||||
}
|
||||
None => None,
|
||||
@@ -3352,11 +3367,12 @@ impl<A: HalApi> Device<A> {
|
||||
|
||||
if is_auto_layout {
|
||||
for bgl in pipeline.layout.bind_group_layouts.iter() {
|
||||
bgl.exclusive_pipeline
|
||||
// `bind_group_layouts` might contain duplicate entries, so we need to ignore the result.
|
||||
let _ = bgl
|
||||
.exclusive_pipeline
|
||||
.set(binding_model::ExclusivePipeline::Render(Arc::downgrade(
|
||||
&pipeline,
|
||||
)))
|
||||
.unwrap();
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3451,27 +3467,20 @@ impl<A: HalApi> Device<A> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "replay")]
|
||||
pub(crate) fn wait_for_submit(
|
||||
&self,
|
||||
submission_index: SubmissionIndex,
|
||||
) -> Result<(), WaitIdleError> {
|
||||
submission_index: crate::SubmissionIndex,
|
||||
) -> Result<(), DeviceError> {
|
||||
let guard = self.fence.read();
|
||||
let fence = guard.as_ref().unwrap();
|
||||
let last_done_index = unsafe {
|
||||
self.raw
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.get_fence_value(fence)
|
||||
.map_err(DeviceError::from)?
|
||||
};
|
||||
let last_done_index = unsafe { self.raw.as_ref().unwrap().get_fence_value(fence)? };
|
||||
if last_done_index < submission_index {
|
||||
log::info!("Waiting for submission {:?}", submission_index);
|
||||
unsafe {
|
||||
self.raw
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.wait(fence, submission_index, !0)
|
||||
.map_err(DeviceError::from)?
|
||||
.wait(fence, submission_index, !0)?
|
||||
};
|
||||
drop(guard);
|
||||
let closures = self
|
||||
@@ -3592,6 +3601,13 @@ impl<A: HalApi> Device<A> {
|
||||
.map(|raw| raw.get_internal_counters())
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
pub fn generate_allocator_report(&self) -> Option<wgt::AllocatorReport> {
|
||||
self.raw
|
||||
.as_ref()
|
||||
.map(|raw| raw.generate_allocator_report())
|
||||
.unwrap_or_default()
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: HalApi> Device<A> {
|
||||
@@ -3610,7 +3626,7 @@ impl<A: HalApi> Device<A> {
|
||||
|
||||
/// Wait for idle and remove resources that we can, before we die.
|
||||
pub(crate) fn prepare_to_die(&self) {
|
||||
self.pending_writes.lock().as_mut().unwrap().deactivate();
|
||||
self.pending_writes.lock().deactivate();
|
||||
let current_index = self
|
||||
.last_successful_submission_index
|
||||
.load(Ordering::Acquire);
|
||||
|
||||
27
third_party/rust/wgpu-core/src/global.rs
vendored
27
third_party/rust/wgpu-core/src/global.rs
vendored
@@ -1,5 +1,3 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use wgt::Backend;
|
||||
|
||||
use crate::{
|
||||
@@ -8,7 +6,6 @@ use crate::{
|
||||
instance::{Instance, Surface},
|
||||
registry::{Registry, RegistryReport},
|
||||
resource_log,
|
||||
storage::Element,
|
||||
};
|
||||
|
||||
#[derive(Debug, PartialEq, Eq)]
|
||||
@@ -90,13 +87,6 @@ impl Global {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear_backend<A: HalApi>(&self, _dummy: ()) {
|
||||
let hub = A::hub(self);
|
||||
let surfaces_locked = self.surfaces.read();
|
||||
// this is used for tests, which keep the adapter
|
||||
hub.clear(&surfaces_locked, false);
|
||||
}
|
||||
|
||||
pub fn generate_report(&self) -> GlobalReport {
|
||||
GlobalReport {
|
||||
surfaces: self.surfaces.generate_report(),
|
||||
@@ -137,29 +127,22 @@ impl Drop for Global {
|
||||
// destroy hubs before the instance gets dropped
|
||||
#[cfg(vulkan)]
|
||||
{
|
||||
self.hubs.vulkan.clear(&surfaces_locked, true);
|
||||
self.hubs.vulkan.clear(&surfaces_locked);
|
||||
}
|
||||
#[cfg(metal)]
|
||||
{
|
||||
self.hubs.metal.clear(&surfaces_locked, true);
|
||||
self.hubs.metal.clear(&surfaces_locked);
|
||||
}
|
||||
#[cfg(dx12)]
|
||||
{
|
||||
self.hubs.dx12.clear(&surfaces_locked, true);
|
||||
self.hubs.dx12.clear(&surfaces_locked);
|
||||
}
|
||||
#[cfg(gles)]
|
||||
{
|
||||
self.hubs.gl.clear(&surfaces_locked, true);
|
||||
self.hubs.gl.clear(&surfaces_locked);
|
||||
}
|
||||
|
||||
// destroy surfaces
|
||||
for element in surfaces_locked.map.drain(..) {
|
||||
if let Element::Occupied(arc_surface, _) = element {
|
||||
let surface = Arc::into_inner(arc_surface)
|
||||
.expect("Surface cannot be destroyed because is still in use");
|
||||
self.instance.destroy_surface(surface);
|
||||
}
|
||||
}
|
||||
surfaces_locked.map.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
19
third_party/rust/wgpu-core/src/hub.rs
vendored
19
third_party/rust/wgpu-core/src/hub.rs
vendored
@@ -214,10 +214,7 @@ impl<A: HalApi> Hub<A> {
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: instead of having a hacky `with_adapters` parameter,
|
||||
// we should have `clear_device(device_id)` that specifically destroys
|
||||
// everything related to a logical device.
|
||||
pub(crate) fn clear(&self, surface_guard: &Storage<Surface>, with_adapters: bool) {
|
||||
pub(crate) fn clear(&self, surface_guard: &Storage<Surface>) {
|
||||
use hal::Surface;
|
||||
|
||||
let mut devices = self.devices.write();
|
||||
@@ -248,7 +245,6 @@ impl<A: HalApi> Hub<A> {
|
||||
let suf = A::surface_as_hal(surface);
|
||||
unsafe {
|
||||
suf.unwrap().unconfigure(device.raw());
|
||||
//TODO: we could destroy the surface here
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -258,17 +254,8 @@ impl<A: HalApi> Hub<A> {
|
||||
self.queues.write().map.clear();
|
||||
devices.map.clear();
|
||||
|
||||
if with_adapters {
|
||||
drop(devices);
|
||||
self.adapters.write().map.clear();
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn surface_unconfigure(&self, device: &Device<A>, surface: &A::Surface) {
|
||||
unsafe {
|
||||
use hal::Surface;
|
||||
surface.unconfigure(device.raw());
|
||||
}
|
||||
drop(devices);
|
||||
self.adapters.write().map.clear();
|
||||
}
|
||||
|
||||
pub fn generate_report(&self) -> HubReport {
|
||||
|
||||
78
third_party/rust/wgpu-core/src/instance.rs
vendored
78
third_party/rust/wgpu-core/src/instance.rs
vendored
@@ -1,5 +1,5 @@
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
use std::{borrow::Cow, collections::HashMap};
|
||||
|
||||
use crate::{
|
||||
api_log,
|
||||
@@ -23,9 +23,10 @@ type HalInstance<A> = <A as hal::Api>::Instance;
|
||||
type HalSurface<A> = <A as hal::Api>::Surface;
|
||||
|
||||
#[derive(Clone, Debug, Error)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[error("Limit '{name}' value {requested} is better than allowed {allowed}")]
|
||||
pub struct FailedLimit {
|
||||
name: &'static str,
|
||||
name: Cow<'static, str>,
|
||||
requested: u64,
|
||||
allowed: u64,
|
||||
}
|
||||
@@ -35,7 +36,7 @@ fn check_limits(requested: &wgt::Limits, allowed: &wgt::Limits) -> Vec<FailedLim
|
||||
|
||||
requested.check_limits_with_fail_fn(allowed, false, |name, requested, allowed| {
|
||||
failed.push(FailedLimit {
|
||||
name,
|
||||
name: Cow::Borrowed(name),
|
||||
requested,
|
||||
allowed,
|
||||
})
|
||||
@@ -111,24 +112,6 @@ impl Instance {
|
||||
flags: instance_desc.flags,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn destroy_surface(&self, surface: Surface) {
|
||||
fn destroy<A: HalApi>(instance: &Option<A::Instance>, mut surface: Option<HalSurface<A>>) {
|
||||
if let Some(surface) = surface.take() {
|
||||
unsafe {
|
||||
instance.as_ref().unwrap().destroy_surface(surface);
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(vulkan)]
|
||||
destroy::<hal::api::Vulkan>(&self.vulkan, surface.vulkan);
|
||||
#[cfg(metal)]
|
||||
destroy::<hal::api::Metal>(&self.metal, surface.metal);
|
||||
#[cfg(dx12)]
|
||||
destroy::<hal::api::Dx12>(&self.dx12, surface.dx12);
|
||||
#[cfg(gles)]
|
||||
destroy::<hal::api::Gles>(&self.gl, surface.gl);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Surface {
|
||||
@@ -292,11 +275,7 @@ impl<A: HalApi> Adapter<A> {
|
||||
instance_flags,
|
||||
) {
|
||||
let device = Arc::new(device);
|
||||
let queue = Queue {
|
||||
device: device.clone(),
|
||||
raw: Some(hal_device.queue),
|
||||
};
|
||||
let queue = Arc::new(queue);
|
||||
let queue = Arc::new(Queue::new(device.clone(), hal_device.queue));
|
||||
device.set_queue(&queue);
|
||||
return Ok((device, queue));
|
||||
}
|
||||
@@ -342,10 +321,6 @@ impl<A: HalApi> Adapter<A> {
|
||||
);
|
||||
}
|
||||
|
||||
if let Some(_) = desc.label {
|
||||
//TODO
|
||||
}
|
||||
|
||||
if let Some(failed) = check_limits(&desc.required_limits, &caps.limits).pop() {
|
||||
return Err(RequestDeviceError::LimitsExceeded(failed));
|
||||
}
|
||||
@@ -391,6 +366,7 @@ pub enum GetSurfaceSupportError {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Error)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
/// Error when requesting a device from the adaptor
|
||||
#[non_exhaustive]
|
||||
pub enum RequestDeviceError {
|
||||
@@ -435,6 +411,7 @@ impl<M: Marker> AdapterInputs<'_, M> {
|
||||
pub struct InvalidAdapter;
|
||||
|
||||
#[derive(Clone, Debug, Error)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[non_exhaustive]
|
||||
pub enum RequestAdapterError {
|
||||
#[error("No suitable adapter found")]
|
||||
@@ -577,9 +554,20 @@ impl Global {
|
||||
metal: Some(self.instance.metal.as_ref().map_or(
|
||||
Err(CreateSurfaceError::BackendNotEnabled(Backend::Metal)),
|
||||
|inst| {
|
||||
// we don't want to link to metal-rs for this
|
||||
#[allow(clippy::transmute_ptr_to_ref)]
|
||||
Ok(inst.create_surface_from_layer(unsafe { std::mem::transmute(layer) }))
|
||||
let layer = layer.cast();
|
||||
// SAFETY: We do this cast and deref. (rather than using `metal` to get the
|
||||
// object we want) to avoid direct coupling on the `metal` crate.
|
||||
//
|
||||
// To wit, this pointer…
|
||||
//
|
||||
// - …is properly aligned.
|
||||
// - …is dereferenceable to a `MetalLayerRef` as an invariant of the `metal`
|
||||
// field.
|
||||
// - …points to an _initialized_ `MetalLayerRef`.
|
||||
// - …is only ever aliased via an immutable reference that lives within this
|
||||
// lexical scope.
|
||||
let layer = unsafe { &*layer };
|
||||
Ok(inst.create_surface_from_layer(layer))
|
||||
},
|
||||
)?),
|
||||
#[cfg(dx12)]
|
||||
@@ -631,7 +619,7 @@ impl Global {
|
||||
) -> Result<SurfaceId, CreateSurfaceError> {
|
||||
profiling::scope!("Instance::instance_create_surface_from_visual");
|
||||
self.instance_create_surface_dx12(id_in, |inst| unsafe {
|
||||
inst.create_surface_from_visual(visual as _)
|
||||
inst.create_surface_from_visual(visual.cast())
|
||||
})
|
||||
}
|
||||
|
||||
@@ -661,7 +649,7 @@ impl Global {
|
||||
) -> Result<SurfaceId, CreateSurfaceError> {
|
||||
profiling::scope!("Instance::instance_create_surface_from_swap_chain_panel");
|
||||
self.instance_create_surface_dx12(id_in, |inst| unsafe {
|
||||
inst.create_surface_from_swap_chain_panel(swap_chain_panel as _)
|
||||
inst.create_surface_from_swap_chain_panel(swap_chain_panel.cast())
|
||||
})
|
||||
}
|
||||
|
||||
@@ -670,15 +658,11 @@ impl Global {
|
||||
|
||||
api_log!("Surface::drop {id:?}");
|
||||
|
||||
fn unconfigure<A: HalApi>(
|
||||
global: &Global,
|
||||
surface: &Option<HalSurface<A>>,
|
||||
present: &Presentation,
|
||||
) {
|
||||
fn unconfigure<A: HalApi>(surface: &Option<HalSurface<A>>, present: &Presentation) {
|
||||
if let Some(surface) = surface {
|
||||
let hub = HalApi::hub(global);
|
||||
if let Some(device) = present.device.downcast_ref::<A>() {
|
||||
hub.surface_unconfigure(device, surface);
|
||||
use hal::Surface;
|
||||
unsafe { surface.unconfigure(device.raw()) };
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -689,15 +673,15 @@ impl Global {
|
||||
|
||||
if let Some(present) = surface.presentation.lock().take() {
|
||||
#[cfg(vulkan)]
|
||||
unconfigure::<hal::api::Vulkan>(self, &surface.vulkan, &present);
|
||||
unconfigure::<hal::api::Vulkan>(&surface.vulkan, &present);
|
||||
#[cfg(metal)]
|
||||
unconfigure::<hal::api::Metal>(self, &surface.metal, &present);
|
||||
unconfigure::<hal::api::Metal>(&surface.metal, &present);
|
||||
#[cfg(dx12)]
|
||||
unconfigure::<hal::api::Dx12>(self, &surface.dx12, &present);
|
||||
unconfigure::<hal::api::Dx12>(&surface.dx12, &present);
|
||||
#[cfg(gles)]
|
||||
unconfigure::<hal::api::Gles>(self, &surface.gl, &present);
|
||||
unconfigure::<hal::api::Gles>(&surface.gl, &present);
|
||||
}
|
||||
self.instance.destroy_surface(surface);
|
||||
drop(surface)
|
||||
}
|
||||
|
||||
fn enumerate<A: HalApi>(
|
||||
|
||||
16
third_party/rust/wgpu-core/src/lib.rs
vendored
16
third_party/rust/wgpu-core/src/lib.rs
vendored
@@ -2,6 +2,20 @@
|
||||
//! It is designed for integration into browsers, as well as wrapping
|
||||
//! into other language-specific user-friendly libraries.
|
||||
//!
|
||||
#
|
||||
that [affects `wgpu-core` documentation builds \
|
||||
severely](https://github.com/gfx-rs/wgpu/issues/4905),
|
||||
the documentation for `wgpu-core` is empty unless built with
|
||||
`RUSTFLAGS="--cfg wgpu_core_doc"`, which may take a very long time.
|
||||
"#
|
||||
)]
|
||||
#![cfg(any(not(doc), wgpu_core_doc))]
|
||||
//!
|
||||
//! ## Feature flags
|
||||
#![doc = document_features::document_features!()]
|
||||
//!
|
||||
@@ -41,6 +55,7 @@
|
||||
rustdoc::private_intra_doc_links
|
||||
)]
|
||||
#![warn(
|
||||
clippy::ptr_as_ptr,
|
||||
trivial_casts,
|
||||
trivial_numeric_casts,
|
||||
unsafe_op_in_unsafe_fn,
|
||||
@@ -71,7 +86,6 @@ pub mod resource;
|
||||
mod snatch;
|
||||
pub mod storage;
|
||||
mod track;
|
||||
mod utils;
|
||||
// This is public for users who pre-compile shaders while still wanting to
|
||||
// preserve all run-time checks that `wgpu-core` does.
|
||||
// See <https://github.com/gfx-rs/wgpu/issues/3103>, after which this can be
|
||||
|
||||
4
third_party/rust/wgpu-core/src/pipeline.rs
vendored
4
third_party/rust/wgpu-core/src/pipeline.rs
vendored
@@ -147,8 +147,6 @@ pub struct ProgrammableStageDescriptor<'a> {
|
||||
/// This is required by the WebGPU spec, but may have overhead which can be avoided
|
||||
/// for cross-platform applications
|
||||
pub zero_initialize_workgroup_memory: bool,
|
||||
/// Should the pipeline attempt to transform vertex shaders to use vertex pulling.
|
||||
pub vertex_pulling_transform: bool,
|
||||
}
|
||||
|
||||
/// Describes a programmable pipeline stage.
|
||||
@@ -176,8 +174,6 @@ pub struct ResolvedProgrammableStageDescriptor<'a, A: HalApi> {
|
||||
/// This is required by the WebGPU spec, but may have overhead which can be avoided
|
||||
/// for cross-platform applications
|
||||
pub zero_initialize_workgroup_memory: bool,
|
||||
/// Should the pipeline attempt to transform vertex shaders to use vertex pulling.
|
||||
pub vertex_pulling_transform: bool,
|
||||
}
|
||||
|
||||
/// Number of implicit bind groups derived at pipeline creation.
|
||||
|
||||
27
third_party/rust/wgpu-core/src/present.rs
vendored
27
third_party/rust/wgpu-core/src/present.rs
vendored
@@ -89,8 +89,11 @@ pub enum ConfigureSurfaceError {
|
||||
requested: wgt::CompositeAlphaMode,
|
||||
available: Vec<wgt::CompositeAlphaMode>,
|
||||
},
|
||||
#[error("Requested usage is not supported")]
|
||||
UnsupportedUsage,
|
||||
#[error("Requested usage {requested:?} is not in the list of supported usages: {available:?}")]
|
||||
UnsupportedUsage {
|
||||
requested: hal::TextureUses,
|
||||
available: hal::TextureUses,
|
||||
},
|
||||
#[error("Gpu got stuck :(")]
|
||||
StuckGpu,
|
||||
}
|
||||
@@ -227,7 +230,6 @@ impl Global {
|
||||
.insert_single(&texture, hal::TextureUses::UNINITIALIZED);
|
||||
|
||||
let id = fid.assign(texture);
|
||||
log::debug!("Created CURRENT Surface Texture {:?}", id);
|
||||
|
||||
if present.acquired_texture.is_some() {
|
||||
return Err(SurfaceError::AlreadyAcquired);
|
||||
@@ -298,10 +300,6 @@ impl Global {
|
||||
|
||||
// The texture ID got added to the device tracker by `submit()`,
|
||||
// and now we are moving it away.
|
||||
log::debug!(
|
||||
"Removing swapchain texture {:?} from the device tracker",
|
||||
texture_id
|
||||
);
|
||||
let texture = hub.textures.unregister(texture_id);
|
||||
if let Some(texture) = texture {
|
||||
device
|
||||
@@ -323,13 +321,7 @@ impl Global {
|
||||
log::error!("Presented frame is from a different surface");
|
||||
Err(hal::SurfaceError::Lost)
|
||||
} else {
|
||||
unsafe {
|
||||
queue
|
||||
.raw
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.present(suf.unwrap(), raw.take().unwrap())
|
||||
}
|
||||
unsafe { queue.raw().present(suf.unwrap(), raw.take().unwrap()) }
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
@@ -339,8 +331,6 @@ impl Global {
|
||||
}
|
||||
};
|
||||
|
||||
log::debug!("Presented. End of Frame");
|
||||
|
||||
match result {
|
||||
Ok(()) => Ok(Status::Good),
|
||||
Err(err) => match err {
|
||||
@@ -390,11 +380,6 @@ impl Global {
|
||||
|
||||
// The texture ID got added to the device tracker by `submit()`,
|
||||
// and now we are moving it away.
|
||||
log::debug!(
|
||||
"Removing swapchain texture {:?} from the device tracker",
|
||||
texture_id
|
||||
);
|
||||
|
||||
let texture = hub.textures.unregister(texture_id);
|
||||
|
||||
if let Some(texture) = texture {
|
||||
|
||||
102
third_party/rust/wgpu-core/src/resource.rs
vendored
102
third_party/rust/wgpu-core/src/resource.rs
vendored
@@ -14,7 +14,7 @@ use crate::{
|
||||
resource_log,
|
||||
snatch::{ExclusiveSnatchGuard, SnatchGuard, Snatchable},
|
||||
track::{SharedTrackerIndexAllocator, TextureSelector, TrackerIndex},
|
||||
Label, LabelHelpers, SubmissionIndex,
|
||||
Label, LabelHelpers,
|
||||
};
|
||||
|
||||
use hal::CommandEncoder;
|
||||
@@ -22,13 +22,13 @@ use smallvec::SmallVec;
|
||||
use thiserror::Error;
|
||||
|
||||
use std::{
|
||||
borrow::Borrow,
|
||||
borrow::{Borrow, Cow},
|
||||
fmt::Debug,
|
||||
iter,
|
||||
mem::{self, ManuallyDrop},
|
||||
ops::Range,
|
||||
ptr::NonNull,
|
||||
sync::{atomic::Ordering, Arc, Weak},
|
||||
sync::{Arc, Weak},
|
||||
};
|
||||
|
||||
/// Information about the wgpu-core resource.
|
||||
@@ -54,14 +54,6 @@ use std::{
|
||||
pub(crate) struct TrackingData {
|
||||
tracker_index: TrackerIndex,
|
||||
tracker_indices: Arc<SharedTrackerIndexAllocator>,
|
||||
/// The index of the last queue submission in which the resource
|
||||
/// was used.
|
||||
///
|
||||
/// Each queue submission is fenced and assigned an index number
|
||||
/// sequentially. Thus, when a queue submission completes, we know any
|
||||
/// resources used in that submission and any lower-numbered submissions are
|
||||
/// no longer in use by the GPU.
|
||||
submission_index: hal::AtomicFenceValue,
|
||||
}
|
||||
|
||||
impl Drop for TrackingData {
|
||||
@@ -75,28 +67,18 @@ impl TrackingData {
|
||||
Self {
|
||||
tracker_index: tracker_indices.alloc(),
|
||||
tracker_indices,
|
||||
submission_index: hal::AtomicFenceValue::new(0),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn tracker_index(&self) -> TrackerIndex {
|
||||
self.tracker_index
|
||||
}
|
||||
|
||||
/// Record that this resource will be used by the queue submission with the
|
||||
/// given index.
|
||||
pub(crate) fn use_at(&self, submit_index: SubmissionIndex) {
|
||||
self.submission_index.store(submit_index, Ordering::Release);
|
||||
}
|
||||
|
||||
pub(crate) fn submission_index(&self) -> SubmissionIndex {
|
||||
self.submission_index.load(Ordering::Acquire)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
pub struct ResourceErrorIdent {
|
||||
r#type: &'static str,
|
||||
r#type: Cow<'static, str>,
|
||||
label: String,
|
||||
}
|
||||
|
||||
@@ -174,7 +156,7 @@ pub(crate) trait Labeled: ResourceType {
|
||||
|
||||
fn error_ident(&self) -> ResourceErrorIdent {
|
||||
ResourceErrorIdent {
|
||||
r#type: Self::TYPE,
|
||||
r#type: Cow::Borrowed(Self::TYPE),
|
||||
label: self.label().to_owned(),
|
||||
}
|
||||
}
|
||||
@@ -193,10 +175,6 @@ macro_rules! impl_labeled {
|
||||
|
||||
pub(crate) trait Trackable: Labeled {
|
||||
fn tracker_index(&self) -> TrackerIndex;
|
||||
/// Record that this resource will be used by the queue submission with the
|
||||
/// given index.
|
||||
fn use_at(&self, submit_index: SubmissionIndex);
|
||||
fn submission_index(&self) -> SubmissionIndex;
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
@@ -206,12 +184,6 @@ macro_rules! impl_trackable {
|
||||
fn tracker_index(&self) -> $crate::track::TrackerIndex {
|
||||
self.tracking_data.tracker_index()
|
||||
}
|
||||
fn use_at(&self, submit_index: $crate::SubmissionIndex) {
|
||||
self.tracking_data.use_at(submit_index)
|
||||
}
|
||||
fn submission_index(&self) -> $crate::SubmissionIndex {
|
||||
self.tracking_data.submission_index()
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -370,6 +342,7 @@ pub struct BufferMapOperation {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Error)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[non_exhaustive]
|
||||
pub enum BufferAccessError {
|
||||
#[error(transparent)]
|
||||
@@ -418,6 +391,7 @@ pub enum BufferAccessError {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Error)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[error("Usage flags {actual:?} of {res} do not contain required usage flags {expected:?}")]
|
||||
pub struct MissingBufferUsageError {
|
||||
pub(crate) res: ResourceErrorIdent,
|
||||
@@ -434,6 +408,7 @@ pub struct MissingTextureUsageError {
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Error)]
|
||||
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
|
||||
#[error("{0} has been destroyed")]
|
||||
pub struct DestroyedResourceError(pub ResourceErrorIdent);
|
||||
|
||||
@@ -642,7 +617,6 @@ impl<A: HalApi> Buffer<A> {
|
||||
let device = &self.device;
|
||||
let snatch_guard = device.snatchable_lock.read();
|
||||
let raw_buf = self.try_raw(&snatch_guard)?;
|
||||
log::debug!("{} map state -> Idle", self.error_ident());
|
||||
match mem::replace(&mut *self.map_state.lock(), BufferMapState::Idle) {
|
||||
BufferMapState::Init { staging_buffer } => {
|
||||
#[cfg(feature = "trace")]
|
||||
@@ -657,11 +631,9 @@ impl<A: HalApi> Buffer<A> {
|
||||
}
|
||||
|
||||
let mut pending_writes = device.pending_writes.lock();
|
||||
let pending_writes = pending_writes.as_mut().unwrap();
|
||||
|
||||
let staging_buffer = staging_buffer.flush();
|
||||
|
||||
self.use_at(device.active_submission_index.load(Ordering::Relaxed) + 1);
|
||||
let region = wgt::BufferSize::new(self.size).map(|size| hal::BufferCopy {
|
||||
src_offset: 0,
|
||||
dst_offset: 0,
|
||||
@@ -738,7 +710,7 @@ impl<A: HalApi> Buffer<A> {
|
||||
};
|
||||
|
||||
queue::TempResource::DestroyedBuffer(DestroyedBuffer {
|
||||
raw: Some(raw),
|
||||
raw: ManuallyDrop::new(raw),
|
||||
device: Arc::clone(&self.device),
|
||||
label: self.label().to_owned(),
|
||||
bind_groups,
|
||||
@@ -746,14 +718,14 @@ impl<A: HalApi> Buffer<A> {
|
||||
};
|
||||
|
||||
let mut pending_writes = device.pending_writes.lock();
|
||||
let pending_writes = pending_writes.as_mut().unwrap();
|
||||
if pending_writes.contains_buffer(self) {
|
||||
pending_writes.consume_temp(temp);
|
||||
} else {
|
||||
let last_submit_index = self.submission_index();
|
||||
device
|
||||
.lock_life()
|
||||
.schedule_resource_destruction(temp, last_submit_index);
|
||||
let mut life_lock = device.lock_life();
|
||||
let last_submit_index = life_lock.get_buffer_latest_submission_index(self);
|
||||
if let Some(last_submit_index) = last_submit_index {
|
||||
life_lock.schedule_resource_destruction(temp, last_submit_index);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -788,7 +760,7 @@ crate::impl_trackable!(Buffer);
|
||||
/// A buffer that has been marked as destroyed and is staged for actual deletion soon.
|
||||
#[derive(Debug)]
|
||||
pub struct DestroyedBuffer<A: HalApi> {
|
||||
raw: Option<A::Buffer>,
|
||||
raw: ManuallyDrop<A::Buffer>,
|
||||
device: Arc<Device<A>>,
|
||||
label: String,
|
||||
bind_groups: Vec<Weak<BindGroup<A>>>,
|
||||
@@ -808,13 +780,12 @@ impl<A: HalApi> Drop for DestroyedBuffer<A> {
|
||||
}
|
||||
drop(deferred);
|
||||
|
||||
if let Some(raw) = self.raw.take() {
|
||||
resource_log!("Destroy raw Buffer (destroyed) {:?}", self.label());
|
||||
|
||||
unsafe {
|
||||
use hal::Device;
|
||||
self.device.raw().destroy_buffer(raw);
|
||||
}
|
||||
resource_log!("Destroy raw Buffer (destroyed) {:?}", self.label());
|
||||
// SAFETY: We are in the Drop impl and we don't use self.raw anymore after this point.
|
||||
let raw = unsafe { ManuallyDrop::take(&mut self.raw) };
|
||||
unsafe {
|
||||
use hal::Device;
|
||||
self.device.raw().destroy_buffer(raw);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1201,7 +1172,7 @@ impl<A: HalApi> Texture<A> {
|
||||
};
|
||||
|
||||
queue::TempResource::DestroyedTexture(DestroyedTexture {
|
||||
raw: Some(raw),
|
||||
raw: ManuallyDrop::new(raw),
|
||||
views,
|
||||
bind_groups,
|
||||
device: Arc::clone(&self.device),
|
||||
@@ -1210,14 +1181,14 @@ impl<A: HalApi> Texture<A> {
|
||||
};
|
||||
|
||||
let mut pending_writes = device.pending_writes.lock();
|
||||
let pending_writes = pending_writes.as_mut().unwrap();
|
||||
if pending_writes.contains_texture(self) {
|
||||
pending_writes.consume_temp(temp);
|
||||
} else {
|
||||
let last_submit_index = self.submission_index();
|
||||
device
|
||||
.lock_life()
|
||||
.schedule_resource_destruction(temp, last_submit_index);
|
||||
let mut life_lock = device.lock_life();
|
||||
let last_submit_index = life_lock.get_texture_latest_submission_index(self);
|
||||
if let Some(last_submit_index) = last_submit_index {
|
||||
life_lock.schedule_resource_destruction(temp, last_submit_index);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -1390,7 +1361,7 @@ impl Global {
|
||||
/// A texture that has been marked as destroyed and is staged for actual deletion soon.
|
||||
#[derive(Debug)]
|
||||
pub struct DestroyedTexture<A: HalApi> {
|
||||
raw: Option<A::Texture>,
|
||||
raw: ManuallyDrop<A::Texture>,
|
||||
views: Vec<Weak<TextureView<A>>>,
|
||||
bind_groups: Vec<Weak<BindGroup<A>>>,
|
||||
device: Arc<Device<A>>,
|
||||
@@ -1416,13 +1387,12 @@ impl<A: HalApi> Drop for DestroyedTexture<A> {
|
||||
}
|
||||
drop(deferred);
|
||||
|
||||
if let Some(raw) = self.raw.take() {
|
||||
resource_log!("Destroy raw Texture (destroyed) {:?}", self.label());
|
||||
|
||||
unsafe {
|
||||
use hal::Device;
|
||||
self.device.raw().destroy_texture(raw);
|
||||
}
|
||||
resource_log!("Destroy raw Texture (destroyed) {:?}", self.label());
|
||||
// SAFETY: We are in the Drop impl and we don't use self.raw anymore after this point.
|
||||
let raw = unsafe { ManuallyDrop::take(&mut self.raw) };
|
||||
unsafe {
|
||||
use hal::Device;
|
||||
self.device.raw().destroy_texture(raw);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1632,6 +1602,8 @@ impl<A: HalApi> TextureView<A> {
|
||||
#[derive(Clone, Debug, Error)]
|
||||
#[non_exhaustive]
|
||||
pub enum CreateTextureViewError {
|
||||
#[error(transparent)]
|
||||
Device(#[from] DeviceError),
|
||||
#[error("TextureId {0:?} is invalid")]
|
||||
InvalidTextureId(TextureId),
|
||||
#[error(transparent)]
|
||||
|
||||
3
third_party/rust/wgpu-core/src/storage.rs
vendored
3
third_party/rust/wgpu-core/src/storage.rs
vendored
@@ -119,13 +119,11 @@ where
|
||||
}
|
||||
|
||||
pub(crate) fn insert(&mut self, id: Id<T::Marker>, value: Arc<T>) {
|
||||
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: Id<T::Marker>) {
|
||||
log::trace!("User is inserting as error {}{:?}", T::TYPE, id);
|
||||
let (index, epoch, _) = id.unzip();
|
||||
self.insert_impl(index as usize, epoch, Element::Error(epoch))
|
||||
}
|
||||
@@ -143,7 +141,6 @@ where
|
||||
}
|
||||
|
||||
pub(crate) fn remove(&mut self, id: Id<T::Marker>) -> Option<Arc<T>> {
|
||||
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) => {
|
||||
|
||||
24
third_party/rust/wgpu-core/src/track/buffer.rs
vendored
24
third_party/rust/wgpu-core/src/track/buffer.rs
vendored
@@ -1,9 +1,8 @@
|
||||
/*! Buffer Trackers
|
||||
*
|
||||
* Buffers are represented by a single state for the whole resource,
|
||||
* a 16 bit bitflag of buffer usages. Because there is only ever
|
||||
* one subresource, they have no selector.
|
||||
!*/
|
||||
//! Buffer Trackers
|
||||
//!
|
||||
//! Buffers are represented by a single state for the whole resource,
|
||||
//! a 16 bit bitflag of buffer usages. Because there is only ever
|
||||
//! one subresource, they have no selector.
|
||||
|
||||
use std::sync::{Arc, Weak};
|
||||
|
||||
@@ -277,6 +276,11 @@ impl<A: HalApi> BufferTracker<A> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if the given buffer is tracked.
|
||||
pub fn contains(&self, buffer: &Buffer<A>) -> bool {
|
||||
self.metadata.contains(buffer.tracker_index().as_usize())
|
||||
}
|
||||
|
||||
/// Returns a list of all buffers tracked.
|
||||
pub fn used_resources(&self) -> impl Iterator<Item = Arc<Buffer<A>>> + '_ {
|
||||
self.metadata.owned_resources()
|
||||
@@ -731,8 +735,6 @@ unsafe fn insert<T: Clone>(
|
||||
strict_assert_eq!(invalid_resource_state(new_start_state), false);
|
||||
strict_assert_eq!(invalid_resource_state(new_end_state), false);
|
||||
|
||||
log::trace!("\tbuf {index}: insert {new_start_state:?}..{new_end_state:?}");
|
||||
|
||||
unsafe {
|
||||
if let Some(&mut ref mut start_state) = start_states {
|
||||
*start_state.get_unchecked_mut(index) = new_start_state;
|
||||
@@ -747,7 +749,7 @@ unsafe fn insert<T: Clone>(
|
||||
#[inline(always)]
|
||||
unsafe fn merge<A: HalApi>(
|
||||
current_states: &mut [BufferUses],
|
||||
index32: u32,
|
||||
_index32: u32,
|
||||
index: usize,
|
||||
state_provider: BufferStateProvider<'_>,
|
||||
metadata_provider: ResourceMetadataProvider<'_, Arc<Buffer<A>>>,
|
||||
@@ -765,8 +767,6 @@ unsafe fn merge<A: HalApi>(
|
||||
));
|
||||
}
|
||||
|
||||
log::trace!("\tbuf {index32}: merge {current_state:?} + {new_state:?}");
|
||||
|
||||
*current_state = merged_state;
|
||||
|
||||
Ok(())
|
||||
@@ -791,8 +791,6 @@ unsafe fn barrier(
|
||||
selector: (),
|
||||
usage: current_state..new_state,
|
||||
});
|
||||
|
||||
log::trace!("\tbuf {index}: transition {current_state:?} -> {new_state:?}");
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
|
||||
@@ -67,7 +67,7 @@ impl<T: Clone> ResourceMetadata<T> {
|
||||
|
||||
/// Returns true if the set contains the resource with the given index.
|
||||
pub(super) fn contains(&self, index: usize) -> bool {
|
||||
self.owned[index]
|
||||
self.owned.get(index).unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Returns true if the set contains the resource with the given index.
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
/*! Stateless Trackers
|
||||
*
|
||||
* Stateless trackers don't have any state, so make no
|
||||
* distinction between a usage scope and a full tracker.
|
||||
!*/
|
||||
//! Stateless Trackers
|
||||
//!
|
||||
//! Stateless trackers don't have any state, so make no
|
||||
//! distinction between a usage scope and a full tracker.
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
@@ -34,12 +33,6 @@ impl<T: Trackable> StatelessBindGroupState<T> {
|
||||
resources.sort_unstable_by_key(|resource| resource.tracker_index());
|
||||
}
|
||||
|
||||
/// Returns a list of all resources tracked. May contain duplicates.
|
||||
pub fn used_resources(&self) -> impl Iterator<Item = Arc<T>> + '_ {
|
||||
let resources = self.resources.lock();
|
||||
resources.iter().cloned().collect::<Vec<_>>().into_iter()
|
||||
}
|
||||
|
||||
/// Adds the given resource.
|
||||
pub fn add_single(&self, resource: &Arc<T>) {
|
||||
let mut resources = self.resources.lock();
|
||||
@@ -79,11 +72,6 @@ impl<T: Trackable> StatelessTracker<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a list of all resources tracked.
|
||||
pub fn used_resources(&self) -> impl Iterator<Item = Arc<T>> + '_ {
|
||||
self.metadata.owned_resources()
|
||||
}
|
||||
|
||||
/// Inserts a single resource into the resource tracker.
|
||||
///
|
||||
/// If the resource already exists in the tracker, it will be overwritten.
|
||||
|
||||
82
third_party/rust/wgpu-core/src/track/texture.rs
vendored
82
third_party/rust/wgpu-core/src/track/texture.rs
vendored
@@ -1,23 +1,22 @@
|
||||
/*! Texture Trackers
|
||||
*
|
||||
* Texture trackers are significantly more complicated than
|
||||
* the buffer trackers because textures can be in a "complex"
|
||||
* state where each individual subresource can potentially be
|
||||
* in a different state from every other subtresource. These
|
||||
* complex states are stored separately from the simple states
|
||||
* because they are signifignatly more difficult to track and
|
||||
* most resources spend the vast majority of their lives in
|
||||
* simple states.
|
||||
*
|
||||
* There are two special texture usages: `UNKNOWN` and `UNINITIALIZED`.
|
||||
* - `UNKNOWN` is only used in complex states and is used to signify
|
||||
* that the complex state does not know anything about those subresources.
|
||||
* It cannot leak into transitions, it is invalid to transition into UNKNOWN
|
||||
* state.
|
||||
* - `UNINITIALIZED` is used in both simple and complex states to mean the texture
|
||||
* is known to be in some undefined state. Any transition away from UNINITIALIZED
|
||||
* will treat the contents as junk.
|
||||
!*/
|
||||
//! Texture Trackers
|
||||
//!
|
||||
//! Texture trackers are significantly more complicated than
|
||||
//! the buffer trackers because textures can be in a "complex"
|
||||
//! state where each individual subresource can potentially be
|
||||
//! in a different state from every other subtresource. These
|
||||
//! complex states are stored separately from the simple states
|
||||
//! because they are signifignatly more difficult to track and
|
||||
//! most resources spend the vast majority of their lives in
|
||||
//! simple states.
|
||||
//!
|
||||
//! There are two special texture usages: `UNKNOWN` and `UNINITIALIZED`.
|
||||
//! - `UNKNOWN` is only used in complex states and is used to signify
|
||||
//! that the complex state does not know anything about those subresources.
|
||||
//! It cannot leak into transitions, it is invalid to transition into UNKNOWN
|
||||
//! state.
|
||||
//! - `UNINITIALIZED` is used in both simple and complex states to mean the texture
|
||||
//! is known to be in some undefined state. Any transition away from UNINITIALIZED
|
||||
//! will treat the contents as junk.
|
||||
|
||||
use super::{range::RangedStates, PendingTransition, PendingTransitionList, TrackerIndex};
|
||||
use crate::{
|
||||
@@ -446,6 +445,11 @@ impl<A: HalApi> TextureTracker<A> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns true if the tracker owns the given texture.
|
||||
pub fn contains(&self, texture: &Texture<A>) -> bool {
|
||||
self.metadata.contains(texture.tracker_index().as_usize())
|
||||
}
|
||||
|
||||
/// Returns a list of all textures tracked.
|
||||
pub fn used_resources(&self) -> impl Iterator<Item = Arc<Texture<A>>> + '_ {
|
||||
self.metadata.owned_resources()
|
||||
@@ -1120,8 +1124,6 @@ unsafe fn insert<T: Clone>(
|
||||
// check that resource states don't have any conflicts.
|
||||
strict_assert_eq!(invalid_resource_state(state), false);
|
||||
|
||||
log::trace!("\ttex {index}: insert start {state:?}");
|
||||
|
||||
if let Some(start_state) = start_state {
|
||||
unsafe { *start_state.simple.get_unchecked_mut(index) = state };
|
||||
}
|
||||
@@ -1137,8 +1139,6 @@ unsafe fn insert<T: Clone>(
|
||||
let complex =
|
||||
unsafe { ComplexTextureState::from_selector_state_iter(full_range, state_iter) };
|
||||
|
||||
log::trace!("\ttex {index}: insert start {complex:?}");
|
||||
|
||||
if let Some(start_state) = start_state {
|
||||
unsafe { *start_state.simple.get_unchecked_mut(index) = TextureUses::COMPLEX };
|
||||
start_state.complex.insert(index, complex.clone());
|
||||
@@ -1159,8 +1159,6 @@ unsafe fn insert<T: Clone>(
|
||||
// check that resource states don't have any conflicts.
|
||||
strict_assert_eq!(invalid_resource_state(state), false);
|
||||
|
||||
log::trace!("\ttex {index}: insert end {state:?}");
|
||||
|
||||
// We only need to insert into the end, as there is guaranteed to be
|
||||
// a start state provider.
|
||||
unsafe { *end_state.simple.get_unchecked_mut(index) = state };
|
||||
@@ -1172,8 +1170,6 @@ unsafe fn insert<T: Clone>(
|
||||
ComplexTextureState::from_selector_state_iter(full_range, state_iter)
|
||||
};
|
||||
|
||||
log::trace!("\ttex {index}: insert end {complex:?}");
|
||||
|
||||
// We only need to insert into the end, as there is guaranteed to be
|
||||
// a start state provider.
|
||||
unsafe { *end_state.simple.get_unchecked_mut(index) = TextureUses::COMPLEX };
|
||||
@@ -1211,8 +1207,6 @@ unsafe fn merge<A: HalApi>(
|
||||
(SingleOrManyStates::Single(current_simple), SingleOrManyStates::Single(new_simple)) => {
|
||||
let merged_state = *current_simple | new_simple;
|
||||
|
||||
log::trace!("\ttex {index}: merge simple {current_simple:?} + {new_simple:?}");
|
||||
|
||||
if invalid_resource_state(merged_state) {
|
||||
return Err(ResourceUsageCompatibilityError::from_texture(
|
||||
unsafe { metadata_provider.get(index) },
|
||||
@@ -1238,8 +1232,6 @@ unsafe fn merge<A: HalApi>(
|
||||
for (selector, new_state) in new_many {
|
||||
let merged_state = *current_simple | new_state;
|
||||
|
||||
log::trace!("\ttex {index}: merge {selector:?} {current_simple:?} + {new_state:?}");
|
||||
|
||||
if invalid_resource_state(merged_state) {
|
||||
return Err(ResourceUsageCompatibilityError::from_texture(
|
||||
unsafe { metadata_provider.get(index) },
|
||||
@@ -1276,11 +1268,6 @@ unsafe fn merge<A: HalApi>(
|
||||
// simple states are never unknown.
|
||||
let merged_state = merged_state - TextureUses::UNKNOWN;
|
||||
|
||||
log::trace!(
|
||||
"\ttex {index}: merge mip {mip_id} layers {layers:?} \
|
||||
{current_layer_state:?} + {new_simple:?}"
|
||||
);
|
||||
|
||||
if invalid_resource_state(merged_state) {
|
||||
return Err(ResourceUsageCompatibilityError::from_texture(
|
||||
unsafe { metadata_provider.get(index) },
|
||||
@@ -1317,11 +1304,6 @@ unsafe fn merge<A: HalApi>(
|
||||
continue;
|
||||
}
|
||||
|
||||
log::trace!(
|
||||
"\ttex {index}: merge mip {mip_id} layers {layers:?} \
|
||||
{current_layer_state:?} + {new_state:?}"
|
||||
);
|
||||
|
||||
if invalid_resource_state(merged_state) {
|
||||
return Err(ResourceUsageCompatibilityError::from_texture(
|
||||
unsafe { metadata_provider.get(index) },
|
||||
@@ -1369,8 +1351,6 @@ unsafe fn barrier(
|
||||
return;
|
||||
}
|
||||
|
||||
log::trace!("\ttex {index}: transition simple {current_simple:?} -> {new_simple:?}");
|
||||
|
||||
barriers.push(PendingTransition {
|
||||
id: index as _,
|
||||
selector: texture_selector.clone(),
|
||||
@@ -1387,10 +1367,6 @@ unsafe fn barrier(
|
||||
continue;
|
||||
}
|
||||
|
||||
log::trace!(
|
||||
"\ttex {index}: transition {selector:?} {current_simple:?} -> {new_state:?}"
|
||||
);
|
||||
|
||||
barriers.push(PendingTransition {
|
||||
id: index as _,
|
||||
selector,
|
||||
@@ -1411,11 +1387,6 @@ unsafe fn barrier(
|
||||
continue;
|
||||
}
|
||||
|
||||
log::trace!(
|
||||
"\ttex {index}: transition mip {mip_id} layers {layers:?} \
|
||||
{current_layer_state:?} -> {new_simple:?}"
|
||||
);
|
||||
|
||||
barriers.push(PendingTransition {
|
||||
id: index as _,
|
||||
selector: TextureSelector {
|
||||
@@ -1445,11 +1416,6 @@ unsafe fn barrier(
|
||||
continue;
|
||||
}
|
||||
|
||||
log::trace!(
|
||||
"\ttex {index}: transition mip {mip_id} layers {layers:?} \
|
||||
{current_layer_state:?} -> {new_state:?}"
|
||||
);
|
||||
|
||||
barriers.push(PendingTransition {
|
||||
id: index as _,
|
||||
selector: TextureSelector {
|
||||
|
||||
54
third_party/rust/wgpu-core/src/utils.rs
vendored
54
third_party/rust/wgpu-core/src/utils.rs
vendored
@@ -1,54 +0,0 @@
|
||||
/// If the first iterator is longer than the second, the zip implementation
|
||||
/// in the standard library will still advance the the first iterator before
|
||||
/// realizing that the second iterator has finished.
|
||||
///
|
||||
/// This implementation will advance the shorter iterator first avoiding
|
||||
/// the issue above.
|
||||
///
|
||||
/// If you can guarantee that the first iterator is always shorter than the
|
||||
/// second, you should use the zip impl in stdlib.
|
||||
pub(crate) struct ZipWithProperAdvance<
|
||||
A: ExactSizeIterator<Item = IA>,
|
||||
B: ExactSizeIterator<Item = IB>,
|
||||
IA,
|
||||
IB,
|
||||
> {
|
||||
a: A,
|
||||
b: B,
|
||||
iter_a_first: bool,
|
||||
}
|
||||
|
||||
impl<A: ExactSizeIterator<Item = IA>, B: ExactSizeIterator<Item = IB>, IA, IB>
|
||||
ZipWithProperAdvance<A, B, IA, IB>
|
||||
{
|
||||
pub(crate) fn new(a: A, b: B) -> Self {
|
||||
let iter_a_first = a.len() <= b.len();
|
||||
Self { a, b, iter_a_first }
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: ExactSizeIterator<Item = IA>, B: ExactSizeIterator<Item = IB>, IA, IB> Iterator
|
||||
for ZipWithProperAdvance<A, B, IA, IB>
|
||||
{
|
||||
type Item = (IA, IB);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.iter_a_first {
|
||||
let a = self.a.next()?;
|
||||
let b = self.b.next()?;
|
||||
Some((a, b))
|
||||
} else {
|
||||
let b = self.b.next()?;
|
||||
let a = self.a.next()?;
|
||||
Some((a, b))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: ExactSizeIterator<Item = IA>, B: ExactSizeIterator<Item = IB>, IA, IB> ExactSizeIterator
|
||||
for ZipWithProperAdvance<A, B, IA, IB>
|
||||
{
|
||||
fn len(&self) -> usize {
|
||||
self.a.len().min(self.b.len())
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
36
third_party/rust/wgpu-hal/Cargo.toml
vendored
36
third_party/rust/wgpu-hal/Cargo.toml
vendored
@@ -11,9 +11,9 @@
|
||||
|
||||
[package]
|
||||
edition = "2021"
|
||||
rust-version = "1.74"
|
||||
rust-version = "1.76"
|
||||
name = "wgpu-hal"
|
||||
version = "0.20.0"
|
||||
version = "22.0.0"
|
||||
authors = ["gfx-rs developers"]
|
||||
description = "WebGPU hardware abstraction layer"
|
||||
homepage = "https://wgpu.rs/"
|
||||
@@ -53,20 +53,20 @@ required-features = ["gles"]
|
||||
|
||||
[dependencies]
|
||||
arrayvec = "0.7"
|
||||
bitflags = "2"
|
||||
bitflags = "2.6"
|
||||
log = "0.4"
|
||||
once_cell = "1.19.0"
|
||||
parking_lot = ">=0.11, <0.13"
|
||||
raw-window-handle = "0.6"
|
||||
rustc-hash = "1.1"
|
||||
thiserror = "1"
|
||||
rustc-hash = "1.1.0"
|
||||
thiserror = "1.0.63"
|
||||
|
||||
[dependencies.glow]
|
||||
version = "0.13.1"
|
||||
version = "0.14.0"
|
||||
optional = true
|
||||
|
||||
[dependencies.naga]
|
||||
version = "0.20.0"
|
||||
version = "22.0.0"
|
||||
path = "../naga"
|
||||
|
||||
[dependencies.profiling]
|
||||
@@ -74,7 +74,7 @@ version = "1"
|
||||
default-features = false
|
||||
|
||||
[dependencies.wgt]
|
||||
version = "0.20.0"
|
||||
version = "22.0.0"
|
||||
path = "../wgpu-types"
|
||||
package = "wgpu-types"
|
||||
|
||||
@@ -84,7 +84,7 @@ env_logger = "0.11"
|
||||
glam = "0.28"
|
||||
|
||||
[dev-dependencies.naga]
|
||||
version = "0.20.0"
|
||||
version = "22.0.0"
|
||||
path = "../naga"
|
||||
features = ["wgsl-in"]
|
||||
|
||||
@@ -120,7 +120,10 @@ gles = [
|
||||
"dep:khronos-egl",
|
||||
"dep:libloading",
|
||||
"dep:ndk-sys",
|
||||
"winapi/libloaderapi",
|
||||
"windows/Win32_Graphics_OpenGL",
|
||||
"windows/Win32_Graphics_Gdi",
|
||||
"windows/Win32_System_LibraryLoader",
|
||||
"windows/Win32_UI_WindowsAndMessaging",
|
||||
]
|
||||
internal_error_panic = []
|
||||
metal = [
|
||||
@@ -223,11 +226,11 @@ optional = true
|
||||
libc = "0.2"
|
||||
|
||||
[target."cfg(windows)".dependencies.bit-set]
|
||||
version = "0.6"
|
||||
version = "0.8"
|
||||
optional = true
|
||||
|
||||
[target."cfg(windows)".dependencies.d3d12]
|
||||
version = "0.20.0"
|
||||
version = "22.0.0"
|
||||
path = "../d3d12/"
|
||||
features = ["libloading"]
|
||||
optional = true
|
||||
@@ -237,7 +240,7 @@ version = "0.6"
|
||||
optional = true
|
||||
|
||||
[target."cfg(windows)".dependencies.gpu-allocator]
|
||||
version = "0.26"
|
||||
version = "0.27"
|
||||
features = [
|
||||
"d3d12",
|
||||
"public-winapi",
|
||||
@@ -246,7 +249,7 @@ optional = true
|
||||
default-features = false
|
||||
|
||||
[target."cfg(windows)".dependencies.hassle-rs]
|
||||
version = "0.11"
|
||||
version = "0.11.0"
|
||||
optional = true
|
||||
|
||||
[target."cfg(windows)".dependencies.range-alloc]
|
||||
@@ -261,3 +264,8 @@ features = [
|
||||
"winuser",
|
||||
"dcomp",
|
||||
]
|
||||
|
||||
[target."cfg(windows)".dependencies.windows]
|
||||
version = "0.58"
|
||||
optional = true
|
||||
default-features = false
|
||||
|
||||
@@ -257,7 +257,6 @@ impl<A: hal::Api> Example<A> {
|
||||
entry_point: "vs_main",
|
||||
constants: &constants,
|
||||
zero_initialize_workgroup_memory: true,
|
||||
vertex_pulling_transform: false,
|
||||
},
|
||||
vertex_buffers: &[],
|
||||
fragment_stage: Some(hal::ProgrammableStage {
|
||||
@@ -265,7 +264,6 @@ impl<A: hal::Api> Example<A> {
|
||||
entry_point: "fs_main",
|
||||
constants: &constants,
|
||||
zero_initialize_workgroup_memory: true,
|
||||
vertex_pulling_transform: false,
|
||||
}),
|
||||
primitive: wgt::PrimitiveState {
|
||||
topology: wgt::PrimitiveTopology::TriangleStrip,
|
||||
@@ -580,7 +578,7 @@ impl<A: hal::Api> Example<A> {
|
||||
|
||||
self.surface.unconfigure(&self.device);
|
||||
self.device.exit(self.queue);
|
||||
self.instance.destroy_surface(self.surface);
|
||||
drop(self.surface);
|
||||
drop(self.adapter);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -379,7 +379,6 @@ impl<A: hal::Api> Example<A> {
|
||||
entry_point: "main",
|
||||
constants: &Default::default(),
|
||||
zero_initialize_workgroup_memory: true,
|
||||
vertex_pulling_transform: false,
|
||||
},
|
||||
cache: None,
|
||||
})
|
||||
@@ -1040,7 +1039,7 @@ impl<A: hal::Api> Example<A> {
|
||||
|
||||
self.surface.unconfigure(&self.device);
|
||||
self.device.exit(self.queue);
|
||||
self.instance.destroy_surface(self.surface);
|
||||
drop(self.surface);
|
||||
drop(self.adapter);
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user