Improve the consistency of identifiers (#5108)

This commit is contained in:
John-John Tedro 2024-01-29 10:56:04 +01:00 committed by GitHub
parent 4face1c2ba
commit dec6ea5ea4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
31 changed files with 687 additions and 572 deletions

View File

@ -32,7 +32,7 @@ pub fn op_webgpu_queue_submit(
}) })
.collect::<Result<Vec<_>, AnyError>>()?; .collect::<Result<Vec<_>, AnyError>>()?;
let maybe_err = gfx_select!(queue => instance.queue_submit(queue, &ids)).err(); let maybe_err = gfx_select!(queue => instance.queue_submit(queue.transmute(), &ids)).err();
for rid in command_buffers { for rid in command_buffers {
let resource = state.resource_table.take::<WebGpuCommandBuffer>(rid)?; let resource = state.resource_table.take::<WebGpuCommandBuffer>(rid)?;
@ -84,7 +84,7 @@ pub fn op_webgpu_write_buffer(
None => &buf[data_offset..], None => &buf[data_offset..],
}; };
let maybe_err = gfx_select!(queue => instance.queue_write_buffer( let maybe_err = gfx_select!(queue => instance.queue_write_buffer(
queue, queue.transmute(),
buffer, buffer,
buffer_offset, buffer_offset,
data data
@ -120,7 +120,7 @@ pub fn op_webgpu_write_texture(
let data_layout = data_layout.into(); let data_layout = data_layout.into();
gfx_ok!(queue => instance.queue_write_texture( gfx_ok!(queue => instance.queue_write_texture(
queue, queue.transmute(),
&destination, &destination,
buf, buf,
&data_layout, &data_layout,

View File

@ -61,7 +61,7 @@ fn main() {
global.instance_create_surface( global.instance_create_surface(
window.display_handle().unwrap().into(), window.display_handle().unwrap().into(),
window.window_handle().unwrap().into(), window.window_handle().unwrap().into(),
wgc::id::TypedId::zip(0, 1, wgt::Backend::Empty), wgc::id::Id::zip(0, 1, wgt::Backend::Empty),
) )
} }
.unwrap(); .unwrap();
@ -79,22 +79,21 @@ fn main() {
#[cfg(not(feature = "winit"))] #[cfg(not(feature = "winit"))]
compatible_surface: None, compatible_surface: None,
}, },
wgc::instance::AdapterInputs::IdSet( wgc::instance::AdapterInputs::IdSet(&[wgc::id::Id::zip(0, 0, backend)], |id| {
&[wgc::id::TypedId::zip(0, 0, backend)], id.backend()
|id| id.backend(), }),
),
) )
.expect("Unable to find an adapter for selected backend"); .expect("Unable to find an adapter for selected backend");
let info = gfx_select!(adapter => global.adapter_get_info(adapter)).unwrap(); let info = gfx_select!(adapter => global.adapter_get_info(adapter)).unwrap();
log::info!("Picked '{}'", info.name); log::info!("Picked '{}'", info.name);
let id = wgc::id::TypedId::zip(1, 0, backend); let id = wgc::id::Id::zip(1, 0, backend);
let (_, _, error) = gfx_select!(adapter => global.adapter_request_device( let (_, _, error) = gfx_select!(adapter => global.adapter_request_device(
adapter, adapter,
&desc, &desc,
None, None,
id, id,
id id.transmute()
)); ));
if let Some(e) = error { if let Some(e) = error {
panic!("{:?}", e); panic!("{:?}", e);

View File

@ -14,10 +14,10 @@ use std::{borrow::Cow, fs, path::Path};
pub struct IdentityPassThroughFactory; pub struct IdentityPassThroughFactory;
impl<I: wgc::id::TypedId> wgc::identity::IdentityHandlerFactory<I> for IdentityPassThroughFactory { impl<T: wgc::id::Marker> wgc::identity::IdentityHandlerFactory<T> for IdentityPassThroughFactory {
type Input = I; type Input = wgc::id::Id<T>;
fn input_to_id(id_in: Self::Input) -> I { fn input_to_id(id_in: Self::Input) -> wgc::id::Id<T> {
id_in id_in
} }
@ -38,7 +38,7 @@ pub trait GlobalPlay {
device: wgc::id::DeviceId, device: wgc::id::DeviceId,
action: trace::Action, action: trace::Action,
dir: &Path, dir: &Path,
comb_manager: &mut wgc::identity::IdentityManager<wgc::id::CommandBufferId>, comb_manager: &mut wgc::identity::IdentityManager<wgc::id::markers::CommandBuffer>,
); );
} }
@ -153,7 +153,7 @@ impl GlobalPlay for wgc::global::Global<IdentityPassThroughFactory> {
device: wgc::id::DeviceId, device: wgc::id::DeviceId,
action: trace::Action, action: trace::Action,
dir: &Path, dir: &Path,
comb_manager: &mut wgc::identity::IdentityManager<wgc::id::CommandBufferId>, comb_manager: &mut wgc::identity::IdentityManager<wgc::id::markers::CommandBuffer>,
) { ) {
use wgc::device::trace::Action; use wgc::device::trace::Action;
log::debug!("action {:?}", action); log::debug!("action {:?}", action);
@ -350,7 +350,7 @@ impl GlobalPlay for wgc::global::Global<IdentityPassThroughFactory> {
let bin = std::fs::read(dir.join(data)).unwrap(); let bin = std::fs::read(dir.join(data)).unwrap();
let size = (range.end - range.start) as usize; let size = (range.end - range.start) as usize;
if queued { if queued {
self.queue_write_buffer::<A>(device, id, range.start, &bin) self.queue_write_buffer::<A>(device.transmute(), id, range.start, &bin)
.unwrap(); .unwrap();
} else { } else {
self.device_wait_for_buffer::<A>(device, id).unwrap(); self.device_wait_for_buffer::<A>(device, id).unwrap();
@ -365,23 +365,24 @@ impl GlobalPlay for wgc::global::Global<IdentityPassThroughFactory> {
size, size,
} => { } => {
let bin = std::fs::read(dir.join(data)).unwrap(); let bin = std::fs::read(dir.join(data)).unwrap();
self.queue_write_texture::<A>(device, &to, &bin, &layout, &size) self.queue_write_texture::<A>(device.transmute(), &to, &bin, &layout, &size)
.unwrap(); .unwrap();
} }
Action::Submit(_index, ref commands) if commands.is_empty() => { Action::Submit(_index, ref commands) if commands.is_empty() => {
self.queue_submit::<A>(device, &[]).unwrap(); self.queue_submit::<A>(device.transmute(), &[]).unwrap();
} }
Action::Submit(_index, commands) => { Action::Submit(_index, commands) => {
let (encoder, error) = self.device_create_command_encoder::<A>( let (encoder, error) = self.device_create_command_encoder::<A>(
device, device,
&wgt::CommandEncoderDescriptor { label: None }, &wgt::CommandEncoderDescriptor { label: None },
comb_manager.process(device.backend()), comb_manager.process(device.backend()).transmute(),
); );
if let Some(e) = error { if let Some(e) = error {
panic!("{e}"); panic!("{e}");
} }
let cmdbuf = self.encode_commands::<A>(encoder, commands); let cmdbuf = self.encode_commands::<A>(encoder, commands);
self.queue_submit::<A>(device, &[cmdbuf]).unwrap(); self.queue_submit::<A>(device.transmute(), &[cmdbuf])
.unwrap();
} }
} }
} }

View File

@ -105,7 +105,7 @@ impl Test<'_> {
test_num: u32, test_num: u32,
) { ) {
let backend = adapter.backend(); let backend = adapter.backend();
let device_id = wgc::id::TypedId::zip(test_num, 0, backend); let device_id = wgc::id::Id::zip(test_num, 0, backend);
let (_, _, error) = wgc::gfx_select!(adapter => global.adapter_request_device( let (_, _, error) = wgc::gfx_select!(adapter => global.adapter_request_device(
adapter, adapter,
&wgt::DeviceDescriptor { &wgt::DeviceDescriptor {
@ -115,7 +115,7 @@ impl Test<'_> {
}, },
None, None,
device_id, device_id,
device_id device_id.transmute()
)); ));
if let Some(e) = error { if let Some(e) = error {
panic!("{:?}", e); panic!("{:?}", e);
@ -128,7 +128,7 @@ impl Test<'_> {
} }
println!("\t\t\tMapping..."); println!("\t\t\tMapping...");
for expect in &self.expectations { for expect in &self.expectations {
let buffer = wgc::id::TypedId::zip(expect.buffer.index, expect.buffer.epoch, backend); let buffer = wgc::id::Id::zip(expect.buffer.index, expect.buffer.epoch, backend);
wgc::gfx_select!(device_id => global.buffer_map_async( wgc::gfx_select!(device_id => global.buffer_map_async(
buffer, buffer,
expect.offset .. expect.offset+expect.data.len() as wgt::BufferAddress, expect.offset .. expect.offset+expect.data.len() as wgt::BufferAddress,
@ -148,7 +148,7 @@ impl Test<'_> {
for expect in self.expectations { for expect in self.expectations {
println!("\t\t\tChecking {}", expect.name); println!("\t\t\tChecking {}", expect.name);
let buffer = wgc::id::TypedId::zip(expect.buffer.index, expect.buffer.epoch, backend); let buffer = wgc::id::Id::zip(expect.buffer.index, expect.buffer.epoch, backend);
let (ptr, size) = let (ptr, size) =
wgc::gfx_select!(device_id => global.buffer_get_mapped_range(buffer, expect.offset, Some(expect.data.len() as wgt::BufferAddress))) wgc::gfx_select!(device_id => global.buffer_get_mapped_range(buffer, expect.offset, Some(expect.data.len() as wgt::BufferAddress)))
.unwrap(); .unwrap();
@ -221,10 +221,9 @@ impl Corpus {
force_fallback_adapter: false, force_fallback_adapter: false,
compatible_surface: None, compatible_surface: None,
}, },
wgc::instance::AdapterInputs::IdSet( wgc::instance::AdapterInputs::IdSet(&[wgc::id::Id::zip(0, 0, backend)], |id| {
&[wgc::id::TypedId::zip(0, 0, backend)], id.backend()
|id| id.backend(), }),
),
) { ) {
Ok(adapter) => adapter, Ok(adapter) => adapter,
Err(_) => continue, Err(_) => continue,

View File

@ -6,10 +6,7 @@ use crate::{
}, },
error::{ErrorFormatter, PrettyError}, error::{ErrorFormatter, PrettyError},
hal_api::HalApi, hal_api::HalApi,
id::{ id::{BindGroupLayoutId, BufferId, SamplerId, TextureId, TextureViewId},
BindGroupId, BindGroupLayoutId, BufferId, PipelineLayoutId, SamplerId, TextureId,
TextureViewId,
},
init_tracker::{BufferInitTrackerAction, TextureInitTrackerAction}, init_tracker::{BufferInitTrackerAction, TextureInitTrackerAction},
resource::{Resource, ResourceInfo, ResourceType}, resource::{Resource, ResourceInfo, ResourceType},
resource_log, resource_log,
@ -441,7 +438,7 @@ pub struct BindGroupLayoutDescriptor<'a> {
pub entries: Cow<'a, [wgt::BindGroupLayoutEntry]>, pub entries: Cow<'a, [wgt::BindGroupLayoutEntry]>,
} }
pub type BindGroupLayouts<A> = crate::storage::Storage<BindGroupLayout<A>, BindGroupLayoutId>; pub type BindGroupLayouts<A> = crate::storage::Storage<BindGroupLayout<A>>;
/// Bind group layout. /// Bind group layout.
#[derive(Debug)] #[derive(Debug)]
@ -458,7 +455,7 @@ pub struct BindGroupLayout<A: HalApi> {
pub(crate) origin: bgl::Origin, pub(crate) origin: bgl::Origin,
#[allow(unused)] #[allow(unused)]
pub(crate) binding_count_validator: BindingTypeMaxCountValidator, pub(crate) binding_count_validator: BindingTypeMaxCountValidator,
pub(crate) info: ResourceInfo<BindGroupLayoutId>, pub(crate) info: ResourceInfo<BindGroupLayout<A>>,
pub(crate) label: String, pub(crate) label: String,
} }
@ -482,14 +479,16 @@ impl<A: HalApi> Drop for BindGroupLayout<A> {
} }
} }
impl<A: HalApi> Resource<BindGroupLayoutId> for BindGroupLayout<A> { impl<A: HalApi> Resource for BindGroupLayout<A> {
const TYPE: ResourceType = "BindGroupLayout"; const TYPE: ResourceType = "BindGroupLayout";
fn as_info(&self) -> &ResourceInfo<BindGroupLayoutId> { type Marker = crate::id::markers::BindGroupLayout;
fn as_info(&self) -> &ResourceInfo<Self> {
&self.info &self.info
} }
fn as_info_mut(&mut self) -> &mut ResourceInfo<BindGroupLayoutId> { fn as_info_mut(&mut self) -> &mut ResourceInfo<Self> {
&mut self.info &mut self.info
} }
@ -602,7 +601,7 @@ pub struct PipelineLayoutDescriptor<'a> {
pub struct PipelineLayout<A: HalApi> { pub struct PipelineLayout<A: HalApi> {
pub(crate) raw: Option<A::PipelineLayout>, pub(crate) raw: Option<A::PipelineLayout>,
pub(crate) device: Arc<Device<A>>, pub(crate) device: Arc<Device<A>>,
pub(crate) info: ResourceInfo<PipelineLayoutId>, pub(crate) info: ResourceInfo<PipelineLayout<A>>,
pub(crate) bind_group_layouts: ArrayVec<Arc<BindGroupLayout<A>>, { hal::MAX_BIND_GROUPS }>, pub(crate) bind_group_layouts: ArrayVec<Arc<BindGroupLayout<A>>, { hal::MAX_BIND_GROUPS }>,
pub(crate) push_constant_ranges: ArrayVec<wgt::PushConstantRange, { SHADER_STAGE_COUNT }>, pub(crate) push_constant_ranges: ArrayVec<wgt::PushConstantRange, { SHADER_STAGE_COUNT }>,
} }
@ -716,14 +715,16 @@ impl<A: HalApi> PipelineLayout<A> {
} }
} }
impl<A: HalApi> Resource<PipelineLayoutId> for PipelineLayout<A> { impl<A: HalApi> Resource for PipelineLayout<A> {
const TYPE: ResourceType = "PipelineLayout"; const TYPE: ResourceType = "PipelineLayout";
fn as_info(&self) -> &ResourceInfo<PipelineLayoutId> { type Marker = crate::id::markers::PipelineLayout;
fn as_info(&self) -> &ResourceInfo<Self> {
&self.info &self.info
} }
fn as_info_mut(&mut self) -> &mut ResourceInfo<PipelineLayoutId> { fn as_info_mut(&mut self) -> &mut ResourceInfo<Self> {
&mut self.info &mut self.info
} }
} }
@ -830,7 +831,7 @@ pub struct BindGroup<A: HalApi> {
pub(crate) raw: Snatchable<A::BindGroup>, pub(crate) raw: Snatchable<A::BindGroup>,
pub(crate) device: Arc<Device<A>>, pub(crate) device: Arc<Device<A>>,
pub(crate) layout: Arc<BindGroupLayout<A>>, pub(crate) layout: Arc<BindGroupLayout<A>>,
pub(crate) info: ResourceInfo<BindGroupId>, pub(crate) info: ResourceInfo<BindGroup<A>>,
pub(crate) used: BindGroupStates<A>, pub(crate) used: BindGroupStates<A>,
pub(crate) used_buffer_ranges: Vec<BufferInitTrackerAction<A>>, pub(crate) used_buffer_ranges: Vec<BufferInitTrackerAction<A>>,
pub(crate) used_texture_ranges: Vec<TextureInitTrackerAction<A>>, pub(crate) used_texture_ranges: Vec<TextureInitTrackerAction<A>>,
@ -919,14 +920,16 @@ impl<A: HalApi> BindGroup<A> {
} }
} }
impl<A: HalApi> Resource<BindGroupId> for BindGroup<A> { impl<A: HalApi> Resource for BindGroup<A> {
const TYPE: ResourceType = "BindGroup"; const TYPE: ResourceType = "BindGroup";
fn as_info(&self) -> &ResourceInfo<BindGroupId> { type Marker = crate::id::markers::BindGroup;
fn as_info(&self) -> &ResourceInfo<Self> {
&self.info &self.info
} }
fn as_info_mut(&mut self) -> &mut ResourceInfo<BindGroupId> { fn as_info_mut(&mut self) -> &mut ResourceInfo<Self> {
&mut self.info &mut self.info
} }
} }

View File

@ -94,7 +94,7 @@ use crate::{
error::{ErrorFormatter, PrettyError}, error::{ErrorFormatter, PrettyError},
hal_api::HalApi, hal_api::HalApi,
hub::Hub, hub::Hub,
id::{self, RenderBundleId}, id,
init_tracker::{BufferInitTrackerAction, MemoryInitKind, TextureInitTrackerAction}, init_tracker::{BufferInitTrackerAction, MemoryInitKind, TextureInitTrackerAction},
pipeline::{PipelineFlags, RenderPipeline, VertexStep}, pipeline::{PipelineFlags, RenderPipeline, VertexStep},
resource::{Resource, ResourceInfo, ResourceType}, resource::{Resource, ResourceInfo, ResourceType},
@ -832,7 +832,7 @@ pub struct RenderBundle<A: HalApi> {
pub(super) buffer_memory_init_actions: Vec<BufferInitTrackerAction<A>>, pub(super) buffer_memory_init_actions: Vec<BufferInitTrackerAction<A>>,
pub(super) texture_memory_init_actions: Vec<TextureInitTrackerAction<A>>, pub(super) texture_memory_init_actions: Vec<TextureInitTrackerAction<A>>,
pub(super) context: RenderPassContext, pub(super) context: RenderPassContext,
pub(crate) info: ResourceInfo<RenderBundleId>, pub(crate) info: ResourceInfo<RenderBundle<A>>,
discard_hal_labels: bool, discard_hal_labels: bool,
} }
@ -1067,14 +1067,16 @@ impl<A: HalApi> RenderBundle<A> {
} }
} }
impl<A: HalApi> Resource<RenderBundleId> for RenderBundle<A> { impl<A: HalApi> Resource for RenderBundle<A> {
const TYPE: ResourceType = "RenderBundle"; const TYPE: ResourceType = "RenderBundle";
fn as_info(&self) -> &ResourceInfo<RenderBundleId> { type Marker = crate::id::markers::RenderBundle;
fn as_info(&self) -> &ResourceInfo<Self> {
&self.info &self.info
} }
fn as_info_mut(&mut self) -> &mut ResourceInfo<RenderBundleId> { fn as_info_mut(&mut self) -> &mut ResourceInfo<Self> {
&mut self.info &mut self.info
} }
} }

View File

@ -305,7 +305,7 @@ impl<A: HalApi> State<A> {
&mut self, &mut self,
raw_encoder: &mut A::CommandEncoder, raw_encoder: &mut A::CommandEncoder,
base_trackers: &mut Tracker<A>, base_trackers: &mut Tracker<A>,
bind_group_guard: &Storage<BindGroup<A>, id::BindGroupId>, bind_group_guard: &Storage<BindGroup<A>>,
indirect_buffer: Option<id::BufferId>, indirect_buffer: Option<id::BufferId>,
snatch_guard: &SnatchGuard, snatch_guard: &SnatchGuard,
) -> Result<(), UsageConflict> { ) -> Result<(), UsageConflict> {

View File

@ -140,7 +140,7 @@ pub struct CommandBuffer<A: HalApi> {
pub(crate) device: Arc<Device<A>>, pub(crate) device: Arc<Device<A>>,
limits: wgt::Limits, limits: wgt::Limits,
support_clear_texture: bool, support_clear_texture: bool,
pub(crate) info: ResourceInfo<CommandBufferId>, pub(crate) info: ResourceInfo<CommandBuffer<A>>,
pub(crate) data: Mutex<Option<CommandBufferMutable<A>>>, pub(crate) data: Mutex<Option<CommandBufferMutable<A>>>,
} }
@ -255,7 +255,7 @@ impl<A: HalApi> CommandBuffer<A> {
id: id::CommandEncoderId, id: id::CommandEncoderId,
) -> Result<Arc<Self>, CommandEncoderError> { ) -> Result<Arc<Self>, CommandEncoderError> {
let storage = hub.command_buffers.read(); let storage = hub.command_buffers.read();
match storage.get(id) { match storage.get(id.transmute()) {
Ok(cmd_buf) => match cmd_buf.data.lock().as_ref().unwrap().status { Ok(cmd_buf) => match cmd_buf.data.lock().as_ref().unwrap().status {
CommandEncoderStatus::Recording => Ok(cmd_buf.clone()), CommandEncoderStatus::Recording => Ok(cmd_buf.clone()),
CommandEncoderStatus::Finished => Err(CommandEncoderError::NotRecording), CommandEncoderStatus::Finished => Err(CommandEncoderError::NotRecording),
@ -296,14 +296,16 @@ impl<A: HalApi> CommandBuffer<A> {
} }
} }
impl<A: HalApi> Resource<CommandBufferId> for CommandBuffer<A> { impl<A: HalApi> Resource for CommandBuffer<A> {
const TYPE: ResourceType = "CommandBuffer"; const TYPE: ResourceType = "CommandBuffer";
fn as_info(&self) -> &ResourceInfo<CommandBufferId> { type Marker = crate::id::markers::CommandBuffer;
fn as_info(&self) -> &ResourceInfo<Self> {
&self.info &self.info
} }
fn as_info_mut(&mut self) -> &mut ResourceInfo<CommandBufferId> { fn as_info_mut(&mut self) -> &mut ResourceInfo<Self> {
&mut self.info &mut self.info
} }
@ -418,7 +420,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let hub = A::hub(self); let hub = A::hub(self);
let error = match hub.command_buffers.get(encoder_id) { let error = match hub.command_buffers.get(encoder_id.transmute()) {
Ok(cmd_buf) => { Ok(cmd_buf) => {
let mut cmd_buf_data = cmd_buf.data.lock(); let mut cmd_buf_data = cmd_buf.data.lock();
let cmd_buf_data = cmd_buf_data.as_mut().unwrap(); let cmd_buf_data = cmd_buf_data.as_mut().unwrap();
@ -444,7 +446,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
Err(_) => Some(CommandEncoderError::Invalid), Err(_) => Some(CommandEncoderError::Invalid),
}; };
(encoder_id, error) (encoder_id.transmute(), error)
} }
pub fn command_encoder_push_debug_group<A: HalApi>( pub fn command_encoder_push_debug_group<A: HalApi>(
@ -700,7 +702,7 @@ impl PrettyError for PassErrorScope {
// This error is not in the error chain, only notes are needed // This error is not in the error chain, only notes are needed
match *self { match *self {
Self::Pass(id) => { Self::Pass(id) => {
fmt.command_buffer_label(&id); fmt.command_buffer_label(&id.transmute());
} }
Self::SetBindGroup(id) => { Self::SetBindGroup(id) => {
fmt.bind_group_label(&id); fmt.bind_group_label(&id);

View File

@ -7,7 +7,7 @@ use crate::{
device::DeviceError, device::DeviceError,
global::Global, global::Global,
hal_api::HalApi, hal_api::HalApi,
id::{self, Id, TypedId}, id::{self, Id},
identity::GlobalIdentityHandlerFactory, identity::GlobalIdentityHandlerFactory,
init_tracker::MemoryInitKind, init_tracker::MemoryInitKind,
resource::QuerySet, resource::QuerySet,
@ -49,7 +49,7 @@ impl<A: HalApi> QueryResetMap<A> {
pub fn reset_queries( pub fn reset_queries(
&mut self, &mut self,
raw_encoder: &mut A::CommandEncoder, raw_encoder: &mut A::CommandEncoder,
query_set_storage: &Storage<QuerySet<A>, id::QuerySetId>, query_set_storage: &Storage<QuerySet<A>>,
backend: wgt::Backend, backend: wgt::Backend,
) -> Result<(), id::QuerySetId> { ) -> Result<(), id::QuerySetId> {
for (query_set_id, (state, epoch)) in self.map.drain() { for (query_set_id, (state, epoch)) in self.map.drain() {
@ -314,7 +314,7 @@ impl<A: HalApi> QuerySet<A> {
pub(super) fn end_occlusion_query<A: HalApi>( pub(super) fn end_occlusion_query<A: HalApi>(
raw_encoder: &mut A::CommandEncoder, raw_encoder: &mut A::CommandEncoder,
storage: &Storage<QuerySet<A>, id::QuerySetId>, storage: &Storage<QuerySet<A>>,
active_query: &mut Option<(id::QuerySetId, u32)>, active_query: &mut Option<(id::QuerySetId, u32)>,
) -> Result<(), QueryUseError> { ) -> Result<(), QueryUseError> {
if let Some((query_set_id, query_index)) = active_query.take() { if let Some((query_set_id, query_index)) = active_query.take() {
@ -331,7 +331,7 @@ pub(super) fn end_occlusion_query<A: HalApi>(
pub(super) fn end_pipeline_statistics_query<A: HalApi>( pub(super) fn end_pipeline_statistics_query<A: HalApi>(
raw_encoder: &mut A::CommandEncoder, raw_encoder: &mut A::CommandEncoder,
storage: &Storage<QuerySet<A>, id::QuerySetId>, storage: &Storage<QuerySet<A>>,
active_query: &mut Option<(id::QuerySetId, u32)>, active_query: &mut Option<(id::QuerySetId, u32)>,
) -> Result<(), QueryUseError> { ) -> Result<(), QueryUseError> {
if let Some((query_set_id, query_index)) = active_query.take() { if let Some((query_set_id, query_index)) = active_query.take() {

View File

@ -784,10 +784,10 @@ impl<'a, A: HalApi> RenderPassInfo<'a, A> {
trackers: &mut Tracker<A>, trackers: &mut Tracker<A>,
texture_memory_actions: &mut CommandBufferTextureMemoryActions<A>, texture_memory_actions: &mut CommandBufferTextureMemoryActions<A>,
pending_query_resets: &mut QueryResetMap<A>, pending_query_resets: &mut QueryResetMap<A>,
view_guard: &'a Storage<TextureView<A>, id::TextureViewId>, view_guard: &'a Storage<TextureView<A>>,
buffer_guard: &'a Storage<Buffer<A>, id::BufferId>, buffer_guard: &'a Storage<Buffer<A>>,
texture_guard: &'a Storage<Texture<A>, id::TextureId>, texture_guard: &'a Storage<Texture<A>>,
query_set_guard: &'a Storage<QuerySet<A>, id::QuerySetId>, query_set_guard: &'a Storage<QuerySet<A>>,
snatch_guard: &SnatchGuard<'a>, snatch_guard: &SnatchGuard<'a>,
) -> Result<Self, RenderPassErrorInner> { ) -> Result<Self, RenderPassErrorInner> {
profiling::scope!("RenderPassInfo::start"); profiling::scope!("RenderPassInfo::start");
@ -2391,7 +2391,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
(trackers, pending_discard_init_fixups) (trackers, pending_discard_init_fixups)
}; };
let cmd_buf = hub.command_buffers.get(encoder_id).unwrap(); let cmd_buf = hub.command_buffers.get(encoder_id.transmute()).unwrap();
let mut cmd_buf_data = cmd_buf.data.lock(); let mut cmd_buf_data = cmd_buf.data.lock();
let cmd_buf_data = cmd_buf_data.as_mut().unwrap(); let cmd_buf_data = cmd_buf_data.as_mut().unwrap();

View File

@ -8,6 +8,7 @@ use crate::{
}, },
global::Global, global::Global,
hal_api::HalApi, hal_api::HalApi,
id::markers,
id::{self, AdapterId, DeviceId, QueueId, SurfaceId}, id::{self, AdapterId, DeviceId, QueueId, SurfaceId},
identity::{GlobalIdentityHandlerFactory, Input}, identity::{GlobalIdentityHandlerFactory, Input},
init_tracker::TextureInitTracker, init_tracker::TextureInitTracker,
@ -146,12 +147,12 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
&self, &self,
device_id: DeviceId, device_id: DeviceId,
desc: &resource::BufferDescriptor, desc: &resource::BufferDescriptor,
id_in: Input<G, id::BufferId>, id_in: Input<G, markers::Buffer>,
) -> (id::BufferId, Option<CreateBufferError>) { ) -> (id::BufferId, Option<CreateBufferError>) {
profiling::scope!("Device::create_buffer"); profiling::scope!("Device::create_buffer");
let hub = A::hub(self); let hub = A::hub(self);
let fid = hub.buffers.prepare::<G>(id_in); let fid = hub.buffers.prepare::<G, _>(id_in);
let mut to_destroy: ArrayVec<resource::Buffer<A>, 2> = ArrayVec::new(); let mut to_destroy: ArrayVec<resource::Buffer<A>, 2> = ArrayVec::new();
let error = loop { let error = loop {
@ -309,20 +310,20 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
/// [`device_create_buffer`]: Global::device_create_buffer /// [`device_create_buffer`]: Global::device_create_buffer
/// [`usage`]: https://www.w3.org/TR/webgpu/#dom-gputexturedescriptor-usage /// [`usage`]: https://www.w3.org/TR/webgpu/#dom-gputexturedescriptor-usage
/// [`wgpu_types::BufferUsages`]: wgt::BufferUsages /// [`wgpu_types::BufferUsages`]: wgt::BufferUsages
pub fn create_buffer_error<A: HalApi>(&self, id_in: Input<G, id::BufferId>, label: Label) { pub fn create_buffer_error<A: HalApi>(&self, id_in: Input<G, markers::Buffer>, label: Label) {
let hub = A::hub(self); let hub = A::hub(self);
let fid = hub.buffers.prepare::<G>(id_in); let fid = hub.buffers.prepare::<G, _>(id_in);
fid.assign_error(label.borrow_or_default()); fid.assign_error(label.borrow_or_default());
} }
pub fn create_render_bundle_error<A: HalApi>( pub fn create_render_bundle_error<A: HalApi>(
&self, &self,
id_in: Input<G, id::RenderBundleId>, id_in: Input<G, markers::RenderBundle>,
label: Label, label: Label,
) { ) {
let hub = A::hub(self); let hub = A::hub(self);
let fid = hub.render_bundles.prepare::<G>(id_in); let fid = hub.render_bundles.prepare::<G, _>(id_in);
fid.assign_error(label.borrow_or_default()); fid.assign_error(label.borrow_or_default());
} }
@ -330,9 +331,9 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
/// Assign `id_in` an error with the given `label`. /// Assign `id_in` an error with the given `label`.
/// ///
/// See `create_buffer_error` for more context and explaination. /// See `create_buffer_error` for more context and explaination.
pub fn create_texture_error<A: HalApi>(&self, id_in: Input<G, id::TextureId>, label: Label) { pub fn create_texture_error<A: HalApi>(&self, id_in: Input<G, markers::Texture>, label: Label) {
let hub = A::hub(self); let hub = A::hub(self);
let fid = hub.textures.prepare::<G>(id_in); let fid = hub.textures.prepare::<G, _>(id_in);
fid.assign_error(label.borrow_or_default()); fid.assign_error(label.borrow_or_default());
} }
@ -545,13 +546,13 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
&self, &self,
device_id: DeviceId, device_id: DeviceId,
desc: &resource::TextureDescriptor, desc: &resource::TextureDescriptor,
id_in: Input<G, id::TextureId>, id_in: Input<G, markers::Texture>,
) -> (id::TextureId, Option<resource::CreateTextureError>) { ) -> (id::TextureId, Option<resource::CreateTextureError>) {
profiling::scope!("Device::create_texture"); profiling::scope!("Device::create_texture");
let hub = A::hub(self); let hub = A::hub(self);
let fid = hub.textures.prepare::<G>(id_in); let fid = hub.textures.prepare::<G, _>(id_in);
let error = loop { let error = loop {
let device = match hub.devices.get(device_id) { let device = match hub.devices.get(device_id) {
@ -599,13 +600,13 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
hal_texture: A::Texture, hal_texture: A::Texture,
device_id: DeviceId, device_id: DeviceId,
desc: &resource::TextureDescriptor, desc: &resource::TextureDescriptor,
id_in: Input<G, id::TextureId>, id_in: Input<G, markers::Texture>,
) -> (id::TextureId, Option<resource::CreateTextureError>) { ) -> (id::TextureId, Option<resource::CreateTextureError>) {
profiling::scope!("Device::create_texture_from_hal"); profiling::scope!("Device::create_texture_from_hal");
let hub = A::hub(self); let hub = A::hub(self);
let fid = hub.textures.prepare::<G>(id_in); let fid = hub.textures.prepare::<G, _>(id_in);
let error = loop { let error = loop {
let device = match hub.devices.get(device_id) { let device = match hub.devices.get(device_id) {
@ -673,12 +674,12 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
hal_buffer: A::Buffer, hal_buffer: A::Buffer,
device_id: DeviceId, device_id: DeviceId,
desc: &resource::BufferDescriptor, desc: &resource::BufferDescriptor,
id_in: Input<G, id::BufferId>, id_in: Input<G, markers::Buffer>,
) -> (id::BufferId, Option<CreateBufferError>) { ) -> (id::BufferId, Option<CreateBufferError>) {
profiling::scope!("Device::create_buffer"); profiling::scope!("Device::create_buffer");
let hub = A::hub(self); let hub = A::hub(self);
let fid = hub.buffers.prepare::<G>(id_in); let fid = hub.buffers.prepare::<G, _>(id_in);
let error = loop { let error = loop {
let device = match hub.devices.get(device_id) { let device = match hub.devices.get(device_id) {
@ -783,13 +784,13 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
&self, &self,
texture_id: id::TextureId, texture_id: id::TextureId,
desc: &resource::TextureViewDescriptor, desc: &resource::TextureViewDescriptor,
id_in: Input<G, id::TextureViewId>, id_in: Input<G, markers::TextureView>,
) -> (id::TextureViewId, Option<resource::CreateTextureViewError>) { ) -> (id::TextureViewId, Option<resource::CreateTextureViewError>) {
profiling::scope!("Texture::create_view"); profiling::scope!("Texture::create_view");
let hub = A::hub(self); let hub = A::hub(self);
let fid = hub.texture_views.prepare::<G>(id_in); let fid = hub.texture_views.prepare::<G, _>(id_in);
let error = loop { let error = loop {
let texture = match hub.textures.get(texture_id) { let texture = match hub.textures.get(texture_id) {
@ -873,12 +874,12 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
&self, &self,
device_id: DeviceId, device_id: DeviceId,
desc: &resource::SamplerDescriptor, desc: &resource::SamplerDescriptor,
id_in: Input<G, id::SamplerId>, id_in: Input<G, markers::Sampler>,
) -> (id::SamplerId, Option<resource::CreateSamplerError>) { ) -> (id::SamplerId, Option<resource::CreateSamplerError>) {
profiling::scope!("Device::create_sampler"); profiling::scope!("Device::create_sampler");
let hub = A::hub(self); let hub = A::hub(self);
let fid = hub.samplers.prepare::<G>(id_in); let fid = hub.samplers.prepare::<G, _>(id_in);
let error = loop { let error = loop {
let device = match hub.devices.get(device_id) { let device = match hub.devices.get(device_id) {
@ -934,7 +935,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
&self, &self,
device_id: DeviceId, device_id: DeviceId,
desc: &binding_model::BindGroupLayoutDescriptor, desc: &binding_model::BindGroupLayoutDescriptor,
id_in: Input<G, id::BindGroupLayoutId>, id_in: Input<G, markers::BindGroupLayout>,
) -> ( ) -> (
id::BindGroupLayoutId, id::BindGroupLayoutId,
Option<binding_model::CreateBindGroupLayoutError>, Option<binding_model::CreateBindGroupLayoutError>,
@ -942,7 +943,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
profiling::scope!("Device::create_bind_group_layout"); profiling::scope!("Device::create_bind_group_layout");
let hub = A::hub(self); let hub = A::hub(self);
let fid = hub.bind_group_layouts.prepare::<G>(id_in); let fid = hub.bind_group_layouts.prepare::<G, _>(id_in);
let error = loop { let error = loop {
let device = match hub.devices.get(device_id) { let device = match hub.devices.get(device_id) {
@ -1004,7 +1005,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
return (id.unwrap(), None); return (id.unwrap(), None);
}; };
let fid = hub.bind_group_layouts.prepare::<G>(id_in); let fid = hub.bind_group_layouts.prepare::<G, _>(id_in);
let id = fid.assign_error(desc.label.borrow_or_default()); let id = fid.assign_error(desc.label.borrow_or_default());
(id, Some(error)) (id, Some(error))
} }
@ -1033,7 +1034,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
&self, &self,
device_id: DeviceId, device_id: DeviceId,
desc: &binding_model::PipelineLayoutDescriptor, desc: &binding_model::PipelineLayoutDescriptor,
id_in: Input<G, id::PipelineLayoutId>, id_in: Input<G, markers::PipelineLayout>,
) -> ( ) -> (
id::PipelineLayoutId, id::PipelineLayoutId,
Option<binding_model::CreatePipelineLayoutError>, Option<binding_model::CreatePipelineLayoutError>,
@ -1041,7 +1042,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
profiling::scope!("Device::create_pipeline_layout"); profiling::scope!("Device::create_pipeline_layout");
let hub = A::hub(self); let hub = A::hub(self);
let fid = hub.pipeline_layouts.prepare::<G>(id_in); let fid = hub.pipeline_layouts.prepare::<G, _>(id_in);
let error = loop { let error = loop {
let device = match hub.devices.get(device_id) { let device = match hub.devices.get(device_id) {
@ -1094,12 +1095,12 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
&self, &self,
device_id: DeviceId, device_id: DeviceId,
desc: &binding_model::BindGroupDescriptor, desc: &binding_model::BindGroupDescriptor,
id_in: Input<G, id::BindGroupId>, id_in: Input<G, markers::BindGroup>,
) -> (id::BindGroupId, Option<binding_model::CreateBindGroupError>) { ) -> (id::BindGroupId, Option<binding_model::CreateBindGroupError>) {
profiling::scope!("Device::create_bind_group"); profiling::scope!("Device::create_bind_group");
let hub = A::hub(self); let hub = A::hub(self);
let fid = hub.bind_groups.prepare::<G>(id_in); let fid = hub.bind_groups.prepare::<G, _>(id_in);
let error = loop { let error = loop {
let device = match hub.devices.get(device_id) { let device = match hub.devices.get(device_id) {
@ -1178,7 +1179,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
device_id: DeviceId, device_id: DeviceId,
desc: &pipeline::ShaderModuleDescriptor, desc: &pipeline::ShaderModuleDescriptor,
source: pipeline::ShaderModuleSource, source: pipeline::ShaderModuleSource,
id_in: Input<G, id::ShaderModuleId>, id_in: Input<G, markers::ShaderModule>,
) -> ( ) -> (
id::ShaderModuleId, id::ShaderModuleId,
Option<pipeline::CreateShaderModuleError>, Option<pipeline::CreateShaderModuleError>,
@ -1186,7 +1187,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
profiling::scope!("Device::create_shader_module"); profiling::scope!("Device::create_shader_module");
let hub = A::hub(self); let hub = A::hub(self);
let fid = hub.shader_modules.prepare::<G>(id_in); let fid = hub.shader_modules.prepare::<G, _>(id_in);
let error = loop { let error = loop {
let device = match hub.devices.get(device_id) { let device = match hub.devices.get(device_id) {
@ -1256,7 +1257,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
device_id: DeviceId, device_id: DeviceId,
desc: &pipeline::ShaderModuleDescriptor, desc: &pipeline::ShaderModuleDescriptor,
source: Cow<[u32]>, source: Cow<[u32]>,
id_in: Input<G, id::ShaderModuleId>, id_in: Input<G, markers::ShaderModule>,
) -> ( ) -> (
id::ShaderModuleId, id::ShaderModuleId,
Option<pipeline::CreateShaderModuleError>, Option<pipeline::CreateShaderModuleError>,
@ -1264,7 +1265,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
profiling::scope!("Device::create_shader_module"); profiling::scope!("Device::create_shader_module");
let hub = A::hub(self); let hub = A::hub(self);
let fid = hub.shader_modules.prepare::<G>(id_in); let fid = hub.shader_modules.prepare::<G, _>(id_in);
let error = loop { let error = loop {
let device = match hub.devices.get(device_id) { let device = match hub.devices.get(device_id) {
@ -1318,12 +1319,14 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
&self, &self,
device_id: DeviceId, device_id: DeviceId,
desc: &wgt::CommandEncoderDescriptor<Label>, desc: &wgt::CommandEncoderDescriptor<Label>,
id_in: Input<G, id::CommandEncoderId>, id_in: Input<G, markers::CommandEncoder>,
) -> (id::CommandEncoderId, Option<DeviceError>) { ) -> (id::CommandEncoderId, Option<DeviceError>) {
profiling::scope!("Device::create_command_encoder"); profiling::scope!("Device::create_command_encoder");
let hub = A::hub(self); let hub = A::hub(self);
let fid = hub.command_buffers.prepare::<G>(id_in); let fid = hub
.command_buffers
.prepare::<G, markers::CommandEncoder>(id_in);
let error = loop { let error = loop {
let device = match hub.devices.get(device_id) { let device = match hub.devices.get(device_id) {
@ -1359,11 +1362,11 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let (id, _) = fid.assign(command_buffer); let (id, _) = fid.assign(command_buffer);
api_log!("Device::create_command_encoder -> {id:?}"); api_log!("Device::create_command_encoder -> {id:?}");
return (id, None); return (id.transmute(), None);
}; };
let id = fid.assign_error(desc.label.borrow_or_default()); let id = fid.assign_error(desc.label.borrow_or_default());
(id, Some(error)) (id.transmute(), Some(error))
} }
pub fn command_buffer_label<A: HalApi>(&self, id: id::CommandBufferId) -> String { pub fn command_buffer_label<A: HalApi>(&self, id: id::CommandBufferId) -> String {
@ -1376,7 +1379,10 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let hub = A::hub(self); let hub = A::hub(self);
if let Some(cmd_buf) = hub.command_buffers.unregister(command_encoder_id) { if let Some(cmd_buf) = hub
.command_buffers
.unregister(command_encoder_id.transmute())
{
cmd_buf cmd_buf
.device .device
.untrack(&cmd_buf.data.lock().as_ref().unwrap().trackers); .untrack(&cmd_buf.data.lock().as_ref().unwrap().trackers);
@ -1386,7 +1392,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
pub fn command_buffer_drop<A: HalApi>(&self, command_buffer_id: id::CommandBufferId) { pub fn command_buffer_drop<A: HalApi>(&self, command_buffer_id: id::CommandBufferId) {
profiling::scope!("CommandBuffer::drop"); profiling::scope!("CommandBuffer::drop");
api_log!("CommandBuffer::drop {command_buffer_id:?}"); api_log!("CommandBuffer::drop {command_buffer_id:?}");
self.command_encoder_drop::<A>(command_buffer_id) self.command_encoder_drop::<A>(command_buffer_id.transmute())
} }
pub fn device_create_render_bundle_encoder( pub fn device_create_render_bundle_encoder(
@ -1394,7 +1400,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
device_id: DeviceId, device_id: DeviceId,
desc: &command::RenderBundleEncoderDescriptor, desc: &command::RenderBundleEncoderDescriptor,
) -> ( ) -> (
id::RenderBundleEncoderId, *mut command::RenderBundleEncoder,
Option<command::CreateRenderBundleError>, Option<command::CreateRenderBundleError>,
) { ) {
profiling::scope!("Device::create_render_bundle_encoder"); profiling::scope!("Device::create_render_bundle_encoder");
@ -1410,13 +1416,13 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
&self, &self,
bundle_encoder: command::RenderBundleEncoder, bundle_encoder: command::RenderBundleEncoder,
desc: &command::RenderBundleDescriptor, desc: &command::RenderBundleDescriptor,
id_in: Input<G, id::RenderBundleId>, id_in: Input<G, markers::RenderBundle>,
) -> (id::RenderBundleId, Option<command::RenderBundleError>) { ) -> (id::RenderBundleId, Option<command::RenderBundleError>) {
profiling::scope!("RenderBundleEncoder::finish"); profiling::scope!("RenderBundleEncoder::finish");
let hub = A::hub(self); let hub = A::hub(self);
let fid = hub.render_bundles.prepare::<G>(id_in); let fid = hub.render_bundles.prepare::<G, _>(id_in);
let error = loop { let error = loop {
let device = match hub.devices.get(bundle_encoder.parent()) { let device = match hub.devices.get(bundle_encoder.parent()) {
@ -1480,12 +1486,12 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
&self, &self,
device_id: DeviceId, device_id: DeviceId,
desc: &resource::QuerySetDescriptor, desc: &resource::QuerySetDescriptor,
id_in: Input<G, id::QuerySetId>, id_in: Input<G, markers::QuerySet>,
) -> (id::QuerySetId, Option<resource::CreateQuerySetError>) { ) -> (id::QuerySetId, Option<resource::CreateQuerySetError>) {
profiling::scope!("Device::create_query_set"); profiling::scope!("Device::create_query_set");
let hub = A::hub(self); let hub = A::hub(self);
let fid = hub.query_sets.prepare::<G>(id_in); let fid = hub.query_sets.prepare::<G, _>(id_in);
let error = loop { let error = loop {
let device = match hub.devices.get(device_id) { let device = match hub.devices.get(device_id) {
@ -1554,7 +1560,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
&self, &self,
device_id: DeviceId, device_id: DeviceId,
desc: &pipeline::RenderPipelineDescriptor, desc: &pipeline::RenderPipelineDescriptor,
id_in: Input<G, id::RenderPipelineId>, id_in: Input<G, markers::RenderPipeline>,
implicit_pipeline_ids: Option<ImplicitPipelineIds<G>>, implicit_pipeline_ids: Option<ImplicitPipelineIds<G>>,
) -> ( ) -> (
id::RenderPipelineId, id::RenderPipelineId,
@ -1564,7 +1570,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let hub = A::hub(self); let hub = A::hub(self);
let fid = hub.render_pipelines.prepare::<G>(id_in); let fid = hub.render_pipelines.prepare::<G, _>(id_in);
let implicit_context = implicit_pipeline_ids.map(|ipi| ipi.prepare(hub)); let implicit_context = implicit_pipeline_ids.map(|ipi| ipi.prepare(hub));
let implicit_error_context = implicit_context.clone(); let implicit_error_context = implicit_context.clone();
@ -1633,7 +1639,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
&self, &self,
pipeline_id: id::RenderPipelineId, pipeline_id: id::RenderPipelineId,
index: u32, index: u32,
id_in: Input<G, id::BindGroupLayoutId>, id_in: Input<G, markers::BindGroupLayout>,
) -> ( ) -> (
id::BindGroupLayoutId, id::BindGroupLayoutId,
Option<binding_model::GetBindGroupLayoutError>, Option<binding_model::GetBindGroupLayoutError>,
@ -1648,7 +1654,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let id = match pipeline.layout.bind_group_layouts.get(index as usize) { let id = match pipeline.layout.bind_group_layouts.get(index as usize) {
Some(bg) => hub Some(bg) => hub
.bind_group_layouts .bind_group_layouts
.prepare::<G>(id_in) .prepare::<G, _>(id_in)
.assign_existing(bg), .assign_existing(bg),
None => break binding_model::GetBindGroupLayoutError::InvalidGroupIndex(index), None => break binding_model::GetBindGroupLayoutError::InvalidGroupIndex(index),
}; };
@ -1657,7 +1663,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let id = hub let id = hub
.bind_group_layouts .bind_group_layouts
.prepare::<G>(id_in) .prepare::<G, _>(id_in)
.assign_error("<derived>"); .assign_error("<derived>");
(id, Some(error)) (id, Some(error))
} }
@ -1692,7 +1698,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
&self, &self,
device_id: DeviceId, device_id: DeviceId,
desc: &pipeline::ComputePipelineDescriptor, desc: &pipeline::ComputePipelineDescriptor,
id_in: Input<G, id::ComputePipelineId>, id_in: Input<G, markers::ComputePipeline>,
implicit_pipeline_ids: Option<ImplicitPipelineIds<G>>, implicit_pipeline_ids: Option<ImplicitPipelineIds<G>>,
) -> ( ) -> (
id::ComputePipelineId, id::ComputePipelineId,
@ -1702,7 +1708,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let hub = A::hub(self); let hub = A::hub(self);
let fid = hub.compute_pipelines.prepare::<G>(id_in); let fid = hub.compute_pipelines.prepare::<G, _>(id_in);
let implicit_context = implicit_pipeline_ids.map(|ipi| ipi.prepare(hub)); let implicit_context = implicit_pipeline_ids.map(|ipi| ipi.prepare(hub));
let implicit_error_context = implicit_context.clone(); let implicit_error_context = implicit_context.clone();
@ -1766,7 +1772,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
&self, &self,
pipeline_id: id::ComputePipelineId, pipeline_id: id::ComputePipelineId,
index: u32, index: u32,
id_in: Input<G, id::BindGroupLayoutId>, id_in: Input<G, markers::BindGroupLayout>,
) -> ( ) -> (
id::BindGroupLayoutId, id::BindGroupLayoutId,
Option<binding_model::GetBindGroupLayoutError>, Option<binding_model::GetBindGroupLayoutError>,
@ -1782,7 +1788,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let id = match pipeline.layout.bind_group_layouts.get(index as usize) { let id = match pipeline.layout.bind_group_layouts.get(index as usize) {
Some(bg) => hub Some(bg) => hub
.bind_group_layouts .bind_group_layouts
.prepare::<G>(id_in) .prepare::<G, _>(id_in)
.assign_existing(bg), .assign_existing(bg),
None => break binding_model::GetBindGroupLayoutError::InvalidGroupIndex(index), None => break binding_model::GetBindGroupLayoutError::InvalidGroupIndex(index),
}; };
@ -1792,7 +1798,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let id = hub let id = hub
.bind_group_layouts .bind_group_layouts
.prepare::<G>(id_in) .prepare::<G, _>(id_in)
.assign_error("<derived>"); .assign_error("<derived>");
(id, Some(error)) (id, Some(error))
} }
@ -2118,7 +2124,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let (closures, queue_empty) = { let (closures, queue_empty) = {
if let wgt::Maintain::WaitForSubmissionIndex(submission_index) = maintain { if let wgt::Maintain::WaitForSubmissionIndex(submission_index) = maintain {
if submission_index.queue_id != device_id { if submission_index.queue_id != device_id.transmute() {
return Err(WaitIdleError::WrongSubmissionIndex( return Err(WaitIdleError::WrongSubmissionIndex(
submission_index.queue_id, submission_index.queue_id,
device_id, device_id,

View File

@ -7,7 +7,7 @@ use crate::{
}, },
hal_api::HalApi, hal_api::HalApi,
id::{ id::{
self, BindGroupId, BindGroupLayoutId, BufferId, ComputePipelineId, PipelineLayoutId, self, BindGroupId, BindGroupLayoutId, BufferId, ComputePipelineId, Id, PipelineLayoutId,
QuerySetId, RenderBundleId, RenderPipelineId, SamplerId, StagingBufferId, TextureId, QuerySetId, RenderBundleId, RenderPipelineId, SamplerId, StagingBufferId, TextureId,
TextureViewId, TextureViewId,
}, },
@ -419,15 +419,14 @@ impl<A: HalApi> LifetimeTracker<A> {
} }
impl<A: HalApi> LifetimeTracker<A> { impl<A: HalApi> LifetimeTracker<A> {
fn triage_resources<Id, R>( fn triage_resources<R>(
resources_map: &mut FastHashMap<Id, Arc<R>>, resources_map: &mut FastHashMap<Id<R::Marker>, Arc<R>>,
active: &mut [ActiveSubmission<A>], active: &mut [ActiveSubmission<A>],
trackers: &mut impl ResourceTracker<Id, R>, trackers: &mut impl ResourceTracker<R>,
get_resource_map: impl Fn(&mut ResourceMaps<A>) -> &mut FastHashMap<Id, Arc<R>>, get_resource_map: impl Fn(&mut ResourceMaps<A>) -> &mut FastHashMap<Id<R::Marker>, Arc<R>>,
) -> Vec<Arc<R>> ) -> Vec<Arc<R>>
where where
Id: id::TypedId, R: Resource,
R: Resource<Id>,
{ {
let mut removed_resources = Vec::new(); let mut removed_resources = Vec::new();
resources_map.retain(|&id, resource| { resources_map.retain(|&id, resource| {

View File

@ -2,7 +2,8 @@ use crate::{
binding_model, binding_model,
hal_api::HalApi, hal_api::HalApi,
hub::Hub, hub::Hub,
id::{self}, id,
id::markers,
identity::{GlobalIdentityHandlerFactory, Input}, identity::{GlobalIdentityHandlerFactory, Input},
resource::{Buffer, BufferAccessResult}, resource::{Buffer, BufferAccessResult},
resource::{BufferAccessError, BufferMapOperation}, resource::{BufferAccessError, BufferMapOperation},
@ -463,18 +464,18 @@ pub struct ImplicitPipelineContext {
} }
pub struct ImplicitPipelineIds<'a, G: GlobalIdentityHandlerFactory> { pub struct ImplicitPipelineIds<'a, G: GlobalIdentityHandlerFactory> {
pub root_id: Input<G, id::PipelineLayoutId>, pub root_id: Input<G, markers::PipelineLayout>,
pub group_ids: &'a [Input<G, id::BindGroupLayoutId>], pub group_ids: &'a [Input<G, markers::BindGroupLayout>],
} }
impl<G: GlobalIdentityHandlerFactory> ImplicitPipelineIds<'_, G> { impl<G: GlobalIdentityHandlerFactory> ImplicitPipelineIds<'_, G> {
fn prepare<A: HalApi>(self, hub: &Hub<A>) -> ImplicitPipelineContext { fn prepare<A: HalApi>(self, hub: &Hub<A>) -> ImplicitPipelineContext {
ImplicitPipelineContext { ImplicitPipelineContext {
root_id: hub.pipeline_layouts.prepare::<G>(self.root_id).into_id(), root_id: hub.pipeline_layouts.prepare::<G, _>(self.root_id).into_id(),
group_ids: self group_ids: self
.group_ids .group_ids
.iter() .iter()
.map(|id_in| hub.bind_group_layouts.prepare::<G>(*id_in).into_id()) .map(|id_in| hub.bind_group_layouts.prepare::<G, _>(*id_in).into_id())
.collect(), .collect(),
} }
} }

View File

@ -12,6 +12,7 @@ use crate::{
global::Global, global::Global,
hal_api::HalApi, hal_api::HalApi,
hal_label, hal_label,
id::markers,
id::{self, QueueId}, id::{self, QueueId},
identity::{GlobalIdentityHandlerFactory, Input}, identity::{GlobalIdentityHandlerFactory, Input},
init_tracker::{has_copy_partial_init_tracker_coverage, TextureInitRange}, init_tracker::{has_copy_partial_init_tracker_coverage, TextureInitRange},
@ -37,17 +38,19 @@ use super::Device;
pub struct Queue<A: HalApi> { pub struct Queue<A: HalApi> {
pub device: Option<Arc<Device<A>>>, pub device: Option<Arc<Device<A>>>,
pub raw: Option<A::Queue>, pub raw: Option<A::Queue>,
pub info: ResourceInfo<QueueId>, pub info: ResourceInfo<Queue<A>>,
} }
impl<A: HalApi> Resource<QueueId> for Queue<A> { impl<A: HalApi> Resource for Queue<A> {
const TYPE: ResourceType = "Queue"; const TYPE: ResourceType = "Queue";
fn as_info(&self) -> &ResourceInfo<QueueId> { type Marker = crate::id::markers::Queue;
fn as_info(&self) -> &ResourceInfo<Self> {
&self.info &self.info
} }
fn as_info_mut(&mut self) -> &mut ResourceInfo<QueueId> { fn as_info_mut(&mut self) -> &mut ResourceInfo<Self> {
&mut self.info &mut self.info
} }
} }
@ -436,7 +439,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
&self, &self,
queue_id: QueueId, queue_id: QueueId,
buffer_size: wgt::BufferSize, buffer_size: wgt::BufferSize,
id_in: Input<G, id::StagingBufferId>, id_in: Input<G, markers::StagingBuffer>,
) -> Result<(id::StagingBufferId, *mut u8), QueueWriteError> { ) -> Result<(id::StagingBufferId, *mut u8), QueueWriteError> {
profiling::scope!("Queue::create_staging_buffer"); profiling::scope!("Queue::create_staging_buffer");
let hub = A::hub(self); let hub = A::hub(self);
@ -451,7 +454,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let (staging_buffer, staging_buffer_ptr) = let (staging_buffer, staging_buffer_ptr) =
prepare_staging_buffer(device, buffer_size.get(), device.instance_flags)?; prepare_staging_buffer(device, buffer_size.get(), device.instance_flags)?;
let fid = hub.staging_buffers.prepare::<G>(id_in); let fid = hub.staging_buffers.prepare::<G, _>(id_in);
let (id, _) = fid.assign(staging_buffer); let (id, _) = fid.assign(staging_buffer);
resource_log!("Queue::create_staging_buffer {id:?}"); resource_log!("Queue::create_staging_buffer {id:?}");
@ -669,7 +672,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
.get(destination.texture) .get(destination.texture)
.map_err(|_| TransferError::InvalidTexture(destination.texture))?; .map_err(|_| TransferError::InvalidTexture(destination.texture))?;
if dst.device.as_info().id() != queue_id { if dst.device.as_info().id() != queue_id.transmute() {
return Err(DeviceError::WrongDevice.into()); return Err(DeviceError::WrongDevice.into());
} }
@ -1150,7 +1153,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
Err(_) => continue, Err(_) => continue,
}; };
if cmdbuf.device.as_info().id() != queue_id { if cmdbuf.device.as_info().id() != queue_id.transmute() {
return Err(DeviceError::WrongDevice.into()); return Err(DeviceError::WrongDevice.into());
} }

View File

@ -12,7 +12,7 @@ use crate::{
hal_api::HalApi, hal_api::HalApi,
hal_label, hal_label,
hub::Hub, hub::Hub,
id::{self, DeviceId, QueueId}, id::QueueId,
init_tracker::{ init_tracker::{
BufferInitTracker, BufferInitTrackerAction, MemoryInitKind, TextureInitRange, BufferInitTracker, BufferInitTrackerAction, MemoryInitKind, TextureInitRange,
TextureInitTracker, TextureInitTrackerAction, TextureInitTracker, TextureInitTrackerAction,
@ -90,7 +90,7 @@ pub struct Device<A: HalApi> {
pub(crate) queue_id: RwLock<Option<QueueId>>, pub(crate) queue_id: RwLock<Option<QueueId>>,
queue_to_drop: RwLock<Option<A::Queue>>, queue_to_drop: RwLock<Option<A::Queue>>,
pub(crate) zero_buffer: Option<A::Buffer>, pub(crate) zero_buffer: Option<A::Buffer>,
pub(crate) info: ResourceInfo<DeviceId>, pub(crate) info: ResourceInfo<Device<A>>,
pub(crate) command_allocator: Mutex<Option<CommandAllocator<A>>>, pub(crate) command_allocator: Mutex<Option<CommandAllocator<A>>>,
//Note: The submission index here corresponds to the last submission that is done. //Note: The submission index here corresponds to the last submission that is done.
@ -1785,7 +1785,7 @@ impl<A: HalApi> Device<A> {
dynamic_binding_info: &mut Vec<binding_model::BindGroupDynamicBindingData>, dynamic_binding_info: &mut Vec<binding_model::BindGroupDynamicBindingData>,
late_buffer_binding_sizes: &mut FastHashMap<u32, wgt::BufferSize>, late_buffer_binding_sizes: &mut FastHashMap<u32, wgt::BufferSize>,
used: &mut BindGroupStates<A>, used: &mut BindGroupStates<A>,
storage: &'a Storage<Buffer<A>, id::BufferId>, storage: &'a Storage<Buffer<A>>,
limits: &wgt::Limits, limits: &wgt::Limits,
snatch_guard: &'a SnatchGuard<'a>, snatch_guard: &'a SnatchGuard<'a>,
) -> Result<hal::BufferBinding<'a, A>, binding_model::CreateBindGroupError> { ) -> Result<hal::BufferBinding<'a, A>, binding_model::CreateBindGroupError> {
@ -2386,7 +2386,7 @@ impl<A: HalApi> Device<A> {
pub(crate) fn create_pipeline_layout( pub(crate) fn create_pipeline_layout(
self: &Arc<Self>, self: &Arc<Self>,
desc: &binding_model::PipelineLayoutDescriptor, desc: &binding_model::PipelineLayoutDescriptor,
bgl_registry: &Registry<id::BindGroupLayoutId, BindGroupLayout<A>>, bgl_registry: &Registry<BindGroupLayout<A>>,
) -> Result<binding_model::PipelineLayout<A>, binding_model::CreatePipelineLayoutError> { ) -> Result<binding_model::PipelineLayout<A>, binding_model::CreatePipelineLayoutError> {
use crate::binding_model::CreatePipelineLayoutError as Error; use crate::binding_model::CreatePipelineLayoutError as Error;
@ -2499,8 +2499,8 @@ impl<A: HalApi> Device<A> {
self: &Arc<Self>, self: &Arc<Self>,
implicit_context: Option<ImplicitPipelineContext>, implicit_context: Option<ImplicitPipelineContext>,
mut derived_group_layouts: ArrayVec<bgl::EntryMap, { hal::MAX_BIND_GROUPS }>, mut derived_group_layouts: ArrayVec<bgl::EntryMap, { hal::MAX_BIND_GROUPS }>,
bgl_registry: &Registry<id::BindGroupLayoutId, BindGroupLayout<A>>, bgl_registry: &Registry<BindGroupLayout<A>>,
pipeline_layout_registry: &Registry<id::PipelineLayoutId, binding_model::PipelineLayout<A>>, pipeline_layout_registry: &Registry<binding_model::PipelineLayout<A>>,
) -> Result<Arc<binding_model::PipelineLayout<A>>, pipeline::ImplicitLayoutError> { ) -> Result<Arc<binding_model::PipelineLayout<A>>, pipeline::ImplicitLayoutError> {
while derived_group_layouts while derived_group_layouts
.last() .last()
@ -3440,14 +3440,16 @@ impl<A: HalApi> Device<A> {
} }
} }
impl<A: HalApi> Resource<DeviceId> for Device<A> { impl<A: HalApi> Resource for Device<A> {
const TYPE: ResourceType = "Device"; const TYPE: ResourceType = "Device";
fn as_info(&self) -> &ResourceInfo<DeviceId> { type Marker = crate::id::markers::Device;
fn as_info(&self) -> &ResourceInfo<Self> {
&self.info &self.info
} }
fn as_info_mut(&mut self) -> &mut ResourceInfo<DeviceId> { fn as_info_mut(&mut self) -> &mut ResourceInfo<Self> {
&mut self.info &mut self.info
} }
} }

View File

@ -5,7 +5,6 @@ use wgt::Backend;
use crate::{ use crate::{
hal_api::HalApi, hal_api::HalApi,
hub::{HubReport, Hubs}, hub::{HubReport, Hubs},
id::SurfaceId,
identity::GlobalIdentityHandlerFactory, identity::GlobalIdentityHandlerFactory,
instance::{Instance, Surface}, instance::{Instance, Surface},
registry::{Registry, RegistryReport}, registry::{Registry, RegistryReport},
@ -47,7 +46,7 @@ impl GlobalReport {
pub struct Global<G: GlobalIdentityHandlerFactory> { pub struct Global<G: GlobalIdentityHandlerFactory> {
pub instance: Instance, pub instance: Instance,
pub surfaces: Registry<SurfaceId, Surface>, pub surfaces: Registry<Surface>,
pub(crate) hubs: Hubs, pub(crate) hubs: Hubs,
_phantom: PhantomData<G>, _phantom: PhantomData<G>,
} }

View File

@ -2,10 +2,13 @@
The `wgpu_core` API uses identifiers of type [`Id<R>`] to refer to The `wgpu_core` API uses identifiers of type [`Id<R>`] to refer to
resources of type `R`. For example, [`id::DeviceId`] is an alias for resources of type `R`. For example, [`id::DeviceId`] is an alias for
`Id<Device<Empty>>`, and [`id::BufferId`] is an alias for `Id<markers::Device>`, and [`id::BufferId`] is an alias for
`Id<Buffer<Empty>>`. `Id` implements `Copy`, `Hash`, `Eq`, `Ord`, and `Id<markers::Buffer>`. `Id` implements `Copy`, `Hash`, `Eq`, `Ord`, and
of course `Debug`. of course `Debug`.
[`id::DeviceId`]: crate::id::DeviceId
[`id::BufferId`]: crate::id::BufferId
Each `Id` contains not only an index for the resource it denotes but Each `Id` contains not only an index for the resource it denotes but
also a Backend indicating which `wgpu` backend it belongs to. You also a Backend indicating which `wgpu` backend it belongs to. You
can use the [`gfx_select`] macro to dynamically dispatch on an id's can use the [`gfx_select`] macro to dynamically dispatch on an id's
@ -43,7 +46,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
&self, &self,
device_id: id::DeviceId, device_id: id::DeviceId,
desc: &resource::BufferDescriptor, desc: &resource::BufferDescriptor,
id_in: Input<G, id::BufferId>, id_in: Input<G>,
) -> (id::BufferId, Option<resource::CreateBufferError>) { ) -> (id::BufferId, Option<resource::CreateBufferError>) {
/* ... */ /* ... */
} }
@ -115,7 +118,6 @@ use crate::{
command::{CommandBuffer, RenderBundle}, command::{CommandBuffer, RenderBundle},
device::{queue::Queue, Device}, device::{queue::Queue, Device},
hal_api::HalApi, hal_api::HalApi,
id,
identity::GlobalIdentityHandlerFactory, identity::GlobalIdentityHandlerFactory,
instance::{Adapter, HalSurface, Surface}, instance::{Adapter, HalSurface, Surface},
pipeline::{ComputePipeline, RenderPipeline, ShaderModule}, pipeline::{ComputePipeline, RenderPipeline, ShaderModule},
@ -177,23 +179,23 @@ impl HubReport {
/// ///
/// [`A::hub(global)`]: HalApi::hub /// [`A::hub(global)`]: HalApi::hub
pub struct Hub<A: HalApi> { pub struct Hub<A: HalApi> {
pub adapters: Registry<id::AdapterId, Adapter<A>>, pub adapters: Registry<Adapter<A>>,
pub devices: Registry<id::DeviceId, Device<A>>, pub devices: Registry<Device<A>>,
pub queues: Registry<id::QueueId, Queue<A>>, pub queues: Registry<Queue<A>>,
pub pipeline_layouts: Registry<id::PipelineLayoutId, PipelineLayout<A>>, pub pipeline_layouts: Registry<PipelineLayout<A>>,
pub shader_modules: Registry<id::ShaderModuleId, ShaderModule<A>>, pub shader_modules: Registry<ShaderModule<A>>,
pub bind_group_layouts: Registry<id::BindGroupLayoutId, BindGroupLayout<A>>, pub bind_group_layouts: Registry<BindGroupLayout<A>>,
pub bind_groups: Registry<id::BindGroupId, BindGroup<A>>, pub bind_groups: Registry<BindGroup<A>>,
pub command_buffers: Registry<id::CommandBufferId, CommandBuffer<A>>, pub command_buffers: Registry<CommandBuffer<A>>,
pub render_bundles: Registry<id::RenderBundleId, RenderBundle<A>>, pub render_bundles: Registry<RenderBundle<A>>,
pub render_pipelines: Registry<id::RenderPipelineId, RenderPipeline<A>>, pub render_pipelines: Registry<RenderPipeline<A>>,
pub compute_pipelines: Registry<id::ComputePipelineId, ComputePipeline<A>>, pub compute_pipelines: Registry<ComputePipeline<A>>,
pub query_sets: Registry<id::QuerySetId, QuerySet<A>>, pub query_sets: Registry<QuerySet<A>>,
pub buffers: Registry<id::BufferId, Buffer<A>>, pub buffers: Registry<Buffer<A>>,
pub staging_buffers: Registry<id::StagingBufferId, StagingBuffer<A>>, pub staging_buffers: Registry<StagingBuffer<A>>,
pub textures: Registry<id::TextureId, Texture<A>>, pub textures: Registry<Texture<A>>,
pub texture_views: Registry<id::TextureViewId, TextureView<A>>, pub texture_views: Registry<TextureView<A>>,
pub samplers: Registry<id::SamplerId, Sampler<A>>, pub samplers: Registry<Sampler<A>>,
} }
impl<A: HalApi> Hub<A> { impl<A: HalApi> Hub<A> {
@ -222,11 +224,7 @@ impl<A: HalApi> Hub<A> {
//TODO: instead of having a hacky `with_adapters` parameter, //TODO: instead of having a hacky `with_adapters` parameter,
// we should have `clear_device(device_id)` that specifically destroys // we should have `clear_device(device_id)` that specifically destroys
// everything related to a logical device. // everything related to a logical device.
pub(crate) fn clear( pub(crate) fn clear(&self, surface_guard: &Storage<Surface>, with_adapters: bool) {
&self,
surface_guard: &Storage<Surface, id::SurfaceId>,
with_adapters: bool,
) {
use hal::Surface; use hal::Surface;
let mut devices = self.devices.write(); let mut devices = self.devices.write();

View File

@ -1,6 +1,5 @@
use crate::{Epoch, Index}; use crate::{Epoch, Index};
use std::{ use std::{
any::Any,
cmp::Ordering, cmp::Ordering,
fmt::{self, Debug}, fmt::{self, Debug},
hash::Hash, hash::Hash,
@ -9,15 +8,74 @@ use std::{
use wgt::{Backend, WasmNotSendSync}; use wgt::{Backend, WasmNotSendSync};
type IdType = u64; type IdType = u64;
type NonZeroId = std::num::NonZeroU64;
type ZippedIndex = Index; type ZippedIndex = Index;
type NonZeroId = std::num::NonZeroU64;
const INDEX_BITS: usize = std::mem::size_of::<ZippedIndex>() * 8; const INDEX_BITS: usize = std::mem::size_of::<ZippedIndex>() * 8;
const EPOCH_BITS: usize = INDEX_BITS - BACKEND_BITS; const EPOCH_BITS: usize = INDEX_BITS - BACKEND_BITS;
const BACKEND_BITS: usize = 3; const BACKEND_BITS: usize = 3;
const BACKEND_SHIFT: usize = INDEX_BITS * 2 - BACKEND_BITS; const BACKEND_SHIFT: usize = INDEX_BITS * 2 - BACKEND_BITS;
pub const EPOCH_MASK: u32 = (1 << (EPOCH_BITS)) - 1; pub const EPOCH_MASK: u32 = (1 << (EPOCH_BITS)) - 1;
type Dummy = hal::api::Empty;
/// The raw underlying representation of an identifier.
#[repr(transparent)]
#[cfg_attr(any(feature = "serde", feature = "trace"), derive(serde::Serialize))]
#[cfg_attr(any(feature = "serde", feature = "replay"), derive(serde::Deserialize))]
#[cfg_attr(feature = "trace", serde(into = "SerialId"))]
#[cfg_attr(feature = "replay", serde(from = "SerialId"))]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct RawId(NonZeroId);
impl RawId {
#[doc(hidden)]
#[inline]
pub fn from_non_zero(non_zero: NonZeroId) -> Self {
Self(non_zero)
}
#[doc(hidden)]
#[inline]
pub fn into_non_zero(self) -> NonZeroId {
self.0
}
/// Zip together an identifier and return its raw underlying representation.
pub fn zip(index: Index, epoch: Epoch, backend: Backend) -> RawId {
assert_eq!(0, epoch >> EPOCH_BITS);
assert_eq!(0, (index as IdType) >> INDEX_BITS);
let v = index as IdType
| ((epoch as IdType) << INDEX_BITS)
| ((backend as IdType) << BACKEND_SHIFT);
Self(NonZeroId::new(v).unwrap())
}
/// Unzip a raw identifier into its components.
#[allow(trivial_numeric_casts)]
pub fn unzip(self) -> (Index, Epoch, Backend) {
(
(self.0.get() as ZippedIndex) as Index,
(((self.0.get() >> INDEX_BITS) as ZippedIndex) & (EPOCH_MASK as ZippedIndex)) as Index,
self.backend(),
)
}
pub fn backend(self) -> Backend {
match self.0.get() >> (BACKEND_SHIFT) as u8 {
0 => Backend::Empty,
1 => Backend::Vulkan,
2 => Backend::Metal,
3 => Backend::Dx12,
4 => Backend::Gl,
_ => unreachable!(),
}
}
}
/// Coerce a slice of identifiers into a slice of raw identifiers.
pub fn into_raw_slice<T: Marker>(ids: &[Id<T>]) -> &[RawId] {
// SAFETY: Any Id<T> is repr(transparent) over `RawId`.
unsafe { std::slice::from_raw_parts(ids.as_ptr().cast(), ids.len()) }
}
/// An identifier for a wgpu object. /// An identifier for a wgpu object.
/// ///
@ -49,21 +107,13 @@ type Dummy = hal::api::Empty;
/// [`Registry`]: crate::hub::Registry /// [`Registry`]: crate::hub::Registry
/// [`Empty`]: hal::api::Empty /// [`Empty`]: hal::api::Empty
#[repr(transparent)] #[repr(transparent)]
#[cfg_attr(feature = "trace", derive(serde::Serialize), serde(into = "SerialId"))] #[cfg_attr(any(feature = "serde", feature = "trace"), derive(serde::Serialize))]
#[cfg_attr(any(feature = "serde", feature = "replay"), derive(serde::Deserialize))]
#[cfg_attr( #[cfg_attr(
feature = "replay", any(feature = "serde", feature = "trace", feature = "replay"),
derive(serde::Deserialize), serde(transparent)
serde(from = "SerialId")
)] )]
#[cfg_attr( pub struct Id<T: Marker>(RawId, PhantomData<T>);
all(feature = "serde", not(feature = "trace")),
derive(serde::Serialize)
)]
#[cfg_attr(
all(feature = "serde", not(feature = "replay")),
derive(serde::Deserialize)
)]
pub struct Id<T: 'static + WasmNotSendSync>(NonZeroId, PhantomData<T>);
// This type represents Id in a more readable (and editable) way. // This type represents Id in a more readable (and editable) way.
#[allow(dead_code)] #[allow(dead_code)]
@ -72,39 +122,40 @@ enum SerialId {
// The only variant forces RON to not ignore "Id" // The only variant forces RON to not ignore "Id"
Id(Index, Epoch, Backend), Id(Index, Epoch, Backend),
} }
#[cfg(feature = "trace")] #[cfg(feature = "trace")]
impl<T> From<Id<T>> for SerialId impl From<RawId> for SerialId {
where fn from(id: RawId) -> Self {
T: 'static + WasmNotSendSync,
{
fn from(id: Id<T>) -> Self {
let (index, epoch, backend) = id.unzip(); let (index, epoch, backend) = id.unzip();
Self::Id(index, epoch, backend) Self::Id(index, epoch, backend)
} }
} }
#[cfg(feature = "replay")] #[cfg(feature = "replay")]
impl<T> From<SerialId> for Id<T> impl From<SerialId> for RawId {
where
T: 'static + WasmNotSendSync,
{
fn from(id: SerialId) -> Self { fn from(id: SerialId) -> Self {
match id { match id {
SerialId::Id(index, epoch, backend) => TypedId::zip(index, epoch, backend), SerialId::Id(index, epoch, backend) => RawId::zip(index, epoch, backend),
} }
} }
} }
impl<T> Id<T> impl<T> Id<T>
where where
T: 'static + WasmNotSendSync, T: Marker,
{ {
/// # Safety /// # Safety
/// ///
/// The raw id must be valid for the type. /// The raw id must be valid for the type.
pub unsafe fn from_raw(raw: NonZeroId) -> Self { pub unsafe fn from_raw(raw: RawId) -> Self {
Self(raw, PhantomData) Self(raw, PhantomData)
} }
/// Coerce the identifiers into its raw underlying representation.
pub fn into_raw(self) -> RawId {
self.0
}
#[allow(dead_code)] #[allow(dead_code)]
pub(crate) fn dummy(index: u32) -> Self { pub(crate) fn dummy(index: u32) -> Self {
Id::zip(index, 1, Backend::Empty) Id::zip(index, 1, Backend::Empty)
@ -115,24 +166,53 @@ where
self.backend() != Backend::Empty self.backend() != Backend::Empty
} }
/// Get the backend this identifier corresponds to.
#[inline]
pub fn backend(self) -> Backend { pub fn backend(self) -> Backend {
match self.0.get() >> (BACKEND_SHIFT) as u8 { self.0.backend()
0 => Backend::Empty, }
1 => Backend::Vulkan,
2 => Backend::Metal, /// Transmute this identifier to one with a different marker trait.
3 => Backend::Dx12, ///
4 => Backend::Gl, /// Legal use is governed through a sealed trait, however it's correctness
_ => unreachable!(), /// depends on the current implementation of `wgpu-core`.
} #[inline]
pub const fn transmute<U: self::transmute::Transmute<T>>(self) -> Id<U> {
Id(self.0, PhantomData)
}
#[inline]
pub fn zip(index: Index, epoch: Epoch, backend: Backend) -> Self {
Id(RawId::zip(index, epoch, backend), PhantomData)
}
#[inline]
pub fn unzip(self) -> (Index, Epoch, Backend) {
self.0.unzip()
} }
} }
impl<T> Copy for Id<T> where T: 'static + WasmNotSendSync {} pub(crate) mod transmute {
// This trait is effectively sealed to prevent illegal transmutes.
pub trait Transmute<U>: super::Marker {}
// Self-transmute is always legal.
impl<T> Transmute<T> for T where T: super::Marker {}
// TODO: Remove these once queues have their own identifiers.
impl Transmute<super::markers::Queue> for super::markers::Device {}
impl Transmute<super::markers::Device> for super::markers::Queue {}
impl Transmute<super::markers::CommandBuffer> for super::markers::CommandEncoder {}
impl Transmute<super::markers::CommandEncoder> for super::markers::CommandBuffer {}
}
impl<T> Copy for Id<T> where T: Marker {}
impl<T> Clone for Id<T> impl<T> Clone for Id<T>
where where
T: 'static + WasmNotSendSync, T: Marker,
{ {
#[inline]
fn clone(&self) -> Self { fn clone(&self) -> Self {
*self *self
} }
@ -140,7 +220,7 @@ where
impl<T> Debug for Id<T> impl<T> Debug for Id<T>
where where
T: 'static + WasmNotSendSync, T: Marker,
{ {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
let (index, epoch, backend) = self.unzip(); let (index, epoch, backend) = self.unzip();
@ -159,8 +239,9 @@ where
impl<T> Hash for Id<T> impl<T> Hash for Id<T>
where where
T: 'static + WasmNotSendSync, T: Marker,
{ {
#[inline]
fn hash<H: std::hash::Hasher>(&self, state: &mut H) { fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.0.hash(state); self.0.hash(state);
} }
@ -168,19 +249,21 @@ where
impl<T> PartialEq for Id<T> impl<T> PartialEq for Id<T>
where where
T: 'static + WasmNotSendSync, T: Marker,
{ {
#[inline]
fn eq(&self, other: &Self) -> bool { fn eq(&self, other: &Self) -> bool {
self.0 == other.0 self.0 == other.0
} }
} }
impl<T> Eq for Id<T> where T: 'static + WasmNotSendSync {} impl<T> Eq for Id<T> where T: Marker {}
impl<T> PartialOrd for Id<T> impl<T> PartialOrd for Id<T>
where where
T: 'static + WasmNotSendSync, T: Marker,
{ {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> { fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.0.partial_cmp(&other.0) self.0.partial_cmp(&other.0)
} }
@ -188,78 +271,73 @@ where
impl<T> Ord for Id<T> impl<T> Ord for Id<T>
where where
T: 'static + WasmNotSendSync, T: Marker,
{ {
#[inline]
fn cmp(&self, other: &Self) -> Ordering { fn cmp(&self, other: &Self) -> Ordering {
self.0.cmp(&other.0) self.0.cmp(&other.0)
} }
} }
/// Trait carrying methods for direct `Id` access. /// Marker trait used to determine which types uniquely identify a resource.
/// ///
/// Most `wgpu-core` clients should not use this trait. Unusual clients that /// For example, `Device<A>` will have the same type of identifier as
/// need to construct `Id` values directly, or access their components, like the /// `Device<B>` because `Device<T>` for any `T` defines the same maker type.
/// WGPU recording player, may use this trait to do so. pub trait Marker: 'static + WasmNotSendSync {}
pub trait TypedId: Copy + Debug + Any + 'static + WasmNotSendSync + Eq + Hash {
fn zip(index: Index, epoch: Epoch, backend: Backend) -> Self;
fn unzip(self) -> (Index, Epoch, Backend);
fn into_raw(self) -> NonZeroId;
}
#[allow(trivial_numeric_casts)] // This allows `()` to be used as a marker type for tests.
impl<T> TypedId for Id<T> //
where // We don't want these in production code, since they essentially remove type
T: 'static + WasmNotSendSync, // safety, like how identifiers across different types can be compared.
{ #[cfg(test)]
fn zip(index: Index, epoch: Epoch, backend: Backend) -> Self { impl Marker for () {}
assert_eq!(0, epoch >> EPOCH_BITS);
assert_eq!(0, (index as IdType) >> INDEX_BITS);
let v = index as IdType
| ((epoch as IdType) << INDEX_BITS)
| ((backend as IdType) << BACKEND_SHIFT);
Id(NonZeroId::new(v).unwrap(), PhantomData)
}
fn unzip(self) -> (Index, Epoch, Backend) { /// Define identifiers for each resource.
( macro_rules! ids {
(self.0.get() as ZippedIndex) as Index, ($(
(((self.0.get() >> INDEX_BITS) as ZippedIndex) & (EPOCH_MASK as ZippedIndex)) as Index, $(#[$($meta:meta)*])*
self.backend(), pub type $name:ident $marker:ident;
) )*) => {
} /// Marker types for each resource.
pub mod markers {
$(
#[derive(Debug)]
pub enum $marker {}
impl super::Marker for $marker {}
)*
}
fn into_raw(self) -> NonZeroId { $(
self.0 $(#[$($meta)*])*
pub type $name = Id<self::markers::$marker>;
)*
} }
} }
pub type AdapterId = Id<crate::instance::Adapter<Dummy>>; ids! {
pub type SurfaceId = Id<crate::instance::Surface>; pub type AdapterId Adapter;
// Device pub type SurfaceId Surface;
pub type DeviceId = Id<crate::device::Device<Dummy>>; pub type DeviceId Device;
pub type QueueId = DeviceId; pub type QueueId Queue;
// Resource pub type BufferId Buffer;
pub type BufferId = Id<crate::resource::Buffer<Dummy>>; pub type StagingBufferId StagingBuffer;
pub type StagingBufferId = Id<crate::resource::StagingBuffer<Dummy>>; pub type TextureViewId TextureView;
pub type TextureViewId = Id<crate::resource::TextureView<Dummy>>; pub type TextureId Texture;
pub type TextureId = Id<crate::resource::Texture<Dummy>>; pub type SamplerId Sampler;
pub type SamplerId = Id<crate::resource::Sampler<Dummy>>; pub type BindGroupLayoutId BindGroupLayout;
// Binding model pub type PipelineLayoutId PipelineLayout;
pub type BindGroupLayoutId = Id<crate::binding_model::BindGroupLayout<Dummy>>; pub type BindGroupId BindGroup;
pub type PipelineLayoutId = Id<crate::binding_model::PipelineLayout<Dummy>>; pub type ShaderModuleId ShaderModule;
pub type BindGroupId = Id<crate::binding_model::BindGroup<Dummy>>; pub type RenderPipelineId RenderPipeline;
// Pipeline pub type ComputePipelineId ComputePipeline;
pub type ShaderModuleId = Id<crate::pipeline::ShaderModule<Dummy>>; pub type CommandEncoderId CommandEncoder;
pub type RenderPipelineId = Id<crate::pipeline::RenderPipeline<Dummy>>; pub type CommandBufferId CommandBuffer;
pub type ComputePipelineId = Id<crate::pipeline::ComputePipeline<Dummy>>; pub type RenderPassEncoderId RenderPassEncoder;
// Command pub type ComputePassEncoderId ComputePassEncoder;
pub type CommandEncoderId = CommandBufferId; pub type RenderBundleEncoderId RenderBundleEncoder;
pub type CommandBufferId = Id<crate::command::CommandBuffer<Dummy>>; pub type RenderBundleId RenderBundle;
pub type RenderPassEncoderId = *mut crate::command::RenderPass; pub type QuerySetId QuerySet;
pub type ComputePassEncoderId = *mut crate::command::ComputePass; }
pub type RenderBundleEncoderId = *mut crate::command::RenderBundleEncoder;
pub type RenderBundleId = Id<crate::command::RenderBundle<Dummy>>;
pub type QuerySetId = Id<crate::resource::QuerySet<Dummy>>;
#[test] #[test]
fn test_id_backend() { fn test_id_backend() {
@ -270,7 +348,7 @@ fn test_id_backend() {
Backend::Dx12, Backend::Dx12,
Backend::Gl, Backend::Gl,
] { ] {
let id: Id<()> = Id::zip(1, 0, b); let id = crate::id::Id::<()>::zip(1, 0, b);
let (_id, _epoch, backend) = id.unzip(); let (_id, _epoch, backend) = id.unzip();
assert_eq!(id.backend(), b); assert_eq!(id.backend(), b);
assert_eq!(backend, b); assert_eq!(backend, b);
@ -292,7 +370,7 @@ fn test_id() {
for &i in &indexes { for &i in &indexes {
for &e in &epochs { for &e in &epochs {
for &b in &backends { for &b in &backends {
let id: Id<()> = Id::zip(i, e, b); let id = crate::id::Id::<()>::zip(i, e, b);
let (index, epoch, backend) = id.unzip(); let (index, epoch, backend) = id.unzip();
assert_eq!(index, i); assert_eq!(index, i);
assert_eq!(epoch, e); assert_eq!(epoch, e);

View File

@ -2,7 +2,7 @@ use parking_lot::Mutex;
use wgt::Backend; use wgt::Backend;
use crate::{ use crate::{
id::{self}, id::{self, Id, Marker},
Epoch, FastHashMap, Index, Epoch, FastHashMap, Index,
}; };
use std::{fmt::Debug, marker::PhantomData, sync::Arc}; use std::{fmt::Debug, marker::PhantomData, sync::Arc};
@ -47,10 +47,10 @@ impl IdentityValues {
/// ///
/// The backend is incorporated into the id, so that ids allocated with /// The backend is incorporated into the id, so that ids allocated with
/// different `backend` values are always distinct. /// different `backend` values are always distinct.
pub fn alloc<I: id::TypedId>(&mut self, backend: Backend) -> I { pub fn alloc<T: Marker>(&mut self, backend: Backend) -> Id<T> {
self.count += 1; self.count += 1;
match self.free.pop() { match self.free.pop() {
Some((index, epoch)) => I::zip(index, epoch + 1, backend), Some((index, epoch)) => Id::zip(index, epoch + 1, backend),
None => { None => {
let epoch = 1; let epoch = 1;
let used = self.used.entry(epoch).or_insert_with(Default::default); let used = self.used.entry(epoch).or_insert_with(Default::default);
@ -60,12 +60,12 @@ impl IdentityValues {
0 0
}; };
used.push(index); used.push(index);
I::zip(index, epoch, backend) Id::zip(index, epoch, backend)
} }
} }
} }
pub fn mark_as_used<I: id::TypedId>(&mut self, id: I) -> I { pub fn mark_as_used<T: Marker>(&mut self, id: Id<T>) -> Id<T> {
self.count += 1; self.count += 1;
let (index, epoch, _backend) = id.unzip(); let (index, epoch, _backend) = id.unzip();
let used = self.used.entry(epoch).or_insert_with(Default::default); let used = self.used.entry(epoch).or_insert_with(Default::default);
@ -74,7 +74,7 @@ impl IdentityValues {
} }
/// Free `id`. It will never be returned from `alloc` again. /// Free `id`. It will never be returned from `alloc` again.
pub fn release<I: id::TypedId>(&mut self, id: I) { pub fn release<T: Marker>(&mut self, id: Id<T>) {
let (index, epoch, _backend) = id.unzip(); let (index, epoch, _backend) = id.unzip();
self.free.push((index, epoch)); self.free.push((index, epoch));
self.count -= 1; self.count -= 1;
@ -86,24 +86,24 @@ impl IdentityValues {
} }
#[derive(Debug)] #[derive(Debug)]
pub struct IdentityManager<I: id::TypedId> { pub struct IdentityManager<T: Marker> {
pub(super) values: Mutex<IdentityValues>, pub(super) values: Mutex<IdentityValues>,
_phantom: PhantomData<I>, _phantom: PhantomData<T>,
} }
impl<I: id::TypedId> IdentityManager<I> { impl<T: Marker> IdentityManager<T> {
pub fn process(&self, backend: Backend) -> I { pub fn process(&self, backend: Backend) -> Id<T> {
self.values.lock().alloc(backend) self.values.lock().alloc(backend)
} }
pub fn mark_as_used(&self, id: I) -> I { pub fn mark_as_used(&self, id: Id<T>) -> Id<T> {
self.values.lock().mark_as_used(id) self.values.lock().mark_as_used(id)
} }
pub fn free(&self, id: I) { pub fn free(&self, id: Id<T>) {
self.values.lock().release(id) self.values.lock().release(id)
} }
} }
impl<I: id::TypedId> IdentityManager<I> { impl<T: Marker> IdentityManager<T> {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
values: Mutex::new(IdentityValues::default()), values: Mutex::new(IdentityValues::default()),
@ -115,7 +115,7 @@ impl<I: id::TypedId> IdentityManager<I> {
/// A type that can produce [`IdentityManager`] filters for ids of type `I`. /// A type that can produce [`IdentityManager`] filters for ids of type `I`.
/// ///
/// See the module-level documentation for details. /// See the module-level documentation for details.
pub trait IdentityHandlerFactory<I: id::TypedId> { pub trait IdentityHandlerFactory<T: Marker> {
type Input: Copy; type Input: Copy;
/// Create an [`IdentityManager<I>`] implementation that can /// Create an [`IdentityManager<I>`] implementation that can
/// transform proto-ids into ids of type `I`. /// transform proto-ids into ids of type `I`.
@ -123,11 +123,11 @@ pub trait IdentityHandlerFactory<I: id::TypedId> {
/// and are not generated by wgpu /// and are not generated by wgpu
/// ///
/// [`IdentityManager<I>`]: IdentityManager /// [`IdentityManager<I>`]: IdentityManager
fn spawn(&self) -> Arc<IdentityManager<I>> { fn spawn(&self) -> Arc<IdentityManager<T>> {
Arc::new(IdentityManager::new()) Arc::new(IdentityManager::new())
} }
fn autogenerate_ids() -> bool; fn autogenerate_ids() -> bool;
fn input_to_id(id_in: Self::Input) -> I; fn input_to_id(id_in: Self::Input) -> Id<T>;
} }
/// A global identity handler factory based on [`IdentityManager`]. /// A global identity handler factory based on [`IdentityManager`].
@ -138,13 +138,13 @@ pub trait IdentityHandlerFactory<I: id::TypedId> {
#[derive(Debug)] #[derive(Debug)]
pub struct IdentityManagerFactory; pub struct IdentityManagerFactory;
impl<I: id::TypedId> IdentityHandlerFactory<I> for IdentityManagerFactory { impl<T: Marker> IdentityHandlerFactory<T> for IdentityManagerFactory {
type Input = (); type Input = ();
fn autogenerate_ids() -> bool { fn autogenerate_ids() -> bool {
true true
} }
fn input_to_id(_id_in: Self::Input) -> I { fn input_to_id(_id_in: Self::Input) -> Id<T> {
unreachable!("It should not be called") unreachable!("It should not be called")
} }
} }
@ -152,23 +152,25 @@ impl<I: id::TypedId> IdentityHandlerFactory<I> for IdentityManagerFactory {
/// A factory that can build [`IdentityManager`]s for all resource /// A factory that can build [`IdentityManager`]s for all resource
/// types. /// types.
pub trait GlobalIdentityHandlerFactory: pub trait GlobalIdentityHandlerFactory:
IdentityHandlerFactory<id::AdapterId> IdentityHandlerFactory<id::markers::Adapter>
+ IdentityHandlerFactory<id::DeviceId> + IdentityHandlerFactory<id::markers::Device>
+ IdentityHandlerFactory<id::PipelineLayoutId> + IdentityHandlerFactory<id::markers::PipelineLayout>
+ IdentityHandlerFactory<id::ShaderModuleId> + IdentityHandlerFactory<id::markers::ShaderModule>
+ IdentityHandlerFactory<id::BindGroupLayoutId> + IdentityHandlerFactory<id::markers::BindGroupLayout>
+ IdentityHandlerFactory<id::BindGroupId> + IdentityHandlerFactory<id::markers::BindGroup>
+ IdentityHandlerFactory<id::CommandBufferId> + IdentityHandlerFactory<id::markers::CommandBuffer>
+ IdentityHandlerFactory<id::RenderBundleId> + IdentityHandlerFactory<id::markers::RenderBundle>
+ IdentityHandlerFactory<id::RenderPipelineId> + IdentityHandlerFactory<id::markers::RenderPipeline>
+ IdentityHandlerFactory<id::ComputePipelineId> + IdentityHandlerFactory<id::markers::ComputePipeline>
+ IdentityHandlerFactory<id::QuerySetId> + IdentityHandlerFactory<id::markers::QuerySet>
+ IdentityHandlerFactory<id::BufferId> + IdentityHandlerFactory<id::markers::Buffer>
+ IdentityHandlerFactory<id::StagingBufferId> + IdentityHandlerFactory<id::markers::StagingBuffer>
+ IdentityHandlerFactory<id::TextureId> + IdentityHandlerFactory<id::markers::Texture>
+ IdentityHandlerFactory<id::TextureViewId> + IdentityHandlerFactory<id::markers::TextureView>
+ IdentityHandlerFactory<id::SamplerId> + IdentityHandlerFactory<id::markers::Sampler>
+ IdentityHandlerFactory<id::SurfaceId> + IdentityHandlerFactory<id::markers::Surface>
+ IdentityHandlerFactory<id::markers::Queue>
+ IdentityHandlerFactory<id::markers::CommandEncoder>
{ {
} }
@ -178,8 +180,7 @@ pub type Input<G, I> = <G as IdentityHandlerFactory<I>>::Input;
#[test] #[test]
fn test_epoch_end_of_life() { fn test_epoch_end_of_life() {
use id::TypedId as _; let man = IdentityManager::<id::markers::Buffer>::new();
let man = IdentityManager::<id::BufferId>::new();
let forced_id = man.mark_as_used(id::BufferId::zip(0, 1, Backend::Empty)); let forced_id = man.mark_as_used(id::BufferId::zip(0, 1, Backend::Empty));
assert_eq!(forced_id.unzip().0, 0); assert_eq!(forced_id.unzip().0, 0);
let id1 = man.process(Backend::Empty); let id1 = man.process(Backend::Empty);

View File

@ -6,6 +6,7 @@ use crate::{
device::{queue::Queue, resource::Device, DeviceDescriptor}, device::{queue::Queue, resource::Device, DeviceDescriptor},
global::Global, global::Global,
hal_api::HalApi, hal_api::HalApi,
id::markers,
id::{AdapterId, DeviceId, QueueId, SurfaceId}, id::{AdapterId, DeviceId, QueueId, SurfaceId},
identity::{GlobalIdentityHandlerFactory, Input}, identity::{GlobalIdentityHandlerFactory, Input},
present::Presentation, present::Presentation,
@ -149,18 +150,20 @@ impl Instance {
pub struct Surface { pub struct Surface {
pub(crate) presentation: Mutex<Option<Presentation>>, pub(crate) presentation: Mutex<Option<Presentation>>,
pub(crate) info: ResourceInfo<SurfaceId>, pub(crate) info: ResourceInfo<Surface>,
pub(crate) raw: AnySurface, pub(crate) raw: AnySurface,
} }
impl Resource<SurfaceId> for Surface { impl Resource for Surface {
const TYPE: ResourceType = "Surface"; const TYPE: ResourceType = "Surface";
fn as_info(&self) -> &ResourceInfo<SurfaceId> { type Marker = crate::id::markers::Surface;
fn as_info(&self) -> &ResourceInfo<Self> {
&self.info &self.info
} }
fn as_info_mut(&mut self) -> &mut ResourceInfo<SurfaceId> { fn as_info_mut(&mut self) -> &mut ResourceInfo<Self> {
&mut self.info &mut self.info
} }
@ -190,7 +193,7 @@ impl Surface {
pub struct Adapter<A: HalApi> { pub struct Adapter<A: HalApi> {
pub(crate) raw: hal::ExposedAdapter<A>, pub(crate) raw: hal::ExposedAdapter<A>,
pub(crate) info: ResourceInfo<AdapterId>, pub(crate) info: ResourceInfo<Adapter<A>>,
} }
impl<A: HalApi> Adapter<A> { impl<A: HalApi> Adapter<A> {
@ -382,14 +385,16 @@ impl<A: HalApi> Adapter<A> {
} }
} }
impl<A: HalApi> Resource<AdapterId> for Adapter<A> { impl<A: HalApi> Resource for Adapter<A> {
const TYPE: ResourceType = "Adapter"; const TYPE: ResourceType = "Adapter";
fn as_info(&self) -> &ResourceInfo<AdapterId> { type Marker = crate::id::markers::Adapter;
fn as_info(&self) -> &ResourceInfo<Self> {
&self.info &self.info
} }
fn as_info_mut(&mut self) -> &mut ResourceInfo<AdapterId> { fn as_info_mut(&mut self) -> &mut ResourceInfo<Self> {
&mut self.info &mut self.info
} }
} }
@ -478,7 +483,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
&self, &self,
display_handle: raw_window_handle::RawDisplayHandle, display_handle: raw_window_handle::RawDisplayHandle,
window_handle: raw_window_handle::RawWindowHandle, window_handle: raw_window_handle::RawWindowHandle,
id_in: Input<G, SurfaceId>, id_in: Input<G, markers::Surface>,
) -> Result<SurfaceId, hal::InstanceError> { ) -> Result<SurfaceId, hal::InstanceError> {
profiling::scope!("Instance::create_surface"); profiling::scope!("Instance::create_surface");
@ -526,7 +531,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
raw: hal_surface, raw: hal_surface,
}; };
let (id, _) = self.surfaces.prepare::<G>(id_in).assign(surface); let (id, _) = self.surfaces.prepare::<G, _>(id_in).assign(surface);
Ok(id) Ok(id)
} }
@ -537,7 +542,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
pub unsafe fn instance_create_surface_metal( pub unsafe fn instance_create_surface_metal(
&self, &self,
layer: *mut std::ffi::c_void, layer: *mut std::ffi::c_void,
id_in: Input<G, SurfaceId>, id_in: Input<G, markers::Surface>,
) -> SurfaceId { ) -> SurfaceId {
profiling::scope!("Instance::create_surface_metal"); profiling::scope!("Instance::create_surface_metal");
@ -561,7 +566,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
}, },
}; };
let (id, _) = self.surfaces.prepare::<G>(id_in).assign(surface); let (id, _) = self.surfaces.prepare::<G, _>(id_in).assign(surface);
id id
} }
@ -572,7 +577,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
pub unsafe fn instance_create_surface_from_visual( pub unsafe fn instance_create_surface_from_visual(
&self, &self,
visual: *mut std::ffi::c_void, visual: *mut std::ffi::c_void,
id_in: Input<G, SurfaceId>, id_in: Input<G, markers::Surface>,
) -> SurfaceId { ) -> SurfaceId {
profiling::scope!("Instance::instance_create_surface_from_visual"); profiling::scope!("Instance::instance_create_surface_from_visual");
@ -592,7 +597,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
}, },
}; };
let (id, _) = self.surfaces.prepare::<G>(id_in).assign(surface); let (id, _) = self.surfaces.prepare::<G, _>(id_in).assign(surface);
id id
} }
@ -603,7 +608,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
pub unsafe fn instance_create_surface_from_surface_handle( pub unsafe fn instance_create_surface_from_surface_handle(
&self, &self,
surface_handle: *mut std::ffi::c_void, surface_handle: *mut std::ffi::c_void,
id_in: Input<G, SurfaceId>, id_in: Input<G, markers::Surface>,
) -> SurfaceId { ) -> SurfaceId {
profiling::scope!("Instance::instance_create_surface_from_surface_handle"); profiling::scope!("Instance::instance_create_surface_from_surface_handle");
@ -625,7 +630,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
}, },
}; };
let (id, _) = self.surfaces.prepare::<G>(id_in).assign(surface); let (id, _) = self.surfaces.prepare::<G, _>(id_in).assign(surface);
id id
} }
@ -636,7 +641,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
pub unsafe fn instance_create_surface_from_swap_chain_panel( pub unsafe fn instance_create_surface_from_swap_chain_panel(
&self, &self,
swap_chain_panel: *mut std::ffi::c_void, swap_chain_panel: *mut std::ffi::c_void,
id_in: Input<G, SurfaceId>, id_in: Input<G, markers::Surface>,
) -> SurfaceId { ) -> SurfaceId {
profiling::scope!("Instance::instance_create_surface_from_swap_chain_panel"); profiling::scope!("Instance::instance_create_surface_from_swap_chain_panel");
@ -658,7 +663,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
}, },
}; };
let (id, _) = self.surfaces.prepare::<G>(id_in).assign(surface); let (id, _) = self.surfaces.prepare::<G, _>(id_in).assign(surface);
id id
} }
@ -703,7 +708,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
&self, &self,
_: A, _: A,
instance: &Option<A::Instance>, instance: &Option<A::Instance>,
inputs: &AdapterInputs<Input<G, AdapterId>>, inputs: &AdapterInputs<Input<G, markers::Adapter>>,
list: &mut Vec<AdapterId>, list: &mut Vec<AdapterId>,
) { ) {
let inst = match *instance { let inst = match *instance {
@ -722,12 +727,15 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
for raw in hal_adapters { for raw in hal_adapters {
let adapter = Adapter::new(raw); let adapter = Adapter::new(raw);
log::info!("Adapter {:?} {:?}", A::VARIANT, adapter.raw.info); log::info!("Adapter {:?} {:?}", A::VARIANT, adapter.raw.info);
let (id, _) = hub.adapters.prepare::<G>(id_backend).assign(adapter); let (id, _) = hub.adapters.prepare::<G, _>(id_backend).assign(adapter);
list.push(id); list.push(id);
} }
} }
pub fn enumerate_adapters(&self, inputs: AdapterInputs<Input<G, AdapterId>>) -> Vec<AdapterId> { pub fn enumerate_adapters(
&self,
inputs: AdapterInputs<Input<G, markers::Adapter>>,
) -> Vec<AdapterId> {
profiling::scope!("Instance::enumerate_adapters"); profiling::scope!("Instance::enumerate_adapters");
api_log!("Instance::enumerate_adapters"); api_log!("Instance::enumerate_adapters");
@ -758,7 +766,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
fn select<A: HalApi>( fn select<A: HalApi>(
&self, &self,
selected: &mut usize, selected: &mut usize,
new_id: Option<Input<G, AdapterId>>, new_id: Option<Input<G, markers::Adapter>>,
mut list: Vec<hal::ExposedAdapter<A>>, mut list: Vec<hal::ExposedAdapter<A>>,
) -> Option<AdapterId> { ) -> Option<AdapterId> {
match selected.checked_sub(list.len()) { match selected.checked_sub(list.len()) {
@ -771,7 +779,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
log::info!("Adapter {:?} {:?}", A::VARIANT, adapter.raw.info); log::info!("Adapter {:?} {:?}", A::VARIANT, adapter.raw.info);
let (id, _) = HalApi::hub(self) let (id, _) = HalApi::hub(self)
.adapters .adapters
.prepare::<G>(new_id.unwrap()) .prepare::<G, _>(new_id.unwrap())
.assign(adapter); .assign(adapter);
Some(id) Some(id)
} }
@ -781,7 +789,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
pub fn request_adapter( pub fn request_adapter(
&self, &self,
desc: &RequestAdapterOptions, desc: &RequestAdapterOptions,
inputs: AdapterInputs<Input<G, AdapterId>>, inputs: AdapterInputs<Input<G, markers::Adapter>>,
) -> Result<AdapterId, RequestAdapterError> { ) -> Result<AdapterId, RequestAdapterError> {
profiling::scope!("Instance::request_adapter"); profiling::scope!("Instance::request_adapter");
api_log!("Instance::request_adapter"); api_log!("Instance::request_adapter");
@ -947,24 +955,23 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
pub unsafe fn create_adapter_from_hal<A: HalApi>( pub unsafe fn create_adapter_from_hal<A: HalApi>(
&self, &self,
hal_adapter: hal::ExposedAdapter<A>, hal_adapter: hal::ExposedAdapter<A>,
input: Input<G, AdapterId>, input: Input<G, markers::Adapter>,
) -> AdapterId { ) -> AdapterId {
profiling::scope!("Instance::create_adapter_from_hal"); profiling::scope!("Instance::create_adapter_from_hal");
let fid = A::hub(self).adapters.prepare::<G>(input); let fid = A::hub(self).adapters.prepare::<G, _>(input);
let (id, _adapter): (crate::id::Id<Adapter<hal::empty::Api>>, Arc<Adapter<A>>) = let (id, _adapter): (_, Arc<Adapter<A>>) = match A::VARIANT {
match A::VARIANT { #[cfg(vulkan)]
#[cfg(vulkan)] Backend::Vulkan => fid.assign(Adapter::new(hal_adapter)),
Backend::Vulkan => fid.assign(Adapter::new(hal_adapter)), #[cfg(metal)]
#[cfg(metal)] Backend::Metal => fid.assign(Adapter::new(hal_adapter)),
Backend::Metal => fid.assign(Adapter::new(hal_adapter)), #[cfg(dx12)]
#[cfg(dx12)] Backend::Dx12 => fid.assign(Adapter::new(hal_adapter)),
Backend::Dx12 => fid.assign(Adapter::new(hal_adapter)), #[cfg(gles)]
#[cfg(gles)] Backend::Gl => fid.assign(Adapter::new(hal_adapter)),
Backend::Gl => fid.assign(Adapter::new(hal_adapter)), _ => unreachable!(),
_ => unreachable!(), };
};
resource_log!("Created Adapter {:?}", id); resource_log!("Created Adapter {:?}", id);
id id
} }
@ -1065,15 +1072,15 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
adapter_id: AdapterId, adapter_id: AdapterId,
desc: &DeviceDescriptor, desc: &DeviceDescriptor,
trace_path: Option<&std::path::Path>, trace_path: Option<&std::path::Path>,
device_id_in: Input<G, DeviceId>, device_id_in: Input<G, markers::Device>,
queue_id_in: Input<G, QueueId>, queue_id_in: Input<G, markers::Queue>,
) -> (DeviceId, QueueId, Option<RequestDeviceError>) { ) -> (DeviceId, QueueId, Option<RequestDeviceError>) {
profiling::scope!("Adapter::request_device"); profiling::scope!("Adapter::request_device");
api_log!("Adapter::request_device"); api_log!("Adapter::request_device");
let hub = A::hub(self); let hub = A::hub(self);
let device_fid = hub.devices.prepare::<G>(device_id_in); let device_fid = hub.devices.prepare::<G, markers::Device>(device_id_in);
let queue_fid = hub.queues.prepare::<G>(queue_id_in); let queue_fid = hub.queues.prepare::<G, markers::Queue>(queue_id_in);
let error = loop { let error = loop {
let adapter = match hub.adapters.get(adapter_id) { let adapter = match hub.adapters.get(adapter_id) {
@ -1114,14 +1121,14 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
hal_device: OpenDevice<A>, hal_device: OpenDevice<A>,
desc: &DeviceDescriptor, desc: &DeviceDescriptor,
trace_path: Option<&std::path::Path>, trace_path: Option<&std::path::Path>,
device_id_in: Input<G, DeviceId>, device_id_in: Input<G, markers::Device>,
queue_id_in: Input<G, QueueId>, queue_id_in: Input<G, markers::Queue>,
) -> (DeviceId, QueueId, Option<RequestDeviceError>) { ) -> (DeviceId, QueueId, Option<RequestDeviceError>) {
profiling::scope!("Global::create_device_from_hal"); profiling::scope!("Global::create_device_from_hal");
let hub = A::hub(self); let hub = A::hub(self);
let devices_fid = hub.devices.prepare::<G>(device_id_in); let devices_fid = hub.devices.prepare::<G, markers::Device>(device_id_in);
let queues_fid = hub.queues.prepare::<G>(queue_id_in); let queues_fid = hub.queues.prepare::<G, markers::Queue>(queue_id_in);
let error = loop { let error = loop {
let adapter = match hub.adapters.get(adapter_id) { let adapter = match hub.adapters.get(adapter_id) {

View File

@ -5,7 +5,7 @@ use crate::{
command::ColorAttachmentError, command::ColorAttachmentError,
device::{Device, DeviceError, MissingDownlevelFlags, MissingFeatures, RenderPassContext}, device::{Device, DeviceError, MissingDownlevelFlags, MissingFeatures, RenderPassContext},
hal_api::HalApi, hal_api::HalApi,
id::{ComputePipelineId, PipelineLayoutId, RenderPipelineId, ShaderModuleId}, id::{PipelineLayoutId, ShaderModuleId},
resource::{Resource, ResourceInfo, ResourceType}, resource::{Resource, ResourceInfo, ResourceType},
resource_log, validation, Label, resource_log, validation, Label,
}; };
@ -50,7 +50,7 @@ pub struct ShaderModule<A: HalApi> {
pub(crate) raw: Option<A::ShaderModule>, pub(crate) raw: Option<A::ShaderModule>,
pub(crate) device: Arc<Device<A>>, pub(crate) device: Arc<Device<A>>,
pub(crate) interface: Option<validation::Interface>, pub(crate) interface: Option<validation::Interface>,
pub(crate) info: ResourceInfo<ShaderModuleId>, pub(crate) info: ResourceInfo<ShaderModule<A>>,
pub(crate) label: String, pub(crate) label: String,
} }
@ -70,14 +70,16 @@ impl<A: HalApi> Drop for ShaderModule<A> {
} }
} }
impl<A: HalApi> Resource<ShaderModuleId> for ShaderModule<A> { impl<A: HalApi> Resource for ShaderModule<A> {
const TYPE: ResourceType = "ShaderModule"; const TYPE: ResourceType = "ShaderModule";
fn as_info(&self) -> &ResourceInfo<ShaderModuleId> { type Marker = crate::id::markers::ShaderModule;
fn as_info(&self) -> &ResourceInfo<Self> {
&self.info &self.info
} }
fn as_info_mut(&mut self) -> &mut ResourceInfo<ShaderModuleId> { fn as_info_mut(&mut self) -> &mut ResourceInfo<Self> {
&mut self.info &mut self.info
} }
@ -267,7 +269,7 @@ pub struct ComputePipeline<A: HalApi> {
pub(crate) device: Arc<Device<A>>, pub(crate) device: Arc<Device<A>>,
pub(crate) _shader_module: Arc<ShaderModule<A>>, pub(crate) _shader_module: Arc<ShaderModule<A>>,
pub(crate) late_sized_buffer_groups: ArrayVec<LateSizedBufferGroup, { hal::MAX_BIND_GROUPS }>, pub(crate) late_sized_buffer_groups: ArrayVec<LateSizedBufferGroup, { hal::MAX_BIND_GROUPS }>,
pub(crate) info: ResourceInfo<ComputePipelineId>, pub(crate) info: ResourceInfo<ComputePipeline<A>>,
} }
impl<A: HalApi> Drop for ComputePipeline<A> { impl<A: HalApi> Drop for ComputePipeline<A> {
@ -288,14 +290,16 @@ impl<A: HalApi> Drop for ComputePipeline<A> {
} }
} }
impl<A: HalApi> Resource<ComputePipelineId> for ComputePipeline<A> { impl<A: HalApi> Resource for ComputePipeline<A> {
const TYPE: ResourceType = "ComputePipeline"; const TYPE: ResourceType = "ComputePipeline";
fn as_info(&self) -> &ResourceInfo<ComputePipelineId> { type Marker = crate::id::markers::ComputePipeline;
fn as_info(&self) -> &ResourceInfo<Self> {
&self.info &self.info
} }
fn as_info_mut(&mut self) -> &mut ResourceInfo<ComputePipelineId> { fn as_info_mut(&mut self) -> &mut ResourceInfo<Self> {
&mut self.info &mut self.info
} }
} }
@ -515,7 +519,7 @@ pub struct RenderPipeline<A: HalApi> {
pub(crate) strip_index_format: Option<wgt::IndexFormat>, pub(crate) strip_index_format: Option<wgt::IndexFormat>,
pub(crate) vertex_steps: Vec<VertexStep>, pub(crate) vertex_steps: Vec<VertexStep>,
pub(crate) late_sized_buffer_groups: ArrayVec<LateSizedBufferGroup, { hal::MAX_BIND_GROUPS }>, pub(crate) late_sized_buffer_groups: ArrayVec<LateSizedBufferGroup, { hal::MAX_BIND_GROUPS }>,
pub(crate) info: ResourceInfo<RenderPipelineId>, pub(crate) info: ResourceInfo<RenderPipeline<A>>,
} }
impl<A: HalApi> Drop for RenderPipeline<A> { impl<A: HalApi> Drop for RenderPipeline<A> {
@ -536,14 +540,16 @@ impl<A: HalApi> Drop for RenderPipeline<A> {
} }
} }
impl<A: HalApi> Resource<RenderPipelineId> for RenderPipeline<A> { impl<A: HalApi> Resource for RenderPipeline<A> {
const TYPE: ResourceType = "RenderPipeline"; const TYPE: ResourceType = "RenderPipeline";
fn as_info(&self) -> &ResourceInfo<RenderPipelineId> { type Marker = crate::id::markers::RenderPipeline;
fn as_info(&self) -> &ResourceInfo<Self> {
&self.info &self.info
} }
fn as_info_mut(&mut self) -> &mut ResourceInfo<RenderPipelineId> { fn as_info_mut(&mut self) -> &mut ResourceInfo<Self> {
&mut self.info &mut self.info
} }
} }

View File

@ -23,6 +23,7 @@ use crate::{
global::Global, global::Global,
hal_api::HalApi, hal_api::HalApi,
hal_label, hal_label,
id::markers,
id::{SurfaceId, TextureId}, id::{SurfaceId, TextureId},
identity::{GlobalIdentityHandlerFactory, Input}, identity::{GlobalIdentityHandlerFactory, Input},
init_tracker::TextureInitTracker, init_tracker::TextureInitTracker,
@ -125,13 +126,13 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
pub fn surface_get_current_texture<A: HalApi>( pub fn surface_get_current_texture<A: HalApi>(
&self, &self,
surface_id: SurfaceId, surface_id: SurfaceId,
texture_id_in: Input<G, TextureId>, texture_id_in: Input<G, markers::Texture>,
) -> Result<SurfaceOutput, SurfaceError> { ) -> Result<SurfaceOutput, SurfaceError> {
profiling::scope!("SwapChain::get_next_texture"); profiling::scope!("SwapChain::get_next_texture");
let hub = A::hub(self); let hub = A::hub(self);
let fid = hub.textures.prepare::<G>(texture_id_in); let fid = hub.textures.prepare::<G, _>(texture_id_in);
let surface = self let surface = self
.surfaces .surfaces

View File

@ -4,7 +4,7 @@ use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
use wgt::Backend; use wgt::Backend;
use crate::{ use crate::{
id, id::{self, Id, Marker},
identity::{IdentityHandlerFactory, IdentityManager}, identity::{IdentityHandlerFactory, IdentityManager},
resource::Resource, resource::Resource,
storage::{Element, InvalidId, Storage}, storage::{Element, InvalidId, Storage},
@ -37,14 +37,14 @@ impl RegistryReport {
/// any other dependent resource /// any other dependent resource
/// ///
#[derive(Debug)] #[derive(Debug)]
pub struct Registry<I: id::TypedId, T: Resource<I>> { pub struct Registry<T: Resource> {
identity: Arc<IdentityManager<I>>, identity: Arc<IdentityManager<T::Marker>>,
storage: RwLock<Storage<T, I>>, storage: RwLock<Storage<T>>,
backend: Backend, backend: Backend,
} }
impl<I: id::TypedId, T: Resource<I>> Registry<I, T> { impl<T: Resource> Registry<T> {
pub(crate) fn new<F: IdentityHandlerFactory<I>>(backend: Backend, factory: &F) -> Self { pub(crate) fn new<F: IdentityHandlerFactory<T::Marker>>(backend: Backend, factory: &F) -> Self {
Self { Self {
identity: factory.spawn(), identity: factory.spawn(),
storage: RwLock::new(Storage::new()), storage: RwLock::new(Storage::new()),
@ -52,25 +52,25 @@ impl<I: id::TypedId, T: Resource<I>> Registry<I, T> {
} }
} }
pub(crate) fn without_backend<F: IdentityHandlerFactory<I>>(factory: &F) -> Self { pub(crate) fn without_backend<F: IdentityHandlerFactory<T::Marker>>(factory: &F) -> Self {
Self::new(Backend::Empty, factory) Self::new(Backend::Empty, factory)
} }
} }
#[must_use] #[must_use]
pub(crate) struct FutureId<'a, I: id::TypedId, T: Resource<I>> { pub(crate) struct FutureId<'a, T: Resource> {
id: I, id: Id<T::Marker>,
identity: Arc<IdentityManager<I>>, identity: Arc<IdentityManager<T::Marker>>,
data: &'a RwLock<Storage<T, I>>, data: &'a RwLock<Storage<T>>,
} }
impl<I: id::TypedId + Copy, T: Resource<I>> FutureId<'_, I, T> { impl<T: Resource> FutureId<'_, T> {
#[allow(dead_code)] #[allow(dead_code)]
pub fn id(&self) -> I { pub fn id(&self) -> Id<T::Marker> {
self.id self.id
} }
pub fn into_id(self) -> I { pub fn into_id(self) -> Id<T::Marker> {
self.id self.id
} }
@ -82,7 +82,7 @@ impl<I: id::TypedId + Copy, T: Resource<I>> FutureId<'_, I, T> {
/// Assign a new resource to this ID. /// Assign a new resource to this ID.
/// ///
/// Registers it with the registry, and fills out the resource info. /// Registers it with the registry, and fills out the resource info.
pub fn assign(self, value: T) -> (I, Arc<T>) { pub fn assign(self, value: T) -> (Id<T::Marker>, Arc<T>) {
let mut data = self.data.write(); let mut data = self.data.write();
data.insert(self.id, self.init(value)); data.insert(self.id, self.init(value));
(self.id, data.get(self.id).unwrap().clone()) (self.id, data.get(self.id).unwrap().clone())
@ -94,73 +94,76 @@ impl<I: id::TypedId + Copy, T: Resource<I>> FutureId<'_, I, T> {
/// ///
/// This _will_ leak the ID, and it will not be recycled again. /// This _will_ leak the ID, and it will not be recycled again.
/// See https://github.com/gfx-rs/wgpu/issues/4912. /// See https://github.com/gfx-rs/wgpu/issues/4912.
pub fn assign_existing(self, value: &Arc<T>) -> I { pub fn assign_existing(self, value: &Arc<T>) -> Id<T::Marker> {
let mut data = self.data.write(); let mut data = self.data.write();
debug_assert!(!data.contains(self.id)); debug_assert!(!data.contains(self.id));
data.insert(self.id, value.clone()); data.insert(self.id, value.clone());
self.id self.id
} }
pub fn assign_error(self, label: &str) -> I { pub fn assign_error(self, label: &str) -> Id<T::Marker> {
self.data.write().insert_error(self.id, label); self.data.write().insert_error(self.id, label);
self.id self.id
} }
} }
impl<I: id::TypedId, T: Resource<I>> Registry<I, T> { impl<T: Resource> Registry<T> {
pub(crate) fn prepare<F>(&self, id_in: F::Input) -> FutureId<I, T> pub(crate) fn prepare<F, U: Marker>(&self, id_in: F::Input) -> FutureId<T>
where where
F: IdentityHandlerFactory<I>, F: IdentityHandlerFactory<U>,
T::Marker: id::transmute::Transmute<U>,
{ {
FutureId { FutureId {
id: if F::autogenerate_ids() { id: if F::autogenerate_ids() {
self.identity.process(self.backend) self.identity.process(self.backend)
} else { } else {
self.identity.mark_as_used(F::input_to_id(id_in)) self.identity
.mark_as_used(F::input_to_id(id_in).transmute())
}, },
identity: self.identity.clone(), identity: self.identity.clone(),
data: &self.storage, data: &self.storage,
} }
} }
pub(crate) fn request(&self) -> FutureId<I, T> {
pub(crate) fn request(&self) -> FutureId<T> {
FutureId { FutureId {
id: self.identity.process(self.backend), id: self.identity.process(self.backend),
identity: self.identity.clone(), identity: self.identity.clone(),
data: &self.storage, data: &self.storage,
} }
} }
pub(crate) fn try_get(&self, id: I) -> Result<Option<Arc<T>>, InvalidId> { pub(crate) fn try_get(&self, id: Id<T::Marker>) -> Result<Option<Arc<T>>, InvalidId> {
self.read().try_get(id).map(|o| o.cloned()) self.read().try_get(id).map(|o| o.cloned())
} }
pub(crate) fn get(&self, id: I) -> Result<Arc<T>, InvalidId> { pub(crate) fn get(&self, id: Id<T::Marker>) -> Result<Arc<T>, InvalidId> {
self.read().get_owned(id) self.read().get_owned(id)
} }
pub(crate) fn read<'a>(&'a self) -> RwLockReadGuard<'a, Storage<T, I>> { pub(crate) fn read<'a>(&'a self) -> RwLockReadGuard<'a, Storage<T>> {
self.storage.read() self.storage.read()
} }
pub(crate) fn write<'a>(&'a self) -> RwLockWriteGuard<'a, Storage<T, I>> { pub(crate) fn write<'a>(&'a self) -> RwLockWriteGuard<'a, Storage<T>> {
self.storage.write() self.storage.write()
} }
pub fn unregister_locked(&self, id: I, storage: &mut Storage<T, I>) -> Option<Arc<T>> { pub fn unregister_locked(&self, id: Id<T::Marker>, storage: &mut Storage<T>) -> Option<Arc<T>> {
storage.remove(id) storage.remove(id)
} }
pub fn force_replace(&self, id: I, mut value: T) { pub fn force_replace(&self, id: Id<T::Marker>, mut value: T) {
let mut storage = self.storage.write(); let mut storage = self.storage.write();
value.as_info_mut().set_id(id, &self.identity); value.as_info_mut().set_id(id, &self.identity);
storage.force_replace(id, value) storage.force_replace(id, value)
} }
pub fn force_replace_with_error(&self, id: I, label: &str) { pub fn force_replace_with_error(&self, id: Id<T::Marker>, label: &str) {
let mut storage = self.storage.write(); let mut storage = self.storage.write();
storage.remove(id); storage.remove(id);
storage.insert_error(id, label); storage.insert_error(id, label);
} }
pub(crate) fn unregister(&self, id: I) -> Option<Arc<T>> { pub(crate) fn unregister(&self, id: Id<T::Marker>) -> Option<Arc<T>> {
let value = self.storage.write().remove(id); let value = self.storage.write().remove(id);
//Returning None is legal if it's an error ID //Returning None is legal if it's an error ID
value value
} }
pub fn label_for_resource(&self, id: I) -> String { pub fn label_for_resource(&self, id: Id<T::Marker>) -> String {
let guard = self.storage.read(); let guard = self.storage.read();
let type_name = guard.kind(); let type_name = guard.kind();

View File

@ -8,10 +8,7 @@ use crate::{
}, },
global::Global, global::Global,
hal_api::HalApi, hal_api::HalApi,
id::{ id::{AdapterId, BufferId, DeviceId, Id, Marker, SurfaceId, TextureId},
AdapterId, BufferId, DeviceId, QuerySetId, SamplerId, StagingBufferId, SurfaceId,
TextureId, TextureViewId, TypedId,
},
identity::{GlobalIdentityHandlerFactory, IdentityManager}, identity::{GlobalIdentityHandlerFactory, IdentityManager},
init_tracker::{BufferInitTracker, TextureInitTracker}, init_tracker::{BufferInitTracker, TextureInitTracker},
resource, resource_log, resource, resource_log,
@ -59,9 +56,9 @@ use std::{
/// [`Device`]: crate::device::resource::Device /// [`Device`]: crate::device::resource::Device
/// [`Buffer`]: crate::resource::Buffer /// [`Buffer`]: crate::resource::Buffer
#[derive(Debug)] #[derive(Debug)]
pub struct ResourceInfo<Id: TypedId> { pub struct ResourceInfo<T: Resource> {
id: Option<Id>, id: Option<Id<T::Marker>>,
identity: Option<Arc<IdentityManager<Id>>>, identity: Option<Arc<IdentityManager<T::Marker>>>,
/// The index of the last queue submission in which the resource /// The index of the last queue submission in which the resource
/// was used. /// was used.
/// ///
@ -75,7 +72,7 @@ pub struct ResourceInfo<Id: TypedId> {
pub(crate) label: String, pub(crate) label: String,
} }
impl<Id: TypedId> Drop for ResourceInfo<Id> { impl<T: Resource> Drop for ResourceInfo<T> {
fn drop(&mut self) { fn drop(&mut self) {
if let Some(identity) = self.identity.as_ref() { if let Some(identity) = self.identity.as_ref() {
let id = self.id.as_ref().unwrap(); let id = self.id.as_ref().unwrap();
@ -84,7 +81,7 @@ impl<Id: TypedId> Drop for ResourceInfo<Id> {
} }
} }
impl<Id: TypedId> ResourceInfo<Id> { impl<T: Resource> ResourceInfo<T> {
#[allow(unused_variables)] #[allow(unused_variables)]
pub(crate) fn new(label: &str) -> Self { pub(crate) fn new(label: &str) -> Self {
Self { Self {
@ -97,7 +94,7 @@ impl<Id: TypedId> ResourceInfo<Id> {
pub(crate) fn label(&self) -> &dyn Debug pub(crate) fn label(&self) -> &dyn Debug
where where
Id: Debug, Id<T::Marker>: Debug,
{ {
if !self.label.is_empty() { if !self.label.is_empty() {
return &self.label; return &self.label;
@ -110,11 +107,11 @@ impl<Id: TypedId> ResourceInfo<Id> {
&"" &""
} }
pub(crate) fn id(&self) -> Id { pub(crate) fn id(&self) -> Id<T::Marker> {
self.id.unwrap() self.id.unwrap()
} }
pub(crate) fn set_id(&mut self, id: Id, identity: &Arc<IdentityManager<Id>>) { pub(crate) fn set_id(&mut self, id: Id<T::Marker>, identity: &Arc<IdentityManager<T::Marker>>) {
self.id = Some(id); self.id = Some(id);
self.identity = Some(identity.clone()); self.identity = Some(identity.clone());
} }
@ -133,10 +130,11 @@ impl<Id: TypedId> ResourceInfo<Id> {
pub(crate) type ResourceType = &'static str; pub(crate) type ResourceType = &'static str;
pub trait Resource<Id: TypedId>: 'static + WasmNotSendSync { pub trait Resource: 'static + Sized + WasmNotSendSync {
type Marker: Marker;
const TYPE: ResourceType; const TYPE: ResourceType;
fn as_info(&self) -> &ResourceInfo<Id>; fn as_info(&self) -> &ResourceInfo<Self>;
fn as_info_mut(&mut self) -> &mut ResourceInfo<Id>; fn as_info_mut(&mut self) -> &mut ResourceInfo<Self>;
fn label(&self) -> String { fn label(&self) -> String {
self.as_info().label.clone() self.as_info().label.clone()
} }
@ -377,7 +375,7 @@ pub struct Buffer<A: HalApi> {
pub(crate) size: wgt::BufferAddress, pub(crate) size: wgt::BufferAddress,
pub(crate) initialization_status: RwLock<BufferInitTracker>, pub(crate) initialization_status: RwLock<BufferInitTracker>,
pub(crate) sync_mapped_writes: Mutex<Option<hal::MemoryRange>>, pub(crate) sync_mapped_writes: Mutex<Option<hal::MemoryRange>>,
pub(crate) info: ResourceInfo<BufferId>, pub(crate) info: ResourceInfo<Buffer<A>>,
pub(crate) map_state: Mutex<BufferMapState<A>>, pub(crate) map_state: Mutex<BufferMapState<A>>,
pub(crate) bind_groups: Mutex<Vec<Weak<BindGroup<A>>>>, pub(crate) bind_groups: Mutex<Vec<Weak<BindGroup<A>>>>,
} }
@ -592,14 +590,16 @@ pub enum CreateBufferError {
MissingDownlevelFlags(#[from] MissingDownlevelFlags), MissingDownlevelFlags(#[from] MissingDownlevelFlags),
} }
impl<A: HalApi> Resource<BufferId> for Buffer<A> { impl<A: HalApi> Resource for Buffer<A> {
const TYPE: ResourceType = "Buffer"; const TYPE: ResourceType = "Buffer";
fn as_info(&self) -> &ResourceInfo<BufferId> { type Marker = crate::id::markers::Buffer;
fn as_info(&self) -> &ResourceInfo<Self> {
&self.info &self.info
} }
fn as_info_mut(&mut self) -> &mut ResourceInfo<BufferId> { fn as_info_mut(&mut self) -> &mut ResourceInfo<Self> {
&mut self.info &mut self.info
} }
} }
@ -693,7 +693,7 @@ pub struct StagingBuffer<A: HalApi> {
pub(crate) device: Arc<Device<A>>, pub(crate) device: Arc<Device<A>>,
pub(crate) size: wgt::BufferAddress, pub(crate) size: wgt::BufferAddress,
pub(crate) is_coherent: bool, pub(crate) is_coherent: bool,
pub(crate) info: ResourceInfo<StagingBufferId>, pub(crate) info: ResourceInfo<StagingBuffer<A>>,
} }
impl<A: HalApi> Drop for StagingBuffer<A> { impl<A: HalApi> Drop for StagingBuffer<A> {
@ -708,14 +708,16 @@ impl<A: HalApi> Drop for StagingBuffer<A> {
} }
} }
impl<A: HalApi> Resource<StagingBufferId> for StagingBuffer<A> { impl<A: HalApi> Resource for StagingBuffer<A> {
const TYPE: ResourceType = "StagingBuffer"; const TYPE: ResourceType = "StagingBuffer";
fn as_info(&self) -> &ResourceInfo<StagingBufferId> { type Marker = crate::id::markers::StagingBuffer;
fn as_info(&self) -> &ResourceInfo<Self> {
&self.info &self.info
} }
fn as_info_mut(&mut self) -> &mut ResourceInfo<StagingBufferId> { fn as_info_mut(&mut self) -> &mut ResourceInfo<Self> {
&mut self.info &mut self.info
} }
@ -773,7 +775,7 @@ pub struct Texture<A: HalApi> {
pub(crate) format_features: wgt::TextureFormatFeatures, pub(crate) format_features: wgt::TextureFormatFeatures,
pub(crate) initialization_status: RwLock<TextureInitTracker>, pub(crate) initialization_status: RwLock<TextureInitTracker>,
pub(crate) full_range: TextureSelector, pub(crate) full_range: TextureSelector,
pub(crate) info: ResourceInfo<TextureId>, pub(crate) info: ResourceInfo<Texture<A>>,
pub(crate) clear_mode: RwLock<TextureClearMode<A>>, pub(crate) clear_mode: RwLock<TextureClearMode<A>>,
pub(crate) views: Mutex<Vec<Weak<TextureView<A>>>>, pub(crate) views: Mutex<Vec<Weak<TextureView<A>>>>,
pub(crate) bind_groups: Mutex<Vec<Weak<BindGroup<A>>>>, pub(crate) bind_groups: Mutex<Vec<Weak<BindGroup<A>>>>,
@ -1166,14 +1168,16 @@ pub enum CreateTextureError {
MissingDownlevelFlags(#[from] MissingDownlevelFlags), MissingDownlevelFlags(#[from] MissingDownlevelFlags),
} }
impl<A: HalApi> Resource<TextureId> for Texture<A> { impl<A: HalApi> Resource for Texture<A> {
const TYPE: ResourceType = "Texture"; const TYPE: ResourceType = "Texture";
fn as_info(&self) -> &ResourceInfo<TextureId> { type Marker = crate::id::markers::Texture;
fn as_info(&self) -> &ResourceInfo<Self> {
&self.info &self.info
} }
fn as_info_mut(&mut self) -> &mut ResourceInfo<TextureId> { fn as_info_mut(&mut self) -> &mut ResourceInfo<Self> {
&mut self.info &mut self.info
} }
} }
@ -1251,7 +1255,7 @@ pub struct TextureView<A: HalApi> {
pub(crate) render_extent: Result<wgt::Extent3d, TextureViewNotRenderableReason>, pub(crate) render_extent: Result<wgt::Extent3d, TextureViewNotRenderableReason>,
pub(crate) samples: u32, pub(crate) samples: u32,
pub(crate) selector: TextureSelector, pub(crate) selector: TextureSelector,
pub(crate) info: ResourceInfo<TextureViewId>, pub(crate) info: ResourceInfo<TextureView<A>>,
} }
impl<A: HalApi> Drop for TextureView<A> { impl<A: HalApi> Drop for TextureView<A> {
@ -1329,14 +1333,16 @@ pub enum CreateTextureViewError {
#[non_exhaustive] #[non_exhaustive]
pub enum TextureViewDestroyError {} pub enum TextureViewDestroyError {}
impl<A: HalApi> Resource<TextureViewId> for TextureView<A> { impl<A: HalApi> Resource for TextureView<A> {
const TYPE: ResourceType = "TextureView"; const TYPE: ResourceType = "TextureView";
fn as_info(&self) -> &ResourceInfo<TextureViewId> { type Marker = crate::id::markers::TextureView;
fn as_info(&self) -> &ResourceInfo<Self> {
&self.info &self.info
} }
fn as_info_mut(&mut self) -> &mut ResourceInfo<TextureViewId> { fn as_info_mut(&mut self) -> &mut ResourceInfo<Self> {
&mut self.info &mut self.info
} }
} }
@ -1374,7 +1380,7 @@ pub struct SamplerDescriptor<'a> {
pub struct Sampler<A: HalApi> { pub struct Sampler<A: HalApi> {
pub(crate) raw: Option<A::Sampler>, pub(crate) raw: Option<A::Sampler>,
pub(crate) device: Arc<Device<A>>, pub(crate) device: Arc<Device<A>>,
pub(crate) info: ResourceInfo<SamplerId>, pub(crate) info: ResourceInfo<Self>,
/// `true` if this is a comparison sampler /// `true` if this is a comparison sampler
pub(crate) comparison: bool, pub(crate) comparison: bool,
/// `true` if this is a filtering sampler /// `true` if this is a filtering sampler
@ -1448,14 +1454,16 @@ pub enum CreateSamplerError {
MissingFeatures(#[from] MissingFeatures), MissingFeatures(#[from] MissingFeatures),
} }
impl<A: HalApi> Resource<SamplerId> for Sampler<A> { impl<A: HalApi> Resource for Sampler<A> {
const TYPE: ResourceType = "Sampler"; const TYPE: ResourceType = "Sampler";
fn as_info(&self) -> &ResourceInfo<SamplerId> { type Marker = crate::id::markers::Sampler;
fn as_info(&self) -> &ResourceInfo<Self> {
&self.info &self.info
} }
fn as_info_mut(&mut self) -> &mut ResourceInfo<SamplerId> { fn as_info_mut(&mut self) -> &mut ResourceInfo<Self> {
&mut self.info &mut self.info
} }
} }
@ -1479,7 +1487,7 @@ pub type QuerySetDescriptor<'a> = wgt::QuerySetDescriptor<Label<'a>>;
pub struct QuerySet<A: HalApi> { pub struct QuerySet<A: HalApi> {
pub(crate) raw: Option<A::QuerySet>, pub(crate) raw: Option<A::QuerySet>,
pub(crate) device: Arc<Device<A>>, pub(crate) device: Arc<Device<A>>,
pub(crate) info: ResourceInfo<QuerySetId>, pub(crate) info: ResourceInfo<Self>,
pub(crate) desc: wgt::QuerySetDescriptor<()>, pub(crate) desc: wgt::QuerySetDescriptor<()>,
} }
@ -1500,14 +1508,16 @@ impl<A: HalApi> Drop for QuerySet<A> {
} }
} }
impl<A: HalApi> Resource<QuerySetId> for QuerySet<A> { impl<A: HalApi> Resource for QuerySet<A> {
const TYPE: ResourceType = "QuerySet"; const TYPE: ResourceType = "QuerySet";
fn as_info(&self) -> &ResourceInfo<QuerySetId> { type Marker = crate::id::markers::QuerySet;
fn as_info(&self) -> &ResourceInfo<Self> {
&self.info &self.info
} }
fn as_info_mut(&mut self) -> &mut ResourceInfo<QuerySetId> { fn as_info_mut(&mut self) -> &mut ResourceInfo<Self> {
&mut self.info &mut self.info
} }
} }

View File

@ -1,8 +1,11 @@
use std::{marker::PhantomData, ops, sync::Arc}; use std::ops;
use std::sync::Arc;
use wgt::Backend; use wgt::Backend;
use crate::{id, resource::Resource, Epoch, Index}; use crate::id::Id;
use crate::resource::Resource;
use crate::{Epoch, Index};
/// An entry in a `Storage::map` table. /// An entry in a `Storage::map` table.
#[derive(Debug)] #[derive(Debug)]
@ -30,47 +33,41 @@ pub(crate) struct InvalidId;
/// values, so you should use an id allocator like `IdentityManager` /// values, so you should use an id allocator like `IdentityManager`
/// that keeps the index values dense and close to zero. /// that keeps the index values dense and close to zero.
#[derive(Debug)] #[derive(Debug)]
pub struct Storage<T, I> pub struct Storage<T>
where where
T: Resource<I>, T: Resource,
I: id::TypedId,
{ {
pub(crate) map: Vec<Element<T>>, pub(crate) map: Vec<Element<T>>,
kind: &'static str, kind: &'static str,
_phantom: PhantomData<I>,
} }
impl<T, I> ops::Index<I> for Storage<T, I> impl<T> ops::Index<Id<T::Marker>> for Storage<T>
where where
T: Resource<I>, T: Resource,
I: id::TypedId,
{ {
type Output = Arc<T>; type Output = Arc<T>;
fn index(&self, id: I) -> &Arc<T> { fn index(&self, id: Id<T::Marker>) -> &Arc<T> {
self.get(id).unwrap() self.get(id).unwrap()
} }
} }
impl<T, I> Storage<T, I> impl<T> Storage<T>
where where
T: Resource<I>, T: Resource,
I: id::TypedId,
{ {
pub(crate) fn new() -> Self { pub(crate) fn new() -> Self {
Self { Self {
map: Vec::new(), map: Vec::new(),
kind: T::TYPE, kind: T::TYPE,
_phantom: PhantomData,
} }
} }
} }
impl<T, I> Storage<T, I> impl<T> Storage<T>
where where
T: Resource<I>, T: Resource,
I: id::TypedId,
{ {
#[allow(dead_code)] #[allow(dead_code)]
pub(crate) fn contains(&self, id: I) -> bool { pub(crate) fn contains(&self, id: Id<T::Marker>) -> bool {
let (index, epoch, _) = id.unzip(); let (index, epoch, _) = id.unzip();
match self.map.get(index as usize) { match self.map.get(index as usize) {
Some(&Element::Vacant) => false, Some(&Element::Vacant) => false,
@ -88,7 +85,7 @@ where
/// This function is primarily intended for the `as_hal` family of functions /// This function is primarily intended for the `as_hal` family of functions
/// where you may need to fallibly get a object backed by an id that could /// where you may need to fallibly get a object backed by an id that could
/// be in a different hub. /// be in a different hub.
pub(crate) fn try_get(&self, id: I) -> Result<Option<&Arc<T>>, InvalidId> { pub(crate) fn try_get(&self, id: Id<T::Marker>) -> Result<Option<&Arc<T>>, InvalidId> {
let (index, epoch, _) = id.unzip(); let (index, epoch, _) = id.unzip();
let (result, storage_epoch) = match self.map.get(index as usize) { let (result, storage_epoch) = match self.map.get(index as usize) {
Some(&Element::Occupied(ref v, epoch)) => (Ok(Some(v)), epoch), Some(&Element::Occupied(ref v, epoch)) => (Ok(Some(v)), epoch),
@ -106,7 +103,7 @@ where
/// Get a reference to an item behind a potentially invalid ID. /// Get a reference to an item behind a potentially invalid ID.
/// Panics if there is an epoch mismatch, or the entry is empty. /// Panics if there is an epoch mismatch, or the entry is empty.
pub(crate) fn get(&self, id: I) -> Result<&Arc<T>, InvalidId> { pub(crate) fn get(&self, id: Id<T::Marker>) -> Result<&Arc<T>, InvalidId> {
let (index, epoch, _) = id.unzip(); let (index, epoch, _) = id.unzip();
let (result, storage_epoch) = match self.map.get(index as usize) { let (result, storage_epoch) = match self.map.get(index as usize) {
Some(&Element::Occupied(ref v, epoch)) => (Ok(v), epoch), Some(&Element::Occupied(ref v, epoch)) => (Ok(v), epoch),
@ -124,11 +121,11 @@ where
/// Get an owned reference to an item behind a potentially invalid ID. /// Get an owned reference to an item behind a potentially invalid ID.
/// Panics if there is an epoch mismatch, or the entry is empty. /// Panics if there is an epoch mismatch, or the entry is empty.
pub(crate) fn get_owned(&self, id: I) -> Result<Arc<T>, InvalidId> { pub(crate) fn get_owned(&self, id: Id<T::Marker>) -> Result<Arc<T>, InvalidId> {
Ok(Arc::clone(self.get(id)?)) Ok(Arc::clone(self.get(id)?))
} }
pub(crate) fn label_for_invalid_id(&self, id: I) -> &str { pub(crate) fn label_for_invalid_id(&self, id: Id<T::Marker>) -> &str {
let (index, _, _) = id.unzip(); let (index, _, _) = id.unzip();
match self.map.get(index as usize) { match self.map.get(index as usize) {
Some(Element::Error(_, label)) => label, Some(Element::Error(_, label)) => label,
@ -161,13 +158,13 @@ where
} }
} }
pub(crate) fn insert(&mut self, id: I, value: Arc<T>) { pub(crate) fn insert(&mut self, id: Id<T::Marker>, value: Arc<T>) {
log::trace!("User is inserting {}{:?}", T::TYPE, id); log::trace!("User is inserting {}{:?}", T::TYPE, id);
let (index, epoch, _backend) = id.unzip(); let (index, epoch, _backend) = id.unzip();
self.insert_impl(index as usize, epoch, Element::Occupied(value, epoch)) self.insert_impl(index as usize, epoch, Element::Occupied(value, epoch))
} }
pub(crate) fn insert_error(&mut self, id: I, label: &str) { pub(crate) fn insert_error(&mut self, id: Id<T::Marker>, label: &str) {
log::trace!("User is insering as error {}{:?}", T::TYPE, id); log::trace!("User is insering as error {}{:?}", T::TYPE, id);
let (index, epoch, _) = id.unzip(); let (index, epoch, _) = id.unzip();
self.insert_impl( self.insert_impl(
@ -177,7 +174,7 @@ where
) )
} }
pub(crate) fn replace_with_error(&mut self, id: I) -> Result<Arc<T>, InvalidId> { pub(crate) fn replace_with_error(&mut self, id: Id<T::Marker>) -> Result<Arc<T>, InvalidId> {
let (index, epoch, _) = id.unzip(); let (index, epoch, _) = id.unzip();
match std::mem::replace( match std::mem::replace(
&mut self.map[index as usize], &mut self.map[index as usize],
@ -192,13 +189,13 @@ where
} }
} }
pub(crate) fn force_replace(&mut self, id: I, value: T) { pub(crate) fn force_replace(&mut self, id: Id<T::Marker>, value: T) {
log::trace!("User is replacing {}{:?}", T::TYPE, id); log::trace!("User is replacing {}{:?}", T::TYPE, id);
let (index, epoch, _) = id.unzip(); let (index, epoch, _) = id.unzip();
self.map[index as usize] = Element::Occupied(Arc::new(value), epoch); self.map[index as usize] = Element::Occupied(Arc::new(value), epoch);
} }
pub(crate) fn remove(&mut self, id: I) -> Option<Arc<T>> { pub(crate) fn remove(&mut self, id: Id<T::Marker>) -> Option<Arc<T>> {
log::trace!("User is removing {}{:?}", T::TYPE, id); log::trace!("User is removing {}{:?}", T::TYPE, id);
let (index, epoch, _) = id.unzip(); let (index, epoch, _) = id.unzip();
match std::mem::replace(&mut self.map[index as usize], Element::Vacant) { match std::mem::replace(&mut self.map[index as usize], Element::Vacant) {
@ -211,13 +208,13 @@ where
} }
} }
pub(crate) fn iter(&self, backend: Backend) -> impl Iterator<Item = (I, &Arc<T>)> { pub(crate) fn iter(&self, backend: Backend) -> impl Iterator<Item = (Id<T::Marker>, &Arc<T>)> {
self.map self.map
.iter() .iter()
.enumerate() .enumerate()
.filter_map(move |(index, x)| match *x { .filter_map(move |(index, x)| match *x {
Element::Occupied(ref value, storage_epoch) => { Element::Occupied(ref value, storage_epoch) => {
Some((I::zip(index as Index, storage_epoch, backend), value)) Some((Id::zip(index as Index, storage_epoch, backend), value))
} }
_ => None, _ => None,
}) })

View File

@ -10,7 +10,7 @@ use std::{borrow::Cow, marker::PhantomData, sync::Arc};
use super::{PendingTransition, ResourceTracker}; use super::{PendingTransition, ResourceTracker};
use crate::{ use crate::{
hal_api::HalApi, hal_api::HalApi,
id::{BufferId, TypedId}, id::BufferId,
resource::{Buffer, Resource}, resource::{Buffer, Resource},
snatch::SnatchGuard, snatch::SnatchGuard,
storage::Storage, storage::Storage,
@ -26,7 +26,6 @@ use wgt::{strict_assert, strict_assert_eq};
impl ResourceUses for BufferUses { impl ResourceUses for BufferUses {
const EXCLUSIVE: Self = Self::EXCLUSIVE; const EXCLUSIVE: Self = Self::EXCLUSIVE;
type Id = BufferId;
type Selector = (); type Selector = ();
fn bits(self) -> u16 { fn bits(self) -> u16 {
@ -92,7 +91,7 @@ impl<A: HalApi> BufferBindGroupState<A> {
/// Adds the given resource with the given state. /// Adds the given resource with the given state.
pub fn add_single<'a>( pub fn add_single<'a>(
&self, &self,
storage: &'a Storage<Buffer<A>, BufferId>, storage: &'a Storage<Buffer<A>>,
id: BufferId, id: BufferId,
state: BufferUses, state: BufferUses,
) -> Option<&'a Arc<Buffer<A>>> { ) -> Option<&'a Arc<Buffer<A>>> {
@ -110,7 +109,7 @@ impl<A: HalApi> BufferBindGroupState<A> {
pub(crate) struct BufferUsageScope<A: HalApi> { pub(crate) struct BufferUsageScope<A: HalApi> {
state: Vec<BufferUses>, state: Vec<BufferUses>,
metadata: ResourceMetadata<A, BufferId, Buffer<A>>, metadata: ResourceMetadata<A, Buffer<A>>,
} }
impl<A: HalApi> BufferUsageScope<A> { impl<A: HalApi> BufferUsageScope<A> {
@ -248,7 +247,7 @@ impl<A: HalApi> BufferUsageScope<A> {
/// the vectors will be extended. A call to set_size is not needed. /// the vectors will be extended. A call to set_size is not needed.
pub fn merge_single<'a>( pub fn merge_single<'a>(
&mut self, &mut self,
storage: &'a Storage<Buffer<A>, BufferId>, storage: &'a Storage<Buffer<A>>,
id: BufferId, id: BufferId,
new_state: BufferUses, new_state: BufferUses,
) -> Result<&'a Arc<Buffer<A>>, UsageConflict> { ) -> Result<&'a Arc<Buffer<A>>, UsageConflict> {
@ -288,12 +287,12 @@ pub(crate) struct BufferTracker<A: HalApi> {
start: Vec<BufferUses>, start: Vec<BufferUses>,
end: Vec<BufferUses>, end: Vec<BufferUses>,
metadata: ResourceMetadata<A, BufferId, Buffer<A>>, metadata: ResourceMetadata<A, Buffer<A>>,
temp: Vec<PendingTransition<BufferUses>>, temp: Vec<PendingTransition<BufferUses>>,
} }
impl<A: HalApi> ResourceTracker<BufferId, Buffer<A>> for BufferTracker<A> { impl<A: HalApi> ResourceTracker<Buffer<A>> for BufferTracker<A> {
/// Try to remove the buffer `id` from this tracker if it is otherwise unused. /// Try to remove the buffer `id` from this tracker if it is otherwise unused.
/// ///
/// A buffer is 'otherwise unused' when the only references to it are: /// A buffer is 'otherwise unused' when the only references to it are:
@ -654,11 +653,11 @@ impl BufferStateProvider<'_> {
unsafe fn insert_or_merge<A: HalApi>( unsafe fn insert_or_merge<A: HalApi>(
start_states: Option<&mut [BufferUses]>, start_states: Option<&mut [BufferUses]>,
current_states: &mut [BufferUses], current_states: &mut [BufferUses],
resource_metadata: &mut ResourceMetadata<A, BufferId, Buffer<A>>, resource_metadata: &mut ResourceMetadata<A, Buffer<A>>,
index32: u32, index32: u32,
index: usize, index: usize,
state_provider: BufferStateProvider<'_>, state_provider: BufferStateProvider<'_>,
metadata_provider: ResourceMetadataProvider<'_, A, BufferId, Buffer<A>>, metadata_provider: ResourceMetadataProvider<'_, A, Buffer<A>>,
) -> Result<(), UsageConflict> { ) -> Result<(), UsageConflict> {
let currently_owned = unsafe { resource_metadata.contains_unchecked(index) }; let currently_owned = unsafe { resource_metadata.contains_unchecked(index) };
@ -709,11 +708,11 @@ unsafe fn insert_or_merge<A: HalApi>(
unsafe fn insert_or_barrier_update<A: HalApi>( unsafe fn insert_or_barrier_update<A: HalApi>(
start_states: Option<&mut [BufferUses]>, start_states: Option<&mut [BufferUses]>,
current_states: &mut [BufferUses], current_states: &mut [BufferUses],
resource_metadata: &mut ResourceMetadata<A, BufferId, Buffer<A>>, resource_metadata: &mut ResourceMetadata<A, Buffer<A>>,
index: usize, index: usize,
start_state_provider: BufferStateProvider<'_>, start_state_provider: BufferStateProvider<'_>,
end_state_provider: Option<BufferStateProvider<'_>>, end_state_provider: Option<BufferStateProvider<'_>>,
metadata_provider: ResourceMetadataProvider<'_, A, BufferId, Buffer<A>>, metadata_provider: ResourceMetadataProvider<'_, A, Buffer<A>>,
barriers: &mut Vec<PendingTransition<BufferUses>>, barriers: &mut Vec<PendingTransition<BufferUses>>,
) { ) {
let currently_owned = unsafe { resource_metadata.contains_unchecked(index) }; let currently_owned = unsafe { resource_metadata.contains_unchecked(index) };
@ -743,11 +742,11 @@ unsafe fn insert_or_barrier_update<A: HalApi>(
unsafe fn insert<A: HalApi>( unsafe fn insert<A: HalApi>(
start_states: Option<&mut [BufferUses]>, start_states: Option<&mut [BufferUses]>,
current_states: &mut [BufferUses], current_states: &mut [BufferUses],
resource_metadata: &mut ResourceMetadata<A, BufferId, Buffer<A>>, resource_metadata: &mut ResourceMetadata<A, Buffer<A>>,
index: usize, index: usize,
start_state_provider: BufferStateProvider<'_>, start_state_provider: BufferStateProvider<'_>,
end_state_provider: Option<BufferStateProvider<'_>>, end_state_provider: Option<BufferStateProvider<'_>>,
metadata_provider: ResourceMetadataProvider<'_, A, BufferId, Buffer<A>>, metadata_provider: ResourceMetadataProvider<'_, A, Buffer<A>>,
) { ) {
let new_start_state = unsafe { start_state_provider.get_state(index) }; let new_start_state = unsafe { start_state_provider.get_state(index) };
let new_end_state = let new_end_state =
@ -777,7 +776,7 @@ unsafe fn merge<A: HalApi>(
index32: u32, index32: u32,
index: usize, index: usize,
state_provider: BufferStateProvider<'_>, state_provider: BufferStateProvider<'_>,
metadata_provider: ResourceMetadataProvider<'_, A, BufferId, Buffer<A>>, metadata_provider: ResourceMetadataProvider<'_, A, Buffer<A>>,
) -> Result<(), UsageConflict> { ) -> Result<(), UsageConflict> {
let current_state = unsafe { current_states.get_unchecked_mut(index) }; let current_state = unsafe { current_states.get_unchecked_mut(index) };
let new_state = unsafe { state_provider.get_state(index) }; let new_state = unsafe { state_provider.get_state(index) };

View File

@ -1,6 +1,6 @@
//! The `ResourceMetadata` type. //! The `ResourceMetadata` type.
use crate::{hal_api::HalApi, id::TypedId, resource::Resource, Epoch}; use crate::{hal_api::HalApi, resource::Resource, Epoch};
use bit_vec::BitVec; use bit_vec::BitVec;
use std::{borrow::Cow, marker::PhantomData, mem, sync::Arc}; use std::{borrow::Cow, marker::PhantomData, mem, sync::Arc};
use wgt::strict_assert; use wgt::strict_assert;
@ -13,7 +13,7 @@ use wgt::strict_assert;
/// members, but a bit vector tracks occupancy, so iteration touches /// members, but a bit vector tracks occupancy, so iteration touches
/// only occupied elements. /// only occupied elements.
#[derive(Debug)] #[derive(Debug)]
pub(super) struct ResourceMetadata<A: HalApi, I: TypedId, T: Resource<I>> { pub(super) struct ResourceMetadata<A: HalApi, T: Resource> {
/// If the resource with index `i` is a member, `owned[i]` is `true`. /// If the resource with index `i` is a member, `owned[i]` is `true`.
owned: BitVec<usize>, owned: BitVec<usize>,
@ -21,10 +21,10 @@ pub(super) struct ResourceMetadata<A: HalApi, I: TypedId, T: Resource<I>> {
resources: Vec<Option<Arc<T>>>, resources: Vec<Option<Arc<T>>>,
/// This tells Rust that this type should be covariant with `A`. /// This tells Rust that this type should be covariant with `A`.
_phantom: PhantomData<(A, I)>, _phantom: PhantomData<A>,
} }
impl<A: HalApi, I: TypedId, T: Resource<I>> ResourceMetadata<A, I, T> { impl<A: HalApi, T: Resource> ResourceMetadata<A, T> {
pub(super) fn new() -> Self { pub(super) fn new() -> Self {
Self { Self {
owned: BitVec::default(), owned: BitVec::default(),
@ -172,15 +172,15 @@ impl<A: HalApi, I: TypedId, T: Resource<I>> ResourceMetadata<A, I, T> {
/// ///
/// This is used to abstract over the various places /// This is used to abstract over the various places
/// trackers can get new resource metadata from. /// trackers can get new resource metadata from.
pub(super) enum ResourceMetadataProvider<'a, A: HalApi, I: TypedId, T: Resource<I>> { pub(super) enum ResourceMetadataProvider<'a, A: HalApi, T: Resource> {
/// Comes directly from explicit values. /// Comes directly from explicit values.
Direct { resource: Cow<'a, Arc<T>> }, Direct { resource: Cow<'a, Arc<T>> },
/// Comes from another metadata tracker. /// Comes from another metadata tracker.
Indirect { Indirect {
metadata: &'a ResourceMetadata<A, I, T>, metadata: &'a ResourceMetadata<A, T>,
}, },
} }
impl<A: HalApi, I: TypedId, T: Resource<I>> ResourceMetadataProvider<'_, A, I, T> { impl<A: HalApi, T: Resource> ResourceMetadataProvider<'_, A, T> {
/// Get the epoch and an owned refcount from this. /// Get the epoch and an owned refcount from this.
/// ///
/// # Safety /// # Safety

View File

@ -104,7 +104,7 @@ mod texture;
use crate::{ use crate::{
binding_model, command, conv, binding_model, command, conv,
hal_api::HalApi, hal_api::HalApi,
id::{self, TypedId}, id::{self, Id},
pipeline, resource, pipeline, resource,
snatch::SnatchGuard, snatch::SnatchGuard,
storage::Storage, storage::Storage,
@ -182,8 +182,6 @@ pub(crate) trait ResourceUses:
/// All flags that are exclusive. /// All flags that are exclusive.
const EXCLUSIVE: Self; const EXCLUSIVE: Self;
/// The relevant resource ID type.
type Id: Copy + fmt::Debug + TypedId;
/// The selector used by this resource. /// The selector used by this resource.
type Selector: fmt::Debug; type Selector: fmt::Debug;
@ -320,8 +318,8 @@ impl<T: ResourceUses> fmt::Display for InvalidUse<T> {
pub(crate) struct BindGroupStates<A: HalApi> { pub(crate) struct BindGroupStates<A: HalApi> {
pub buffers: BufferBindGroupState<A>, pub buffers: BufferBindGroupState<A>,
pub textures: TextureBindGroupState<A>, pub textures: TextureBindGroupState<A>,
pub views: StatelessBindGroupSate<id::TextureViewId, resource::TextureView<A>>, pub views: StatelessBindGroupSate<resource::TextureView<A>>,
pub samplers: StatelessBindGroupSate<id::SamplerId, resource::Sampler<A>>, pub samplers: StatelessBindGroupSate<resource::Sampler<A>>,
} }
impl<A: HalApi> BindGroupStates<A> { impl<A: HalApi> BindGroupStates<A> {
@ -354,20 +352,19 @@ pub(crate) struct RenderBundleScope<A: HalApi> {
pub buffers: RwLock<BufferUsageScope<A>>, pub buffers: RwLock<BufferUsageScope<A>>,
pub textures: RwLock<TextureUsageScope<A>>, pub textures: RwLock<TextureUsageScope<A>>,
// Don't need to track views and samplers, they are never used directly, only by bind groups. // Don't need to track views and samplers, they are never used directly, only by bind groups.
pub bind_groups: RwLock<StatelessTracker<A, id::BindGroupId, binding_model::BindGroup<A>>>, pub bind_groups: RwLock<StatelessTracker<A, binding_model::BindGroup<A>>>,
pub render_pipelines: pub render_pipelines: RwLock<StatelessTracker<A, pipeline::RenderPipeline<A>>>,
RwLock<StatelessTracker<A, id::RenderPipelineId, pipeline::RenderPipeline<A>>>, pub query_sets: RwLock<StatelessTracker<A, resource::QuerySet<A>>>,
pub query_sets: RwLock<StatelessTracker<A, id::QuerySetId, resource::QuerySet<A>>>,
} }
impl<A: HalApi> RenderBundleScope<A> { impl<A: HalApi> RenderBundleScope<A> {
/// Create the render bundle scope and pull the maximum IDs from the hubs. /// Create the render bundle scope and pull the maximum IDs from the hubs.
pub fn new( pub fn new(
buffers: &Storage<resource::Buffer<A>, id::BufferId>, buffers: &Storage<resource::Buffer<A>>,
textures: &Storage<resource::Texture<A>, id::TextureId>, textures: &Storage<resource::Texture<A>>,
bind_groups: &Storage<binding_model::BindGroup<A>, id::BindGroupId>, bind_groups: &Storage<binding_model::BindGroup<A>>,
render_pipelines: &Storage<pipeline::RenderPipeline<A>, id::RenderPipelineId>, render_pipelines: &Storage<pipeline::RenderPipeline<A>>,
query_sets: &Storage<resource::QuerySet<A>, id::QuerySetId>, query_sets: &Storage<resource::QuerySet<A>>,
) -> Self { ) -> Self {
let value = Self { let value = Self {
buffers: RwLock::new(BufferUsageScope::new()), buffers: RwLock::new(BufferUsageScope::new()),
@ -424,8 +421,8 @@ pub(crate) struct UsageScope<A: HalApi> {
impl<A: HalApi> UsageScope<A> { impl<A: HalApi> UsageScope<A> {
/// Create the render bundle scope and pull the maximum IDs from the hubs. /// Create the render bundle scope and pull the maximum IDs from the hubs.
pub fn new( pub fn new(
buffers: &Storage<resource::Buffer<A>, id::BufferId>, buffers: &Storage<resource::Buffer<A>>,
textures: &Storage<resource::Texture<A>, id::TextureId>, textures: &Storage<resource::Texture<A>>,
) -> Self { ) -> Self {
let mut value = Self { let mut value = Self {
buffers: BufferUsageScope::new(), buffers: BufferUsageScope::new(),
@ -481,25 +478,24 @@ impl<A: HalApi> UsageScope<A> {
} }
} }
pub(crate) trait ResourceTracker<Id, R> pub(crate) trait ResourceTracker<R>
where where
Id: TypedId, R: resource::Resource,
R: resource::Resource<Id>,
{ {
fn remove_abandoned(&mut self, id: Id) -> bool; fn remove_abandoned(&mut self, id: Id<R::Marker>) -> bool;
} }
/// A full double sided tracker used by CommandBuffers and the Device. /// A full double sided tracker used by CommandBuffers and the Device.
pub(crate) struct Tracker<A: HalApi> { pub(crate) struct Tracker<A: HalApi> {
pub buffers: BufferTracker<A>, pub buffers: BufferTracker<A>,
pub textures: TextureTracker<A>, pub textures: TextureTracker<A>,
pub views: StatelessTracker<A, id::TextureViewId, resource::TextureView<A>>, pub views: StatelessTracker<A, resource::TextureView<A>>,
pub samplers: StatelessTracker<A, id::SamplerId, resource::Sampler<A>>, pub samplers: StatelessTracker<A, resource::Sampler<A>>,
pub bind_groups: StatelessTracker<A, id::BindGroupId, binding_model::BindGroup<A>>, pub bind_groups: StatelessTracker<A, binding_model::BindGroup<A>>,
pub compute_pipelines: StatelessTracker<A, id::ComputePipelineId, pipeline::ComputePipeline<A>>, pub compute_pipelines: StatelessTracker<A, pipeline::ComputePipeline<A>>,
pub render_pipelines: StatelessTracker<A, id::RenderPipelineId, pipeline::RenderPipeline<A>>, pub render_pipelines: StatelessTracker<A, pipeline::RenderPipeline<A>>,
pub bundles: StatelessTracker<A, id::RenderBundleId, command::RenderBundle<A>>, pub bundles: StatelessTracker<A, command::RenderBundle<A>>,
pub query_sets: StatelessTracker<A, id::QuerySetId, resource::QuerySet<A>>, pub query_sets: StatelessTracker<A, resource::QuerySet<A>>,
} }
impl<A: HalApi> Tracker<A> { impl<A: HalApi> Tracker<A> {
@ -520,15 +516,15 @@ impl<A: HalApi> Tracker<A> {
/// Pull the maximum IDs from the hubs. /// Pull the maximum IDs from the hubs.
pub fn set_size( pub fn set_size(
&mut self, &mut self,
buffers: Option<&Storage<resource::Buffer<A>, id::BufferId>>, buffers: Option<&Storage<resource::Buffer<A>>>,
textures: Option<&Storage<resource::Texture<A>, id::TextureId>>, textures: Option<&Storage<resource::Texture<A>>>,
views: Option<&Storage<resource::TextureView<A>, id::TextureViewId>>, views: Option<&Storage<resource::TextureView<A>>>,
samplers: Option<&Storage<resource::Sampler<A>, id::SamplerId>>, samplers: Option<&Storage<resource::Sampler<A>>>,
bind_groups: Option<&Storage<binding_model::BindGroup<A>, id::BindGroupId>>, bind_groups: Option<&Storage<binding_model::BindGroup<A>>>,
compute_pipelines: Option<&Storage<pipeline::ComputePipeline<A>, id::ComputePipelineId>>, compute_pipelines: Option<&Storage<pipeline::ComputePipeline<A>>>,
render_pipelines: Option<&Storage<pipeline::RenderPipeline<A>, id::RenderPipelineId>>, render_pipelines: Option<&Storage<pipeline::RenderPipeline<A>>>,
bundles: Option<&Storage<command::RenderBundle<A>, id::RenderBundleId>>, bundles: Option<&Storage<command::RenderBundle<A>>>,
query_sets: Option<&Storage<resource::QuerySet<A>, id::QuerySetId>>, query_sets: Option<&Storage<resource::QuerySet<A>>>,
) { ) {
if let Some(buffers) = buffers { if let Some(buffers) = buffers {
self.buffers.set_size(buffers.len()); self.buffers.set_size(buffers.len());

View File

@ -4,24 +4,27 @@
* distinction between a usage scope and a full tracker. * distinction between a usage scope and a full tracker.
!*/ !*/
use std::{marker::PhantomData, sync::Arc}; use std::sync::Arc;
use parking_lot::Mutex; use parking_lot::Mutex;
use crate::{ use crate::{
hal_api::HalApi, id::TypedId, resource::Resource, resource_log, storage::Storage, hal_api::HalApi, id::Id, resource::Resource, resource_log, storage::Storage,
track::ResourceMetadata, track::ResourceMetadata,
}; };
use super::ResourceTracker; use super::ResourceTracker;
/// Satisfy clippy.
type Pair<T> = (Id<<T as Resource>::Marker>, Arc<T>);
/// Stores all the resources that a bind group stores. /// Stores all the resources that a bind group stores.
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct StatelessBindGroupSate<Id: TypedId, T: Resource<Id>> { pub(crate) struct StatelessBindGroupSate<T: Resource> {
resources: Mutex<Vec<(Id, Arc<T>)>>, resources: Mutex<Vec<Pair<T>>>,
} }
impl<Id: TypedId, T: Resource<Id>> StatelessBindGroupSate<Id, T> { impl<T: Resource> StatelessBindGroupSate<T> {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
resources: Mutex::new(Vec::new()), resources: Mutex::new(Vec::new()),
@ -58,7 +61,7 @@ impl<Id: TypedId, T: Resource<Id>> StatelessBindGroupSate<Id, T> {
} }
/// Adds the given resource. /// Adds the given resource.
pub fn add_single<'a>(&self, storage: &'a Storage<T, Id>, id: Id) -> Option<&'a T> { pub fn add_single<'a>(&self, storage: &'a Storage<T>, id: Id<T::Marker>) -> Option<&'a T> {
let resource = storage.get(id).ok()?; let resource = storage.get(id).ok()?;
let mut resources = self.resources.lock(); let mut resources = self.resources.lock();
@ -70,14 +73,11 @@ impl<Id: TypedId, T: Resource<Id>> StatelessBindGroupSate<Id, T> {
/// Stores all resource state within a command buffer or device. /// Stores all resource state within a command buffer or device.
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct StatelessTracker<A: HalApi, Id: TypedId, T: Resource<Id>> { pub(crate) struct StatelessTracker<A: HalApi, T: Resource> {
metadata: ResourceMetadata<A, Id, T>, metadata: ResourceMetadata<A, T>,
_phantom: PhantomData<Id>,
} }
impl<A: HalApi, Id: TypedId, T: Resource<Id>> ResourceTracker<Id, T> impl<A: HalApi, T: Resource> ResourceTracker<T> for StatelessTracker<A, T> {
for StatelessTracker<A, Id, T>
{
/// Try to remove the given resource from the tracker iff we have the last reference to the /// Try to remove the given resource from the tracker iff we have the last reference to the
/// resource and the epoch matches. /// resource and the epoch matches.
/// ///
@ -85,7 +85,7 @@ impl<A: HalApi, Id: TypedId, T: Resource<Id>> ResourceTracker<Id, T>
/// ///
/// If the ID is higher than the length of internal vectors, /// If the ID is higher than the length of internal vectors,
/// false will be returned. /// false will be returned.
fn remove_abandoned(&mut self, id: Id) -> bool { fn remove_abandoned(&mut self, id: Id<T::Marker>) -> bool {
let index = id.unzip().0 as usize; let index = id.unzip().0 as usize;
if index >= self.metadata.size() { if index >= self.metadata.size() {
@ -120,11 +120,10 @@ impl<A: HalApi, Id: TypedId, T: Resource<Id>> ResourceTracker<Id, T>
} }
} }
impl<A: HalApi, Id: TypedId, T: Resource<Id>> StatelessTracker<A, Id, T> { impl<A: HalApi, T: Resource> StatelessTracker<A, T> {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
metadata: ResourceMetadata::new(), metadata: ResourceMetadata::new(),
_phantom: PhantomData,
} }
} }
@ -164,7 +163,7 @@ impl<A: HalApi, Id: TypedId, T: Resource<Id>> StatelessTracker<A, Id, T> {
/// ///
/// If the ID is higher than the length of internal vectors, /// If the ID is higher than the length of internal vectors,
/// the vectors will be extended. A call to set_size is not needed. /// the vectors will be extended. A call to set_size is not needed.
pub fn insert_single(&mut self, id: Id, resource: Arc<T>) { pub fn insert_single(&mut self, id: Id<T::Marker>, resource: Arc<T>) {
let (index32, _epoch, _) = id.unzip(); let (index32, _epoch, _) = id.unzip();
let index = index32 as usize; let index = index32 as usize;
@ -181,7 +180,11 @@ impl<A: HalApi, Id: TypedId, T: Resource<Id>> StatelessTracker<A, Id, T> {
/// ///
/// If the ID is higher than the length of internal vectors, /// If the ID is higher than the length of internal vectors,
/// the vectors will be extended. A call to set_size is not needed. /// the vectors will be extended. A call to set_size is not needed.
pub fn add_single<'a>(&mut self, storage: &'a Storage<T, Id>, id: Id) -> Option<&'a Arc<T>> { pub fn add_single<'a>(
&mut self,
storage: &'a Storage<T>,
id: Id<T::Marker>,
) -> Option<&'a Arc<T>> {
let resource = storage.get(id).ok()?; let resource = storage.get(id).ok()?;
let (index32, _epoch, _) = id.unzip(); let (index32, _epoch, _) = id.unzip();
@ -222,7 +225,7 @@ impl<A: HalApi, Id: TypedId, T: Resource<Id>> StatelessTracker<A, Id, T> {
} }
} }
pub fn get(&self, id: Id) -> Option<&Arc<T>> { pub fn get(&self, id: Id<T::Marker>) -> Option<&Arc<T>> {
let index = id.unzip().0 as usize; let index = id.unzip().0 as usize;
if index > self.metadata.size() { if index > self.metadata.size() {
return None; return None;

View File

@ -22,7 +22,7 @@
use super::{range::RangedStates, PendingTransition, PendingTransitionList, ResourceTracker}; use super::{range::RangedStates, PendingTransition, PendingTransitionList, ResourceTracker};
use crate::{ use crate::{
hal_api::HalApi, hal_api::HalApi,
id::{TextureId, TypedId}, id::TextureId,
resource::{Resource, Texture, TextureInner}, resource::{Resource, Texture, TextureInner},
snatch::SnatchGuard, snatch::SnatchGuard,
track::{ track::{
@ -50,7 +50,6 @@ pub struct TextureSelector {
impl ResourceUses for TextureUses { impl ResourceUses for TextureUses {
const EXCLUSIVE: Self = Self::EXCLUSIVE; const EXCLUSIVE: Self = Self::EXCLUSIVE;
type Id = TextureId;
type Selector = TextureSelector; type Selector = TextureSelector;
fn bits(self) -> u16 { fn bits(self) -> u16 {
@ -232,7 +231,7 @@ impl TextureStateSet {
#[derive(Debug)] #[derive(Debug)]
pub(crate) struct TextureUsageScope<A: HalApi> { pub(crate) struct TextureUsageScope<A: HalApi> {
set: TextureStateSet, set: TextureStateSet,
metadata: ResourceMetadata<A, TextureId, Texture<A>>, metadata: ResourceMetadata<A, Texture<A>>,
} }
impl<A: HalApi> TextureUsageScope<A> { impl<A: HalApi> TextureUsageScope<A> {
@ -387,14 +386,14 @@ pub(crate) struct TextureTracker<A: HalApi> {
start_set: TextureStateSet, start_set: TextureStateSet,
end_set: TextureStateSet, end_set: TextureStateSet,
metadata: ResourceMetadata<A, TextureId, Texture<A>>, metadata: ResourceMetadata<A, Texture<A>>,
temp: Vec<PendingTransition<TextureUses>>, temp: Vec<PendingTransition<TextureUses>>,
_phantom: PhantomData<A>, _phantom: PhantomData<A>,
} }
impl<A: HalApi> ResourceTracker<TextureId, Texture<A>> for TextureTracker<A> { impl<A: HalApi> ResourceTracker<Texture<A>> for TextureTracker<A> {
/// Try to remove the given resource from the tracker iff we have the last reference to the /// Try to remove the given resource from the tracker iff we have the last reference to the
/// resource and the epoch matches. /// resource and the epoch matches.
/// ///
@ -864,10 +863,10 @@ impl<'a> TextureStateProvider<'a> {
unsafe fn insert_or_merge<A: HalApi>( unsafe fn insert_or_merge<A: HalApi>(
texture_selector: &TextureSelector, texture_selector: &TextureSelector,
current_state_set: &mut TextureStateSet, current_state_set: &mut TextureStateSet,
resource_metadata: &mut ResourceMetadata<A, TextureId, Texture<A>>, resource_metadata: &mut ResourceMetadata<A, Texture<A>>,
index: usize, index: usize,
state_provider: TextureStateProvider<'_>, state_provider: TextureStateProvider<'_>,
metadata_provider: ResourceMetadataProvider<'_, A, TextureId, Texture<A>>, metadata_provider: ResourceMetadataProvider<'_, A, Texture<A>>,
) -> Result<(), UsageConflict> { ) -> Result<(), UsageConflict> {
let currently_owned = unsafe { resource_metadata.contains_unchecked(index) }; let currently_owned = unsafe { resource_metadata.contains_unchecked(index) };
@ -920,11 +919,11 @@ unsafe fn insert_or_barrier_update<A: HalApi>(
texture_selector: &TextureSelector, texture_selector: &TextureSelector,
start_state: Option<&mut TextureStateSet>, start_state: Option<&mut TextureStateSet>,
current_state_set: &mut TextureStateSet, current_state_set: &mut TextureStateSet,
resource_metadata: &mut ResourceMetadata<A, TextureId, Texture<A>>, resource_metadata: &mut ResourceMetadata<A, Texture<A>>,
index: usize, index: usize,
start_state_provider: TextureStateProvider<'_>, start_state_provider: TextureStateProvider<'_>,
end_state_provider: Option<TextureStateProvider<'_>>, end_state_provider: Option<TextureStateProvider<'_>>,
metadata_provider: ResourceMetadataProvider<'_, A, TextureId, Texture<A>>, metadata_provider: ResourceMetadataProvider<'_, A, Texture<A>>,
barriers: &mut Vec<PendingTransition<TextureUses>>, barriers: &mut Vec<PendingTransition<TextureUses>>,
) { ) {
let currently_owned = unsafe { resource_metadata.contains_unchecked(index) }; let currently_owned = unsafe { resource_metadata.contains_unchecked(index) };
@ -973,11 +972,11 @@ unsafe fn insert<A: HalApi>(
texture_selector: Option<&TextureSelector>, texture_selector: Option<&TextureSelector>,
start_state: Option<&mut TextureStateSet>, start_state: Option<&mut TextureStateSet>,
end_state: &mut TextureStateSet, end_state: &mut TextureStateSet,
resource_metadata: &mut ResourceMetadata<A, TextureId, Texture<A>>, resource_metadata: &mut ResourceMetadata<A, Texture<A>>,
index: usize, index: usize,
start_state_provider: TextureStateProvider<'_>, start_state_provider: TextureStateProvider<'_>,
end_state_provider: Option<TextureStateProvider<'_>>, end_state_provider: Option<TextureStateProvider<'_>>,
metadata_provider: ResourceMetadataProvider<'_, A, TextureId, Texture<A>>, metadata_provider: ResourceMetadataProvider<'_, A, Texture<A>>,
) { ) {
let start_layers = unsafe { start_state_provider.get_state(texture_selector, index) }; let start_layers = unsafe { start_state_provider.get_state(texture_selector, index) };
match start_layers { match start_layers {
@ -1060,7 +1059,7 @@ unsafe fn merge<A: HalApi>(
current_state_set: &mut TextureStateSet, current_state_set: &mut TextureStateSet,
index: usize, index: usize,
state_provider: TextureStateProvider<'_>, state_provider: TextureStateProvider<'_>,
metadata_provider: ResourceMetadataProvider<'_, A, TextureId, Texture<A>>, metadata_provider: ResourceMetadataProvider<'_, A, Texture<A>>,
) -> Result<(), UsageConflict> { ) -> Result<(), UsageConflict> {
let current_simple = unsafe { current_state_set.simple.get_unchecked_mut(index) }; let current_simple = unsafe { current_state_set.simple.get_unchecked_mut(index) };
let current_state = if *current_simple == TextureUses::COMPLEX { let current_state = if *current_simple == TextureUses::COMPLEX {

View File

@ -24,7 +24,6 @@ use std::{
}; };
use wgc::command::{bundle_ffi::*, compute_ffi::*, render_ffi::*}; use wgc::command::{bundle_ffi::*, compute_ffi::*, render_ffi::*};
use wgc::device::DeviceLostClosure; use wgc::device::DeviceLostClosure;
use wgc::id::TypedId;
use wgt::WasmNotSendSync; use wgt::WasmNotSendSync;
const LABEL: &str = "label"; const LABEL: &str = "label";
@ -604,7 +603,7 @@ impl crate::Context for ContextWgpuCore {
id: queue_id, id: queue_id,
error_sink, error_sink,
}; };
ready(Ok((device_id, device, device_id, queue))) ready(Ok((device_id, device, device_id.transmute(), queue)))
} }
fn instance_poll_all_devices(&self, force_wait: bool) -> bool { fn instance_poll_all_devices(&self, force_wait: bool) -> bool {
@ -1805,7 +1804,8 @@ impl crate::Context for ContextWgpuCore {
if let Err(cause) = wgc::gfx_select!( if let Err(cause) = wgc::gfx_select!(
encoder => self.0.command_encoder_run_compute_pass(*encoder, pass_data) encoder => self.0.command_encoder_run_compute_pass(*encoder, pass_data)
) { ) {
let name = wgc::gfx_select!(encoder => self.0.command_buffer_label(*encoder)); let name =
wgc::gfx_select!(encoder => self.0.command_buffer_label(encoder.transmute()));
self.handle_error( self.handle_error(
&encoder_data.error_sink, &encoder_data.error_sink,
cause, cause,
@ -1888,7 +1888,8 @@ impl crate::Context for ContextWgpuCore {
if let Err(cause) = if let Err(cause) =
wgc::gfx_select!(encoder => self.0.command_encoder_run_render_pass(*encoder, pass_data)) wgc::gfx_select!(encoder => self.0.command_encoder_run_render_pass(*encoder, pass_data))
{ {
let name = wgc::gfx_select!(encoder => self.0.command_buffer_label(*encoder)); let name =
wgc::gfx_select!(encoder => self.0.command_buffer_label(encoder.transmute()));
self.handle_error( self.handle_error(
&encoder_data.error_sink, &encoder_data.error_sink,
cause, cause,
@ -2922,10 +2923,10 @@ impl crate::Context for ContextWgpuCore {
impl<T> From<ObjectId> for wgc::id::Id<T> impl<T> From<ObjectId> for wgc::id::Id<T>
where where
T: 'static + WasmNotSendSync, T: wgc::id::Marker,
{ {
fn from(id: ObjectId) -> Self { fn from(id: ObjectId) -> Self {
let id = id.id(); let id = wgc::id::RawId::from_non_zero(id.id());
// SAFETY: The id was created via the impl below // SAFETY: The id was created via the impl below
unsafe { Self::from_raw(id) } unsafe { Self::from_raw(id) }
} }
@ -2933,10 +2934,10 @@ where
impl<T> From<wgc::id::Id<T>> for ObjectId impl<T> From<wgc::id::Id<T>> for ObjectId
where where
T: 'static + WasmNotSendSync, T: wgc::id::Marker,
{ {
fn from(id: wgc::id::Id<T>) -> Self { fn from(id: wgc::id::Id<T>) -> Self {
let id = id.into_raw(); let id = id.into_raw().into_non_zero();
Self::from_global_id(id) Self::from_global_id(id)
} }
} }