summaryrefslogtreecommitdiffstats
path: root/third_party/rust/wgpu-core
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/wgpu-core')
-rw-r--r--third_party/rust/wgpu-core/.cargo-checksum.json2
-rw-r--r--third_party/rust/wgpu-core/Cargo.toml4
-rw-r--r--third_party/rust/wgpu-core/src/command/bundle.rs21
-rw-r--r--third_party/rust/wgpu-core/src/command/clear.rs7
-rw-r--r--third_party/rust/wgpu-core/src/command/compute.rs9
-rw-r--r--third_party/rust/wgpu-core/src/command/memory_init.rs11
-rw-r--r--third_party/rust/wgpu-core/src/command/render.rs15
-rw-r--r--third_party/rust/wgpu-core/src/command/transfer.rs19
-rw-r--r--third_party/rust/wgpu-core/src/device/global.rs33
-rw-r--r--third_party/rust/wgpu-core/src/device/life.rs15
-rw-r--r--third_party/rust/wgpu-core/src/device/mod.rs11
-rw-r--r--third_party/rust/wgpu-core/src/device/queue.rs17
-rw-r--r--third_party/rust/wgpu-core/src/device/resource.rs20
-rw-r--r--third_party/rust/wgpu-core/src/snatch.rs35
-rw-r--r--third_party/rust/wgpu-core/src/track/buffer.rs12
-rw-r--r--third_party/rust/wgpu-core/src/track/metadata.rs5
-rw-r--r--third_party/rust/wgpu-core/src/track/mod.rs50
-rw-r--r--third_party/rust/wgpu-core/src/track/texture.rs13
18 files changed, 224 insertions, 75 deletions
diff --git a/third_party/rust/wgpu-core/.cargo-checksum.json b/third_party/rust/wgpu-core/.cargo-checksum.json
index d22e0914d7..f025f2ccaa 100644
--- a/third_party/rust/wgpu-core/.cargo-checksum.json
+++ b/third_party/rust/wgpu-core/.cargo-checksum.json
@@ -1 +1 @@
-{"files":{"Cargo.toml":"4880d66b004519ca6e424fc9e2e6ac065536d36334a2e327b90422e97f2a2a35","LICENSE.APACHE":"a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9","LICENSE.MIT":"c7fea58d1cfe49634cd92e54fc10a9d871f4b275321a4cd8c09e449122caaeb4","build.rs":"a99478d7f63fb41429e3834f4d0e5cd333f94ba1834c68295f929170e16987de","src/any_surface.rs":"1c032bc1894a222a47f0116b976f1543c1140c0534678502ee1172d4f77fc515","src/binding_model.rs":"bb4aefad17957e770a5f70f00bf5853dc13da1d9f836493c9aa9adbbe7bb8147","src/command/bind.rs":"a37f042484b65d9fdea4cdab3667381623ee9a8943a6d32683d410b92736d306","src/command/bundle.rs":"fea00382acdf204bcb58522953335dd8f0092565693fa65d0c008e2698e39445","src/command/clear.rs":"03cfc0d4c689d56010391440ab279e615ef1d3235eb1f9f9df0323682d275109","src/command/compute.rs":"2b6beed328ed351ad6fe7088cfa1824c1bf4be50deaeab971cdcb09914d791de","src/command/draw.rs":"15f9ad857504d8098279f9c789317feba321c9b6b8f0de20b8ba98f358c99d89","src/command/memory_init.rs":"6ec93b9e2eb21edaa534e60770b4ba95735e9de61e74d827bc492df8e3639449","src/command/mod.rs":"1d347e1746194f7a07d1f75bd3a9d3cbe121fbaa479c25ba6b8c16e9d699e06b","src/command/query.rs":"43b78a163eb0eb5f1427b7a57b6d39a2748c25f880ba024c91e2f71e2a6a817d","src/command/render.rs":"808dc8106811b32877637851e63baeba7c7438748dec67cbb17ea93c58dc61bd","src/command/transfer.rs":"bf1077d1a99a258bad46087ae7234703627e7f4d30b38e6142d016c02deaad3a","src/conv.rs":"7e3ffe33b47a6fd3617aabf9f11cc68f1ccbee2c7343b8dbbcd0e8f3447e1ad8","src/device/any_device.rs":"65f47b58939b60f88f47861e65d5d45209492df8e73e7c1b60b3b459f510c09e","src/device/bgl.rs":"ec8bdd6e9b4cd50c25bed317275863d0c16bb6619f62ed85bf0464948010dfc1","src/device/global.rs":"ff90a9e3b261bedbec37ab1aed0bf23f1e50c5418da72184e2b175057ed18fce","src/device/life.rs":"3cacaaa74df04bb1285a36d70395b35cfa17059f8d6289b41e665ecbc64cb66a","src/device/mod.rs":"fff41f92e1a9f6660e18dc30452d9911ca827701bb8303af2ae06f1c1e1a795f","src/device/queue.rs":"da0aeebfd1d1c6e155dc89cebf75dfdb6ec18062f9512044ed7e0fef0bda2f74","src/device/resource.rs":"74d3180c12602133bee46925d3788ac510d2ad5ea141a2b46f6904f38549053b","src/device/trace.rs":"9deb1b083165e07253b4928ac2f564aba06f9089c3aca1c0a1d438d87d981542","src/error.rs":"e3b6b7a69877437f4e46af7f0e8ca1db1822beae7c8448db41c2bae0f64b2bb4","src/global.rs":"0966475959706650fd036a18d51441a8e14c3ef10107db617f597614ca47e50a","src/hal_api.rs":"1cd9c3fe1c9d8c3a24e3e7f963a2ef26e056a2b26d529b840dbc969090aaf201","src/hash_utils.rs":"e8d484027c7ce81978e4679a5e20af9416ab7d2fa595f1ca95992b29d625b0ca","src/hub.rs":"352a1b75d4535f24b06d16134421db98f910e6e719f50f863a204df6768e3369","src/id.rs":"9f67dbef5d7a416eb740281ecf8a94673f624da16f21ec33c425c11d9ed01e90","src/identity.rs":"12b820eb4b8bd7b226e15eec97d0f100a695f6b9be7acd79ad2421f2d0fe1985","src/init_tracker/buffer.rs":"61eb9cfaa312135b7a937ff6a3117f531b5b7323fae6553a41d6de9bc106d7e0","src/init_tracker/mod.rs":"a0f64730cc025113b656b4690f9dcb0ec18b8770bc7ef24c7b4ad8bebae03d24","src/init_tracker/texture.rs":"030fd594bf9948fad391390d85c5e1fec7eaf67b6e812c60f2dd59bc4fda8fd5","src/instance.rs":"b6de2a371ef3b43d3217102fe87e423dd1eb12da86b65f54b902d9eaa38b6b9f","src/lib.rs":"4ad9979442cf88557fb3b9f8d3b26c7b929a710c60cabcd1f51788917c95aecb","src/pipeline.rs":"89d88de4b8b8e1dd2bc834d101a1bdf34816ebcaa616dc795f604e9183a21cd0","src/pool.rs":"778ea1c23fcfaaa5001606e686f712f606826039d60dd5a3cd26e7de91ac057a","src/present.rs":"f69580ee0baf181162f9dd82b159596c738558d8abb60db93047effbe1436b2f","src/registry.rs":"913e651dc585ff12fe7659443c38d635a2904881e56cb7159c5ca72d45ae5800","src/resource.rs":"59731bc9a207d87b07b6db9c897e20d64be27c144bb8eb8ab2505807163acfc4","src/snatch.rs":"29a1135ee09c06883eac4df6f45b7220c2ba8f89f34232ea1d270d6e7b05c7a8","src/storage.rs":"f0c41461b8f9cdc862dbd3de04c8e720ee416c7c57310696f6f4fd22183fcc85","src/track/buffer.rs":"83a0cbb8026dbd651d32ea5a47f332f691afed1c5e6f14e78a4fe8aa25e2ad12","src/track/metadata.rs":"655985fdfdd1c7fe8220af98abadf33de7e8920b485e3dd27c28688c3dd2e47d","src/track/mod.rs":"52470a48de6b5dce55385e23ba7a3cbf512cc10cdf431a35aa42190e2fc4306d","src/track/range.rs":"2a15794e79b0470d5ba6b3267173a42f34312878e1cb288f198d2854a7888e53","src/track/stateless.rs":"305e0a493fb1cd0a325274c0757e99c19f9d14deaa8ca11ada41c1399a4ae5c4","src/track/texture.rs":"ba3e3814b341b5242548b55d77bef1d1d9e7d52d63784be98c51e342da7fefff","src/validation.rs":"026168ac4f23bc6a58a90c78fd3eb73485b3c1aad630ef43755604d1babade79"},"package":null} \ No newline at end of file
+{"files":{"Cargo.toml":"3f5fa464854359b0150d4fe82cf5b0c17874dbb3c3c708b2a9cc24ebc1a61349","LICENSE.APACHE":"a6cba85bc92e0cff7a450b1d873c0eaa2e9fc96bf472df0247a26bec77bf3ff9","LICENSE.MIT":"c7fea58d1cfe49634cd92e54fc10a9d871f4b275321a4cd8c09e449122caaeb4","build.rs":"a99478d7f63fb41429e3834f4d0e5cd333f94ba1834c68295f929170e16987de","src/any_surface.rs":"1c032bc1894a222a47f0116b976f1543c1140c0534678502ee1172d4f77fc515","src/binding_model.rs":"bb4aefad17957e770a5f70f00bf5853dc13da1d9f836493c9aa9adbbe7bb8147","src/command/bind.rs":"a37f042484b65d9fdea4cdab3667381623ee9a8943a6d32683d410b92736d306","src/command/bundle.rs":"3435ea21daba6f5a26f9a4158b342d0b9a1839da39b82fa8c23d84ee144b9da0","src/command/clear.rs":"2eb9c323c3ae3644563cab1bb1d26e4a17a54f5a120698c7f09ef9f9e9077780","src/command/compute.rs":"1ad1d8b83774422bd73c7c67c153205e451fd71602b37f34162b59e5f7dbbc75","src/command/draw.rs":"15f9ad857504d8098279f9c789317feba321c9b6b8f0de20b8ba98f358c99d89","src/command/memory_init.rs":"71550dabbf7cc3c3ff6aa4ccd31af080bb5e1cb1e21422daea63fee30294476f","src/command/mod.rs":"1d347e1746194f7a07d1f75bd3a9d3cbe121fbaa479c25ba6b8c16e9d699e06b","src/command/query.rs":"43b78a163eb0eb5f1427b7a57b6d39a2748c25f880ba024c91e2f71e2a6a817d","src/command/render.rs":"875545efa83e56face9a857c5d8c814bc46f4b0538a152933265533176ad1e84","src/command/transfer.rs":"63042151145825c5cac6459a5a254a82142c86d299895f72bef2682f71de7ad1","src/conv.rs":"7e3ffe33b47a6fd3617aabf9f11cc68f1ccbee2c7343b8dbbcd0e8f3447e1ad8","src/device/any_device.rs":"65f47b58939b60f88f47861e65d5d45209492df8e73e7c1b60b3b459f510c09e","src/device/bgl.rs":"ec8bdd6e9b4cd50c25bed317275863d0c16bb6619f62ed85bf0464948010dfc1","src/device/global.rs":"6a08dcc25059f2194999c4f5e3a57a1a96b17031873b1a871095dc58115470fb","src/device/life.rs":"efba75c8632e0bd9c655dbff1f8ff027900f388b6eeb357a9c02ddad24474b23","src/device/mod.rs":"e578d03253a9af314e1e81168d45ea8cc0a8f56df79e440dc1ade945d75277ec","src/device/queue.rs":"4405a6b8ea29093239f1556e5352f7c777f4f6b783fd5dea458fde22556741ca","src/device/resource.rs":"65f84150c467aa50615a097d15f6b4dba3514b0adf2de1e9b9837e5084619a80","src/device/trace.rs":"9deb1b083165e07253b4928ac2f564aba06f9089c3aca1c0a1d438d87d981542","src/error.rs":"e3b6b7a69877437f4e46af7f0e8ca1db1822beae7c8448db41c2bae0f64b2bb4","src/global.rs":"0966475959706650fd036a18d51441a8e14c3ef10107db617f597614ca47e50a","src/hal_api.rs":"1cd9c3fe1c9d8c3a24e3e7f963a2ef26e056a2b26d529b840dbc969090aaf201","src/hash_utils.rs":"e8d484027c7ce81978e4679a5e20af9416ab7d2fa595f1ca95992b29d625b0ca","src/hub.rs":"352a1b75d4535f24b06d16134421db98f910e6e719f50f863a204df6768e3369","src/id.rs":"9f67dbef5d7a416eb740281ecf8a94673f624da16f21ec33c425c11d9ed01e90","src/identity.rs":"12b820eb4b8bd7b226e15eec97d0f100a695f6b9be7acd79ad2421f2d0fe1985","src/init_tracker/buffer.rs":"61eb9cfaa312135b7a937ff6a3117f531b5b7323fae6553a41d6de9bc106d7e0","src/init_tracker/mod.rs":"a0f64730cc025113b656b4690f9dcb0ec18b8770bc7ef24c7b4ad8bebae03d24","src/init_tracker/texture.rs":"030fd594bf9948fad391390d85c5e1fec7eaf67b6e812c60f2dd59bc4fda8fd5","src/instance.rs":"b6de2a371ef3b43d3217102fe87e423dd1eb12da86b65f54b902d9eaa38b6b9f","src/lib.rs":"4ad9979442cf88557fb3b9f8d3b26c7b929a710c60cabcd1f51788917c95aecb","src/pipeline.rs":"89d88de4b8b8e1dd2bc834d101a1bdf34816ebcaa616dc795f604e9183a21cd0","src/pool.rs":"778ea1c23fcfaaa5001606e686f712f606826039d60dd5a3cd26e7de91ac057a","src/present.rs":"f69580ee0baf181162f9dd82b159596c738558d8abb60db93047effbe1436b2f","src/registry.rs":"913e651dc585ff12fe7659443c38d635a2904881e56cb7159c5ca72d45ae5800","src/resource.rs":"59731bc9a207d87b07b6db9c897e20d64be27c144bb8eb8ab2505807163acfc4","src/snatch.rs":"5cf0e4e4611083e8256092696ecf0caa9e855dd680c18fc7dbb227d071aa2548","src/storage.rs":"f0c41461b8f9cdc862dbd3de04c8e720ee416c7c57310696f6f4fd22183fcc85","src/track/buffer.rs":"d1b4c85dfaf1bcc93013d7f51ba677f97c36245c9de224fb328595aa15109cf6","src/track/metadata.rs":"7016911136bc5b97053f54241b01d344f5d65c4337a292c8aa32bb142a26be0c","src/track/mod.rs":"5365c532a531d224a958bd8217769ef59d67d293b4f95972c10db71f6bff1a80","src/track/range.rs":"2a15794e79b0470d5ba6b3267173a42f34312878e1cb288f198d2854a7888e53","src/track/stateless.rs":"305e0a493fb1cd0a325274c0757e99c19f9d14deaa8ca11ada41c1399a4ae5c4","src/track/texture.rs":"da83403d5990021c5db78f1ffdf69198eadb99cc77a6bc481648337a5403295c","src/validation.rs":"026168ac4f23bc6a58a90c78fd3eb73485b3c1aad630ef43755604d1babade79"},"package":null} \ No newline at end of file
diff --git a/third_party/rust/wgpu-core/Cargo.toml b/third_party/rust/wgpu-core/Cargo.toml
index 3d3b4dc80c..aef86b3bbf 100644
--- a/third_party/rust/wgpu-core/Cargo.toml
+++ b/third_party/rust/wgpu-core/Cargo.toml
@@ -11,7 +11,7 @@
[package]
edition = "2021"
-rust-version = "1.70"
+rust-version = "1.74"
name = "wgpu-core"
version = "0.19.0"
authors = ["gfx-rs developers"]
@@ -127,7 +127,7 @@ vulkan = ["hal/vulkan"]
wgsl = ["naga/wgsl-in"]
[target."cfg(all(target_arch = \"wasm32\", not(target_os = \"emscripten\")))".dependencies.web-sys]
-version = "0.3.67"
+version = "0.3.69"
features = [
"HtmlCanvasElement",
"OffscreenCanvas",
diff --git a/third_party/rust/wgpu-core/src/command/bundle.rs b/third_party/rust/wgpu-core/src/command/bundle.rs
index ab2d18bc59..47beda8ec6 100644
--- a/third_party/rust/wgpu-core/src/command/bundle.rs
+++ b/third_party/rust/wgpu-core/src/command/bundle.rs
@@ -99,6 +99,7 @@ use crate::{
pipeline::{PipelineFlags, RenderPipeline, VertexStep},
resource::{Buffer, Resource, ResourceInfo, ResourceType},
resource_log,
+ snatch::SnatchGuard,
track::RenderBundleScope,
validation::check_buffer_usage,
Label, LabelHelpers,
@@ -165,7 +166,7 @@ fn validate_indexed_draw<A: HalApi>(
) -> Result<(), DrawError> {
let last_index = first_index as u64 + index_count as u64;
let index_limit = index_state.limit();
- if last_index <= index_limit {
+ if last_index > index_limit {
return Err(DrawError::IndexBeyondLimit {
last_index,
index_limit,
@@ -894,7 +895,11 @@ impl<A: HalApi> RenderBundle<A> {
/// Note that the function isn't expected to fail, generally.
/// All the validation has already been done by this point.
/// The only failure condition is if some of the used buffers are destroyed.
- pub(super) unsafe fn execute(&self, raw: &mut A::CommandEncoder) -> Result<(), ExecutionError> {
+ pub(super) unsafe fn execute(
+ &self,
+ raw: &mut A::CommandEncoder,
+ snatch_guard: &SnatchGuard,
+ ) -> Result<(), ExecutionError> {
let mut offsets = self.base.dynamic_offsets.as_slice();
let mut pipeline_layout = None::<Arc<PipelineLayout<A>>>;
if !self.discard_hal_labels {
@@ -903,8 +908,6 @@ impl<A: HalApi> RenderBundle<A> {
}
}
- let snatch_guard = self.device.snatchable_lock.read();
-
use ArcRenderCommand as Cmd;
for command in self.base.commands.iter() {
match command {
@@ -914,7 +917,7 @@ impl<A: HalApi> RenderBundle<A> {
bind_group,
} => {
let raw_bg = bind_group
- .raw(&snatch_guard)
+ .raw(snatch_guard)
.ok_or(ExecutionError::InvalidBindGroup(bind_group.info.id()))?;
unsafe {
raw.set_bind_group(
@@ -938,7 +941,7 @@ impl<A: HalApi> RenderBundle<A> {
size,
} => {
let buffer: &A::Buffer = buffer
- .raw(&snatch_guard)
+ .raw(snatch_guard)
.ok_or(ExecutionError::DestroyedBuffer(buffer.info.id()))?;
let bb = hal::BufferBinding {
buffer,
@@ -954,7 +957,7 @@ impl<A: HalApi> RenderBundle<A> {
size,
} => {
let buffer = buffer
- .raw(&snatch_guard)
+ .raw(snatch_guard)
.ok_or(ExecutionError::DestroyedBuffer(buffer.info.id()))?;
let bb = hal::BufferBinding {
buffer,
@@ -1041,7 +1044,7 @@ impl<A: HalApi> RenderBundle<A> {
indexed: false,
} => {
let buffer = buffer
- .raw(&snatch_guard)
+ .raw(snatch_guard)
.ok_or(ExecutionError::DestroyedBuffer(buffer.info.id()))?;
unsafe { raw.draw_indirect(buffer, *offset, 1) };
}
@@ -1052,7 +1055,7 @@ impl<A: HalApi> RenderBundle<A> {
indexed: true,
} => {
let buffer = buffer
- .raw(&snatch_guard)
+ .raw(snatch_guard)
.ok_or(ExecutionError::DestroyedBuffer(buffer.info.id()))?;
unsafe { raw.draw_indexed_indirect(buffer, *offset, 1) };
}
diff --git a/third_party/rust/wgpu-core/src/command/clear.rs b/third_party/rust/wgpu-core/src/command/clear.rs
index e404fabb14..72c923f82e 100644
--- a/third_party/rust/wgpu-core/src/command/clear.rs
+++ b/third_party/rust/wgpu-core/src/command/clear.rs
@@ -12,6 +12,7 @@ use crate::{
id::{BufferId, CommandEncoderId, DeviceId, TextureId},
init_tracker::{MemoryInitKind, TextureInitRange},
resource::{Resource, Texture, TextureClearMode},
+ snatch::SnatchGuard,
track::{TextureSelector, TextureTracker},
};
@@ -239,6 +240,7 @@ impl Global {
}
let (encoder, tracker) = cmd_buf_data.open_encoder_and_tracker()?;
+ let snatch_guard = device.snatchable_lock.read();
clear_texture(
&dst_texture,
TextureInitRange {
@@ -249,6 +251,7 @@ impl Global {
&mut tracker.textures,
&device.alignments,
device.zero_buffer.as_ref().unwrap(),
+ &snatch_guard,
)
}
}
@@ -260,10 +263,10 @@ pub(crate) fn clear_texture<A: HalApi>(
texture_tracker: &mut TextureTracker<A>,
alignments: &hal::Alignments,
zero_buffer: &A::Buffer,
+ snatch_guard: &SnatchGuard<'_>,
) -> Result<(), ClearError> {
- let snatch_guard = dst_texture.device.snatchable_lock.read();
let dst_raw = dst_texture
- .raw(&snatch_guard)
+ .raw(snatch_guard)
.ok_or_else(|| ClearError::InvalidTexture(dst_texture.as_info().id()))?;
// Issue the right barrier.
diff --git a/third_party/rust/wgpu-core/src/command/compute.rs b/third_party/rust/wgpu-core/src/command/compute.rs
index c2fd3ab397..b38324984c 100644
--- a/third_party/rust/wgpu-core/src/command/compute.rs
+++ b/third_party/rust/wgpu-core/src/command/compute.rs
@@ -272,14 +272,14 @@ where
}
}
-struct State<A: HalApi> {
+struct State<'a, A: HalApi> {
binder: Binder<A>,
pipeline: Option<id::ComputePipelineId>,
- scope: UsageScope<A>,
+ scope: UsageScope<'a, A>,
debug_scope_depth: u32,
}
-impl<A: HalApi> State<A> {
+impl<'a, A: HalApi> State<'a, A> {
fn is_ready(&self) -> Result<(), DispatchError> {
let bind_mask = self.binder.invalid_mask();
if bind_mask != 0 {
@@ -407,7 +407,7 @@ impl Global {
let mut state = State {
binder: Binder::new(),
pipeline: None,
- scope: UsageScope::new(&device.tracker_indices),
+ scope: device.new_usage_scope(),
debug_scope_depth: 0,
};
let mut temp_offsets = Vec::new();
@@ -868,6 +868,7 @@ impl Global {
transit,
&mut tracker.textures,
device,
+ &snatch_guard,
);
CommandBuffer::insert_barriers_from_tracker(
transit,
diff --git a/third_party/rust/wgpu-core/src/command/memory_init.rs b/third_party/rust/wgpu-core/src/command/memory_init.rs
index 3bfc71f4f7..54bdedb792 100644
--- a/third_party/rust/wgpu-core/src/command/memory_init.rs
+++ b/third_party/rust/wgpu-core/src/command/memory_init.rs
@@ -7,6 +7,7 @@ use crate::{
hal_api::HalApi,
init_tracker::*,
resource::{Resource, Texture},
+ snatch::SnatchGuard,
track::{TextureTracker, Tracker},
FastHashMap,
};
@@ -144,6 +145,7 @@ pub(crate) fn fixup_discarded_surfaces<
encoder: &mut A::CommandEncoder,
texture_tracker: &mut TextureTracker<A>,
device: &Device<A>,
+ snatch_guard: &SnatchGuard<'_>,
) {
for init in inits {
clear_texture(
@@ -156,6 +158,7 @@ pub(crate) fn fixup_discarded_surfaces<
texture_tracker,
&device.alignments,
device.zero_buffer.as_ref().unwrap(),
+ snatch_guard,
)
.unwrap();
}
@@ -167,6 +170,7 @@ impl<A: HalApi> BakedCommands<A> {
pub(crate) fn initialize_buffer_memory(
&mut self,
device_tracker: &mut Tracker<A>,
+ snatch_guard: &SnatchGuard<'_>,
) -> Result<(), DestroyedBufferError> {
// Gather init ranges for each buffer so we can collapse them.
// It is not possible to do this at an earlier point since previously
@@ -225,16 +229,15 @@ impl<A: HalApi> BakedCommands<A> {
.unwrap()
.1;
- let snatch_guard = buffer.device.snatchable_lock.read();
let raw_buf = buffer
.raw
- .get(&snatch_guard)
+ .get(snatch_guard)
.ok_or(DestroyedBufferError(buffer_id))?;
unsafe {
self.encoder.transition_buffers(
transition
- .map(|pending| pending.into_hal(&buffer, &snatch_guard))
+ .map(|pending| pending.into_hal(&buffer, snatch_guard))
.into_iter(),
);
}
@@ -271,6 +274,7 @@ impl<A: HalApi> BakedCommands<A> {
&mut self,
device_tracker: &mut Tracker<A>,
device: &Device<A>,
+ snatch_guard: &SnatchGuard<'_>,
) -> Result<(), DestroyedTextureError> {
let mut ranges: Vec<TextureInitRange> = Vec::new();
for texture_use in self.texture_memory_actions.drain_init_actions() {
@@ -310,6 +314,7 @@ impl<A: HalApi> BakedCommands<A> {
&mut device_tracker.textures,
&device.alignments,
device.zero_buffer.as_ref().unwrap(),
+ snatch_guard,
);
// A Texture can be destroyed between the command recording
diff --git a/third_party/rust/wgpu-core/src/command/render.rs b/third_party/rust/wgpu-core/src/command/render.rs
index 9141ddb021..7e859e3cc8 100644
--- a/third_party/rust/wgpu-core/src/command/render.rs
+++ b/third_party/rust/wgpu-core/src/command/render.rs
@@ -739,9 +739,9 @@ impl<A: HalApi> TextureView<A> {
const MAX_TOTAL_ATTACHMENTS: usize = hal::MAX_COLOR_ATTACHMENTS + hal::MAX_COLOR_ATTACHMENTS + 1;
type AttachmentDataVec<T> = ArrayVec<T, MAX_TOTAL_ATTACHMENTS>;
-struct RenderPassInfo<'a, A: HalApi> {
+struct RenderPassInfo<'a, 'd, A: HalApi> {
context: RenderPassContext,
- usage_scope: UsageScope<A>,
+ usage_scope: UsageScope<'d, A>,
/// All render attachments, including depth/stencil
render_attachments: AttachmentDataVec<RenderAttachment<'a, A>>,
is_depth_read_only: bool,
@@ -754,7 +754,7 @@ struct RenderPassInfo<'a, A: HalApi> {
multiview: Option<NonZeroU32>,
}
-impl<'a, A: HalApi> RenderPassInfo<'a, A> {
+impl<'a, 'd, A: HalApi> RenderPassInfo<'a, 'd, A> {
fn add_pass_texture_init_actions<V>(
channel: &PassChannel<V>,
texture_memory_actions: &mut CommandBufferTextureMemoryActions<A>,
@@ -790,7 +790,7 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
}
fn start(
- device: &Device<A>,
+ device: &'d Device<A>,
label: Option<&str>,
color_attachments: &[Option<RenderPassColorAttachment>],
depth_stencil_attachment: Option<&RenderPassDepthStencilAttachment>,
@@ -1214,7 +1214,7 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
Ok(Self {
context,
- usage_scope: UsageScope::new(&device.tracker_indices),
+ usage_scope: device.new_usage_scope(),
render_attachments,
is_depth_read_only,
is_stencil_read_only,
@@ -1230,7 +1230,7 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
mut self,
raw: &mut A::CommandEncoder,
snatch_guard: &SnatchGuard,
- ) -> Result<(UsageScope<A>, SurfacesInDiscardState<A>), RenderPassErrorInner> {
+ ) -> Result<(UsageScope<'d, A>, SurfacesInDiscardState<A>), RenderPassErrorInner> {
profiling::scope!("RenderPassInfo::finish");
unsafe {
raw.end_render_pass();
@@ -2374,7 +2374,7 @@ impl Global {
.extend(texture_memory_actions.register_init_action(action));
}
- unsafe { bundle.execute(raw) }
+ unsafe { bundle.execute(raw, &snatch_guard) }
.map_err(|e| match e {
ExecutionError::DestroyedBuffer(id) => {
RenderCommandError::DestroyedBuffer(id)
@@ -2427,6 +2427,7 @@ impl Global {
transit,
&mut tracker.textures,
&cmd_buf.device,
+ &snatch_guard,
);
cmd_buf_data
diff --git a/third_party/rust/wgpu-core/src/command/transfer.rs b/third_party/rust/wgpu-core/src/command/transfer.rs
index 0a952dfc84..8e98a4c9b9 100644
--- a/third_party/rust/wgpu-core/src/command/transfer.rs
+++ b/third_party/rust/wgpu-core/src/command/transfer.rs
@@ -14,6 +14,7 @@ use crate::{
TextureInitTrackerAction,
},
resource::{Resource, Texture, TextureErrorDimension},
+ snatch::SnatchGuard,
track::{TextureSelector, Tracker},
};
@@ -452,6 +453,7 @@ fn handle_texture_init<A: HalApi>(
copy_texture: &ImageCopyTexture,
copy_size: &Extent3d,
texture: &Arc<Texture<A>>,
+ snatch_guard: &SnatchGuard<'_>,
) -> Result<(), ClearError> {
let init_action = TextureInitTrackerAction {
texture: texture.clone(),
@@ -480,6 +482,7 @@ fn handle_texture_init<A: HalApi>(
&mut trackers.textures,
&device.alignments,
device.zero_buffer.as_ref().unwrap(),
+ snatch_guard,
)?;
}
}
@@ -499,6 +502,7 @@ fn handle_src_texture_init<A: HalApi>(
source: &ImageCopyTexture,
copy_size: &Extent3d,
texture: &Arc<Texture<A>>,
+ snatch_guard: &SnatchGuard<'_>,
) -> Result<(), TransferError> {
handle_texture_init(
MemoryInitKind::NeedsInitializedMemory,
@@ -509,6 +513,7 @@ fn handle_src_texture_init<A: HalApi>(
source,
copy_size,
texture,
+ snatch_guard,
)?;
Ok(())
}
@@ -525,6 +530,7 @@ fn handle_dst_texture_init<A: HalApi>(
destination: &ImageCopyTexture,
copy_size: &Extent3d,
texture: &Arc<Texture<A>>,
+ snatch_guard: &SnatchGuard<'_>,
) -> Result<(), TransferError> {
// Attention: If we don't write full texture subresources, we need to a full
// clear first since we don't track subrects. This means that in rare cases
@@ -549,6 +555,7 @@ fn handle_dst_texture_init<A: HalApi>(
destination,
copy_size,
texture,
+ snatch_guard,
)?;
Ok(())
}
@@ -779,6 +786,8 @@ impl Global {
let (dst_range, dst_base) = extract_texture_selector(destination, copy_size, &dst_texture)?;
+ let snatch_guard = device.snatchable_lock.read();
+
// Handle texture init *before* dealing with barrier transitions so we
// have an easier time inserting "immediate-inits" that may be required
// by prior discards in rare cases.
@@ -790,10 +799,9 @@ impl Global {
destination,
copy_size,
&dst_texture,
+ &snatch_guard,
)?;
- let snatch_guard = device.snatchable_lock.read();
-
let (src_buffer, src_pending) = {
let buffer_guard = hub.buffers.read();
let src_buffer = buffer_guard
@@ -935,6 +943,8 @@ impl Global {
let (src_range, src_base) = extract_texture_selector(source, copy_size, &src_texture)?;
+ let snatch_guard = device.snatchable_lock.read();
+
// Handle texture init *before* dealing with barrier transitions so we
// have an easier time inserting "immediate-inits" that may be required
// by prior discards in rare cases.
@@ -946,10 +956,9 @@ impl Global {
source,
copy_size,
&src_texture,
+ &snatch_guard,
)?;
- let snatch_guard = device.snatchable_lock.read();
-
let src_pending = tracker
.textures
.set_single(&src_texture, src_range, hal::TextureUses::COPY_SRC)
@@ -1152,6 +1161,7 @@ impl Global {
source,
copy_size,
&src_texture,
+ &snatch_guard,
)?;
handle_dst_texture_init(
encoder,
@@ -1161,6 +1171,7 @@ impl Global {
destination,
copy_size,
&dst_texture,
+ &snatch_guard,
)?;
let src_pending = cmd_buf_data
diff --git a/third_party/rust/wgpu-core/src/device/global.rs b/third_party/rust/wgpu-core/src/device/global.rs
index 539b92e0f3..0c97e1b504 100644
--- a/third_party/rust/wgpu-core/src/device/global.rs
+++ b/third_party/rust/wgpu-core/src/device/global.rs
@@ -192,7 +192,15 @@ impl Global {
let ptr = if map_size == 0 {
std::ptr::NonNull::dangling()
} else {
- match map_buffer(device.raw(), &buffer, 0, map_size, HostMap::Write) {
+ let snatch_guard = device.snatchable_lock.read();
+ match map_buffer(
+ device.raw(),
+ &buffer,
+ 0,
+ map_size,
+ HostMap::Write,
+ &snatch_guard,
+ ) {
Ok(ptr) => ptr,
Err(e) => {
to_destroy.push(buffer);
@@ -2008,9 +2016,10 @@ impl Global {
}
// Wait for all work to finish before configuring the surface.
+ let snatch_guard = device.snatchable_lock.read();
let fence = device.fence.read();
let fence = fence.as_ref().unwrap();
- match device.maintain(fence, wgt::Maintain::Wait) {
+ match device.maintain(fence, wgt::Maintain::Wait, snatch_guard) {
Ok((closures, _)) => {
user_callbacks = closures;
}
@@ -2120,9 +2129,10 @@ impl Global {
device: &crate::device::Device<A>,
maintain: wgt::Maintain<queue::WrappedSubmissionIndex>,
) -> Result<DevicePoll, WaitIdleError> {
+ let snatch_guard = device.snatchable_lock.read();
let fence = device.fence.read();
let fence = fence.as_ref().unwrap();
- let (closures, queue_empty) = device.maintain(fence, maintain)?;
+ let (closures, queue_empty) = device.maintain(fence, maintain, snatch_guard)?;
// Some deferred destroys are scheduled in maintain so run this right after
// to avoid holding on to them until the next device poll.
@@ -2240,6 +2250,15 @@ impl Global {
}
}
+ // This is a test-only function to force the device into an
+ // invalid state by inserting an error value in its place in
+ // the registry.
+ pub fn device_make_invalid<A: HalApi>(&self, device_id: DeviceId) {
+ let hub = A::hub(self);
+ hub.devices
+ .force_replace_with_error(device_id, "Made invalid.");
+ }
+
pub fn device_drop<A: HalApi>(&self, device_id: DeviceId) {
profiling::scope!("Device::drop");
api_log!("Device::drop {device_id:?}");
@@ -2275,7 +2294,7 @@ impl Global {
) {
let hub = A::hub(self);
- if let Ok(device) = hub.devices.get(device_id) {
+ if let Ok(Some(device)) = hub.devices.try_get(device_id) {
let mut life_tracker = device.lock_life();
if let Some(existing_closure) = life_tracker.device_lost_closure.take() {
// It's important to not hold the lock while calling the closure.
@@ -2284,6 +2303,12 @@ impl Global {
life_tracker = device.lock_life();
}
life_tracker.device_lost_closure = Some(device_lost_closure);
+ } else {
+ // No device? Okay. Just like we have to call any existing closure
+ // before we drop it, we need to call this closure before we exit
+ // this function, because there's no device that is ever going to
+ // call it.
+ device_lost_closure.call(DeviceLostReason::DeviceInvalid, "".to_string());
}
}
diff --git a/third_party/rust/wgpu-core/src/device/life.rs b/third_party/rust/wgpu-core/src/device/life.rs
index 7b06a4a30b..af345015df 100644
--- a/third_party/rust/wgpu-core/src/device/life.rs
+++ b/third_party/rust/wgpu-core/src/device/life.rs
@@ -12,6 +12,7 @@ use crate::{
self, Buffer, DestroyedBuffer, DestroyedTexture, QuerySet, Resource, Sampler,
StagingBuffer, Texture, TextureView,
},
+ snatch::SnatchGuard,
track::{ResourceTracker, Tracker, TrackerIndex},
FastHashMap, SubmissionIndex,
};
@@ -309,12 +310,12 @@ impl<A: HalApi> LifetimeTracker<A> {
}
pub fn post_submit(&mut self) {
- for v in self.future_suspected_buffers.drain(..).take(1) {
+ for v in self.future_suspected_buffers.drain(..) {
self.suspected_resources
.buffers
.insert(v.as_info().tracker_index(), v);
}
- for v in self.future_suspected_textures.drain(..).take(1) {
+ for v in self.future_suspected_textures.drain(..) {
self.suspected_resources
.textures
.insert(v.as_info().tracker_index(), v);
@@ -780,6 +781,7 @@ impl<A: HalApi> LifetimeTracker<A> {
&mut self,
raw: &A::Device,
trackers: &Mutex<Tracker<A>>,
+ snatch_guard: &SnatchGuard,
) -> Vec<super::BufferMapPendingClosure> {
if self.ready_to_map.is_empty() {
return Vec::new();
@@ -816,7 +818,14 @@ impl<A: HalApi> LifetimeTracker<A> {
log::debug!("Buffer {tracker_index:?} map state -> Active");
let host = mapping.op.host;
let size = mapping.range.end - mapping.range.start;
- match super::map_buffer(raw, &buffer, mapping.range.start, size, host) {
+ match super::map_buffer(
+ raw,
+ &buffer,
+ mapping.range.start,
+ size,
+ host,
+ snatch_guard,
+ ) {
Ok(ptr) => {
*buffer.map_state.lock() = resource::BufferMapState::Active {
ptr,
diff --git a/third_party/rust/wgpu-core/src/device/mod.rs b/third_party/rust/wgpu-core/src/device/mod.rs
index 7ecda830a3..e2ab6c2690 100644
--- a/third_party/rust/wgpu-core/src/device/mod.rs
+++ b/third_party/rust/wgpu-core/src/device/mod.rs
@@ -3,9 +3,10 @@ use crate::{
hal_api::HalApi,
hub::Hub,
id::{BindGroupLayoutId, PipelineLayoutId},
- resource::{Buffer, BufferAccessResult},
- resource::{BufferAccessError, BufferMapOperation},
- resource_log, Label, DOWNLEVEL_ERROR_MESSAGE,
+ resource::{Buffer, BufferAccessError, BufferAccessResult, BufferMapOperation},
+ resource_log,
+ snatch::SnatchGuard,
+ Label, DOWNLEVEL_ERROR_MESSAGE,
};
use arrayvec::ArrayVec;
@@ -317,10 +318,10 @@ fn map_buffer<A: HalApi>(
offset: BufferAddress,
size: BufferAddress,
kind: HostMap,
+ snatch_guard: &SnatchGuard,
) -> Result<ptr::NonNull<u8>, BufferAccessError> {
- let snatch_guard = buffer.device.snatchable_lock.read();
let raw_buffer = buffer
- .raw(&snatch_guard)
+ .raw(snatch_guard)
.ok_or(BufferAccessError::Destroyed)?;
let mapping = unsafe {
raw.map_buffer(raw_buffer, offset..offset + size)
diff --git a/third_party/rust/wgpu-core/src/device/queue.rs b/third_party/rust/wgpu-core/src/device/queue.rs
index 6ebb9eb09b..3cb5f695a7 100644
--- a/third_party/rust/wgpu-core/src/device/queue.rs
+++ b/third_party/rust/wgpu-core/src/device/queue.rs
@@ -815,6 +815,7 @@ impl Global {
&mut trackers.textures,
&device.alignments,
device.zero_buffer.as_ref().unwrap(),
+ &device.snatchable_lock.read(),
)
.map_err(QueueWriteError::from)?;
}
@@ -1084,6 +1085,7 @@ impl Global {
&mut trackers.textures,
&device.alignments,
device.zero_buffer.as_ref().unwrap(),
+ &device.snatchable_lock.read(),
)
.map_err(QueueWriteError::from)?;
}
@@ -1147,6 +1149,9 @@ impl Global {
let device = queue.device.as_ref().unwrap();
+ let snatch_guard = device.snatchable_lock.read();
+
+ // Fence lock must be acquired after the snatch lock everywhere to avoid deadlocks.
let mut fence = device.fence.write();
let fence = fence.as_mut().unwrap();
let submit_index = device
@@ -1155,9 +1160,7 @@ impl Global {
+ 1;
let mut active_executions = Vec::new();
- let mut used_surface_textures = track::TextureUsageScope::new();
-
- let snatch_guard = device.snatchable_lock.read();
+ let mut used_surface_textures = track::TextureUsageScope::default();
let mut submit_surface_textures_owned = SmallVec::<[_; 2]>::new();
@@ -1391,10 +1394,10 @@ impl Global {
//Note: locking the trackers has to be done after the storages
let mut trackers = device.trackers.lock();
baked
- .initialize_buffer_memory(&mut *trackers)
+ .initialize_buffer_memory(&mut *trackers, &snatch_guard)
.map_err(|err| QueueSubmitError::DestroyedBuffer(err.0))?;
baked
- .initialize_texture_memory(&mut *trackers, device)
+ .initialize_texture_memory(&mut *trackers, device, &snatch_guard)
.map_err(|err| QueueSubmitError::DestroyedTexture(err.0))?;
//Note: stateless trackers are not merged:
// device already knows these resources exist.
@@ -1435,7 +1438,7 @@ impl Global {
baked.encoder.end_encoding().unwrap()
};
baked.list.push(present);
- used_surface_textures = track::TextureUsageScope::new();
+ used_surface_textures = track::TextureUsageScope::default();
}
// done
@@ -1542,7 +1545,7 @@ impl Global {
// This will schedule destruction of all resources that are no longer needed
// by the user but used in the command stream, among other things.
- let (closures, _) = match device.maintain(fence, wgt::Maintain::Poll) {
+ let (closures, _) = match device.maintain(fence, wgt::Maintain::Poll, snatch_guard) {
Ok(closures) => closures,
Err(WaitIdleError::Device(err)) => return Err(QueueSubmitError::Queue(err)),
Err(WaitIdleError::StuckGpu) => return Err(QueueSubmitError::StuckGpu),
diff --git a/third_party/rust/wgpu-core/src/device/resource.rs b/third_party/rust/wgpu-core/src/device/resource.rs
index 28ba0eafb1..4892aecb75 100644
--- a/third_party/rust/wgpu-core/src/device/resource.rs
+++ b/third_party/rust/wgpu-core/src/device/resource.rs
@@ -28,7 +28,10 @@ use crate::{
resource_log,
snatch::{SnatchGuard, SnatchLock, Snatchable},
storage::Storage,
- track::{BindGroupStates, TextureSelector, Tracker, TrackerIndexAllocators},
+ track::{
+ BindGroupStates, TextureSelector, Tracker, TrackerIndexAllocators, UsageScope,
+ UsageScopePool,
+ },
validation::{
self, check_buffer_usage, check_texture_usage, validate_color_attachment_bytes_per_sample,
},
@@ -97,6 +100,8 @@ pub struct Device<A: HalApi> {
pub(crate) command_allocator: Mutex<Option<CommandAllocator<A>>>,
//Note: The submission index here corresponds to the last submission that is done.
pub(crate) active_submission_index: AtomicU64, //SubmissionIndex,
+ // NOTE: if both are needed, the `snatchable_lock` must be consistently acquired before the
+ // `fence` lock to avoid deadlocks.
pub(crate) fence: RwLock<Option<A::Fence>>,
pub(crate) snatchable_lock: SnatchLock,
@@ -135,6 +140,7 @@ pub struct Device<A: HalApi> {
pub(crate) deferred_destroy: Mutex<Vec<DeferredDestroy<A>>>,
#[cfg(feature = "trace")]
pub(crate) trace: Mutex<Option<trace::Trace>>,
+ pub(crate) usage_scopes: UsageScopePool<A>,
}
pub(crate) enum DeferredDestroy<A: HalApi> {
@@ -296,6 +302,7 @@ impl<A: HalApi> Device<A> {
instance_flags,
pending_writes: Mutex::new(Some(pending_writes)),
deferred_destroy: Mutex::new(Vec::new()),
+ usage_scopes: Default::default(),
})
}
@@ -387,6 +394,7 @@ impl<A: HalApi> Device<A> {
&'this self,
fence: &A::Fence,
maintain: wgt::Maintain<queue::WrappedSubmissionIndex>,
+ snatch_guard: SnatchGuard,
) -> Result<(UserClosures, bool), WaitIdleError> {
profiling::scope!("Device::maintain");
let last_done_index = if maintain.is_wait() {
@@ -440,7 +448,8 @@ impl<A: HalApi> Device<A> {
life_tracker.triage_mapped();
}
- let mapping_closures = life_tracker.handle_mapping(self.raw(), &self.trackers);
+ let mapping_closures =
+ life_tracker.handle_mapping(self.raw(), &self.trackers, &snatch_guard);
let queue_empty = life_tracker.queue_empty();
@@ -467,8 +476,9 @@ impl<A: HalApi> Device<A> {
}
}
- // Don't hold the lock while calling release_gpu_resources.
+ // Don't hold the locks while calling release_gpu_resources.
drop(life_tracker);
+ drop(snatch_guard);
if should_release_gpu_resource {
self.release_gpu_resources();
@@ -3568,6 +3578,10 @@ impl<A: HalApi> Device<A> {
let _ = texture.destroy();
}
}
+
+ pub(crate) fn new_usage_scope(&self) -> UsageScope<'_, A> {
+ UsageScope::new_pooled(&self.usage_scopes, &self.tracker_indices)
+ }
}
impl<A: HalApi> Device<A> {
diff --git a/third_party/rust/wgpu-core/src/snatch.rs b/third_party/rust/wgpu-core/src/snatch.rs
index 2324d33574..d5cd1a3d37 100644
--- a/third_party/rust/wgpu-core/src/snatch.rs
+++ b/third_party/rust/wgpu-core/src/snatch.rs
@@ -1,7 +1,12 @@
#![allow(unused)]
use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
-use std::cell::UnsafeCell;
+use std::{
+ backtrace::Backtrace,
+ cell::{Cell, RefCell, UnsafeCell},
+ panic::{self, Location},
+ thread,
+};
/// A guard that provides read access to snatchable data.
pub struct SnatchGuard<'a>(RwLockReadGuard<'a, ()>);
@@ -59,6 +64,10 @@ impl<T> std::fmt::Debug for Snatchable<T> {
unsafe impl<T> Sync for Snatchable<T> {}
+thread_local! {
+ static READ_LOCK_LOCATION: Cell<Option<(&'static Location<'static>, Backtrace)>> = const { Cell::new(None) };
+}
+
/// A Device-global lock for all snatchable data.
pub struct SnatchLock {
lock: RwLock<()>,
@@ -76,7 +85,24 @@ impl SnatchLock {
}
/// Request read access to snatchable resources.
+ #[track_caller]
pub fn read(&self) -> SnatchGuard {
+ if cfg!(debug_assertions) {
+ let caller = Location::caller();
+ let backtrace = Backtrace::capture();
+ if let Some((prev, bt)) = READ_LOCK_LOCATION.take() {
+ let current = thread::current();
+ let name = current.name().unwrap_or("<unnamed>");
+ panic!(
+ "thread '{name}' attempted to acquire a snatch read lock recursively.\n
+ - {prev}\n{bt}\n
+ - {caller}\n{backtrace}"
+ );
+ } else {
+ READ_LOCK_LOCATION.set(Some((caller, backtrace)));
+ }
+ }
+
SnatchGuard(self.lock.read())
}
@@ -89,3 +115,10 @@ impl SnatchLock {
ExclusiveSnatchGuard(self.lock.write())
}
}
+
+impl Drop for SnatchGuard<'_> {
+ fn drop(&mut self) {
+ #[cfg(debug_assertions)]
+ READ_LOCK_LOCATION.take();
+ }
+}
diff --git a/third_party/rust/wgpu-core/src/track/buffer.rs b/third_party/rust/wgpu-core/src/track/buffer.rs
index a30ac2a225..6cf1fdda6f 100644
--- a/third_party/rust/wgpu-core/src/track/buffer.rs
+++ b/third_party/rust/wgpu-core/src/track/buffer.rs
@@ -108,23 +108,27 @@ impl<A: HalApi> BufferBindGroupState<A> {
#[derive(Debug)]
pub(crate) struct BufferUsageScope<A: HalApi> {
state: Vec<BufferUses>,
-
metadata: ResourceMetadata<Buffer<A>>,
}
-impl<A: HalApi> BufferUsageScope<A> {
- pub fn new() -> Self {
+impl<A: HalApi> Default for BufferUsageScope<A> {
+ fn default() -> Self {
Self {
state: Vec::new(),
-
metadata: ResourceMetadata::new(),
}
}
+}
+impl<A: HalApi> BufferUsageScope<A> {
fn tracker_assert_in_bounds(&self, index: usize) {
strict_assert!(index < self.state.len());
self.metadata.tracker_assert_in_bounds(index);
}
+ pub fn clear(&mut self) {
+ self.state.clear();
+ self.metadata.clear();
+ }
/// Sets the size of all the vectors inside the tracker.
///
diff --git a/third_party/rust/wgpu-core/src/track/metadata.rs b/third_party/rust/wgpu-core/src/track/metadata.rs
index 744783a7fa..3e71e0e084 100644
--- a/third_party/rust/wgpu-core/src/track/metadata.rs
+++ b/third_party/rust/wgpu-core/src/track/metadata.rs
@@ -39,6 +39,11 @@ impl<T: Resource> ResourceMetadata<T> {
resize_bitvec(&mut self.owned, size);
}
+ pub(super) fn clear(&mut self) {
+ self.resources.clear();
+ self.owned.clear();
+ }
+
/// Ensures a given index is in bounds for all arrays and does
/// sanity checks of the presence of a refcount.
///
diff --git a/third_party/rust/wgpu-core/src/track/mod.rs b/third_party/rust/wgpu-core/src/track/mod.rs
index 9ca37ebadc..374dfe7493 100644
--- a/third_party/rust/wgpu-core/src/track/mod.rs
+++ b/third_party/rust/wgpu-core/src/track/mod.rs
@@ -480,8 +480,8 @@ impl<A: HalApi> RenderBundleScope<A> {
/// Create the render bundle scope and pull the maximum IDs from the hubs.
pub fn new() -> Self {
Self {
- buffers: RwLock::new(BufferUsageScope::new()),
- textures: RwLock::new(TextureUsageScope::new()),
+ buffers: RwLock::new(BufferUsageScope::default()),
+ textures: RwLock::new(TextureUsageScope::default()),
bind_groups: RwLock::new(StatelessTracker::new()),
render_pipelines: RwLock::new(StatelessTracker::new()),
query_sets: RwLock::new(StatelessTracker::new()),
@@ -512,28 +512,52 @@ impl<A: HalApi> RenderBundleScope<A> {
}
}
+/// A pool for storing the memory used by [`UsageScope`]s. We take and store this memory when the
+/// scope is dropped to avoid reallocating. The memory required only grows and allocation cost is
+/// significant when a large number of resources have been used.
+pub(crate) type UsageScopePool<A> = Mutex<Vec<(BufferUsageScope<A>, TextureUsageScope<A>)>>;
+
/// A usage scope tracker. Only needs to store stateful resources as stateless
/// resources cannot possibly have a usage conflict.
#[derive(Debug)]
-pub(crate) struct UsageScope<A: HalApi> {
+pub(crate) struct UsageScope<'a, A: HalApi> {
+ pub pool: &'a UsageScopePool<A>,
pub buffers: BufferUsageScope<A>,
pub textures: TextureUsageScope<A>,
}
-impl<A: HalApi> UsageScope<A> {
- /// Create the render bundle scope and pull the maximum IDs from the hubs.
- pub fn new(tracker_indices: &TrackerIndexAllocators) -> Self {
- let mut value = Self {
- buffers: BufferUsageScope::new(),
- textures: TextureUsageScope::new(),
- };
+impl<'a, A: HalApi> Drop for UsageScope<'a, A> {
+ fn drop(&mut self) {
+ // clear vecs and push into pool
+ self.buffers.clear();
+ self.textures.clear();
+ self.pool.lock().push((
+ std::mem::take(&mut self.buffers),
+ std::mem::take(&mut self.textures),
+ ));
+ }
+}
- value.buffers.set_size(tracker_indices.buffers.size());
- value.textures.set_size(tracker_indices.textures.size());
+impl<A: HalApi> UsageScope<'static, A> {
+ pub fn new_pooled<'d>(
+ pool: &'d UsageScopePool<A>,
+ tracker_indices: &TrackerIndexAllocators,
+ ) -> UsageScope<'d, A> {
+ let pooled = pool.lock().pop().unwrap_or_default();
+
+ let mut scope = UsageScope::<'d, A> {
+ pool,
+ buffers: pooled.0,
+ textures: pooled.1,
+ };
- value
+ scope.buffers.set_size(tracker_indices.buffers.size());
+ scope.textures.set_size(tracker_indices.textures.size());
+ scope
}
+}
+impl<'a, A: HalApi> UsageScope<'a, A> {
/// Merge the inner contents of a bind group into the usage scope.
///
/// Only stateful things are merged in here, all other resources are owned
diff --git a/third_party/rust/wgpu-core/src/track/texture.rs b/third_party/rust/wgpu-core/src/track/texture.rs
index e7c4707c93..3cf95ff38a 100644
--- a/third_party/rust/wgpu-core/src/track/texture.rs
+++ b/third_party/rust/wgpu-core/src/track/texture.rs
@@ -210,6 +210,7 @@ pub(crate) struct TextureStateSet {
simple: Vec<TextureUses>,
complex: FastHashMap<usize, ComplexTextureState>,
}
+
impl TextureStateSet {
fn new() -> Self {
Self {
@@ -235,15 +236,16 @@ pub(crate) struct TextureUsageScope<A: HalApi> {
metadata: ResourceMetadata<Texture<A>>,
}
-impl<A: HalApi> TextureUsageScope<A> {
- pub fn new() -> Self {
+impl<A: HalApi> Default for TextureUsageScope<A> {
+ fn default() -> Self {
Self {
set: TextureStateSet::new(),
-
metadata: ResourceMetadata::new(),
}
}
+}
+impl<A: HalApi> TextureUsageScope<A> {
fn tracker_assert_in_bounds(&self, index: usize) {
self.metadata.tracker_assert_in_bounds(index);
@@ -258,6 +260,11 @@ impl<A: HalApi> TextureUsageScope<A> {
});
}
+ pub fn clear(&mut self) {
+ self.set.clear();
+ self.metadata.clear();
+ }
+
/// Sets the size of all the vectors inside the tracker.
///
/// Must be called with the highest possible Texture ID before