mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
Merge #1594
1594: Generation of memory reports for Hubs r=cwfitzgerald a=kvark **Connections** Part of #1501 **Description** Tried to see if we aren't accidentally growing the hubs. **Testing** Examples... Co-authored-by: Dzmitry Malyshau <kvark@fastmail.com>
This commit is contained in:
@@ -15,7 +15,7 @@ use wgt::Backend;
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
use std::cell::Cell;
|
||||
use std::{fmt::Debug, marker::PhantomData, ops};
|
||||
use std::{fmt::Debug, marker::PhantomData, mem, ops};
|
||||
|
||||
/// A simple structure to manage identities of objects.
|
||||
#[derive(Debug)]
|
||||
@@ -73,6 +73,20 @@ enum Element<T> {
|
||||
Error(Epoch, String),
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Default)]
|
||||
pub struct StorageReport {
|
||||
pub num_occupied: usize,
|
||||
pub num_vacant: usize,
|
||||
pub num_error: usize,
|
||||
pub element_size: usize,
|
||||
}
|
||||
|
||||
impl StorageReport {
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.num_occupied + self.num_vacant + self.num_error == 0
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub(crate) struct InvalidId;
|
||||
|
||||
@@ -212,6 +226,21 @@ impl<T, I: id::TypedId> Storage<T, I> {
|
||||
_ => None,
|
||||
})
|
||||
}
|
||||
|
||||
fn generate_report(&self) -> StorageReport {
|
||||
let mut report = StorageReport {
|
||||
element_size: mem::size_of::<T>(),
|
||||
..Default::default()
|
||||
};
|
||||
for element in self.map.iter() {
|
||||
match *element {
|
||||
Element::Occupied(..) => report.num_occupied += 1,
|
||||
Element::Vacant => report.num_vacant += 1,
|
||||
Element::Error(..) => report.num_error += 1,
|
||||
}
|
||||
}
|
||||
report
|
||||
}
|
||||
}
|
||||
|
||||
/// Type system for enforcing the lock order on shared HUB structures.
|
||||
@@ -526,6 +555,32 @@ impl<T: Resource, I: id::TypedId + Copy, F: IdentityHandlerFactory<I>> Registry<
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct HubReport {
|
||||
pub adapters: StorageReport,
|
||||
pub devices: StorageReport,
|
||||
pub swap_chains: StorageReport,
|
||||
pub pipeline_layouts: StorageReport,
|
||||
pub shader_modules: StorageReport,
|
||||
pub bind_group_layouts: StorageReport,
|
||||
pub bind_groups: StorageReport,
|
||||
pub command_buffers: StorageReport,
|
||||
pub render_bundles: StorageReport,
|
||||
pub render_pipelines: StorageReport,
|
||||
pub compute_pipelines: StorageReport,
|
||||
pub query_sets: StorageReport,
|
||||
pub buffers: StorageReport,
|
||||
pub textures: StorageReport,
|
||||
pub texture_views: StorageReport,
|
||||
pub samplers: StorageReport,
|
||||
}
|
||||
|
||||
impl HubReport {
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.adapters.is_empty()
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Hub<A: hal::Api, F: GlobalIdentityHandlerFactory> {
|
||||
pub adapters: Registry<Adapter<A>, id::AdapterId, F>,
|
||||
pub devices: Registry<Device<A>, id::DeviceId, F>,
|
||||
@@ -566,9 +621,7 @@ impl<A: HalApi, F: GlobalIdentityHandlerFactory> Hub<A, F> {
|
||||
samplers: Registry::new(A::VARIANT, factory),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<A: HalApi, F: GlobalIdentityHandlerFactory> Hub<A, F> {
|
||||
//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.
|
||||
@@ -711,6 +764,27 @@ impl<A: HalApi, F: GlobalIdentityHandlerFactory> Hub<A, F> {
|
||||
self.adapters.data.write().map.clear();
|
||||
}
|
||||
}
|
||||
|
||||
pub fn generate_report(&self) -> HubReport {
|
||||
HubReport {
|
||||
adapters: self.adapters.data.read().generate_report(),
|
||||
devices: self.devices.data.read().generate_report(),
|
||||
swap_chains: self.swap_chains.data.read().generate_report(),
|
||||
pipeline_layouts: self.pipeline_layouts.data.read().generate_report(),
|
||||
shader_modules: self.shader_modules.data.read().generate_report(),
|
||||
bind_group_layouts: self.bind_group_layouts.data.read().generate_report(),
|
||||
bind_groups: self.bind_groups.data.read().generate_report(),
|
||||
command_buffers: self.command_buffers.data.read().generate_report(),
|
||||
render_bundles: self.render_bundles.data.read().generate_report(),
|
||||
render_pipelines: self.render_pipelines.data.read().generate_report(),
|
||||
compute_pipelines: self.compute_pipelines.data.read().generate_report(),
|
||||
query_sets: self.query_sets.data.read().generate_report(),
|
||||
buffers: self.buffers.data.read().generate_report(),
|
||||
textures: self.textures.data.read().generate_report(),
|
||||
texture_views: self.texture_views.data.read().generate_report(),
|
||||
samplers: self.samplers.data.read().generate_report(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Hubs<F: GlobalIdentityHandlerFactory> {
|
||||
@@ -743,6 +817,21 @@ impl<F: GlobalIdentityHandlerFactory> Hubs<F> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct GlobalReport {
|
||||
pub surfaces: StorageReport,
|
||||
#[cfg(vulkan)]
|
||||
pub vulkan: Option<HubReport>,
|
||||
#[cfg(metal)]
|
||||
pub metal: Option<HubReport>,
|
||||
#[cfg(dx12)]
|
||||
pub dx12: Option<HubReport>,
|
||||
#[cfg(dx11)]
|
||||
pub dx11: Option<HubReport>,
|
||||
#[cfg(gl)]
|
||||
pub gl: Option<HubReport>,
|
||||
}
|
||||
|
||||
pub struct Global<G: GlobalIdentityHandlerFactory> {
|
||||
pub instance: Instance,
|
||||
pub surfaces: Registry<Surface, id::SurfaceId, G>,
|
||||
@@ -765,6 +854,42 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
// this is used for tests, which keep the adapter
|
||||
hub.clear(&mut *surface_guard, false);
|
||||
}
|
||||
|
||||
pub fn generate_report(&self) -> GlobalReport {
|
||||
GlobalReport {
|
||||
surfaces: self.surfaces.data.read().generate_report(),
|
||||
#[cfg(vulkan)]
|
||||
vulkan: if self.instance.vulkan.is_some() {
|
||||
Some(self.hubs.vulkan.generate_report())
|
||||
} else {
|
||||
None
|
||||
},
|
||||
#[cfg(metal)]
|
||||
metal: if self.instance.metal.is_some() {
|
||||
Some(self.hubs.metal.generate_report())
|
||||
} else {
|
||||
None
|
||||
},
|
||||
#[cfg(dx12)]
|
||||
dx12: if self.instance.dx12.is_some() {
|
||||
Some(self.hubs.dx12.generate_report())
|
||||
} else {
|
||||
None
|
||||
},
|
||||
#[cfg(dx11)]
|
||||
dx11: if self.instance.dx11.is_some() {
|
||||
Some(self.hubs.dx11.generate_report())
|
||||
} else {
|
||||
None
|
||||
},
|
||||
#[cfg(gl)]
|
||||
gl: if self.instance.gl.is_some() {
|
||||
Some(self.hubs.gl.generate_report())
|
||||
} else {
|
||||
None
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<G: GlobalIdentityHandlerFactory> Drop for Global<G> {
|
||||
|
||||
@@ -254,6 +254,18 @@ fn start<E: Example>(
|
||||
| WindowEvent::CloseRequested => {
|
||||
*control_flow = ControlFlow::Exit;
|
||||
}
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
WindowEvent::KeyboardInput {
|
||||
input:
|
||||
event::KeyboardInput {
|
||||
virtual_keycode: Some(event::VirtualKeyCode::R),
|
||||
state: event::ElementState::Pressed,
|
||||
..
|
||||
},
|
||||
..
|
||||
} => {
|
||||
println!("{:#?}", instance.generate_report());
|
||||
}
|
||||
_ => {
|
||||
example.update(event);
|
||||
}
|
||||
|
||||
@@ -50,6 +50,10 @@ impl Context {
|
||||
}))
|
||||
}
|
||||
|
||||
pub fn generate_report(&self) -> wgc::hub::GlobalReport {
|
||||
self.0.generate_report()
|
||||
}
|
||||
|
||||
/*TODO: raw surface
|
||||
#[cfg(any(target_os = "ios", target_os = "macos"))]
|
||||
pub unsafe fn create_surface_from_core_animation_layer(
|
||||
|
||||
@@ -1454,6 +1454,12 @@ impl Instance {
|
||||
pub fn poll_all(&self, force_wait: bool) {
|
||||
self.context.instance_poll_all_devices(force_wait);
|
||||
}
|
||||
|
||||
/// Generates memory report.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub fn generate_report(&self) -> wgc::hub::GlobalReport {
|
||||
self.context.generate_report()
|
||||
}
|
||||
}
|
||||
|
||||
impl Adapter {
|
||||
|
||||
Reference in New Issue
Block a user