Skip to content

Conversation

@ErichDonGubler
Copy link
Member

@ErichDonGubler ErichDonGubler commented Oct 23, 2025

Connections

Description

For cases where a buffer is mapped_at_creation, our current implementation of Buffer::create initializes the buffer's internal state with BufferMapState::Init (which contains a staging buffer underneath the hood) for a descriptor requesting MAP_READ that is copied to a host-backed buffer . MAP_WRITE works a little differently, starting from the beginning with a host-backed buffer.

Init does a buffer copy between the staging buffer and the host-backed buffer in the device's queue when the buffer is unmapped. However, Buffer::map_async (correctly) assumes that a host-backed buffer need not wait for anything in the queue. This results in a bug where map_async doesn't actually wait long enough for the device queue to complete its operations before resolving. Oops!

Up to the point where a buffer is unmapped after being mapped at creation, MAP_READ, MAP_WRITE, and even non-MAP_* buffers' capabilities are the same. That is, we should be able to get mutable slices for mapped ranges, no matter what. So, make MAP_READ just initialize its internal state in the same way as with MAP_WRITE.

Testing

Added webgpu:api,operation,buffers,map:mapAsync,read:*, which is expected to fail in the first commit, and is resolved with the second commit.

Squash or Rebase?

Rebase.

@ErichDonGubler ErichDonGubler changed the title WIP: fix(core): use BufferMapState::Active for any BufferUsages::MAP_* flags fix(core): use BufferMapState::Active for any BufferUsages::MAP_* flags Oct 23, 2025
@ErichDonGubler
Copy link
Member Author

ErichDonGubler commented Oct 24, 2025

Hmmm…I'm not immediately sure how to fix the CI errors, which all seem to be on GL backends (incl. WebGL). I'm not familiar with GL backends, so I'm sure I'm doing something wrong with bookkeeping there, but not what that might be.

@ErichDonGubler ErichDonGubler force-pushed the erichdongubler-push-dazed-adept-horse branch from 984c1ea to 60bd075 Compare October 24, 2025 21:53
… flags

For cases where a buffer is `mapped_at_creation`, our current
implementation of `Buffer::create` initializes the buffer's internal
state with `BufferMapState::Init` (which contains a staging buffer
underneath the hood) for a descriptor requesting `MAP_READ` that is
copied to a host-backed buffer . `MAP_WRITE` works a little differently,
starting from the beginning with a host-backed buffer.

`Init` does a buffer copy between the staging buffer and the host-backed
buffer in the device's queue when the buffer is `unmap`ped. However,
`Buffer::map_async` (correctly) assumes that a host-backed buffer need
not wait for anything in the queue. This results in a bug where
`map_async` doesn't actually wait long enough for the device queue to
complete its operations before resolving. Oops!

Up to the point where a buffer is unmapped after being mapped at
creation, `MAP_READ`, `MAP_WRITE`, and even _non_-`MAP_*` buffers'
capabilities are the same. That is, we should be able to get mutable
slices for mapped ranges, no matter what. So, make `MAP_READ` just
initialize its internal state in the same way as with `MAP_WRITE`.
@ErichDonGubler ErichDonGubler force-pushed the erichdongubler-push-dazed-adept-horse branch from 60bd075 to 10d652f Compare October 24, 2025 22:04
@ErichDonGubler ErichDonGubler marked this pull request as ready for review October 24, 2025 22:04
@ErichDonGubler
Copy link
Member Author

Going to mark this as ready for review. I'm not sure how to resolve CI yet, but at least the approach can be validated, and maybe a reviewer will know more than I do about how to resolve this. 😖

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Read-mapped buffer content incorrect unless a submission happens between write and read

1 participant