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

Proposal: Dynamic uniform and storage buffer offsets #116

@Kangz

Description

@Kangz

In a typical application, most draws will use different uniforms values for things like the world position and orientation. In the current state of WebGPU this means that a new bind group needs to be created for each draw (or reused from a cache) to set the right uniforms. Bind group creation is expected to be more expensive than recording draws because they incur an allocation. To reduce the number of bind groups that need to be created, WebGPU could introduce a concept of dynamic uniform/storage buffers. The proposal is at the bottom but the API would be somewhat similar to Vulkan.

Vulkan

Vulkan has a descriptor type called VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC that can be specified in VkDescriptorSetLayoutBinding::descriptorType that means this binding will be a dynamic uniform buffer binding. Then dynamic offsets are passed to vkCmdBindDescriptorSets via dynamicOffsetCount and pDynamicOffsets. This causes dynamic uniform buffers to be bound at an offset that is the base offset already present in the descriptor set plus the respective element of pDynamicOffsets (the ordering of pDynamicOffsets is the same ordering as dynamic buffers in the descriptor set layout).

Metal

In Metal, every time a buffer is bound, it gets passed an offset.

D3D12

The binding model here is the most flexible. Dynamic buffers can be implemented in a variety of ways:

  1. The dynamic offset can be stored as a root constant and added to every access to [RW]ByteAddressedBuffer. This wouldn't work for uniform buffers though.
  2. The virtual address of the offset can be computed and stored in a root UAV/CBV descriptor using ID3D12GraphicsCommandList::SetComputeRootConstantBufferView and ID3D12GraphicsCommandList::SetComputeRootUnorderedAccessView (or their SetGrahpics equivalents).
  3. The descriptor can be computed and stored in descriptor heap, kind of like a new copy of the bind group with a different offset.
  1. seems like the best choice, but root table space is limited so we'd have to aggressively limit the number of dynamic buffers per pipeline layout.

Proposal

The WebGPU version would look similar to the Vulkan model:

partial enum WebGPUBindingType {
    "dynamicUniformBuffer",
    "dynamicStorageBuffer",
};

partial interface WebGPUProgrammablePassEncoder {
    void setBindGroup(u32 index, WebGPUBindGroup bindGroup, sequence<u32>? dynamicOffsets);
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions