diff --git a/wgpu-core/src/command/bundle.rs b/wgpu-core/src/command/bundle.rs index 221ce52dd92..310d034ded5 100644 --- a/wgpu-core/src/command/bundle.rs +++ b/wgpu-core/src/command/bundle.rs @@ -250,6 +250,15 @@ impl RenderBundleEncoder { } => { let scope = PassErrorScope::SetBindGroup(bind_group_id); + let bind_group: &crate::binding_model::BindGroup = state + .trackers + .bind_groups + .use_extend(&*bind_group_guard, bind_group_id, (), ()) + .map_err(|_| RenderCommandError::InvalidBindGroup(bind_group_id)) + .map_pass_err(scope)?; + self.check_valid_to_use(bind_group.device_id.value) + .map_pass_err(scope)?; + let max_bind_groups = device.limits.max_bind_groups; if (index as u32) >= max_bind_groups { return Err(RenderCommandError::BindGroupIndexOutOfRange { @@ -266,12 +275,6 @@ impl RenderBundleEncoder { next_dynamic_offset = offsets_range.end; let offsets = &base.dynamic_offsets[offsets_range.clone()]; - let bind_group = state - .trackers - .bind_groups - .use_extend(&*bind_group_guard, bind_group_id, (), ()) - .map_err(|_| RenderCommandError::InvalidBindGroup(bind_group_id)) - .map_pass_err(scope)?; if bind_group.dynamic_binding_info.len() != offsets.len() { return Err(RenderCommandError::InvalidDynamicOffsetCount { actual: offsets.len(), @@ -318,6 +321,8 @@ impl RenderBundleEncoder { .use_extend(&*pipeline_guard, pipeline_id, (), ()) .map_err(|_| RenderCommandError::InvalidPipeline(pipeline_id)) .map_pass_err(scope)?; + self.check_valid_to_use(pipeline.device_id.value) + .map_pass_err(scope)?; self.context .check_compatible(&pipeline.pass_context) @@ -357,6 +362,8 @@ impl RenderBundleEncoder { .buffers .use_extend(&*buffer_guard, buffer_id, (), hal::BufferUses::INDEX) .unwrap(); + self.check_valid_to_use(buffer.device_id.value) + .map_pass_err(scope)?; check_buffer_usage(buffer.usage, wgt::BufferUsages::INDEX) .map_pass_err(scope)?; @@ -384,6 +391,8 @@ impl RenderBundleEncoder { .buffers .use_extend(&*buffer_guard, buffer_id, (), hal::BufferUses::VERTEX) .unwrap(); + self.check_valid_to_use(buffer.device_id.value) + .map_pass_err(scope)?; check_buffer_usage(buffer.usage, wgt::BufferUsages::VERTEX) .map_pass_err(scope)?; @@ -509,6 +518,8 @@ impl RenderBundleEncoder { .buffers .use_extend(&*buffer_guard, buffer_id, (), hal::BufferUses::INDIRECT) .unwrap(); + self.check_valid_to_use(buffer.device_id.value) + .map_pass_err(scope)?; check_buffer_usage(buffer.usage, wgt::BufferUsages::INDIRECT) .map_pass_err(scope)?; @@ -543,6 +554,8 @@ impl RenderBundleEncoder { .use_extend(&*buffer_guard, buffer_id, (), hal::BufferUses::INDIRECT) .map_err(|err| RenderCommandError::Buffer(buffer_id, err)) .map_pass_err(scope)?; + self.check_valid_to_use(buffer.device_id.value) + .map_pass_err(scope)?; check_buffer_usage(buffer.usage, wgt::BufferUsages::INDIRECT) .map_pass_err(scope)?; @@ -594,6 +607,17 @@ impl RenderBundleEncoder { }) } + pub(crate) fn check_valid_to_use( + &self, + device_id: id::Valid, + ) -> Result<(), crate::validation::ValidToUseError> { + if device_id.0 != self.parent_id { + return Err(crate::validation::ValidToUseError); + } + + Ok(()) + } + pub fn set_index_buffer( &mut self, buffer_id: id::BufferId, @@ -1272,6 +1296,8 @@ pub(super) enum RenderBundleErrorInner { Draw(#[from] DrawError), #[error(transparent)] MissingDownlevelFlags(#[from] MissingDownlevelFlags), + #[error(transparent)] + ValidToUse(crate::validation::ValidToUseError), } impl From for RenderBundleErrorInner @@ -1319,6 +1345,12 @@ where } } +impl From for RenderBundleErrorInner { + fn from(err: crate::validation::ValidToUseError) -> Self { + RenderBundleErrorInner::ValidToUse(err) + } +} + pub mod bundle_ffi { use super::{RenderBundleEncoder, RenderCommand}; use crate::{id, RawString}; diff --git a/wgpu-core/src/validation.rs b/wgpu-core/src/validation.rs index 148eeecfa53..ce942d09b1e 100644 --- a/wgpu-core/src/validation.rs +++ b/wgpu-core/src/validation.rs @@ -1186,3 +1186,7 @@ impl Interface { Ok(outputs) } } + +#[derive(Clone, Debug, Error)] +#[error("GPUObject is not valid to use with method target")] +pub(crate) struct ValidToUseError;