Skip to content

Commit

Permalink
Remove flume dependency of wgpu (#4585)
Browse files Browse the repository at this point in the history
* Remove `flume` dependency of `wgpu`

* Add `Exclusive`
  • Loading branch information
a1phyr authored Oct 27, 2023
1 parent 4c5a817 commit 8998b9d
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 11 deletions.
1 change: 0 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion wgpu/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
34 changes: 25 additions & 9 deletions wgpu/src/util/belt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,31 @@ use crate::{
BufferViewMut, CommandEncoder, Device, MapMode,
};
use std::fmt;
use std::sync::Arc;
use std::sync::{mpsc, Arc};

struct Chunk {
buffer: Arc<Buffer>,
size: BufferAddress,
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>(T);

unsafe impl<T> Sync for Exclusive<T> {}

impl<T> Exclusive<T> {
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.
Expand All @@ -36,9 +53,9 @@ pub struct StagingBelt {
/// into `active_chunks`.
free_chunks: Vec<Chunk>,
/// When closed chunks are mapped again, the map callback sends them here.
sender: flume::Sender<Chunk>,
sender: Exclusive<mpsc::Sender<Chunk>>,
/// Free chunks are received here to be put on `self.free_chunks`.
receiver: flume::Receiver<Chunk>,
receiver: Exclusive<mpsc::Receiver<Chunk>>,
}

impl StagingBelt {
Expand All @@ -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),
}
}

Expand Down Expand Up @@ -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()
Expand All @@ -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);
}
Expand Down

0 comments on commit 8998b9d

Please sign in to comment.