vk: hello triangle swapchain
This commit is contained in:
parent
f08098680a
commit
1d07c66239
47
Cargo.lock
generated
47
Cargo.lock
generated
|
@ -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",
|
||||||
]
|
]
|
||||||
|
|
|
@ -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"
|
||||||
|
|
|
@ -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
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
108
librashader-runtime-vk/src/hello_triangle/swapchain.rs
Normal file
108
librashader-runtime-vk/src/hello_triangle/swapchain.rs
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue