summaryrefslogtreecommitdiffstats
path: root/third_party/rust/wgpu-core/src/device
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/wgpu-core/src/device')
-rw-r--r--third_party/rust/wgpu-core/src/device/global.rs245
-rw-r--r--third_party/rust/wgpu-core/src/device/life.rs129
-rw-r--r--third_party/rust/wgpu-core/src/device/queue.rs125
-rw-r--r--third_party/rust/wgpu-core/src/device/resource.rs204
4 files changed, 438 insertions, 265 deletions
diff --git a/third_party/rust/wgpu-core/src/device/global.rs b/third_party/rust/wgpu-core/src/device/global.rs
index 64fd6d4de7..539b92e0f3 100644
--- a/third_party/rust/wgpu-core/src/device/global.rs
+++ b/third_party/rust/wgpu-core/src/device/global.rs
@@ -26,9 +26,7 @@ use wgt::{BufferAddress, TextureFormat};
use std::{
borrow::Cow,
- iter,
- ops::Range,
- ptr,
+ iter, ptr,
sync::{atomic::Ordering, Arc},
};
@@ -219,7 +217,7 @@ impl Global {
mapped_at_creation: false,
};
let stage = match device.create_buffer(&stage_desc, true) {
- Ok(stage) => stage,
+ Ok(stage) => Arc::new(stage),
Err(e) => {
to_destroy.push(buffer);
break e;
@@ -232,14 +230,10 @@ impl Global {
Ok(mapping) => mapping,
Err(e) => {
to_destroy.push(buffer);
- to_destroy.push(stage);
break CreateBufferError::Device(e.into());
}
};
- let stage_fid = hub.buffers.request();
- let stage = stage_fid.init(stage);
-
assert_eq!(buffer.size % wgt::COPY_BUFFER_ALIGNMENT, 0);
// Zero initialize memory and then mark both staging and buffer as initialized
// (it's guaranteed that this is the case by the time the buffer is usable)
@@ -262,7 +256,7 @@ impl Global {
.trackers
.lock()
.buffers
- .insert_single(id, resource, buffer_use);
+ .insert_single(resource, buffer_use);
return (id, None);
};
@@ -383,7 +377,7 @@ impl Global {
.buffers
.get(buffer_id)
.map_err(|_| BufferAccessError::Invalid)?;
- check_buffer_usage(buffer.usage, wgt::BufferUsages::MAP_WRITE)?;
+ check_buffer_usage(buffer_id, buffer.usage, wgt::BufferUsages::MAP_WRITE)?;
//assert!(buffer isn't used by the GPU);
#[cfg(feature = "trace")]
@@ -446,7 +440,7 @@ impl Global {
.buffers
.get(buffer_id)
.map_err(|_| BufferAccessError::Invalid)?;
- check_buffer_usage(buffer.usage, wgt::BufferUsages::MAP_READ)?;
+ check_buffer_usage(buffer_id, buffer.usage, wgt::BufferUsages::MAP_READ)?;
//assert!(buffer isn't used by the GPU);
let raw_buf = buffer
@@ -529,7 +523,7 @@ impl Global {
.lock_life()
.suspected_resources
.buffers
- .insert(buffer_id, buffer);
+ .insert(buffer.info.tracker_index(), buffer);
}
if wait {
@@ -573,11 +567,11 @@ impl Global {
let (id, resource) = fid.assign(texture);
api_log!("Device::create_texture({desc:?}) -> {id:?}");
- device.trackers.lock().textures.insert_single(
- id,
- resource,
- hal::TextureUses::UNINITIALIZED,
- );
+ device
+ .trackers
+ .lock()
+ .textures
+ .insert_single(resource, hal::TextureUses::UNINITIALIZED);
return (id, None);
};
@@ -647,11 +641,11 @@ impl Global {
let (id, resource) = fid.assign(texture);
api_log!("Device::create_texture({desc:?}) -> {id:?}");
- device.trackers.lock().textures.insert_single(
- id,
- resource,
- hal::TextureUses::UNINITIALIZED,
- );
+ device
+ .trackers
+ .lock()
+ .textures
+ .insert_single(resource, hal::TextureUses::UNINITIALIZED);
return (id, None);
};
@@ -704,7 +698,7 @@ impl Global {
.trackers
.lock()
.buffers
- .insert_single(id, buffer, hal::BufferUses::empty());
+ .insert_single(buffer, hal::BufferUses::empty());
return (id, None);
};
@@ -764,7 +758,7 @@ impl Global {
.lock_life()
.suspected_resources
.textures
- .insert(texture_id, texture.clone());
+ .insert(texture.info.tracker_index(), texture.clone());
}
}
@@ -824,7 +818,7 @@ impl Global {
}
api_log!("Texture::create_view({texture_id:?}) -> {id:?}");
- device.trackers.lock().views.insert_single(id, resource);
+ device.trackers.lock().views.insert_single(resource);
return (id, None);
};
@@ -854,7 +848,7 @@ impl Global {
.lock_life()
.suspected_resources
.texture_views
- .insert(texture_view_id, view.clone());
+ .insert(view.info.tracker_index(), view.clone());
if wait {
match view.device.wait_for_submit(last_submit_index) {
@@ -900,7 +894,7 @@ impl Global {
let (id, resource) = fid.assign(sampler);
api_log!("Device::create_sampler -> {id:?}");
- device.trackers.lock().samplers.insert_single(id, resource);
+ device.trackers.lock().samplers.insert_single(resource);
return (id, None);
};
@@ -925,7 +919,7 @@ impl Global {
.lock_life()
.suspected_resources
.samplers
- .insert(sampler_id, sampler.clone());
+ .insert(sampler.info.tracker_index(), sampler.clone());
}
}
@@ -1024,7 +1018,7 @@ impl Global {
.lock_life()
.suspected_resources
.bind_group_layouts
- .insert(bind_group_layout_id, layout.clone());
+ .insert(layout.info.tracker_index(), layout.clone());
}
}
@@ -1085,7 +1079,7 @@ impl Global {
.lock_life()
.suspected_resources
.pipeline_layouts
- .insert(pipeline_layout_id, layout.clone());
+ .insert(layout.info.tracker_index(), layout.clone());
}
}
@@ -1140,11 +1134,7 @@ impl Global {
api_log!("Device::create_bind_group -> {id:?}");
- device
- .trackers
- .lock()
- .bind_groups
- .insert_single(id, resource);
+ device.trackers.lock().bind_groups.insert_single(resource);
return (id, None);
};
@@ -1168,7 +1158,7 @@ impl Global {
.lock_life()
.suspected_resources
.bind_groups
- .insert(bind_group_id, bind_group.clone());
+ .insert(bind_group.info.tracker_index(), bind_group.clone());
}
}
@@ -1332,9 +1322,8 @@ impl Global {
if !device.is_valid() {
break DeviceError::Lost;
}
- let queue = match hub.queues.get(device.queue_id.read().unwrap()) {
- Ok(queue) => queue,
- Err(_) => break DeviceError::InvalidQueueId,
+ let Some(queue) = device.get_queue() else {
+ break DeviceError::InvalidQueueId;
};
let encoder = match device
.command_allocator
@@ -1379,6 +1368,7 @@ impl Global {
.command_buffers
.unregister(command_encoder_id.transmute())
{
+ cmd_buf.data.lock().as_mut().unwrap().encoder.discard();
cmd_buf
.device
.untrack(&cmd_buf.data.lock().as_ref().unwrap().trackers);
@@ -1450,7 +1440,7 @@ impl Global {
let (id, resource) = fid.assign(render_bundle);
api_log!("RenderBundleEncoder::finish -> {id:?}");
- device.trackers.lock().bundles.insert_single(id, resource);
+ device.trackers.lock().bundles.insert_single(resource);
return (id, None);
};
@@ -1474,7 +1464,7 @@ impl Global {
.lock_life()
.suspected_resources
.render_bundles
- .insert(render_bundle_id, bundle.clone());
+ .insert(bundle.info.tracker_index(), bundle.clone());
}
}
@@ -1513,11 +1503,7 @@ impl Global {
let (id, resource) = fid.assign(query_set);
api_log!("Device::create_query_set -> {id:?}");
- device
- .trackers
- .lock()
- .query_sets
- .insert_single(id, resource);
+ device.trackers.lock().query_sets.insert_single(resource);
return (id, None);
};
@@ -1544,7 +1530,7 @@ impl Global {
.lock_life()
.suspected_resources
.query_sets
- .insert(query_set_id, query_set.clone());
+ .insert(query_set.info.tracker_index(), query_set.clone());
}
}
@@ -1600,7 +1586,7 @@ impl Global {
.trackers
.lock()
.render_pipelines
- .insert_single(id, resource);
+ .insert_single(resource);
return (id, None);
};
@@ -1672,18 +1658,17 @@ impl Global {
let hub = A::hub(self);
if let Some(pipeline) = hub.render_pipelines.unregister(render_pipeline_id) {
- let layout_id = pipeline.layout.as_info().id();
let device = &pipeline.device;
let mut life_lock = device.lock_life();
life_lock
.suspected_resources
.render_pipelines
- .insert(render_pipeline_id, pipeline.clone());
+ .insert(pipeline.info.tracker_index(), pipeline.clone());
- life_lock
- .suspected_resources
- .pipeline_layouts
- .insert(layout_id, pipeline.layout.clone());
+ life_lock.suspected_resources.pipeline_layouts.insert(
+ pipeline.layout.info.tracker_index(),
+ pipeline.layout.clone(),
+ );
}
}
@@ -1734,7 +1719,7 @@ impl Global {
.trackers
.lock()
.compute_pipelines
- .insert_single(id, resource);
+ .insert_single(resource);
return (id, None);
};
@@ -1804,17 +1789,16 @@ impl Global {
let hub = A::hub(self);
if let Some(pipeline) = hub.compute_pipelines.unregister(compute_pipeline_id) {
- let layout_id = pipeline.layout.as_info().id();
let device = &pipeline.device;
let mut life_lock = device.lock_life();
life_lock
.suspected_resources
.compute_pipelines
- .insert(compute_pipeline_id, pipeline.clone());
- life_lock
- .suspected_resources
- .pipeline_layouts
- .insert(layout_id, pipeline.layout.clone());
+ .insert(pipeline.info.tracker_index(), pipeline.clone());
+ life_lock.suspected_resources.pipeline_layouts.insert(
+ pipeline.layout.info.tracker_index(),
+ pipeline.layout.clone(),
+ );
}
}
@@ -2113,28 +2097,41 @@ impl Global {
.get(device_id)
.map_err(|_| DeviceError::Invalid)?;
- let (closures, queue_empty) = {
- if let wgt::Maintain::WaitForSubmissionIndex(submission_index) = maintain {
- if submission_index.queue_id != device_id.transmute() {
- return Err(WaitIdleError::WrongSubmissionIndex(
- submission_index.queue_id,
- device_id,
- ));
- }
+ if let wgt::Maintain::WaitForSubmissionIndex(submission_index) = maintain {
+ if submission_index.queue_id != device_id.transmute() {
+ return Err(WaitIdleError::WrongSubmissionIndex(
+ submission_index.queue_id,
+ device_id,
+ ));
}
+ }
- let fence = device.fence.read();
- let fence = fence.as_ref().unwrap();
- device.maintain(fence, maintain)?
- };
+ let DevicePoll {
+ closures,
+ queue_empty,
+ } = Self::poll_single_device(&device, maintain)?;
+
+ closures.fire();
+
+ Ok(queue_empty)
+ }
+
+ fn poll_single_device<A: HalApi>(
+ device: &crate::device::Device<A>,
+ maintain: wgt::Maintain<queue::WrappedSubmissionIndex>,
+ ) -> Result<DevicePoll, WaitIdleError> {
+ let fence = device.fence.read();
+ let fence = fence.as_ref().unwrap();
+ let (closures, queue_empty) = device.maintain(fence, maintain)?;
// Some deferred destroys are scheduled in maintain so run this right after
// to avoid holding on to them until the next device poll.
device.deferred_resource_destruction();
- closures.fire();
-
- Ok(queue_empty)
+ Ok(DevicePoll {
+ closures,
+ queue_empty,
+ })
}
/// Poll all devices belonging to the backend `A`.
@@ -2143,7 +2140,7 @@ impl Global {
///
/// Return `all_queue_empty` indicating whether there are more queue
/// submissions still in flight.
- fn poll_device<A: HalApi>(
+ fn poll_all_devices_of_api<A: HalApi>(
&self,
force_wait: bool,
closures: &mut UserClosures,
@@ -2161,10 +2158,13 @@ impl Global {
} else {
wgt::Maintain::Poll
};
- let fence = device.fence.read();
- let fence = fence.as_ref().unwrap();
- let (cbs, queue_empty) = device.maintain(fence, maintain)?;
- all_queue_empty = all_queue_empty && queue_empty;
+
+ let DevicePoll {
+ closures: cbs,
+ queue_empty,
+ } = Self::poll_single_device(device, maintain)?;
+
+ all_queue_empty &= queue_empty;
closures.extend(cbs);
}
@@ -2186,23 +2186,23 @@ impl Global {
#[cfg(vulkan)]
{
- all_queue_empty =
- self.poll_device::<hal::api::Vulkan>(force_wait, &mut closures)? && all_queue_empty;
+ all_queue_empty &=
+ self.poll_all_devices_of_api::<hal::api::Vulkan>(force_wait, &mut closures)?;
}
#[cfg(metal)]
{
- all_queue_empty =
- self.poll_device::<hal::api::Metal>(force_wait, &mut closures)? && all_queue_empty;
+ all_queue_empty &=
+ self.poll_all_devices_of_api::<hal::api::Metal>(force_wait, &mut closures)?;
}
#[cfg(dx12)]
{
- all_queue_empty =
- self.poll_device::<hal::api::Dx12>(force_wait, &mut closures)? && all_queue_empty;
+ all_queue_empty &=
+ self.poll_all_devices_of_api::<hal::api::Dx12>(force_wait, &mut closures)?;
}
#[cfg(gles)]
{
- all_queue_empty =
- self.poll_device::<hal::api::Gles>(force_wait, &mut closures)? && all_queue_empty;
+ all_queue_empty &=
+ self.poll_all_devices_of_api::<hal::api::Gles>(force_wait, &mut closures)?;
}
closures.fire();
@@ -2336,15 +2336,18 @@ impl Global {
pub fn buffer_map_async<A: HalApi>(
&self,
buffer_id: id::BufferId,
- range: Range<BufferAddress>,
+ offset: BufferAddress,
+ size: Option<BufferAddress>,
op: BufferMapOperation,
) -> BufferAccessResult {
- api_log!("Buffer::map_async {buffer_id:?} range {range:?} op: {op:?}");
+ api_log!("Buffer::map_async {buffer_id:?} offset {offset:?} size {size:?} op: {op:?}");
// User callbacks must not be called while holding buffer_map_async_inner's locks, so we
// defer the error callback if it needs to be called immediately (typically when running
// into errors).
- if let Err((mut operation, err)) = self.buffer_map_async_inner::<A>(buffer_id, range, op) {
+ if let Err((mut operation, err)) =
+ self.buffer_map_async_inner::<A>(buffer_id, offset, size, op)
+ {
if let Some(callback) = operation.callback.take() {
callback.call(Err(err.clone()));
}
@@ -2360,7 +2363,8 @@ impl Global {
fn buffer_map_async_inner<A: HalApi>(
&self,
buffer_id: id::BufferId,
- range: Range<BufferAddress>,
+ offset: BufferAddress,
+ size: Option<BufferAddress>,
op: BufferMapOperation,
) -> Result<(), (BufferMapOperation, BufferAccessError)> {
profiling::scope!("Buffer::map_async");
@@ -2372,29 +2376,50 @@ impl Global {
HostMap::Write => (wgt::BufferUsages::MAP_WRITE, hal::BufferUses::MAP_WRITE),
};
- if range.start % wgt::MAP_ALIGNMENT != 0 || range.end % wgt::COPY_BUFFER_ALIGNMENT != 0 {
- return Err((op, BufferAccessError::UnalignedRange));
- }
-
let buffer = {
- let buffer = hub
- .buffers
- .get(buffer_id)
- .map_err(|_| BufferAccessError::Invalid);
+ let buffer = hub.buffers.get(buffer_id);
let buffer = match buffer {
Ok(b) => b,
- Err(e) => {
- return Err((op, e));
+ Err(_) => {
+ return Err((op, BufferAccessError::Invalid));
}
};
+ {
+ let snatch_guard = buffer.device.snatchable_lock.read();
+ if buffer.is_destroyed(&snatch_guard) {
+ return Err((op, BufferAccessError::Destroyed));
+ }
+ }
+
+ let range_size = if let Some(size) = size {
+ size
+ } else if offset > buffer.size {
+ 0
+ } else {
+ buffer.size - offset
+ };
+
+ if offset % wgt::MAP_ALIGNMENT != 0 {
+ return Err((op, BufferAccessError::UnalignedOffset { offset }));
+ }
+ if range_size % wgt::COPY_BUFFER_ALIGNMENT != 0 {
+ return Err((op, BufferAccessError::UnalignedRangeSize { range_size }));
+ }
+
+ let range = offset..(offset + range_size);
+
+ if range.start % wgt::MAP_ALIGNMENT != 0 || range.end % wgt::COPY_BUFFER_ALIGNMENT != 0
+ {
+ return Err((op, BufferAccessError::UnalignedRange));
+ }
let device = &buffer.device;
if !device.is_valid() {
return Err((op, DeviceError::Lost.into()));
}
- if let Err(e) = check_buffer_usage(buffer.usage, pub_usage) {
+ if let Err(e) = check_buffer_usage(buffer.info.id(), buffer.usage, pub_usage) {
return Err((op, e.into()));
}
@@ -2417,11 +2442,6 @@ impl Global {
));
}
- let snatch_guard = device.snatchable_lock.read();
- if buffer.is_destroyed(&snatch_guard) {
- return Err((op, BufferAccessError::Destroyed));
- }
-
{
let map_state = &mut *buffer.map_state.lock();
*map_state = match *map_state {
@@ -2442,6 +2462,8 @@ impl Global {
};
}
+ let snatch_guard = buffer.device.snatchable_lock.read();
+
{
let mut trackers = buffer.device.as_ref().trackers.lock();
trackers.buffers.set_single(&buffer, internal_use);
@@ -2557,3 +2579,8 @@ impl Global {
buffer.unmap()
}
}
+
+struct DevicePoll {
+ closures: UserClosures,
+ queue_empty: bool,
+}
diff --git a/third_party/rust/wgpu-core/src/device/life.rs b/third_party/rust/wgpu-core/src/device/life.rs
index 86c5d027c7..7b06a4a30b 100644
--- a/third_party/rust/wgpu-core/src/device/life.rs
+++ b/third_party/rust/wgpu-core/src/device/life.rs
@@ -6,17 +6,13 @@ use crate::{
DeviceError, DeviceLostClosure,
},
hal_api::HalApi,
- id::{
- self, BindGroupId, BindGroupLayoutId, BufferId, ComputePipelineId, Id, PipelineLayoutId,
- QuerySetId, RenderBundleId, RenderPipelineId, SamplerId, StagingBufferId, TextureId,
- TextureViewId,
- },
+ id,
pipeline::{ComputePipeline, RenderPipeline},
resource::{
self, Buffer, DestroyedBuffer, DestroyedTexture, QuerySet, Resource, Sampler,
StagingBuffer, Texture, TextureView,
},
- track::{ResourceTracker, Tracker},
+ track::{ResourceTracker, Tracker, TrackerIndex},
FastHashMap, SubmissionIndex,
};
use smallvec::SmallVec;
@@ -28,20 +24,20 @@ use thiserror::Error;
/// A struct that keeps lists of resources that are no longer needed by the user.
#[derive(Default)]
pub(crate) struct ResourceMaps<A: HalApi> {
- pub buffers: FastHashMap<BufferId, Arc<Buffer<A>>>,
- pub staging_buffers: FastHashMap<StagingBufferId, Arc<StagingBuffer<A>>>,
- pub textures: FastHashMap<TextureId, Arc<Texture<A>>>,
- pub texture_views: FastHashMap<TextureViewId, Arc<TextureView<A>>>,
- pub samplers: FastHashMap<SamplerId, Arc<Sampler<A>>>,
- pub bind_groups: FastHashMap<BindGroupId, Arc<BindGroup<A>>>,
- pub bind_group_layouts: FastHashMap<BindGroupLayoutId, Arc<BindGroupLayout<A>>>,
- pub render_pipelines: FastHashMap<RenderPipelineId, Arc<RenderPipeline<A>>>,
- pub compute_pipelines: FastHashMap<ComputePipelineId, Arc<ComputePipeline<A>>>,
- pub pipeline_layouts: FastHashMap<PipelineLayoutId, Arc<PipelineLayout<A>>>,
- pub render_bundles: FastHashMap<RenderBundleId, Arc<RenderBundle<A>>>,
- pub query_sets: FastHashMap<QuerySetId, Arc<QuerySet<A>>>,
- pub destroyed_buffers: FastHashMap<BufferId, Arc<DestroyedBuffer<A>>>,
- pub destroyed_textures: FastHashMap<TextureId, Arc<DestroyedTexture<A>>>,
+ pub buffers: FastHashMap<TrackerIndex, Arc<Buffer<A>>>,
+ pub staging_buffers: FastHashMap<TrackerIndex, Arc<StagingBuffer<A>>>,
+ pub textures: FastHashMap<TrackerIndex, Arc<Texture<A>>>,
+ pub texture_views: FastHashMap<TrackerIndex, Arc<TextureView<A>>>,
+ pub samplers: FastHashMap<TrackerIndex, Arc<Sampler<A>>>,
+ pub bind_groups: FastHashMap<TrackerIndex, Arc<BindGroup<A>>>,
+ pub bind_group_layouts: FastHashMap<TrackerIndex, Arc<BindGroupLayout<A>>>,
+ pub render_pipelines: FastHashMap<TrackerIndex, Arc<RenderPipeline<A>>>,
+ pub compute_pipelines: FastHashMap<TrackerIndex, Arc<ComputePipeline<A>>>,
+ pub pipeline_layouts: FastHashMap<TrackerIndex, Arc<PipelineLayout<A>>>,
+ pub render_bundles: FastHashMap<TrackerIndex, Arc<RenderBundle<A>>>,
+ pub query_sets: FastHashMap<TrackerIndex, Arc<QuerySet<A>>>,
+ pub destroyed_buffers: FastHashMap<TrackerIndex, Arc<DestroyedBuffer<A>>>,
+ pub destroyed_textures: FastHashMap<TrackerIndex, Arc<DestroyedTexture<A>>>,
}
impl<A: HalApi> ResourceMaps<A> {
@@ -276,25 +272,29 @@ impl<A: HalApi> LifetimeTracker<A> {
for res in temp_resources {
match res {
TempResource::Buffer(raw) => {
- last_resources.buffers.insert(raw.as_info().id(), raw);
+ last_resources
+ .buffers
+ .insert(raw.as_info().tracker_index(), raw);
}
TempResource::StagingBuffer(raw) => {
last_resources
.staging_buffers
- .insert(raw.as_info().id(), raw);
+ .insert(raw.as_info().tracker_index(), raw);
}
TempResource::DestroyedBuffer(destroyed) => {
last_resources
.destroyed_buffers
- .insert(destroyed.id, destroyed);
+ .insert(destroyed.tracker_index, destroyed);
}
TempResource::Texture(raw) => {
- last_resources.textures.insert(raw.as_info().id(), raw);
+ last_resources
+ .textures
+ .insert(raw.as_info().tracker_index(), raw);
}
TempResource::DestroyedTexture(destroyed) => {
last_resources
.destroyed_textures
- .insert(destroyed.id, destroyed);
+ .insert(destroyed.tracker_index, destroyed);
}
}
}
@@ -310,12 +310,14 @@ impl<A: HalApi> LifetimeTracker<A> {
pub fn post_submit(&mut self) {
for v in self.future_suspected_buffers.drain(..).take(1) {
- self.suspected_resources.buffers.insert(v.as_info().id(), v);
+ self.suspected_resources
+ .buffers
+ .insert(v.as_info().tracker_index(), v);
}
for v in self.future_suspected_textures.drain(..).take(1) {
self.suspected_resources
.textures
- .insert(v.as_info().id(), v);
+ .insert(v.as_info().tracker_index(), v);
}
}
@@ -386,19 +388,27 @@ impl<A: HalApi> LifetimeTracker<A> {
if let Some(resources) = resources {
match temp_resource {
TempResource::Buffer(raw) => {
- resources.buffers.insert(raw.as_info().id(), raw);
+ resources.buffers.insert(raw.as_info().tracker_index(), raw);
}
TempResource::StagingBuffer(raw) => {
- resources.staging_buffers.insert(raw.as_info().id(), raw);
+ resources
+ .staging_buffers
+ .insert(raw.as_info().tracker_index(), raw);
}
TempResource::DestroyedBuffer(destroyed) => {
- resources.destroyed_buffers.insert(destroyed.id, destroyed);
+ resources
+ .destroyed_buffers
+ .insert(destroyed.tracker_index, destroyed);
}
TempResource::Texture(raw) => {
- resources.textures.insert(raw.as_info().id(), raw);
+ resources
+ .textures
+ .insert(raw.as_info().tracker_index(), raw);
}
TempResource::DestroyedTexture(destroyed) => {
- resources.destroyed_textures.insert(destroyed.id, destroyed);
+ resources
+ .destroyed_textures
+ .insert(destroyed.tracker_index, destroyed);
}
}
}
@@ -420,27 +430,27 @@ impl<A: HalApi> LifetimeTracker<A> {
impl<A: HalApi> LifetimeTracker<A> {
fn triage_resources<R>(
- resources_map: &mut FastHashMap<Id<R::Marker>, Arc<R>>,
+ resources_map: &mut FastHashMap<TrackerIndex, Arc<R>>,
active: &mut [ActiveSubmission<A>],
- trackers: &mut impl ResourceTracker<R>,
- get_resource_map: impl Fn(&mut ResourceMaps<A>) -> &mut FastHashMap<Id<R::Marker>, Arc<R>>,
+ trackers: &mut impl ResourceTracker,
+ get_resource_map: impl Fn(&mut ResourceMaps<A>) -> &mut FastHashMap<TrackerIndex, Arc<R>>,
) -> Vec<Arc<R>>
where
R: Resource,
{
let mut removed_resources = Vec::new();
- resources_map.retain(|&id, resource| {
+ resources_map.retain(|&index, resource| {
let submit_index = resource.as_info().submission_index();
let non_referenced_resources = active
.iter_mut()
.find(|a| a.index == submit_index)
.map(|a| &mut a.last_resources);
- let is_removed = trackers.remove_abandoned(id);
+ let is_removed = trackers.remove_abandoned(index);
if is_removed {
removed_resources.push(resource.clone());
if let Some(resources) = non_referenced_resources {
- get_resource_map(resources).insert(id, resource.clone());
+ get_resource_map(resources).insert(index, resource.clone());
}
}
!is_removed
@@ -459,27 +469,29 @@ impl<A: HalApi> LifetimeTracker<A> {
);
removed_resources.drain(..).for_each(|bundle| {
for v in bundle.used.buffers.write().drain_resources() {
- self.suspected_resources.buffers.insert(v.as_info().id(), v);
+ self.suspected_resources
+ .buffers
+ .insert(v.as_info().tracker_index(), v);
}
for v in bundle.used.textures.write().drain_resources() {
self.suspected_resources
.textures
- .insert(v.as_info().id(), v);
+ .insert(v.as_info().tracker_index(), v);
}
for v in bundle.used.bind_groups.write().drain_resources() {
self.suspected_resources
.bind_groups
- .insert(v.as_info().id(), v);
+ .insert(v.as_info().tracker_index(), v);
}
for v in bundle.used.render_pipelines.write().drain_resources() {
self.suspected_resources
.render_pipelines
- .insert(v.as_info().id(), v);
+ .insert(v.as_info().tracker_index(), v);
}
for v in bundle.used.query_sets.write().drain_resources() {
self.suspected_resources
.query_sets
- .insert(v.as_info().id(), v);
+ .insert(v.as_info().tracker_index(), v);
}
});
self
@@ -496,27 +508,30 @@ impl<A: HalApi> LifetimeTracker<A> {
);
removed_resource.drain(..).for_each(|bind_group| {
for v in bind_group.used.buffers.drain_resources() {
- self.suspected_resources.buffers.insert(v.as_info().id(), v);
+ self.suspected_resources
+ .buffers
+ .insert(v.as_info().tracker_index(), v);
}
for v in bind_group.used.textures.drain_resources() {
self.suspected_resources
.textures
- .insert(v.as_info().id(), v);
+ .insert(v.as_info().tracker_index(), v);
}
for v in bind_group.used.views.drain_resources() {
self.suspected_resources
.texture_views
- .insert(v.as_info().id(), v);
+ .insert(v.as_info().tracker_index(), v);
}
for v in bind_group.used.samplers.drain_resources() {
self.suspected_resources
.samplers
- .insert(v.as_info().id(), v);
+ .insert(v.as_info().tracker_index(), v);
}
- self.suspected_resources
- .bind_group_layouts
- .insert(bind_group.layout.as_info().id(), bind_group.layout.clone());
+ self.suspected_resources.bind_group_layouts.insert(
+ bind_group.layout.as_info().tracker_index(),
+ bind_group.layout.clone(),
+ );
});
self
}
@@ -605,7 +620,7 @@ impl<A: HalApi> LifetimeTracker<A> {
);
removed_resources.drain(..).for_each(|compute_pipeline| {
self.suspected_resources.pipeline_layouts.insert(
- compute_pipeline.layout.as_info().id(),
+ compute_pipeline.layout.as_info().tracker_index(),
compute_pipeline.layout.clone(),
);
});
@@ -623,7 +638,7 @@ impl<A: HalApi> LifetimeTracker<A> {
);
removed_resources.drain(..).for_each(|render_pipeline| {
self.suspected_resources.pipeline_layouts.insert(
- render_pipeline.layout.as_info().id(),
+ render_pipeline.layout.as_info().tracker_index(),
render_pipeline.layout.clone(),
);
});
@@ -642,7 +657,7 @@ impl<A: HalApi> LifetimeTracker<A> {
for bgl in &pipeline_layout.bind_group_layouts {
self.suspected_resources
.bind_group_layouts
- .insert(bgl.as_info().id(), bgl.clone());
+ .insert(bgl.as_info().tracker_index(), bgl.clone());
}
});
self
@@ -773,14 +788,14 @@ impl<A: HalApi> LifetimeTracker<A> {
Vec::with_capacity(self.ready_to_map.len());
for buffer in self.ready_to_map.drain(..) {
- let buffer_id = buffer.info.id();
+ let tracker_index = buffer.info.tracker_index();
let is_removed = {
let mut trackers = trackers.lock();
- trackers.buffers.remove_abandoned(buffer_id)
+ trackers.buffers.remove_abandoned(tracker_index)
};
if is_removed {
*buffer.map_state.lock() = resource::BufferMapState::Idle;
- log::trace!("Buffer ready to map {:?} is not tracked anymore", buffer_id);
+ log::trace!("Buffer ready to map {tracker_index:?} is not tracked anymore");
} else {
let mapping = match std::mem::replace(
&mut *buffer.map_state.lock(),
@@ -798,7 +813,7 @@ impl<A: HalApi> LifetimeTracker<A> {
_ => panic!("No pending mapping."),
};
let status = if mapping.range.start != mapping.range.end {
- log::debug!("Buffer {:?} map state -> Active", buffer_id);
+ log::debug!("Buffer {tracker_index:?} map state -> Active");
let host = mapping.op.host;
let size = mapping.range.end - mapping.range.start;
match super::map_buffer(raw, &buffer, mapping.range.start, size, host) {
diff --git a/third_party/rust/wgpu-core/src/device/queue.rs b/third_party/rust/wgpu-core/src/device/queue.rs
index 08c5b767b6..6ebb9eb09b 100644
--- a/third_party/rust/wgpu-core/src/device/queue.rs
+++ b/third_party/rust/wgpu-core/src/device/queue.rs
@@ -12,7 +12,7 @@ use crate::{
global::Global,
hal_api::HalApi,
hal_label,
- id::{self, QueueId},
+ id::{self, DeviceId, QueueId},
init_tracker::{has_copy_partial_init_tracker_coverage, TextureInitRange},
resource::{
Buffer, BufferAccessError, BufferMapState, DestroyedBuffer, DestroyedTexture, Resource,
@@ -188,10 +188,17 @@ impl<A: HalApi> EncoderInFlight<A> {
#[derive(Debug)]
pub(crate) struct PendingWrites<A: HalApi> {
pub command_encoder: A::CommandEncoder,
- pub is_active: bool,
+
+ /// True if `command_encoder` is in the "recording" state, as
+ /// described in the docs for the [`wgpu_hal::CommandEncoder`]
+ /// trait.
+ pub is_recording: bool,
+
pub temp_resources: Vec<TempResource<A>>,
pub dst_buffers: FastHashMap<id::BufferId, Arc<Buffer<A>>>,
pub dst_textures: FastHashMap<id::TextureId, Arc<Texture<A>>>,
+
+ /// All command buffers allocated from `command_encoder`.
pub executing_command_buffers: Vec<A::CommandBuffer>,
}
@@ -199,7 +206,7 @@ impl<A: HalApi> PendingWrites<A> {
pub fn new(command_encoder: A::CommandEncoder) -> Self {
Self {
command_encoder,
- is_active: false,
+ is_recording: false,
temp_resources: Vec::new(),
dst_buffers: FastHashMap::default(),
dst_textures: FastHashMap::default(),
@@ -209,7 +216,7 @@ impl<A: HalApi> PendingWrites<A> {
pub fn dispose(mut self, device: &A::Device) {
unsafe {
- if self.is_active {
+ if self.is_recording {
self.command_encoder.discard_encoding();
}
self.command_encoder
@@ -232,9 +239,9 @@ impl<A: HalApi> PendingWrites<A> {
fn pre_submit(&mut self) -> Result<Option<&A::CommandBuffer>, DeviceError> {
self.dst_buffers.clear();
self.dst_textures.clear();
- if self.is_active {
+ if self.is_recording {
let cmd_buf = unsafe { self.command_encoder.end_encoding()? };
- self.is_active = false;
+ self.is_recording = false;
self.executing_command_buffers.push(cmd_buf);
return Ok(self.executing_command_buffers.last());
@@ -262,23 +269,23 @@ impl<A: HalApi> PendingWrites<A> {
}
pub fn activate(&mut self) -> &mut A::CommandEncoder {
- if !self.is_active {
+ if !self.is_recording {
unsafe {
self.command_encoder
.begin_encoding(Some("(wgpu internal) PendingWrites"))
.unwrap();
}
- self.is_active = true;
+ self.is_recording = true;
}
&mut self.command_encoder
}
pub fn deactivate(&mut self) {
- if self.is_active {
+ if self.is_recording {
unsafe {
self.command_encoder.discard_encoding();
}
- self.is_active = false;
+ self.is_recording = false;
}
}
}
@@ -303,7 +310,10 @@ fn prepare_staging_buffer<A: HalApi>(
raw: Mutex::new(Some(buffer)),
device: device.clone(),
size,
- info: ResourceInfo::new("<StagingBuffer>"),
+ info: ResourceInfo::new(
+ "<StagingBuffer>",
+ Some(device.tracker_indices.staging_buffers.clone()),
+ ),
is_coherent: mapping.is_coherent,
};
@@ -332,6 +342,15 @@ pub struct InvalidQueue;
#[derive(Clone, Debug, Error)]
#[non_exhaustive]
pub enum QueueWriteError {
+ #[error(
+ "Device of queue ({:?}) does not match device of write recipient ({:?})",
+ queue_device_id,
+ target_device_id
+ )]
+ DeviceMismatch {
+ queue_device_id: DeviceId,
+ target_device_id: DeviceId,
+ },
#[error(transparent)]
Queue(#[from] DeviceError),
#[error(transparent)]
@@ -376,6 +395,14 @@ impl Global {
let hub = A::hub(self);
+ let buffer_device_id = hub
+ .buffers
+ .get(buffer_id)
+ .map_err(|_| TransferError::InvalidBuffer(buffer_id))?
+ .device
+ .as_info()
+ .id();
+
let queue = hub
.queues
.get(queue_id)
@@ -383,6 +410,16 @@ impl Global {
let device = queue.device.as_ref().unwrap();
+ {
+ let queue_device_id = device.as_info().id();
+ if buffer_device_id != queue_device_id {
+ return Err(QueueWriteError::DeviceMismatch {
+ queue_device_id,
+ target_device_id: buffer_device_id,
+ });
+ }
+ }
+
let data_size = data.len() as wgt::BufferAddress;
#[cfg(feature = "trace")]
@@ -1143,7 +1180,7 @@ impl Global {
for &cmb_id in command_buffer_ids {
// we reset the used surface textures every time we use
// it, so make sure to set_size on it.
- used_surface_textures.set_size(hub.textures.read().len());
+ used_surface_textures.set_size(device.tracker_indices.textures.size());
#[allow(unused_mut)]
let mut cmdbuf = match command_buffer_guard.replace_with_error(cmb_id) {
@@ -1188,11 +1225,13 @@ impl Global {
// update submission IDs
for buffer in cmd_buf_trackers.buffers.used_resources() {
- let id = buffer.info.id();
+ let tracker_index = buffer.info.tracker_index();
let raw_buf = match buffer.raw.get(&snatch_guard) {
Some(raw) => raw,
None => {
- return Err(QueueSubmitError::DestroyedBuffer(id));
+ return Err(QueueSubmitError::DestroyedBuffer(
+ buffer.info.id(),
+ ));
}
};
buffer.info.use_at(submit_index);
@@ -1207,28 +1246,28 @@ impl Global {
.as_mut()
.unwrap()
.buffers
- .insert(id, buffer.clone());
+ .insert(tracker_index, buffer.clone());
} else {
match *buffer.map_state.lock() {
BufferMapState::Idle => (),
- _ => return Err(QueueSubmitError::BufferStillMapped(id)),
+ _ => {
+ return Err(QueueSubmitError::BufferStillMapped(
+ buffer.info.id(),
+ ))
+ }
}
}
}
for texture in cmd_buf_trackers.textures.used_resources() {
- let id = texture.info.id();
+ let tracker_index = texture.info.tracker_index();
let should_extend = match texture.inner.get(&snatch_guard) {
None => {
- return Err(QueueSubmitError::DestroyedTexture(id));
+ return Err(QueueSubmitError::DestroyedTexture(
+ texture.info.id(),
+ ));
}
Some(TextureInner::Native { .. }) => false,
- Some(TextureInner::Surface {
- ref has_work,
- ref raw,
- ..
- }) => {
- has_work.store(true, Ordering::Relaxed);
-
+ Some(TextureInner::Surface { ref raw, .. }) => {
if raw.is_some() {
submit_surface_textures_owned.push(texture.clone());
}
@@ -1242,7 +1281,7 @@ impl Global {
.as_mut()
.unwrap()
.textures
- .insert(id, texture.clone());
+ .insert(tracker_index, texture.clone());
}
if should_extend {
unsafe {
@@ -1255,11 +1294,10 @@ impl Global {
for texture_view in cmd_buf_trackers.views.used_resources() {
texture_view.info.use_at(submit_index);
if texture_view.is_unique() {
- temp_suspected
- .as_mut()
- .unwrap()
- .texture_views
- .insert(texture_view.as_info().id(), texture_view.clone());
+ temp_suspected.as_mut().unwrap().texture_views.insert(
+ texture_view.as_info().tracker_index(),
+ texture_view.clone(),
+ );
}
}
{
@@ -1279,7 +1317,7 @@ impl Global {
.as_mut()
.unwrap()
.bind_groups
- .insert(bg.as_info().id(), bg.clone());
+ .insert(bg.as_info().tracker_index(), bg.clone());
}
}
}
@@ -1290,7 +1328,7 @@ impl Global {
compute_pipeline.info.use_at(submit_index);
if compute_pipeline.is_unique() {
temp_suspected.as_mut().unwrap().compute_pipelines.insert(
- compute_pipeline.as_info().id(),
+ compute_pipeline.as_info().tracker_index(),
compute_pipeline.clone(),
);
}
@@ -1301,7 +1339,7 @@ impl Global {
render_pipeline.info.use_at(submit_index);
if render_pipeline.is_unique() {
temp_suspected.as_mut().unwrap().render_pipelines.insert(
- render_pipeline.as_info().id(),
+ render_pipeline.as_info().tracker_index(),
render_pipeline.clone(),
);
}
@@ -1309,11 +1347,10 @@ impl Global {
for query_set in cmd_buf_trackers.query_sets.used_resources() {
query_set.info.use_at(submit_index);
if query_set.is_unique() {
- temp_suspected
- .as_mut()
- .unwrap()
- .query_sets
- .insert(query_set.as_info().id(), query_set.clone());
+ temp_suspected.as_mut().unwrap().query_sets.insert(
+ query_set.as_info().tracker_index(),
+ query_set.clone(),
+ );
}
}
for bundle in cmd_buf_trackers.bundles.used_resources() {
@@ -1334,7 +1371,7 @@ impl Global {
.as_mut()
.unwrap()
.render_bundles
- .insert(bundle.as_info().id(), bundle.clone());
+ .insert(bundle.as_info().tracker_index(), bundle.clone());
}
}
}
@@ -1423,13 +1460,7 @@ impl Global {
return Err(QueueSubmitError::DestroyedTexture(id));
}
Some(TextureInner::Native { .. }) => {}
- Some(TextureInner::Surface {
- ref has_work,
- ref raw,
- ..
- }) => {
- has_work.store(true, Ordering::Relaxed);
-
+ Some(TextureInner::Surface { ref raw, .. }) => {
if raw.is_some() {
submit_surface_textures_owned.push(texture.clone());
}
diff --git a/third_party/rust/wgpu-core/src/device/resource.rs b/third_party/rust/wgpu-core/src/device/resource.rs
index b2c85a056a..28ba0eafb1 100644
--- a/third_party/rust/wgpu-core/src/device/resource.rs
+++ b/third_party/rust/wgpu-core/src/device/resource.rs
@@ -13,7 +13,6 @@ use crate::{
hal_api::HalApi,
hal_label,
hub::Hub,
- id::QueueId,
init_tracker::{
BufferInitTracker, BufferInitTrackerAction, MemoryInitKind, TextureInitRange,
TextureInitTracker, TextureInitTrackerAction,
@@ -29,13 +28,16 @@ use crate::{
resource_log,
snatch::{SnatchGuard, SnatchLock, Snatchable},
storage::Storage,
- track::{BindGroupStates, TextureSelector, Tracker},
- validation::{self, check_buffer_usage, check_texture_usage},
+ track::{BindGroupStates, TextureSelector, Tracker, TrackerIndexAllocators},
+ validation::{
+ self, check_buffer_usage, check_texture_usage, validate_color_attachment_bytes_per_sample,
+ },
FastHashMap, LabelHelpers as _, SubmissionIndex,
};
use arrayvec::ArrayVec;
use hal::{CommandEncoder as _, Device as _};
+use once_cell::sync::OnceCell;
use parking_lot::{Mutex, MutexGuard, RwLock};
use smallvec::SmallVec;
@@ -54,7 +56,7 @@ use std::{
use super::{
life::{self, ResourceMaps},
- queue::{self},
+ queue::{self, Queue},
DeviceDescriptor, DeviceError, ImplicitPipelineContext, UserClosures, ENTRYPOINT_FAILURE_ERROR,
IMPLICIT_BIND_GROUP_LAYOUT_ERROR_LABEL, ZERO_BUFFER_SIZE,
};
@@ -87,8 +89,8 @@ use super::{
pub struct Device<A: HalApi> {
raw: Option<A::Device>,
pub(crate) adapter: Arc<Adapter<A>>,
- pub(crate) queue_id: RwLock<Option<QueueId>>,
- queue_to_drop: RwLock<Option<A::Queue>>,
+ pub(crate) queue: OnceCell<Weak<Queue<A>>>,
+ queue_to_drop: OnceCell<A::Queue>,
pub(crate) zero_buffer: Option<A::Buffer>,
pub(crate) info: ResourceInfo<Device<A>>,
@@ -116,6 +118,7 @@ pub struct Device<A: HalApi> {
/// Has to be locked temporarily only (locked last)
/// and never before pending_writes
pub(crate) trackers: Mutex<Tracker<A>>,
+ pub(crate) tracker_indices: TrackerIndexAllocators,
// Life tracker should be locked right after the device and before anything else.
life_tracker: Mutex<LifetimeTracker<A>>,
/// Temporary storage for resource management functions. Cleared at the end
@@ -160,7 +163,7 @@ impl<A: HalApi> Drop for Device<A> {
unsafe {
raw.destroy_buffer(self.zero_buffer.take().unwrap());
raw.destroy_fence(self.fence.write().take().unwrap());
- let queue = self.queue_to_drop.write().take().unwrap();
+ let queue = self.queue_to_drop.take().unwrap();
raw.exit(queue);
}
}
@@ -258,16 +261,17 @@ impl<A: HalApi> Device<A> {
Ok(Self {
raw: Some(raw_device),
adapter: adapter.clone(),
- queue_id: RwLock::new(None),
- queue_to_drop: RwLock::new(None),
+ queue: OnceCell::new(),
+ queue_to_drop: OnceCell::new(),
zero_buffer: Some(zero_buffer),
- info: ResourceInfo::new("<device>"),
+ info: ResourceInfo::new("<device>", None),
command_allocator: Mutex::new(Some(com_alloc)),
active_submission_index: AtomicU64::new(0),
fence: RwLock::new(Some(fence)),
snatchable_lock: unsafe { SnatchLock::new() },
valid: AtomicBool::new(true),
trackers: Mutex::new(Tracker::new()),
+ tracker_indices: TrackerIndexAllocators::new(),
life_tracker: Mutex::new(life::LifetimeTracker::new()),
temp_suspected: Mutex::new(Some(life::ResourceMaps::new())),
bgl_pool: ResourcePool::new(),
@@ -300,7 +304,7 @@ impl<A: HalApi> Device<A> {
}
pub(crate) fn release_queue(&self, queue: A::Queue) {
- self.queue_to_drop.write().replace(queue);
+ assert!(self.queue_to_drop.set(queue).is_ok());
}
pub(crate) fn lock_life<'a>(&'a self) -> MutexGuard<'a, LifetimeTracker<A>> {
@@ -339,7 +343,8 @@ impl<A: HalApi> Device<A> {
let Some(bind_group) = bind_group.upgrade() else {
continue;
};
- let Some(raw_bind_group) = bind_group.raw.snatch(self.snatchable_lock.write()) else {
+ let Some(raw_bind_group) = bind_group.raw.snatch(self.snatchable_lock.write())
+ else {
continue;
};
@@ -357,6 +362,14 @@ impl<A: HalApi> Device<A> {
}
}
+ pub fn get_queue(&self) -> Option<Arc<Queue<A>>> {
+ self.queue.get().as_ref()?.upgrade()
+ }
+
+ pub fn set_queue(&self, queue: Arc<Queue<A>>) {
+ assert!(self.queue.set(Arc::downgrade(&queue)).is_ok());
+ }
+
/// Check this device for completed commands.
///
/// The `maintain` argument tells how the maintence function should behave, either
@@ -483,56 +496,56 @@ impl<A: HalApi> Device<A> {
if resource.is_unique() {
temp_suspected
.buffers
- .insert(resource.as_info().id(), resource.clone());
+ .insert(resource.as_info().tracker_index(), resource.clone());
}
}
for resource in trackers.textures.used_resources() {
if resource.is_unique() {
temp_suspected
.textures
- .insert(resource.as_info().id(), resource.clone());
+ .insert(resource.as_info().tracker_index(), resource.clone());
}
}
for resource in trackers.views.used_resources() {
if resource.is_unique() {
temp_suspected
.texture_views
- .insert(resource.as_info().id(), resource.clone());
+ .insert(resource.as_info().tracker_index(), resource.clone());
}
}
for resource in trackers.bind_groups.used_resources() {
if resource.is_unique() {
temp_suspected
.bind_groups
- .insert(resource.as_info().id(), resource.clone());
+ .insert(resource.as_info().tracker_index(), resource.clone());
}
}
for resource in trackers.samplers.used_resources() {
if resource.is_unique() {
temp_suspected
.samplers
- .insert(resource.as_info().id(), resource.clone());
+ .insert(resource.as_info().tracker_index(), resource.clone());
}
}
for resource in trackers.compute_pipelines.used_resources() {
if resource.is_unique() {
temp_suspected
.compute_pipelines
- .insert(resource.as_info().id(), resource.clone());
+ .insert(resource.as_info().tracker_index(), resource.clone());
}
}
for resource in trackers.render_pipelines.used_resources() {
if resource.is_unique() {
temp_suspected
.render_pipelines
- .insert(resource.as_info().id(), resource.clone());
+ .insert(resource.as_info().tracker_index(), resource.clone());
}
}
for resource in trackers.query_sets.used_resources() {
if resource.is_unique() {
temp_suspected
.query_sets
- .insert(resource.as_info().id(), resource.clone());
+ .insert(resource.as_info().tracker_index(), resource.clone());
}
}
}
@@ -633,7 +646,10 @@ impl<A: HalApi> Device<A> {
initialization_status: RwLock::new(BufferInitTracker::new(aligned_size)),
sync_mapped_writes: Mutex::new(None),
map_state: Mutex::new(resource::BufferMapState::Idle),
- info: ResourceInfo::new(desc.label.borrow_or_default()),
+ info: ResourceInfo::new(
+ desc.label.borrow_or_default(),
+ Some(self.tracker_indices.buffers.clone()),
+ ),
bind_groups: Mutex::new(Vec::new()),
})
}
@@ -662,7 +678,10 @@ impl<A: HalApi> Device<A> {
mips: 0..desc.mip_level_count,
layers: 0..desc.array_layer_count(),
},
- info: ResourceInfo::new(desc.label.borrow_or_default()),
+ info: ResourceInfo::new(
+ desc.label.borrow_or_default(),
+ Some(self.tracker_indices.textures.clone()),
+ ),
clear_mode: RwLock::new(clear_mode),
views: Mutex::new(Vec::new()),
bind_groups: Mutex::new(Vec::new()),
@@ -684,7 +703,10 @@ impl<A: HalApi> Device<A> {
initialization_status: RwLock::new(BufferInitTracker::new(0)),
sync_mapped_writes: Mutex::new(None),
map_state: Mutex::new(resource::BufferMapState::Idle),
- info: ResourceInfo::new(desc.label.borrow_or_default()),
+ info: ResourceInfo::new(
+ desc.label.borrow_or_default(),
+ Some(self.tracker_indices.buffers.clone()),
+ ),
bind_groups: Mutex::new(Vec::new()),
}
}
@@ -1262,7 +1284,10 @@ impl<A: HalApi> Device<A> {
render_extent,
samples: texture.desc.sample_count,
selector,
- info: ResourceInfo::new(desc.label.borrow_or_default()),
+ info: ResourceInfo::new(
+ desc.label.borrow_or_default(),
+ Some(self.tracker_indices.texture_views.clone()),
+ ),
})
}
@@ -1366,7 +1391,10 @@ impl<A: HalApi> Device<A> {
Ok(Sampler {
raw: Some(raw),
device: self.clone(),
- info: ResourceInfo::new(desc.label.borrow_or_default()),
+ info: ResourceInfo::new(
+ desc.label.borrow_or_default(),
+ Some(self.tracker_indices.samplers.clone()),
+ ),
comparison: desc.compare.is_some(),
filtering: desc.min_filter == wgt::FilterMode::Linear
|| desc.mag_filter == wgt::FilterMode::Linear,
@@ -1484,6 +1512,10 @@ impl<A: HalApi> Device<A> {
.contains(wgt::Features::SHADER_EARLY_DEPTH_TEST),
);
caps.set(
+ Caps::SHADER_INT64,
+ self.features.contains(wgt::Features::SHADER_INT64),
+ );
+ caps.set(
Caps::MULTISAMPLED_SHADING,
self.downlevel
.flags
@@ -1559,7 +1591,7 @@ impl<A: HalApi> Device<A> {
raw: Some(raw),
device: self.clone(),
interface: Some(interface),
- info: ResourceInfo::new(desc.label.borrow_or_default()),
+ info: ResourceInfo::new(desc.label.borrow_or_default(), None),
label: desc.label.borrow_or_default().to_string(),
})
}
@@ -1600,7 +1632,7 @@ impl<A: HalApi> Device<A> {
raw: Some(raw),
device: self.clone(),
interface: None,
- info: ResourceInfo::new(desc.label.borrow_or_default()),
+ info: ResourceInfo::new(desc.label.borrow_or_default(), None),
label: desc.label.borrow_or_default().to_string(),
})
}
@@ -1704,10 +1736,23 @@ impl<A: HalApi> Device<A> {
BindGroupLayoutEntryError::SampleTypeFloatFilterableBindingMultisampled,
});
}
- Bt::Texture { .. } => (
- Some(wgt::Features::TEXTURE_BINDING_ARRAY),
- WritableStorage::No,
- ),
+ Bt::Texture {
+ multisampled,
+ view_dimension,
+ ..
+ } => {
+ if multisampled && view_dimension != TextureViewDimension::D2 {
+ return Err(binding_model::CreateBindGroupLayoutError::Entry {
+ binding: entry.binding,
+ error: BindGroupLayoutEntryError::Non2DMultisampled(view_dimension),
+ });
+ }
+
+ (
+ Some(wgt::Features::TEXTURE_BINDING_ARRAY),
+ WritableStorage::No,
+ )
+ }
Bt::StorageTexture {
access,
view_dimension,
@@ -1840,7 +1885,10 @@ impl<A: HalApi> Device<A> {
entries: entry_map,
origin,
binding_count_validator: count_validator,
- info: ResourceInfo::new(label.unwrap_or("<BindGroupLayout>")),
+ info: ResourceInfo::new(
+ label.unwrap_or("<BindGroupLayout>"),
+ Some(self.tracker_indices.bind_group_layouts.clone()),
+ ),
label: label.unwrap_or_default().to_string(),
})
}
@@ -1905,7 +1953,7 @@ impl<A: HalApi> Device<A> {
.add_single(storage, bb.buffer_id, internal_use)
.ok_or(Error::InvalidBuffer(bb.buffer_id))?;
- check_buffer_usage(buffer.usage, pub_usage)?;
+ check_buffer_usage(bb.buffer_id, buffer.usage, pub_usage)?;
let raw_buffer = buffer
.raw
.get(snatch_guard)
@@ -2273,7 +2321,10 @@ impl<A: HalApi> Device<A> {
raw: Snatchable::new(raw),
device: self.clone(),
layout: layout.clone(),
- info: ResourceInfo::new(desc.label.borrow_or_default()),
+ info: ResourceInfo::new(
+ desc.label.borrow_or_default(),
+ Some(self.tracker_indices.bind_groups.clone()),
+ ),
used,
used_buffer_ranges,
used_texture_ranges,
@@ -2555,7 +2606,10 @@ impl<A: HalApi> Device<A> {
Ok(binding_model::PipelineLayout {
raw: Some(raw),
device: self.clone(),
- info: ResourceInfo::new(desc.label.borrow_or_default()),
+ info: ResourceInfo::new(
+ desc.label.borrow_or_default(),
+ Some(self.tracker_indices.pipeline_layouts.clone()),
+ ),
bind_group_layouts,
push_constant_ranges: desc.push_constant_ranges.iter().cloned().collect(),
})
@@ -2656,14 +2710,21 @@ impl<A: HalApi> Device<A> {
let mut shader_binding_sizes = FastHashMap::default();
let io = validation::StageIo::default();
+ let final_entry_point_name;
+
{
let stage = wgt::ShaderStages::COMPUTE;
+ final_entry_point_name = shader_module.finalize_entry_point_name(
+ stage,
+ desc.stage.entry_point.as_ref().map(|ep| ep.as_ref()),
+ )?;
+
if let Some(ref interface) = shader_module.interface {
let _ = interface.check_stage(
&mut binding_layout_source,
&mut shader_binding_sizes,
- &desc.stage.entry_point,
+ &final_entry_point_name,
stage,
io,
None,
@@ -2691,7 +2752,7 @@ impl<A: HalApi> Device<A> {
label: desc.label.to_hal(self.instance_flags),
layout: pipeline_layout.raw(),
stage: hal::ProgrammableStage {
- entry_point: desc.stage.entry_point.as_ref(),
+ entry_point: final_entry_point_name.as_ref(),
module: shader_module.raw(),
},
};
@@ -2720,7 +2781,10 @@ impl<A: HalApi> Device<A> {
device: self.clone(),
_shader_module: shader_module,
late_sized_buffer_groups,
- info: ResourceInfo::new(desc.label.borrow_or_default()),
+ info: ResourceInfo::new(
+ desc.label.borrow_or_default(),
+ Some(self.tracker_indices.compute_pipelines.clone()),
+ ),
};
Ok(pipeline)
}
@@ -2749,11 +2813,12 @@ impl<A: HalApi> Device<A> {
let mut shader_binding_sizes = FastHashMap::default();
let num_attachments = desc.fragment.as_ref().map(|f| f.targets.len()).unwrap_or(0);
- if num_attachments > hal::MAX_COLOR_ATTACHMENTS {
+ let max_attachments = self.limits.max_color_attachments as usize;
+ if num_attachments > max_attachments {
return Err(pipeline::CreateRenderPipelineError::ColorAttachment(
command::ColorAttachmentError::TooMany {
given: num_attachments,
- limit: hal::MAX_COLOR_ATTACHMENTS,
+ limit: max_attachments,
},
));
}
@@ -2959,6 +3024,7 @@ impl<A: HalApi> Device<A> {
}
}
}
+
break None;
};
if let Some(e) = error {
@@ -2967,6 +3033,16 @@ impl<A: HalApi> Device<A> {
}
}
+ let limit = self.limits.max_color_attachment_bytes_per_sample;
+ let formats = color_targets
+ .iter()
+ .map(|cs| cs.as_ref().map(|cs| cs.format));
+ if let Err(total) = validate_color_attachment_bytes_per_sample(formats, limit) {
+ return Err(pipeline::CreateRenderPipelineError::ColorAttachment(
+ command::ColorAttachmentError::TooManyBytesPerSample { total, limit },
+ ));
+ }
+
if let Some(ds) = depth_stencil_state {
let error = loop {
let format_features = self.describe_format_features(adapter, ds.format)?;
@@ -3051,6 +3127,7 @@ impl<A: HalApi> Device<A> {
};
let vertex_shader_module;
+ let vertex_entry_point_name;
let vertex_stage = {
let stage_desc = &desc.vertex.stage;
let stage = wgt::ShaderStages::VERTEX;
@@ -3065,27 +3142,37 @@ impl<A: HalApi> Device<A> {
return Err(DeviceError::WrongDevice.into());
}
+ let stage_err = |error| pipeline::CreateRenderPipelineError::Stage { stage, error };
+
+ vertex_entry_point_name = vertex_shader_module
+ .finalize_entry_point_name(
+ stage,
+ stage_desc.entry_point.as_ref().map(|ep| ep.as_ref()),
+ )
+ .map_err(stage_err)?;
+
if let Some(ref interface) = vertex_shader_module.interface {
io = interface
.check_stage(
&mut binding_layout_source,
&mut shader_binding_sizes,
- &stage_desc.entry_point,
+ &vertex_entry_point_name,
stage,
io,
desc.depth_stencil.as_ref().map(|d| d.depth_compare),
)
- .map_err(|error| pipeline::CreateRenderPipelineError::Stage { stage, error })?;
+ .map_err(stage_err)?;
validated_stages |= stage;
}
hal::ProgrammableStage {
module: vertex_shader_module.raw(),
- entry_point: stage_desc.entry_point.as_ref(),
+ entry_point: &vertex_entry_point_name,
}
};
let mut fragment_shader_module = None;
+ let fragment_entry_point_name;
let fragment_stage = match desc.fragment {
Some(ref fragment_state) => {
let stage = wgt::ShaderStages::FRAGMENT;
@@ -3099,28 +3186,38 @@ impl<A: HalApi> Device<A> {
})?,
);
+ let stage_err = |error| pipeline::CreateRenderPipelineError::Stage { stage, error };
+
+ fragment_entry_point_name = shader_module
+ .finalize_entry_point_name(
+ stage,
+ fragment_state
+ .stage
+ .entry_point
+ .as_ref()
+ .map(|ep| ep.as_ref()),
+ )
+ .map_err(stage_err)?;
+
if validated_stages == wgt::ShaderStages::VERTEX {
if let Some(ref interface) = shader_module.interface {
io = interface
.check_stage(
&mut binding_layout_source,
&mut shader_binding_sizes,
- &fragment_state.stage.entry_point,
+ &fragment_entry_point_name,
stage,
io,
desc.depth_stencil.as_ref().map(|d| d.depth_compare),
)
- .map_err(|error| pipeline::CreateRenderPipelineError::Stage {
- stage,
- error,
- })?;
+ .map_err(stage_err)?;
validated_stages |= stage;
}
}
if let Some(ref interface) = shader_module.interface {
shader_expects_dual_source_blending = interface
- .fragment_uses_dual_source_blending(&fragment_state.stage.entry_point)
+ .fragment_uses_dual_source_blending(&fragment_entry_point_name)
.map_err(|error| pipeline::CreateRenderPipelineError::Stage {
stage,
error,
@@ -3129,7 +3226,7 @@ impl<A: HalApi> Device<A> {
Some(hal::ProgrammableStage {
module: shader_module.raw(),
- entry_point: fragment_state.stage.entry_point.as_ref(),
+ entry_point: &fragment_entry_point_name,
})
}
None => None,
@@ -3302,7 +3399,10 @@ impl<A: HalApi> Device<A> {
strip_index_format: desc.primitive.strip_index_format,
vertex_steps,
late_sized_buffer_groups,
- info: ResourceInfo::new(desc.label.borrow_or_default()),
+ info: ResourceInfo::new(
+ desc.label.borrow_or_default(),
+ Some(self.tracker_indices.render_pipelines.clone()),
+ ),
};
Ok(pipeline)
}
@@ -3415,7 +3515,7 @@ impl<A: HalApi> Device<A> {
Ok(QuerySet {
raw: Some(unsafe { self.raw().create_query_set(&hal_desc).unwrap() }),
device: self.clone(),
- info: ResourceInfo::new(""),
+ info: ResourceInfo::new("", Some(self.tracker_indices.query_sets.clone())),
desc: desc.map_label(|_| ()),
})
}