fix(core): Flush pending writes before mapAsync, if needed#9307
fix(core): Flush pending writes before mapAsync, if needed#9307andyleiserson wants to merge 1 commit intogfx-rs:trunkfrom
Conversation
0f42fa3 to
29bff7a
Compare
| // Review note: the code previously dropped the snatch lock here. I don't see how | ||
| // that was correct, if we drop it then the buffer could be destroyed. |
There was a problem hiding this comment.
I think it was ok because we were not using the raw hal buffer for any operation but we were chaning state on the core buffer so, maybe we could have gotten into an unexpected situation.
| Self::InvalidResource(e) => e.webgpu_error_type(), | ||
| Self::DestroyedResource(e) => e.webgpu_error_type(), | ||
|
|
||
| Self::QueueSubmit(_) => ErrorType::Internal, |
There was a problem hiding this comment.
The spec allows the internal variant to only be returned by pipeline creation.
| // These errors are not expected. Encode them as a string, because | ||
| // some of them are not serializable, while `BufferAccessError` is. | ||
| log::debug!("Unexpected error flushing writes for buffer: {e}"); | ||
| Err(BufferAccessError::QueueSubmit(e.to_string())) |
There was a problem hiding this comment.
I think we should either panic here or add a new submit function to make it impossible for these variants to be returned.
There was a problem hiding this comment.
Refactoring the submit function to be used by a new submit function that doesn't return these variants seems a lot more tricky.
There was a problem hiding this comment.
Maybe it's possible to take out this block and call it from map_async.
wgpu/wgpu-core/src/device/queue.rs
Lines 1375 to 1470 in a58f51a
Below it we call device.maintain to cleanup resources of previous submissions but I don't think we should do that in map_async.
Fixes #5173
This implements the strategy @teoxoy suggested in bug 1994733, comment 6: if
mapAsyncfinds thatPendingWritesholds writes for the buffer being mapped, thenPendingWritesis flushed/submitted before mapping the buffer.This strategy never makes
Queue::writeBufferorunmapperform a submission. A submission only happens if/whenmapAsyncis called for a buffer with pending writes. This has the nice property thatmapAsyncwas already an operation that might have to wait on the queue, although this change broadens the circumstances when that will happen and may increase the amount of queued work thatmapAsynchas to wait on. (More sophisticated approaches would be to only flush the pending writes for the buffer in question, rather than all of them, or to proactively flush pending writes if the queue is idle, to reduce the chance thatmapAsyncends up waiting on them.)In terms of code changes, this didn't end up being that bad, but I'd definitely consider it a risky change and I am not sure how best to shake out any potential issues.
There is a long-standing TODO in
mapAsyncabout possibly needing a barrier. I briefly considered trying to address that as part of that change, but I think it's a separable concern, and comes with its own set of performance risks that it is better not to lump together with this change.Testing
Adds a directed test and some CTS tests.
Squash or Rebase? Squash
Checklist
CHANGELOG.mdentry.