diff --git a/wgpu-core/src/binding_model.rs b/wgpu-core/src/binding_model.rs index 2357a8c776..6f43ac5234 100644 --- a/wgpu-core/src/binding_model.rs +++ b/wgpu-core/src/binding_model.rs @@ -373,10 +373,6 @@ impl BindingTypeMaxCountValidator { limits.max_sampled_textures_per_shader_stage, BindingTypeMaxCountErrorKind::SampledTextures, )?; - self.storage_buffers.validate( - limits.max_storage_buffers_per_shader_stage, - BindingTypeMaxCountErrorKind::StorageBuffers, - )?; self.samplers.validate( limits.max_samplers_per_shader_stage, BindingTypeMaxCountErrorKind::Samplers, diff --git a/wgpu-core/src/command/compute.rs b/wgpu-core/src/command/compute.rs index 5de03917d2..133a5af35a 100644 --- a/wgpu-core/src/command/compute.rs +++ b/wgpu-core/src/command/compute.rs @@ -136,6 +136,8 @@ pub enum ComputePassErrorInner { BindGroupIndexOutOfRange { index: u32, max: u32 }, #[error(transparent)] DestroyedResource(#[from] DestroyedResourceError), + #[error("Indirect buffer offset {0:?} is not a multiple of 4")] + UnalignedIndirectBufferOffset(BufferAddress), #[error("Indirect buffer uses bytes {offset}..{end_offset} which overruns indirect buffer of size {buffer_size}")] IndirectBufferOverrun { offset: u64, @@ -495,8 +497,6 @@ impl Global { state.raw_encoder.begin_compute_pass(&hal_desc); } - // TODO: We should be draining the commands here, avoiding extra copies in the process. - // (A command encoder can't be executed twice!) for command in base.commands { match command { ArcComputeCommand::SetBindGroup { @@ -780,7 +780,7 @@ fn set_push_constant( .binder .pipeline_layout .as_ref() - //TODO: don't error here, lazily update the push constants + // TODO: don't error here, lazily update the push constants using `state.push_constants` .ok_or(ComputePassErrorInner::Dispatch( DispatchError::MissingPipeline, ))?; @@ -847,6 +847,10 @@ fn dispatch_indirect( .merge_single(&buffer, hal::BufferUses::INDIRECT)?; buffer.check_usage(wgt::BufferUsages::INDIRECT)?; + if offset % 4 != 0 { + return Err(ComputePassErrorInner::UnalignedIndirectBufferOffset(offset)); + } + let end_offset = offset + size_of::() as u64; if end_offset > buffer.size { return Err(ComputePassErrorInner::IndirectBufferOverrun { diff --git a/wgpu-core/src/command/render.rs b/wgpu-core/src/command/render.rs index b6680333c2..d22eb5f0d6 100644 --- a/wgpu-core/src/command/render.rs +++ b/wgpu-core/src/command/render.rs @@ -638,6 +638,8 @@ pub enum RenderPassErrorInner { MissingFeatures(#[from] MissingFeatures), #[error(transparent)] MissingDownlevelFlags(#[from] MissingDownlevelFlags), + #[error("Indirect buffer offset {0:?} is not a multiple of 4")] + UnalignedIndirectBufferOffset(BufferAddress), #[error("Indirect draw uses bytes {offset}..{end_offset} {} which overruns indirect buffer of size {buffer_size}", count.map_or_else(String::new, |v| format!("(using count {v})")))] IndirectBufferOverrun { @@ -2450,6 +2452,10 @@ fn multi_draw_indirect( let actual_count = count.map_or(1, |c| c.get()); + if offset % 4 != 0 { + return Err(RenderPassErrorInner::UnalignedIndirectBufferOffset(offset)); + } + let end_offset = offset + stride as u64 * actual_count as u64; if end_offset > indirect_buffer.size { return Err(RenderPassErrorInner::IndirectBufferOverrun { @@ -2534,6 +2540,10 @@ fn multi_draw_indirect_count( count_buffer.check_usage(BufferUsages::INDIRECT)?; let count_raw = count_buffer.try_raw(state.snatch_guard)?; + if offset % 4 != 0 { + return Err(RenderPassErrorInner::UnalignedIndirectBufferOffset(offset)); + } + let end_offset = offset + stride * max_count as u64; if end_offset > indirect_buffer.size { return Err(RenderPassErrorInner::IndirectBufferOverrun { diff --git a/wgpu-core/src/device/resource.rs b/wgpu-core/src/device/resource.rs index 03b183e085..8c6eb5b2f2 100644 --- a/wgpu-core/src/device/resource.rs +++ b/wgpu-core/src/device/resource.rs @@ -38,7 +38,6 @@ use arrayvec::ArrayVec; use once_cell::sync::OnceCell; use smallvec::SmallVec; -use thiserror::Error; use wgt::{ math::align_to, DeviceLostReason, TextureFormat, TextureSampleType, TextureViewDimension, }; @@ -187,14 +186,6 @@ impl Drop for Device { } } -#[derive(Clone, Debug, Error)] -pub enum CreateDeviceError { - #[error("Not enough memory left to create device")] - OutOfMemory, - #[error("Failed to create internal buffer for initializing textures")] - FailedToCreateZeroBuffer(#[from] DeviceError), -} - impl Device { pub(crate) fn raw(&self) -> &dyn hal::DynDevice { self.raw.as_ref() @@ -372,7 +363,7 @@ impl Device { let Some(view) = view.upgrade() else { continue; }; - let Some(raw_view) = view.raw.snatch(self.snatchable_lock.write()) else { + let Some(raw_view) = view.raw.snatch(&mut self.snatchable_lock.write()) else { continue; }; @@ -386,7 +377,8 @@ impl Device { let Some(bind_group) = bind_group.upgrade() else { continue; }; - let Some(raw_bind_group) = bind_group.raw.snatch(self.snatchable_lock.write()) + let Some(raw_bind_group) = + bind_group.raw.snatch(&mut self.snatchable_lock.write()) else { continue; }; diff --git a/wgpu-core/src/present.rs b/wgpu-core/src/present.rs index c9d0124bf4..b12e35328a 100644 --- a/wgpu-core/src/present.rs +++ b/wgpu-core/src/present.rs @@ -288,8 +288,11 @@ impl Global { .textures .remove(texture.tracker_index()); let suf = surface.raw(device.backend()).unwrap(); - let exclusive_snatch_guard = device.snatchable_lock.write(); - match texture.inner.snatch(exclusive_snatch_guard).unwrap() { + match texture + .inner + .snatch(&mut device.snatchable_lock.write()) + .unwrap() + { resource::TextureInner::Surface { raw, parent_id } => { if surface_id != parent_id { log::error!("Presented frame is from a different surface"); @@ -359,8 +362,11 @@ impl Global { .textures .remove(texture.tracker_index()); let suf = surface.raw(device.backend()); - let exclusive_snatch_guard = device.snatchable_lock.write(); - match texture.inner.snatch(exclusive_snatch_guard).unwrap() { + match texture + .inner + .snatch(&mut device.snatchable_lock.write()) + .unwrap() + { resource::TextureInner::Surface { raw, parent_id } => { if surface_id == parent_id { unsafe { suf.unwrap().discard_texture(raw) }; diff --git a/wgpu-core/src/resource.rs b/wgpu-core/src/resource.rs index 5df285da54..32fde3dd57 100644 --- a/wgpu-core/src/resource.rs +++ b/wgpu-core/src/resource.rs @@ -737,8 +737,7 @@ impl Buffer { let device = &self.device; let temp = { - let snatch_guard = device.snatchable_lock.write(); - let raw = match self.raw.snatch(snatch_guard) { + let raw = match self.raw.snatch(&mut device.snatchable_lock.write()) { Some(raw) => raw, None => { return Err(DestroyError::AlreadyDestroyed); @@ -1185,8 +1184,7 @@ impl Texture { let device = &self.device; let temp = { - let snatch_guard = device.snatchable_lock.write(); - let raw = match self.inner.snatch(snatch_guard) { + let raw = match self.inner.snatch(&mut device.snatchable_lock.write()) { Some(TextureInner::Native { raw }) => raw, Some(TextureInner::Surface { .. }) => { return Ok(()); diff --git a/wgpu-core/src/snatch.rs b/wgpu-core/src/snatch.rs index 9866b77723..a817e2068c 100644 --- a/wgpu-core/src/snatch.rs +++ b/wgpu-core/src/snatch.rs @@ -38,7 +38,7 @@ impl Snatchable { } /// Take the value. Requires a the snatchable lock's write guard. - pub fn snatch(&self, _guard: ExclusiveSnatchGuard) -> Option { + pub fn snatch(&self, _guard: &mut ExclusiveSnatchGuard) -> Option { unsafe { (*self.value.get()).take() } }