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.

131 lines
2.8KB

  1. use crate::{
  2. hal::ErrSdl,
  3. render::{ensure_properties, Conf, ErrNoProperty},
  4. util::meta,
  5. };
  6. use ash::{
  7. extensions::khr,
  8. version::{EntryV1_0, InstanceV1_0},
  9. vk, vk_make_version, InstanceError,
  10. };
  11. use std::{os::raw::c_char, rc::Rc};
  12. pub struct Instance {
  13. #[allow(dead_code)]
  14. entry: ash::Entry,
  15. handle: ash::Instance,
  16. pub surface_ext: khr::Surface,
  17. }
  18. #[derive(Debug)]
  19. pub enum ErrInstanceCreate {
  20. Vk(vk::Result),
  21. Instance(InstanceError),
  22. NoExtension(ErrNoProperty),
  23. Sdl(ErrSdl),
  24. }
  25. fn enable_instance_layers(
  26. layers: &[*const c_char],
  27. entry: &ash::Entry,
  28. ) -> Result<vk::InstanceCreateInfo, ErrInstanceCreate> {
  29. if !layers.is_empty() {
  30. let props = entry.enumerate_instance_layer_properties()?;
  31. ensure_properties(&props, layers, |x| x.layer_name.as_ptr())?;
  32. }
  33. Ok(vk::InstanceCreateInfo {
  34. enabled_layer_count: layers.len() as u32,
  35. pp_enabled_layer_names: layers.as_ptr(),
  36. ..Default::default()
  37. })
  38. }
  39. impl Instance {
  40. pub fn create(
  41. conf: &Conf,
  42. entry: ash::Entry,
  43. window: &crate::hal::Window,
  44. ) -> Result<Rc<Self>, ErrInstanceCreate> {
  45. let exts = window.vulkan_instance_extensions()?;
  46. let app_info = vk::ApplicationInfo {
  47. p_engine_name: meta::ffi::name(),
  48. api_version: vk_make_version!(1, 0, 0),
  49. ..Default::default()
  50. };
  51. let mut layers = Vec::new();
  52. if conf.validation_layers {
  53. layers.push(c_str!("VK_LAYER_KHRONOS_validation"));
  54. }
  55. let create_info = vk::InstanceCreateInfo {
  56. p_application_info: &app_info,
  57. enabled_extension_count: exts.len() as u32,
  58. pp_enabled_extension_names: exts.as_ptr(),
  59. ..enable_instance_layers(&layers, &entry)?
  60. };
  61. let handle = unsafe { entry.create_instance(&create_info, None)? };
  62. let surface_ext = khr::Surface::new(&entry, &handle);
  63. Ok(Rc::new(Self { entry, handle, surface_ext }))
  64. }
  65. }
  66. impl Drop for Instance {
  67. fn drop(&mut self) {
  68. unsafe {
  69. self.handle.destroy_instance(None);
  70. }
  71. }
  72. }
  73. impl std::ops::Deref for Instance {
  74. type Target = ash::Instance;
  75. fn deref(&self) -> &Self::Target {
  76. &self.handle
  77. }
  78. }
  79. impl std::fmt::Display for ErrInstanceCreate {
  80. fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
  81. match self {
  82. Self::Vk(res) => res.fmt(f),
  83. Self::Instance(err) => err.fmt(f),
  84. Self::NoExtension(err) => write!(f, "Missing extension: {}", err),
  85. Self::Sdl(err) => err.fmt(f),
  86. }
  87. }
  88. }
  89. impl std::error::Error for ErrInstanceCreate {}
  90. impl From<vk::Result> for ErrInstanceCreate {
  91. fn from(res: vk::Result) -> Self {
  92. Self::Vk(res)
  93. }
  94. }
  95. impl From<InstanceError> for ErrInstanceCreate {
  96. fn from(err: InstanceError) -> Self {
  97. Self::Instance(err)
  98. }
  99. }
  100. impl From<ErrNoProperty> for ErrInstanceCreate {
  101. fn from(err: ErrNoProperty) -> Self {
  102. Self::NoExtension(err)
  103. }
  104. }
  105. impl From<ErrSdl> for ErrInstanceCreate {
  106. fn from(err: ErrSdl) -> Self {
  107. Self::Sdl(err)
  108. }
  109. }
  110. // EOF