-
Notifications
You must be signed in to change notification settings - Fork 329
Description
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:
- 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. - The virtual address of the offset can be computed and stored in a root UAV/CBV descriptor using
ID3D12GraphicsCommandList::SetComputeRootConstantBufferView
andID3D12GraphicsCommandList::SetComputeRootUnorderedAccessView
(or theirSetGrahpics
equivalents). - The descriptor can be computed and stored in descriptor heap, kind of like a new copy of the bind group with a different offset.
- 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);
}