diff --git a/Cargo.lock b/Cargo.lock index 27f96dd11..25a5cea9b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4013,7 +4013,6 @@ version = "0.18.0" dependencies = [ "arrayvec 0.7.4", "cfg-if", - "flume", "js-sys", "log", "naga", diff --git a/wgpu/Cargo.toml b/wgpu/Cargo.toml index 6851bb53b..fcda54e16 100644 --- a/wgpu/Cargo.toml +++ b/wgpu/Cargo.toml @@ -103,7 +103,6 @@ optional = true [dependencies] arrayvec.workspace = true cfg-if.workspace = true -flume.workspace = true log.workspace = true parking_lot.workspace = true profiling.workspace = true diff --git a/wgpu/src/util/belt.rs b/wgpu/src/util/belt.rs index 0c019fa23..98ad2c139 100644 --- a/wgpu/src/util/belt.rs +++ b/wgpu/src/util/belt.rs @@ -3,7 +3,7 @@ use crate::{ BufferViewMut, CommandEncoder, Device, MapMode, }; use std::fmt; -use std::sync::Arc; +use std::sync::{mpsc, Arc}; struct Chunk { buffer: Arc, @@ -11,6 +11,23 @@ struct Chunk { offset: BufferAddress, } +/// `Sync` wrapper that works by providing only exclusive access. +/// +/// See https://doc.rust-lang.org/nightly/std/sync/struct.Exclusive.html +struct Exclusive(T); + +unsafe impl Sync for Exclusive {} + +impl Exclusive { + fn new(value: T) -> Self { + Self(value) + } + + fn get_mut(&mut self) -> &mut T { + &mut self.0 + } +} + /// Efficiently performs many buffer writes by sharing and reusing temporary buffers. /// /// Internally it uses a ring-buffer of staging buffers that are sub-allocated. @@ -36,9 +53,9 @@ pub struct StagingBelt { /// into `active_chunks`. free_chunks: Vec, /// When closed chunks are mapped again, the map callback sends them here. - sender: flume::Sender, + sender: Exclusive>, /// Free chunks are received here to be put on `self.free_chunks`. - receiver: flume::Receiver, + receiver: Exclusive>, } impl StagingBelt { @@ -53,14 +70,14 @@ impl StagingBelt { /// (per [`StagingBelt::finish()`]); and /// * bigger is better, within these bounds. pub fn new(chunk_size: BufferAddress) -> Self { - let (sender, receiver) = flume::unbounded(); + let (sender, receiver) = std::sync::mpsc::channel(); StagingBelt { chunk_size, active_chunks: Vec::new(), closed_chunks: Vec::new(), free_chunks: Vec::new(), - sender, - receiver, + sender: Exclusive::new(sender), + receiver: Exclusive::new(receiver), } } @@ -148,9 +165,8 @@ impl StagingBelt { pub fn recall(&mut self) { self.receive_chunks(); - let sender = &self.sender; for chunk in self.closed_chunks.drain(..) { - let sender = sender.clone(); + let sender = self.sender.get_mut().clone(); chunk .buffer .clone() @@ -164,7 +180,7 @@ impl StagingBelt { /// Move all chunks that the GPU is done with (and are now mapped again) /// from `self.receiver` to `self.free_chunks`. fn receive_chunks(&mut self) { - while let Ok(mut chunk) = self.receiver.try_recv() { + while let Ok(mut chunk) = self.receiver.get_mut().try_recv() { chunk.offset = 0; self.free_chunks.push(chunk); }