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.

177 lines
3.9KB

  1. use crate::render::{
  2. ensure_properties, Conf, ErrNoProperty, Instance, QueueFamilyInfo,
  3. };
  4. use ash::{
  5. extensions::khr,
  6. version::{DeviceV1_0, InstanceV1_0},
  7. vk,
  8. };
  9. use std::{os::raw::c_char, rc::Rc};
  10. pub struct Device {
  11. handle: ash::Device,
  12. pub instance: Rc<Instance>,
  13. pub swapchain_ext: khr::Swapchain,
  14. }
  15. pub struct PhysicalDevice {
  16. handle: vk::PhysicalDevice,
  17. pub instance: Rc<Instance>,
  18. }
  19. #[derive(Debug)]
  20. pub enum ErrDeviceCreate {
  21. Vk(vk::Result),
  22. NoExtension(ErrNoProperty),
  23. }
  24. #[derive(Debug)]
  25. pub enum ErrPhysicalDeviceGet {
  26. Vk(vk::Result),
  27. NoDevice,
  28. }
  29. fn enable_device_extensions(
  30. instance: &ash::Instance,
  31. phys_device: &PhysicalDevice,
  32. extensions: &[*const c_char],
  33. ) -> Result<vk::DeviceCreateInfo, ErrDeviceCreate> {
  34. if !extensions.is_empty() {
  35. let props = unsafe {
  36. instance.enumerate_device_extension_properties(**phys_device)?
  37. };
  38. ensure_properties(&props, extensions, |x| x.extension_name.as_ptr())?;
  39. }
  40. Ok(vk::DeviceCreateInfo {
  41. enabled_extension_count: extensions.len() as u32,
  42. pp_enabled_extension_names: extensions.as_ptr(),
  43. ..Default::default()
  44. })
  45. }
  46. impl Device {
  47. pub fn create(
  48. instance: Rc<Instance>,
  49. phys_device: &PhysicalDevice,
  50. qf_info: &QueueFamilyInfo,
  51. ) -> Result<Rc<Self>, ErrDeviceCreate> {
  52. const QUEUE_PRIORITY: [f32; 1] = [1.0];
  53. let queue_create_info = [
  54. vk::DeviceQueueCreateInfo {
  55. queue_family_index: qf_info.gfx_index,
  56. queue_count: 1,
  57. p_queue_priorities: QUEUE_PRIORITY.as_ptr(),
  58. ..Default::default()
  59. },
  60. vk::DeviceQueueCreateInfo {
  61. queue_family_index: qf_info.srf_index,
  62. queue_count: 1,
  63. p_queue_priorities: QUEUE_PRIORITY.as_ptr(),
  64. ..Default::default()
  65. },
  66. ];
  67. let device_features = vk::PhysicalDeviceFeatures::default();
  68. let extensions = [c_str!("VK_KHR_swapchain")];
  69. let create_info = vk::DeviceCreateInfo {
  70. queue_create_info_count: queue_create_info.len() as u32,
  71. p_queue_create_infos: queue_create_info.as_ptr(),
  72. p_enabled_features: &device_features,
  73. ..enable_device_extensions(&instance, phys_device, &extensions)?
  74. };
  75. let handle =
  76. unsafe { instance.create_device(**phys_device, &create_info, None)? };
  77. let swapchain_ext = khr::Swapchain::new(&**instance, &handle);
  78. Ok(Rc::new(Self { handle, instance, swapchain_ext }))
  79. }
  80. }
  81. impl PhysicalDevice {
  82. pub fn get(
  83. instance: Rc<Instance>,
  84. conf: &Conf,
  85. ) -> Result<Rc<Self>, ErrPhysicalDeviceGet> {
  86. let devs = unsafe { instance.enumerate_physical_devices()? };
  87. if conf.device < devs.len() {
  88. let handle = devs[conf.device];
  89. Ok(Rc::new(Self { handle, instance }))
  90. } else {
  91. Err(ErrPhysicalDeviceGet::NoDevice)
  92. }
  93. }
  94. }
  95. impl Drop for Device {
  96. fn drop(&mut self) {
  97. unsafe {
  98. self.handle.destroy_device(None);
  99. }
  100. }
  101. }
  102. impl std::ops::Deref for Device {
  103. type Target = ash::Device;
  104. fn deref(&self) -> &Self::Target {
  105. &self.handle
  106. }
  107. }
  108. impl std::ops::Deref for PhysicalDevice {
  109. type Target = vk::PhysicalDevice;
  110. fn deref(&self) -> &Self::Target {
  111. &self.handle
  112. }
  113. }
  114. impl std::fmt::Display for ErrDeviceCreate {
  115. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  116. match self {
  117. Self::Vk(res) => res.fmt(f),
  118. Self::NoExtension(err) => write!(f, "Missing extension: {}", err),
  119. }
  120. }
  121. }
  122. impl std::fmt::Display for ErrPhysicalDeviceGet {
  123. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  124. match self {
  125. Self::Vk(res) => res.fmt(f),
  126. Self::NoDevice => f.write_str("No suitable devices available"),
  127. }
  128. }
  129. }
  130. impl std::error::Error for ErrDeviceCreate {}
  131. impl std::error::Error for ErrPhysicalDeviceGet {}
  132. impl From<vk::Result> for ErrDeviceCreate {
  133. fn from(res: vk::Result) -> Self {
  134. Self::Vk(res)
  135. }
  136. }
  137. impl From<ErrNoProperty> for ErrDeviceCreate {
  138. fn from(err: ErrNoProperty) -> Self {
  139. Self::NoExtension(err)
  140. }
  141. }
  142. impl From<vk::Result> for ErrPhysicalDeviceGet {
  143. fn from(res: vk::Result) -> Self {
  144. Self::Vk(res)
  145. }
  146. }
  147. // EOF