Skip to content

Commit 9834d9a

Browse files
andyleisersoncwfitzgerald
authored andcommitted
Revert "Validate binding ranges against buffer size"
This reverts commit ef428fc.
1 parent b052780 commit 9834d9a

File tree

22 files changed

+213
-363
lines changed

22 files changed

+213
-363
lines changed

wgpu-core/src/binding_model.rs

Lines changed: 8 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -94,48 +94,15 @@ impl WebGpuError for CreateBindGroupLayoutError {
9494
}
9595
}
9696

97-
#[derive(Clone, Debug, Error)]
98-
#[non_exhaustive]
99-
pub enum BindingError {
100-
#[error(transparent)]
101-
DestroyedResource(#[from] DestroyedResourceError),
102-
#[error("Buffer {buffer}: Binding with size {binding_size} at offset {offset} would overflow buffer size of {buffer_size}")]
103-
BindingRangeTooLarge {
104-
buffer: ResourceErrorIdent,
105-
offset: wgt::BufferAddress,
106-
binding_size: u64,
107-
buffer_size: u64,
108-
},
109-
#[error("Buffer {buffer}: Binding offset {offset} is greater than or equal to buffer size {buffer_size}")]
110-
BindingOffsetTooLarge {
111-
buffer: ResourceErrorIdent,
112-
offset: wgt::BufferAddress,
113-
buffer_size: u64,
114-
},
115-
}
97+
//TODO: refactor this to move out `enum BindingError`.
11698

117-
impl WebGpuError for BindingError {
118-
fn webgpu_error_type(&self) -> ErrorType {
119-
match self {
120-
Self::DestroyedResource(e) => e.webgpu_error_type(),
121-
Self::BindingRangeTooLarge { .. } | Self::BindingOffsetTooLarge { .. } => {
122-
ErrorType::Validation
123-
}
124-
}
125-
}
126-
}
127-
128-
// TODO: there may be additional variants here that can be extracted into
129-
// `BindingError`.
13099
#[derive(Clone, Debug, Error)]
131100
#[non_exhaustive]
132101
pub enum CreateBindGroupError {
133102
#[error(transparent)]
134103
Device(#[from] DeviceError),
135104
#[error(transparent)]
136105
DestroyedResource(#[from] DestroyedResourceError),
137-
#[error(transparent)]
138-
BindingError(#[from] BindingError),
139106
#[error(
140107
"Binding count declared with at most {expected} items, but {actual} items were provided"
141108
)]
@@ -146,6 +113,12 @@ pub enum CreateBindGroupError {
146113
BindingArrayLengthMismatch { actual: usize, expected: usize },
147114
#[error("Array binding provided zero elements")]
148115
BindingArrayZeroLength,
116+
#[error("The bound range {range:?} of {buffer} overflows its size ({size})")]
117+
BindingRangeTooLarge {
118+
buffer: ResourceErrorIdent,
119+
range: Range<wgt::BufferAddress>,
120+
size: u64,
121+
},
149122
#[error("Binding size {actual} of {buffer} is less than minimum {min}")]
150123
BindingSizeTooSmall {
151124
buffer: ResourceErrorIdent,
@@ -260,14 +233,14 @@ impl WebGpuError for CreateBindGroupError {
260233
let e: &dyn WebGpuError = match self {
261234
Self::Device(e) => e,
262235
Self::DestroyedResource(e) => e,
263-
Self::BindingError(e) => e,
264236
Self::MissingBufferUsage(e) => e,
265237
Self::MissingTextureUsage(e) => e,
266238
Self::ResourceUsageCompatibility(e) => e,
267239
Self::InvalidResource(e) => e,
268240
Self::BindingArrayPartialLengthMismatch { .. }
269241
| Self::BindingArrayLengthMismatch { .. }
270242
| Self::BindingArrayZeroLength
243+
| Self::BindingRangeTooLarge { .. }
271244
| Self::BindingSizeTooSmall { .. }
272245
| Self::BindingsNumMismatch { .. }
273246
| Self::BindingZeroSize(_)

wgpu-core/src/command/bundle.rs

Lines changed: 22 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -602,7 +602,6 @@ fn set_pipeline(
602602
Ok(())
603603
}
604604

605-
// This function is duplicative of `render::set_index_buffer`.
606605
fn set_index_buffer(
607606
state: &mut State,
608607
buffer_guard: &crate::storage::Storage<Fallible<Buffer>>,
@@ -621,20 +620,21 @@ fn set_index_buffer(
621620
buffer.same_device(&state.device)?;
622621
buffer.check_usage(wgt::BufferUsages::INDEX)?;
623622

624-
let end = buffer.resolve_binding_size(offset, size)?;
625-
623+
let end = match size {
624+
Some(s) => offset + s.get(),
625+
None => buffer.size,
626+
};
626627
state
627628
.buffer_memory_init_actions
628629
.extend(buffer.initialization_status.read().create_action(
629630
&buffer,
630-
offset..end.get(),
631+
offset..end,
631632
MemoryInitKind::NeedsInitializedMemory,
632633
));
633-
state.set_index_buffer(buffer, index_format, offset..end.get());
634+
state.set_index_buffer(buffer, index_format, offset..end);
634635
Ok(())
635636
}
636637

637-
// This function is duplicative of `render::set_vertex_buffer`.
638638
fn set_vertex_buffer(
639639
state: &mut State,
640640
buffer_guard: &crate::storage::Storage<Fallible<Buffer>>,
@@ -662,16 +662,18 @@ fn set_vertex_buffer(
662662
buffer.same_device(&state.device)?;
663663
buffer.check_usage(wgt::BufferUsages::VERTEX)?;
664664

665-
let end = buffer.resolve_binding_size(offset, size)?;
666-
665+
let end = match size {
666+
Some(s) => offset + s.get(),
667+
None => buffer.size,
668+
};
667669
state
668670
.buffer_memory_init_actions
669671
.extend(buffer.initialization_status.read().create_action(
670672
&buffer,
671-
offset..end.get(),
673+
offset..end,
672674
MemoryInitKind::NeedsInitializedMemory,
673675
));
674-
state.vertex[slot as usize] = Some(VertexState::new(buffer, offset..end.get()));
676+
state.vertex[slot as usize] = Some(VertexState::new(buffer, offset..end));
675677
Ok(())
676678
}
677679

@@ -963,14 +965,10 @@ impl RenderBundle {
963965
size,
964966
} => {
965967
let buffer = buffer.try_raw(snatch_guard)?;
966-
let bb = unsafe {
967-
// SAFETY: The binding size was checked against the buffer size
968-
// in `set_index_buffer` and again in `IndexState::flush`.
969-
hal::BufferBinding::new_unchecked(
970-
buffer,
971-
*offset,
972-
size.expect("size was resolved in `RenderBundleEncoder::finish`"),
973-
)
968+
let bb = hal::BufferBinding {
969+
buffer,
970+
offset: *offset,
971+
size: *size,
974972
};
975973
unsafe { raw.set_index_buffer(bb, *index_format) };
976974
}
@@ -981,14 +979,10 @@ impl RenderBundle {
981979
size,
982980
} => {
983981
let buffer = buffer.try_raw(snatch_guard)?;
984-
let bb = unsafe {
985-
// SAFETY: The binding size was checked against the buffer size
986-
// in `set_vertex_buffer` and again in `VertexState::flush`.
987-
hal::BufferBinding::new_unchecked(
988-
buffer,
989-
*offset,
990-
size.expect("size was resolved in `RenderBundleEncoder::finish`"),
991-
)
982+
let bb = hal::BufferBinding {
983+
buffer,
984+
offset: *offset,
985+
size: *size,
992986
};
993987
unsafe { raw.set_vertex_buffer(*slot, bb) };
994988
}
@@ -1137,9 +1131,6 @@ crate::impl_trackable!(RenderBundle);
11371131
/// [`RenderBundleEncoder::finish`] records the currently set index buffer here,
11381132
/// and calls [`State::flush_index`] before any indexed draw command to produce
11391133
/// a `SetIndexBuffer` command if one is necessary.
1140-
///
1141-
/// Binding ranges must be validated against the size of the buffer before
1142-
/// being stored in `IndexState`.
11431134
#[derive(Debug)]
11441135
struct IndexState {
11451136
buffer: Arc<Buffer>,
@@ -1161,24 +1152,13 @@ impl IndexState {
11611152
/// Generate a `SetIndexBuffer` command to prepare for an indexed draw
11621153
/// command, if needed.
11631154
fn flush(&mut self) -> Option<ArcRenderCommand> {
1164-
// This was all checked before, but let's check again just in case.
1165-
let binding_size = self
1166-
.range
1167-
.end
1168-
.checked_sub(self.range.start)
1169-
.and_then(wgt::BufferSize::new);
1170-
assert!(
1171-
self.range.end <= self.buffer.size && binding_size.is_some(),
1172-
"index buffer range must have non-zero size and be contained in buffer",
1173-
);
1174-
11751155
if self.is_dirty {
11761156
self.is_dirty = false;
11771157
Some(ArcRenderCommand::SetIndexBuffer {
11781158
buffer: self.buffer.clone(),
11791159
index_format: self.format,
11801160
offset: self.range.start,
1181-
size: binding_size,
1161+
size: wgt::BufferSize::new(self.range.end - self.range.start),
11821162
})
11831163
} else {
11841164
None
@@ -1194,9 +1174,6 @@ impl IndexState {
11941174
/// calls this type's [`flush`] method just before any draw command to
11951175
/// produce a `SetVertexBuffer` commands if one is necessary.
11961176
///
1197-
/// Binding ranges must be validated against the size of the buffer before
1198-
/// being stored in `VertexState`.
1199-
///
12001177
/// [`flush`]: IndexState::flush
12011178
#[derive(Debug)]
12021179
struct VertexState {
@@ -1206,9 +1183,6 @@ struct VertexState {
12061183
}
12071184

12081185
impl VertexState {
1209-
/// Create a new `VertexState`.
1210-
///
1211-
/// The `range` must be contained within `buffer`.
12121186
fn new(buffer: Arc<Buffer>, range: Range<wgt::BufferAddress>) -> Self {
12131187
Self {
12141188
buffer,
@@ -1221,24 +1195,13 @@ impl VertexState {
12211195
///
12221196
/// `slot` is the index of the vertex buffer slot that `self` tracks.
12231197
fn flush(&mut self, slot: u32) -> Option<ArcRenderCommand> {
1224-
// This was all checked before, but let's check again just in case.
1225-
let binding_size = self
1226-
.range
1227-
.end
1228-
.checked_sub(self.range.start)
1229-
.and_then(wgt::BufferSize::new);
1230-
assert!(
1231-
self.range.end <= self.buffer.size && binding_size.is_some(),
1232-
"vertex buffer range must have non-zero size and be contained in buffer",
1233-
);
1234-
12351198
if self.is_dirty {
12361199
self.is_dirty = false;
12371200
Some(ArcRenderCommand::SetVertexBuffer {
12381201
slot,
12391202
buffer: self.buffer.clone(),
12401203
offset: self.range.start,
1241-
size: binding_size,
1204+
size: wgt::BufferSize::new(self.range.end - self.range.start),
12421205
})
12431206
} else {
12441207
None

wgpu-core/src/command/draw.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use wgt::error::{ErrorType, WebGpuError};
77
use super::bind::BinderError;
88
use crate::command::pass;
99
use crate::{
10-
binding_model::{BindingError, LateMinBufferBindingSizeMismatch, PushConstantUploadError},
10+
binding_model::{LateMinBufferBindingSizeMismatch, PushConstantUploadError},
1111
resource::{
1212
DestroyedResourceError, MissingBufferUsageError, MissingTextureUsageError,
1313
ResourceErrorIdent,
@@ -89,8 +89,6 @@ pub enum RenderCommandError {
8989
MissingTextureUsage(#[from] MissingTextureUsageError),
9090
#[error(transparent)]
9191
PushConstants(#[from] PushConstantUploadError),
92-
#[error(transparent)]
93-
BindingError(#[from] BindingError),
9492
#[error("Viewport size {{ w: {w}, h: {h} }} greater than device's requested `max_texture_dimension_2d` limit {max}, or less than zero")]
9593
InvalidViewportRectSize { w: f32, h: f32, max: u32 },
9694
#[error("Viewport has invalid rect {rect:?} for device's requested `max_texture_dimension_2d` limit; Origin less than -2 * `max_texture_dimension_2d` ({min}), or rect extends past 2 * `max_texture_dimension_2d` - 1 ({max})")]
@@ -112,7 +110,6 @@ impl WebGpuError for RenderCommandError {
112110
Self::MissingBufferUsage(e) => e,
113111
Self::MissingTextureUsage(e) => e,
114112
Self::PushConstants(e) => e,
115-
Self::BindingError(e) => e,
116113

117114
Self::BindGroupIndexOutOfRange { .. }
118115
| Self::VertexBufferIndexOutOfRange { .. }

wgpu-core/src/command/render.rs

Lines changed: 30 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use alloc::{borrow::Cow, sync::Arc, vec::Vec};
2-
use core::{fmt, num::NonZeroU32, str};
2+
use core::{fmt, num::NonZeroU32, ops::Range, str};
33

44
use arrayvec::ArrayVec;
55
use thiserror::Error;
@@ -356,17 +356,13 @@ struct IndexState {
356356
}
357357

358358
impl IndexState {
359-
fn update_buffer<B: hal::DynBuffer + ?Sized>(
360-
&mut self,
361-
binding: &hal::BufferBinding<'_, B>,
362-
format: IndexFormat,
363-
) {
359+
fn update_buffer(&mut self, range: Range<BufferAddress>, format: IndexFormat) {
364360
self.buffer_format = Some(format);
365361
let shift = match format {
366362
IndexFormat::Uint16 => 1,
367363
IndexFormat::Uint32 => 2,
368364
};
369-
self.limit = binding.size.get() >> shift;
365+
self.limit = (range.end - range.start) >> shift;
370366
}
371367

372368
fn reset(&mut self) {
@@ -2326,7 +2322,6 @@ fn set_pipeline(
23262322
Ok(())
23272323
}
23282324

2329-
// This function is duplicative of `bundle::set_index_buffer`.
23302325
fn set_index_buffer(
23312326
state: &mut State,
23322327
cmd_buf: &Arc<CommandBuffer>,
@@ -2346,27 +2341,33 @@ fn set_index_buffer(
23462341
buffer.same_device_as(cmd_buf.as_ref())?;
23472342

23482343
buffer.check_usage(BufferUsages::INDEX)?;
2344+
let buf_raw = buffer.try_raw(state.general.snatch_guard)?;
23492345

2350-
let binding = buffer
2351-
.binding(offset, size, state.general.snatch_guard)
2352-
.map_err(RenderCommandError::from)?;
2353-
state.index.update_buffer(&binding, index_format);
2346+
let end = match size {
2347+
Some(s) => offset + s.get(),
2348+
None => buffer.size,
2349+
};
2350+
state.index.update_buffer(offset..end, index_format);
23542351

23552352
state.general.buffer_memory_init_actions.extend(
23562353
buffer.initialization_status.read().create_action(
23572354
&buffer,
2358-
offset..(offset + binding.size.get()),
2355+
offset..end,
23592356
MemoryInitKind::NeedsInitializedMemory,
23602357
),
23612358
);
23622359

2360+
let bb = hal::BufferBinding {
2361+
buffer: buf_raw,
2362+
offset,
2363+
size,
2364+
};
23632365
unsafe {
2364-
hal::DynCommandEncoder::set_index_buffer(state.general.raw_encoder, binding, index_format);
2366+
hal::DynCommandEncoder::set_index_buffer(state.general.raw_encoder, bb, index_format);
23652367
}
23662368
Ok(())
23672369
}
23682370

2369-
// This function is duplicative of `render::set_vertex_buffer`.
23702371
fn set_vertex_buffer(
23712372
state: &mut State,
23722373
cmd_buf: &Arc<CommandBuffer>,
@@ -2398,22 +2399,30 @@ fn set_vertex_buffer(
23982399
}
23992400

24002401
buffer.check_usage(BufferUsages::VERTEX)?;
2402+
let buf_raw = buffer.try_raw(state.general.snatch_guard)?;
24012403

2402-
let binding = buffer
2403-
.binding(offset, size, state.general.snatch_guard)
2404-
.map_err(RenderCommandError::from)?;
2405-
state.vertex.buffer_sizes[slot as usize] = Some(binding.size.get());
2404+
//TODO: where are we checking that the offset is in bound?
2405+
let buffer_size = match size {
2406+
Some(s) => s.get(),
2407+
None => buffer.size - offset,
2408+
};
2409+
state.vertex.buffer_sizes[slot as usize] = Some(buffer_size);
24062410

24072411
state.general.buffer_memory_init_actions.extend(
24082412
buffer.initialization_status.read().create_action(
24092413
&buffer,
2410-
offset..(offset + binding.size.get()),
2414+
offset..(offset + buffer_size),
24112415
MemoryInitKind::NeedsInitializedMemory,
24122416
),
24132417
);
24142418

2419+
let bb = hal::BufferBinding {
2420+
buffer: buf_raw,
2421+
offset,
2422+
size,
2423+
};
24152424
unsafe {
2416-
hal::DynCommandEncoder::set_vertex_buffer(state.general.raw_encoder, slot, binding);
2425+
hal::DynCommandEncoder::set_vertex_buffer(state.general.raw_encoder, slot, bb);
24172426
}
24182427
if let Some(pipeline) = state.pipeline.as_ref() {
24192428
state.vertex.update_limits(&pipeline.vertex_steps);

0 commit comments

Comments
 (0)