use std::cmp::min;
use crate::{
command::FamilyId,
memory::{DynamicConfig, HeapsConfig, LinearConfig},
util::DeviceId,
};
#[derive(Clone, derivative::Derivative)]
#[derivative(Debug, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct Config<D = BasicDevicesConfigure, H = BasicHeapsConfigure, Q = OneGraphicsQueue> {
pub devices: D,
pub heaps: H,
pub queues: Q,
}
pub unsafe trait QueuesConfigure {
type Priorities: AsRef<[f32]>;
type Families: IntoIterator<Item = (FamilyId, Self::Priorities)>;
fn configure(
self,
device: DeviceId,
families: &[impl gfx_hal::queue::QueueFamily],
) -> Self::Families;
}
#[derive(Clone, Copy, Debug, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct OneGraphicsQueue;
unsafe impl QueuesConfigure for OneGraphicsQueue {
type Priorities = [f32; 1];
type Families = Option<(FamilyId, [f32; 1])>;
fn configure(
self,
device: DeviceId,
families: &[impl gfx_hal::queue::QueueFamily],
) -> Option<(FamilyId, [f32; 1])> {
families
.iter()
.find(|f| f.supports_graphics() && f.max_queues() > 0)
.map(|f| {
(
FamilyId {
device,
index: f.id().0,
},
[1.0],
)
})
}
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct SavedQueueConfig(Vec<(usize, Vec<f32>)>);
unsafe impl QueuesConfigure for SavedQueueConfig {
type Priorities = Vec<f32>;
type Families = Vec<(FamilyId, Vec<f32>)>;
fn configure(
self,
device: DeviceId,
_: &[impl gfx_hal::queue::QueueFamily],
) -> Vec<(FamilyId, Vec<f32>)> {
self.0
.into_iter()
.map(|(id, vec)| (FamilyId { device, index: id }, vec))
.collect()
}
}
pub unsafe trait HeapsConfigure {
type Types: IntoIterator<Item = (gfx_hal::memory::Properties, u32, HeapsConfig)>;
type Heaps: IntoIterator<Item = u64>;
fn configure(
self,
properties: &gfx_hal::adapter::MemoryProperties,
) -> (Self::Types, Self::Heaps);
}
#[derive(Clone, Copy, Debug, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct BasicHeapsConfigure;
unsafe impl HeapsConfigure for BasicHeapsConfigure {
type Types = Vec<(gfx_hal::memory::Properties, u32, HeapsConfig)>;
type Heaps = Vec<u64>;
fn configure(
self,
properties: &gfx_hal::adapter::MemoryProperties,
) -> (Self::Types, Self::Heaps) {
let _1mb = 1024 * 1024;
let _32mb = 32 * _1mb;
let _128mb = 128 * _1mb;
let types = properties
.memory_types
.iter()
.map(|mt| {
let config = HeapsConfig {
linear: if mt
.properties
.contains(gfx_hal::memory::Properties::CPU_VISIBLE)
{
Some(LinearConfig {
linear_size: min(_128mb, properties.memory_heaps[mt.heap_index] / 16),
})
} else {
None
},
dynamic: Some(DynamicConfig {
block_size_granularity: 256.min(
(properties.memory_heaps[mt.heap_index] / 4096).next_power_of_two(),
),
min_device_allocation: _1mb
.min(properties.memory_heaps[mt.heap_index] / 1048)
.next_power_of_two(),
max_chunk_size: _32mb.min(
(properties.memory_heaps[mt.heap_index] / 128).next_power_of_two(),
),
}),
};
(mt.properties, mt.heap_index as u32, config)
})
.collect();
let heaps = properties.memory_heaps.iter().cloned().collect();
(types, heaps)
}
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct SavedHeapsConfig {
types: Vec<(gfx_hal::memory::Properties, u32, HeapsConfig)>,
heaps: Vec<u64>,
}
unsafe impl HeapsConfigure for SavedHeapsConfig {
type Types = Vec<(gfx_hal::memory::Properties, u32, HeapsConfig)>;
type Heaps = Vec<u64>;
fn configure(
self,
_properties: &gfx_hal::adapter::MemoryProperties,
) -> (Self::Types, Self::Heaps) {
(self.types, self.heaps)
}
}
pub trait DevicesConfigure {
fn pick<B>(&self, adapters: &[gfx_hal::Adapter<B>]) -> usize
where
B: gfx_hal::Backend;
}
#[derive(Clone, Copy, Debug, Default)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub struct BasicDevicesConfigure;
impl DevicesConfigure for BasicDevicesConfigure {
fn pick<B>(&self, adapters: &[gfx_hal::Adapter<B>]) -> usize
where
B: gfx_hal::Backend,
{
adapters
.iter()
.enumerate()
.min_by_key(|(_, adapter)| match adapter.info.device_type {
gfx_hal::adapter::DeviceType::DiscreteGpu => 0,
gfx_hal::adapter::DeviceType::IntegratedGpu => 1,
gfx_hal::adapter::DeviceType::VirtualGpu => 2,
gfx_hal::adapter::DeviceType::Cpu => 3,
_ => 4,
})
.expect("No adapters present")
.0
}
}