librashader/librashader-runtime-vk/tests/hello_triangle/swapchain.rs
2023-02-16 00:39:36 -05:00

229 lines
8.8 KiB
Rust

use crate::hello_triangle::surface::VulkanSurface;
use crate::hello_triangle::vulkan_base::VulkanBase;
use crate::hello_triangle::memory::VulkanImageMemory;
use ash::prelude::VkResult;
use ash::vk;
use ash::vk::Extent3D;
use std::sync::Arc;
pub struct VulkanSwapchain {
pub swapchain: vk::SwapchainKHR,
pub loader: ash::extensions::khr::Swapchain,
pub format: vk::SurfaceFormatKHR,
pub extent: vk::Extent2D,
pub mode: vk::PresentModeKHR,
pub swapchain_images: Vec<vk::Image>,
pub swapchain_image_views: Vec<vk::ImageView>,
pub render_images: Vec<(vk::Image, VulkanImageMemory)>,
pub render_image_views: Vec<vk::ImageView>,
device: Arc<ash::Device>,
}
impl VulkanSwapchain {
pub fn new(
base: &VulkanBase,
surface: &VulkanSurface,
width: u32,
height: u32,
) -> VkResult<VulkanSwapchain> {
let format = surface.choose_format(base)?;
let mode = surface.choose_present_mode(base)?;
let extent = surface.choose_swapchain_extent(base, width, height)?;
let capabilities = surface.get_capabilities(base)?;
let image_count = capabilities.min_image_count + 1;
let image_count = if capabilities.max_image_count > 0 {
image_count.min(capabilities.max_image_count)
} else {
image_count
};
if base.graphics_queue != surface.present_queue {
panic!("exclusive mode only")
}
let create_info = vk::SwapchainCreateInfoKHR::builder()
.surface(surface.surface)
.present_mode(mode)
.min_image_count(image_count)
.image_color_space(format.color_space)
.image_format(format.format)
.image_extent(extent)
.image_sharing_mode(vk::SharingMode::EXCLUSIVE)
.pre_transform(capabilities.current_transform)
.composite_alpha(vk::CompositeAlphaFlagsKHR::OPAQUE)
.clipped(true)
.image_array_layers(1)
// todo: switch to IMAGE_USAGE_TRANSFER_DST
.image_usage(vk::ImageUsageFlags::COLOR_ATTACHMENT)
;
let loader = ash::extensions::khr::Swapchain::new(&base.instance, &base.device);
let swapchain = unsafe { loader.create_swapchain(&create_info, None)? };
let swapchain_images = unsafe { loader.get_swapchain_images(swapchain)? };
let mut render_images = vec![];
// create render imaghes
for _ in 0..swapchain_images.len() {
let create_info = vk::ImageCreateInfo::builder()
.extent(Extent3D {
width,
height,
depth: 1,
})
.format(format.format)
.image_type(vk::ImageType::TYPE_2D)
.sharing_mode(vk::SharingMode::EXCLUSIVE)
.samples(vk::SampleCountFlags::TYPE_1)
.tiling(vk::ImageTiling::OPTIMAL)
.array_layers(1)
.mip_levels(1)
.usage(
vk::ImageUsageFlags::SAMPLED
| vk::ImageUsageFlags::COLOR_ATTACHMENT
| vk::ImageUsageFlags::TRANSFER_SRC,
)
.initial_layout(vk::ImageLayout::UNDEFINED);
unsafe {
let image = base.device.create_image(&create_info, None)?;
let mem_reqs = base.device.get_image_memory_requirements(image);
let memory =
VulkanImageMemory::new(&base.device, &base.allocator, mem_reqs, &image)
.unwrap();
render_images.push((image, memory))
}
}
let swapchain_image_views: VkResult<Vec<vk::ImageView>> = swapchain_images
.iter()
.map(|image| {
let create_info = vk::ImageViewCreateInfo::builder()
.view_type(vk::ImageViewType::TYPE_2D)
.format(format.format)
.components(vk::ComponentMapping {
r: vk::ComponentSwizzle::IDENTITY,
g: vk::ComponentSwizzle::IDENTITY,
b: vk::ComponentSwizzle::IDENTITY,
a: vk::ComponentSwizzle::IDENTITY,
})
.subresource_range(vk::ImageSubresourceRange {
aspect_mask: vk::ImageAspectFlags::COLOR,
base_mip_level: 0,
level_count: 1,
base_array_layer: 0,
layer_count: 1,
})
.image(*image)
;
let view = unsafe { base.device.create_image_view(&create_info, None)? };
// unsafe {
// base.debug
// .loader
// .set_debug_utils_object_name(
// base.device.handle(),
// &vk::DebugUtilsObjectNameInfoEXT::builder()
// .object_handle(image.as_raw())
// .object_name(CStr::from_bytes_with_nul_unchecked(
// b"SwapchainImage\0",
// ))
// .object_type(vk::ObjectType::IMAGE)
// ,
// )
// .expect("could not set object name");
// base.debug
// .loader
// .set_debug_utils_object_name(
// base.device.handle(),
// &vk::DebugUtilsObjectNameInfoEXT::builder()
// .object_handle(view.as_raw())
// .object_name(CStr::from_bytes_with_nul_unchecked(
// b"SwapchainImageView\0",
// ))
// .object_type(vk::ObjectType::IMAGE_VIEW)
// ,
// )
// .expect("could not set object name");
// }
Ok(view)
})
.collect();
let render_image_views: VkResult<Vec<vk::ImageView>> = render_images
.iter()
.map(|(image, _)| {
let create_info = vk::ImageViewCreateInfo::builder()
.view_type(vk::ImageViewType::TYPE_2D)
.format(format.format)
.components(vk::ComponentMapping {
r: vk::ComponentSwizzle::IDENTITY,
g: vk::ComponentSwizzle::IDENTITY,
b: vk::ComponentSwizzle::IDENTITY,
a: vk::ComponentSwizzle::IDENTITY,
})
.subresource_range(vk::ImageSubresourceRange {
aspect_mask: vk::ImageAspectFlags::COLOR,
base_mip_level: 0,
level_count: 1,
base_array_layer: 0,
layer_count: 1,
})
.image(*image)
;
let view = unsafe { base.device.create_image_view(&create_info, None)? };
// unsafe {
// base.debug
// .loader
// .set_debug_utils_object_name(
// base.device.handle(),
// &vk::DebugUtilsObjectNameInfoEXT::builder()
// .object_handle(view.as_raw())
// .object_name(CStr::from_bytes_with_nul_unchecked(
// b"RenderImageView\0",
// ))
// .object_type(vk::ObjectType::IMAGE_VIEW)
// ,
// )
// .expect("could not set object name");
// }
Ok(view)
})
.collect();
Ok(VulkanSwapchain {
swapchain,
loader,
format,
extent,
mode,
swapchain_images,
render_images,
swapchain_image_views: swapchain_image_views?,
render_image_views: render_image_views?,
device: base.device.clone(),
})
}
}
impl Drop for VulkanSwapchain {
fn drop(&mut self) {
unsafe {
for view in &self.render_image_views {
self.device.destroy_image_view(*view, None)
}
for (view, _memory) in &self.render_images {
self.device.destroy_image(*view, None);
}
self.loader.destroy_swapchain(self.swapchain, None)
}
}
}