use crate::{
binding_model::{BindGroup, BindGroupLayout, PipelineLayout},
command::{CommandBuffer, RenderBundle},
device::{queue::Queue, Device},
hal_api::HalApi,
id,
identity::GlobalIdentityHandlerFactory,
instance::{Adapter, HalSurface, Surface},
pipeline::{ComputePipeline, 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 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 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>>,
}
impl<A: HalApi> Hub<A> {
fn new<F: GlobalIdentityHandlerFactory>(factory: &F) -> Self {
Self {
adapters: Registry::new(A::VARIANT, factory),
devices: Registry::new(A::VARIANT, factory),
queues: Registry::new(A::VARIANT, factory),
pipeline_layouts: Registry::new(A::VARIANT, factory),
shader_modules: Registry::new(A::VARIANT, factory),
bind_group_layouts: Registry::new(A::VARIANT, factory),
bind_groups: Registry::new(A::VARIANT, factory),
command_buffers: Registry::new(A::VARIANT, factory),
render_bundles: Registry::new(A::VARIANT, factory),
render_pipelines: Registry::new(A::VARIANT, factory),
compute_pipelines: Registry::new(A::VARIANT, factory),
query_sets: Registry::new(A::VARIANT, factory),
buffers: Registry::new(A::VARIANT, factory),
staging_buffers: Registry::new(A::VARIANT, factory),
textures: Registry::new(A::VARIANT, factory),
texture_views: Registry::new(A::VARIANT, factory),
samplers: Registry::new(A::VARIANT, factory),
}
}
pub(crate) fn clear(
&self,
surface_guard: &Storage<Surface, id::SurfaceId>,
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.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::get_surface(surface);
unsafe {
suf.unwrap().raw.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: &HalSurface<A>) {
unsafe {
use hal::Surface;
surface.raw.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(),
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<F: GlobalIdentityHandlerFactory>(factory: &F) -> Self {
Self {
#[cfg(vulkan)]
vulkan: Hub::new(factory),
#[cfg(metal)]
metal: Hub::new(factory),
#[cfg(dx12)]
dx12: Hub::new(factory),
#[cfg(gles)]
gl: Hub::new(factory),
#[cfg(all(not(vulkan), not(metal), not(dx12), not(gles)))]
empty: Hub::new(factory),
}
}
}