use std::error::Error;
use std::sync::Arc;
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
use vulkano::{
device::{
physical::PhysicalDevice, Device, DeviceCreateInfo, DeviceExtensions, Queue,
QueueCreateInfo, QueueFlags,
},
instance::{Instance, InstanceCreateInfo},
memory::allocator::StandardMemoryAllocator,
swapchain::Surface,
VulkanLibrary,
};
use crate::E;
#[derive(Debug, Clone)]
pub struct PmseRenderInit {
库: Arc<VulkanLibrary>,
}
impl PmseRenderInit {
pub fn vulkan() -> Result<Self, Box<dyn Error>> {
println!("init vulkan .. .");
let 库 = VulkanLibrary::new()?;
Ok(Self { 库 })
}
pub fn init_w(
self,
w: Arc<impl HasRawDisplayHandle + HasRawWindowHandle + Send + Sync + 'static>,
) -> Result<PmseRenderHost, Box<dyn Error>> {
let 实例扩展 = Surface::required_extensions(w.as_ref());
let 实例 = Instance::new(
self.库.clone(),
InstanceCreateInfo {
enabled_extensions: 实例扩展,
..Default::default()
},
)?;
let 设备扩展 = DeviceExtensions {
khr_swapchain: true,
..DeviceExtensions::empty()
};
let (物理设备, 队列序号) = 选择设备(&实例, 设备扩展.clone())?;
let (设备, 队列) = 创建设备队列(&物理设备, 队列序号, 设备扩展)?;
let ma = Arc::new(StandardMemoryAllocator::new_default(设备.clone()));
let 表面 = Surface::from_window(实例.clone(), w)?;
Ok(PmseRenderHost::new(物理设备, 设备, 队列, ma, 表面))
}
}
#[derive(Debug, Clone)]
pub struct PmseRenderHost {
p: Arc<PhysicalDevice>,
d: Arc<Device>,
q: Arc<Queue>,
ma: Arc<StandardMemoryAllocator>,
s: Arc<Surface>,
}
impl PmseRenderHost {
pub(crate) fn new(
p: Arc<PhysicalDevice>,
d: Arc<Device>,
q: Arc<Queue>,
ma: Arc<StandardMemoryAllocator>,
s: Arc<Surface>,
) -> Self {
Self { p, d, q, ma, s }
}
pub fn p(&self) -> &Arc<PhysicalDevice> {
&self.p
}
pub fn d(&self) -> &Arc<Device> {
&self.d
}
pub fn q(&self) -> &Arc<Queue> {
&self.q
}
pub fn ma(&self) -> &Arc<StandardMemoryAllocator> {
&self.ma
}
pub fn s(&self) -> &Arc<Surface> {
&self.s
}
}
fn 选择设备(
实例: &Arc<Instance>,
扩展: DeviceExtensions,
) -> Result<(Arc<PhysicalDevice>, u32), Box<dyn Error>> {
let 设备列表 = 实例
.enumerate_physical_devices()?
.filter(|p| p.supported_extensions().contains(&扩展));
let mut d1: Option<Arc<PhysicalDevice>> = None;
for i in 设备列表 {
println!(" {}", i.properties().device_name);
if d1.is_none() {
d1.replace(i);
}
}
let 设备 = d1.ok_or(E("ERROR vulkan list device".into()))?;
for f in 设备.queue_family_properties() {
println!("vulkan device queue {:?}", f.queue_count);
}
let queue_family_index = 设备
.queue_family_properties()
.iter()
.enumerate()
.position(|(_i, q)| q.queue_flags.contains(QueueFlags::GRAPHICS))
.ok_or(E("ERROR vulkan find queue".into()))? as u32;
println!("vulkan queue index {}", queue_family_index);
Ok((设备, queue_family_index))
}
fn 创建设备队列(
设备: &Arc<PhysicalDevice>,
queue_family_index: u32,
enabled_extensions: DeviceExtensions,
) -> Result<(Arc<Device>, Arc<Queue>), Box<dyn Error>> {
let (d, mut 队列) = Device::new(
设备.clone(),
DeviceCreateInfo {
queue_create_infos: vec![QueueCreateInfo {
queue_family_index,
..Default::default()
}],
enabled_extensions,
..Default::default()
},
)?;
let q = 队列.next().unwrap();
Ok((d, q))
}