You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

176 lines
3.9 KiB

use crate::render::{
ensure_properties, Conf, ErrNoProperty, Instance, QueueFamilyInfo,
};
use ash::{
extensions::khr,
version::{DeviceV1_0, InstanceV1_0},
vk,
};
use std::{os::raw::c_char, rc::Rc};
pub struct Device {
handle: ash::Device,
pub instance: Rc<Instance>,
pub swapchain_ext: khr::Swapchain,
}
pub struct PhysicalDevice {
handle: vk::PhysicalDevice,
pub instance: Rc<Instance>,
}
#[derive(Debug)]
pub enum ErrDeviceCreate {
Vk(vk::Result),
NoExtension(ErrNoProperty),
}
#[derive(Debug)]
pub enum ErrPhysicalDeviceGet {
Vk(vk::Result),
NoDevice,
}
fn enable_device_extensions(
instance: &ash::Instance,
phys_device: &PhysicalDevice,
extensions: &[*const c_char],
) -> Result<vk::DeviceCreateInfo, ErrDeviceCreate> {
if !extensions.is_empty() {
let props = unsafe {
instance.enumerate_device_extension_properties(**phys_device)?
};
ensure_properties(&props, extensions, |x| x.extension_name.as_ptr())?;
}
Ok(vk::DeviceCreateInfo {
enabled_extension_count: extensions.len() as u32,
pp_enabled_extension_names: extensions.as_ptr(),
..Default::default()
})
}
impl Device {
pub fn create(
instance: Rc<Instance>,
phys_device: &PhysicalDevice,
qf_info: &QueueFamilyInfo,
) -> Result<Rc<Self>, ErrDeviceCreate> {
const QUEUE_PRIORITY: [f32; 1] = [1.0];
let queue_create_info = [
vk::DeviceQueueCreateInfo {
queue_family_index: qf_info.gfx_index,
queue_count: 1,
p_queue_priorities: QUEUE_PRIORITY.as_ptr(),
..Default::default()
},
vk::DeviceQueueCreateInfo {
queue_family_index: qf_info.srf_index,
queue_count: 1,
p_queue_priorities: QUEUE_PRIORITY.as_ptr(),
..Default::default()
},
];
let device_features = vk::PhysicalDeviceFeatures::default();
let extensions = [c_str!("VK_KHR_swapchain")];
let create_info = vk::DeviceCreateInfo {
queue_create_info_count: queue_create_info.len() as u32,
p_queue_create_infos: queue_create_info.as_ptr(),
p_enabled_features: &device_features,
..enable_device_extensions(&instance, phys_device, &extensions)?
};
let handle =
unsafe { instance.create_device(**phys_device, &create_info, None)? };
let swapchain_ext = khr::Swapchain::new(&**instance, &handle);
Ok(Rc::new(Self { handle, instance, swapchain_ext }))
}
}
impl PhysicalDevice {
pub fn get(
instance: Rc<Instance>,
conf: &Conf,
) -> Result<Rc<Self>, ErrPhysicalDeviceGet> {
let devs = unsafe { instance.enumerate_physical_devices()? };
if conf.device < devs.len() {
let handle = devs[conf.device];
Ok(Rc::new(Self { handle, instance }))
} else {
Err(ErrPhysicalDeviceGet::NoDevice)
}
}
}
impl Drop for Device {
fn drop(&mut self) {
unsafe {
self.handle.destroy_device(None);
}
}
}
impl std::ops::Deref for Device {
type Target = ash::Device;
fn deref(&self) -> &Self::Target {
&self.handle
}
}
impl std::ops::Deref for PhysicalDevice {
type Target = vk::PhysicalDevice;
fn deref(&self) -> &Self::Target {
&self.handle
}
}
impl std::fmt::Display for ErrDeviceCreate {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Vk(res) => res.fmt(f),
Self::NoExtension(err) => write!(f, "Missing extension: {}", err),
}
}
}
impl std::fmt::Display for ErrPhysicalDeviceGet {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Vk(res) => res.fmt(f),
Self::NoDevice => f.write_str("No suitable devices available"),
}
}
}
impl std::error::Error for ErrDeviceCreate {}
impl std::error::Error for ErrPhysicalDeviceGet {}
impl From<vk::Result> for ErrDeviceCreate {
fn from(res: vk::Result) -> Self {
Self::Vk(res)
}
}
impl From<ErrNoProperty> for ErrDeviceCreate {
fn from(err: ErrNoProperty) -> Self {
Self::NoExtension(err)
}
}
impl From<vk::Result> for ErrPhysicalDeviceGet {
fn from(res: vk::Result) -> Self {
Self::Vk(res)
}
}
// EOF