621: Keep Adapter alive r=grovesNL a=kvark



Co-authored-by: Dzmitry Malyshau <kvarkus@gmail.com>
This commit is contained in:
bors[bot] 2020-05-01 04:30:09 +00:00 committed by GitHub
commit e2100b6911
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 74 additions and 51 deletions

View File

@ -369,7 +369,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let (context, sample_count) = { let (context, sample_count) = {
use hal::{adapter::PhysicalDevice as _, device::Device as _}; use hal::{adapter::PhysicalDevice as _, device::Device as _};
let limits = adapter_guard[device.adapter_id] let limits = adapter_guard[device.adapter_id.value]
.raw .raw
.physical_device .physical_device
.limits(); .limits();

View File

@ -185,7 +185,7 @@ fn fire_map_callbacks<I: IntoIterator<Item = BufferMapPendingCallback>>(callback
#[derive(Debug)] #[derive(Debug)]
pub struct Device<B: hal::Backend> { pub struct Device<B: hal::Backend> {
pub(crate) raw: B::Device, pub(crate) raw: B::Device,
pub(crate) adapter_id: id::AdapterId, pub(crate) adapter_id: Stored<id::AdapterId>,
pub(crate) queue_group: hal::queue::QueueGroup<B>, pub(crate) queue_group: hal::queue::QueueGroup<B>,
pub(crate) com_allocator: command::CommandAllocator<B>, pub(crate) com_allocator: command::CommandAllocator<B>,
mem_allocator: Mutex<Heaps<B>>, mem_allocator: Mutex<Heaps<B>>,
@ -207,7 +207,7 @@ pub struct Device<B: hal::Backend> {
impl<B: GfxBackend> Device<B> { impl<B: GfxBackend> Device<B> {
pub(crate) fn new( pub(crate) fn new(
raw: B::Device, raw: B::Device,
adapter_id: id::AdapterId, adapter_id: Stored<id::AdapterId>,
queue_group: hal::queue::QueueGroup<B>, queue_group: hal::queue::QueueGroup<B>,
mem_props: hal::adapter::MemoryProperties, mem_props: hal::adapter::MemoryProperties,
non_coherent_atom_size: u64, non_coherent_atom_size: u64,
@ -274,18 +274,18 @@ impl<B: GfxBackend> Device<B> {
} }
} }
fn lock_life<'a>( fn lock_life<'this, 'token: 'this>(
&'a self, &'this self,
_token: &mut Token<'a, Self>, _token: &mut Token<'token, Self>,
) -> MutexGuard<'a, life::LifetimeTracker<B>> { ) -> MutexGuard<'this, life::LifetimeTracker<B>> {
self.life_tracker.lock() self.life_tracker.lock()
} }
fn maintain<'a, G: GlobalIdentityHandlerFactory>( fn maintain<'this, 'token: 'this, G: GlobalIdentityHandlerFactory>(
&'a self, &'this self,
global: &Global<G>, global: &Global<G>,
force_wait: bool, force_wait: bool,
token: &mut Token<'a, Self>, token: &mut Token<'token, Self>,
) -> Vec<BufferMapPendingCallback> { ) -> Vec<BufferMapPendingCallback> {
let mut life_tracker = self.lock_life(token); let mut life_tracker = self.lock_life(token);
@ -2313,7 +2313,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let (caps, formats) = { let (caps, formats) = {
let suf = B::get_surface_mut(surface); let suf = B::get_surface_mut(surface);
let adapter = &adapter_guard[device.adapter_id]; let adapter = &adapter_guard[device.adapter_id.value];
assert!( assert!(
suf.supports_queue_family(&adapter.raw.queue_families[0]), suf.supports_queue_family(&adapter.raw.queue_families[0]),
"Surface {:?} doesn't support queue family {:?}", "Surface {:?} doesn't support queue family {:?}",
@ -2439,9 +2439,18 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
pub fn device_destroy<B: GfxBackend>(&self, device_id: id::DeviceId) { pub fn device_destroy<B: GfxBackend>(&self, device_id: id::DeviceId) {
let hub = B::hub(self); let hub = B::hub(self);
let mut token = Token::root(); let mut token = Token::root();
let (device, mut token) = hub.devices.unregister(device_id, &mut token); let device = {
device.maintain(self, true, &mut token); let (device, mut token) = hub.devices.unregister(device_id, &mut token);
drop(token); device.maintain(self, true, &mut token);
device
};
// Adapter is only referenced by the device and itself.
// This isn't a robust way to destroy them, we should find a better one.
if device.adapter_id.ref_count.load() == 1 {
let (_adapter, _) = hub.adapters.unregister(device.adapter_id.value, &mut token);
}
device.dispose(); device.dispose();
} }

View File

@ -25,7 +25,7 @@ use wgt::Backend;
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
use std::cell::Cell; use std::cell::Cell;
use std::{fmt::Debug, marker::PhantomData, ops}; use std::{fmt::Debug, marker::PhantomData, ops, thread};
/// A simple structure to manage identities of objects. /// A simple structure to manage identities of objects.
#[derive(Debug)] #[derive(Debug)]
@ -553,10 +553,12 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
impl<G: GlobalIdentityHandlerFactory> Drop for Global<G> { impl<G: GlobalIdentityHandlerFactory> Drop for Global<G> {
fn drop(&mut self) { fn drop(&mut self) {
log::info!("Dropping Global"); if !thread::panicking() {
// destroy surfaces log::info!("Dropping Global");
for (_, (surface, _)) in self.surfaces.data.write().map.drain() { // destroy surfaces
self.instance.destroy_surface(surface); for (_, (surface, _)) in self.surfaces.data.write().map.drain() {
self.instance.destroy_surface(surface);
}
} }
} }
} }

View File

@ -7,7 +7,7 @@ use crate::{
device::Device, device::Device,
hub::{GfxBackend, Global, GlobalIdentityHandlerFactory, Input, Token}, hub::{GfxBackend, Global, GlobalIdentityHandlerFactory, Input, Token},
id::{AdapterId, DeviceId, SurfaceId}, id::{AdapterId, DeviceId, SurfaceId},
power, power, LifeGuard, Stored,
}; };
use wgt::{Backend, BackendBit, DeviceDescriptor, PowerPreference, BIND_BUFFER_ALIGNMENT}; use wgt::{Backend, BackendBit, DeviceDescriptor, PowerPreference, BIND_BUFFER_ALIGNMENT};
@ -119,6 +119,16 @@ pub struct Surface {
#[derive(Debug)] #[derive(Debug)]
pub struct Adapter<B: hal::Backend> { pub struct Adapter<B: hal::Backend> {
pub(crate) raw: hal::adapter::Adapter<B>, pub(crate) raw: hal::adapter::Adapter<B>,
life_guard: LifeGuard,
}
impl<B: hal::Backend> Adapter<B> {
fn new(raw: hal::adapter::Adapter<B>) -> Self {
Adapter {
raw,
life_guard: LifeGuard::new(),
}
}
} }
/// Metadata about a backend adapter. /// Metadata about a backend adapter.
@ -316,7 +326,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
if let Some(ref inst) = instance.vulkan { if let Some(ref inst) = instance.vulkan {
if let Some(id_vulkan) = inputs.find(Backend::Vulkan) { if let Some(id_vulkan) = inputs.find(Backend::Vulkan) {
for raw in inst.enumerate_adapters() { for raw in inst.enumerate_adapters() {
let adapter = Adapter { raw }; let adapter = Adapter::new(raw);
log::info!("Adapter Vulkan {:?}", adapter.raw.info); log::info!("Adapter Vulkan {:?}", adapter.raw.info);
adapters.push(backend::Vulkan::hub(self).adapters.register_identity( adapters.push(backend::Vulkan::hub(self).adapters.register_identity(
id_vulkan.clone(), id_vulkan.clone(),
@ -331,7 +341,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
{ {
if let Some(id_metal) = inputs.find(Backend::Metal) { if let Some(id_metal) = inputs.find(Backend::Metal) {
for raw in instance.metal.enumerate_adapters() { for raw in instance.metal.enumerate_adapters() {
let adapter = Adapter { raw }; let adapter = Adapter::new(raw);
log::info!("Adapter Metal {:?}", adapter.raw.info); log::info!("Adapter Metal {:?}", adapter.raw.info);
adapters.push(backend::Metal::hub(self).adapters.register_identity( adapters.push(backend::Metal::hub(self).adapters.register_identity(
id_metal.clone(), id_metal.clone(),
@ -346,7 +356,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
if let Some(ref inst) = instance.dx12 { if let Some(ref inst) = instance.dx12 {
if let Some(id_dx12) = inputs.find(Backend::Dx12) { if let Some(id_dx12) = inputs.find(Backend::Dx12) {
for raw in inst.enumerate_adapters() { for raw in inst.enumerate_adapters() {
let adapter = Adapter { raw }; let adapter = Adapter::new(raw);
log::info!("Adapter Dx12 {:?}", adapter.raw.info); log::info!("Adapter Dx12 {:?}", adapter.raw.info);
adapters.push(backend::Dx12::hub(self).adapters.register_identity( adapters.push(backend::Dx12::hub(self).adapters.register_identity(
id_dx12.clone(), id_dx12.clone(),
@ -359,7 +369,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
if let Some(id_dx11) = inputs.find(Backend::Dx11) { if let Some(id_dx11) = inputs.find(Backend::Dx11) {
for raw in instance.dx11.enumerate_adapters() { for raw in instance.dx11.enumerate_adapters() {
let adapter = Adapter { raw }; let adapter = Adapter::new(raw);
log::info!("Adapter Dx11 {:?}", adapter.raw.info); log::info!("Adapter Dx11 {:?}", adapter.raw.info);
adapters.push(backend::Dx11::hub(self).adapters.register_identity( adapters.push(backend::Dx11::hub(self).adapters.register_identity(
id_dx11.clone(), id_dx11.clone(),
@ -514,9 +524,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
))] ))]
{ {
if selected < adapters_vk.len() { if selected < adapters_vk.len() {
let adapter = Adapter { let adapter = Adapter::new(adapters_vk.swap_remove(selected));
raw: adapters_vk.swap_remove(selected),
};
log::info!("Adapter Vulkan {:?}", adapter.raw.info); log::info!("Adapter Vulkan {:?}", adapter.raw.info);
let id = backend::Vulkan::hub(self).adapters.register_identity( let id = backend::Vulkan::hub(self).adapters.register_identity(
id_vulkan.unwrap(), id_vulkan.unwrap(),
@ -530,9 +538,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
#[cfg(any(target_os = "ios", target_os = "macos"))] #[cfg(any(target_os = "ios", target_os = "macos"))]
{ {
if selected < adapters_mtl.len() { if selected < adapters_mtl.len() {
let adapter = Adapter { let adapter = Adapter::new(adapters_mtl.swap_remove(selected));
raw: adapters_mtl.swap_remove(selected),
};
log::info!("Adapter Metal {:?}", adapter.raw.info); log::info!("Adapter Metal {:?}", adapter.raw.info);
let id = backend::Metal::hub(self).adapters.register_identity( let id = backend::Metal::hub(self).adapters.register_identity(
id_metal.unwrap(), id_metal.unwrap(),
@ -546,9 +552,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
#[cfg(windows)] #[cfg(windows)]
{ {
if selected < adapters_dx12.len() { if selected < adapters_dx12.len() {
let adapter = Adapter { let adapter = Adapter::new(adapters_dx12.swap_remove(selected));
raw: adapters_dx12.swap_remove(selected),
};
log::info!("Adapter Dx12 {:?}", adapter.raw.info); log::info!("Adapter Dx12 {:?}", adapter.raw.info);
let id = backend::Dx12::hub(self).adapters.register_identity( let id = backend::Dx12::hub(self).adapters.register_identity(
id_dx12.unwrap(), id_dx12.unwrap(),
@ -559,9 +563,7 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
} }
selected -= adapters_dx12.len(); selected -= adapters_dx12.len();
if selected < adapters_dx11.len() { if selected < adapters_dx11.len() {
let adapter = Adapter { let adapter = Adapter::new(adapters_dx11.swap_remove(selected));
raw: adapters_dx11.swap_remove(selected),
};
log::info!("Adapter Dx11 {:?}", adapter.raw.info); log::info!("Adapter Dx11 {:?}", adapter.raw.info);
let id = backend::Dx11::hub(self).adapters.register_identity( let id = backend::Dx11::hub(self).adapters.register_identity(
id_dx11.unwrap(), id_dx11.unwrap(),
@ -589,7 +591,19 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
pub fn adapter_destroy<B: GfxBackend>(&self, adapter_id: AdapterId) { pub fn adapter_destroy<B: GfxBackend>(&self, adapter_id: AdapterId) {
let hub = B::hub(self); let hub = B::hub(self);
let mut token = Token::root(); let mut token = Token::root();
let (_adapter, _) = hub.adapters.unregister(adapter_id, &mut token); let (mut guard, _) = hub.adapters.write(&mut token);
if guard[adapter_id]
.life_guard
.ref_count
.take()
.unwrap()
.load()
== 1
{
hub.adapters.free_id(adapter_id);
let _adapter = guard.remove(adapter_id).unwrap();
}
} }
} }
@ -605,11 +619,12 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
let mut token = Token::root(); let mut token = Token::root();
let device = { let device = {
let (adapter_guard, _) = hub.adapters.read(&mut token); let (adapter_guard, _) = hub.adapters.read(&mut token);
let adapter = &adapter_guard[adapter_id].raw; let adapter = &adapter_guard[adapter_id];
let phd = &adapter.raw.physical_device;
let wishful_features = hal::Features::VERTEX_STORES_AND_ATOMICS let wishful_features = hal::Features::VERTEX_STORES_AND_ATOMICS
| hal::Features::FRAGMENT_STORES_AND_ATOMICS | hal::Features::FRAGMENT_STORES_AND_ATOMICS
| hal::Features::NDC_Y_UP; | hal::Features::NDC_Y_UP;
let enabled_features = adapter.physical_device.features() & wishful_features; let enabled_features = adapter.raw.physical_device.features() & wishful_features;
if enabled_features != wishful_features { if enabled_features != wishful_features {
log::warn!( log::warn!(
"Missing features: {:?}", "Missing features: {:?}",
@ -618,18 +633,14 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
} }
let family = adapter let family = adapter
.raw
.queue_families .queue_families
.iter() .iter()
.find(|family| family.queue_type().supports_graphics()) .find(|family| family.queue_type().supports_graphics())
.unwrap(); .unwrap();
let mut gpu = unsafe { let mut gpu = unsafe { phd.open(&[(family, &[1.0])], enabled_features).unwrap() };
adapter
.physical_device
.open(&[(family, &[1.0])], enabled_features)
.unwrap()
};
let limits = adapter.physical_device.limits(); let limits = phd.limits();
assert_eq!( assert_eq!(
0, 0,
BIND_BUFFER_ALIGNMENT % limits.min_storage_buffer_offset_alignment, BIND_BUFFER_ALIGNMENT % limits.min_storage_buffer_offset_alignment,
@ -649,17 +660,18 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
); );
} }
let mem_props = adapter.physical_device.memory_properties(); let mem_props = phd.memory_properties();
let supports_texture_d24_s8 = phd
let supports_texture_d24_s8 = adapter
.physical_device
.format_properties(Some(hal::format::Format::D24UnormS8Uint)) .format_properties(Some(hal::format::Format::D24UnormS8Uint))
.optimal_tiling .optimal_tiling
.contains(hal::format::ImageFeature::DEPTH_STENCIL_ATTACHMENT); .contains(hal::format::ImageFeature::DEPTH_STENCIL_ATTACHMENT);
Device::new( Device::new(
gpu.device, gpu.device,
adapter_id, Stored {
value: adapter_id,
ref_count: adapter.life_guard.add_ref(),
},
gpu.queue_groups.swap_remove(0), gpu.queue_groups.swap_remove(0),
mem_props, mem_props,
limits.non_coherent_atom_size as u64, limits.non_coherent_atom_size as u64,