use crate::{
binding_model::{BindGroup, BindGroupLayout, PipelineLayout},
command::{CommandBuffer, RenderBundle},
device::{queue::Queue, Device},
hal_api::HalApi,
instance::{Adapter, Surface},
pipeline::{ComputePipeline, PipelineCache, RenderPipeline, ShaderModule},
registry::{Registry, RegistryReport},
resource::{Buffer, QuerySet, Sampler, StagingBuffer, Texture, TextureView},
storage::{Element, Storage},
};
use std::fmt::Debug;
#[derive(Debug, PartialEq, Eq)]
pub struct HubReport {
pub adapters: RegistryReport,
pub devices: RegistryReport,
pub queues: RegistryReport,
pub pipeline_layouts: RegistryReport,
pub shader_modules: RegistryReport,
pub bind_group_layouts: RegistryReport,
pub bind_groups: RegistryReport,
pub command_buffers: RegistryReport,
pub render_bundles: RegistryReport,
pub render_pipelines: RegistryReport,
pub compute_pipelines: RegistryReport,
pub pipeline_caches: RegistryReport,
pub query_sets: RegistryReport,
pub buffers: RegistryReport,
pub textures: RegistryReport,
pub texture_views: RegistryReport,
pub samplers: RegistryReport,
}
impl HubReport {
pub fn is_empty(&self) -> bool {
self.adapters.is_empty()
}
}
#[allow(rustdoc::private_intra_doc_links)]
pub struct Hub<A: HalApi> {
pub(crate) adapters: Registry<Adapter<A>>,
pub(crate) devices: Registry<Device<A>>,
pub(crate) queues: Registry<Queue<A>>,
pub(crate) pipeline_layouts: Registry<PipelineLayout<A>>,
pub(crate) shader_modules: Registry<ShaderModule<A>>,
pub(crate) bind_group_layouts: Registry<BindGroupLayout<A>>,
pub(crate) bind_groups: Registry<BindGroup<A>>,
pub(crate) command_buffers: Registry<CommandBuffer<A>>,
pub(crate) render_bundles: Registry<RenderBundle<A>>,
pub(crate) render_pipelines: Registry<RenderPipeline<A>>,
pub(crate) compute_pipelines: Registry<ComputePipeline<A>>,
pub(crate) pipeline_caches: Registry<PipelineCache<A>>,
pub(crate) query_sets: Registry<QuerySet<A>>,
pub(crate) buffers: Registry<Buffer<A>>,
pub(crate) staging_buffers: Registry<StagingBuffer<A>>,
pub(crate) textures: Registry<Texture<A>>,
pub(crate) texture_views: Registry<TextureView<A>>,
pub(crate) samplers: Registry<Sampler<A>>,
}
impl<A: HalApi> Hub<A> {
fn new() -> Self {
Self {
adapters: Registry::new(A::VARIANT),
devices: Registry::new(A::VARIANT),
queues: Registry::new(A::VARIANT),
pipeline_layouts: Registry::new(A::VARIANT),
shader_modules: Registry::new(A::VARIANT),
bind_group_layouts: Registry::new(A::VARIANT),
bind_groups: Registry::new(A::VARIANT),
command_buffers: Registry::new(A::VARIANT),
render_bundles: Registry::new(A::VARIANT),
render_pipelines: Registry::new(A::VARIANT),
compute_pipelines: Registry::new(A::VARIANT),
pipeline_caches: Registry::new(A::VARIANT),
query_sets: Registry::new(A::VARIANT),
buffers: Registry::new(A::VARIANT),
staging_buffers: Registry::new(A::VARIANT),
textures: Registry::new(A::VARIANT),
texture_views: Registry::new(A::VARIANT),
samplers: Registry::new(A::VARIANT),
}
}
pub(crate) fn clear(&self, surface_guard: &Storage<Surface>, with_adapters: bool) {
use hal::Surface;
let mut devices = self.devices.write();
for element in devices.map.iter() {
if let Element::Occupied(ref device, _) = *element {
device.prepare_to_die();
}
}
self.command_buffers.write().map.clear();
self.samplers.write().map.clear();
self.texture_views.write().map.clear();
self.textures.write().map.clear();
self.buffers.write().map.clear();
self.bind_groups.write().map.clear();
self.shader_modules.write().map.clear();
self.bind_group_layouts.write().map.clear();
self.pipeline_layouts.write().map.clear();
self.compute_pipelines.write().map.clear();
self.render_pipelines.write().map.clear();
self.pipeline_caches.write().map.clear();
self.query_sets.write().map.clear();
for element in surface_guard.map.iter() {
if let Element::Occupied(ref surface, _epoch) = *element {
if let Some(ref mut present) = surface.presentation.lock().take() {
if let Some(device) = present.device.downcast_ref::<A>() {
let suf = A::surface_as_hal(surface);
unsafe {
suf.unwrap().unconfigure(device.raw());
}
}
}
}
}
self.queues.write().map.clear();
devices.map.clear();
if with_adapters {
drop(devices);
self.adapters.write().map.clear();
}
}
pub(crate) fn surface_unconfigure(&self, device: &Device<A>, surface: &A::Surface) {
unsafe {
use hal::Surface;
surface.unconfigure(device.raw());
}
}
pub fn generate_report(&self) -> HubReport {
HubReport {
adapters: self.adapters.generate_report(),
devices: self.devices.generate_report(),
queues: self.queues.generate_report(),
pipeline_layouts: self.pipeline_layouts.generate_report(),
shader_modules: self.shader_modules.generate_report(),
bind_group_layouts: self.bind_group_layouts.generate_report(),
bind_groups: self.bind_groups.generate_report(),
command_buffers: self.command_buffers.generate_report(),
render_bundles: self.render_bundles.generate_report(),
render_pipelines: self.render_pipelines.generate_report(),
compute_pipelines: self.compute_pipelines.generate_report(),
pipeline_caches: self.pipeline_caches.generate_report(),
query_sets: self.query_sets.generate_report(),
buffers: self.buffers.generate_report(),
textures: self.textures.generate_report(),
texture_views: self.texture_views.generate_report(),
samplers: self.samplers.generate_report(),
}
}
}
pub struct Hubs {
#[cfg(vulkan)]
pub(crate) vulkan: Hub<hal::api::Vulkan>,
#[cfg(metal)]
pub(crate) metal: Hub<hal::api::Metal>,
#[cfg(dx12)]
pub(crate) dx12: Hub<hal::api::Dx12>,
#[cfg(gles)]
pub(crate) gl: Hub<hal::api::Gles>,
#[cfg(all(not(vulkan), not(metal), not(dx12), not(gles)))]
pub(crate) empty: Hub<hal::api::Empty>,
}
impl Hubs {
pub(crate) fn new() -> Self {
Self {
#[cfg(vulkan)]
vulkan: Hub::new(),
#[cfg(metal)]
metal: Hub::new(),
#[cfg(dx12)]
dx12: Hub::new(),
#[cfg(gles)]
gl: Hub::new(),
#[cfg(all(not(vulkan), not(metal), not(dx12), not(gles)))]
empty: Hub::new(),
}
}
}