2016-12-26 00:38:26 +11:00
|
|
|
extern crate ash;
|
2019-02-27 06:54:48 +11:00
|
|
|
extern crate winit;
|
2020-09-03 17:07:09 +10:00
|
|
|
|
2018-12-05 07:22:03 +11:00
|
|
|
use ash::extensions::{
|
2020-04-29 17:28:59 +10:00
|
|
|
ext::DebugUtils,
|
2018-12-05 07:22:03 +11:00
|
|
|
khr::{Surface, Swapchain},
|
|
|
|
};
|
2021-05-01 01:13:23 +10:00
|
|
|
use ash::{vk, Entry};
|
2021-09-10 06:50:34 +10:00
|
|
|
pub use ash::{Device, Instance};
|
2022-09-23 20:40:12 +10:00
|
|
|
use raw_window_handle::{HasRawDisplayHandle, HasRawWindowHandle};
|
2020-04-29 17:28:59 +10:00
|
|
|
use std::borrow::Cow;
|
2017-12-13 00:25:10 +11:00
|
|
|
use std::cell::RefCell;
|
2018-07-31 22:51:45 +10:00
|
|
|
use std::default::Default;
|
2021-12-28 10:14:56 +11:00
|
|
|
use std::ffi::CStr;
|
2016-12-26 00:38:26 +11:00
|
|
|
use std::ops::Drop;
|
2021-12-22 06:42:47 +11:00
|
|
|
use std::os::raw::c_char;
|
2016-12-26 00:38:26 +11:00
|
|
|
|
2022-05-27 19:05:15 +10:00
|
|
|
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
|
|
|
use ash::vk::{
|
|
|
|
KhrGetPhysicalDeviceProperties2Fn, KhrPortabilityEnumerationFn, KhrPortabilitySubsetFn,
|
|
|
|
};
|
|
|
|
|
2021-11-09 09:25:13 +11:00
|
|
|
use winit::{
|
2021-11-10 05:12:51 +11:00
|
|
|
event::{ElementState, Event, KeyboardInput, VirtualKeyCode, WindowEvent},
|
2021-11-09 09:25:13 +11:00
|
|
|
event_loop::{ControlFlow, EventLoop},
|
|
|
|
platform::run_return::EventLoopExtRunReturn,
|
|
|
|
window::WindowBuilder,
|
|
|
|
};
|
|
|
|
|
2016-12-26 00:38:26 +11:00
|
|
|
// Simple offset_of macro akin to C++ offsetof
|
|
|
|
#[macro_export]
|
2018-07-31 22:51:45 +10:00
|
|
|
macro_rules! offset_of {
|
|
|
|
($base:path, $field:ident) => {{
|
|
|
|
#[allow(unused_unsafe)]
|
|
|
|
unsafe {
|
2019-05-26 05:13:17 +10:00
|
|
|
let b: $base = mem::zeroed();
|
2022-11-23 05:52:14 +11:00
|
|
|
std::ptr::addr_of!(b.$field) as isize - std::ptr::addr_of!(b) as isize
|
2016-12-26 00:38:26 +11:00
|
|
|
}
|
2018-07-31 22:51:45 +10:00
|
|
|
}};
|
2016-12-26 00:38:26 +11:00
|
|
|
}
|
2020-10-03 08:08:42 +10:00
|
|
|
/// Helper function for submitting command buffers. Immediately waits for the fence before the command buffer
|
|
|
|
/// is executed. That way we can delay the waiting for the fences by 1 frame which is good for performance.
|
|
|
|
/// Make sure to create the fence in a signaled state on the first use.
|
|
|
|
#[allow(clippy::too_many_arguments)]
|
2021-05-01 01:13:23 +10:00
|
|
|
pub fn record_submit_commandbuffer<F: FnOnce(&Device, vk::CommandBuffer)>(
|
|
|
|
device: &Device,
|
2017-12-13 00:25:10 +11:00
|
|
|
command_buffer: vk::CommandBuffer,
|
2020-10-03 08:08:42 +10:00
|
|
|
command_buffer_reuse_fence: vk::Fence,
|
2017-12-13 00:25:10 +11:00
|
|
|
submit_queue: vk::Queue,
|
|
|
|
wait_mask: &[vk::PipelineStageFlags],
|
|
|
|
wait_semaphores: &[vk::Semaphore],
|
|
|
|
signal_semaphores: &[vk::Semaphore],
|
|
|
|
f: F,
|
|
|
|
) {
|
2016-12-26 00:38:26 +11:00
|
|
|
unsafe {
|
2020-10-03 08:08:42 +10:00
|
|
|
device
|
|
|
|
.wait_for_fences(&[command_buffer_reuse_fence], true, std::u64::MAX)
|
|
|
|
.expect("Wait for fence failed.");
|
|
|
|
|
|
|
|
device
|
|
|
|
.reset_fences(&[command_buffer_reuse_fence])
|
|
|
|
.expect("Reset fences failed.");
|
|
|
|
|
2017-12-13 00:25:10 +11:00
|
|
|
device
|
|
|
|
.reset_command_buffer(
|
|
|
|
command_buffer,
|
2018-07-31 20:45:29 +10:00
|
|
|
vk::CommandBufferResetFlags::RELEASE_RESOURCES,
|
2018-12-08 04:47:57 +11:00
|
|
|
)
|
|
|
|
.expect("Reset command buffer failed.");
|
2018-12-10 00:47:29 +11:00
|
|
|
|
2022-03-30 04:15:14 +11:00
|
|
|
let command_buffer_begin_info = vk::CommandBufferBeginInfo::default()
|
2018-12-07 14:53:53 +11:00
|
|
|
.flags(vk::CommandBufferUsageFlags::ONE_TIME_SUBMIT);
|
2018-12-07 01:58:12 +11:00
|
|
|
|
2017-12-13 00:25:10 +11:00
|
|
|
device
|
|
|
|
.begin_command_buffer(command_buffer, &command_buffer_begin_info)
|
2016-12-26 00:38:26 +11:00
|
|
|
.expect("Begin commandbuffer");
|
|
|
|
f(device, command_buffer);
|
2017-12-13 00:25:10 +11:00
|
|
|
device
|
|
|
|
.end_command_buffer(command_buffer)
|
|
|
|
.expect("End commandbuffer");
|
2018-12-07 01:58:12 +11:00
|
|
|
|
2018-12-07 14:53:53 +11:00
|
|
|
let command_buffers = vec![command_buffer];
|
2018-12-10 07:33:21 +11:00
|
|
|
|
2022-03-30 04:15:14 +11:00
|
|
|
let submit_info = vk::SubmitInfo::default()
|
2018-12-10 06:41:23 +11:00
|
|
|
.wait_semaphores(wait_semaphores)
|
|
|
|
.wait_dst_stage_mask(wait_mask)
|
|
|
|
.command_buffers(&command_buffers)
|
2018-12-10 07:33:21 +11:00
|
|
|
.signal_semaphores(signal_semaphores);
|
|
|
|
|
2017-12-13 00:25:10 +11:00
|
|
|
device
|
2022-03-30 04:15:14 +11:00
|
|
|
.queue_submit(submit_queue, &[submit_info], command_buffer_reuse_fence)
|
2016-12-26 11:58:44 +11:00
|
|
|
.expect("queue submit failed.");
|
2016-12-26 00:38:26 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-13 00:25:10 +11:00
|
|
|
unsafe extern "system" fn vulkan_debug_callback(
|
2020-04-29 17:28:59 +10:00
|
|
|
message_severity: vk::DebugUtilsMessageSeverityFlagsEXT,
|
|
|
|
message_type: vk::DebugUtilsMessageTypeFlagsEXT,
|
|
|
|
p_callback_data: *const vk::DebugUtilsMessengerCallbackDataEXT,
|
|
|
|
_user_data: *mut std::os::raw::c_void,
|
|
|
|
) -> vk::Bool32 {
|
|
|
|
let callback_data = *p_callback_data;
|
2022-12-20 05:18:45 +11:00
|
|
|
let message_id_number = callback_data.message_id_number;
|
2020-04-29 17:28:59 +10:00
|
|
|
|
|
|
|
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!(
|
2023-02-18 04:11:44 +11:00
|
|
|
"{message_severity:?}:\n{message_type:?} [{message_id_name} ({message_id_number})] : {message}\n",
|
2020-04-29 17:28:59 +10:00
|
|
|
);
|
|
|
|
|
2018-11-12 23:12:38 +11:00
|
|
|
vk::FALSE
|
2016-12-26 00:38:26 +11:00
|
|
|
}
|
|
|
|
|
2017-12-13 00:25:10 +11:00
|
|
|
pub fn find_memorytype_index(
|
|
|
|
memory_req: &vk::MemoryRequirements,
|
|
|
|
memory_prop: &vk::PhysicalDeviceMemoryProperties,
|
|
|
|
flags: vk::MemoryPropertyFlags,
|
|
|
|
) -> Option<u32> {
|
2020-10-29 17:37:31 +11:00
|
|
|
memory_prop.memory_types[..memory_prop.memory_type_count as _]
|
2020-10-19 21:11:57 +11:00
|
|
|
.iter()
|
|
|
|
.enumerate()
|
|
|
|
.find(|(index, memory_type)| {
|
|
|
|
(1 << index) & memory_req.memory_type_bits != 0
|
|
|
|
&& memory_type.property_flags & flags == flags
|
|
|
|
})
|
|
|
|
.map(|(index, _memory_type)| index as _)
|
2016-12-26 00:38:26 +11:00
|
|
|
}
|
2016-12-29 16:02:37 +11:00
|
|
|
|
2016-12-26 00:38:26 +11:00
|
|
|
pub struct ExampleBase {
|
2018-11-11 20:41:58 +11:00
|
|
|
pub entry: Entry,
|
|
|
|
pub instance: Instance,
|
|
|
|
pub device: Device,
|
2016-12-26 00:38:26 +11:00
|
|
|
pub surface_loader: Surface,
|
|
|
|
pub swapchain_loader: Swapchain,
|
2020-04-29 17:28:59 +10:00
|
|
|
pub debug_utils_loader: DebugUtils,
|
2021-11-09 09:25:13 +11:00
|
|
|
pub window: winit::window::Window,
|
2021-12-21 10:45:18 +11:00
|
|
|
pub event_loop: RefCell<EventLoop<()>>,
|
2020-04-29 17:28:59 +10:00
|
|
|
pub debug_call_back: vk::DebugUtilsMessengerEXT,
|
2016-12-26 00:38:26 +11:00
|
|
|
|
|
|
|
pub pdevice: vk::PhysicalDevice,
|
|
|
|
pub device_memory_properties: vk::PhysicalDeviceMemoryProperties,
|
|
|
|
pub queue_family_index: u32,
|
|
|
|
pub present_queue: vk::Queue,
|
|
|
|
|
|
|
|
pub surface: vk::SurfaceKHR,
|
|
|
|
pub surface_format: vk::SurfaceFormatKHR,
|
|
|
|
pub surface_resolution: vk::Extent2D,
|
|
|
|
|
|
|
|
pub swapchain: vk::SwapchainKHR,
|
|
|
|
pub present_images: Vec<vk::Image>,
|
|
|
|
pub present_image_views: Vec<vk::ImageView>,
|
|
|
|
|
|
|
|
pub pool: vk::CommandPool,
|
|
|
|
pub draw_command_buffer: vk::CommandBuffer,
|
|
|
|
pub setup_command_buffer: vk::CommandBuffer,
|
|
|
|
|
|
|
|
pub depth_image: vk::Image,
|
|
|
|
pub depth_image_view: vk::ImageView,
|
|
|
|
pub depth_image_memory: vk::DeviceMemory,
|
|
|
|
|
|
|
|
pub present_complete_semaphore: vk::Semaphore,
|
|
|
|
pub rendering_complete_semaphore: vk::Semaphore,
|
2020-10-03 08:08:42 +10:00
|
|
|
|
|
|
|
pub draw_commands_reuse_fence: vk::Fence,
|
|
|
|
pub setup_commands_reuse_fence: vk::Fence,
|
2016-12-26 00:38:26 +11:00
|
|
|
}
|
|
|
|
|
|
|
|
impl ExampleBase {
|
|
|
|
pub fn render_loop<F: Fn()>(&self, f: F) {
|
2021-12-21 10:45:18 +11:00
|
|
|
self.event_loop
|
2021-11-09 09:25:13 +11:00
|
|
|
.borrow_mut()
|
|
|
|
.run_return(|event, _, control_flow| {
|
2022-01-04 09:24:36 +11:00
|
|
|
*control_flow = ControlFlow::Poll;
|
|
|
|
match event {
|
|
|
|
Event::WindowEvent {
|
|
|
|
event:
|
|
|
|
WindowEvent::CloseRequested
|
|
|
|
| WindowEvent::KeyboardInput {
|
|
|
|
input:
|
|
|
|
KeyboardInput {
|
|
|
|
state: ElementState::Pressed,
|
|
|
|
virtual_keycode: Some(VirtualKeyCode::Escape),
|
|
|
|
..
|
|
|
|
},
|
|
|
|
..
|
|
|
|
},
|
|
|
|
..
|
|
|
|
} => *control_flow = ControlFlow::Exit,
|
|
|
|
Event::MainEventsCleared => f(),
|
|
|
|
_ => (),
|
2021-11-09 09:25:13 +11:00
|
|
|
}
|
|
|
|
});
|
2016-12-26 00:38:26 +11:00
|
|
|
}
|
2018-03-03 18:59:28 +11:00
|
|
|
|
2016-12-26 00:38:26 +11:00
|
|
|
pub fn new(window_width: u32, window_height: u32) -> Self {
|
|
|
|
unsafe {
|
2021-12-21 10:45:18 +11:00
|
|
|
let event_loop = EventLoop::new();
|
2021-11-09 09:25:13 +11:00
|
|
|
let window = WindowBuilder::new()
|
2017-01-05 18:09:23 +11:00
|
|
|
.with_title("Ash - Example")
|
2021-11-09 09:25:13 +11:00
|
|
|
.with_inner_size(winit::dpi::LogicalSize::new(
|
2019-10-21 02:18:40 +11:00
|
|
|
f64::from(window_width),
|
|
|
|
f64::from(window_height),
|
2018-12-08 04:47:57 +11:00
|
|
|
))
|
2021-12-21 10:45:18 +11:00
|
|
|
.build(&event_loop)
|
2016-12-26 00:38:26 +11:00
|
|
|
.unwrap();
|
2021-12-27 21:49:40 +11:00
|
|
|
let entry = Entry::linked();
|
2021-12-28 10:14:56 +11:00
|
|
|
let app_name = CStr::from_bytes_with_nul_unchecked(b"VulkanTriangle\0");
|
2016-12-26 00:38:26 +11:00
|
|
|
|
2021-12-22 06:42:47 +11:00
|
|
|
let layer_names = [CStr::from_bytes_with_nul_unchecked(
|
|
|
|
b"VK_LAYER_KHRONOS_validation\0",
|
|
|
|
)];
|
|
|
|
let layers_names_raw: Vec<*const c_char> = layer_names
|
2017-12-13 00:25:10 +11:00
|
|
|
.iter()
|
2016-12-26 00:38:26 +11:00
|
|
|
.map(|raw_name| raw_name.as_ptr())
|
|
|
|
.collect();
|
2018-07-07 14:45:52 +10:00
|
|
|
|
2022-09-23 20:40:12 +10:00
|
|
|
let mut extension_names =
|
|
|
|
ash_window::enumerate_required_extensions(window.raw_display_handle())
|
|
|
|
.unwrap()
|
|
|
|
.to_vec();
|
2023-03-10 09:53:04 +11:00
|
|
|
extension_names.push(DebugUtils::NAME.as_ptr());
|
2018-12-07 01:58:12 +11:00
|
|
|
|
2022-05-27 19:05:15 +10:00
|
|
|
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
|
|
|
{
|
2023-03-10 09:53:04 +11:00
|
|
|
extension_names.push(KhrPortabilityEnumerationFn::NAME.as_ptr());
|
2022-05-27 19:05:15 +10:00
|
|
|
// Enabling this extension is a requirement when using `VK_KHR_portability_subset`
|
2023-03-10 09:53:04 +11:00
|
|
|
extension_names.push(KhrGetPhysicalDeviceProperties2Fn::NAME.as_ptr());
|
2022-05-27 19:05:15 +10:00
|
|
|
}
|
|
|
|
|
2022-03-30 04:15:14 +11:00
|
|
|
let appinfo = vk::ApplicationInfo::default()
|
2021-12-28 10:14:56 +11:00
|
|
|
.application_name(app_name)
|
2018-12-07 01:58:12 +11:00
|
|
|
.application_version(0)
|
2021-12-28 10:14:56 +11:00
|
|
|
.engine_name(app_name)
|
2018-12-07 01:58:12 +11:00
|
|
|
.engine_version(0)
|
2021-06-06 19:00:29 +10:00
|
|
|
.api_version(vk::make_api_version(0, 1, 0, 0));
|
2018-12-07 01:58:12 +11:00
|
|
|
|
2022-05-27 19:05:15 +10:00
|
|
|
let create_flags = if cfg!(any(target_os = "macos", target_os = "ios")) {
|
|
|
|
vk::InstanceCreateFlags::ENUMERATE_PORTABILITY_KHR
|
|
|
|
} else {
|
|
|
|
vk::InstanceCreateFlags::default()
|
|
|
|
};
|
|
|
|
|
2022-03-30 04:15:14 +11:00
|
|
|
let create_info = vk::InstanceCreateInfo::default()
|
2018-12-07 01:58:12 +11:00
|
|
|
.application_info(&appinfo)
|
|
|
|
.enabled_layer_names(&layers_names_raw)
|
2022-05-27 19:05:15 +10:00
|
|
|
.enabled_extension_names(&extension_names)
|
|
|
|
.flags(create_flags);
|
2018-12-07 01:58:12 +11:00
|
|
|
|
2018-11-11 20:41:58 +11:00
|
|
|
let instance: Instance = entry
|
2017-12-13 00:25:10 +11:00
|
|
|
.create_instance(&create_info, None)
|
2016-12-26 00:38:26 +11:00
|
|
|
.expect("Instance creation error");
|
2018-12-07 01:58:12 +11:00
|
|
|
|
2022-03-30 04:15:14 +11:00
|
|
|
let debug_info = vk::DebugUtilsMessengerCreateInfoEXT::default()
|
2020-04-29 17:28:59 +10:00
|
|
|
.message_severity(
|
|
|
|
vk::DebugUtilsMessageSeverityFlagsEXT::ERROR
|
|
|
|
| vk::DebugUtilsMessageSeverityFlagsEXT::WARNING
|
|
|
|
| vk::DebugUtilsMessageSeverityFlagsEXT::INFO,
|
2018-12-08 04:47:57 +11:00
|
|
|
)
|
2021-11-10 10:35:35 +11:00
|
|
|
.message_type(
|
|
|
|
vk::DebugUtilsMessageTypeFlagsEXT::GENERAL
|
|
|
|
| vk::DebugUtilsMessageTypeFlagsEXT::VALIDATION
|
|
|
|
| vk::DebugUtilsMessageTypeFlagsEXT::PERFORMANCE,
|
|
|
|
)
|
2020-04-29 17:28:59 +10:00
|
|
|
.pfn_user_callback(Some(vulkan_debug_callback));
|
2018-12-07 01:58:12 +11:00
|
|
|
|
2020-04-29 17:28:59 +10:00
|
|
|
let debug_utils_loader = DebugUtils::new(&entry, &instance);
|
|
|
|
let debug_call_back = debug_utils_loader
|
|
|
|
.create_debug_utils_messenger(&debug_info, None)
|
2017-12-13 00:25:10 +11:00
|
|
|
.unwrap();
|
2022-09-23 20:40:12 +10:00
|
|
|
let surface = ash_window::create_surface(
|
|
|
|
&entry,
|
|
|
|
&instance,
|
|
|
|
window.raw_display_handle(),
|
|
|
|
window.raw_window_handle(),
|
|
|
|
None,
|
|
|
|
)
|
|
|
|
.unwrap();
|
2017-12-13 00:25:10 +11:00
|
|
|
let pdevices = instance
|
|
|
|
.enumerate_physical_devices()
|
|
|
|
.expect("Physical device error");
|
2018-11-18 05:05:28 +11:00
|
|
|
let surface_loader = Surface::new(&entry, &instance);
|
2017-12-13 00:25:10 +11:00
|
|
|
let (pdevice, queue_family_index) = pdevices
|
|
|
|
.iter()
|
2022-02-27 08:01:28 +11:00
|
|
|
.find_map(|pdevice| {
|
2017-12-13 00:25:10 +11:00
|
|
|
instance
|
|
|
|
.get_physical_device_queue_family_properties(*pdevice)
|
2016-12-26 00:38:26 +11:00
|
|
|
.iter()
|
|
|
|
.enumerate()
|
2022-02-27 08:01:28 +11:00
|
|
|
.find_map(|(index, info)| {
|
2018-07-31 22:51:45 +10:00
|
|
|
let supports_graphic_and_surface =
|
2018-11-18 05:05:28 +11:00
|
|
|
info.queue_flags.contains(vk::QueueFlags::GRAPHICS)
|
2019-05-19 07:09:12 +10:00
|
|
|
&& surface_loader
|
|
|
|
.get_physical_device_surface_support(
|
|
|
|
*pdevice,
|
|
|
|
index as u32,
|
|
|
|
surface,
|
|
|
|
)
|
|
|
|
.unwrap();
|
2019-10-21 02:18:40 +11:00
|
|
|
if supports_graphic_and_surface {
|
|
|
|
Some((*pdevice, index))
|
|
|
|
} else {
|
|
|
|
None
|
2016-12-26 00:38:26 +11:00
|
|
|
}
|
2018-12-08 04:47:57 +11:00
|
|
|
})
|
|
|
|
})
|
2016-12-26 00:38:26 +11:00
|
|
|
.expect("Couldn't find suitable device.");
|
|
|
|
let queue_family_index = queue_family_index as u32;
|
2022-05-27 19:05:15 +10:00
|
|
|
let device_extension_names_raw = [
|
2023-03-10 09:53:04 +11:00
|
|
|
Swapchain::NAME.as_ptr(),
|
2022-05-27 19:05:15 +10:00
|
|
|
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
2023-03-10 09:53:04 +11:00
|
|
|
KhrPortabilitySubsetFn::NAME.as_ptr(),
|
2022-05-27 19:05:15 +10:00
|
|
|
];
|
2017-12-13 00:25:10 +11:00
|
|
|
let features = vk::PhysicalDeviceFeatures {
|
|
|
|
shader_clip_distance: 1,
|
|
|
|
..Default::default()
|
|
|
|
};
|
2016-12-26 00:38:26 +11:00
|
|
|
let priorities = [1.0];
|
2018-12-07 01:58:12 +11:00
|
|
|
|
2022-03-30 04:15:14 +11:00
|
|
|
let queue_info = vk::DeviceQueueCreateInfo::default()
|
2018-12-08 04:47:57 +11:00
|
|
|
.queue_family_index(queue_family_index)
|
2021-12-19 22:33:39 +11:00
|
|
|
.queue_priorities(&priorities);
|
2018-12-07 01:58:12 +11:00
|
|
|
|
2022-03-30 04:15:14 +11:00
|
|
|
let device_create_info = vk::DeviceCreateInfo::default()
|
2021-12-19 22:33:39 +11:00
|
|
|
.queue_create_infos(std::slice::from_ref(&queue_info))
|
2018-12-07 01:58:12 +11:00
|
|
|
.enabled_extension_names(&device_extension_names_raw)
|
2019-03-04 20:16:08 +11:00
|
|
|
.enabled_features(&features);
|
2019-02-03 22:48:05 +11:00
|
|
|
|
2018-11-11 20:41:58 +11:00
|
|
|
let device: Device = instance
|
2017-12-13 00:25:10 +11:00
|
|
|
.create_device(pdevice, &device_create_info, None)
|
2016-12-26 00:38:26 +11:00
|
|
|
.unwrap();
|
2019-02-03 22:48:05 +11:00
|
|
|
|
2022-12-20 05:18:45 +11:00
|
|
|
let present_queue = device.get_device_queue(queue_family_index, 0);
|
2016-12-26 00:38:26 +11:00
|
|
|
|
2020-05-14 17:06:57 +10:00
|
|
|
let surface_format = surface_loader
|
2018-12-05 07:22:03 +11:00
|
|
|
.get_physical_device_surface_formats(pdevice, surface)
|
2020-05-14 17:06:57 +10:00
|
|
|
.unwrap()[0];
|
|
|
|
|
2017-12-13 00:25:10 +11:00
|
|
|
let surface_capabilities = surface_loader
|
2018-12-05 07:22:03 +11:00
|
|
|
.get_physical_device_surface_capabilities(pdevice, surface)
|
2017-12-13 00:25:10 +11:00
|
|
|
.unwrap();
|
2017-01-06 18:47:39 +11:00
|
|
|
let mut desired_image_count = surface_capabilities.min_image_count + 1;
|
2017-12-13 00:25:10 +11:00
|
|
|
if surface_capabilities.max_image_count > 0
|
|
|
|
&& desired_image_count > surface_capabilities.max_image_count
|
|
|
|
{
|
2017-01-06 18:47:39 +11:00
|
|
|
desired_image_count = surface_capabilities.max_image_count;
|
|
|
|
}
|
2016-12-26 00:38:26 +11:00
|
|
|
let surface_resolution = match surface_capabilities.current_extent.width {
|
2017-12-13 00:25:10 +11:00
|
|
|
std::u32::MAX => vk::Extent2D {
|
|
|
|
width: window_width,
|
|
|
|
height: window_height,
|
|
|
|
},
|
2016-12-26 00:38:26 +11:00
|
|
|
_ => surface_capabilities.current_extent,
|
|
|
|
};
|
2017-12-13 00:25:10 +11:00
|
|
|
let pre_transform = if surface_capabilities
|
|
|
|
.supported_transforms
|
2018-09-17 04:59:55 +10:00
|
|
|
.contains(vk::SurfaceTransformFlagsKHR::IDENTITY)
|
2017-12-13 00:25:10 +11:00
|
|
|
{
|
2018-08-01 16:51:50 +10:00
|
|
|
vk::SurfaceTransformFlagsKHR::IDENTITY
|
2016-12-26 00:38:26 +11:00
|
|
|
} else {
|
|
|
|
surface_capabilities.current_transform
|
|
|
|
};
|
2017-12-13 00:25:10 +11:00
|
|
|
let present_modes = surface_loader
|
2018-12-05 07:22:03 +11:00
|
|
|
.get_physical_device_surface_present_modes(pdevice, surface)
|
2017-12-13 00:25:10 +11:00
|
|
|
.unwrap();
|
|
|
|
let present_mode = present_modes
|
|
|
|
.iter()
|
2016-12-26 00:38:26 +11:00
|
|
|
.cloned()
|
2018-08-01 16:51:50 +10:00
|
|
|
.find(|&mode| mode == vk::PresentModeKHR::MAILBOX)
|
|
|
|
.unwrap_or(vk::PresentModeKHR::FIFO);
|
2018-11-18 05:05:28 +11:00
|
|
|
let swapchain_loader = Swapchain::new(&instance, &device);
|
2018-12-07 01:58:12 +11:00
|
|
|
|
2022-03-30 04:15:14 +11:00
|
|
|
let swapchain_create_info = vk::SwapchainCreateInfoKHR::default()
|
2018-12-07 01:58:12 +11:00
|
|
|
.surface(surface)
|
2018-12-08 04:47:57 +11:00
|
|
|
.min_image_count(desired_image_count)
|
|
|
|
.image_color_space(surface_format.color_space)
|
|
|
|
.image_format(surface_format.format)
|
2019-10-21 02:18:40 +11:00
|
|
|
.image_extent(surface_resolution)
|
2018-12-08 04:47:57 +11:00
|
|
|
.image_usage(vk::ImageUsageFlags::COLOR_ATTACHMENT)
|
2018-12-07 14:53:53 +11:00
|
|
|
.image_sharing_mode(vk::SharingMode::EXCLUSIVE)
|
2018-12-08 04:47:57 +11:00
|
|
|
.pre_transform(pre_transform)
|
|
|
|
.composite_alpha(vk::CompositeAlphaFlagsKHR::OPAQUE)
|
|
|
|
.present_mode(present_mode)
|
2018-12-07 14:53:53 +11:00
|
|
|
.clipped(true)
|
2018-12-08 04:47:57 +11:00
|
|
|
.image_array_layers(1);
|
2018-12-07 14:53:53 +11:00
|
|
|
|
2017-12-13 00:25:10 +11:00
|
|
|
let swapchain = swapchain_loader
|
2018-12-05 07:22:03 +11:00
|
|
|
.create_swapchain(&swapchain_create_info, None)
|
2016-12-29 16:02:37 +11:00
|
|
|
.unwrap();
|
2018-12-07 01:58:12 +11:00
|
|
|
|
2022-03-30 04:15:14 +11:00
|
|
|
let pool_create_info = vk::CommandPoolCreateInfo::default()
|
2018-12-07 01:58:12 +11:00
|
|
|
.flags(vk::CommandPoolCreateFlags::RESET_COMMAND_BUFFER)
|
2018-12-07 14:53:53 +11:00
|
|
|
.queue_family_index(queue_family_index);
|
2018-12-07 01:58:12 +11:00
|
|
|
|
2016-12-28 19:24:24 +11:00
|
|
|
let pool = device.create_command_pool(&pool_create_info, None).unwrap();
|
2018-12-07 01:58:12 +11:00
|
|
|
|
2022-03-30 04:15:14 +11:00
|
|
|
let command_buffer_allocate_info = vk::CommandBufferAllocateInfo::default()
|
2018-12-07 01:58:12 +11:00
|
|
|
.command_buffer_count(2)
|
|
|
|
.command_pool(pool)
|
2018-12-07 14:53:53 +11:00
|
|
|
.level(vk::CommandBufferLevel::PRIMARY);
|
2018-12-07 01:58:12 +11:00
|
|
|
|
2017-12-13 00:25:10 +11:00
|
|
|
let command_buffers = device
|
|
|
|
.allocate_command_buffers(&command_buffer_allocate_info)
|
2016-12-26 00:38:26 +11:00
|
|
|
.unwrap();
|
|
|
|
let setup_command_buffer = command_buffers[0];
|
|
|
|
let draw_command_buffer = command_buffers[1];
|
|
|
|
|
2018-12-05 07:22:03 +11:00
|
|
|
let present_images = swapchain_loader.get_swapchain_images(swapchain).unwrap();
|
2017-12-13 00:25:10 +11:00
|
|
|
let present_image_views: Vec<vk::ImageView> = present_images
|
|
|
|
.iter()
|
2016-12-26 00:38:26 +11:00
|
|
|
.map(|&image| {
|
2022-03-30 04:15:14 +11:00
|
|
|
let create_view_info = vk::ImageViewCreateInfo::default()
|
2018-12-08 04:47:57 +11:00
|
|
|
.view_type(vk::ImageViewType::TYPE_2D)
|
2018-12-07 01:58:12 +11:00
|
|
|
.format(surface_format.format)
|
2018-12-08 04:47:57 +11:00
|
|
|
.components(vk::ComponentMapping {
|
2018-12-07 14:53:53 +11:00
|
|
|
r: vk::ComponentSwizzle::R,
|
|
|
|
g: vk::ComponentSwizzle::G,
|
|
|
|
b: vk::ComponentSwizzle::B,
|
|
|
|
a: vk::ComponentSwizzle::A,
|
|
|
|
})
|
2018-12-08 04:47:57 +11:00
|
|
|
.subresource_range(vk::ImageSubresourceRange {
|
2018-12-07 14:53:53 +11:00
|
|
|
aspect_mask: vk::ImageAspectFlags::COLOR,
|
|
|
|
base_mip_level: 0,
|
|
|
|
level_count: 1,
|
|
|
|
base_array_layer: 0,
|
|
|
|
layer_count: 1,
|
|
|
|
})
|
2018-12-08 04:47:57 +11:00
|
|
|
.image(image);
|
2016-12-28 19:24:24 +11:00
|
|
|
device.create_image_view(&create_view_info, None).unwrap()
|
2018-12-08 04:47:57 +11:00
|
|
|
})
|
|
|
|
.collect();
|
2016-12-26 00:38:26 +11:00
|
|
|
let device_memory_properties = instance.get_physical_device_memory_properties(pdevice);
|
2022-03-30 04:15:14 +11:00
|
|
|
let depth_image_create_info = vk::ImageCreateInfo::default()
|
2018-12-08 04:47:57 +11:00
|
|
|
.image_type(vk::ImageType::TYPE_2D)
|
|
|
|
.format(vk::Format::D16_UNORM)
|
2022-01-23 02:29:45 +11:00
|
|
|
.extent(surface_resolution.into())
|
2018-12-08 04:47:57 +11:00
|
|
|
.mip_levels(1)
|
|
|
|
.array_layers(1)
|
|
|
|
.samples(vk::SampleCountFlags::TYPE_1)
|
|
|
|
.tiling(vk::ImageTiling::OPTIMAL)
|
2018-12-07 01:58:12 +11:00
|
|
|
.usage(vk::ImageUsageFlags::DEPTH_STENCIL_ATTACHMENT)
|
2018-12-08 04:47:57 +11:00
|
|
|
.sharing_mode(vk::SharingMode::EXCLUSIVE);
|
2018-12-07 01:58:12 +11:00
|
|
|
|
2016-12-28 19:24:24 +11:00
|
|
|
let depth_image = device.create_image(&depth_image_create_info, None).unwrap();
|
2016-12-26 00:38:26 +11:00
|
|
|
let depth_image_memory_req = device.get_image_memory_requirements(depth_image);
|
2018-08-03 05:22:46 +10:00
|
|
|
let depth_image_memory_index = find_memorytype_index(
|
|
|
|
&depth_image_memory_req,
|
|
|
|
&device_memory_properties,
|
|
|
|
vk::MemoryPropertyFlags::DEVICE_LOCAL,
|
2018-12-08 04:47:57 +11:00
|
|
|
)
|
|
|
|
.expect("Unable to find suitable memory index for depth image.");
|
2016-12-26 00:38:26 +11:00
|
|
|
|
2022-03-30 04:15:14 +11:00
|
|
|
let depth_image_allocate_info = vk::MemoryAllocateInfo::default()
|
2018-12-07 01:58:12 +11:00
|
|
|
.allocation_size(depth_image_memory_req.size)
|
2018-12-10 06:35:48 +11:00
|
|
|
.memory_type_index(depth_image_memory_index);
|
2018-12-07 01:58:12 +11:00
|
|
|
|
2017-12-13 00:25:10 +11:00
|
|
|
let depth_image_memory = device
|
|
|
|
.allocate_memory(&depth_image_allocate_info, None)
|
2016-12-28 19:24:24 +11:00
|
|
|
.unwrap();
|
2018-12-07 01:58:12 +11:00
|
|
|
|
2017-12-13 00:25:10 +11:00
|
|
|
device
|
|
|
|
.bind_image_memory(depth_image, depth_image_memory, 0)
|
2016-12-26 00:38:26 +11:00
|
|
|
.expect("Unable to bind depth image memory");
|
2018-12-07 01:58:12 +11:00
|
|
|
|
2020-10-03 08:08:42 +10:00
|
|
|
let fence_create_info =
|
2022-03-30 04:15:14 +11:00
|
|
|
vk::FenceCreateInfo::default().flags(vk::FenceCreateFlags::SIGNALED);
|
2020-10-03 08:08:42 +10:00
|
|
|
|
|
|
|
let draw_commands_reuse_fence = device
|
|
|
|
.create_fence(&fence_create_info, None)
|
|
|
|
.expect("Create fence failed.");
|
|
|
|
let setup_commands_reuse_fence = device
|
|
|
|
.create_fence(&fence_create_info, None)
|
|
|
|
.expect("Create fence failed.");
|
|
|
|
|
2017-12-13 00:25:10 +11:00
|
|
|
record_submit_commandbuffer(
|
|
|
|
&device,
|
|
|
|
setup_command_buffer,
|
2020-10-03 08:08:42 +10:00
|
|
|
setup_commands_reuse_fence,
|
2017-12-13 00:25:10 +11:00
|
|
|
present_queue,
|
2018-12-07 01:58:12 +11:00
|
|
|
&[],
|
2017-12-13 00:25:10 +11:00
|
|
|
&[],
|
|
|
|
&[],
|
|
|
|
|device, setup_command_buffer| {
|
2022-03-30 04:15:14 +11:00
|
|
|
let layout_transition_barriers = vk::ImageMemoryBarrier::default()
|
2018-12-10 06:41:23 +11:00
|
|
|
.image(depth_image)
|
|
|
|
.dst_access_mask(
|
|
|
|
vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_READ
|
|
|
|
| vk::AccessFlags::DEPTH_STENCIL_ATTACHMENT_WRITE,
|
|
|
|
)
|
|
|
|
.new_layout(vk::ImageLayout::DEPTH_STENCIL_ATTACHMENT_OPTIMAL)
|
|
|
|
.old_layout(vk::ImageLayout::UNDEFINED)
|
|
|
|
.subresource_range(
|
2022-03-30 04:15:14 +11:00
|
|
|
vk::ImageSubresourceRange::default()
|
2018-12-10 06:41:23 +11:00
|
|
|
.aspect_mask(vk::ImageAspectFlags::DEPTH)
|
|
|
|
.layer_count(1)
|
2022-03-30 04:15:14 +11:00
|
|
|
.level_count(1),
|
2018-12-10 07:33:21 +11:00
|
|
|
);
|
2018-12-07 01:58:12 +11:00
|
|
|
|
2017-12-13 00:25:10 +11:00
|
|
|
device.cmd_pipeline_barrier(
|
|
|
|
setup_command_buffer,
|
2018-07-31 20:45:29 +10:00
|
|
|
vk::PipelineStageFlags::BOTTOM_OF_PIPE,
|
|
|
|
vk::PipelineStageFlags::LATE_FRAGMENT_TESTS,
|
2017-12-13 00:25:10 +11:00
|
|
|
vk::DependencyFlags::empty(),
|
|
|
|
&[],
|
|
|
|
&[],
|
2022-03-30 04:15:14 +11:00
|
|
|
&[layout_transition_barriers],
|
2017-12-13 00:25:10 +11:00
|
|
|
);
|
|
|
|
},
|
|
|
|
);
|
2018-12-07 01:58:12 +11:00
|
|
|
|
2022-03-30 04:15:14 +11:00
|
|
|
let depth_image_view_info = vk::ImageViewCreateInfo::default()
|
2018-12-07 01:58:12 +11:00
|
|
|
.subresource_range(
|
2022-03-30 04:15:14 +11:00
|
|
|
vk::ImageSubresourceRange::default()
|
2018-12-07 01:58:12 +11:00
|
|
|
.aspect_mask(vk::ImageAspectFlags::DEPTH)
|
|
|
|
.level_count(1)
|
2022-03-30 04:15:14 +11:00
|
|
|
.layer_count(1),
|
2018-12-10 01:01:13 +11:00
|
|
|
)
|
|
|
|
.image(depth_image)
|
2018-12-07 01:58:12 +11:00
|
|
|
.format(depth_image_create_info.format)
|
2018-12-10 06:35:48 +11:00
|
|
|
.view_type(vk::ImageViewType::TYPE_2D);
|
2018-12-07 01:58:12 +11:00
|
|
|
|
2017-12-13 00:25:10 +11:00
|
|
|
let depth_image_view = device
|
|
|
|
.create_image_view(&depth_image_view_info, None)
|
|
|
|
.unwrap();
|
2018-12-07 01:58:12 +11:00
|
|
|
|
|
|
|
let semaphore_create_info = vk::SemaphoreCreateInfo::default();
|
|
|
|
|
2017-12-13 00:25:10 +11:00
|
|
|
let present_complete_semaphore = device
|
|
|
|
.create_semaphore(&semaphore_create_info, None)
|
2016-12-26 00:38:26 +11:00
|
|
|
.unwrap();
|
2017-12-13 00:25:10 +11:00
|
|
|
let rendering_complete_semaphore = device
|
|
|
|
.create_semaphore(&semaphore_create_info, None)
|
2016-12-26 00:38:26 +11:00
|
|
|
.unwrap();
|
2020-10-03 08:08:42 +10:00
|
|
|
|
2016-12-26 00:38:26 +11:00
|
|
|
ExampleBase {
|
2021-12-21 10:45:18 +11:00
|
|
|
event_loop: RefCell::new(event_loop),
|
2019-10-21 02:18:40 +11:00
|
|
|
entry,
|
|
|
|
instance,
|
|
|
|
device,
|
|
|
|
queue_family_index,
|
|
|
|
pdevice,
|
|
|
|
device_memory_properties,
|
|
|
|
window,
|
|
|
|
surface_loader,
|
|
|
|
surface_format,
|
|
|
|
present_queue,
|
|
|
|
surface_resolution,
|
|
|
|
swapchain_loader,
|
|
|
|
swapchain,
|
|
|
|
present_images,
|
|
|
|
present_image_views,
|
|
|
|
pool,
|
|
|
|
draw_command_buffer,
|
|
|
|
setup_command_buffer,
|
|
|
|
depth_image,
|
|
|
|
depth_image_view,
|
|
|
|
present_complete_semaphore,
|
|
|
|
rendering_complete_semaphore,
|
2020-10-03 08:08:42 +10:00
|
|
|
draw_commands_reuse_fence,
|
|
|
|
setup_commands_reuse_fence,
|
2019-10-21 02:18:40 +11:00
|
|
|
surface,
|
|
|
|
debug_call_back,
|
2020-04-29 17:28:59 +10:00
|
|
|
debug_utils_loader,
|
2019-10-21 02:18:40 +11:00
|
|
|
depth_image_memory,
|
2016-12-26 00:38:26 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2017-01-01 18:09:51 +11:00
|
|
|
|
2016-12-26 00:38:26 +11:00
|
|
|
impl Drop for ExampleBase {
|
|
|
|
fn drop(&mut self) {
|
|
|
|
unsafe {
|
|
|
|
self.device.device_wait_idle().unwrap();
|
2017-12-13 00:25:10 +11:00
|
|
|
self.device
|
|
|
|
.destroy_semaphore(self.present_complete_semaphore, None);
|
|
|
|
self.device
|
|
|
|
.destroy_semaphore(self.rendering_complete_semaphore, None);
|
2020-10-03 08:08:42 +10:00
|
|
|
self.device
|
|
|
|
.destroy_fence(self.draw_commands_reuse_fence, None);
|
|
|
|
self.device
|
|
|
|
.destroy_fence(self.setup_commands_reuse_fence, None);
|
2016-12-29 16:02:37 +11:00
|
|
|
self.device.free_memory(self.depth_image_memory, None);
|
2016-12-28 19:24:24 +11:00
|
|
|
self.device.destroy_image_view(self.depth_image_view, None);
|
|
|
|
self.device.destroy_image(self.depth_image, None);
|
2016-12-26 00:38:26 +11:00
|
|
|
for &image_view in self.present_image_views.iter() {
|
2016-12-28 19:24:24 +11:00
|
|
|
self.device.destroy_image_view(image_view, None);
|
2016-12-26 00:38:26 +11:00
|
|
|
}
|
2016-12-28 19:24:24 +11:00
|
|
|
self.device.destroy_command_pool(self.pool, None);
|
2017-12-13 00:25:10 +11:00
|
|
|
self.swapchain_loader
|
2018-12-05 07:22:03 +11:00
|
|
|
.destroy_swapchain(self.swapchain, None);
|
2016-12-28 19:24:24 +11:00
|
|
|
self.device.destroy_device(None);
|
2018-12-05 07:22:03 +11:00
|
|
|
self.surface_loader.destroy_surface(self.surface, None);
|
2020-04-29 17:28:59 +10:00
|
|
|
self.debug_utils_loader
|
|
|
|
.destroy_debug_utils_messenger(self.debug_call_back, None);
|
2016-12-28 21:04:50 +11:00
|
|
|
self.instance.destroy_instance(None);
|
2016-12-26 00:38:26 +11:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|