vk: hello triangle swapchain

This commit is contained in:
chyyran 2023-01-04 00:49:42 -05:00
parent f08098680a
commit 1d07c66239
6 changed files with 228 additions and 4 deletions

47
Cargo.lock generated
View file

@ -888,6 +888,7 @@ dependencies = [
"librashader-presets", "librashader-presets",
"librashader-reflect", "librashader-reflect",
"librashader-runtime", "librashader-runtime",
"num",
"raw-window-handle 0.5.0", "raw-window-handle 0.5.0",
"rustc-hash", "rustc-hash",
"spirv_cross", "spirv_cross",
@ -1114,6 +1115,40 @@ dependencies = [
"nom", "nom",
] ]
[[package]]
name = "num"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43db66d1170d347f9a065114077f7dccb00c1b9478c89384490a3425279a4606"
dependencies = [
"num-bigint",
"num-complex",
"num-integer",
"num-iter",
"num-rational",
"num-traits",
]
[[package]]
name = "num-bigint"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]]
name = "num-complex"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ae39348c8bc5fbd7f40c727a9925f03517afd2ab27d46702108b6a7e5414c19"
dependencies = [
"num-traits",
]
[[package]] [[package]]
name = "num-integer" name = "num-integer"
version = "0.1.45" version = "0.1.45"
@ -1124,6 +1159,17 @@ dependencies = [
"num-traits", "num-traits",
] ]
[[package]]
name = "num-iter"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d03e6c028c5dc5cac6e2dec0efda81fc887605bb3d884578bb6d6bf7514e252"
dependencies = [
"autocfg",
"num-integer",
"num-traits",
]
[[package]] [[package]]
name = "num-rational" name = "num-rational"
version = "0.4.1" version = "0.4.1"
@ -1131,6 +1177,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0" checksum = "0638a1c9d0a3c0914158145bc76cff373a75a627e6ecbfb71cbe6f453a5a19b0"
dependencies = [ dependencies = [
"autocfg", "autocfg",
"num-bigint",
"num-integer", "num-integer",
"num-traits", "num-traits",
] ]

View file

@ -25,6 +25,7 @@ bytemuck = "1.12.3"
thiserror = "1.0.37" thiserror = "1.0.37"
ash = { version = "0.37.1+1.3.235", features = ["linked", "debug"] } ash = { version = "0.37.1+1.3.235", features = ["linked", "debug"] }
num = "0.4.0"
glfw = "0.47.0" glfw = "0.47.0"
winit = "0.27.5" winit = "0.27.5"
raw-window-handle = "0.5" raw-window-handle = "0.5"

View file

@ -2,12 +2,14 @@ pub mod vulkan_base;
mod debug; mod debug;
mod physicaldevice; mod physicaldevice;
mod surface; mod surface;
mod swapchain;
use winit::event::{Event, VirtualKeyCode, ElementState, KeyboardInput, WindowEvent}; use winit::event::{Event, VirtualKeyCode, ElementState, KeyboardInput, WindowEvent};
use winit::event_loop::{EventLoop, ControlFlow, EventLoopBuilder}; use winit::event_loop::{EventLoop, ControlFlow, EventLoopBuilder};
use winit::platform::windows::EventLoopBuilderExtWindows; use winit::platform::windows::EventLoopBuilderExtWindows;
use crate::filter_chain::FilterChainVulkan; use crate::filter_chain::{FilterChainVulkan, Vulkan};
use crate::hello_triangle::surface::VulkanSurface; use crate::hello_triangle::surface::VulkanSurface;
use crate::hello_triangle::swapchain::VulkanSwapchain;
use crate::hello_triangle::vulkan_base::VulkanBase; use crate::hello_triangle::vulkan_base::VulkanBase;
// Constants // Constants
@ -60,6 +62,7 @@ impl VulkanWindow {
pub struct VulkanDraw { pub struct VulkanDraw {
surface: VulkanSurface, surface: VulkanSurface,
base: VulkanBase, base: VulkanBase,
pub swapchain: VulkanSwapchain,
} }
pub fn main(vulkan: VulkanBase, filter_chain: FilterChainVulkan) { pub fn main(vulkan: VulkanBase, filter_chain: FilterChainVulkan) {
@ -72,8 +75,12 @@ pub fn main(vulkan: VulkanBase, filter_chain: FilterChainVulkan) {
let surface = VulkanSurface::new(&vulkan, &window) let surface = VulkanSurface::new(&vulkan, &window)
.unwrap(); .unwrap();
let swapchain = VulkanSwapchain::new(&vulkan, &surface, WINDOW_WIDTH, WINDOW_HEIGHT)
.unwrap();
let vulkan = VulkanDraw { let vulkan = VulkanDraw {
surface, surface,
swapchain,
base: vulkan base: vulkan
}; };

View file

@ -5,8 +5,8 @@ use crate::hello_triangle::vulkan_base::VulkanBase;
pub struct VulkanSurface { pub struct VulkanSurface {
surface_loader: ash::extensions::khr::Surface, surface_loader: ash::extensions::khr::Surface,
surface: vk::SurfaceKHR, pub surface: vk::SurfaceKHR,
present_queue: vk::Queue pub present_queue: vk::Queue
} }
impl VulkanSurface { impl VulkanSurface {
@ -56,5 +56,67 @@ impl VulkanSurface {
present_queue present_queue
}) })
} }
pub fn choose_format(&self, base: &VulkanBase) -> VkResult<vk::SurfaceFormatKHR> {
unsafe {
let available_formats = self.surface_loader.get_physical_device_surface_formats(base.physical_device, self.surface)?;
for available_format in available_formats.iter() {
if available_format.format == vk::Format::B8G8R8A8_SRGB
&& available_format.color_space == vk::ColorSpaceKHR::SRGB_NONLINEAR
{
return Ok(available_format.clone());
}
} }
return Ok(available_formats.first().unwrap().clone());
}
}
pub fn choose_present_mode(&self, base: &VulkanBase) -> VkResult<vk::PresentModeKHR> {
unsafe {
let available_formats = self.surface_loader.get_physical_device_surface_present_modes(base.physical_device, self.surface)?;
Ok(if available_formats.contains(&vk::PresentModeKHR::MAILBOX) {
vk::PresentModeKHR::MAILBOX
} else {
vk::PresentModeKHR::FIFO
})
}
}
pub fn choose_swapchain_extent(&self, base: &VulkanBase, width: u32, height: u32) -> VkResult<vk::Extent2D> {
let capabilities = self.get_capabilities(base)?;
if capabilities.current_extent.width != u32::MAX {
Ok(capabilities.current_extent)
} else {
use num::clamp;
Ok(vk::Extent2D {
width: clamp(
width,
capabilities.min_image_extent.width,
capabilities.max_image_extent.width,
),
height: clamp(
height,
capabilities.min_image_extent.height,
capabilities.max_image_extent.height,
),
})
}
}
pub fn get_capabilities(&self, base: &VulkanBase) -> VkResult<vk::SurfaceCapabilitiesKHR> {
unsafe {
self.surface_loader.get_physical_device_surface_capabilities(base.physical_device, self.surface)
}
}
}
impl Drop for VulkanSurface {
fn drop(&mut self) {
unsafe {
self.surface_loader.destroy_surface(self.surface, None);
}
}
}

View file

@ -0,0 +1,108 @@
use ash::prelude::VkResult;
use ash::vk;
use crate::hello_triangle::surface::VulkanSurface;
use crate::hello_triangle::vulkan_base::VulkanBase;
pub struct VulkanSwapchain {
pub swapchain: vk::SwapchainKHR,
pub loader: ash::extensions::khr::Swapchain,
format: vk::SurfaceFormatKHR,
extent: vk::Extent2D,
mode: vk::PresentModeKHR,
images: Vec<vk::Image>,
image_views: Vec<vk::ImageView>,
device: 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)
.build();
let loader = ash::extensions::khr::Swapchain::new(&base.instance, &base.device);
let swapchain = unsafe {
loader.create_swapchain(&create_info, None)?
};
let images = unsafe { loader.get_swapchain_images(swapchain)? };
let image_views: VkResult<Vec<vk::ImageView>> = 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)
.build();
let view = unsafe {
base.device.create_image_view(&create_info, None)?
};
Ok(view)
}).collect();
Ok(VulkanSwapchain {
swapchain,
loader,
format,
extent,
mode,
images,
image_views: image_views?,
device: base.device.clone()
})
}
}
impl Drop for VulkanSwapchain {
fn drop(&mut self) {
unsafe {
for view in &self.image_views {
self.device.destroy_image_view(*view, None)
}
self.loader.destroy_swapchain(self.swapchain, None)
}
}
}

View file

@ -151,7 +151,6 @@ impl Drop for VulkanBase {
fn drop(&mut self) { fn drop(&mut self) {
unsafe { unsafe {
self.device.destroy_device(None); self.device.destroy_device(None);
self.instance.destroy_instance(None);
} }
} }
} }