Skip to content

Commit 0210857

Browse files
committed
Revise comments; discuss platform considerations in hal
1 parent eff1aca commit 0210857

3 files changed

Lines changed: 56 additions & 26 deletions

File tree

wgpu-core/src/device/resource.rs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1214,18 +1214,20 @@ impl Device {
12141214

12151215
// The great thing about buffer sizes is there are so many to choose from!
12161216
// - The application may request an arbitrary byte-aligned size.
1217-
// - We add an extra byte if it's a vertex or index buffer so that we can simulate
1218-
// binding an empty range at the end of the buffer, which Vulkan does not natively
1219-
// allow.
1220-
// - The overall buffer size must generally be a non-zero multiple of
1221-
// COPY_BUFFER_ALIGNMENT (4), but in special cases an additional platform-dependent
1222-
// requirement may apply (e.g. 256 for D3D12 constant buffers).
1217+
// - If the buffer supports usage as a vertex or index buffer, we must ensure there
1218+
// is a naturally aligned block of 4B at the end of the buffer. Zero-size bindings
1219+
// are not supported by hal and must be redirected to this block.
1220+
// - The overall buffer size must be a non-zero multiple of COPY_BUFFER_ALIGNMENT (4).
1221+
// In some cases additional platform-dependent requirements may apply. The actual
1222+
// allocated size of the buffer is returned by hal along with the buffer object from
1223+
// `create_buffer`. `wgpu-core` is responsible for ensuring that any region of the
1224+
// buffer, including hal-added padding, is initialized before it may be accessed.
12231225
//
1224-
// Because initialization operates at multiples of COPY_BUFFER_ALIGNMENT, and
1225-
// initialization tracking will never determine that it is necessary to initialize a
1226-
// region outside the application-visible range, round the tracked initialization range
1227-
// down to a multiple of COPY_BUFFER_ALIGNMENT (tail_start), and eagerly zero-initialize
1228-
// from there to the buffer's true end offset.
1226+
// Because buffer writes for initialization operate at multiples of COPY_BUFFER_ALIGNMENT,
1227+
// and because initialization tracking will never determine that it is necessary to
1228+
// initialize a region outside the application-visible range, round the tracked
1229+
// initialization range down to a multiple of COPY_BUFFER_ALIGNMENT (tail_start), and
1230+
// eagerly zero-initialize from there to the buffer's true end.
12291231

12301232
let actual_size = if desc.size == 0 {
12311233
wgt::COPY_BUFFER_ALIGNMENT

wgpu-core/src/resource.rs

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -632,23 +632,11 @@ impl Buffer {
632632

633633
/// Resolve the binding range for a vertex or index buffer.
634634
///
635-
/// These may have zero size. For storage and uniform buffer bindings, which
636-
/// must have non-zero size, use [`Buffer::binding`].
635+
/// This function is for vertex and index buffer bindings, which WebGPU
636+
/// allows to have zero size. For storage and uniform buffer bindings,
637+
/// which must have non-zero size, use [`Buffer::binding`].
637638
///
638639
/// Returns an error if the binding would overflow the buffer.
639-
///
640-
/// Vulkan's `vkCmdBindVertexBuffers` and `vkCmdBindIndexBuffer` have
641-
/// some important restrictions:
642-
///
643-
/// 1. There is no ability to specify the size of the binding.
644-
/// 2. The binding offset must be strictly less than the buffer size.
645-
///
646-
/// Due to (1), resolving a zero-size binding in-place could let a
647-
/// shader read non-zero data outside the bounds of the binding.
648-
/// To avoid that, zero-size bindings are relocated to the end of the buffer.
649-
/// Due to (2), buffers with [`wgt::BufferUses::INDEX`] or
650-
/// [`wgt::BufferUses::VERTEX`] must be padded with zeros on creation to
651-
/// support binding them at the end.
652640
pub fn resolve_vertex_or_index_binding_range(
653641
&self,
654642
offset: wgt::BufferAddress,

wgpu-hal/src/lib.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -905,6 +905,18 @@ pub trait Device: WasmNotSendSync {
905905
/// Creates a new buffer.
906906
///
907907
/// The initial usage is `wgt::BufferUses::empty()`.
908+
///
909+
/// `wgpu_hal` may adjust the size in `desc` to a larger value if required
910+
/// by the platform. On success, it returns a tuple of the buffer itself
911+
/// and its actual allocated size. `wgpu-core` is responsible for
912+
/// initializing any portion of the buffer that may be accessed, including
913+
/// any padding added by `create_buffer`.
914+
///
915+
/// Platform-dependent padding is currently required for uniform buffers on
916+
/// dx12. Support for zero-size vertex and index bindings is also platform
917+
/// dependent, but presently, `wgpu-core` adds padding to the end of all
918+
/// buffers with vertex or index usage, and redirects all zero-size bindings
919+
/// to that padding region, regardless of platform.
908920
unsafe fn create_buffer(
909921
&self,
910922
desc: &BufferDescriptor,
@@ -1655,11 +1667,39 @@ pub trait CommandEncoder: WasmNotSendSync + fmt::Debug {
16551667

16561668
unsafe fn set_render_pipeline(&mut self, pipeline: &<Self::A as Api>::RenderPipeline);
16571669

1670+
/// Register an index buffer binding.
1671+
///
1672+
/// The binding offset must be 4B-aligned and strictly less than the buffer
1673+
/// size. On some backends, the binding size is ignored. This means that
1674+
/// zero-size bindings must be simulated by binding a region of zeros
1675+
/// spanning from the provided offset to the end of the buffer. See
1676+
/// [`CommandEncoder::set_vertex_buffer`] for more detail.
16581677
unsafe fn set_index_buffer<'a>(
16591678
&mut self,
16601679
binding: BufferBinding<'a, <Self::A as Api>::Buffer, wgt::BufferAddress>,
16611680
format: wgt::IndexFormat,
16621681
);
1682+
/// Register a vertex buffer binding.
1683+
///
1684+
/// The binding offset must be 4B-aligned and strictly less than the buffer
1685+
/// size. On some backends, the binding size is ignored. This means that
1686+
/// zero-size bindings must be simulated by binding a region of zeros
1687+
/// spanning from the provided offset to the end of the buffer.
1688+
///
1689+
/// These restrictions arise from Vulkan's `vkCmdBindVertexBuffers` and
1690+
/// `vkCmdBindIndexBuffer`, which:
1691+
///
1692+
/// 1. Do not support specifying the size of the binding.
1693+
/// 2. Require that the binding offset is strictly less than the buffer size.
1694+
///
1695+
/// A read at any offset from a zero-size binding is out-of-bounds, and
1696+
/// should return zero. Because the binding size is not respected, this
1697+
/// means there may not be non-zero data between the binding offset and
1698+
/// the end of the buffer.
1699+
///
1700+
/// Because the binding offset must be strictly less than the buffer size,
1701+
/// supporting zero-size bindings requires zero padding at the end of the
1702+
/// buffer.
16631703
unsafe fn set_vertex_buffer<'a>(
16641704
&mut self,
16651705
index: u32,

0 commit comments

Comments
 (0)