Add swapchain (work in progress)
Some checks failed
Build legacy Nix package on Ubuntu / build (push) Failing after 0s
Some checks failed
Build legacy Nix package on Ubuntu / build (push) Failing after 0s
This commit is contained in:
parent
caa79270db
commit
ee8b886aec
7 changed files with 139 additions and 13 deletions
|
@ -35,6 +35,7 @@ impl Window {
|
||||||
let mut extension_names = ash_window::enumerate_required_extensions(display_handle.as_raw())?
|
let mut extension_names = ash_window::enumerate_required_extensions(display_handle.as_raw())?
|
||||||
.to_vec();
|
.to_vec();
|
||||||
|
|
||||||
|
// TODO: Move this because is not related to Window extensions
|
||||||
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
#[cfg(any(target_os = "macos", target_os = "ios"))]
|
||||||
{
|
{
|
||||||
extension_names.push(ash::khr::portability_enumeration::NAME.as_ptr());
|
extension_names.push(ash::khr::portability_enumeration::NAME.as_ptr());
|
||||||
|
@ -48,6 +49,10 @@ impl Window {
|
||||||
pub fn handle(&self) -> Option<&winit::window::Window> {
|
pub fn handle(&self) -> Option<&winit::window::Window> {
|
||||||
self.handle.as_ref()
|
self.handle.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn size(&self) -> Option<winit::dpi::Size> {
|
||||||
|
self.window_attributes.inner_size
|
||||||
|
}
|
||||||
|
|
||||||
pub fn window_event(&mut self, _event_loop: &ActiveEventLoop, _id: WindowId, event: WindowEvent) {
|
pub fn window_event(&mut self, _event_loop: &ActiveEventLoop, _id: WindowId, event: WindowEvent) {
|
||||||
match event {
|
match event {
|
||||||
|
|
|
@ -15,4 +15,7 @@ pub use vk_physical_device::VkPhysicalDevice;
|
||||||
pub(self) mod vk_device;
|
pub(self) mod vk_device;
|
||||||
pub use vk_device::VkDevice;
|
pub use vk_device::VkDevice;
|
||||||
|
|
||||||
|
pub(self) mod vk_swapchain;
|
||||||
|
pub use vk_swapchain::VkSwapchain;
|
||||||
|
|
||||||
mod utils;
|
mod utils;
|
||||||
|
|
|
@ -2,7 +2,7 @@ use ash::vk;
|
||||||
use crate::vulkan::{VkInstance, VkPhysicalDevice};
|
use crate::vulkan::{VkInstance, VkPhysicalDevice};
|
||||||
|
|
||||||
pub struct VkDevice {
|
pub struct VkDevice {
|
||||||
handle: ash::Device,
|
pub(crate) handle: ash::Device,
|
||||||
queue_family_index: u32
|
queue_family_index: u32
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,8 +11,8 @@ use std::fmt::{Display, Formatter};
|
||||||
use winit::raw_window_handle::{HasDisplayHandle, HasWindowHandle};
|
use winit::raw_window_handle::{HasDisplayHandle, HasWindowHandle};
|
||||||
|
|
||||||
pub struct VkInstance {
|
pub struct VkInstance {
|
||||||
entry: Entry,
|
pub(super) entry: Entry,
|
||||||
handle: Instance,
|
pub(super) handle: Instance,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VkInstance {
|
impl VkInstance {
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
use crate::vulkan::{VkDevice, VkInstance, VkPhysicalDevice, VkSurface};
|
use crate::vulkan::{VkDevice, VkInstance, VkPhysicalDevice, VkSurface, VkSwapchain};
|
||||||
use ash::vk::QueueFlags;
|
use ash::vk::QueueFlags;
|
||||||
|
|
||||||
pub struct VkRenderContext {
|
pub struct VkRenderContext {
|
||||||
instance: VkInstance,
|
instance: VkInstance,
|
||||||
surface: VkSurface,
|
surface: VkSurface,
|
||||||
|
device: VkDevice,
|
||||||
|
swapchain: VkSwapchain
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VkRenderContext {
|
impl VkRenderContext {
|
||||||
|
@ -26,19 +28,20 @@ impl VkRenderContext {
|
||||||
let device = VkDevice::new_graphics_device(&instance, &physical_device, queue_family_index)
|
let device = VkDevice::new_graphics_device(&instance, &physical_device, queue_family_index)
|
||||||
.expect("Unable to create device");
|
.expect("Unable to create device");
|
||||||
|
|
||||||
let present_queue = device.get_device_queue(0);
|
let swapchain = surface.create_swapchain(
|
||||||
|
&window,
|
||||||
|
&instance,
|
||||||
|
&device,
|
||||||
|
&physical_device
|
||||||
|
).expect("Unable to create swapchain");
|
||||||
|
|
||||||
let surface_format = surface.get_physical_device_surface_formats(physical_device)
|
// let present_queue = device.get_device_queue(0);
|
||||||
.unwrap_or_default()
|
|
||||||
.first()
|
|
||||||
.expect("Unable to get surface format");
|
|
||||||
|
|
||||||
let surface_capabilities = surface.get_physical_device_surface_capabilities(physical_device)
|
|
||||||
.expect("Unable to get surface capabilities");
|
|
||||||
|
|
||||||
Ok(Self {
|
Ok(Self {
|
||||||
instance,
|
instance,
|
||||||
surface,
|
surface,
|
||||||
|
device,
|
||||||
|
swapchain
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
use crate::vulkan::{VkPhysicalDevice, LOG_TARGET};
|
use crate::vulkan::{VkDevice, VkInstance, VkPhysicalDevice, VkSwapchain, LOG_TARGET};
|
||||||
use ash::prelude::VkResult;
|
use ash::prelude::VkResult;
|
||||||
use ash::vk;
|
use ash::vk;
|
||||||
|
use crate::display::Window;
|
||||||
|
|
||||||
pub struct VkSurface {
|
pub struct VkSurface {
|
||||||
surface_loader: ash::khr::surface::Instance,
|
surface_loader: ash::khr::surface::Instance,
|
||||||
|
@ -54,6 +55,92 @@ impl VkSurface {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_swapchain(
|
||||||
|
&self,
|
||||||
|
window: &Window,
|
||||||
|
instance: &VkInstance,
|
||||||
|
device: &VkDevice,
|
||||||
|
physical_device: &VkPhysicalDevice,
|
||||||
|
) -> anyhow::Result<VkSwapchain> {
|
||||||
|
log::debug!(target: LOG_TARGET, "Creating swapchain");
|
||||||
|
|
||||||
|
let surface_formats = self.get_physical_device_surface_formats(physical_device)?;
|
||||||
|
log::debug!(target: LOG_TARGET, "Supported surface formats by physical device: {surface_formats:#?}");
|
||||||
|
|
||||||
|
let surface_format = surface_formats.first()
|
||||||
|
.ok_or_else(|| anyhow::anyhow!("No available surface formats"))?;
|
||||||
|
log::debug!(target: LOG_TARGET, "Selected surface format: {surface_format:?}");
|
||||||
|
|
||||||
|
let surface_capabilities = self.get_physical_device_surface_capabilities(physical_device)?;
|
||||||
|
log::debug!(target: LOG_TARGET, "Surface capabilities: {surface_capabilities:#?}");
|
||||||
|
|
||||||
|
let mut desired_image_count = surface_capabilities.min_image_count + 1;
|
||||||
|
if surface_capabilities.max_image_count > 0
|
||||||
|
&& desired_image_count > surface_capabilities.max_image_count
|
||||||
|
{
|
||||||
|
desired_image_count = surface_capabilities.max_image_count;
|
||||||
|
}
|
||||||
|
log::debug!(target: LOG_TARGET, "Selected surface image count: {desired_image_count}");
|
||||||
|
|
||||||
|
let window_size = window.size()
|
||||||
|
.ok_or_else(|| anyhow::anyhow!("Window size is not valid"))?
|
||||||
|
.to_physical::<u32>(1.0);
|
||||||
|
log::debug!(target: LOG_TARGET, "Window size: {window_size:?}");
|
||||||
|
|
||||||
|
let surface_resolution = match surface_capabilities.current_extent.width {
|
||||||
|
u32::MAX => vk::Extent2D {
|
||||||
|
width: window_size.width,
|
||||||
|
height: window_size.height,
|
||||||
|
},
|
||||||
|
_ => surface_capabilities.current_extent,
|
||||||
|
};
|
||||||
|
log::debug!(target: LOG_TARGET, "Surface resolution: {surface_resolution:?}");
|
||||||
|
|
||||||
|
let pre_transform = if surface_capabilities
|
||||||
|
.supported_transforms
|
||||||
|
.contains(vk::SurfaceTransformFlagsKHR::IDENTITY)
|
||||||
|
{
|
||||||
|
vk::SurfaceTransformFlagsKHR::IDENTITY
|
||||||
|
} else {
|
||||||
|
surface_capabilities.current_transform
|
||||||
|
};
|
||||||
|
|
||||||
|
let present_modes = self
|
||||||
|
.get_physical_device_surface_present_modes(physical_device)?;
|
||||||
|
|
||||||
|
let present_mode = present_modes
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.find(|&mode| mode == vk::PresentModeKHR::MAILBOX)
|
||||||
|
.unwrap_or(vk::PresentModeKHR::FIFO);
|
||||||
|
let swapchain_loader = ash::khr::swapchain::Device::new(&instance.handle, &device.handle);
|
||||||
|
|
||||||
|
let swapchain_create_info = vk::SwapchainCreateInfoKHR::default()
|
||||||
|
.surface(self.surface)
|
||||||
|
.min_image_count(desired_image_count)
|
||||||
|
.image_color_space(surface_format.color_space)
|
||||||
|
.image_format(surface_format.format)
|
||||||
|
.image_extent(surface_resolution)
|
||||||
|
.image_usage(vk::ImageUsageFlags::COLOR_ATTACHMENT)
|
||||||
|
.image_sharing_mode(vk::SharingMode::EXCLUSIVE)
|
||||||
|
.pre_transform(pre_transform)
|
||||||
|
.composite_alpha(vk::CompositeAlphaFlagsKHR::OPAQUE)
|
||||||
|
.present_mode(present_mode)
|
||||||
|
.clipped(true)
|
||||||
|
.image_array_layers(1);
|
||||||
|
log::debug!(target: LOG_TARGET, "Swapchain info: {swapchain_create_info:#?}");
|
||||||
|
|
||||||
|
let swapchain = unsafe {
|
||||||
|
swapchain_loader.create_swapchain(&swapchain_create_info, None)?
|
||||||
|
};
|
||||||
|
log::debug!(target: LOG_TARGET, "Swapchain created");
|
||||||
|
|
||||||
|
Ok(VkSwapchain::new(
|
||||||
|
swapchain_loader,
|
||||||
|
Some(swapchain)
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for VkSurface {
|
impl Drop for VkSurface {
|
||||||
|
|
28
src/vulkan/vk_swapchain.rs
Normal file
28
src/vulkan/vk_swapchain.rs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
use ash::vk;
|
||||||
|
|
||||||
|
pub struct VkSwapchain {
|
||||||
|
swapchain_loader: ash::khr::swapchain::Device,
|
||||||
|
swapchain: Option<vk::SwapchainKHR>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VkSwapchain {
|
||||||
|
pub fn new(
|
||||||
|
swapchain_loader: ash::khr::swapchain::Device,
|
||||||
|
swapchain: Option<vk::SwapchainKHR>,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
swapchain_loader,
|
||||||
|
swapchain
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for VkSwapchain {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
if let Some(swapchain) = self.swapchain {
|
||||||
|
unsafe {
|
||||||
|
self.swapchain_loader.destroy_swapchain(swapchain, None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue