这是indexloc提供的服务,不要输入任何密码
Skip to content

Buffer partitioning (real bad proposal but it was promised) #481

@Kangz

Description

@Kangz

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:

  • offset and size must be aligned to 256.
  • buffer.[[is partition]] is true.
  • buffer must not be in the destroyed or mapped state. It can already be partitioned.
  • the range must not intersect the range of any other partition of buffer that's not in the destroyed state.

Upon success a new partition of the buffer, result is returned. The steps are roughly:

  • buffer is put in the partitioned state.
  • a new GPUBuffer called result is created.
  • result is inserted in buffer's [[partitions]]
  • result's [[is partition]] is set to true.
  • result's [[parent buffer]] is set to buffer
  • result is put in the unmapped state.
  • result's data store represents the correct range of buffer'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 unmapped state.

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions