-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
Description
With wgpu 0.14, code like the following is valid:
let (tx, rx) = futures::channel::oneshot::channel();
wgpu::util::DownloadBuffer::read_buffer(
&self.fw.device,
&self.fw.queue,
&self.buffer.slice(..download_size as u64),
move |result| {
tx.send(result).unwrap_or_else(|_| panic!("Failed to download buffer."));
});
self.fw.device.poll(wgpu::Maintain::Wait);
let download = rx.block_on().unwrap().unwrap();
...
With wgpu 0.15 and forward, it won't compile, because of this change 052bd17#diff-00d306ac48be4eb4a03df7b093e35fabfb521d981f82315a3a725a9dc15e1ae1R77-R80
The error I get is:
error[E0277]: `(dyn wgpu::context::BufferMappedRange + 'static)` cannot be sent between threads safely
--> src\gpgpu2.rs:332:13
|
328 | wgpu::util::DownloadBuffer::read_buffer(
| --------------------------------------- required by a bound introduced by this call
...
332 | / move |result| {
333 | | tx.send(result)
334 | | .unwrap_or_else(|_| panic!("Failed to download buffer."));
335 | | },
| |_____________^ `(dyn wgpu::context::BufferMappedRange + 'static)` cannot be sent between threads safely
|
= help: the trait `std::marker::Send` is not implemented for `(dyn wgpu::context::BufferMappedRange + 'static)`
= note: required for `Unique<(dyn wgpu::context::BufferMappedRange + 'static)>` to implement `std::marker::Send`
= note: required because it appears within the type `Box<dyn BufferMappedRange>`
= note: required because it appears within the type `DownloadBuffer`
= note: required because it appears within the type `Result<DownloadBuffer, BufferAsyncError>`
= note: required because it appears within the type `Option<Result<DownloadBuffer, BufferAsyncError>>`
= note: required for `channel::lock::Lock<Option<Result<DownloadBuffer, BufferAsyncError>>>` to implement `Sync`
= note: required because it appears within the type `Inner<Result<DownloadBuffer, BufferAsyncError>>`
= note: required for `Arc<oneshot::Inner<Result<DownloadBuffer, BufferAsyncError>>>` to implement `std::marker::Send`
= note: required because it appears within the type `Sender<Result<DownloadBuffer, BufferAsyncError>>`
note: required because it's used within this closure
--> src\gpgpu2.rs:332:13
|
332 | move |result| {
| ^^^^^^^^^^^^^
note: required by a bound in `DownloadBuffer::read_buffer`
--> C:\Users\Pema Malling\.cargo\registry\src\gitproxy.zycloud.tk-1ecc6299db9ec823\wgpu-0.15.1\src\util\mod.rs:98:72
|
98 | callback: impl FnOnce(Result<Self, super::BufferAsyncError>) + Send + 'static,
| ^^^^ required by this bound in `DownloadBuffer::read_buffer`
Repro steps
- Clone https://github.com/pema99/rust-path-tracer/tree/wgpu-fail (branch
wgpu-fail
). cargo build
- Build fails
Expected vs observed behavior
Expected: Build succeeds
Actual: Build fails
Extra materials
The reason I am using this older method of downloading buffers, and not directly using map_async
, is that I found for my use case that adding MAP_READ
to the buffer I want to read back causes a massive drop in performance. I can still use this older method, but because the trait object isn't Send
, I'm forced to do an extra copy (ie. copy to vector, send the vector between threads instead). This causes a drop in performance.
I've "fixed" the issue myself on my own branch, but I'm not sure if the change is ok and/or breaking: pema99@e44f8ae