Skip to content

Commit bc17280

Browse files
authored
wgpu-hal: Document some details of buffer binding. (#3169)
1 parent 0e937c8 commit bc17280

File tree

3 files changed

+70
-0
lines changed

3 files changed

+70
-0
lines changed

wgpu-hal/src/lib.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -884,8 +884,27 @@ pub struct PipelineLayoutDescriptor<'a, A: Api> {
884884

885885
#[derive(Debug)]
886886
pub struct BufferBinding<'a, A: Api> {
887+
/// The buffer being bound.
887888
pub buffer: &'a A::Buffer,
889+
890+
/// The offset at which the bound region starts.
891+
///
892+
/// This must be less than the size of the buffer. Some back ends
893+
/// cannot tolerate zero-length regions; for example, see
894+
/// [VUID-VkDescriptorBufferInfo-offset-00340][340] and
895+
/// [VUID-VkDescriptorBufferInfo-range-00341][341], or the
896+
/// documentation for GLES's [glBindBufferRange][bbr].
897+
///
898+
/// [340]: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-VkDescriptorBufferInfo-offset-00340
899+
/// [341]: https://registry.khronos.org/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-VkDescriptorBufferInfo-range-00341
900+
/// [bbr]: https://registry.khronos.org/OpenGL-Refpages/es3.0/html/glBindBufferRange.xhtml
888901
pub offset: wgt::BufferAddress,
902+
903+
/// The size of the region bound, in bytes.
904+
///
905+
/// If `None`, the region extends from `offset` to the end of the
906+
/// buffer. Given the restrictions on `offset`, this means that
907+
/// the size is always greater than zero.
889908
pub size: Option<wgt::BufferSize>,
890909
}
891910

wgpu-hal/src/metal/device.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,17 @@ struct CompiledShader {
1616
function: mtl::Function,
1717
wg_size: mtl::MTLSize,
1818
wg_memory_sizes: Vec<u32>,
19+
20+
/// Bindings of WGSL `storage` globals that contain variable-sized arrays.
21+
///
22+
/// In order to implement bounds checks and the `arrayLength` function for
23+
/// WGSL runtime-sized arrays, we pass the entry point a struct with a
24+
/// member for each global variable that contains such an array. That member
25+
/// is a `u32` holding the variable's total size in bytes---which is simply
26+
/// the size of the `Buffer` supplying that variable's contents for the
27+
/// draw call.
1928
sized_bindings: Vec<naga::ResourceBinding>,
29+
2030
immutable_buffer_mask: usize,
2131
}
2232

@@ -724,6 +734,8 @@ impl crate::Device<super::Api> for super::Device {
724734
let end = start + size as usize;
725735
bg.buffers
726736
.extend(desc.buffers[start..end].iter().map(|source| {
737+
// Given the restrictions on `BufferBinding::offset`,
738+
// this should never be `None`.
727739
let remaining_size =
728740
wgt::BufferSize::new(source.buffer.size - source.offset);
729741
let binding_size = match ty {

wgpu-hal/src/metal/mod.rs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -584,7 +584,17 @@ struct BufferResource {
584584
ptr: BufferPtr,
585585
offset: wgt::BufferAddress,
586586
dynamic_index: Option<u32>,
587+
588+
/// The buffer's size, if it is a [`Storage`] binding. Otherwise `None`.
589+
///
590+
/// Buffers with the [`wgt::BufferBindingType::Storage`] binding type can
591+
/// hold WGSL runtime-sized arrays. When one does, we must pass its size to
592+
/// shader entry points to implement bounds checks and WGSL's `arrayLength`
593+
/// function. See [`device::CompiledShader::sized_bindings`] for details.
594+
///
595+
/// [`Storage`]: wgt::BufferBindingType::Storage
587596
binding_size: Option<wgt::BufferSize>,
597+
588598
binding_location: u32,
589599
}
590600

@@ -607,7 +617,15 @@ pub struct ShaderModule {
607617
#[derive(Debug, Default)]
608618
struct PipelineStageInfo {
609619
push_constants: Option<PushConstantsInfo>,
620+
621+
/// The buffer argument table index at which we pass runtime-sized arrays' buffer sizes.
622+
///
623+
/// See [`device::CompiledShader::sized_bindings`] for more details.
610624
sizes_slot: Option<naga::back::msl::Slot>,
625+
626+
/// Bindings of all WGSL `storage` globals that contain runtime-sized arrays.
627+
///
628+
/// See [`device::CompiledShader::sized_bindings`] for more details.
611629
sized_bindings: Vec<naga::ResourceBinding>,
612630
}
613631

@@ -714,7 +732,28 @@ struct CommandState {
714732
index: Option<IndexState>,
715733
raw_wg_size: mtl::MTLSize,
716734
stage_infos: MultiStageData<PipelineStageInfo>,
735+
736+
/// Sizes of currently bound [`wgt::BufferBindingType::Storage`] buffers.
737+
///
738+
/// Specifically:
739+
///
740+
/// - The keys are ['ResourceBinding`] values (that is, the WGSL `@group`
741+
/// and `@binding` attributes) for `var<storage>` global variables in the
742+
/// current module that contain runtime-sized arrays.
743+
///
744+
/// - The values are the actual sizes of the buffers currently bound to
745+
/// provide those globals' contents, which are needed to implement bounds
746+
/// checks and the WGSL `arrayLength` function.
747+
///
748+
/// For each stage `S` in `stage_infos`, we consult this to find the sizes
749+
/// of the buffers listed in [`stage_infos.S.sized_bindings`], which we must
750+
/// pass to the entry point.
751+
///
752+
/// See [`device::CompiledShader::sized_bindings`] for more details.
753+
///
754+
/// [`ResourceBinding`]: naga::ResourceBinding
717755
storage_buffer_length_map: fxhash::FxHashMap<naga::ResourceBinding, wgt::BufferSize>,
756+
718757
work_group_memory_sizes: Vec<u32>,
719758
push_constants: Vec<u32>,
720759
}

0 commit comments

Comments
 (0)