mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-22 23:04:07 +00:00
Merge #621
621: Keep Adapter alive r=grovesNL a=kvark Co-authored-by: Dzmitry Malyshau <kvarkus@gmail.com>
This commit is contained in:
commit
e2100b6911
@ -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();
|
||||||
|
@ -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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
Loading…
Reference in New Issue
Block a user