0adf3505ec
This doesn't cause an API break in the C API but we don't actually make an attempt to verify that it's safe to access any of the device contexts.
226 lines
8.8 KiB
Rust
226 lines
8.8 KiB
Rust
use crate::hello_triangle::memory::VulkanImageMemory;
|
|
use crate::hello_triangle::surface::VulkanSurface;
|
|
use crate::hello_triangle::vulkan_base::VulkanBase;
|
|
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)
|
|
}
|
|
}
|
|
}
|