2023-01-10 14:54:54 +11:00
|
|
|
use ash::vk;
|
2023-01-03 16:55:35 +11:00
|
|
|
use std::borrow::Cow;
|
|
|
|
use std::error::Error;
|
|
|
|
|
2023-01-13 17:48:04 +11:00
|
|
|
use crate::error::FilterChainError;
|
2023-01-14 09:59:22 +11:00
|
|
|
use crate::filter_chain::VulkanObjects;
|
2023-01-03 16:55:35 +11:00
|
|
|
use crate::hello_triangle::debug::VulkanDebug;
|
|
|
|
use crate::hello_triangle::physicaldevice::{find_queue_family, pick_physical_device};
|
|
|
|
use crate::hello_triangle::surface::VulkanSurface;
|
2023-01-10 14:54:54 +11:00
|
|
|
use ash::prelude::VkResult;
|
|
|
|
use std::ffi::{CStr, CString};
|
2023-01-15 07:06:43 +11:00
|
|
|
use std::sync::Arc;
|
2023-01-03 16:55:35 +11:00
|
|
|
|
2023-01-13 16:07:03 +11:00
|
|
|
const WINDOW_TITLE: &'static [u8] = b"librashader Vulkan\0";
|
|
|
|
const KHRONOS_VALIDATION: &'static [u8] = b"VK_LAYER_KHRONOS_validation\0";
|
2023-01-03 16:55:35 +11:00
|
|
|
|
|
|
|
pub struct VulkanBase {
|
|
|
|
pub entry: ash::Entry,
|
|
|
|
pub instance: ash::Instance,
|
2023-01-15 07:06:43 +11:00
|
|
|
pub device: Arc<ash::Device>,
|
2023-01-03 16:55:35 +11:00
|
|
|
pub graphics_queue: vk::Queue,
|
|
|
|
pub debug: VulkanDebug,
|
|
|
|
pub physical_device: vk::PhysicalDevice,
|
|
|
|
pub mem_props: vk::PhysicalDeviceMemoryProperties,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl VulkanBase {
|
|
|
|
pub fn new(entry: ash::Entry) -> VkResult<VulkanBase> {
|
|
|
|
let app_info = vk::ApplicationInfo::builder()
|
2023-01-13 16:07:03 +11:00
|
|
|
.application_name(unsafe { &CStr::from_bytes_with_nul_unchecked(WINDOW_TITLE) })
|
|
|
|
.engine_name(unsafe { &CStr::from_bytes_with_nul_unchecked(WINDOW_TITLE) })
|
2023-01-03 16:55:35 +11:00
|
|
|
.engine_version(0)
|
|
|
|
.application_version(0)
|
|
|
|
.api_version(vk::make_api_version(0, 1, 3, 0))
|
|
|
|
.build();
|
|
|
|
|
2023-01-13 16:07:03 +11:00
|
|
|
dbg!("entry");
|
2023-01-03 16:55:35 +11:00
|
|
|
// todo: make this xplat
|
|
|
|
let extensions = [
|
|
|
|
ash::extensions::khr::Surface::name().as_ptr(),
|
|
|
|
ash::extensions::khr::Win32Surface::name().as_ptr(),
|
2023-01-10 14:54:54 +11:00
|
|
|
ash::extensions::ext::DebugUtils::name().as_ptr(),
|
2023-01-03 16:55:35 +11:00
|
|
|
];
|
|
|
|
|
2023-01-13 17:48:04 +11:00
|
|
|
let layers = unsafe { [KHRONOS_VALIDATION.as_ptr().cast()] };
|
2023-01-03 16:55:35 +11:00
|
|
|
|
|
|
|
let create_info = vk::InstanceCreateInfo::builder()
|
|
|
|
.application_info(&app_info)
|
|
|
|
.enabled_layer_names(&layers)
|
|
|
|
.enabled_extension_names(&extensions)
|
|
|
|
.build();
|
|
|
|
|
2023-01-10 14:54:54 +11:00
|
|
|
let instance = unsafe { entry.create_instance(&create_info, None)? };
|
2023-01-03 16:55:35 +11:00
|
|
|
|
|
|
|
let debug = VulkanDebug::new(&entry, &instance, Some(vulkan_debug_callback))?;
|
|
|
|
|
|
|
|
let physical_device = pick_physical_device(&instance);
|
|
|
|
|
2023-01-13 16:07:03 +11:00
|
|
|
dbg!("picked physdev");
|
2023-01-03 16:55:35 +11:00
|
|
|
let (device, queue) = VulkanBase::create_device(&instance, &physical_device)?;
|
2023-01-13 16:07:03 +11:00
|
|
|
dbg!("created device");
|
2023-01-03 16:55:35 +11:00
|
|
|
|
2023-01-10 14:54:54 +11:00
|
|
|
let mem_props = unsafe { instance.get_physical_device_memory_properties(physical_device) };
|
2023-01-13 16:07:03 +11:00
|
|
|
dbg!("got memprops");
|
2023-01-03 16:55:35 +11:00
|
|
|
|
|
|
|
Ok(VulkanBase {
|
|
|
|
entry,
|
|
|
|
instance,
|
2023-01-15 07:06:43 +11:00
|
|
|
device: Arc::new(device),
|
2023-01-03 16:55:35 +11:00
|
|
|
graphics_queue: queue,
|
|
|
|
physical_device,
|
|
|
|
mem_props,
|
|
|
|
debug,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-01-10 14:54:54 +11:00
|
|
|
fn create_device(
|
|
|
|
instance: &ash::Instance,
|
|
|
|
physical_device: &vk::PhysicalDevice,
|
|
|
|
) -> VkResult<(ash::Device, vk::Queue)> {
|
2023-01-13 17:48:04 +11:00
|
|
|
let debug = [unsafe { CStr::from_bytes_with_nul_unchecked(KHRONOS_VALIDATION).as_ptr() }];
|
2023-01-03 16:55:35 +11:00
|
|
|
|
|
|
|
let indices = find_queue_family(&instance, *physical_device);
|
2023-01-13 16:07:03 +11:00
|
|
|
let queue_info = [vk::DeviceQueueCreateInfo::builder()
|
2023-01-03 16:55:35 +11:00
|
|
|
.queue_family_index(indices.graphics_family())
|
|
|
|
.queue_priorities(&[1.0f32])
|
2023-01-13 16:07:03 +11:00
|
|
|
.build()];
|
2023-01-03 16:55:35 +11:00
|
|
|
|
2023-01-12 09:53:43 +11:00
|
|
|
// let physical_device_features = vk::PhysicalDeviceFeatures::default();
|
|
|
|
|
|
|
|
let mut physical_device_features = vk::PhysicalDeviceVulkan13Features::builder()
|
|
|
|
.dynamic_rendering(true)
|
|
|
|
.build();
|
|
|
|
|
|
|
|
// let mut physical_device_features =
|
|
|
|
// vk::PhysicalDeviceFeatures2::builder().push_next(&mut physical_device_features)
|
|
|
|
// .build();
|
|
|
|
|
2023-01-13 16:07:03 +11:00
|
|
|
let extensions = [
|
|
|
|
ash::extensions::khr::Swapchain::name().as_ptr(),
|
|
|
|
ash::extensions::khr::DynamicRendering::name().as_ptr(),
|
|
|
|
];
|
|
|
|
|
2023-01-03 16:55:35 +11:00
|
|
|
let device_create_info = vk::DeviceCreateInfo::builder()
|
2023-01-13 16:07:03 +11:00
|
|
|
.queue_create_infos(&queue_info)
|
|
|
|
.enabled_layer_names(&debug)
|
|
|
|
.enabled_extension_names(&extensions)
|
2023-01-12 09:53:43 +11:00
|
|
|
.push_next(&mut physical_device_features)
|
|
|
|
// .enabled_features(&physical_device_features)
|
2023-01-03 16:55:35 +11:00
|
|
|
.build();
|
|
|
|
|
2023-01-10 14:54:54 +11:00
|
|
|
let device =
|
|
|
|
unsafe { instance.create_device(*physical_device, &device_create_info, None)? };
|
2023-01-03 16:55:35 +11:00
|
|
|
|
|
|
|
let queue = unsafe { device.get_device_queue(indices.graphics_family(), 0) };
|
|
|
|
|
|
|
|
Ok((device, queue))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
unsafe extern "system" fn vulkan_debug_callback(
|
|
|
|
message_severity: vk::DebugUtilsMessageSeverityFlagsEXT,
|
|
|
|
message_type: vk::DebugUtilsMessageTypeFlagsEXT,
|
|
|
|
p_callback_data: *const vk::DebugUtilsMessengerCallbackDataEXT,
|
|
|
|
_user_data: *mut std::os::raw::c_void,
|
|
|
|
) -> vk::Bool32 {
|
2023-01-13 16:07:03 +11:00
|
|
|
// let callback_data = *p_callback_data;
|
|
|
|
// let message_id_number: i32 = callback_data.message_id_number as i32;
|
|
|
|
//
|
|
|
|
// let message_id_name = if callback_data.p_message_id_name.is_null() {
|
|
|
|
// Cow::from("")
|
|
|
|
// } else {
|
|
|
|
// CStr::from_ptr(callback_data.p_message_id_name).to_string_lossy()
|
|
|
|
// };
|
|
|
|
//
|
|
|
|
// let message = if callback_data.p_message.is_null() {
|
|
|
|
// Cow::from("")
|
|
|
|
// } else {
|
|
|
|
// CStr::from_ptr(callback_data.p_message).to_string_lossy()
|
|
|
|
// };
|
|
|
|
//
|
|
|
|
// println!(
|
|
|
|
// "{:?}:\n{:?} [{} ({})] : {}\n",
|
|
|
|
// message_severity,
|
|
|
|
// message_type,
|
|
|
|
// message_id_name,
|
|
|
|
// &message_id_number.to_string(),
|
|
|
|
// message,
|
|
|
|
// );
|
2023-01-03 16:55:35 +11:00
|
|
|
|
|
|
|
vk::FALSE
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Drop for VulkanBase {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
unsafe {
|
|
|
|
self.device.destroy_device(None);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-14 09:59:22 +11:00
|
|
|
impl TryFrom<&VulkanBase> for VulkanObjects {
|
2023-01-13 17:19:41 +11:00
|
|
|
type Error = FilterChainError;
|
2023-01-03 16:55:35 +11:00
|
|
|
|
|
|
|
fn try_from(value: &VulkanBase) -> Result<Self, Self::Error> {
|
2023-01-14 09:59:22 +11:00
|
|
|
VulkanObjects::try_from((
|
2023-01-13 17:19:41 +11:00
|
|
|
value.physical_device,
|
|
|
|
value.instance.clone(),
|
2023-01-10 14:54:54 +11:00
|
|
|
value.device.clone(),
|
|
|
|
))
|
2023-01-03 16:55:35 +11:00
|
|
|
}
|
2023-01-10 14:54:54 +11:00
|
|
|
}
|