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>>()?;
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 {
let resource = state.resource_table.take::<WebGpuCommandBuffer>(rid)?;
@ -84,7 +84,7 @@ pub fn op_webgpu_write_buffer(
None => &buf[data_offset..],
};
let maybe_err = gfx_select!(queue => instance.queue_write_buffer(
queue,
queue.transmute(),
buffer,
buffer_offset,
data
@ -120,7 +120,7 @@ pub fn op_webgpu_write_texture(
let data_layout = data_layout.into();
gfx_ok!(queue => instance.queue_write_texture(
queue,
queue.transmute(),
&destination,
buf,
&data_layout,

View File

@ -61,7 +61,7 @@ fn main() {
global.instance_create_surface(
window.display_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();
@ -79,22 +79,21 @@ fn main() {
#[cfg(not(feature = "winit"))]
compatible_surface: None,
},
wgc::instance::AdapterInputs::IdSet(
&[wgc::id::TypedId::zip(0, 0, backend)],
|id| id.backend(),
),
wgc::instance::AdapterInputs::IdSet(&[wgc::id::Id::zip(0, 0, backend)], |id| {
id.backend()
}),
)
.expect("Unable to find an adapter for selected backend");
let info = gfx_select!(adapter => global.adapter_get_info(adapter)).unwrap();
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(
adapter,
&desc,
None,
id,
id
id.transmute()
));
if let Some(e) = error {
panic!("{:?}", e);

View File

@ -14,10 +14,10 @@ use std::{borrow::Cow, fs, path::Path};
pub struct IdentityPassThroughFactory;
impl<I: wgc::id::TypedId> wgc::identity::IdentityHandlerFactory<I> for IdentityPassThroughFactory {
type Input = I;
impl<T: wgc::id::Marker> wgc::identity::IdentityHandlerFactory<T> for IdentityPassThroughFactory {
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
}
@ -38,7 +38,7 @@ pub trait GlobalPlay {
device: wgc::id::DeviceId,
action: trace::Action,
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,
action: trace::Action,
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;
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 size = (range.end - range.start) as usize;
if queued {
self.queue_write_buffer::<A>(device, id, range.start, &bin)
self.queue_write_buffer::<A>(device.transmute(), id, range.start, &bin)
.unwrap();
} else {
self.device_wait_for_buffer::<A>(device, id).unwrap();
@ -365,23 +365,24 @@ impl GlobalPlay for wgc::global::Global<IdentityPassThroughFactory> {
size,
} => {
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();
}
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) => {
let (encoder, error) = self.device_create_command_encoder::<A>(
device,
&wgt::CommandEncoderDescriptor { label: None },
comb_manager.process(device.backend()),
comb_manager.process(device.backend()).transmute(),
);
if let Some(e) = error {
panic!("{e}");
}
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,
) {
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(
adapter,
&wgt::DeviceDescriptor {
@ -115,7 +115,7 @@ impl Test<'_> {
},
None,
device_id,
device_id
device_id.transmute()
));
if let Some(e) = error {
panic!("{:?}", e);
@ -128,7 +128,7 @@ impl Test<'_> {
}
println!("\t\t\tMapping...");
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(
buffer,
expect.offset .. expect.offset+expect.data.len() as wgt::BufferAddress,
@ -148,7 +148,7 @@ impl Test<'_> {
for expect in self.expectations {
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) =
wgc::gfx_select!(device_id => global.buffer_get_mapped_range(buffer, expect.offset, Some(expect.data.len() as wgt::BufferAddress)))
.unwrap();
@ -221,10 +221,9 @@ impl Corpus {
force_fallback_adapter: false,
compatible_surface: None,
},
wgc::instance::AdapterInputs::IdSet(
&[wgc::id::TypedId::zip(0, 0, backend)],
|id| id.backend(),
),
wgc::instance::AdapterInputs::IdSet(&[wgc::id::Id::zip(0, 0, backend)], |id| {
id.backend()
}),
) {
Ok(adapter) => adapter,
Err(_) => continue,

View File

@ -6,10 +6,7 @@ use crate::{
},
error::{ErrorFormatter, PrettyError},
hal_api::HalApi,
id::{
BindGroupId, BindGroupLayoutId, BufferId, PipelineLayoutId, SamplerId, TextureId,
TextureViewId,
},
id::{BindGroupLayoutId, BufferId, SamplerId, TextureId, TextureViewId},
init_tracker::{BufferInitTrackerAction, TextureInitTrackerAction},
resource::{Resource, ResourceInfo, ResourceType},
resource_log,
@ -441,7 +438,7 @@ pub struct BindGroupLayoutDescriptor<'a> {
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.
#[derive(Debug)]
@ -458,7 +455,7 @@ pub struct BindGroupLayout<A: HalApi> {
pub(crate) origin: bgl::Origin,
#[allow(unused)]
pub(crate) binding_count_validator: BindingTypeMaxCountValidator,
pub(crate) info: ResourceInfo<BindGroupLayoutId>,
pub(crate) info: ResourceInfo<BindGroupLayout<A>>,
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";
fn as_info(&self) -> &ResourceInfo<BindGroupLayoutId> {
type Marker = crate::id::markers::BindGroupLayout;
fn as_info(&self) -> &ResourceInfo<Self> {
&self.info
}
fn as_info_mut(&mut self) -> &mut ResourceInfo<BindGroupLayoutId> {
fn as_info_mut(&mut self) -> &mut ResourceInfo<Self> {
&mut self.info
}
@ -602,7 +601,7 @@ pub struct PipelineLayoutDescriptor<'a> {
pub struct PipelineLayout<A: HalApi> {
pub(crate) raw: Option<A::PipelineLayout>,
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) 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";
fn as_info(&self) -> &ResourceInfo<PipelineLayoutId> {
type Marker = crate::id::markers::PipelineLayout;
fn as_info(&self) -> &ResourceInfo<Self> {
&self.info
}
fn as_info_mut(&mut self) -> &mut ResourceInfo<PipelineLayoutId> {
fn as_info_mut(&mut self) -> &mut ResourceInfo<Self> {
&mut self.info
}
}
@ -830,7 +831,7 @@ pub struct BindGroup<A: HalApi> {
pub(crate) raw: Snatchable<A::BindGroup>,
pub(crate) device: Arc<Device<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_buffer_ranges: Vec<BufferInitTrackerAction<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";
fn as_info(&self) -> &ResourceInfo<BindGroupId> {
type Marker = crate::id::markers::BindGroup;
fn as_info(&self) -> &ResourceInfo<Self> {
&self.info
}
fn as_info_mut(&mut self) -> &mut ResourceInfo<BindGroupId> {
fn as_info_mut(&mut self) -> &mut ResourceInfo<Self> {
&mut self.info
}
}

View File

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

View File

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

View File

@ -140,7 +140,7 @@ pub struct CommandBuffer<A: HalApi> {
pub(crate) device: Arc<Device<A>>,
limits: wgt::Limits,
support_clear_texture: bool,
pub(crate) info: ResourceInfo<CommandBufferId>,
pub(crate) info: ResourceInfo<CommandBuffer<A>>,
pub(crate) data: Mutex<Option<CommandBufferMutable<A>>>,
}
@ -255,7 +255,7 @@ impl<A: HalApi> CommandBuffer<A> {
id: id::CommandEncoderId,
) -> Result<Arc<Self>, CommandEncoderError> {
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 {
CommandEncoderStatus::Recording => Ok(cmd_buf.clone()),
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";
fn as_info(&self) -> &ResourceInfo<CommandBufferId> {
type Marker = crate::id::markers::CommandBuffer;
fn as_info(&self) -> &ResourceInfo<Self> {
&self.info
}
fn as_info_mut(&mut self) -> &mut ResourceInfo<CommandBufferId> {
fn as_info_mut(&mut self) -> &mut ResourceInfo<Self> {
&mut self.info
}
@ -418,7 +420,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
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) => {
let mut cmd_buf_data = cmd_buf.data.lock();
let cmd_buf_data = cmd_buf_data.as_mut().unwrap();
@ -444,7 +446,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
Err(_) => Some(CommandEncoderError::Invalid),
};
(encoder_id, error)
(encoder_id.transmute(), error)
}
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
match *self {
Self::Pass(id) => {
fmt.command_buffer_label(&id);
fmt.command_buffer_label(&id.transmute());
}
Self::SetBindGroup(id) => {
fmt.bind_group_label(&id);

View File

@ -7,7 +7,7 @@ use crate::{
device::DeviceError,
global::Global,
hal_api::HalApi,
id::{self, Id, TypedId},
id::{self, Id},
identity::GlobalIdentityHandlerFactory,
init_tracker::MemoryInitKind,
resource::QuerySet,
@ -49,7 +49,7 @@ impl<A: HalApi> QueryResetMap<A> {
pub fn reset_queries(
&mut self,
raw_encoder: &mut A::CommandEncoder,
query_set_storage: &Storage<QuerySet<A>, id::QuerySetId>,
query_set_storage: &Storage<QuerySet<A>>,
backend: wgt::Backend,
) -> Result<(), id::QuerySetId> {
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>(
raw_encoder: &mut A::CommandEncoder,
storage: &Storage<QuerySet<A>, id::QuerySetId>,
storage: &Storage<QuerySet<A>>,
active_query: &mut Option<(id::QuerySetId, u32)>,
) -> Result<(), QueryUseError> {
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>(
raw_encoder: &mut A::CommandEncoder,
storage: &Storage<QuerySet<A>, id::QuerySetId>,
storage: &Storage<QuerySet<A>>,
active_query: &mut Option<(id::QuerySetId, u32)>,
) -> Result<(), QueryUseError> {
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>,
texture_memory_actions: &mut CommandBufferTextureMemoryActions<A>,
pending_query_resets: &mut QueryResetMap<A>,
view_guard: &'a Storage<TextureView<A>, id::TextureViewId>,
buffer_guard: &'a Storage<Buffer<A>, id::BufferId>,
texture_guard: &'a Storage<Texture<A>, id::TextureId>,
query_set_guard: &'a Storage<QuerySet<A>, id::QuerySetId>,
view_guard: &'a Storage<TextureView<A>>,
buffer_guard: &'a Storage<Buffer<A>>,
texture_guard: &'a Storage<Texture<A>>,
query_set_guard: &'a Storage<QuerySet<A>>,
snatch_guard: &SnatchGuard<'a>,
) -> Result<Self, RenderPassErrorInner> {
profiling::scope!("RenderPassInfo::start");
@ -2391,7 +2391,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
(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 cmd_buf_data = cmd_buf_data.as_mut().unwrap();

View File

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

View File

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

View File

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

View File

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

View File

@ -12,7 +12,7 @@ use crate::{
hal_api::HalApi,
hal_label,
hub::Hub,
id::{self, DeviceId, QueueId},
id::QueueId,
init_tracker::{
BufferInitTracker, BufferInitTrackerAction, MemoryInitKind, TextureInitRange,
TextureInitTracker, TextureInitTrackerAction,
@ -90,7 +90,7 @@ pub struct Device<A: HalApi> {
pub(crate) queue_id: RwLock<Option<QueueId>>,
queue_to_drop: RwLock<Option<A::Queue>>,
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>>>,
//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>,
late_buffer_binding_sizes: &mut FastHashMap<u32, wgt::BufferSize>,
used: &mut BindGroupStates<A>,
storage: &'a Storage<Buffer<A>, id::BufferId>,
storage: &'a Storage<Buffer<A>>,
limits: &wgt::Limits,
snatch_guard: &'a SnatchGuard<'a>,
) -> Result<hal::BufferBinding<'a, A>, binding_model::CreateBindGroupError> {
@ -2386,7 +2386,7 @@ impl<A: HalApi> Device<A> {
pub(crate) fn create_pipeline_layout(
self: &Arc<Self>,
desc: &binding_model::PipelineLayoutDescriptor,
bgl_registry: &Registry<id::BindGroupLayoutId, BindGroupLayout<A>>,
bgl_registry: &Registry<BindGroupLayout<A>>,
) -> Result<binding_model::PipelineLayout<A>, binding_model::CreatePipelineLayoutError> {
use crate::binding_model::CreatePipelineLayoutError as Error;
@ -2499,8 +2499,8 @@ impl<A: HalApi> Device<A> {
self: &Arc<Self>,
implicit_context: Option<ImplicitPipelineContext>,
mut derived_group_layouts: ArrayVec<bgl::EntryMap, { hal::MAX_BIND_GROUPS }>,
bgl_registry: &Registry<id::BindGroupLayoutId, BindGroupLayout<A>>,
pipeline_layout_registry: &Registry<id::PipelineLayoutId, binding_model::PipelineLayout<A>>,
bgl_registry: &Registry<BindGroupLayout<A>>,
pipeline_layout_registry: &Registry<binding_model::PipelineLayout<A>>,
) -> Result<Arc<binding_model::PipelineLayout<A>>, pipeline::ImplicitLayoutError> {
while derived_group_layouts
.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";
fn as_info(&self) -> &ResourceInfo<DeviceId> {
type Marker = crate::id::markers::Device;
fn as_info(&self) -> &ResourceInfo<Self> {
&self.info
}
fn as_info_mut(&mut self) -> &mut ResourceInfo<DeviceId> {
fn as_info_mut(&mut self) -> &mut ResourceInfo<Self> {
&mut self.info
}
}

View File

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

View File

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

View File

@ -1,6 +1,5 @@
use crate::{Epoch, Index};
use std::{
any::Any,
cmp::Ordering,
fmt::{self, Debug},
hash::Hash,
@ -9,15 +8,74 @@ use std::{
use wgt::{Backend, WasmNotSendSync};
type IdType = u64;
type NonZeroId = std::num::NonZeroU64;
type ZippedIndex = Index;
type NonZeroId = std::num::NonZeroU64;
const INDEX_BITS: usize = std::mem::size_of::<ZippedIndex>() * 8;
const EPOCH_BITS: usize = INDEX_BITS - BACKEND_BITS;
const BACKEND_BITS: usize = 3;
const BACKEND_SHIFT: usize = INDEX_BITS * 2 - BACKEND_BITS;
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.
///
@ -49,21 +107,13 @@ type Dummy = hal::api::Empty;
/// [`Registry`]: crate::hub::Registry
/// [`Empty`]: hal::api::Empty
#[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(
feature = "replay",
derive(serde::Deserialize),
serde(from = "SerialId")
any(feature = "serde", feature = "trace", feature = "replay"),
serde(transparent)
)]
#[cfg_attr(
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>);
pub struct Id<T: Marker>(RawId, PhantomData<T>);
// This type represents Id in a more readable (and editable) way.
#[allow(dead_code)]
@ -72,39 +122,40 @@ enum SerialId {
// The only variant forces RON to not ignore "Id"
Id(Index, Epoch, Backend),
}
#[cfg(feature = "trace")]
impl<T> From<Id<T>> for SerialId
where
T: 'static + WasmNotSendSync,
{
fn from(id: Id<T>) -> Self {
impl From<RawId> for SerialId {
fn from(id: RawId) -> Self {
let (index, epoch, backend) = id.unzip();
Self::Id(index, epoch, backend)
}
}
#[cfg(feature = "replay")]
impl<T> From<SerialId> for Id<T>
where
T: 'static + WasmNotSendSync,
{
impl From<SerialId> for RawId {
fn from(id: SerialId) -> Self {
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>
where
T: 'static + WasmNotSendSync,
T: Marker,
{
/// # Safety
///
/// 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)
}
/// Coerce the identifiers into its raw underlying representation.
pub fn into_raw(self) -> RawId {
self.0
}
#[allow(dead_code)]
pub(crate) fn dummy(index: u32) -> Self {
Id::zip(index, 1, Backend::Empty)
@ -115,24 +166,53 @@ where
self.backend() != Backend::Empty
}
/// Get the backend this identifier corresponds to.
#[inline]
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!(),
}
self.0.backend()
}
/// Transmute this identifier to one with a different marker trait.
///
/// Legal use is governed through a sealed trait, however it's correctness
/// 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>
where
T: 'static + WasmNotSendSync,
T: Marker,
{
#[inline]
fn clone(&self) -> Self {
*self
}
@ -140,7 +220,7 @@ where
impl<T> Debug for Id<T>
where
T: 'static + WasmNotSendSync,
T: Marker,
{
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
let (index, epoch, backend) = self.unzip();
@ -159,8 +239,9 @@ where
impl<T> Hash for Id<T>
where
T: 'static + WasmNotSendSync,
T: Marker,
{
#[inline]
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.0.hash(state);
}
@ -168,19 +249,21 @@ where
impl<T> PartialEq for Id<T>
where
T: 'static + WasmNotSendSync,
T: Marker,
{
#[inline]
fn eq(&self, other: &Self) -> bool {
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>
where
T: 'static + WasmNotSendSync,
T: Marker,
{
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.0.partial_cmp(&other.0)
}
@ -188,78 +271,73 @@ where
impl<T> Ord for Id<T>
where
T: 'static + WasmNotSendSync,
T: Marker,
{
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
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
/// need to construct `Id` values directly, or access their components, like the
/// WGPU recording player, may use this trait to do so.
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;
}
/// For example, `Device<A>` will have the same type of identifier as
/// `Device<B>` because `Device<T>` for any `T` defines the same maker type.
pub trait Marker: 'static + WasmNotSendSync {}
#[allow(trivial_numeric_casts)]
impl<T> TypedId for Id<T>
where
T: 'static + WasmNotSendSync,
{
fn zip(index: Index, epoch: Epoch, backend: Backend) -> Self {
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)
}
// This allows `()` to be used as a marker type for tests.
//
// We don't want these in production code, since they essentially remove type
// safety, like how identifiers across different types can be compared.
#[cfg(test)]
impl Marker for () {}
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(),
)
}
/// Define identifiers for each resource.
macro_rules! ids {
($(
$(#[$($meta:meta)*])*
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>>;
pub type SurfaceId = Id<crate::instance::Surface>;
// Device
pub type DeviceId = Id<crate::device::Device<Dummy>>;
pub type QueueId = DeviceId;
// Resource
pub type BufferId = Id<crate::resource::Buffer<Dummy>>;
pub type StagingBufferId = Id<crate::resource::StagingBuffer<Dummy>>;
pub type TextureViewId = Id<crate::resource::TextureView<Dummy>>;
pub type TextureId = Id<crate::resource::Texture<Dummy>>;
pub type SamplerId = Id<crate::resource::Sampler<Dummy>>;
// Binding model
pub type BindGroupLayoutId = Id<crate::binding_model::BindGroupLayout<Dummy>>;
pub type PipelineLayoutId = Id<crate::binding_model::PipelineLayout<Dummy>>;
pub type BindGroupId = Id<crate::binding_model::BindGroup<Dummy>>;
// Pipeline
pub type ShaderModuleId = Id<crate::pipeline::ShaderModule<Dummy>>;
pub type RenderPipelineId = Id<crate::pipeline::RenderPipeline<Dummy>>;
pub type ComputePipelineId = Id<crate::pipeline::ComputePipeline<Dummy>>;
// Command
pub type CommandEncoderId = CommandBufferId;
pub type CommandBufferId = Id<crate::command::CommandBuffer<Dummy>>;
pub type RenderPassEncoderId = *mut crate::command::RenderPass;
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>>;
ids! {
pub type AdapterId Adapter;
pub type SurfaceId Surface;
pub type DeviceId Device;
pub type QueueId Queue;
pub type BufferId Buffer;
pub type StagingBufferId StagingBuffer;
pub type TextureViewId TextureView;
pub type TextureId Texture;
pub type SamplerId Sampler;
pub type BindGroupLayoutId BindGroupLayout;
pub type PipelineLayoutId PipelineLayout;
pub type BindGroupId BindGroup;
pub type ShaderModuleId ShaderModule;
pub type RenderPipelineId RenderPipeline;
pub type ComputePipelineId ComputePipeline;
pub type CommandEncoderId CommandEncoder;
pub type CommandBufferId CommandBuffer;
pub type RenderPassEncoderId RenderPassEncoder;
pub type ComputePassEncoderId ComputePassEncoder;
pub type RenderBundleEncoderId RenderBundleEncoder;
pub type RenderBundleId RenderBundle;
pub type QuerySetId QuerySet;
}
#[test]
fn test_id_backend() {
@ -270,7 +348,7 @@ fn test_id_backend() {
Backend::Dx12,
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();
assert_eq!(id.backend(), b);
assert_eq!(backend, b);
@ -292,7 +370,7 @@ fn test_id() {
for &i in &indexes {
for &e in &epochs {
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();
assert_eq!(index, i);
assert_eq!(epoch, e);

View File

@ -2,7 +2,7 @@ use parking_lot::Mutex;
use wgt::Backend;
use crate::{
id::{self},
id::{self, Id, Marker},
Epoch, FastHashMap, Index,
};
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
/// 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;
match self.free.pop() {
Some((index, epoch)) => I::zip(index, epoch + 1, backend),
Some((index, epoch)) => Id::zip(index, epoch + 1, backend),
None => {
let epoch = 1;
let used = self.used.entry(epoch).or_insert_with(Default::default);
@ -60,12 +60,12 @@ impl IdentityValues {
0
};
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;
let (index, epoch, _backend) = id.unzip();
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.
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();
self.free.push((index, epoch));
self.count -= 1;
@ -86,24 +86,24 @@ impl IdentityValues {
}
#[derive(Debug)]
pub struct IdentityManager<I: id::TypedId> {
pub struct IdentityManager<T: Marker> {
pub(super) values: Mutex<IdentityValues>,
_phantom: PhantomData<I>,
_phantom: PhantomData<T>,
}
impl<I: id::TypedId> IdentityManager<I> {
pub fn process(&self, backend: Backend) -> I {
impl<T: Marker> IdentityManager<T> {
pub fn process(&self, backend: Backend) -> Id<T> {
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)
}
pub fn free(&self, id: I) {
pub fn free(&self, id: Id<T>) {
self.values.lock().release(id)
}
}
impl<I: id::TypedId> IdentityManager<I> {
impl<T: Marker> IdentityManager<T> {
pub fn new() -> Self {
Self {
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`.
///
/// See the module-level documentation for details.
pub trait IdentityHandlerFactory<I: id::TypedId> {
pub trait IdentityHandlerFactory<T: Marker> {
type Input: Copy;
/// Create an [`IdentityManager<I>`] implementation that can
/// transform proto-ids into ids of type `I`.
@ -123,11 +123,11 @@ pub trait IdentityHandlerFactory<I: id::TypedId> {
/// and are not generated by wgpu
///
/// [`IdentityManager<I>`]: IdentityManager
fn spawn(&self) -> Arc<IdentityManager<I>> {
fn spawn(&self) -> Arc<IdentityManager<T>> {
Arc::new(IdentityManager::new())
}
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`].
@ -138,13 +138,13 @@ pub trait IdentityHandlerFactory<I: id::TypedId> {
#[derive(Debug)]
pub struct IdentityManagerFactory;
impl<I: id::TypedId> IdentityHandlerFactory<I> for IdentityManagerFactory {
impl<T: Marker> IdentityHandlerFactory<T> for IdentityManagerFactory {
type Input = ();
fn autogenerate_ids() -> bool {
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")
}
}
@ -152,23 +152,25 @@ impl<I: id::TypedId> IdentityHandlerFactory<I> for IdentityManagerFactory {
/// A factory that can build [`IdentityManager`]s for all resource
/// types.
pub trait GlobalIdentityHandlerFactory:
IdentityHandlerFactory<id::AdapterId>
+ IdentityHandlerFactory<id::DeviceId>
+ IdentityHandlerFactory<id::PipelineLayoutId>
+ IdentityHandlerFactory<id::ShaderModuleId>
+ IdentityHandlerFactory<id::BindGroupLayoutId>
+ IdentityHandlerFactory<id::BindGroupId>
+ IdentityHandlerFactory<id::CommandBufferId>
+ IdentityHandlerFactory<id::RenderBundleId>
+ IdentityHandlerFactory<id::RenderPipelineId>
+ IdentityHandlerFactory<id::ComputePipelineId>
+ IdentityHandlerFactory<id::QuerySetId>
+ IdentityHandlerFactory<id::BufferId>
+ IdentityHandlerFactory<id::StagingBufferId>
+ IdentityHandlerFactory<id::TextureId>
+ IdentityHandlerFactory<id::TextureViewId>
+ IdentityHandlerFactory<id::SamplerId>
+ IdentityHandlerFactory<id::SurfaceId>
IdentityHandlerFactory<id::markers::Adapter>
+ IdentityHandlerFactory<id::markers::Device>
+ IdentityHandlerFactory<id::markers::PipelineLayout>
+ IdentityHandlerFactory<id::markers::ShaderModule>
+ IdentityHandlerFactory<id::markers::BindGroupLayout>
+ IdentityHandlerFactory<id::markers::BindGroup>
+ IdentityHandlerFactory<id::markers::CommandBuffer>
+ IdentityHandlerFactory<id::markers::RenderBundle>
+ IdentityHandlerFactory<id::markers::RenderPipeline>
+ IdentityHandlerFactory<id::markers::ComputePipeline>
+ IdentityHandlerFactory<id::markers::QuerySet>
+ IdentityHandlerFactory<id::markers::Buffer>
+ IdentityHandlerFactory<id::markers::StagingBuffer>
+ IdentityHandlerFactory<id::markers::Texture>
+ IdentityHandlerFactory<id::markers::TextureView>
+ IdentityHandlerFactory<id::markers::Sampler>
+ 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]
fn test_epoch_end_of_life() {
use id::TypedId as _;
let man = IdentityManager::<id::BufferId>::new();
let man = IdentityManager::<id::markers::Buffer>::new();
let forced_id = man.mark_as_used(id::BufferId::zip(0, 1, Backend::Empty));
assert_eq!(forced_id.unzip().0, 0);
let id1 = man.process(Backend::Empty);

View File

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

View File

@ -5,7 +5,7 @@ use crate::{
command::ColorAttachmentError,
device::{Device, DeviceError, MissingDownlevelFlags, MissingFeatures, RenderPassContext},
hal_api::HalApi,
id::{ComputePipelineId, PipelineLayoutId, RenderPipelineId, ShaderModuleId},
id::{PipelineLayoutId, ShaderModuleId},
resource::{Resource, ResourceInfo, ResourceType},
resource_log, validation, Label,
};
@ -50,7 +50,7 @@ pub struct ShaderModule<A: HalApi> {
pub(crate) raw: Option<A::ShaderModule>,
pub(crate) device: Arc<Device<A>>,
pub(crate) interface: Option<validation::Interface>,
pub(crate) info: ResourceInfo<ShaderModuleId>,
pub(crate) info: ResourceInfo<ShaderModule<A>>,
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";
fn as_info(&self) -> &ResourceInfo<ShaderModuleId> {
type Marker = crate::id::markers::ShaderModule;
fn as_info(&self) -> &ResourceInfo<Self> {
&self.info
}
fn as_info_mut(&mut self) -> &mut ResourceInfo<ShaderModuleId> {
fn as_info_mut(&mut self) -> &mut ResourceInfo<Self> {
&mut self.info
}
@ -267,7 +269,7 @@ pub struct ComputePipeline<A: HalApi> {
pub(crate) device: Arc<Device<A>>,
pub(crate) _shader_module: Arc<ShaderModule<A>>,
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> {
@ -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";
fn as_info(&self) -> &ResourceInfo<ComputePipelineId> {
type Marker = crate::id::markers::ComputePipeline;
fn as_info(&self) -> &ResourceInfo<Self> {
&self.info
}
fn as_info_mut(&mut self) -> &mut ResourceInfo<ComputePipelineId> {
fn as_info_mut(&mut self) -> &mut ResourceInfo<Self> {
&mut self.info
}
}
@ -515,7 +519,7 @@ pub struct RenderPipeline<A: HalApi> {
pub(crate) strip_index_format: Option<wgt::IndexFormat>,
pub(crate) vertex_steps: Vec<VertexStep>,
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> {
@ -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";
fn as_info(&self) -> &ResourceInfo<RenderPipelineId> {
type Marker = crate::id::markers::RenderPipeline;
fn as_info(&self) -> &ResourceInfo<Self> {
&self.info
}
fn as_info_mut(&mut self) -> &mut ResourceInfo<RenderPipelineId> {
fn as_info_mut(&mut self) -> &mut ResourceInfo<Self> {
&mut self.info
}
}

View File

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

View File

@ -4,7 +4,7 @@ use parking_lot::{RwLock, RwLockReadGuard, RwLockWriteGuard};
use wgt::Backend;
use crate::{
id,
id::{self, Id, Marker},
identity::{IdentityHandlerFactory, IdentityManager},
resource::Resource,
storage::{Element, InvalidId, Storage},
@ -37,14 +37,14 @@ impl RegistryReport {
/// any other dependent resource
///
#[derive(Debug)]
pub struct Registry<I: id::TypedId, T: Resource<I>> {
identity: Arc<IdentityManager<I>>,
storage: RwLock<Storage<T, I>>,
pub struct Registry<T: Resource> {
identity: Arc<IdentityManager<T::Marker>>,
storage: RwLock<Storage<T>>,
backend: Backend,
}
impl<I: id::TypedId, T: Resource<I>> Registry<I, T> {
pub(crate) fn new<F: IdentityHandlerFactory<I>>(backend: Backend, factory: &F) -> Self {
impl<T: Resource> Registry<T> {
pub(crate) fn new<F: IdentityHandlerFactory<T::Marker>>(backend: Backend, factory: &F) -> Self {
Self {
identity: factory.spawn(),
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)
}
}
#[must_use]
pub(crate) struct FutureId<'a, I: id::TypedId, T: Resource<I>> {
id: I,
identity: Arc<IdentityManager<I>>,
data: &'a RwLock<Storage<T, I>>,
pub(crate) struct FutureId<'a, T: Resource> {
id: Id<T::Marker>,
identity: Arc<IdentityManager<T::Marker>>,
data: &'a RwLock<Storage<T>>,
}
impl<I: id::TypedId + Copy, T: Resource<I>> FutureId<'_, I, T> {
impl<T: Resource> FutureId<'_, T> {
#[allow(dead_code)]
pub fn id(&self) -> I {
pub fn id(&self) -> Id<T::Marker> {
self.id
}
pub fn into_id(self) -> I {
pub fn into_id(self) -> Id<T::Marker> {
self.id
}
@ -82,7 +82,7 @@ impl<I: id::TypedId + Copy, T: Resource<I>> FutureId<'_, I, T> {
/// Assign a new resource to this ID.
///
/// 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();
data.insert(self.id, self.init(value));
(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.
/// 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();
debug_assert!(!data.contains(self.id));
data.insert(self.id, value.clone());
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.id
}
}
impl<I: id::TypedId, T: Resource<I>> Registry<I, T> {
pub(crate) fn prepare<F>(&self, id_in: F::Input) -> FutureId<I, T>
impl<T: Resource> Registry<T> {
pub(crate) fn prepare<F, U: Marker>(&self, id_in: F::Input) -> FutureId<T>
where
F: IdentityHandlerFactory<I>,
F: IdentityHandlerFactory<U>,
T::Marker: id::transmute::Transmute<U>,
{
FutureId {
id: if F::autogenerate_ids() {
self.identity.process(self.backend)
} 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(),
data: &self.storage,
}
}
pub(crate) fn request(&self) -> FutureId<I, T> {
pub(crate) fn request(&self) -> FutureId<T> {
FutureId {
id: self.identity.process(self.backend),
identity: self.identity.clone(),
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())
}
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)
}
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()
}
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()
}
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)
}
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();
value.as_info_mut().set_id(id, &self.identity);
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();
storage.remove(id);
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);
//Returning None is legal if it's an error ID
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 type_name = guard.kind();

View File

@ -8,10 +8,7 @@ use crate::{
},
global::Global,
hal_api::HalApi,
id::{
AdapterId, BufferId, DeviceId, QuerySetId, SamplerId, StagingBufferId, SurfaceId,
TextureId, TextureViewId, TypedId,
},
id::{AdapterId, BufferId, DeviceId, Id, Marker, SurfaceId, TextureId},
identity::{GlobalIdentityHandlerFactory, IdentityManager},
init_tracker::{BufferInitTracker, TextureInitTracker},
resource, resource_log,
@ -59,9 +56,9 @@ use std::{
/// [`Device`]: crate::device::resource::Device
/// [`Buffer`]: crate::resource::Buffer
#[derive(Debug)]
pub struct ResourceInfo<Id: TypedId> {
id: Option<Id>,
identity: Option<Arc<IdentityManager<Id>>>,
pub struct ResourceInfo<T: Resource> {
id: Option<Id<T::Marker>>,
identity: Option<Arc<IdentityManager<T::Marker>>>,
/// The index of the last queue submission in which the resource
/// was used.
///
@ -75,7 +72,7 @@ pub struct ResourceInfo<Id: TypedId> {
pub(crate) label: String,
}
impl<Id: TypedId> Drop for ResourceInfo<Id> {
impl<T: Resource> Drop for ResourceInfo<T> {
fn drop(&mut self) {
if let Some(identity) = self.identity.as_ref() {
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)]
pub(crate) fn new(label: &str) -> Self {
Self {
@ -97,7 +94,7 @@ impl<Id: TypedId> ResourceInfo<Id> {
pub(crate) fn label(&self) -> &dyn Debug
where
Id: Debug,
Id<T::Marker>: Debug,
{
if !self.label.is_empty() {
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()
}
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.identity = Some(identity.clone());
}
@ -133,10 +130,11 @@ impl<Id: TypedId> ResourceInfo<Id> {
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;
fn as_info(&self) -> &ResourceInfo<Id>;
fn as_info_mut(&mut self) -> &mut ResourceInfo<Id>;
fn as_info(&self) -> &ResourceInfo<Self>;
fn as_info_mut(&mut self) -> &mut ResourceInfo<Self>;
fn label(&self) -> String {
self.as_info().label.clone()
}
@ -377,7 +375,7 @@ pub struct Buffer<A: HalApi> {
pub(crate) size: wgt::BufferAddress,
pub(crate) initialization_status: RwLock<BufferInitTracker>,
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) bind_groups: Mutex<Vec<Weak<BindGroup<A>>>>,
}
@ -592,14 +590,16 @@ pub enum CreateBufferError {
MissingDownlevelFlags(#[from] MissingDownlevelFlags),
}
impl<A: HalApi> Resource<BufferId> for Buffer<A> {
impl<A: HalApi> Resource for Buffer<A> {
const TYPE: ResourceType = "Buffer";
fn as_info(&self) -> &ResourceInfo<BufferId> {
type Marker = crate::id::markers::Buffer;
fn as_info(&self) -> &ResourceInfo<Self> {
&self.info
}
fn as_info_mut(&mut self) -> &mut ResourceInfo<BufferId> {
fn as_info_mut(&mut self) -> &mut ResourceInfo<Self> {
&mut self.info
}
}
@ -693,7 +693,7 @@ pub struct StagingBuffer<A: HalApi> {
pub(crate) device: Arc<Device<A>>,
pub(crate) size: wgt::BufferAddress,
pub(crate) is_coherent: bool,
pub(crate) info: ResourceInfo<StagingBufferId>,
pub(crate) info: ResourceInfo<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";
fn as_info(&self) -> &ResourceInfo<StagingBufferId> {
type Marker = crate::id::markers::StagingBuffer;
fn as_info(&self) -> &ResourceInfo<Self> {
&self.info
}
fn as_info_mut(&mut self) -> &mut ResourceInfo<StagingBufferId> {
fn as_info_mut(&mut self) -> &mut ResourceInfo<Self> {
&mut self.info
}
@ -773,7 +775,7 @@ pub struct Texture<A: HalApi> {
pub(crate) format_features: wgt::TextureFormatFeatures,
pub(crate) initialization_status: RwLock<TextureInitTracker>,
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) views: Mutex<Vec<Weak<TextureView<A>>>>,
pub(crate) bind_groups: Mutex<Vec<Weak<BindGroup<A>>>>,
@ -1166,14 +1168,16 @@ pub enum CreateTextureError {
MissingDownlevelFlags(#[from] MissingDownlevelFlags),
}
impl<A: HalApi> Resource<TextureId> for Texture<A> {
impl<A: HalApi> Resource for Texture<A> {
const TYPE: ResourceType = "Texture";
fn as_info(&self) -> &ResourceInfo<TextureId> {
type Marker = crate::id::markers::Texture;
fn as_info(&self) -> &ResourceInfo<Self> {
&self.info
}
fn as_info_mut(&mut self) -> &mut ResourceInfo<TextureId> {
fn as_info_mut(&mut self) -> &mut ResourceInfo<Self> {
&mut self.info
}
}
@ -1251,7 +1255,7 @@ pub struct TextureView<A: HalApi> {
pub(crate) render_extent: Result<wgt::Extent3d, TextureViewNotRenderableReason>,
pub(crate) samples: u32,
pub(crate) selector: TextureSelector,
pub(crate) info: ResourceInfo<TextureViewId>,
pub(crate) info: ResourceInfo<TextureView<A>>,
}
impl<A: HalApi> Drop for TextureView<A> {
@ -1329,14 +1333,16 @@ pub enum CreateTextureViewError {
#[non_exhaustive]
pub enum TextureViewDestroyError {}
impl<A: HalApi> Resource<TextureViewId> for TextureView<A> {
impl<A: HalApi> Resource for TextureView<A> {
const TYPE: ResourceType = "TextureView";
fn as_info(&self) -> &ResourceInfo<TextureViewId> {
type Marker = crate::id::markers::TextureView;
fn as_info(&self) -> &ResourceInfo<Self> {
&self.info
}
fn as_info_mut(&mut self) -> &mut ResourceInfo<TextureViewId> {
fn as_info_mut(&mut self) -> &mut ResourceInfo<Self> {
&mut self.info
}
}
@ -1374,7 +1380,7 @@ pub struct SamplerDescriptor<'a> {
pub struct Sampler<A: HalApi> {
pub(crate) raw: Option<A::Sampler>,
pub(crate) device: Arc<Device<A>>,
pub(crate) info: ResourceInfo<SamplerId>,
pub(crate) info: ResourceInfo<Self>,
/// `true` if this is a comparison sampler
pub(crate) comparison: bool,
/// `true` if this is a filtering sampler
@ -1448,14 +1454,16 @@ pub enum CreateSamplerError {
MissingFeatures(#[from] MissingFeatures),
}
impl<A: HalApi> Resource<SamplerId> for Sampler<A> {
impl<A: HalApi> Resource for Sampler<A> {
const TYPE: ResourceType = "Sampler";
fn as_info(&self) -> &ResourceInfo<SamplerId> {
type Marker = crate::id::markers::Sampler;
fn as_info(&self) -> &ResourceInfo<Self> {
&self.info
}
fn as_info_mut(&mut self) -> &mut ResourceInfo<SamplerId> {
fn as_info_mut(&mut self) -> &mut ResourceInfo<Self> {
&mut self.info
}
}
@ -1479,7 +1487,7 @@ pub type QuerySetDescriptor<'a> = wgt::QuerySetDescriptor<Label<'a>>;
pub struct QuerySet<A: HalApi> {
pub(crate) raw: Option<A::QuerySet>,
pub(crate) device: Arc<Device<A>>,
pub(crate) info: ResourceInfo<QuerySetId>,
pub(crate) info: ResourceInfo<Self>,
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";
fn as_info(&self) -> &ResourceInfo<QuerySetId> {
type Marker = crate::id::markers::QuerySet;
fn as_info(&self) -> &ResourceInfo<Self> {
&self.info
}
fn as_info_mut(&mut self) -> &mut ResourceInfo<QuerySetId> {
fn as_info_mut(&mut self) -> &mut ResourceInfo<Self> {
&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 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.
#[derive(Debug)]
@ -30,47 +33,41 @@ pub(crate) struct InvalidId;
/// values, so you should use an id allocator like `IdentityManager`
/// that keeps the index values dense and close to zero.
#[derive(Debug)]
pub struct Storage<T, I>
pub struct Storage<T>
where
T: Resource<I>,
I: id::TypedId,
T: Resource,
{
pub(crate) map: Vec<Element<T>>,
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
T: Resource<I>,
I: id::TypedId,
T: Resource,
{
type Output = Arc<T>;
fn index(&self, id: I) -> &Arc<T> {
fn index(&self, id: Id<T::Marker>) -> &Arc<T> {
self.get(id).unwrap()
}
}
impl<T, I> Storage<T, I>
impl<T> Storage<T>
where
T: Resource<I>,
I: id::TypedId,
T: Resource,
{
pub(crate) fn new() -> Self {
Self {
map: Vec::new(),
kind: T::TYPE,
_phantom: PhantomData,
}
}
}
impl<T, I> Storage<T, I>
impl<T> Storage<T>
where
T: Resource<I>,
I: id::TypedId,
T: Resource,
{
#[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();
match self.map.get(index as usize) {
Some(&Element::Vacant) => false,
@ -88,7 +85,7 @@ where
/// 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
/// 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 (result, storage_epoch) = match self.map.get(index as usize) {
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.
/// 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 (result, storage_epoch) = match self.map.get(index as usize) {
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.
/// 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)?))
}
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();
match self.map.get(index as usize) {
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);
let (index, epoch, _backend) = id.unzip();
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);
let (index, epoch, _) = id.unzip();
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();
match std::mem::replace(
&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);
let (index, epoch, _) = id.unzip();
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);
let (index, epoch, _) = id.unzip();
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
.iter()
.enumerate()
.filter_map(move |(index, x)| match *x {
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,
})

View File

@ -10,7 +10,7 @@ use std::{borrow::Cow, marker::PhantomData, sync::Arc};
use super::{PendingTransition, ResourceTracker};
use crate::{
hal_api::HalApi,
id::{BufferId, TypedId},
id::BufferId,
resource::{Buffer, Resource},
snatch::SnatchGuard,
storage::Storage,
@ -26,7 +26,6 @@ use wgt::{strict_assert, strict_assert_eq};
impl ResourceUses for BufferUses {
const EXCLUSIVE: Self = Self::EXCLUSIVE;
type Id = BufferId;
type Selector = ();
fn bits(self) -> u16 {
@ -92,7 +91,7 @@ impl<A: HalApi> BufferBindGroupState<A> {
/// Adds the given resource with the given state.
pub fn add_single<'a>(
&self,
storage: &'a Storage<Buffer<A>, BufferId>,
storage: &'a Storage<Buffer<A>>,
id: BufferId,
state: BufferUses,
) -> Option<&'a Arc<Buffer<A>>> {
@ -110,7 +109,7 @@ impl<A: HalApi> BufferBindGroupState<A> {
pub(crate) struct BufferUsageScope<A: HalApi> {
state: Vec<BufferUses>,
metadata: ResourceMetadata<A, BufferId, Buffer<A>>,
metadata: ResourceMetadata<A, Buffer<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.
pub fn merge_single<'a>(
&mut self,
storage: &'a Storage<Buffer<A>, BufferId>,
storage: &'a Storage<Buffer<A>>,
id: BufferId,
new_state: BufferUses,
) -> Result<&'a Arc<Buffer<A>>, UsageConflict> {
@ -288,12 +287,12 @@ pub(crate) struct BufferTracker<A: HalApi> {
start: Vec<BufferUses>,
end: Vec<BufferUses>,
metadata: ResourceMetadata<A, BufferId, Buffer<A>>,
metadata: ResourceMetadata<A, Buffer<A>>,
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.
///
/// 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>(
start_states: Option<&mut [BufferUses]>,
current_states: &mut [BufferUses],
resource_metadata: &mut ResourceMetadata<A, BufferId, Buffer<A>>,
resource_metadata: &mut ResourceMetadata<A, Buffer<A>>,
index32: u32,
index: usize,
state_provider: BufferStateProvider<'_>,
metadata_provider: ResourceMetadataProvider<'_, A, BufferId, Buffer<A>>,
metadata_provider: ResourceMetadataProvider<'_, A, Buffer<A>>,
) -> Result<(), UsageConflict> {
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>(
start_states: Option<&mut [BufferUses]>,
current_states: &mut [BufferUses],
resource_metadata: &mut ResourceMetadata<A, BufferId, Buffer<A>>,
resource_metadata: &mut ResourceMetadata<A, Buffer<A>>,
index: usize,
start_state_provider: BufferStateProvider<'_>,
end_state_provider: Option<BufferStateProvider<'_>>,
metadata_provider: ResourceMetadataProvider<'_, A, BufferId, Buffer<A>>,
metadata_provider: ResourceMetadataProvider<'_, A, Buffer<A>>,
barriers: &mut Vec<PendingTransition<BufferUses>>,
) {
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>(
start_states: Option<&mut [BufferUses]>,
current_states: &mut [BufferUses],
resource_metadata: &mut ResourceMetadata<A, BufferId, Buffer<A>>,
resource_metadata: &mut ResourceMetadata<A, Buffer<A>>,
index: usize,
start_state_provider: 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_end_state =
@ -777,7 +776,7 @@ unsafe fn merge<A: HalApi>(
index32: u32,
index: usize,
state_provider: BufferStateProvider<'_>,
metadata_provider: ResourceMetadataProvider<'_, A, BufferId, Buffer<A>>,
metadata_provider: ResourceMetadataProvider<'_, A, Buffer<A>>,
) -> Result<(), UsageConflict> {
let current_state = unsafe { current_states.get_unchecked_mut(index) };
let new_state = unsafe { state_provider.get_state(index) };

View File

@ -1,6 +1,6 @@
//! 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 std::{borrow::Cow, marker::PhantomData, mem, sync::Arc};
use wgt::strict_assert;
@ -13,7 +13,7 @@ use wgt::strict_assert;
/// members, but a bit vector tracks occupancy, so iteration touches
/// only occupied elements.
#[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`.
owned: BitVec<usize>,
@ -21,10 +21,10 @@ pub(super) struct ResourceMetadata<A: HalApi, I: TypedId, T: Resource<I>> {
resources: Vec<Option<Arc<T>>>,
/// 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 {
Self {
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
/// 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.
Direct { resource: Cow<'a, Arc<T>> },
/// Comes from another metadata tracker.
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.
///
/// # Safety

View File

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

View File

@ -4,24 +4,27 @@
* distinction between a usage scope and a full tracker.
!*/
use std::{marker::PhantomData, sync::Arc};
use std::sync::Arc;
use parking_lot::Mutex;
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,
};
use super::ResourceTracker;
/// Satisfy clippy.
type Pair<T> = (Id<<T as Resource>::Marker>, Arc<T>);
/// Stores all the resources that a bind group stores.
#[derive(Debug)]
pub(crate) struct StatelessBindGroupSate<Id: TypedId, T: Resource<Id>> {
resources: Mutex<Vec<(Id, Arc<T>)>>,
pub(crate) struct StatelessBindGroupSate<T: Resource> {
resources: Mutex<Vec<Pair<T>>>,
}
impl<Id: TypedId, T: Resource<Id>> StatelessBindGroupSate<Id, T> {
impl<T: Resource> StatelessBindGroupSate<T> {
pub fn new() -> Self {
Self {
resources: Mutex::new(Vec::new()),
@ -58,7 +61,7 @@ impl<Id: TypedId, T: Resource<Id>> StatelessBindGroupSate<Id, T> {
}
/// 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 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.
#[derive(Debug)]
pub(crate) struct StatelessTracker<A: HalApi, Id: TypedId, T: Resource<Id>> {
metadata: ResourceMetadata<A, Id, T>,
_phantom: PhantomData<Id>,
pub(crate) struct StatelessTracker<A: HalApi, T: Resource> {
metadata: ResourceMetadata<A, T>,
}
impl<A: HalApi, Id: TypedId, T: Resource<Id>> ResourceTracker<Id, T>
for StatelessTracker<A, Id, T>
{
impl<A: HalApi, T: Resource> ResourceTracker<T> for StatelessTracker<A, T> {
/// Try to remove the given resource from the tracker iff we have the last reference to the
/// 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,
/// 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;
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 {
Self {
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,
/// 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 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,
/// 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 (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;
if index > self.metadata.size() {
return None;

View File

@ -22,7 +22,7 @@
use super::{range::RangedStates, PendingTransition, PendingTransitionList, ResourceTracker};
use crate::{
hal_api::HalApi,
id::{TextureId, TypedId},
id::TextureId,
resource::{Resource, Texture, TextureInner},
snatch::SnatchGuard,
track::{
@ -50,7 +50,6 @@ pub struct TextureSelector {
impl ResourceUses for TextureUses {
const EXCLUSIVE: Self = Self::EXCLUSIVE;
type Id = TextureId;
type Selector = TextureSelector;
fn bits(self) -> u16 {
@ -232,7 +231,7 @@ impl TextureStateSet {
#[derive(Debug)]
pub(crate) struct TextureUsageScope<A: HalApi> {
set: TextureStateSet,
metadata: ResourceMetadata<A, TextureId, Texture<A>>,
metadata: ResourceMetadata<A, Texture<A>>,
}
impl<A: HalApi> TextureUsageScope<A> {
@ -387,14 +386,14 @@ pub(crate) struct TextureTracker<A: HalApi> {
start_set: TextureStateSet,
end_set: TextureStateSet,
metadata: ResourceMetadata<A, TextureId, Texture<A>>,
metadata: ResourceMetadata<A, Texture<A>>,
temp: Vec<PendingTransition<TextureUses>>,
_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
/// resource and the epoch matches.
///
@ -864,10 +863,10 @@ impl<'a> TextureStateProvider<'a> {
unsafe fn insert_or_merge<A: HalApi>(
texture_selector: &TextureSelector,
current_state_set: &mut TextureStateSet,
resource_metadata: &mut ResourceMetadata<A, TextureId, Texture<A>>,
resource_metadata: &mut ResourceMetadata<A, Texture<A>>,
index: usize,
state_provider: TextureStateProvider<'_>,
metadata_provider: ResourceMetadataProvider<'_, A, TextureId, Texture<A>>,
metadata_provider: ResourceMetadataProvider<'_, A, Texture<A>>,
) -> Result<(), UsageConflict> {
let currently_owned = unsafe { resource_metadata.contains_unchecked(index) };
@ -920,11 +919,11 @@ unsafe fn insert_or_barrier_update<A: HalApi>(
texture_selector: &TextureSelector,
start_state: Option<&mut TextureStateSet>,
current_state_set: &mut TextureStateSet,
resource_metadata: &mut ResourceMetadata<A, TextureId, Texture<A>>,
resource_metadata: &mut ResourceMetadata<A, Texture<A>>,
index: usize,
start_state_provider: TextureStateProvider<'_>,
end_state_provider: Option<TextureStateProvider<'_>>,
metadata_provider: ResourceMetadataProvider<'_, A, TextureId, Texture<A>>,
metadata_provider: ResourceMetadataProvider<'_, A, Texture<A>>,
barriers: &mut Vec<PendingTransition<TextureUses>>,
) {
let currently_owned = unsafe { resource_metadata.contains_unchecked(index) };
@ -973,11 +972,11 @@ unsafe fn insert<A: HalApi>(
texture_selector: Option<&TextureSelector>,
start_state: Option<&mut TextureStateSet>,
end_state: &mut TextureStateSet,
resource_metadata: &mut ResourceMetadata<A, TextureId, Texture<A>>,
resource_metadata: &mut ResourceMetadata<A, Texture<A>>,
index: usize,
start_state_provider: 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) };
match start_layers {
@ -1060,7 +1059,7 @@ unsafe fn merge<A: HalApi>(
current_state_set: &mut TextureStateSet,
index: usize,
state_provider: TextureStateProvider<'_>,
metadata_provider: ResourceMetadataProvider<'_, A, TextureId, Texture<A>>,
metadata_provider: ResourceMetadataProvider<'_, A, Texture<A>>,
) -> Result<(), UsageConflict> {
let current_simple = unsafe { current_state_set.simple.get_unchecked_mut(index) };
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::device::DeviceLostClosure;
use wgc::id::TypedId;
use wgt::WasmNotSendSync;
const LABEL: &str = "label";
@ -604,7 +603,7 @@ impl crate::Context for ContextWgpuCore {
id: queue_id,
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 {
@ -1805,7 +1804,8 @@ impl crate::Context for ContextWgpuCore {
if let Err(cause) = wgc::gfx_select!(
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(
&encoder_data.error_sink,
cause,
@ -1888,7 +1888,8 @@ impl crate::Context for ContextWgpuCore {
if let Err(cause) =
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(
&encoder_data.error_sink,
cause,
@ -2922,10 +2923,10 @@ impl crate::Context for ContextWgpuCore {
impl<T> From<ObjectId> for wgc::id::Id<T>
where
T: 'static + WasmNotSendSync,
T: wgc::id::Marker,
{
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
unsafe { Self::from_raw(id) }
}
@ -2933,10 +2934,10 @@ where
impl<T> From<wgc::id::Id<T>> for ObjectId
where
T: 'static + WasmNotSendSync,
T: wgc::id::Marker,
{
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)
}
}