improve device mismatch errors

This commit is contained in:
teoxoy 2024-06-18 20:36:51 +02:00 committed by Nicolas Silva
parent adfb183dc0
commit ce716adb5e
14 changed files with 242 additions and 69 deletions

View File

@ -8,7 +8,7 @@ use crate::{
hal_api::HalApi,
id::{BindGroupLayoutId, BufferId, SamplerId, TextureId, TextureViewId},
init_tracker::{BufferInitTrackerAction, TextureInitTrackerAction},
resource::{Resource, ResourceInfo, ResourceType},
resource::{ParentDevice, Resource, ResourceInfo, ResourceType},
resource_log,
snatch::{SnatchGuard, Snatchable},
track::{BindGroupStates, UsageConflict},
@ -518,6 +518,13 @@ impl<A: HalApi> Resource for BindGroupLayout<A> {
&self.label
}
}
impl<A: HalApi> ParentDevice<A> for BindGroupLayout<A> {
fn device(&self) -> &Arc<Device<A>> {
&self.device
}
}
impl<A: HalApi> BindGroupLayout<A> {
pub(crate) fn raw(&self) -> &A::BindGroupLayout {
self.raw.as_ref().unwrap()
@ -751,6 +758,12 @@ impl<A: HalApi> Resource for PipelineLayout<A> {
}
}
impl<A: HalApi> ParentDevice<A> for PipelineLayout<A> {
fn device(&self) -> &Arc<Device<A>> {
&self.device
}
}
#[repr(C)]
#[derive(Clone, Debug, Hash, Eq, PartialEq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
@ -956,6 +969,12 @@ impl<A: HalApi> Resource for BindGroup<A> {
}
}
impl<A: HalApi> ParentDevice<A> for BindGroup<A> {
fn device(&self) -> &Arc<Device<A>> {
&self.device
}
}
#[derive(Clone, Debug, Error)]
#[non_exhaustive]
pub enum GetBindGroupLayoutError {

View File

@ -97,7 +97,7 @@ use crate::{
id,
init_tracker::{BufferInitTrackerAction, MemoryInitKind, TextureInitTrackerAction},
pipeline::{PipelineFlags, RenderPipeline, VertexStep},
resource::{Buffer, Resource, ResourceInfo, ResourceType},
resource::{Buffer, ParentDevice, Resource, ResourceInfo, ResourceType},
resource_log,
snatch::SnatchGuard,
track::RenderBundleScope,
@ -1104,6 +1104,12 @@ impl<A: HalApi> Resource for RenderBundle<A> {
}
}
impl<A: HalApi> ParentDevice<A> for RenderBundle<A> {
fn device(&self) -> &Arc<Device<A>> {
&self.device
}
}
/// A render bundle's current index buffer state.
///
/// [`RenderBundleEncoder::finish`] records the currently set index buffer here,

View File

@ -11,7 +11,7 @@ use crate::{
hal_api::HalApi,
id::{BufferId, CommandEncoderId, DeviceId, TextureId},
init_tracker::{MemoryInitKind, TextureInitRange},
resource::{Resource, Texture, TextureClearMode},
resource::{ParentDevice, Resource, Texture, TextureClearMode},
snatch::SnatchGuard,
track::{TextureSelector, TextureTracker},
};
@ -104,7 +104,7 @@ impl Global {
.get(dst)
.map_err(|_| ClearError::InvalidBuffer(dst))?;
dst_buffer.device.same_device(&cmd_buf.device)?;
dst_buffer.same_device_as(cmd_buf.as_ref())?;
cmd_buf_data
.trackers
@ -201,7 +201,7 @@ impl Global {
.get(dst)
.map_err(|_| ClearError::InvalidTexture(dst))?;
dst_texture.device.same_device(&cmd_buf.device)?;
dst_texture.same_device_as(cmd_buf.as_ref())?;
// Check if subresource aspects are valid.
let clear_aspects =

View File

@ -15,7 +15,7 @@ use crate::{
hal_api::HalApi,
hal_label, id,
init_tracker::MemoryInitKind,
resource::{self, Resource},
resource::{self, ParentDevice, Resource},
snatch::SnatchGuard,
track::{Tracker, TrackerIndex, UsageConflict, UsageScope},
validation::{check_buffer_usage, MissingBufferUsageError},
@ -350,11 +350,8 @@ impl Global {
);
};
if query_set.device.same_device(&cmd_buf.device).is_err() {
return (
ComputePass::new(None, arc_desc),
Some(CommandEncoderError::WrongDeviceForTimestampWritesQuerySet),
);
if let Err(e) = query_set.same_device_as(cmd_buf.as_ref()) {
return (ComputePass::new(None, arc_desc), Some(e.into()));
}
Some(ArcComputePassTimestampWrites {
@ -582,7 +579,7 @@ impl Global {
} => {
let scope = PassErrorScope::SetBindGroup(bind_group.as_info().id());
bind_group.device.same_device(device).map_pass_err(scope)?;
bind_group.same_device_as(cmd_buf).map_pass_err(scope)?;
let max_bind_groups = cmd_buf.limits.max_bind_groups;
if index >= max_bind_groups {
@ -649,7 +646,7 @@ impl Global {
let pipeline_id = pipeline.as_info().id();
let scope = PassErrorScope::SetPipelineCompute(pipeline_id);
pipeline.device.same_device(device).map_pass_err(scope)?;
pipeline.same_device_as(cmd_buf).map_pass_err(scope)?;
state.pipeline = Some(pipeline_id);
@ -790,7 +787,7 @@ impl Global {
pipeline: state.pipeline,
};
buffer.device.same_device(device).map_pass_err(scope)?;
buffer.same_device_as(cmd_buf).map_pass_err(scope)?;
state.is_ready().map_pass_err(scope)?;
@ -885,7 +882,7 @@ impl Global {
} => {
let scope = PassErrorScope::WriteTimestamp;
query_set.device.same_device(device).map_pass_err(scope)?;
query_set.same_device_as(cmd_buf).map_pass_err(scope)?;
device
.require_features(wgt::Features::TIMESTAMP_QUERY_INSIDE_PASSES)
@ -903,7 +900,7 @@ impl Global {
} => {
let scope = PassErrorScope::BeginPipelineStatisticsQuery;
query_set.device.same_device(device).map_pass_err(scope)?;
query_set.same_device_as(cmd_buf).map_pass_err(scope)?;
let query_set = tracker.query_sets.insert_single(query_set);

View File

@ -29,7 +29,7 @@ use crate::lock::{rank, Mutex};
use crate::snatch::SnatchGuard;
use crate::init_tracker::BufferInitTrackerAction;
use crate::resource::{Resource, ResourceInfo, ResourceType};
use crate::resource::{ParentDevice, Resource, ResourceInfo, ResourceType};
use crate::track::{Tracker, UsageScope};
use crate::{api_log, global::Global, hal_api::HalApi, id, resource_log, Label};
@ -541,6 +541,12 @@ impl<A: HalApi> Resource for CommandBuffer<A> {
}
}
impl<A: HalApi> ParentDevice<A> for CommandBuffer<A> {
fn device(&self) -> &Arc<Device<A>> {
&self.device
}
}
#[derive(Copy, Clone, Debug)]
pub struct BasePassRef<'a, C> {
pub label: Option<&'a str>,
@ -633,11 +639,8 @@ pub enum CommandEncoderError {
Device(#[from] DeviceError),
#[error("Command encoder is locked by a previously created render/compute pass. Before recording any new commands, the pass must be ended.")]
Locked,
#[error("QuerySet provided for pass timestamp writes is invalid.")]
InvalidTimestampWritesQuerySetId,
#[error("QuerySet provided for pass timestamp writes that was created by a different device.")]
WrongDeviceForTimestampWritesQuerySet,
}
impl Global {

View File

@ -9,7 +9,7 @@ use crate::{
hal_api::HalApi,
id::{self, Id},
init_tracker::MemoryInitKind,
resource::QuerySet,
resource::{ParentDevice, QuerySet},
storage::Storage,
Epoch, FastHashMap, Index,
};
@ -405,7 +405,7 @@ impl Global {
.add_single(&*query_set_guard, query_set_id)
.ok_or(QueryError::InvalidQuerySet(query_set_id))?;
query_set.device.same_device(&cmd_buf.device)?;
query_set.same_device_as(cmd_buf.as_ref())?;
let (dst_buffer, dst_pending) = {
let buffer_guard = hub.buffers.read();
@ -413,7 +413,7 @@ impl Global {
.get(destination)
.map_err(|_| QueryError::InvalidBuffer(destination))?;
dst_buffer.device.same_device(&cmd_buf.device)?;
dst_buffer.same_device_as(cmd_buf.as_ref())?;
tracker
.buffers

View File

@ -25,7 +25,7 @@ use crate::{
hal_label, id,
init_tracker::{MemoryInitKind, TextureInitRange, TextureInitTrackerAction},
pipeline::{self, PipelineFlags},
resource::{QuerySet, Texture, TextureView, TextureViewNotRenderableReason},
resource::{ParentDevice, QuerySet, Texture, TextureView, TextureViewNotRenderableReason},
storage::Storage,
track::{TextureSelector, Tracker, UsageConflict, UsageScope},
validation::{
@ -1476,7 +1476,9 @@ impl Global {
.ok_or(RenderCommandError::InvalidBindGroup(bind_group_id))
.map_pass_err(scope)?;
bind_group.device.same_device(device).map_pass_err(scope)?;
bind_group
.same_device_as(cmd_buf.as_ref())
.map_pass_err(scope)?;
bind_group
.validate_dynamic_bindings(index, &temp_offsets, &cmd_buf.limits)
@ -1542,7 +1544,9 @@ impl Global {
.ok_or(RenderCommandError::InvalidPipeline(pipeline_id))
.map_pass_err(scope)?;
pipeline.device.same_device(device).map_pass_err(scope)?;
pipeline
.same_device_as(cmd_buf.as_ref())
.map_pass_err(scope)?;
info.context
.check_compatible(
@ -1669,7 +1673,9 @@ impl Global {
.merge_single(&*buffer_guard, buffer_id, hal::BufferUses::INDEX)
.map_pass_err(scope)?;
buffer.device.same_device(device).map_pass_err(scope)?;
buffer
.same_device_as(cmd_buf.as_ref())
.map_pass_err(scope)?;
check_buffer_usage(buffer_id, buffer.usage, BufferUsages::INDEX)
.map_pass_err(scope)?;
@ -1720,7 +1726,9 @@ impl Global {
.merge_single(&*buffer_guard, buffer_id, hal::BufferUses::VERTEX)
.map_pass_err(scope)?;
buffer.device.same_device(device).map_pass_err(scope)?;
buffer
.same_device_as(cmd_buf.as_ref())
.map_pass_err(scope)?;
let max_vertex_buffers = device.limits.max_vertex_buffers;
if slot >= max_vertex_buffers {
@ -2325,7 +2333,9 @@ impl Global {
.ok_or(RenderCommandError::InvalidRenderBundle(bundle_id))
.map_pass_err(scope)?;
bundle.device.same_device(device).map_pass_err(scope)?;
bundle
.same_device_as(cmd_buf.as_ref())
.map_pass_err(scope)?;
info.context
.check_compatible(

View File

@ -13,7 +13,7 @@ use crate::{
has_copy_partial_init_tracker_coverage, MemoryInitKind, TextureInitRange,
TextureInitTrackerAction,
},
resource::{Resource, Texture, TextureErrorDimension},
resource::{ParentDevice, Resource, Texture, TextureErrorDimension},
snatch::SnatchGuard,
track::{TextureSelector, Tracker},
};
@ -602,7 +602,7 @@ impl Global {
.get(source)
.map_err(|_| TransferError::InvalidBuffer(source))?;
src_buffer.device.same_device(device)?;
src_buffer.same_device_as(cmd_buf.as_ref())?;
cmd_buf_data
.trackers
@ -626,7 +626,7 @@ impl Global {
.get(destination)
.map_err(|_| TransferError::InvalidBuffer(destination))?;
dst_buffer.device.same_device(device)?;
dst_buffer.same_device_as(cmd_buf.as_ref())?;
cmd_buf_data
.trackers
@ -777,7 +777,7 @@ impl Global {
.get(destination.texture)
.map_err(|_| TransferError::InvalidTexture(destination.texture))?;
dst_texture.device.same_device(device)?;
dst_texture.same_device_as(cmd_buf.as_ref())?;
let (hal_copy_size, array_layer_count) = validate_texture_copy_range(
destination,
@ -810,7 +810,7 @@ impl Global {
.get(source.buffer)
.map_err(|_| TransferError::InvalidBuffer(source.buffer))?;
src_buffer.device.same_device(device)?;
src_buffer.same_device_as(cmd_buf.as_ref())?;
tracker
.buffers
@ -943,7 +943,7 @@ impl Global {
.get(source.texture)
.map_err(|_| TransferError::InvalidTexture(source.texture))?;
src_texture.device.same_device(device)?;
src_texture.same_device_as(cmd_buf.as_ref())?;
let (hal_copy_size, array_layer_count) =
validate_texture_copy_range(source, &src_texture.desc, CopySide::Source, copy_size)?;
@ -997,7 +997,7 @@ impl Global {
.get(destination.buffer)
.map_err(|_| TransferError::InvalidBuffer(destination.buffer))?;
dst_buffer.device.same_device(device)?;
dst_buffer.same_device_as(cmd_buf.as_ref())?;
tracker
.buffers
@ -1127,8 +1127,8 @@ impl Global {
.get(destination.texture)
.map_err(|_| TransferError::InvalidTexture(source.texture))?;
src_texture.device.same_device(device)?;
dst_texture.device.same_device(device)?;
src_texture.same_device_as(cmd_buf.as_ref())?;
dst_texture.same_device_as(cmd_buf.as_ref())?;
// src and dst texture format must be copy-compatible
// https://gpuweb.github.io/gpuweb/#copy-compatible

View File

@ -15,6 +15,7 @@ use crate::{
pipeline, present,
resource::{
self, BufferAccessError, BufferAccessResult, BufferMapOperation, CreateBufferError,
ParentDevice,
},
validation::check_buffer_usage,
Label, LabelHelpers as _,
@ -1124,7 +1125,7 @@ impl Global {
Err(..) => break 'error binding_model::CreateBindGroupError::InvalidLayout,
};
if let Err(e) = bind_group_layout.device.same_device(&device) {
if let Err(e) = bind_group_layout.same_device(&device) {
break 'error e.into();
}

View File

@ -3,7 +3,9 @@ use crate::{
hal_api::HalApi,
hub::Hub,
id::{BindGroupLayoutId, PipelineLayoutId},
resource::{Buffer, BufferAccessError, BufferAccessResult, BufferMapOperation},
resource::{
Buffer, BufferAccessError, BufferAccessResult, BufferMapOperation, ResourceErrorIdent,
},
snatch::SnatchGuard,
Label, DOWNLEVEL_ERROR_MESSAGE,
};
@ -382,6 +384,30 @@ fn map_buffer<A: HalApi>(
#[error("Device is invalid")]
pub struct InvalidDevice;
#[derive(Clone, Debug)]
pub struct WrongDevice {
pub(super) res: ResourceErrorIdent,
pub(super) res_device: ResourceErrorIdent,
pub(super) target: Option<ResourceErrorIdent>,
pub(super) target_device: ResourceErrorIdent,
}
impl std::fmt::Display for WrongDevice {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
write!(
f,
"{} of {} doesn't match {}",
self.res_device, self.res, self.target_device
)?;
if let Some(target) = self.target.as_ref() {
write!(f, " of {target}")?;
}
Ok(())
}
}
impl std::error::Error for WrongDevice {}
#[derive(Clone, Debug, Error)]
#[non_exhaustive]
pub enum DeviceError {
@ -395,8 +421,8 @@ pub enum DeviceError {
ResourceCreationFailed,
#[error("QueueId is invalid")]
InvalidQueueId,
#[error("Attempt to use a resource with a different device from the one that created it")]
WrongDevice,
#[error(transparent)]
WrongDevice(#[from] Box<WrongDevice>),
}
impl From<hal::DeviceError> for DeviceError {

View File

@ -16,8 +16,8 @@ use crate::{
init_tracker::{has_copy_partial_init_tracker_coverage, TextureInitRange},
lock::{rank, Mutex, RwLockWriteGuard},
resource::{
Buffer, BufferAccessError, BufferMapState, DestroyedBuffer, DestroyedTexture, Resource,
ResourceInfo, ResourceType, StagingBuffer, Texture, TextureInner,
Buffer, BufferAccessError, BufferMapState, DestroyedBuffer, DestroyedTexture, ParentDevice,
Resource, ResourceInfo, ResourceType, StagingBuffer, Texture, TextureInner,
},
resource_log, track, FastHashMap, SubmissionIndex,
};
@ -53,6 +53,12 @@ impl<A: HalApi> Resource for Queue<A> {
}
}
impl<A: HalApi> ParentDevice<A> for Queue<A> {
fn device(&self) -> &Arc<Device<A>> {
self.device.as_ref().unwrap()
}
}
impl<A: HalApi> Drop for Queue<A> {
fn drop(&mut self) {
let queue = self.raw.take().unwrap();
@ -408,7 +414,7 @@ impl Global {
let device = queue.device.as_ref().unwrap();
buffer.device.same_device(device)?;
buffer.same_device_as(queue.as_ref())?;
let data_size = data.len() as wgt::BufferAddress;
@ -449,6 +455,7 @@ impl Global {
}
let result = self.queue_write_staging_buffer_impl(
&queue,
device,
pending_writes,
&staging_buffer,
@ -523,6 +530,7 @@ impl Global {
}
let result = self.queue_write_staging_buffer_impl(
&queue,
device,
pending_writes,
&staging_buffer,
@ -587,6 +595,7 @@ impl Global {
fn queue_write_staging_buffer_impl<A: HalApi>(
&self,
queue: &Arc<Queue<A>>,
device: &Arc<Device<A>>,
pending_writes: &mut PendingWrites<A>,
staging_buffer: &StagingBuffer<A>,
@ -612,7 +621,7 @@ impl Global {
.get(&snatch_guard)
.ok_or(TransferError::InvalidBuffer(buffer_id))?;
dst.device.same_device(device)?;
dst.same_device_as(queue.as_ref())?;
let src_buffer_size = staging_buffer.size;
self.queue_validate_write_buffer_impl(&dst, buffer_id, buffer_offset, src_buffer_size)?;
@ -695,7 +704,7 @@ impl Global {
.get(destination.texture)
.map_err(|_| TransferError::InvalidTexture(destination.texture))?;
dst.device.same_device(device)?;
dst.same_device_as(queue.as_ref())?;
if !dst.desc.usage.contains(wgt::TextureUsages::COPY_DST) {
return Err(
@ -1176,7 +1185,7 @@ impl Global {
Err(_) => continue,
};
cmdbuf.device.same_device(device)?;
cmdbuf.same_device_as(queue.as_ref())?;
#[cfg(feature = "trace")]
if let Some(ref mut trace) = *device.trace.lock() {

View File

@ -24,8 +24,8 @@ use crate::{
pool::ResourcePool,
registry::Registry,
resource::{
self, Buffer, QuerySet, Resource, ResourceInfo, ResourceType, Sampler, Texture,
TextureView, TextureViewNotRenderableReason,
self, Buffer, ParentDevice, QuerySet, Resource, ResourceInfo, ResourceType, Sampler,
Texture, TextureView, TextureViewNotRenderableReason,
},
resource_log,
snatch::{SnatchGuard, SnatchLock, Snatchable},
@ -313,12 +313,6 @@ impl<A: HalApi> Device<A> {
self.valid.load(Ordering::Acquire)
}
pub fn same_device(self: &Arc<Self>, other: &Arc<Self>) -> Result<(), DeviceError> {
Arc::ptr_eq(self, other)
.then_some(())
.ok_or(DeviceError::WrongDevice)
}
pub(crate) fn release_queue(&self, queue: A::Queue) {
assert!(self.queue_to_drop.set(queue).is_ok());
}
@ -1904,7 +1898,7 @@ impl<A: HalApi> Device<A> {
.add_single(storage, bb.buffer_id, internal_use)
.ok_or(Error::InvalidBuffer(bb.buffer_id))?;
buffer.device.same_device(self)?;
buffer.same_device(self)?;
check_buffer_usage(bb.buffer_id, buffer.usage, pub_usage)?;
let raw_buffer = buffer
@ -1997,7 +1991,7 @@ impl<A: HalApi> Device<A> {
.add_single(storage, id)
.ok_or(Error::InvalidSampler(id))?;
sampler.device.same_device(self)?;
sampler.same_device(self)?;
Ok(sampler)
}
@ -2019,7 +2013,7 @@ impl<A: HalApi> Device<A> {
.add_single(storage, id)
.ok_or(Error::InvalidTextureView(id))?;
view.device.same_device(self)?;
view.same_device(self)?;
let (pub_usage, internal_use) = self.texture_use_parameters(
binding,
@ -2038,7 +2032,7 @@ impl<A: HalApi> Device<A> {
texture_id,
))?;
texture.device.same_device(&view.device)?;
texture.same_device_as(view)?;
check_texture_usage(texture.desc.usage, pub_usage)?;
@ -2523,7 +2517,7 @@ impl<A: HalApi> Device<A> {
// Validate total resource counts and check for a matching device
for bgl in &bind_group_layouts {
bgl.device.same_device(self)?;
bgl.same_device(self)?;
count_validator.merge(&bgl.binding_count_validator);
}
@ -2631,7 +2625,7 @@ impl<A: HalApi> Device<A> {
.get(desc.stage.module)
.map_err(|_| validation::StageError::InvalidModule)?;
shader_module.device.same_device(self)?;
shader_module.same_device(self)?;
// Get the pipeline layout from the desc if it is provided.
let pipeline_layout = match desc.layout {
@ -2641,7 +2635,7 @@ impl<A: HalApi> Device<A> {
.get(pipeline_layout_id)
.map_err(|_| pipeline::CreateComputePipelineError::InvalidLayout)?;
pipeline_layout.device.same_device(self)?;
pipeline_layout.same_device(self)?;
Some(pipeline_layout)
}
@ -2703,7 +2697,7 @@ impl<A: HalApi> Device<A> {
break 'cache None;
};
cache.device.same_device(self)?;
cache.same_device(self)?;
Some(cache)
};
@ -3081,7 +3075,7 @@ impl<A: HalApi> Device<A> {
.get(pipeline_layout_id)
.map_err(|_| pipeline::CreateRenderPipelineError::InvalidLayout)?;
pipeline_layout.device.same_device(self)?;
pipeline_layout.same_device(self)?;
Some(pipeline_layout)
}
@ -3116,7 +3110,7 @@ impl<A: HalApi> Device<A> {
error: validation::StageError::InvalidModule,
}
})?;
vertex_shader_module.device.same_device(self)?;
vertex_shader_module.same_device(self)?;
let stage_err = |error| pipeline::CreateRenderPipelineError::Stage { stage, error };
@ -3308,7 +3302,7 @@ impl<A: HalApi> Device<A> {
break 'cache None;
};
cache.device.same_device(self)?;
cache.same_device(self)?;
Some(cache)
};

View File

@ -7,7 +7,7 @@ use crate::{
device::{Device, DeviceError, MissingDownlevelFlags, MissingFeatures, RenderPassContext},
hal_api::HalApi,
id::{PipelineCacheId, PipelineLayoutId, ShaderModuleId},
resource::{Resource, ResourceInfo, ResourceType},
resource::{ParentDevice, Resource, ResourceInfo, ResourceType},
resource_log, validation, Label,
};
use arrayvec::ArrayVec;
@ -90,6 +90,12 @@ impl<A: HalApi> Resource for ShaderModule<A> {
}
}
impl<A: HalApi> ParentDevice<A> for ShaderModule<A> {
fn device(&self) -> &Arc<Device<A>> {
&self.device
}
}
impl<A: HalApi> ShaderModule<A> {
pub(crate) fn raw(&self) -> &A::ShaderModule {
self.raw.as_ref().unwrap()
@ -258,6 +264,12 @@ impl<A: HalApi> Resource for ComputePipeline<A> {
}
}
impl<A: HalApi> ParentDevice<A> for ComputePipeline<A> {
fn device(&self) -> &Arc<Device<A>> {
&self.device
}
}
impl<A: HalApi> ComputePipeline<A> {
pub(crate) fn raw(&self) -> &A::ComputePipeline {
self.raw.as_ref().unwrap()
@ -326,6 +338,12 @@ impl<A: HalApi> Resource for PipelineCache<A> {
}
}
impl<A: HalApi> ParentDevice<A> for PipelineCache<A> {
fn device(&self) -> &Arc<Device<A>> {
&self.device
}
}
/// Describes how the vertex buffer is interpreted.
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
@ -585,6 +603,12 @@ impl<A: HalApi> Resource for RenderPipeline<A> {
}
}
impl<A: HalApi> ParentDevice<A> for RenderPipeline<A> {
fn device(&self) -> &Arc<Device<A>> {
&self.device
}
}
impl<A: HalApi> RenderPipeline<A> {
pub(crate) fn raw(&self) -> &A::RenderPipeline {
self.raw.as_ref().unwrap()

View File

@ -4,7 +4,7 @@ use crate::{
binding_model::BindGroup,
device::{
queue, resource::DeferredDestroy, BufferMapPendingClosure, Device, DeviceError, HostMap,
MissingDownlevelFlags, MissingFeatures,
MissingDownlevelFlags, MissingFeatures, WrongDevice,
},
global::Global,
hal_api::HalApi,
@ -143,6 +143,48 @@ impl<T: Resource> ResourceInfo<T> {
}
}
#[derive(Clone, Debug)]
pub struct ResourceErrorIdent {
r#type: ResourceType,
label: String,
}
impl std::fmt::Display for ResourceErrorIdent {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
write!(f, "{} with '{}' label", self.r#type, self.label)
}
}
pub(crate) trait ParentDevice<A: HalApi>: Resource {
fn device(&self) -> &Arc<Device<A>>;
fn same_device_as<O: ParentDevice<A>>(&self, other: &O) -> Result<(), DeviceError> {
Arc::ptr_eq(self.device(), other.device())
.then_some(())
.ok_or_else(|| {
DeviceError::WrongDevice(Box::new(WrongDevice {
res: self.error_ident(),
res_device: self.device().error_ident(),
target: Some(other.error_ident()),
target_device: other.device().error_ident(),
}))
})
}
fn same_device(&self, device: &Arc<Device<A>>) -> Result<(), DeviceError> {
Arc::ptr_eq(self.device(), device)
.then_some(())
.ok_or_else(|| {
DeviceError::WrongDevice(Box::new(WrongDevice {
res: self.error_ident(),
res_device: self.device().error_ident(),
target: None,
target_device: device.error_ident(),
}))
})
}
}
pub(crate) type ResourceType = &'static str;
pub(crate) trait Resource: 'static + Sized + WasmNotSendSync {
@ -169,6 +211,12 @@ pub(crate) trait Resource: 'static + Sized + WasmNotSendSync {
fn is_equal(&self, other: &Self) -> bool {
self.as_info().id().unzip() == other.as_info().id().unzip()
}
fn error_ident(&self) -> ResourceErrorIdent {
ResourceErrorIdent {
r#type: Self::TYPE,
label: self.label().to_owned(),
}
}
}
/// The status code provided to the buffer mapping callback.
@ -627,6 +675,12 @@ impl<A: HalApi> Resource for Buffer<A> {
}
}
impl<A: HalApi> ParentDevice<A> for Buffer<A> {
fn device(&self) -> &Arc<Device<A>> {
&self.device
}
}
/// A buffer that has been marked as destroyed and is staged for actual deletion soon.
#[derive(Debug)]
pub struct DestroyedBuffer<A: HalApi> {
@ -731,6 +785,12 @@ impl<A: HalApi> Resource for StagingBuffer<A> {
}
}
impl<A: HalApi> ParentDevice<A> for StagingBuffer<A> {
fn device(&self) -> &Arc<Device<A>> {
&self.device
}
}
pub type TextureDescriptor<'a> = wgt::TextureDescriptor<Label<'a>, Vec<wgt::TextureFormat>>;
#[derive(Debug)]
@ -1245,6 +1305,12 @@ impl<A: HalApi> Resource for Texture<A> {
}
}
impl<A: HalApi> ParentDevice<A> for Texture<A> {
fn device(&self) -> &Arc<Device<A>> {
&self.device
}
}
impl<A: HalApi> Borrow<TextureSelector> for Texture<A> {
fn borrow(&self) -> &TextureSelector {
&self.full_range
@ -1410,6 +1476,12 @@ impl<A: HalApi> Resource for TextureView<A> {
}
}
impl<A: HalApi> ParentDevice<A> for TextureView<A> {
fn device(&self) -> &Arc<Device<A>> {
&self.device
}
}
/// Describes a [`Sampler`]
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
@ -1531,6 +1603,12 @@ impl<A: HalApi> Resource for Sampler<A> {
}
}
impl<A: HalApi> ParentDevice<A> for Sampler<A> {
fn device(&self) -> &Arc<Device<A>> {
&self.device
}
}
#[derive(Clone, Debug, Error)]
#[non_exhaustive]
pub enum CreateQuerySetError {
@ -1571,6 +1649,12 @@ impl<A: HalApi> Drop for QuerySet<A> {
}
}
impl<A: HalApi> ParentDevice<A> for QuerySet<A> {
fn device(&self) -> &Arc<Device<A>> {
&self.device
}
}
impl<A: HalApi> Resource for QuerySet<A> {
const TYPE: ResourceType = "QuerySet";