This commit is contained in:
parent
e9ce480f96
commit
210a5504ab
6 changed files with 162 additions and 90 deletions
36
Cargo.lock
generated
36
Cargo.lock
generated
|
@ -242,9 +242,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.1.36"
|
||||
version = "1.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baee610e9452a8f6f0a1b6194ec09ff9e2d85dea54432acdae41aa0761c95d70"
|
||||
checksum = "fd9de9f2205d5ef3fd67e685b0df337994ddd4495e2a28d185500d0e1edfea47"
|
||||
dependencies = [
|
||||
"jobserver",
|
||||
"libc",
|
||||
|
@ -566,9 +566,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.161"
|
||||
version = "0.2.164"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1"
|
||||
checksum = "433bfe06b8c75da9b2e3fbea6e5329ff87748f0b144ef75306e674c3f6f7c13f"
|
||||
|
||||
[[package]]
|
||||
name = "libloading"
|
||||
|
@ -954,9 +954,9 @@ checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
|
|||
|
||||
[[package]]
|
||||
name = "polling"
|
||||
version = "3.7.3"
|
||||
version = "3.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cc2790cd301dec6cd3b7a025e4815cf825724a51c98dccfe6a3e55f05ffb6511"
|
||||
checksum = "a604568c3202727d1507653cb121dbd627a58684eb09a820fd746bee38b4442f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"concurrent-queue",
|
||||
|
@ -1053,9 +1053,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "regex-automata"
|
||||
version = "0.4.8"
|
||||
version = "0.4.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "368758f23274712b504848e9d5a6f010445cc8b87a7cdb4d7cbee666c1288da3"
|
||||
checksum = "809e8dc61f6de73b46c85f4c96486310fe304c434cfa43669d7b40f711150908"
|
||||
dependencies = [
|
||||
"aho-corasick",
|
||||
"memchr",
|
||||
|
@ -1082,9 +1082,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rustix"
|
||||
version = "0.38.39"
|
||||
version = "0.38.40"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "375116bee2be9ed569afe2154ea6a99dfdffd257f533f187498c2a8f5feaf4ee"
|
||||
checksum = "99e4ea3e1cdc4b559b8e5650f9c8e5998e3e5c1343b4eaf034565f32318d63c0"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"errno",
|
||||
|
@ -1123,18 +1123,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.214"
|
||||
version = "1.0.215"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f55c3193aca71c12ad7890f1785d2b73e1b9f63a0bbc353c08ef26fe03fc56b5"
|
||||
checksum = "6513c1ad0b11a9376da888e3e0baa0077f1aed55c17f50e7b2397136129fb88f"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.214"
|
||||
version = "1.0.215"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "de523f781f095e28fa605cdce0f8307e451cc0fd14e2eb4cd2e98a355b147766"
|
||||
checksum = "ad1e866f866923f252f05c889987993144fb74e722403468a4ebd70c3cd756c0"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
@ -1215,18 +1215,18 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.68"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02dd99dc800bbb97186339685293e1cc5d9df1f8fae2d0aecd9ff1c77efea892"
|
||||
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.68"
|
||||
version = "1.0.69"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a7c61ec9a6f64d2793d8a45faba21efbe3ced62a886d44c36a009b2b519b4c7e"
|
||||
checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use std::ffi::c_char;
|
||||
use winit::dpi::Pixel;
|
||||
use winit::event_loop::ActiveEventLoop;
|
||||
use winit::raw_window_handle::HasDisplayHandle;
|
||||
|
||||
|
@ -49,8 +50,10 @@ impl Window {
|
|||
self.handle.as_ref()
|
||||
}
|
||||
|
||||
pub fn size(&self) -> Option<winit::dpi::Size> {
|
||||
self.window_attributes.inner_size
|
||||
pub fn physical_size<P: Pixel>(&self) -> Option<winit::dpi::PhysicalSize<P>> {
|
||||
self.window_attributes
|
||||
.inner_size
|
||||
.and_then(|size| Some(size.to_physical::<P>(1.0)))
|
||||
}
|
||||
|
||||
pub fn request_redraw(&self) {
|
||||
|
|
|
@ -7,7 +7,12 @@ pub struct VkDevice {
|
|||
instance: Arc<VkInstance>,
|
||||
pub(super) handle: ash::Device,
|
||||
pub(super) swapchain_loader: ash::khr::swapchain::Device,
|
||||
|
||||
queue_family_index: u32,
|
||||
|
||||
// Arc not used because vk::Queue is destroyed with Device automatically
|
||||
// so any references of vk::Queue must be destroyed with VkDevice
|
||||
queues: Vec<vk::Queue>,
|
||||
}
|
||||
|
||||
impl VkDevice {
|
||||
|
@ -25,11 +30,11 @@ impl VkDevice {
|
|||
shader_clip_distance: 1,
|
||||
..Default::default()
|
||||
};
|
||||
let priorities = [1.0];
|
||||
|
||||
let queues_priorities = [1.0];
|
||||
let queue_info = vk::DeviceQueueCreateInfo::default()
|
||||
.queue_family_index(queue_family_index)
|
||||
.queue_priorities(&priorities);
|
||||
.queue_priorities(&queues_priorities);
|
||||
|
||||
let device_create_info = vk::DeviceCreateInfo::default()
|
||||
.queue_create_infos(std::slice::from_ref(&queue_info))
|
||||
|
@ -43,6 +48,12 @@ impl VkDevice {
|
|||
};
|
||||
log::debug!(target: LOG_TARGET, "Device created ({:?})", device.handle());
|
||||
|
||||
let queues = queues_priorities
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, _)| unsafe { device.get_device_queue(queue_family_index, index as u32) })
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let swapchain_loader = ash::khr::swapchain::Device::new(&instance.handle, &device);
|
||||
|
||||
Ok(Self {
|
||||
|
@ -50,14 +61,12 @@ impl VkDevice {
|
|||
handle: device,
|
||||
swapchain_loader,
|
||||
queue_family_index,
|
||||
queues,
|
||||
})
|
||||
}
|
||||
|
||||
pub(super) fn get_device_queue(&self, queue_index: u32) -> vk::Queue {
|
||||
unsafe {
|
||||
self.handle
|
||||
.get_device_queue(self.queue_family_index, queue_index)
|
||||
}
|
||||
pub(super) fn get_device_queue(&self, queue_index: u32) -> Option<&vk::Queue> {
|
||||
self.queues.get(queue_index as usize)
|
||||
}
|
||||
|
||||
pub(super) fn create_image_view(
|
||||
|
|
|
@ -41,14 +41,17 @@ impl VkInstance {
|
|||
}
|
||||
|
||||
// Layers
|
||||
let layers = use_layers(
|
||||
&entry,
|
||||
LayersSelector::SpecificLayers(vec![
|
||||
#[allow(unused)]
|
||||
let mut layer_selector = LayersSelector::Nothing;
|
||||
#[cfg(debug_assertions)]
|
||||
{
|
||||
layer_selector = LayersSelector::SpecificLayers(vec![
|
||||
"VK_LAYER_KHRONOS_validation",
|
||||
"VK_LAYER_MANGOHUD_overlay_x86_64",
|
||||
"VK_LAYER_NV_optimus",
|
||||
]),
|
||||
);
|
||||
]);
|
||||
}
|
||||
let layers = use_layers(&entry, layer_selector);
|
||||
|
||||
{
|
||||
let layers = layers
|
||||
|
|
|
@ -4,6 +4,12 @@ use ash::vk;
|
|||
use std::sync::Arc;
|
||||
use winit::raw_window_handle::{HasDisplayHandle, HasWindowHandle};
|
||||
|
||||
pub struct SwapchainSupportDetails(
|
||||
pub Vec<vk::SurfaceFormatKHR>,
|
||||
pub vk::SurfaceCapabilitiesKHR,
|
||||
pub Vec<vk::PresentModeKHR>,
|
||||
);
|
||||
|
||||
pub struct VkSurface {
|
||||
instance: Arc<VkInstance>,
|
||||
pub(super) surface: vk::SurfaceKHR,
|
||||
|
@ -46,14 +52,10 @@ impl VkSurface {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn get_physical_device_surface_infos(
|
||||
pub fn get_physical_device_swapchain_support_details(
|
||||
&self,
|
||||
physical_device: &VkPhysicalDevice,
|
||||
) -> VkResult<(
|
||||
Vec<vk::SurfaceFormatKHR>,
|
||||
vk::SurfaceCapabilitiesKHR,
|
||||
Vec<vk::PresentModeKHR>,
|
||||
)> {
|
||||
) -> VkResult<SwapchainSupportDetails> {
|
||||
unsafe {
|
||||
let formats = self
|
||||
.instance
|
||||
|
@ -70,7 +72,11 @@ impl VkSurface {
|
|||
.surface_loader
|
||||
.get_physical_device_surface_present_modes(physical_device.handle, self.surface)?;
|
||||
|
||||
Ok((formats, capabilities, present_modes))
|
||||
Ok(SwapchainSupportDetails(
|
||||
formats,
|
||||
capabilities,
|
||||
present_modes,
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use crate::display::Window;
|
||||
use crate::vulkan::vk_surface::SwapchainSupportDetails;
|
||||
use crate::vulkan::{VkDevice, VkPhysicalDevice, VkSurface, LOG_TARGET};
|
||||
use ash::prelude::VkResult;
|
||||
use ash::vk;
|
||||
|
@ -8,10 +9,11 @@ pub struct VkSwapchain {
|
|||
surface: Arc<VkSurface>,
|
||||
device: Arc<VkDevice>,
|
||||
swapchain: Option<vk::SwapchainKHR>,
|
||||
swapchain_support_details: SwapchainSupportDetails,
|
||||
|
||||
pub(super) desired_image_count: u32,
|
||||
pub(super) surface_format: vk::SurfaceFormatKHR,
|
||||
pub(super) surface_resolution: vk::Extent2D,
|
||||
pub(super) swapchain_extent: vk::Extent2D,
|
||||
pub(super) present_mode: vk::PresentModeKHR,
|
||||
pub(super) pre_transform: vk::SurfaceTransformFlagsKHR,
|
||||
|
||||
|
@ -28,64 +30,42 @@ impl VkSwapchain {
|
|||
) -> anyhow::Result<Self> {
|
||||
log::debug!(target: LOG_TARGET, "Creating swapchain");
|
||||
|
||||
let (surface_formats, surface_capabilities, present_modes) =
|
||||
surface.get_physical_device_surface_infos(physical_device)?;
|
||||
let window_size = window
|
||||
.physical_size::<u32>()
|
||||
.and_then(|size| {
|
||||
Some(vk::Extent2D {
|
||||
width: size.width,
|
||||
height: size.height,
|
||||
})
|
||||
})
|
||||
.ok_or_else(|| anyhow::anyhow!("Failed to get swapchain extent"))?;
|
||||
log::debug!(target: LOG_TARGET, "Window size ({}x{})", window_size.width, window_size.height);
|
||||
|
||||
let swapchain_support_details =
|
||||
surface.get_physical_device_swapchain_support_details(physical_device)?;
|
||||
let SwapchainSupportDetails(surface_formats, surface_capabilities, present_modes) =
|
||||
&swapchain_support_details;
|
||||
log::debug!(target: LOG_TARGET, "Supported surface formats by physical device: {surface_formats:#?}");
|
||||
log::debug!(target: LOG_TARGET, "Surface capabilities: {surface_capabilities:#?}");
|
||||
log::debug!(target: LOG_TARGET, "Present modes: {present_modes:#?}");
|
||||
|
||||
let surface_format = surface_formats
|
||||
.first()
|
||||
.and_then(|f| Some(*f))
|
||||
let surface_format = Self::choose_surface_format(surface_formats)
|
||||
.ok_or_else(|| anyhow::anyhow!("No available surface formats"))?;
|
||||
log::debug!(target: LOG_TARGET, "Selected surface format: {surface_format:?}");
|
||||
|
||||
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_mode = present_modes
|
||||
.iter()
|
||||
.cloned()
|
||||
.find(|&mode| mode == vk::PresentModeKHR::MAILBOX)
|
||||
.unwrap_or(vk::PresentModeKHR::FIFO);
|
||||
let desired_image_count = Self::choose_desired_image_count(surface_capabilities);
|
||||
let swapchain_extent = Self::choose_swapchain_extent(window_size, surface_capabilities);
|
||||
let pre_transform = Self::choose_pre_transform(surface_capabilities);
|
||||
let present_mode = Self::choose_present_mode(present_modes);
|
||||
|
||||
let mut swapchain = Self {
|
||||
surface,
|
||||
device,
|
||||
swapchain: None,
|
||||
swapchain_support_details,
|
||||
desired_image_count,
|
||||
surface_format,
|
||||
surface_resolution,
|
||||
swapchain_extent,
|
||||
present_mode,
|
||||
pre_transform,
|
||||
swapchain: None,
|
||||
present_images: None,
|
||||
present_image_views: None,
|
||||
};
|
||||
|
@ -138,10 +118,22 @@ impl VkSwapchain {
|
|||
}
|
||||
|
||||
pub(super) fn update_resolution(&mut self, width: u32, height: u32) -> VkResult<()> {
|
||||
log::debug!(target: LOG_TARGET, "New resolution requested for swapchain {width}x{height}");
|
||||
self.surface_resolution = vk::Extent2D { width, height };
|
||||
log::debug!(target: LOG_TARGET, "New resolution requested ({width}x{height})");
|
||||
|
||||
self.create_swapchain()?;
|
||||
let chosen_extent = Self::choose_swapchain_extent(
|
||||
vk::Extent2D { width, height },
|
||||
&self.swapchain_support_details.1,
|
||||
);
|
||||
if chosen_extent.width != self.swapchain_extent.width
|
||||
|| chosen_extent.height != self.swapchain_extent.height
|
||||
{
|
||||
self.swapchain_extent = chosen_extent;
|
||||
log::debug!(target: LOG_TARGET, "New resolution applied ({}x{})", chosen_extent.width, chosen_extent.height);
|
||||
|
||||
self.create_swapchain()?;
|
||||
} else {
|
||||
log::debug!(target: LOG_TARGET, "New resolution skipped ({width}x{height}) : Same resolution");
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -152,7 +144,7 @@ impl VkSwapchain {
|
|||
.min_image_count(self.desired_image_count)
|
||||
.image_color_space(self.surface_format.color_space)
|
||||
.image_format(self.surface_format.format)
|
||||
.image_extent(self.surface_resolution)
|
||||
.image_extent(self.swapchain_extent)
|
||||
.image_usage(vk::ImageUsageFlags::COLOR_ATTACHMENT)
|
||||
.image_sharing_mode(vk::SharingMode::EXCLUSIVE)
|
||||
.pre_transform(self.pre_transform)
|
||||
|
@ -161,6 +153,65 @@ impl VkSwapchain {
|
|||
.clipped(true)
|
||||
.image_array_layers(1)
|
||||
}
|
||||
|
||||
fn choose_swapchain_extent(
|
||||
window_size: vk::Extent2D,
|
||||
surface_capabilities: &vk::SurfaceCapabilitiesKHR,
|
||||
) -> vk::Extent2D {
|
||||
vk::Extent2D {
|
||||
width: window_size
|
||||
.width
|
||||
.max(surface_capabilities.min_image_extent.width)
|
||||
.min(surface_capabilities.max_image_extent.width),
|
||||
height: window_size
|
||||
.height
|
||||
.max(surface_capabilities.min_image_extent.height)
|
||||
.min(surface_capabilities.max_image_extent.height),
|
||||
}
|
||||
}
|
||||
|
||||
fn choose_surface_format(
|
||||
surface_formats: &Vec<vk::SurfaceFormatKHR>
|
||||
) -> Option<vk::SurfaceFormatKHR> {
|
||||
surface_formats
|
||||
.first()
|
||||
.and_then(|f| Some(*f))
|
||||
}
|
||||
|
||||
fn choose_desired_image_count(
|
||||
surface_capabilities: &vk::SurfaceCapabilitiesKHR
|
||||
) -> u32 {
|
||||
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;
|
||||
}
|
||||
desired_image_count
|
||||
}
|
||||
|
||||
fn choose_pre_transform(
|
||||
surface_capabilities: &vk::SurfaceCapabilitiesKHR
|
||||
) -> vk::SurfaceTransformFlagsKHR {
|
||||
if surface_capabilities
|
||||
.supported_transforms
|
||||
.contains(vk::SurfaceTransformFlagsKHR::IDENTITY)
|
||||
{
|
||||
vk::SurfaceTransformFlagsKHR::IDENTITY
|
||||
} else {
|
||||
surface_capabilities.current_transform
|
||||
}
|
||||
}
|
||||
|
||||
fn choose_present_mode(
|
||||
present_modes: &Vec<vk::PresentModeKHR>
|
||||
) -> vk::PresentModeKHR {
|
||||
present_modes
|
||||
.iter()
|
||||
.cloned()
|
||||
.find(|&mode| mode == vk::PresentModeKHR::MAILBOX)
|
||||
.unwrap_or(vk::PresentModeKHR::FIFO)
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for VkSwapchain {
|
||||
|
|
Loading…
Reference in a new issue