summaryrefslogtreecommitdiffstats
path: root/third_party/rust/wgpu-core/src/device/resource.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/wgpu-core/src/device/resource.rs')
-rw-r--r--third_party/rust/wgpu-core/src/device/resource.rs204
1 files changed, 152 insertions, 52 deletions
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(|_| ()),
})
}