#[derive(Debug, Clone)]
pub struct GpuDeviceInfo {
pub name: String,
pub backend: String,
pub device_type: String,
}
pub struct GpuContext {
#[cfg(feature = "gpu")]
pub(crate) device: wgpu::Device,
#[cfg(feature = "gpu")]
pub(crate) queue: wgpu::Queue,
_private: (),
}
impl GpuContext {
pub fn try_init() -> Option<Self> {
#[cfg(feature = "gpu")]
{
pollster::block_on(Self::try_init_async())
}
#[cfg(not(feature = "gpu"))]
{
None
}
}
#[cfg(feature = "gpu")]
async fn try_init_async() -> Option<Self> {
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
backends: wgpu::Backends::all(),
..wgpu::InstanceDescriptor::new_without_display_handle()
});
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::HighPerformance,
compatible_surface: None,
force_fallback_adapter: false,
})
.await
.ok()?;
let (device, queue) = adapter
.request_device(&wgpu::DeviceDescriptor::default())
.await
.ok()?;
Some(GpuContext {
device,
queue,
_private: (),
})
}
pub fn enumerate_devices() -> Vec<GpuDeviceInfo> {
#[cfg(feature = "gpu")]
{
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
backends: wgpu::Backends::all(),
..wgpu::InstanceDescriptor::new_without_display_handle()
});
pollster::block_on(instance.enumerate_adapters(wgpu::Backends::all()))
.into_iter()
.map(|adapter| {
let info = adapter.get_info();
GpuDeviceInfo {
name: info.name,
backend: format!("{:?}", info.backend),
device_type: format!("{:?}", info.device_type),
}
})
.collect()
}
#[cfg(not(feature = "gpu"))]
{
Vec::new()
}
}
pub fn try_init_with_name(name_pattern: &str) -> Option<Self> {
#[cfg(feature = "gpu")]
{
pollster::block_on(Self::try_init_with_name_async(name_pattern))
}
#[cfg(not(feature = "gpu"))]
{
let _ = name_pattern;
None
}
}
#[cfg(feature = "gpu")]
async fn try_init_with_name_async(name_pattern: &str) -> Option<Self> {
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
backends: wgpu::Backends::all(),
..wgpu::InstanceDescriptor::new_without_display_handle()
});
let pattern_lower = name_pattern.to_lowercase();
let adapter = instance
.enumerate_adapters(wgpu::Backends::all())
.await
.into_iter()
.find(|a| a.get_info().name.to_lowercase().contains(&pattern_lower))?;
let (device, queue) = adapter
.request_device(&wgpu::DeviceDescriptor::default())
.await
.ok()?;
Some(GpuContext {
device,
queue,
_private: (),
})
}
pub fn try_init_with_index(index: usize) -> Option<Self> {
#[cfg(feature = "gpu")]
{
pollster::block_on(Self::try_init_with_index_async(index))
}
#[cfg(not(feature = "gpu"))]
{
let _ = index;
None
}
}
#[cfg(feature = "gpu")]
async fn try_init_with_index_async(index: usize) -> Option<Self> {
let instance = wgpu::Instance::new(wgpu::InstanceDescriptor {
backends: wgpu::Backends::all(),
..wgpu::InstanceDescriptor::new_without_display_handle()
});
let adapters: Vec<_> = instance
.enumerate_adapters(wgpu::Backends::all())
.await
.into_iter()
.collect();
let adapter = adapters.into_iter().nth(index)?;
let (device, queue) = adapter
.request_device(&wgpu::DeviceDescriptor::default())
.await
.ok()?;
Some(GpuContext {
device,
queue,
_private: (),
})
}
}