-
Notifications
You must be signed in to change notification settings - Fork 361
Description
Edit: this proposal originates in #156 known as "buffer views"
I tried really hard to make some proposal for buffer partitioning that makes sense but the best I could get is what's below. It has major flaws and I wouldn't want it as part of WebGPU but I'm posting it because it was promised, and because maybe someone will inspiration for a better idea.
Feel free to not read if you're not interested in my rambling.
Buffer partitioning
This is a proposal for how buffers could be split in such a way that one piece of the buffer if mapped while another is in use by the GPU.
The basic requirement was that UBOs could be ring-allocated in a mappable buffer, such that a part of the buffer is in use as a UBO by the GPU while the other is being populated by that application. Doing this is important because a single bind-group could be used to address the whole ringbuffer with a dynamic offset.
Basics
GPUBuffer gains three internal slots:
[[is partition]]a boolean that defaults to false.[[partitions]]a list of partitions for this buffer (always empty if[[is partition]]).[[parent buffer]]the parent of the buffer (always null if not[[is partition]])
Buffer partitioning is done through a method of GPUBuffer:
partial interface GPUBuffer {
GPUBuffer partition(offset, size);
};buffer.partition(offset, size) creates a new Buffer representing the range [offset, offset + size) of the buffer. A validation error happens and an error GPUBuffer is returned if one of these conditions isn't respected:
offsetandsizemust be aligned to 256.buffer.[[is partition]]is true.buffermust not be in thedestroyedormappedstate. It can already be partitioned.- the range must not intersect the range of any other partition of
bufferthat's not in the destroyed state.
Upon success a new partition of the buffer, result is returned. The steps are roughly:
bufferis put in thepartitionedstate.- a new
GPUBuffercalledresultis created. resultis inserted in buffer's[[partitions]]result's[[is partition]]is set to true.result's[[parent buffer]]is set tobufferresultis put in theunmappedstate.result's data store represents the correct range ofbuffer's data store' (hands waving).
Interactions with other WebGPU features
Interaction with destroy()
- Calling destroy on a partitioned buffer recursively destroys all its partitions.
- Calling destroy on a partition removes it from it's parent's list of partitions, and if the list of partition is empty the parent is put in the
unmappedstate.
Interaction with dynamic offset
The intent was that you would be able to make a dynamic UBO on the parent buffer in the bind group and somehow choosing an offset that is in a correct (unmapped) partition at submit time would be allowed.
But this requires, at submit time, to check dynamic offsets are in a correct partition if the dynamic uniform buffer is partitioned. It doesn't look very tractable.
Interaction with GPUQueue.submit()
It is an error to have a partitioned buffer used in the command buffers, except as dynamic UBO / storage buffers. If that case happens, the dynamic offset must be such that [offset, offset + binding size) is entirely contained in a single unmapped parition.
Interaction with mapping.
And this proposal breaks down even more. The different partitions of a large ring buffer will be mapReadAsynced independently, but then we might want to stitch them together to make bigger partitions that are all in the mapped state. That and splitting a large mapped region into two sub-regions one that's going to be used as a UBO on the GPU and one that stays mapped for the next frame.