ash/examples/src/lib.rs

594 lines
23 KiB
Rust
Raw Normal View History

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::{
ext::DebugUtils,
2018-12-05 07:22:03 +11:00
khr::{Surface, Swapchain},
};
use ash::{vk, Entry};
pub use ash::{Device, Instance};
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;
2016-12-26 00:38:26 +11:00
use std::ffi::{CStr, CString};
use std::ops::Drop;
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 {
let b: $base = mem::zeroed();
2018-07-31 22:51:45 +10:00
(&b.$field as *const _ as isize) - (&b as *const _ 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
}
/// 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)]
pub fn record_submit_commandbuffer<F: FnOnce(&Device, vk::CommandBuffer)>(
device: &Device,
2017-12-13 00:25:10 +11:00
command_buffer: vk::CommandBuffer,
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 {
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
let command_buffer_begin_info = vk::CommandBufferBeginInfo::builder()
.flags(vk::CommandBufferUsageFlags::ONE_TIME_SUBMIT);
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");
let command_buffers = vec![command_buffer];
2018-12-10 07:33:21 +11:00
let submit_info = vk::SubmitInfo::builder()
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
.queue_submit(
submit_queue,
&[submit_info.build()],
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(
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;
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,
);
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> {
memory_prop.memory_types[..memory_prop.memory_type_count as _]
.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-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,
pub debug_utils_loader: DebugUtils,
2021-11-09 09:25:13 +11:00
pub window: winit::window::Window,
pub event_loop: RefCell<EventLoop<()>>,
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,
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) {
self.event_loop
2021-11-09 09:25:13 +11:00
.borrow_mut()
.run_return(|event, _, control_flow| {
*control_flow = ControlFlow::Wait;
f();
if let Event::WindowEvent {
event:
2021-11-10 05:12:51 +11:00
WindowEvent::CloseRequested
| WindowEvent::KeyboardInput {
input:
KeyboardInput {
state: ElementState::Pressed,
virtual_keycode: Some(VirtualKeyCode::Escape),
..
},
2021-11-09 09:25:13 +11:00
..
},
..
} = event
{
*control_flow = ControlFlow::Exit
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 {
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(
f64::from(window_width),
f64::from(window_height),
2018-12-08 04:47:57 +11:00
))
.build(&event_loop)
2016-12-26 00:38:26 +11:00
.unwrap();
let entry = Entry::new();
2016-12-26 00:38:26 +11:00
let app_name = CString::new("VulkanTriangle").unwrap();
let layer_names = [CString::new("VK_LAYER_KHRONOS_validation").unwrap()];
2017-12-13 00:25:10 +11:00
let layers_names_raw: Vec<*const i8> = layer_names
.iter()
2016-12-26 00:38:26 +11:00
.map(|raw_name| raw_name.as_ptr())
.collect();
2020-09-03 17:07:09 +10:00
let surface_extensions = ash_window::enumerate_required_extensions(&window).unwrap();
let mut extension_names_raw = surface_extensions
.iter()
.map(|ext| ext.as_ptr())
.collect::<Vec<_>>();
extension_names_raw.push(DebugUtils::name().as_ptr());
let appinfo = vk::ApplicationInfo::builder()
2018-12-07 06:18:37 +11:00
.application_name(&app_name)
.application_version(0)
.engine_name(&app_name)
.engine_version(0)
.api_version(vk::make_api_version(0, 1, 0, 0));
let create_info = vk::InstanceCreateInfo::builder()
.application_info(&appinfo)
.enabled_layer_names(&layers_names_raw)
2018-12-10 06:35:48 +11:00
.enabled_extension_names(&extension_names_raw);
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");
let debug_info = vk::DebugUtilsMessengerCreateInfoEXT::builder()
.message_severity(
vk::DebugUtilsMessageSeverityFlagsEXT::ERROR
| vk::DebugUtilsMessageSeverityFlagsEXT::WARNING
| vk::DebugUtilsMessageSeverityFlagsEXT::INFO,
2018-12-08 04:47:57 +11:00
)
.message_type(
vk::DebugUtilsMessageTypeFlagsEXT::GENERAL
| vk::DebugUtilsMessageTypeFlagsEXT::VALIDATION
| vk::DebugUtilsMessageTypeFlagsEXT::PERFORMANCE,
)
.pfn_user_callback(Some(vulkan_debug_callback));
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();
2020-09-03 17:07:09 +10:00
let surface = ash_window::create_surface(&entry, &instance, &window, 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()
2016-12-26 00:38:26 +11:00
.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()
.filter_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();
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
})
2020-03-15 10:55:26 +11:00
.next()
2018-12-08 04:47:57 +11:00
})
.flatten()
2020-03-15 10:55:26 +11:00
.next()
2016-12-26 00:38:26 +11:00
.expect("Couldn't find suitable device.");
let queue_family_index = queue_family_index as u32;
2016-12-28 14:19:03 +11:00
let device_extension_names_raw = [Swapchain::name().as_ptr()];
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];
examples: Use `slice::from_ref` to not loose lifetime on nested slices As per the readme `.build()` should only be called as late as possible, and only if absolutely necessary; such cases include slices that are passed directly to functions. More precisely, such build calls and the creation of temporary slices should happen inside the same expression as the function call to be sound and completely lifetime-checked. This pattern of `&[my_builder.build()]` is however not possible when constructing intermediary Vulkan objects that reference the slice. In the first place this slice goes out of scope after the expression that creates the Vulkan object, which is caught and disallowed by rustc (unless this expression itself ends in `.build()`, which is completely unsound as it makes rustc unable to validate this lifetime dependency). In the second place - and as is most relevant for this patch that removes `.build()` calls that were not surrounded by temporary slice constructors - said expression drops the lifetime checks on anything held by `my_builder` which _could_ go out of scope before the newly constructed Vulkan object is used, resulting yet again in Undefined Behaviour. Fortunately, for slices of size 1 which are typical in Vulkan, `std::slice::as_ref` exists which is analogous to taking a pointer to an object and considering it an array of length 1 in C(++). This maintains the lifetime through `Deref` and makes rustc able to fully check all lifetimes and prevent unsound code. Albeit improving overall consistency, the `&[my_builder.build()]` pattern is not substituted in aforementioned Vulkan function-call expressions as that is considered "extraneous" [1] and demonstrates the various ways to safely construct Vulkan objects for the observant reader. [1]: https://github.com/MaikKlein/ash/pull/506#discussion_r762630648
2021-12-19 22:33:39 +11:00
let queue_info = vk::DeviceQueueCreateInfo::builder()
2018-12-08 04:47:57 +11:00
.queue_family_index(queue_family_index)
examples: Use `slice::from_ref` to not loose lifetime on nested slices As per the readme `.build()` should only be called as late as possible, and only if absolutely necessary; such cases include slices that are passed directly to functions. More precisely, such build calls and the creation of temporary slices should happen inside the same expression as the function call to be sound and completely lifetime-checked. This pattern of `&[my_builder.build()]` is however not possible when constructing intermediary Vulkan objects that reference the slice. In the first place this slice goes out of scope after the expression that creates the Vulkan object, which is caught and disallowed by rustc (unless this expression itself ends in `.build()`, which is completely unsound as it makes rustc unable to validate this lifetime dependency). In the second place - and as is most relevant for this patch that removes `.build()` calls that were not surrounded by temporary slice constructors - said expression drops the lifetime checks on anything held by `my_builder` which _could_ go out of scope before the newly constructed Vulkan object is used, resulting yet again in Undefined Behaviour. Fortunately, for slices of size 1 which are typical in Vulkan, `std::slice::as_ref` exists which is analogous to taking a pointer to an object and considering it an array of length 1 in C(++). This maintains the lifetime through `Deref` and makes rustc able to fully check all lifetimes and prevent unsound code. Albeit improving overall consistency, the `&[my_builder.build()]` pattern is not substituted in aforementioned Vulkan function-call expressions as that is considered "extraneous" [1] and demonstrates the various ways to safely construct Vulkan objects for the observant reader. [1]: https://github.com/MaikKlein/ash/pull/506#discussion_r762630648
2021-12-19 22:33:39 +11:00
.queue_priorities(&priorities);
2019-03-04 20:16:08 +11:00
let device_create_info = vk::DeviceCreateInfo::builder()
examples: Use `slice::from_ref` to not loose lifetime on nested slices As per the readme `.build()` should only be called as late as possible, and only if absolutely necessary; such cases include slices that are passed directly to functions. More precisely, such build calls and the creation of temporary slices should happen inside the same expression as the function call to be sound and completely lifetime-checked. This pattern of `&[my_builder.build()]` is however not possible when constructing intermediary Vulkan objects that reference the slice. In the first place this slice goes out of scope after the expression that creates the Vulkan object, which is caught and disallowed by rustc (unless this expression itself ends in `.build()`, which is completely unsound as it makes rustc unable to validate this lifetime dependency). In the second place - and as is most relevant for this patch that removes `.build()` calls that were not surrounded by temporary slice constructors - said expression drops the lifetime checks on anything held by `my_builder` which _could_ go out of scope before the newly constructed Vulkan object is used, resulting yet again in Undefined Behaviour. Fortunately, for slices of size 1 which are typical in Vulkan, `std::slice::as_ref` exists which is analogous to taking a pointer to an object and considering it an array of length 1 in C(++). This maintains the lifetime through `Deref` and makes rustc able to fully check all lifetimes and prevent unsound code. Albeit improving overall consistency, the `&[my_builder.build()]` pattern is not substituted in aforementioned Vulkan function-call expressions as that is considered "extraneous" [1] and demonstrates the various ways to safely construct Vulkan objects for the observant reader. [1]: https://github.com/MaikKlein/ash/pull/506#discussion_r762630648
2021-12-19 22:33:39 +11:00
.queue_create_infos(std::slice::from_ref(&queue_info))
.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
2016-12-26 00:38:26 +11:00
let present_queue = device.get_device_queue(queue_family_index as u32, 0);
let surface_format = surface_loader
2018-12-05 07:22:03 +11:00
.get_physical_device_surface_formats(pdevice, surface)
.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
.contains(vk::SurfaceTransformFlagsKHR::IDENTITY)
2017-12-13 00:25:10 +11: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()
.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);
let swapchain_create_info = vk::SwapchainCreateInfoKHR::builder()
.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)
.image_extent(surface_resolution)
2018-12-08 04:47:57 +11:00
.image_usage(vk::ImageUsageFlags::COLOR_ATTACHMENT)
.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)
.clipped(true)
2018-12-08 04:47:57 +11:00
.image_array_layers(1);
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)
.unwrap();
let pool_create_info = vk::CommandPoolCreateInfo::builder()
.flags(vk::CommandPoolCreateFlags::RESET_COMMAND_BUFFER)
.queue_family_index(queue_family_index);
2016-12-28 19:24:24 +11:00
let pool = device.create_command_pool(&pool_create_info, None).unwrap();
let command_buffer_allocate_info = vk::CommandBufferAllocateInfo::builder()
.command_buffer_count(2)
.command_pool(pool)
.level(vk::CommandBufferLevel::PRIMARY);
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| {
let create_view_info = vk::ImageViewCreateInfo::builder()
2018-12-08 04:47:57 +11:00
.view_type(vk::ImageViewType::TYPE_2D)
.format(surface_format.format)
2018-12-08 04:47:57 +11:00
.components(vk::ComponentMapping {
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 {
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);
let depth_image_create_info = vk::ImageCreateInfo::builder()
2018-12-08 04:47:57 +11:00
.image_type(vk::ImageType::TYPE_2D)
.format(vk::Format::D16_UNORM)
.extent(vk::Extent3D {
2016-12-26 00:38:26 +11:00
width: surface_resolution.width,
height: surface_resolution.height,
2018-12-07 06:18:37 +11:00
depth: 1,
})
2018-12-08 04:47:57 +11:00
.mip_levels(1)
.array_layers(1)
.samples(vk::SampleCountFlags::TYPE_1)
.tiling(vk::ImageTiling::OPTIMAL)
.usage(vk::ImageUsageFlags::DEPTH_STENCIL_ATTACHMENT)
2018-12-08 04:47:57 +11:00
.sharing_mode(vk::SharingMode::EXCLUSIVE);
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
let depth_image_allocate_info = vk::MemoryAllocateInfo::builder()
.allocation_size(depth_image_memory_req.size)
2018-12-10 06:35:48 +11:00
.memory_type_index(depth_image_memory_index);
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();
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");
let fence_create_info =
vk::FenceCreateInfo::builder().flags(vk::FenceCreateFlags::SIGNALED);
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,
setup_commands_reuse_fence,
2017-12-13 00:25:10 +11:00
present_queue,
&[],
2017-12-13 00:25:10 +11:00
&[],
&[],
|device, setup_command_buffer| {
2018-12-10 07:33:21 +11:00
let layout_transition_barriers = vk::ImageMemoryBarrier::builder()
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(
vk::ImageSubresourceRange::builder()
.aspect_mask(vk::ImageAspectFlags::DEPTH)
.layer_count(1)
.level_count(1)
.build(),
2018-12-10 07:33:21 +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(),
&[],
&[],
2018-12-10 07:33:21 +11:00
&[layout_transition_barriers.build()],
2017-12-13 00:25:10 +11:00
);
},
);
let depth_image_view_info = vk::ImageViewCreateInfo::builder()
.subresource_range(
vk::ImageSubresourceRange::builder()
.aspect_mask(vk::ImageAspectFlags::DEPTH)
.level_count(1)
.layer_count(1)
2018-12-07 06:18:37 +11:00
.build(),
2018-12-10 01:01:13 +11:00
)
.image(depth_image)
.format(depth_image_create_info.format)
2018-12-10 06:35:48 +11:00
.view_type(vk::ImageViewType::TYPE_2D);
2017-12-13 00:25:10 +11:00
let depth_image_view = device
.create_image_view(&depth_image_view_info, None)
.unwrap();
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();
2016-12-26 00:38:26 +11:00
ExampleBase {
event_loop: RefCell::new(event_loop),
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,
draw_commands_reuse_fence,
setup_commands_reuse_fence,
surface,
debug_call_back,
debug_utils_loader,
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);
self.device
.destroy_fence(self.draw_commands_reuse_fence, None);
self.device
.destroy_fence(self.setup_commands_reuse_fence, None);
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);
self.debug_utils_loader
.destroy_debug_utils_messenger(self.debug_call_back, None);
self.instance.destroy_instance(None);
2016-12-26 00:38:26 +11:00
}
}
}