mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-12-08 21:26:17 +00:00
Validate vertex and index buffer alignment (#7929)
This commit is contained in:
parent
ae946dbb8c
commit
c868142709
@ -29,8 +29,8 @@ webgpu:api,validation,encoding,cmds,index_access:*
|
||||
//FAIL: webgpu:api,validation,encoding,cmds,render,draw:*
|
||||
webgpu:api,validation,encoding,cmds,render,draw:index_buffer_OOB:*
|
||||
webgpu:api,validation,encoding,cmds,render,draw:unused_buffer_bound:*
|
||||
webgpu:api,validation,encoding,cmds,render,setIndexBuffer:index_buffer_state:*
|
||||
webgpu:api,validation,encoding,cmds,render,setVertexBuffer:vertex_buffer_state:*
|
||||
webgpu:api,validation,encoding,cmds,render,setIndexBuffer:*
|
||||
webgpu:api,validation,encoding,cmds,render,setVertexBuffer:*
|
||||
webgpu:api,validation,encoding,encoder_state:*
|
||||
webgpu:api,validation,encoding,encoder_open_state:non_pass_commands:*
|
||||
webgpu:api,validation,encoding,encoder_open_state:render_pass_commands:*
|
||||
|
||||
@ -622,6 +622,13 @@ fn set_index_buffer(
|
||||
buffer.same_device(&state.device)?;
|
||||
buffer.check_usage(wgt::BufferUsages::INDEX)?;
|
||||
|
||||
if offset % u64::try_from(index_format.byte_size()).unwrap() != 0 {
|
||||
return Err(RenderCommandError::UnalignedIndexBuffer {
|
||||
offset,
|
||||
alignment: index_format.byte_size(),
|
||||
}
|
||||
.into());
|
||||
}
|
||||
let end = offset + buffer.resolve_binding_size(offset, size)?;
|
||||
|
||||
state
|
||||
@ -663,6 +670,9 @@ fn set_vertex_buffer(
|
||||
buffer.same_device(&state.device)?;
|
||||
buffer.check_usage(wgt::BufferUsages::VERTEX)?;
|
||||
|
||||
if offset % wgt::VERTEX_ALIGNMENT != 0 {
|
||||
return Err(RenderCommandError::UnalignedVertexBuffer { slot, offset }.into());
|
||||
}
|
||||
let end = offset + buffer.resolve_binding_size(offset, size)?;
|
||||
|
||||
state
|
||||
|
||||
@ -73,6 +73,12 @@ pub enum RenderCommandError {
|
||||
BindGroupIndexOutOfRange(#[from] pass::BindGroupIndexOutOfRange),
|
||||
#[error("Vertex buffer index {index} is greater than the device's requested `max_vertex_buffers` limit {max}")]
|
||||
VertexBufferIndexOutOfRange { index: u32, max: u32 },
|
||||
#[error(
|
||||
"Offset {offset} for vertex buffer in slot {slot} is not a multiple of `VERTEX_ALIGNMENT`"
|
||||
)]
|
||||
UnalignedVertexBuffer { slot: u32, offset: u64 },
|
||||
#[error("Offset {offset} for index buffer is not a multiple of {alignment}")]
|
||||
UnalignedIndexBuffer { offset: u64, alignment: usize },
|
||||
#[error("Render pipeline targets are incompatible with render pass")]
|
||||
IncompatiblePipelineTargets(#[from] crate::device::RenderPassCompatibilityError),
|
||||
#[error("{0} writes to depth, while the pass has read-only depth access")]
|
||||
@ -116,6 +122,8 @@ impl WebGpuError for RenderCommandError {
|
||||
|
||||
Self::BindGroupIndexOutOfRange { .. }
|
||||
| Self::VertexBufferIndexOutOfRange { .. }
|
||||
| Self::UnalignedIndexBuffer { .. }
|
||||
| Self::UnalignedVertexBuffer { .. }
|
||||
| Self::IncompatibleDepthAccess(..)
|
||||
| Self::IncompatibleStencilAccess(..)
|
||||
| Self::InvalidViewportRectSize { .. }
|
||||
|
||||
@ -2344,6 +2344,13 @@ fn set_index_buffer(
|
||||
|
||||
buffer.check_usage(BufferUsages::INDEX)?;
|
||||
|
||||
if offset % u64::try_from(index_format.byte_size()).unwrap() != 0 {
|
||||
return Err(RenderCommandError::UnalignedIndexBuffer {
|
||||
offset,
|
||||
alignment: index_format.byte_size(),
|
||||
}
|
||||
.into());
|
||||
}
|
||||
let (binding, resolved_size) = buffer
|
||||
.binding(offset, size, state.general.snatch_guard)
|
||||
.map_err(RenderCommandError::from)?;
|
||||
@ -2397,6 +2404,9 @@ fn set_vertex_buffer(
|
||||
|
||||
buffer.check_usage(BufferUsages::VERTEX)?;
|
||||
|
||||
if offset % wgt::VERTEX_ALIGNMENT != 0 {
|
||||
return Err(RenderCommandError::UnalignedVertexBuffer { slot, offset }.into());
|
||||
}
|
||||
let (binding, buffer_size) = buffer
|
||||
.binding(offset, size, state.general.snatch_guard)
|
||||
.map_err(RenderCommandError::from)?;
|
||||
|
||||
@ -3159,7 +3159,7 @@ impl Device {
|
||||
limit: self.limits.max_vertex_buffer_array_stride,
|
||||
});
|
||||
}
|
||||
if vb_state.array_stride % wgt::VERTEX_STRIDE_ALIGNMENT != 0 {
|
||||
if vb_state.array_stride % wgt::VERTEX_ALIGNMENT != 0 {
|
||||
return Err(pipeline::CreateRenderPipelineError::UnalignedVertexStride {
|
||||
index: i as u32,
|
||||
stride: vb_state.array_stride,
|
||||
|
||||
@ -512,7 +512,7 @@ pub enum CreateRenderPipelineError {
|
||||
given: u32,
|
||||
limit: u32,
|
||||
},
|
||||
#[error("Vertex buffer {index} stride {stride} does not respect `VERTEX_STRIDE_ALIGNMENT`")]
|
||||
#[error("Vertex buffer {index} stride {stride} does not respect `VERTEX_ALIGNMENT`")]
|
||||
UnalignedVertexStride {
|
||||
index: u32,
|
||||
stride: wgt::BufferAddress,
|
||||
|
||||
@ -97,10 +97,18 @@ pub const COPY_BUFFER_ALIGNMENT: BufferAddress = 4;
|
||||
/// [`get_mapped_range()`]: ../wgpu/struct.Buffer.html#method.get_mapped_range
|
||||
pub const MAP_ALIGNMENT: BufferAddress = 8;
|
||||
|
||||
/// [Vertex buffer offsets] and [strides] have to be a multiple of this number.
|
||||
///
|
||||
/// [Vertex buffer offsets]: ../wgpu/util/trait.RenderEncoder.html#tymethod.set_vertex_buffer
|
||||
/// [strides]: ../wgpu/struct.VertexBufferLayout.html#structfield.array_stride
|
||||
pub const VERTEX_ALIGNMENT: BufferAddress = 4;
|
||||
|
||||
/// [Vertex buffer strides] have to be a multiple of this number.
|
||||
///
|
||||
/// [Vertex buffer strides]: ../wgpu/struct.VertexBufferLayout.html#structfield.array_stride
|
||||
#[deprecated(note = "Use `VERTEX_ALIGNMENT` instead", since = "27.0.0")]
|
||||
pub const VERTEX_STRIDE_ALIGNMENT: BufferAddress = 4;
|
||||
|
||||
/// Ranges of [writes to push constant storage] must be at least this aligned.
|
||||
///
|
||||
/// [writes to push constant storage]: ../wgpu/struct.RenderPass.html#method.set_push_constants
|
||||
|
||||
@ -76,7 +76,7 @@ impl RenderPipeline {
|
||||
pub struct VertexBufferLayout<'a> {
|
||||
/// The stride, in bytes, between elements of this buffer (between vertices).
|
||||
///
|
||||
/// This must be a multiple of [`VERTEX_STRIDE_ALIGNMENT`].
|
||||
/// This must be a multiple of [`VERTEX_ALIGNMENT`].
|
||||
pub array_stride: BufferAddress,
|
||||
/// How often this vertex buffer is "stepped" forward.
|
||||
pub step_mode: VertexStepMode,
|
||||
|
||||
@ -90,8 +90,12 @@ pub use wgt::{
|
||||
TextureTransition, TextureUsages, TextureUses, TextureViewDimension, Trace, VertexAttribute,
|
||||
VertexFormat, VertexStepMode, WasmNotSend, WasmNotSendSync, WasmNotSync, COPY_BUFFER_ALIGNMENT,
|
||||
COPY_BYTES_PER_ROW_ALIGNMENT, MAP_ALIGNMENT, PUSH_CONSTANT_ALIGNMENT,
|
||||
QUERY_RESOLVE_BUFFER_ALIGNMENT, QUERY_SET_MAX_QUERIES, QUERY_SIZE, VERTEX_STRIDE_ALIGNMENT,
|
||||
QUERY_RESOLVE_BUFFER_ALIGNMENT, QUERY_SET_MAX_QUERIES, QUERY_SIZE, VERTEX_ALIGNMENT,
|
||||
};
|
||||
|
||||
#[expect(deprecated)]
|
||||
pub use wgt::VERTEX_STRIDE_ALIGNMENT;
|
||||
|
||||
// wasm-only types, we try to keep as many types non-platform
|
||||
// specific, but these need to depend on web-sys.
|
||||
#[cfg(web)]
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user