// SAFETY: The value we are passing to `new_unchecked` is not zero, so this is safe. const SRC_BUFFER_SIZE: NonZeroU64 = unsafe { NonZeroU64::new_unchecked(size_of::<u32>() as u64 * 3) };
// SAFETY: The value we are passing to `new_unchecked` is not zero, so this is safe. const DST_BUFFER_SIZE: NonZeroU64 = unsafe {
NonZeroU64::new_unchecked(
SRC_BUFFER_SIZE.get() * 2, // From above: `dst: array<u32, 6>`
)
};
/// `Ok(None)` will only be returned if `buffer_size` is `0`. pubfn create_src_bind_group(
&self,
device: &dyn hal::DynDevice,
limits: &wgt::Limits,
buffer_size: u64,
buffer: &dyn hal::DynBuffer,
) -> Result<Option<Box<dyn hal::DynBindGroup>>, DeviceError> { let binding_size = calculate_src_buffer_binding_size(buffer_size, limits); let Some(binding_size) = NonZeroU64::new(binding_size) else { return Ok(None);
}; let hal_desc = hal::BindGroupDescriptor {
label: None,
layout: self.src_bind_group_layout.as_ref(),
entries: &[hal::BindGroupEntry {
binding: 0,
resource_index: 0,
count: 1,
}],
buffers: &[hal::BufferBinding {
buffer,
offset: 0,
size: Some(binding_size),
}],
samplers: &[],
textures: &[],
acceleration_structures: &[],
}; unsafe {
device
.create_bind_group(&hal_desc)
.map(Some)
.map_err(DeviceError::from_hal)
}
}
pubfn params<'a>(&'a self, limits: &wgt::Limits, offset: u64, buffer_size: u64) -> Params<'a> { // The offset we receive is only required to be aligned to 4 bytes. // // Binding offsets and dynamic offsets are required to be aligned to // min_storage_buffer_offset_alignment (256 bytes by default). // // So, we work around this limitation by calculating an aligned offset // and pass the remainder through a push constant. // // We could bind the whole buffer and only have to pass the offset // through a push constant but we might run into the // max_storage_buffer_binding_size limit. // // See the inner docs of `calculate_src_buffer_binding_size` to // see how we get the appropriate `binding_size`. let alignment = limits.min_storage_buffer_offset_alignment as u64; let binding_size = calculate_src_buffer_binding_size(buffer_size, limits); let aligned_offset = offset - offset % alignment; // This works because `binding_size` is either `buffer_size` or `alignment * 2 + buffer_size % alignment`. let max_aligned_offset = buffer_size - binding_size; let aligned_offset = aligned_offset.min(max_aligned_offset); let offset_remainder = offset - aligned_offset;
fn calculate_src_buffer_binding_size(buffer_size: u64, limits: &wgt::Limits) -> u64 { let alignment = limits.min_storage_buffer_offset_alignment as u64;
// We need to choose a binding size that can address all possible sets of 12 contiguous bytes in the buffer taking // into account that the dynamic offset needs to be a multiple of `min_storage_buffer_offset_alignment`.
// Given the know variables: `offset`, `buffer_size`, `alignment` and the rule `offset + 12 <= buffer_size`.
// Let `chunks = floor(buffer_size / alignment)`. // Let `chunk` be the interval `[0, chunks]`. // Let `offset = alignment * chunk + r` where `r` is the interval [0, alignment - 4]. // Let `binding` be the interval `[offset, offset + 12]`. // Let `aligned_offset = alignment * chunk`. // Let `aligned_binding` be the interval `[aligned_offset, aligned_offset + r + 12]`. // Let `aligned_binding_size = r + 12 = [12, alignment + 8]`. // Let `min_aligned_binding_size = alignment + 8`.
// `min_aligned_binding_size` is the minimum binding size required to address all 12 contiguous bytes in the buffer // but the last aligned_offset + min_aligned_binding_size might overflow the buffer. In order to avoid this we must // pick a larger `binding_size` that satisfies: `last_aligned_offset + binding_size = buffer_size` and // `binding_size >= min_aligned_binding_size`.
// Let `buffer_size = alignment * chunks + sr` where `sr` is the interval [0, alignment - 4]. // Let `last_aligned_offset = alignment * (chunks - u)` where `u` is the interval [0, chunks]. // => `binding_size = buffer_size - last_aligned_offset` // => `binding_size = alignment * chunks + sr - alignment * (chunks - u)` // => `binding_size = alignment * chunks + sr - alignment * chunks + alignment * u` // => `binding_size = sr + alignment * u` // => `min_aligned_binding_size <= sr + alignment * u` // => `alignment + 8 <= sr + alignment * u` // => `u` must be at least 2 // => `binding_size = sr + alignment * 2`
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.13Bemerkung:
(vorverarbeitet am 2026-06-23)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.