1245: Trace pipeline creation before it actually happens r=kvark a=kvark

**Connections**
Fixes #1174

**Description**
We want to add descriptors to the trace before panicking if anything goes wacky.

**Testing**
tested on wgpu-rs examples

Co-authored-by: Dzmitry Malyshau <kvarkus@gmail.com>
This commit is contained in:
bors[bot]
2021-03-04 01:00:47 +00:00
committed by GitHub
12 changed files with 562 additions and 600 deletions

1
Cargo.lock generated
View File

@@ -956,7 +956,6 @@ dependencies = [
"log",
"num-traits",
"petgraph",
"serde",
"spirv_headers",
"thiserror",
]

View File

@@ -196,13 +196,11 @@ impl GlobalPlay for wgc::hub::Global<IdentityPassThroughFactory> {
self.sampler_drop::<B>(id);
}
A::GetSwapChainTexture { id, parent_id } => {
if let Some(id) = id {
self.device_maintain_ids::<B>(device).unwrap();
self.swap_chain_get_current_texture_view::<B>(parent_id, id)
.unwrap()
.view_id
.unwrap();
}
self.device_maintain_ids::<B>(device).unwrap();
self.swap_chain_get_current_texture_view::<B>(parent_id, id)
.unwrap()
.view_id
.unwrap();
}
A::CreateBindGroupLayout(id, desc) => {
let (_, error) = self.device_create_bind_group_layout::<B>(device, &desc, id);
@@ -254,10 +252,21 @@ impl GlobalPlay for wgc::hub::Global<IdentityPassThroughFactory> {
A::DestroyShaderModule(id) => {
self.shader_module_drop::<B>(id);
}
A::CreateComputePipeline(id, desc) => {
A::CreateComputePipeline {
id,
desc,
implicit_context,
} => {
self.device_maintain_ids::<B>(device).unwrap();
let implicit_ids =
implicit_context
.as_ref()
.map(|ic| wgc::device::ImplicitPipelineIds {
root_id: ic.root_id,
group_ids: &ic.group_ids,
});
let (_, _, error) =
self.device_create_compute_pipeline::<B>(device, &desc, id, None);
self.device_create_compute_pipeline::<B>(device, &desc, id, implicit_ids);
if let Some(e) = error {
panic!("{:?}", e);
}
@@ -265,10 +274,21 @@ impl GlobalPlay for wgc::hub::Global<IdentityPassThroughFactory> {
A::DestroyComputePipeline(id) => {
self.compute_pipeline_drop::<B>(id);
}
A::CreateRenderPipeline(id, desc) => {
A::CreateRenderPipeline {
id,
desc,
implicit_context,
} => {
self.device_maintain_ids::<B>(device).unwrap();
let implicit_ids =
implicit_context
.as_ref()
.map(|ic| wgc::device::ImplicitPipelineIds {
root_id: ic.root_id,
group_ids: &ic.group_ids,
});
let (_, _, error) =
self.device_create_render_pipeline::<B>(device, &desc, id, None);
self.device_create_render_pipeline::<B>(device, &desc, id, implicit_ids);
if let Some(e) = error {
panic!("{:?}", e);
}

View File

@@ -15,14 +15,17 @@
),
data: "empty.wgsl",
),
CreateComputePipeline(Id(0, 1, Empty), (
label: None,
layout: Some(Id(0, 1, Empty)),
stage: (
module: Id(0, 1, Empty),
entry_point: "main",
CreateComputePipeline(
id: Id(0, 1, Empty),
desc: (
label: None,
layout: Some(Id(0, 1, Empty)),
stage: (
module: Id(0, 1, Empty),
entry_point: "main",
),
),
)),
),
CreateBuffer(Id(0, 1, Empty), (
label: None,
size: 16,

View File

@@ -1,167 +1,170 @@
(
features: (bits: 0x0),
expectations: [
// Ensuring that mapping zero-inits buffers.
(
name: "mapped_at_creation: false, with MAP_WRITE",
buffer: (index: 0, epoch: 1),
offset: 0,
data: Raw([0x00, 0x00, 0x00, 0x00]),
),
(
name: "mapped_at_creation: false, without MAP_WRITE",
buffer: (index: 1, epoch: 1),
offset: 0,
data: Raw([0x00, 0x00, 0x00, 0x00]),
),
(
name: "partially written buffer",
buffer: (index: 2, epoch: 1),
offset: 0,
data: Raw([0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x80, 0xBF,
0x00, 0x00, 0x80, 0xBF,
0x00, 0x00, 0x80, 0x3F,
0x00, 0x00, 0x80, 0x3F,
0x00, 0x00, 0x00, 0x00]),
),
// Ensuring that binding zero-inits buffers
// (by observing correct side effects of compute shader reading & writing values)
(
name: "buffer has correct values",
buffer: (index: 3, epoch: 1),
offset: 0,
data: Raw([0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00]),
)
],
actions: [
CreateBuffer(
Id(0, 1, Empty),
(
label: Some("mapped_at_creation: false, with MAP_WRITE"),
size: 16,
usage: (
bits: 131, // STORAGE + MAP_READ + MAP_WRITE
),
mapped_at_creation: false,
),
),
CreateBuffer(
Id(1, 1, Empty),
(
label: Some("mapped_at_creation: false, without MAP_WRITE"),
size: 16,
usage: (
bits: 129, // STORAGE + MAP_READ
),
mapped_at_creation: false,
),
),
CreateBuffer(
Id(2, 1, Empty),
(
label: Some("partially written"),
size: 24,
usage: (
bits: 9, // MAP_READ + COPY_DST
),
mapped_at_creation: false,
),
),
WriteBuffer(
id: Id(2, 1, Empty),
data: "data1.bin",
range: (
start: 4,
end: 20,
),
queued: true,
),
CreateShaderModule(
id: Id(0, 1, Empty),
desc: (
label: None,
flags: (bits: 3),
),
data: "buffer-zero-init-for-binding.wgsl",
),
CreateBuffer(Id(3, 1, Empty), (
label: Some("used in binding"),
size: 16,
usage: (
bits: 129, // STORAGE + MAP_READ
),
mapped_at_creation: false,
)),
CreateBindGroupLayout(Id(0, 1, Empty), (
label: None,
entries: [
(
binding: 0,
visibility: (
bits: 4,
),
ty: Buffer(
ty: Storage(
read_only: false,
),
has_dynamic_offset: false,
min_binding_size: Some(16),
),
count: None,
),
],
)),
CreateBindGroup(Id(0, 1, Empty), (
label: None,
layout: Id(0, 1, Empty),
entries: [
(
binding: 0,
resource: Buffer((
buffer_id: Id(3, 1, Empty),
offset: 0,
size: Some(16),
)),
),
],
)),
CreatePipelineLayout(Id(0, 1, Empty), (
label: None,
bind_group_layouts: [
Id(0, 1, Empty),
],
push_constant_ranges: [],
)),
CreateComputePipeline(Id(0, 1, Empty), (
label: None,
layout: Some(Id(0, 1, Empty)),
stage: (
module: Id(0, 1, Empty),
entry_point: "main",
),
)),
Submit(1, [
RunComputePass(
base: (
label: None,
commands: [
SetPipeline(Id(0, 1, Empty)),
SetBindGroup(
index: 0,
num_dynamic_offsets: 0,
bind_group_id: Id(0, 1, Empty),
),
Dispatch((4, 1, 1)),
],
dynamic_offsets: [],
string_data: [],
push_constant_data: [],
),
)
]),
]
)
(
features: (bits: 0x0),
expectations: [
// Ensuring that mapping zero-inits buffers.
(
name: "mapped_at_creation: false, with MAP_WRITE",
buffer: (index: 0, epoch: 1),
offset: 0,
data: Raw([0x00, 0x00, 0x00, 0x00]),
),
(
name: "mapped_at_creation: false, without MAP_WRITE",
buffer: (index: 1, epoch: 1),
offset: 0,
data: Raw([0x00, 0x00, 0x00, 0x00]),
),
(
name: "partially written buffer",
buffer: (index: 2, epoch: 1),
offset: 0,
data: Raw([0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x80, 0xBF,
0x00, 0x00, 0x80, 0xBF,
0x00, 0x00, 0x80, 0x3F,
0x00, 0x00, 0x80, 0x3F,
0x00, 0x00, 0x00, 0x00]),
),
// Ensuring that binding zero-inits buffers
// (by observing correct side effects of compute shader reading & writing values)
(
name: "buffer has correct values",
buffer: (index: 3, epoch: 1),
offset: 0,
data: Raw([0x00, 0x00, 0x00, 0x00,
0x01, 0x00, 0x00, 0x00,
0x02, 0x00, 0x00, 0x00,
0x03, 0x00, 0x00, 0x00]),
)
],
actions: [
CreateBuffer(
Id(0, 1, Empty),
(
label: Some("mapped_at_creation: false, with MAP_WRITE"),
size: 16,
usage: (
bits: 131, // STORAGE + MAP_READ + MAP_WRITE
),
mapped_at_creation: false,
),
),
CreateBuffer(
Id(1, 1, Empty),
(
label: Some("mapped_at_creation: false, without MAP_WRITE"),
size: 16,
usage: (
bits: 129, // STORAGE + MAP_READ
),
mapped_at_creation: false,
),
),
CreateBuffer(
Id(2, 1, Empty),
(
label: Some("partially written"),
size: 24,
usage: (
bits: 9, // MAP_READ + COPY_DST
),
mapped_at_creation: false,
),
),
WriteBuffer(
id: Id(2, 1, Empty),
data: "data1.bin",
range: (
start: 4,
end: 20,
),
queued: true,
),
CreateShaderModule(
id: Id(0, 1, Empty),
desc: (
label: None,
flags: (bits: 3),
),
data: "buffer-zero-init-for-binding.wgsl",
),
CreateBuffer(Id(3, 1, Empty), (
label: Some("used in binding"),
size: 16,
usage: (
bits: 129, // STORAGE + MAP_READ
),
mapped_at_creation: false,
)),
CreateBindGroupLayout(Id(0, 1, Empty), (
label: None,
entries: [
(
binding: 0,
visibility: (
bits: 4,
),
ty: Buffer(
ty: Storage(
read_only: false,
),
has_dynamic_offset: false,
min_binding_size: Some(16),
),
count: None,
),
],
)),
CreateBindGroup(Id(0, 1, Empty), (
label: None,
layout: Id(0, 1, Empty),
entries: [
(
binding: 0,
resource: Buffer((
buffer_id: Id(3, 1, Empty),
offset: 0,
size: Some(16),
)),
),
],
)),
CreatePipelineLayout(Id(0, 1, Empty), (
label: None,
bind_group_layouts: [
Id(0, 1, Empty),
],
push_constant_ranges: [],
)),
CreateComputePipeline(
id: Id(0, 1, Empty),
desc: (
label: None,
layout: Some(Id(0, 1, Empty)),
stage: (
module: Id(0, 1, Empty),
entry_point: "main",
),
),
),
Submit(1, [
RunComputePass(
base: (
label: None,
commands: [
SetPipeline(Id(0, 1, Empty)),
SetBindGroup(
index: 0,
num_dynamic_offsets: 0,
bind_group_id: Id(0, 1, Empty),
),
Dispatch((4, 1, 1)),
],
dynamic_offsets: [],
string_data: [],
push_constant_data: [],
),
)
]),
]
)

View File

@@ -53,28 +53,31 @@
bind_group_layouts: [],
push_constant_ranges: [],
)),
CreateRenderPipeline(Id(0, 1, Empty), (
label: None,
layout: Some(Id(0, 1, Empty)),
vertex: (
stage: (
module: Id(0, 1, Empty),
entry_point: "vs_main",
),
buffers: [],
),
fragment: Some((
stage: (
module: Id(0, 1, Empty),
entry_point: "fs_main",
),
targets: [
(
format: Rgba8Unorm,
CreateRenderPipeline(
id: Id(0, 1, Empty),
desc: (
label: None,
layout: Some(Id(0, 1, Empty)),
vertex: (
stage: (
module: Id(0, 1, Empty),
entry_point: "vs_main",
),
],
)),
)),
buffers: [],
),
fragment: Some((
stage: (
module: Id(0, 1, Empty),
entry_point: "fs_main",
),
targets: [
(
format: Rgba8Unorm,
),
],
)),
),
),
Submit(1, [
RunRenderPass(
base: (

View File

@@ -16,9 +16,9 @@ default = []
# Enable SPIRV-Cross
cross = ["gfx-backend-metal/cross", "gfx-backend-gl/cross"]
# Enable API tracing
trace = ["ron", "serde", "wgt/trace", "naga/serialize"]
trace = ["ron", "serde", "wgt/trace", "arrayvec/serde"]
# Enable API replaying
replay = ["serde", "wgt/replay", "naga/deserialize"]
replay = ["serde", "wgt/replay", "arrayvec/serde"]
# Enable serializable compute/render passes, and bundle encoders.
serial-pass = ["serde", "wgt/serde", "arrayvec/serde"]

View File

@@ -128,6 +128,11 @@ impl RenderBundleEncoder {
}
}
#[cfg(feature = "trace")]
pub(crate) fn to_base_pass(&self) -> BasePass<RenderCommand> {
BasePass::from_ref(self.base.as_ref())
}
pub fn parent(&self) -> id::DeviceId {
self.parent_id
}
@@ -552,11 +557,6 @@ unsafe impl Send for RenderBundle {}
unsafe impl Sync for RenderBundle {}
impl RenderBundle {
#[cfg(feature = "trace")]
pub(crate) fn to_base_pass(&self) -> BasePass<RenderCommand> {
BasePass::from_ref(self.base.as_ref())
}
/// Actually encode the contents into a native command buffer.
///
/// This is partially duplicating the logic of `command_encoder_run_render_pass`.

View File

@@ -49,8 +49,6 @@ pub mod queue;
pub mod trace;
use smallvec::SmallVec;
#[cfg(feature = "trace")]
use trace::{Action, Trace};
pub const MAX_COLOR_TARGETS: usize = 4;
pub const MAX_MIP_LEVELS: u32 = 16;
@@ -290,7 +288,7 @@ pub struct Device<B: hal::Backend> {
// to borrow Device immutably, such as `write_buffer`, `write_texture`, and `buffer_unmap`.
pending_writes: queue::PendingWrites<B>,
#[cfg(feature = "trace")]
pub(crate) trace: Option<Mutex<Trace>>,
pub(crate) trace: Option<Mutex<trace::Trace>>,
}
#[derive(Clone, Debug, Error)]
@@ -359,9 +357,9 @@ impl<B: GfxBackend> Device<B> {
life_tracker: Mutex::new(life::LifetimeTracker::new()),
temp_suspected: life::SuspectedResources::default(),
#[cfg(feature = "trace")]
trace: trace_path.and_then(|path| match Trace::new(path) {
trace: trace_path.and_then(|path| match trace::Trace::new(path) {
Ok(mut trace) => {
trace.add(Action::Init {
trace.add(trace::Action::Init {
desc: desc.clone(),
backend: B::VARIANT,
});
@@ -1787,14 +1785,13 @@ impl<B: GfxBackend> Device<B> {
//TODO: refactor this. It's the only method of `Device` that registers new objects
// (the pipeline layout).
fn derive_pipeline_layout<G: GlobalIdentityHandlerFactory>(
fn derive_pipeline_layout(
&self,
self_id: id::DeviceId,
implicit_pipeline_ids: Option<ImplicitPipelineIds<G>>,
implicit_context: Option<ImplicitPipelineContext>,
mut derived_group_layouts: ArrayVec<[binding_model::BindEntryMap; MAX_BIND_GROUPS]>,
bgl_guard: &mut Storage<binding_model::BindGroupLayout<B>, id::BindGroupLayoutId>,
pipeline_layout_guard: &mut Storage<binding_model::PipelineLayout<B>, id::PipelineLayoutId>,
hub: &Hub<B, G>,
) -> Result<
(id::PipelineLayoutId, pipeline::ImplicitBindGroupCount),
pipeline::ImplicitLayoutError,
@@ -1808,10 +1805,9 @@ impl<B: GfxBackend> Device<B> {
{
derived_group_layouts.pop();
}
let ids = implicit_pipeline_ids
.as_ref()
.ok_or(pipeline::ImplicitLayoutError::MissingIds(0))?;
if ids.group_ids.len() < derived_group_layouts.len() {
let mut ids = implicit_context.ok_or(pipeline::ImplicitLayoutError::MissingIds(0))?;
let group_count = derived_group_layouts.len();
if ids.group_ids.len() < group_count {
tracing::error!(
"Not enough bind group IDs ({}) specified for the implicit layout ({})",
ids.group_ids.len(),
@@ -1822,66 +1818,33 @@ impl<B: GfxBackend> Device<B> {
));
}
let mut derived_group_layout_ids =
ArrayVec::<[id::BindGroupLayoutId; MAX_BIND_GROUPS]>::new();
for (bgl_id, map) in ids.group_ids.iter().zip(derived_group_layouts) {
let processed_id = match Device::deduplicate_bind_group_layout(self_id, &map, bgl_guard)
{
Some(dedup_id) => dedup_id,
for (bgl_id, map) in ids.group_ids.iter_mut().zip(derived_group_layouts) {
match Device::deduplicate_bind_group_layout(self_id, &map, bgl_guard) {
Some(dedup_id) => {
*bgl_id = dedup_id;
}
None => {
#[cfg(feature = "trace")]
let bgl_desc = binding_model::BindGroupLayoutDescriptor {
label: None,
entries: if self.trace.is_some() {
Cow::Owned(map.values().cloned().collect())
} else {
Cow::Borrowed(&[])
},
};
let bgl = self.create_bind_group_layout(self_id, None, map)?;
let out_id = hub.bind_group_layouts.register_identity_locked(
bgl_id.clone(),
bgl,
bgl_guard,
);
#[cfg(feature = "trace")]
if let Some(ref trace) = self.trace {
trace
.lock()
.add(trace::Action::CreateBindGroupLayout(out_id.0, bgl_desc));
}
out_id.0
bgl_guard.insert(*bgl_id, bgl);
}
};
derived_group_layout_ids.push(processed_id);
}
let layout_desc = binding_model::PipelineLayoutDescriptor {
label: None,
bind_group_layouts: Cow::Borrowed(&derived_group_layout_ids),
bind_group_layouts: Cow::Borrowed(&ids.group_ids[..group_count]),
push_constant_ranges: Cow::Borrowed(&[]), //TODO?
};
let layout = self.create_pipeline_layout(self_id, &layout_desc, bgl_guard)?;
let layout_id = hub.pipeline_layouts.register_identity_locked(
ids.root_id.clone(),
layout,
pipeline_layout_guard,
);
#[cfg(feature = "trace")]
if let Some(ref trace) = self.trace {
trace.lock().add(trace::Action::CreatePipelineLayout(
layout_id.0,
layout_desc,
));
}
Ok((layout_id.0, derived_bind_group_count))
pipeline_layout_guard.insert(ids.root_id, layout);
Ok((ids.root_id, derived_bind_group_count))
}
fn create_compute_pipeline<G: GlobalIdentityHandlerFactory>(
&self,
self_id: id::DeviceId,
desc: &pipeline::ComputePipelineDescriptor,
implicit_pipeline_ids: Option<ImplicitPipelineIds<G>>,
implicit_context: Option<ImplicitPipelineContext>,
hub: &Hub<B, G>,
token: &mut Token<Self>,
) -> Result<
@@ -1951,11 +1914,10 @@ impl<B: GfxBackend> Device<B> {
Some(id) => (id, 0),
None => self.derive_pipeline_layout(
self_id,
implicit_pipeline_ids,
implicit_context,
derived_group_layouts,
&mut *bgl_guard,
&mut *pipeline_layout_guard,
&hub,
)?,
};
let layout = pipeline_layout_guard
@@ -1999,7 +1961,7 @@ impl<B: GfxBackend> Device<B> {
&self,
self_id: id::DeviceId,
desc: &pipeline::RenderPipelineDescriptor,
implicit_pipeline_ids: Option<ImplicitPipelineIds<G>>,
implicit_context: Option<ImplicitPipelineContext>,
hub: &Hub<B, G>,
token: &mut Token<Self>,
) -> Result<
@@ -2367,11 +2329,10 @@ impl<B: GfxBackend> Device<B> {
Some(id) => (id, 0),
None => self.derive_pipeline_layout(
self_id,
implicit_pipeline_ids,
implicit_context,
derived_group_layouts,
&mut *bgl_guard,
&mut *pipeline_layout_guard,
&hub,
)?,
};
let layout = pipeline_layout_guard
@@ -2582,11 +2543,32 @@ impl DeviceError {
}
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "trace", derive(serde::Serialize))]
#[cfg_attr(feature = "replay", derive(serde::Deserialize))]
pub struct ImplicitPipelineContext {
pub root_id: id::PipelineLayoutId,
pub group_ids: ArrayVec<[id::BindGroupLayoutId; MAX_BIND_GROUPS]>,
}
pub struct ImplicitPipelineIds<'a, G: GlobalIdentityHandlerFactory> {
pub root_id: Input<G, id::PipelineLayoutId>,
pub group_ids: &'a [Input<G, id::BindGroupLayoutId>],
}
impl<G: GlobalIdentityHandlerFactory> ImplicitPipelineIds<'_, G> {
fn prepare<B: hal::Backend>(self, hub: &Hub<B, G>) -> ImplicitPipelineContext {
ImplicitPipelineContext {
root_id: hub.pipeline_layouts.prepare(self.root_id).into_id(),
group_ids: self
.group_ids
.iter()
.map(|id_in| hub.bind_group_layouts.prepare(id_in.clone()).into_id())
.collect(),
}
}
}
impl<G: GlobalIdentityHandlerFactory> Global<G> {
pub fn adapter_get_swap_chain_preferred_format<B: GfxBackend>(
&self,
@@ -2648,8 +2630,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let hub = B::hub(self);
let mut token = Token::root();
tracing::info!("Create buffer {:?} with ID {:?}", desc, id_in);
let fid = hub.buffers.prepare(id_in);
let (device_guard, mut token) = hub.devices.read(&mut token);
let error = loop {
@@ -2657,6 +2638,18 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
Ok(device) => device,
Err(_) => break DeviceError::Invalid.into(),
};
#[cfg(feature = "trace")]
if let Some(ref trace) = device.trace {
let mut desc = desc.clone();
let mapped_at_creation = mem::replace(&mut desc.mapped_at_creation, false);
if mapped_at_creation && !desc.usage.contains(wgt::BufferUsage::MAP_WRITE) {
desc.usage |= wgt::BufferUsage::COPY_DST;
}
trace
.lock()
.add(trace::Action::CreateBuffer(fid.id(), desc));
}
let mut buffer = match device.create_buffer(device_id, desc, false) {
Ok(buffer) => buffer,
Err(e) => break e,
@@ -2741,17 +2734,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
resource::BufferUse::COPY_DST
};
let id = hub.buffers.register_identity(id_in, buffer, &mut token);
let id = fid.assign(buffer, &mut token);
tracing::info!("Created buffer {:?} with {:?}", id, desc);
#[cfg(feature = "trace")]
if let Some(ref trace) = device.trace {
let mut desc = desc.clone();
let mapped_at_creation = mem::replace(&mut desc.mapped_at_creation, false);
if mapped_at_creation && !desc.usage.contains(wgt::BufferUsage::MAP_WRITE) {
desc.usage |= wgt::BufferUsage::COPY_DST;
}
trace.lock().add(trace::Action::CreateBuffer(id.0, desc));
}
device
.trackers
@@ -2762,9 +2746,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
return (id.0, None);
};
let id = hub
.buffers
.register_error(id_in, desc.label.borrow_or_default(), &mut token);
let id = fid.assign_error(desc.label.borrow_or_default(), &mut token);
(id, Some(error))
}
@@ -2970,6 +2952,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let hub = B::hub(self);
let mut token = Token::root();
let fid = hub.textures.prepare(id_in);
let (adapter_guard, mut token) = hub.adapters.read(&mut token);
let (device_guard, mut token) = hub.devices.read(&mut token);
@@ -2978,6 +2961,13 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
Ok(device) => device,
Err(_) => break DeviceError::Invalid.into(),
};
#[cfg(feature = "trace")]
if let Some(ref trace) = device.trace {
trace
.lock()
.add(trace::Action::CreateTexture(fid.id(), desc.clone()));
}
let adapter = &adapter_guard[device.adapter_id.value];
let texture = match device.create_texture(device_id, adapter, desc) {
Ok(texture) => texture,
@@ -2987,14 +2977,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let num_layers = texture.full_range.layers.end;
let ref_count = texture.life_guard.add_ref();
let id = hub.textures.register_identity(id_in, texture, &mut token);
let id = fid.assign(texture, &mut token);
tracing::info!("Created texture {:?} with {:?}", id, desc);
#[cfg(feature = "trace")]
if let Some(ref trace) = device.trace {
trace
.lock()
.add(trace::Action::CreateTexture(id.0, desc.clone()));
}
device
.trackers
@@ -3005,9 +2989,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
return (id.0, None);
};
let id = hub
.textures
.register_error(id_in, desc.label.borrow_or_default(), &mut token);
let id = fid.assign_error(desc.label.borrow_or_default(), &mut token);
(id, Some(error))
}
@@ -3120,6 +3102,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let hub = B::hub(self);
let mut token = Token::root();
let fid = hub.texture_views.prepare(id_in);
let (device_guard, mut token) = hub.devices.read(&mut token);
let (texture_guard, mut token) = hub.textures.read(&mut token);
@@ -3129,22 +3112,21 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
Err(_) => break resource::CreateTextureViewError::InvalidTexture,
};
let device = &device_guard[texture.device_id.value];
#[cfg(feature = "trace")]
if let Some(ref trace) = device.trace {
trace.lock().add(trace::Action::CreateTextureView {
id: fid.id(),
parent_id: texture_id,
desc: desc.clone(),
});
}
let view = match device.create_texture_view(texture, texture_id, desc) {
Ok(view) => view,
Err(e) => break e,
};
let ref_count = view.life_guard.add_ref();
let id = hub.texture_views.register_identity(id_in, view, &mut token);
#[cfg(feature = "trace")]
if let Some(ref trace) = device.trace {
trace.lock().add(trace::Action::CreateTextureView {
id: id.0,
parent_id: texture_id,
desc: desc.clone(),
});
}
let id = fid.assign(view, &mut token);
device
.trackers
@@ -3155,9 +3137,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
return (id.0, None);
};
let id =
hub.texture_views
.register_error(id_in, desc.label.borrow_or_default(), &mut token);
let id = fid.assign_error(desc.label.borrow_or_default(), &mut token);
(id, Some(error))
}
@@ -3233,27 +3213,27 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let hub = B::hub(self);
let mut token = Token::root();
let (device_guard, mut token) = hub.devices.read(&mut token);
let fid = hub.samplers.prepare(id_in);
let (device_guard, mut token) = hub.devices.read(&mut token);
let error = loop {
let device = match device_guard.get(device_id) {
Ok(device) => device,
Err(_) => break DeviceError::Invalid.into(),
};
#[cfg(feature = "trace")]
if let Some(ref trace) = device.trace {
trace
.lock()
.add(trace::Action::CreateSampler(fid.id(), desc.clone()));
}
let sampler = match device.create_sampler(device_id, desc) {
Ok(sampler) => sampler,
Err(e) => break e,
};
let ref_count = sampler.life_guard.add_ref();
let id = hub.samplers.register_identity(id_in, sampler, &mut token);
#[cfg(feature = "trace")]
if let Some(ref trace) = device.trace {
trace
.lock()
.add(trace::Action::CreateSampler(id.0, desc.clone()));
}
let id = fid.assign(sampler, &mut token);
device
.trackers
@@ -3264,9 +3244,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
return (id.0, None);
};
let id = hub
.samplers
.register_error(id_in, desc.label.borrow_or_default(), &mut token);
let id = fid.assign_error(desc.label.borrow_or_default(), &mut token);
(id, Some(error))
}
@@ -3316,8 +3294,21 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let mut token = Token::root();
let hub = B::hub(self);
let fid = hub.bind_group_layouts.prepare(id_in);
let error = 'outer: loop {
let (device_guard, mut token) = hub.devices.read(&mut token);
let device = match device_guard.get(device_id) {
Ok(device) => device,
Err(_) => break DeviceError::Invalid.into(),
};
#[cfg(feature = "trace")]
if let Some(ref trace) = device.trace {
trace
.lock()
.add(trace::Action::CreateBindGroupLayout(fid.id(), desc.clone()));
}
let mut entry_map = FastHashMap::default();
for entry in desc.entries.iter() {
if entry_map.insert(entry.binding, entry.clone()).is_some() {
@@ -3327,12 +3318,6 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
}
}
let (device_guard, mut token) = hub.devices.read(&mut token);
let device = match device_guard.get(device_id) {
Ok(device) => device,
Err(_) => break DeviceError::Invalid.into(),
};
// If there is an equivalent BGL, just bump the refcount and return it.
// This is only applicable for identity filters that are generating new IDs,
// so their inputs are `PhantomData` of size 0.
@@ -3354,23 +3339,11 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
Err(e) => break e,
};
let id = hub
.bind_group_layouts
.register_identity(id_in, layout, &mut token);
#[cfg(feature = "trace")]
if let Some(ref trace) = device.trace {
trace
.lock()
.add(trace::Action::CreateBindGroupLayout(id.0, desc.clone()));
}
let id = fid.assign(layout, &mut token);
return (id.0, None);
};
let id = hub.bind_group_layouts.register_error(
id_in,
desc.label.borrow_or_default(),
&mut token,
);
let id = fid.assign_error(desc.label.borrow_or_default(), &mut token);
(id, Some(error))
}
@@ -3419,6 +3392,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let hub = B::hub(self);
let mut token = Token::root();
let fid = hub.pipeline_layouts.prepare(id_in);
let (device_guard, mut token) = hub.devices.read(&mut token);
let error = loop {
@@ -3426,6 +3400,12 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
Ok(device) => device,
Err(_) => break DeviceError::Invalid.into(),
};
#[cfg(feature = "trace")]
if let Some(ref trace) = device.trace {
trace
.lock()
.add(trace::Action::CreatePipelineLayout(fid.id(), desc.clone()));
}
let layout = {
let (bgl_guard, _) = hub.bind_group_layouts.read(&mut token);
@@ -3435,21 +3415,11 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
}
};
let id = hub
.pipeline_layouts
.register_identity(id_in, layout, &mut token);
#[cfg(feature = "trace")]
if let Some(ref trace) = device.trace {
trace
.lock()
.add(trace::Action::CreatePipelineLayout(id.0, desc.clone()));
}
let id = fid.assign(layout, &mut token);
return (id.0, None);
};
let id =
hub.pipeline_layouts
.register_error(id_in, desc.label.borrow_or_default(), &mut token);
let id = fid.assign_error(desc.label.borrow_or_default(), &mut token);
(id, Some(error))
}
@@ -3498,6 +3468,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let hub = B::hub(self);
let mut token = Token::root();
let fid = hub.bind_groups.prepare(id_in);
let (device_guard, mut token) = hub.devices.read(&mut token);
let (bind_group_layout_guard, mut token) = hub.bind_group_layouts.read(&mut token);
@@ -3507,11 +3478,17 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
Ok(device) => device,
Err(_) => break DeviceError::Invalid.into(),
};
#[cfg(feature = "trace")]
if let Some(ref trace) = device.trace {
trace
.lock()
.add(trace::Action::CreateBindGroup(fid.id(), desc.clone()));
}
let bind_group_layout = match bind_group_layout_guard.get(desc.layout) {
Ok(layout) => layout,
Err(_) => break binding_model::CreateBindGroupError::InvalidLayout,
};
let bind_group = match device.create_bind_group(
device_id,
bind_group_layout,
@@ -3524,20 +3501,12 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
};
let ref_count = bind_group.life_guard.add_ref();
let id = hub
.bind_groups
.register_identity(id_in, bind_group, &mut token);
let id = fid.assign(bind_group, &mut token);
tracing::debug!(
"Bind group {:?} {:#?}",
id,
hub.bind_groups.read(&mut token).0[id].used
);
#[cfg(feature = "trace")]
if let Some(ref trace) = device.trace {
trace
.lock()
.add(trace::Action::CreateBindGroup(id.0, desc.clone()));
}
device
.trackers
@@ -3548,9 +3517,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
return (id.0, None);
};
let id = hub
.bind_groups
.register_error(id_in, desc.label.borrow_or_default(), &mut token);
let id = fid.assign_error(desc.label.borrow_or_default(), &mut token);
(id, Some(error))
}
@@ -3601,6 +3568,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let hub = B::hub(self);
let mut token = Token::root();
let fid = hub.shader_modules.prepare(id_in);
let (device_guard, mut token) = hub.devices.read(&mut token);
let error = loop {
@@ -3609,53 +3577,38 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
Err(_) => break DeviceError::Invalid.into(),
};
#[cfg(feature = "trace")]
let data = match device.trace {
Some(ref trace) => {
let mut trace = trace.lock();
match source {
pipeline::ShaderModuleSource::SpirV(ref spv) => {
trace.make_binary("spv", unsafe {
std::slice::from_raw_parts(spv.as_ptr() as *const u8, spv.len() * 4)
})
}
pipeline::ShaderModuleSource::Wgsl(ref code) => {
trace.make_binary("wgsl", code.as_bytes())
}
pipeline::ShaderModuleSource::Naga(ref module) => {
let config = ron::ser::PrettyConfig::new();
let mut ron = Vec::new();
ron::ser::to_writer_pretty(&mut ron, &module, config).unwrap();
trace.make_binary("ron", &ron)
}
if let Some(ref trace) = device.trace {
let mut trace = trace.lock();
let data = match source {
pipeline::ShaderModuleSource::SpirV(ref spv) => {
trace.make_binary("spv", unsafe {
std::slice::from_raw_parts(spv.as_ptr() as *const u8, spv.len() * 4)
})
}
}
None => String::new(),
pipeline::ShaderModuleSource::Wgsl(ref code) => {
trace.make_binary("wgsl", code.as_bytes())
}
pipeline::ShaderModuleSource::Naga(_) => {
// we don't want to enable Naga serialization just for this alone
trace.make_binary("ron", &[])
}
};
trace.add(trace::Action::CreateShaderModule {
id: fid.id(),
desc: desc.clone(),
data,
});
};
let shader = match device.create_shader_module(device_id, desc, source) {
Ok(shader) => shader,
Err(e) => break e,
};
let id = hub
.shader_modules
.register_identity(id_in, shader, &mut token);
#[cfg(feature = "trace")]
if let Some(ref trace) = device.trace {
let mut trace = trace.lock();
trace.add(trace::Action::CreateShaderModule {
id: id.0,
desc: desc.clone(),
data,
});
}
let id = fid.assign(shader, &mut token);
return (id.0, None);
};
let id =
hub.shader_modules
.register_error(id_in, desc.label.borrow_or_default(), &mut token);
let id = fid.assign_error(desc.label.borrow_or_default(), &mut token);
(id, Some(error))
}
@@ -3694,6 +3647,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let hub = B::hub(self);
let mut token = Token::root();
let fid = hub.command_buffers.prepare(id_in);
let (device_guard, mut token) = hub.devices.read(&mut token);
let error = loop {
@@ -3728,18 +3682,11 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
raw.begin_primary(hal::command::CommandBufferFlags::ONE_TIME_SUBMIT);
}
let id = hub
.command_buffers
.register_identity(id_in, command_buffer, &mut token);
let id = fid.assign(command_buffer, &mut token);
return (id.0, None);
};
let id = B::hub(self).command_buffers.register_error(
id_in,
desc.label.borrow_or_default(),
&mut token,
);
let id = fid.assign_error(desc.label.borrow_or_default(), &mut token);
(id, Some(error))
}
@@ -3795,37 +3742,34 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let hub = B::hub(self);
let mut token = Token::root();
let (device_guard, mut token) = hub.devices.read(&mut token);
let fid = hub.render_bundles.prepare(id_in);
let (device_guard, mut token) = hub.devices.read(&mut token);
let error = loop {
let device = match device_guard.get(bundle_encoder.parent()) {
Ok(device) => device,
Err(_) => break command::RenderBundleError::INVALID_DEVICE,
};
#[cfg(feature = "trace")]
if let Some(ref trace) = device.trace {
trace.lock().add(trace::Action::CreateRenderBundle {
id: fid.id(),
desc: trace::new_render_bundle_encoder_descriptor(
desc.label.clone(),
&bundle_encoder.context,
),
base: bundle_encoder.to_base_pass(),
});
}
let render_bundle = match bundle_encoder.finish(desc, device, &hub, &mut token) {
Ok(bundle) => bundle,
Err(e) => break e,
};
tracing::debug!("Render bundle {:?} = {:#?}", id_in, render_bundle.used);
tracing::debug!("Render bundle {:#?}", render_bundle.used);
let ref_count = render_bundle.life_guard.add_ref();
let id = hub
.render_bundles
.register_identity(id_in, render_bundle, &mut token);
#[cfg(feature = "trace")]
if let Some(ref trace) = device.trace {
let (bundle_guard, _) = hub.render_bundles.read(&mut token);
let bundle = &bundle_guard[id];
let label = desc.label.as_ref().map(|l| l.as_ref());
trace.lock().add(trace::Action::CreateRenderBundle {
id: id.0,
desc: trace::new_render_bundle_encoder_descriptor(label, &bundle.context),
base: bundle.to_base_pass(),
});
}
let id = fid.assign(render_bundle, &mut token);
device
.trackers
@@ -3836,11 +3780,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
return (id.0, None);
};
let id = B::hub(self).render_bundles.register_error(
id_in,
desc.label.borrow_or_default(),
&mut token,
);
let id = fid.assign_error(desc.label.borrow_or_default(), &mut token);
(id, Some(error))
}
@@ -3886,14 +3826,21 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let hub = B::hub(self);
let mut token = Token::root();
let fid = hub.query_sets.prepare(id_in);
let (device_guard, mut token) = hub.devices.read(&mut token);
let error = loop {
let device = match device_guard.get(device_id) {
Ok(device) => device,
Err(_) => break DeviceError::Invalid.into(),
};
#[cfg(feature = "trace")]
if let Some(ref trace) = device.trace {
trace.lock().add(trace::Action::CreateQuerySet {
id: fid.id(),
desc: desc.clone(),
});
}
match desc.ty {
wgt::QueryType::Timestamp => {
@@ -3942,18 +3889,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
};
let ref_count = query_set.life_guard.add_ref();
let id = hub
.query_sets
.register_identity(id_in, query_set, &mut token);
#[cfg(feature = "trace")]
match device.trace {
Some(ref trace) => trace.lock().add(trace::Action::CreateQuerySet {
id: id.0,
desc: desc.clone(),
}),
None => (),
};
let id = fid.assign(query_set, &mut token);
device
.trackers
@@ -3965,9 +3901,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
return (id.0, None);
};
let id = B::hub(self)
.query_sets
.register_error(id_in, "", &mut token);
let id = fid.assign_error("", &mut token);
(id, Some(error))
}
@@ -3988,12 +3922,11 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let device = &device_guard[device_id];
#[cfg(feature = "trace")]
match device.trace {
Some(ref trace) => trace
if let Some(ref trace) = device.trace {
trace
.lock()
.add(trace::Action::DestroyQuerySet(query_set_id)),
None => (),
};
.add(trace::Action::DestroyQuerySet(query_set_id));
}
device
.lock_life(&mut token)
@@ -4018,40 +3951,36 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let hub = B::hub(self);
let mut token = Token::root();
let fid = hub.render_pipelines.prepare(id_in);
let implicit_context = implicit_pipeline_ids.map(|ipi| ipi.prepare(&hub));
let (device_guard, mut token) = hub.devices.read(&mut token);
let error = loop {
let device = match device_guard.get(device_id) {
Ok(device) => device,
Err(_) => break DeviceError::Invalid.into(),
};
let (pipeline, derived_bind_group_count, layout_id) = match device
.create_render_pipeline(device_id, desc, implicit_pipeline_ids, &hub, &mut token)
#[cfg(feature = "trace")]
if let Some(ref trace) = device.trace {
trace.lock().add(trace::Action::CreateRenderPipeline {
id: fid.id(),
desc: desc.clone(),
implicit_context: implicit_context.clone(),
});
}
let (pipeline, derived_bind_group_count, _layout_id) = match device
.create_render_pipeline(device_id, desc, implicit_context, &hub, &mut token)
{
Ok(pair) => pair,
Err(e) => break e,
};
let id = hub
.render_pipelines
.register_identity(id_in, pipeline, &mut token);
#[cfg(feature = "trace")]
if let Some(ref trace) = device.trace {
trace.lock().add(trace::Action::CreateRenderPipeline(
id.0,
pipeline::RenderPipelineDescriptor {
layout: Some(layout_id),
..desc.clone()
},
));
}
let _ = layout_id;
let id = fid.assign(pipeline, &mut token);
return (id.0, derived_bind_group_count, None);
};
let id =
hub.render_pipelines
.register_error(id_in, desc.label.borrow_or_default(), &mut token);
let id = fid.assign_error(desc.label.borrow_or_default(), &mut token);
(id, 0, Some(error))
}
@@ -4093,7 +4022,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let id = hub
.bind_group_layouts
.register_error(id_in, "<derived>", &mut token);
.prepare(id_in)
.assign_error("<derived>", &mut token);
(id, Some(error))
}
@@ -4149,40 +4079,36 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let hub = B::hub(self);
let mut token = Token::root();
let fid = hub.compute_pipelines.prepare(id_in);
let implicit_context = implicit_pipeline_ids.map(|ipi| ipi.prepare(&hub));
let (device_guard, mut token) = hub.devices.read(&mut token);
let error = loop {
let device = match device_guard.get(device_id) {
Ok(device) => device,
Err(_) => break DeviceError::Invalid.into(),
};
let (pipeline, derived_bind_group_count, layout_id) = match device
.create_compute_pipeline(device_id, desc, implicit_pipeline_ids, &hub, &mut token)
#[cfg(feature = "trace")]
if let Some(ref trace) = device.trace {
trace.lock().add(trace::Action::CreateComputePipeline {
id: fid.id(),
desc: desc.clone(),
implicit_context: implicit_context.clone(),
});
}
let (pipeline, derived_bind_group_count, _layout_id) = match device
.create_compute_pipeline(device_id, desc, implicit_context, &hub, &mut token)
{
Ok(pair) => pair,
Err(e) => break e,
};
let id = hub
.compute_pipelines
.register_identity(id_in, pipeline, &mut token);
#[cfg(feature = "trace")]
if let Some(ref trace) = device.trace {
trace.lock().add(trace::Action::CreateComputePipeline(
id.0,
pipeline::ComputePipelineDescriptor {
layout: Some(layout_id),
..desc.clone()
},
));
}
let _ = layout_id;
let id = fid.assign(pipeline, &mut token);
return (id.0, derived_bind_group_count, None);
};
let id =
hub.compute_pipelines
.register_error(id_in, desc.label.borrow_or_default(), &mut token);
let id = fid.assign_error(desc.label.borrow_or_default(), &mut token);
(id, 0, Some(error))
}
@@ -4224,7 +4150,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let id = hub
.bind_group_layouts
.register_error(id_in, "<derived>", &mut token);
.prepare(id_in)
.assign_error("<derived>", &mut token);
(id, Some(error))
}
@@ -4369,7 +4296,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
if let Some(ref trace) = device.trace {
trace
.lock()
.add(Action::CreateSwapChain(sc_id, desc.clone()));
.add(trace::Action::CreateSwapChain(sc_id, desc.clone()));
}
let swap_chain = swap_chain::SwapChain {

View File

@@ -15,11 +15,11 @@ pub const FILE_NAME: &str = "trace.ron";
#[cfg(feature = "trace")]
pub(crate) fn new_render_bundle_encoder_descriptor<'a>(
label: Option<&'a str>,
label: crate::Label<'a>,
context: &'a super::RenderPassContext,
) -> crate::command::RenderBundleEncoderDescriptor<'a> {
crate::command::RenderBundleEncoderDescriptor {
label: label.map(Cow::Borrowed),
label,
color_formats: Cow::Borrowed(&context.attachments.colors),
depth_stencil_format: context.attachments.depth_stencil,
sample_count: context.sample_count as u32,
@@ -50,7 +50,7 @@ pub enum Action<'a> {
DestroySampler(id::SamplerId),
CreateSwapChain(id::SwapChainId, wgt::SwapChainDescriptor),
GetSwapChainTexture {
id: Option<id::TextureViewId>,
id: id::TextureViewId,
parent_id: id::SwapChainId,
},
PresentSwapChain(id::SwapChainId),
@@ -75,15 +75,19 @@ pub enum Action<'a> {
data: FileName,
},
DestroyShaderModule(id::ShaderModuleId),
CreateComputePipeline(
id::ComputePipelineId,
crate::pipeline::ComputePipelineDescriptor<'a>,
),
CreateComputePipeline {
id: id::ComputePipelineId,
desc: crate::pipeline::ComputePipelineDescriptor<'a>,
#[cfg_attr(feature = "replay", serde(default))]
implicit_context: Option<super::ImplicitPipelineContext>,
},
DestroyComputePipeline(id::ComputePipelineId),
CreateRenderPipeline(
id::RenderPipelineId,
crate::pipeline::RenderPipelineDescriptor<'a>,
),
CreateRenderPipeline {
id: id::RenderPipelineId,
desc: crate::pipeline::RenderPipelineDescriptor<'a>,
#[cfg_attr(feature = "replay", serde(default))]
implicit_context: Option<super::ImplicitPipelineContext>,
},
DestroyRenderPipeline(id::RenderPipelineId),
CreateRenderBundle {
id: id::RenderBundleId,

View File

@@ -302,7 +302,7 @@ thread_local! {
///
/// Note: there can only be one non-borrowed `Token` alive on a thread
/// at a time, which is enforced by `ACTIVE_TOKEN`.
pub struct Token<'a, T: 'a> {
pub(crate) struct Token<'a, T: 'a> {
level: PhantomData<&'a T>,
}
@@ -439,60 +439,58 @@ impl<T: Resource, I: TypedId, F: IdentityHandlerFactory<I>> Registry<T, I, F> {
}
}
impl<T: Resource, I: TypedId + Copy, F: IdentityHandlerFactory<I>> Registry<T, I, F> {
pub fn register<A: Access<T>>(&self, id: I, value: T, _token: &mut Token<A>) {
debug_assert_eq!(id.unzip().2, self.backend);
self.data.write().insert(id, value);
#[must_use]
pub(crate) struct FutureId<'a, I: TypedId, T> {
id: I,
data: &'a RwLock<Storage<T, I>>,
}
impl<I: TypedId + Copy, T> FutureId<'_, I, T> {
#[cfg(feature = "trace")]
pub fn id(&self) -> I {
self.id
}
pub fn read<'a, A: Access<T>>(
pub fn into_id(self) -> I {
self.id
}
pub fn assign<'a, A: Access<T>>(self, value: T, _: &'a mut Token<A>) -> Valid<I> {
self.data.write().insert(self.id, value);
Valid(self.id)
}
pub fn assign_error<'a, A: Access<T>>(self, label: &str, _: &'a mut Token<A>) -> I {
self.data.write().insert_error(self.id, label);
self.id
}
}
impl<T: Resource, I: TypedId + Copy, F: IdentityHandlerFactory<I>> Registry<T, I, F> {
pub(crate) fn prepare(
&self,
id_in: <F::Filter as IdentityHandler<I>>::Input,
) -> FutureId<I, T> {
FutureId {
id: self.identity.process(id_in, self.backend),
data: &self.data,
}
}
pub(crate) fn read<'a, A: Access<T>>(
&'a self,
_token: &'a mut Token<A>,
) -> (RwLockReadGuard<'a, Storage<T, I>>, Token<'a, T>) {
(self.data.read(), Token::new())
}
pub fn write<'a, A: Access<T>>(
pub(crate) fn write<'a, A: Access<T>>(
&'a self,
_token: &'a mut Token<A>,
) -> (RwLockWriteGuard<'a, Storage<T, I>>, Token<'a, T>) {
(self.data.write(), Token::new())
}
pub(crate) fn register_identity<A: Access<T>>(
&self,
id_in: <F::Filter as IdentityHandler<I>>::Input,
value: T,
token: &mut Token<A>,
) -> Valid<I> {
let id = self.identity.process(id_in, self.backend);
self.register(id, value, token);
Valid(id)
}
pub(crate) fn register_identity_locked(
&self,
id_in: <F::Filter as IdentityHandler<I>>::Input,
value: T,
guard: &mut Storage<T, I>,
) -> Valid<I> {
let id = self.identity.process(id_in, self.backend);
guard.insert(id, value);
Valid(id)
}
pub fn register_error<A: Access<T>>(
&self,
id_in: <F::Filter as IdentityHandler<I>>::Input,
label: &str,
_token: &mut Token<A>,
) -> I {
let id = self.identity.process(id_in, self.backend);
debug_assert_eq!(id.unzip().2, self.backend);
self.data.write().insert_error(id, label);
id
}
pub fn unregister_locked(&self, id: I, guard: &mut Storage<T, I>) -> Option<T> {
let value = guard.remove(id);
//Note: careful about the order here!
@@ -501,7 +499,7 @@ impl<T: Resource, I: TypedId + Copy, F: IdentityHandlerFactory<I>> Registry<T, I
value
}
pub fn unregister<'a, A: Access<T>>(
pub(crate) fn unregister<'a, A: Access<T>>(
&self,
id: I,
_token: &'a mut Token<A>,
@@ -513,14 +511,6 @@ impl<T: Resource, I: TypedId + Copy, F: IdentityHandlerFactory<I>> Registry<T, I
(value, Token::new())
}
pub fn process_id(&self, id_in: <F::Filter as IdentityHandler<I>>::Input) -> I {
self.identity.process(id_in, self.backend)
}
pub fn free_id(&self, id: I) {
self.identity.free(id)
}
pub fn label_for_resource(&self, id: I) -> String {
let guard = self.data.read();

View File

@@ -627,7 +627,29 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
};
let mut token = Token::root();
let id = self.surfaces.register_identity(id_in, surface, &mut token);
let id = self.surfaces.prepare(id_in).assign(surface, &mut token);
id.0
}
#[cfg(metal)]
pub fn instance_create_surface_metal(
&self,
layer: *mut std::ffi::c_void,
id_in: Input<G, SurfaceId>,
) -> SurfaceId {
span!(_guard, INFO, "Instance::instance_create_surface_metal");
let surface =
Surface {
#[cfg(feature = "vulkan-portability")]
vulkan: None, //TODO: create_surface_from_layer ?
metal: self.instance.metal.as_ref().map(|inst| {
inst.create_surface_from_layer(unsafe { std::mem::transmute(layer) })
}),
};
let mut token = Token::root();
let id = self.surfaces.prepare(id_in).assign(surface, &mut token);
id.0
}
@@ -653,11 +675,9 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
for raw in inst.enumerate_adapters() {
let adapter = Adapter::new(raw);
tracing::info!("Adapter {} {:?}", backend_info, adapter.raw.info);
let id = hub.adapters.register_identity(
id_backend.clone(),
adapter,
&mut token,
);
let id = hub.adapters
.prepare(id_backend.clone())
.assign(adapter, &mut token);
adapters.push(id.0);
}
}
@@ -803,11 +823,9 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
if selected < adapters_backend.len() {
let adapter = Adapter::new(adapters_backend.swap_remove(selected));
tracing::info!("Adapter {} {:?}", info_adapter, adapter.raw.info);
let id = backend_hub(self).adapters.register_identity(
id_backend.take().unwrap(),
adapter,
&mut token,
);
let id = backend_hub(self).adapters
.prepare(id_backend.take().unwrap())
.assign(adapter, &mut token);
return Ok(id.0);
}
selected -= adapters_backend.len();
@@ -905,16 +923,13 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let mut token = Token::root();
let (mut adapter_guard, _) = hub.adapters.write(&mut token);
match adapter_guard.get_mut(adapter_id) {
Ok(adapter) => {
if adapter.life_guard.ref_count.take().unwrap().load() == 1 {
hub.adapters
.unregister_locked(adapter_id, &mut *adapter_guard);
}
}
Err(_) => {
hub.adapters.free_id(adapter_id);
}
let free = match adapter_guard.get_mut(adapter_id) {
Ok(adapter) => adapter.life_guard.ref_count.take().unwrap().load() == 1,
Err(_) => true,
};
if free {
hub.adapters
.unregister_locked(adapter_id, &mut *adapter_guard);
}
}
}
@@ -931,6 +946,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let hub = B::hub(self);
let mut token = Token::root();
let fid = hub.devices.prepare(id_in);
let error = loop {
let (adapter_guard, mut token) = hub.adapters.read(&mut token);
@@ -942,13 +958,11 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
Ok(device) => device,
Err(e) => break e,
};
let id = hub.devices.register_identity(id_in, device, &mut token);
let id = fid.assign(device, &mut token);
return (id.0, None);
};
let id = hub
.devices
.register_error(id_in, desc.label.borrow_or_default(), &mut token);
let id = fid.assign_error(desc.label.borrow_or_default(), &mut token);
(id, Some(error))
}
}

View File

@@ -143,6 +143,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let hub = B::hub(self);
let mut token = Token::root();
let fid = hub.texture_views.prepare(view_id_in);
let (mut surface_guard, mut token) = self.surfaces.write(&mut token);
let surface = surface_guard
@@ -153,8 +154,16 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let sc = swap_chain_guard
.get_mut(swap_chain_id)
.map_err(|_| SwapChainError::Invalid)?;
#[cfg_attr(not(feature = "trace"), allow(unused_variables))]
#[allow(unused_variables)]
let device = &device_guard[sc.device_id.value];
#[cfg(feature = "trace")]
if let Some(ref trace) = device.trace {
trace.lock().add(Action::GetSwapChainTexture {
id: fid.id(),
parent_id: swap_chain_id,
});
}
let suf = B::get_surface_mut(surface);
let (image, status) = match unsafe { suf.acquire_image(FRAME_TIMEOUT_MS * 1_000_000) } {
@@ -206,9 +215,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
};
let ref_count = view.life_guard.add_ref();
let id = hub
.texture_views
.register_identity(view_id_in, view, &mut token);
let id = fid.assign(view, &mut token);
if sc.acquired_view_id.is_some() {
return Err(SwapChainError::AlreadyAcquired);
@@ -224,14 +231,6 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
None => None,
};
#[cfg(feature = "trace")]
if let Some(ref trace) = device.trace {
trace.lock().add(Action::GetSwapChainTexture {
id: view_id,
parent_id: swap_chain_id,
});
}
Ok(SwapChainOutput { status, view_id })
}