From 052fdc4e3e0826aef6a6917b3c11cfb15e8e182a Mon Sep 17 00:00:00 2001 From: Janis Date: Sat, 14 Dec 2024 23:19:33 +0100 Subject: [PATCH] stuff..... building & rebuilding swapchain --- Cargo.toml | 1 + crates/game/src/main.rs | 65 ++- crates/renderer/Cargo.toml | 1 + crates/renderer/src/lib.rs | 848 ++++++++++++++++++++++++++++--------- 4 files changed, 706 insertions(+), 209 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 666c2bd..843ad78 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,6 +18,7 @@ tracing-subscriber = "0.3.18" vk-mem = "0.4.0" vk-sync = "0.1.6" winit = "0.30.5" +tinyvec = "1.8" futures = "0.3" smol = "2.0" diff --git a/crates/game/src/main.rs b/crates/game/src/main.rs index 0964d8c..daf04e7 100644 --- a/crates/game/src/main.rs +++ b/crates/game/src/main.rs @@ -1,11 +1,12 @@ use std::collections::BTreeMap; +use renderer::Renderer; use tracing::info; use winit::{ application::ApplicationHandler, dpi::{LogicalSize, PhysicalSize}, event_loop::EventLoop, - raw_window_handle::HasDisplayHandle, + raw_window_handle::{DisplayHandle, HasDisplayHandle, HasWindowHandle}, window::{Window, WindowAttributes, WindowId}, }; @@ -13,10 +14,11 @@ struct WindowState { last_resize_events: BTreeMap>, window_attrs: WindowAttributes, window: Option, + renderer: Renderer, } impl WindowState { - fn new(window_title: String) -> WindowState { + fn new(window_title: String, display: DisplayHandle) -> WindowState { Self { window: None, last_resize_events: BTreeMap::new(), @@ -24,30 +26,66 @@ impl WindowState { .with_title(window_title) .with_resizable(true) .with_inner_size(LogicalSize::new(800, 600)), + // TODO: pass down this error and add some kind of error handling UI or dump + renderer: Renderer::new(display).expect("renderer"), } } - fn handle_final_resize(&mut self, window_id: WindowId, new_size: PhysicalSize) { + fn handle_final_resize( + &mut self, + window_id: WindowId, + new_size: PhysicalSize, + ) { _ = (window_id, new_size); info!("TODO: implement resize events"); + if let Some(ctx) = self.renderer.window_contexts.get_mut(&window_id) { + ctx.recreate_swapchain(renderer::Extent2D { + width: new_size.width, + height: new_size.height, + }) + .expect("swapchain recreation"); + } } fn handle_draw_request(&mut self, window_id: WindowId) { - _ = (window_id); + _ = window_id; + info!("TODO: implement draw request"); } } impl ApplicationHandler for WindowState { fn resumed(&mut self, event_loop: &winit::event_loop::ActiveEventLoop) { tracing::debug!("winit::resumed"); - self.window = Some(event_loop.create_window(self.window_attrs.clone()).unwrap()); - tracing::info!( - window = u64::from(self.window.as_ref().unwrap().id()), - "created new window" + self.window = + Some(event_loop.create_window(self.window_attrs.clone()).unwrap()); + let window_id = self.window.as_ref().unwrap().id(); + tracing::info!(window = u64::from(window_id), "created new window"); + + let size = self + .window_attrs + .inner_size + .map(|size| size.to_physical(1.0)) + .unwrap_or(PhysicalSize::new(0, 0)); + let extent = renderer::Extent2D { + width: size.width, + height: size.height, + }; + + self.renderer.new_window_context( + extent, + window_id, + self.window + .as_ref() + .unwrap() + .window_handle() + .expect("window handle"), ); } - fn about_to_wait(&mut self, _event_loop: &winit::event_loop::ActiveEventLoop) { + fn about_to_wait( + &mut self, + _event_loop: &winit::event_loop::ActiveEventLoop, + ) { for (&window, &resize) in self.last_resize_events.clone().iter() { self.handle_final_resize(window, resize); } @@ -70,7 +108,10 @@ impl ApplicationHandler for WindowState { _ = self.last_resize_events.insert(window_id, physical_size); } winit::event::WindowEvent::CloseRequested => { - tracing::info!(window = u64::from(window_id), "window close requested"); + tracing::info!( + window = u64::from(window_id), + "window close requested" + ); event_loop.exit(); } winit::event::WindowEvent::KeyboardInput { @@ -108,7 +149,7 @@ fn main() { tracing_subscriber::fmt().init(); let ev = EventLoop::new().unwrap(); - let display = ev.owned_display_handle().display_handle(); - let mut game = WindowState::new("Vidya".to_owned()); + let display = ev.display_handle().expect("display handle"); + let mut game = WindowState::new("Vidya".to_owned(), display); ev.run_app(&mut game).unwrap(); } diff --git a/crates/renderer/Cargo.toml b/crates/renderer/Cargo.toml index 276ec0a..62257e3 100644 --- a/crates/renderer/Cargo.toml +++ b/crates/renderer/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.0" edition = "2021" [dependencies] +tinyvec = {workspace = true} dyn-clone = "1" anyhow = "1.0.89" ash = "0.38.0" diff --git a/crates/renderer/src/lib.rs b/crates/renderer/src/lib.rs index 595f423..0beeeeb 100644 --- a/crates/renderer/src/lib.rs +++ b/crates/renderer/src/lib.rs @@ -1,16 +1,17 @@ -#![feature(c_str_module, closure_lifetime_binder)] +#![feature(c_str_module, closure_lifetime_binder, let_chains)] +#![allow(unused)] use std::{ - borrow::Borrow, - collections::{BTreeMap, BTreeSet}, - ffi::CStr, + collections::{BTreeMap, BTreeSet, HashMap}, + ffi::{CStr, CString}, fmt::Debug, marker::PhantomData, - ops::Deref, sync::{Arc, Mutex}, }; -use ash::{khr, prelude::*, vk, Entry}; +use ash::{khr, vk, Entry}; use dyn_clone::DynClone; +use tinyvec::{array_vec, ArrayVec}; +use winit::raw_window_handle::DisplayHandle; #[derive(Debug, thiserror::Error)] pub enum Error { @@ -20,6 +21,8 @@ pub enum Error { Result(#[from] ash::vk::Result), #[error(transparent)] CStrError(#[from] core::ffi::c_str::FromBytesUntilNulError), + #[error(transparent)] + NulError(#[from] std::ffi::NulError), #[error("No Physical Device found.")] NoPhysicalDevice, } @@ -48,7 +51,10 @@ struct DeviceExtension<'a> { version: u32, } -fn make_extention_properties(name: &CStr, version: u32) -> vk::ExtensionProperties { +fn make_extention_properties( + name: &CStr, + version: u32, +) -> vk::ExtensionProperties { vk::ExtensionProperties::default() .spec_version(version) .extension_name(name) @@ -86,14 +92,23 @@ impl Queue { } } -trait ExtendsDeviceFeatures2Debug: vk::ExtendsPhysicalDeviceFeatures2 + Debug {} -trait ExtendsDeviceProperties2Debug: vk::ExtendsPhysicalDeviceProperties2 + Debug + DynClone {} +trait ExtendsDeviceFeatures2Debug: + vk::ExtendsPhysicalDeviceFeatures2 + Debug +{ +} +trait ExtendsDeviceProperties2Debug: + vk::ExtendsPhysicalDeviceProperties2 + Debug + DynClone +{ +} -impl ExtendsDeviceFeatures2Debug for T {} -impl ExtendsDeviceProperties2Debug +impl ExtendsDeviceFeatures2Debug for T { } +impl + ExtendsDeviceProperties2Debug for T +{ +} #[derive(Default, Debug)] struct PhysicalDeviceFeatures { @@ -117,7 +132,10 @@ impl PhysicalDeviceFeatures { .features13(Default::default()) } - fn query(instance: &ash::Instance, pdev: vk::PhysicalDevice) -> Result { + fn query( + instance: &ash::Instance, + pdev: vk::PhysicalDevice, + ) -> Result { let mut this = Self::all_default(); let mut features2 = this.features2(); let features = unsafe { @@ -127,44 +145,64 @@ impl PhysicalDeviceFeatures { }; this = this.features10(features); - let extensions = unsafe { instance.enumerate_device_extension_properties(pdev)? }; + let extensions = + unsafe { instance.enumerate_device_extension_properties(pdev)? }; this = this.device_extensions(extensions); Ok(this) } - fn features10(self, physical_features_10: vk::PhysicalDeviceFeatures) -> Self { + fn features10( + self, + physical_features_10: vk::PhysicalDeviceFeatures, + ) -> Self { Self { physical_features_10, ..self } } - fn features11(self, physical_features_11: vk::PhysicalDeviceVulkan11Features<'static>) -> Self { + fn features11( + self, + physical_features_11: vk::PhysicalDeviceVulkan11Features<'static>, + ) -> Self { Self { physical_features_11: Some(physical_features_11), ..self } } - fn features12(self, physical_features_12: vk::PhysicalDeviceVulkan12Features<'static>) -> Self { + fn features12( + self, + physical_features_12: vk::PhysicalDeviceVulkan12Features<'static>, + ) -> Self { Self { physical_features_12: Some(physical_features_12), ..self } } - fn features13(self, physical_features_13: vk::PhysicalDeviceVulkan13Features<'static>) -> Self { + fn features13( + self, + physical_features_13: vk::PhysicalDeviceVulkan13Features<'static>, + ) -> Self { Self { physical_features_13: Some(physical_features_13), ..self } } - fn device_extensions(self, device_extensions: Vec) -> Self { + fn device_extensions( + self, + device_extensions: Vec, + ) -> Self { Self { device_extensions, ..self } } - fn with_extension(mut self, ext: vk::ExtensionProperties, features: F) -> Self + fn with_extension( + mut self, + ext: vk::ExtensionProperties, + features: F, + ) -> Self where F: ExtendsDeviceFeatures2Debug + 'static, { @@ -175,8 +213,8 @@ impl PhysicalDeviceFeatures { } fn features2(&mut self) -> vk::PhysicalDeviceFeatures2<'_> { - let mut features2 = - vk::PhysicalDeviceFeatures2::default().features(self.physical_features_10); + let mut features2 = vk::PhysicalDeviceFeatures2::default() + .features(self.physical_features_10); if let Some(ref mut features11) = self.physical_features_11 { features2 = features2.push_next(features11); @@ -196,7 +234,8 @@ impl PhysicalDeviceFeatures { } fn compatible_with(&self, device: &Self) -> bool { - let sort_exts = |a: &vk::ExtensionProperties, b: &vk::ExtensionProperties| { + let sort_exts = |a: &vk::ExtensionProperties, + b: &vk::ExtensionProperties| { (a.extension_name_as_c_str().unwrap(), a.spec_version) .cmp(&(b.extension_name_as_c_str().unwrap(), b.spec_version)) }; @@ -228,21 +267,30 @@ impl PhysicalDeviceFeatures { .physical_features_11 .zip(device.physical_features_11) .map(|(a, b)| { - utils::eq_device_features11(&utils::bitand_device_features11(&a, &b), &a) + utils::eq_device_features11( + &utils::bitand_device_features11(&a, &b), + &a, + ) }) .unwrap_or(true) && self .physical_features_12 .zip(device.physical_features_12) .map(|(a, b)| { - utils::eq_device_features12(&utils::bitand_device_features12(&a, &b), &a) + utils::eq_device_features12( + &utils::bitand_device_features12(&a, &b), + &a, + ) }) .unwrap_or(true) && self .physical_features_13 .zip(device.physical_features_13) .map(|(a, b)| { - utils::eq_device_features13(&utils::bitand_device_features13(&a, &b), &a) + utils::eq_device_features13( + &utils::bitand_device_features13(&a, &b), + &a, + ) }) .unwrap_or(true) } @@ -305,6 +353,20 @@ struct PhysicalDevice { properties: PhysicalDeviceProperties, } +impl PhysicalDevice { + fn swapchain_family_indices(&self) -> ArrayVec<[u32; 2]> { + let mut indices = array_vec!([u32; 2] => self.queue_families.graphics); + + if let Some(present) = self.queue_families.present + && present != self.queue_families.graphics + { + indices.push(present); + } + + indices + } +} + struct Instance { entry: Entry, instance: ash::Instance, @@ -316,8 +378,10 @@ struct Instance { impl Drop for Instance { fn drop(&mut self) { unsafe { - self.debug_utils - .destroy_debug_utils_messenger(self.debug_utils_messenger, None); + self.debug_utils.destroy_debug_utils_messenger( + self.debug_utils_messenger, + None, + ); } } } @@ -341,15 +405,23 @@ struct DeviceQueueFamilies { transfer: Option, } -#[derive(Clone)] struct Device { + physical: PhysicalDevice, device: ash::Device, swapchain: khr::swapchain::Device, } impl Device { - fn new(device: ash::Device, swapchain: khr::swapchain::Device) -> Self { - Self { device, swapchain } + fn new( + device: ash::Device, + physical: PhysicalDevice, + swapchain: khr::swapchain::Device, + ) -> Self { + Self { + device, + physical, + swapchain, + } } } @@ -375,8 +447,7 @@ impl Drop for Device { } struct DeviceAndQueues { - physical: PhysicalDevice, - logical: Arc, + device: Arc, main_queue: Queue, compute_queue: Queue, transfer_queue: Queue, @@ -385,20 +456,24 @@ struct DeviceAndQueues { impl AsRef for DeviceAndQueues { fn as_ref(&self) -> &ash::Device { - &self.logical.device + &self.device.device } } impl AsRef for DeviceAndQueues { fn as_ref(&self) -> &ash::khr::swapchain::Device { - &self.logical.swapchain + &self.device.swapchain } } struct Swapchain { + instance: Arc, device: Arc, + // has a strong ref to the surface because the surface may not outlive the swapchain + surface: Arc, swapchain: vk::SwapchainKHR, present_mode: vk::PresentModeKHR, color_space: vk::ColorSpaceKHR, + format: vk::Format, images: Vec, image_views: Vec, extent: vk::Extent2D, @@ -417,15 +492,39 @@ impl Drop for Swapchain { } } +fn current_extent_or_clamped( + caps: &vk::SurfaceCapabilitiesKHR, + fallback: vk::Extent2D, +) -> vk::Extent2D { + if caps.current_extent.width == u32::MAX { + vk::Extent2D { + width: fallback.width.clamp( + caps.min_image_extent.width, + caps.max_image_extent.width, + ), + height: fallback.height.clamp( + caps.min_image_extent.height, + caps.max_image_extent.height, + ), + } + } else { + caps.current_extent + } +} + impl Swapchain { - fn create_new( - instance: Arc, - device: Arc, + fn get_swapchain_params_from_surface( + instance: &Arc, surface: vk::SurfaceKHR, pdev: vk::PhysicalDevice, - queue_families: &[u32], - extent: vk::Extent2D, - ) -> Result { + requested_extent: vk::Extent2D, + ) -> Result<( + vk::PresentModeKHR, + vk::Format, + vk::ColorSpaceKHR, + u32, + vk::Extent2D, + )> { let caps = unsafe { instance .surface @@ -453,49 +552,194 @@ impl Swapchain { .max_by_key(|&&format| { let is_rgba_unorm = format.format == vk::Format::R8G8B8A8_UNORM || format.format == vk::Format::B8G8R8A8_UNORM; - let is_srgb = format.color_space == vk::ColorSpaceKHR::SRGB_NONLINEAR; + let is_srgb = + format.color_space == vk::ColorSpaceKHR::SRGB_NONLINEAR; is_rgba_unorm as u8 * 10 + is_srgb as u8 }) .or(formats.first()) .cloned() - .context("no surface format available!")?; + .expect("no surface format available!"); - let image_count = caps.min_image_count.max( - core::num::NonZeroU32::new(surface_caps.max_image_count) - .or(core::num::NonZero::new(u32::MAX)) - .unwrap() - .get() - .min(3u32), - ); - let image_count = 3u32.clamp(caps.min_image_count, caps.max_image_count); + let image_count = + 3u32.clamp(caps.min_image_count, caps.max_image_count); - let extent = if caps.current_extent.width == u32::MAX { - vk::Extent2D { - width: extent - .width - .clamp(caps.min_image_extent.width, caps.max_image_extent.width), - height: extent - .height - .clamp(caps.min_image_extent.height, caps.max_image_extent.height), - } - } else { - caps.current_extent + let extent = current_extent_or_clamped(&caps, requested_extent); + + Ok(( + present_mode, + format.format, + format.color_space, + image_count, + extent, + )) + } + fn create_new( + instance: Arc, + device: Arc, + surface: Arc, + pdev: vk::PhysicalDevice, + extent: vk::Extent2D, + ) -> Result { + let (present_mode, format, color_space, image_count, extent) = + Self::get_swapchain_params_from_surface( + &instance, + surface.surface, + pdev, + extent, + )?; + + let (swapchain, images) = Self::create_vkswapchainkhr( + &device, + surface.surface, + &device.physical.swapchain_family_indices(), + extent, + None, + present_mode, + format, + color_space, + image_count, + )?; + + let image_views = images + .iter() + .map(|&image| { + let info = vk::ImageViewCreateInfo::default() + .image(image) + .format(format) + .components(vk::ComponentMapping::default()) + .subresource_range( + vk::ImageSubresourceRange::default() + .aspect_mask(vk::ImageAspectFlags::COLOR) + .base_mip_level(0) + .level_count(1) + .base_array_layer(0) + .layer_count(1), + ); + + unsafe { device.device.create_image_view(&info, None) } + }) + .collect::, _>>()?; + + Ok(Self { + instance, + device, + surface, + swapchain, + present_mode, + color_space, + format, + images, + image_views, + extent, + }) + } + + fn recreate(&self, extent: vk::Extent2D) -> Result { + let (present_mode, format, color_space, image_count, extent) = + Self::get_swapchain_params_from_surface( + &self.instance, + self.surface.surface, + self.device.physical.pdev, + extent, + )?; + + let (swapchain, images) = Self::create_vkswapchainkhr( + &self.device, + self.surface.surface, + &self.device.physical.swapchain_family_indices(), + extent, + Some(self.swapchain), + present_mode, + format, + color_space, + image_count, + )?; + + let image_views = images + .iter() + .map(|&image| { + let info = vk::ImageViewCreateInfo::default() + .image(image) + .format(format) + .components(vk::ComponentMapping::default()) + .subresource_range( + vk::ImageSubresourceRange::default() + .aspect_mask(vk::ImageAspectFlags::COLOR) + .base_mip_level(0) + .level_count(1) + .base_array_layer(0) + .layer_count(1), + ); + + unsafe { self.device.device.create_image_view(&info, None) } + }) + .collect::, _>>()?; + + Ok(Self { + instance: self.instance.clone(), + device: self.device.clone(), + swapchain, + surface: self.surface.clone(), + present_mode, + color_space, + format, + images, + image_views, + extent, + }) + } + + fn create_vkswapchainkhr( + device: &Arc, + surface: vk::SurfaceKHR, + queue_families: &[u32], + image_extent: vk::Extent2D, + old_swapchain: Option, + present_mode: vk::PresentModeKHR, + image_format: vk::Format, + image_color_space: vk::ColorSpaceKHR, + image_count: u32, + ) -> Result<(vk::SwapchainKHR, Vec)> { + let create_info = vk::SwapchainCreateInfoKHR::default() + .surface(surface) + .present_mode(present_mode) + .image_color_space(image_color_space) + .image_format(image_format) + .min_image_count(image_count) + .image_usage(vk::ImageUsageFlags::TRANSFER_DST) + .image_array_layers(1) + .image_extent(image_extent) + .image_sharing_mode(if queue_families.len() <= 1 { + vk::SharingMode::EXCLUSIVE + } else { + vk::SharingMode::CONCURRENT + }) + .queue_family_indices(queue_families) + .pre_transform(vk::SurfaceTransformFlagsKHR::IDENTITY) + .composite_alpha(vk::CompositeAlphaFlagsKHR::OPAQUE) + .old_swapchain(old_swapchain.unwrap_or(vk::SwapchainKHR::null())) + .clipped(true); + + let (swapchain, images) = unsafe { + let swapchain = + device.swapchain.create_swapchain(&create_info, None)?; + let images = device.swapchain.get_swapchain_images(swapchain)?; + + (swapchain, images) }; - todo!() + Ok((swapchain, images)) } } struct Surface { instance: Arc, surface: vk::SurfaceKHR, - swapchain: Option, } impl Surface { fn create( instance: Arc, - device: Arc, display_handle: winit::raw_window_handle::RawDisplayHandle, window_handle: winit::raw_window_handle::RawWindowHandle, ) -> Result { @@ -509,13 +753,7 @@ impl Surface { )? }; - let mut this = Self { - instance, - surface, - swapchain: None, - }; - - todo!() + Ok(Self { instance, surface }) } } @@ -534,9 +772,11 @@ pub struct Vulkan { } impl Vulkan { - const VALIDATION_LAYER_NAME: &'static core::ffi::CStr = c"VK_LAYER_KHRONOS_validation"; + const VALIDATION_LAYER_NAME: &'static core::ffi::CStr = + c"VK_LAYER_KHRONOS_validation"; #[allow(unused)] - const RENDERDOC_LAYER_NAME: &'static core::ffi::CStr = c"VK_LAYER_RENDERDOC_Capture"; + const RENDERDOC_LAYER_NAME: &'static core::ffi::CStr = + c"VK_LAYER_RENDERDOC_Capture"; #[allow(unused)] const NSIGHT_TRACE_LAYER_NAME: &'static core::ffi::CStr = c"VK_LAYER_NV_GPU_Trace_release_public_2021_4_2"; @@ -545,16 +785,18 @@ impl Vulkan { c"VK_LAYER_NV_nomad_release_public_2021_4_2"; pub fn new( + app_name: &str, instance_layers: &[&CStr], instance_extensions: &[&CStr], display_handle: winit::raw_window_handle::DisplayHandle, ) -> Result { let entry = unsafe { ash::Entry::load()? }; + let app_name = CString::new(app_name)?; let app_info = vk::ApplicationInfo::default() .api_version(vk::make_api_version(0, 1, 3, 0)) - .application_name(c"Vidya") - .engine_name(c"Vidya") + .application_name(&app_name) + .engine_name(c"PrimalGame") .application_version(0) .engine_version(0); @@ -568,7 +810,9 @@ impl Vulkan { .values(&[1]), vk::LayerSettingEXT::default() .layer_name(Self::VALIDATION_LAYER_NAME) - .setting_name(c"VK_KHRONOS_VALIDATION_VALIDATE_BEST_PRACTICES_AMD") + .setting_name( + c"VK_KHRONOS_VALIDATION_VALIDATE_BEST_PRACTICES_AMD", + ) .ty(vk::LayerSettingTypeEXT::BOOL32) .values(&[1]), vk::LayerSettingEXT::default() @@ -577,10 +821,11 @@ impl Vulkan { .ty(vk::LayerSettingTypeEXT::BOOL32) .values(&[1]), ]; - let mut validation_info = - vk::LayerSettingsCreateInfoEXT::default().settings(&validation_settings); + let mut validation_info = vk::LayerSettingsCreateInfoEXT::default() + .settings(&validation_settings); - let layers = Self::get_layers(&entry, &[Self::VALIDATION_LAYER_NAME]).unwrap(); + let layers = + Self::get_layers(&entry, &[Self::VALIDATION_LAYER_NAME]).unwrap(); let extensions = Self::get_extensions( &entry, &layers, @@ -612,10 +857,14 @@ impl Vulkan { ) .pfn_user_callback(Some(debug::debug_callback)); - let debug_utils_instance = ash::ext::debug_utils::Instance::new(&entry, &instance); - let debug_utils_messenger = - unsafe { debug_utils_instance.create_debug_utils_messenger(&debug_info, None)? }; - let surface_instance = ash::khr::surface::Instance::new(&entry, &instance); + let debug_utils_instance = + ash::ext::debug_utils::Instance::new(&entry, &instance); + let debug_utils_messenger = unsafe { + debug_utils_instance + .create_debug_utils_messenger(&debug_info, None)? + }; + let surface_instance = + ash::khr::surface::Instance::new(&entry, &instance); let instance = Arc::new(Instance { instance, @@ -632,7 +881,10 @@ impl Vulkan { .sampler_anisotropy(true) .multi_draw_indirect(true), ) - .features11(vk::PhysicalDeviceVulkan11Features::default().shader_draw_parameters(true)) + .features11( + vk::PhysicalDeviceVulkan11Features::default() + .shader_draw_parameters(true), + ) .features12( vk::PhysicalDeviceVulkan12Features::default() .shader_int8(true) @@ -658,11 +910,18 @@ impl Vulkan { ash::khr::index_type_uint8::NAME, ash::khr::index_type_uint8::SPEC_VERSION, ), - vk::PhysicalDeviceIndexTypeUint8FeaturesKHR::default().index_type_uint8(true), + vk::PhysicalDeviceIndexTypeUint8FeaturesKHR::default() + .index_type_uint8(true), ) .device_extensions(vec![ - make_extention_properties(khr::swapchain::NAME, khr::swapchain::SPEC_VERSION), - make_extention_properties(khr::spirv_1_4::NAME, khr::spirv_1_4::SPEC_VERSION), + make_extention_properties( + khr::swapchain::NAME, + khr::swapchain::SPEC_VERSION, + ), + make_extention_properties( + khr::spirv_1_4::NAME, + khr::spirv_1_4::SPEC_VERSION, + ), ]); // Consider this: switching physical device in game? @@ -681,8 +940,11 @@ impl Vulkan { tracing::debug!("pdev: {pdev:?}"); let dev = Self::create_device(&instance, pdev, &mut features)?; - let alloc_info = - vk_mem::AllocatorCreateInfo::new(&instance.instance, dev.as_ref(), dev.physical.pdev); + let alloc_info = vk_mem::AllocatorCreateInfo::new( + &instance.instance, + dev.as_ref(), + dev.device.physical.pdev, + ); let alloc = Arc::new(unsafe { vk_mem::Allocator::new(alloc_info)? }); @@ -701,24 +963,37 @@ impl Vulkan { ) -> bool { unsafe { match display_handle.as_raw() { - winit::raw_window_handle::RawDisplayHandle::Xlib(_xlib_display_handle) => { + winit::raw_window_handle::RawDisplayHandle::Xlib( + _xlib_display_handle, + ) => { todo!() } - winit::raw_window_handle::RawDisplayHandle::Xcb(_xcb_display_handle) => todo!(), - winit::raw_window_handle::RawDisplayHandle::Wayland(wayland_display_handle) => { - ash::khr::wayland_surface::Instance::new(&instance.entry, &instance.instance) - .get_physical_device_wayland_presentation_support( - pdev, - queue_family, - wayland_display_handle.display.cast().as_mut(), - ) - } + winit::raw_window_handle::RawDisplayHandle::Xcb( + _xcb_display_handle, + ) => todo!(), + winit::raw_window_handle::RawDisplayHandle::Wayland( + wayland_display_handle, + ) => ash::khr::wayland_surface::Instance::new( + &instance.entry, + &instance.instance, + ) + .get_physical_device_wayland_presentation_support( + pdev, + queue_family, + wayland_display_handle.display.cast().as_mut(), + ), winit::raw_window_handle::RawDisplayHandle::Drm(_) => { todo!() } winit::raw_window_handle::RawDisplayHandle::Windows(_) => { - ash::khr::win32_surface::Instance::new(&instance.entry, &instance.instance) - .get_physical_device_win32_presentation_support(pdev, queue_family) + ash::khr::win32_surface::Instance::new( + &instance.entry, + &instance.instance, + ) + .get_physical_device_win32_presentation_support( + pdev, + queue_family, + ) } _ => panic!("unsupported platform"), } @@ -796,13 +1071,20 @@ impl Vulkan { .enumerate() .map(|(i, family)| { let q = i as u32; - let is_graphics = family.queue_flags.contains(vk::QueueFlags::GRAPHICS); - let is_compute = family.queue_flags.contains(vk::QueueFlags::COMPUTE); - let is_transfer = family.queue_flags.contains(vk::QueueFlags::TRANSFER) - || is_compute - || is_graphics; - let is_present = - Self::queue_family_supports_presentation(instance, pdev, q, display_handle); + let is_graphics = + family.queue_flags.contains(vk::QueueFlags::GRAPHICS); + let is_compute = + family.queue_flags.contains(vk::QueueFlags::COMPUTE); + let is_transfer = + family.queue_flags.contains(vk::QueueFlags::TRANSFER) + || is_compute + || is_graphics; + let is_present = Self::queue_family_supports_presentation( + instance, + pdev, + q, + display_handle, + ); QueueFamily { num_queues: family.queue_count, is_compute, @@ -825,18 +1107,20 @@ impl Vulkan { .unwrap(); // find present queue first because it is rather more important than a secondary compute queue - let present = if !queue_families.0.get(graphics as usize).unwrap().is_present { - // unwrap because we do need a present queue - Some( - queue_families - .find_first(|family| family.is_present) - .unwrap(), - ) - } else { - None - }; + let present = + if !queue_families.0.get(graphics as usize).unwrap().is_present { + // unwrap because we do need a present queue + Some( + queue_families + .find_first(|family| family.is_present) + .unwrap(), + ) + } else { + None + }; - let async_compute = queue_families.find_first(|family| family.is_compute); + let async_compute = + queue_families.find_first(|family| family.is_compute); let transfer = queue_families.find_first(|family| family.is_transfer); // family of each queue, of which one is allocated for each queue, with graphics being the fallback queue for compute and transfer, and present possibly being `None`, in which case it is Graphics @@ -845,7 +1129,8 @@ impl Vulkan { async_compute, transfer, present: present.or({ - if !queue_families.0.get(graphics as usize).unwrap().is_present { + if !queue_families.0.get(graphics as usize).unwrap().is_present + { panic!("no present queue available"); } else { None @@ -878,12 +1163,18 @@ impl Vulkan { }; let graphics_family_and_index = helper(pdev.queue_families.graphics); - let compute_family_and_index = pdev.queue_families.async_compute.map(|f| helper(f)); - let transfer_family_and_index = pdev.queue_families.transfer.map(|f| helper(f)); - let present_family_and_index = pdev.queue_families.present.map(|f| helper(f)); + let compute_family_and_index = + pdev.queue_families.async_compute.map(|f| helper(f)); + let transfer_family_and_index = + pdev.queue_families.transfer.map(|f| helper(f)); + let present_family_and_index = + pdev.queue_families.present.map(|f| helper(f)); - let priorities = - vec![1.0f32; unique_families.iter().fold(0, |acc, (_, num)| acc + *num) as usize]; + let priorities = vec![ + 1.0f32; + unique_families.iter().fold(0, |acc, (_, num)| acc + *num) + as usize + ]; let queue_infos = unique_families .into_iter() @@ -907,15 +1198,20 @@ impl Vulkan { .push_next(&mut features2); let device_and_queues = unsafe { - let device = instance - .instance - .create_device(pdev.pdev, &device_info, None)?; + let device = instance.instance.create_device( + pdev.pdev, + &device_info, + None, + )?; let main_queue = Queue::new( &device, graphics_family_and_index.0, graphics_family_and_index.1, ); - device.get_device_queue(graphics_family_and_index.0, graphics_family_and_index.1); + device.get_device_queue( + graphics_family_and_index.0, + graphics_family_and_index.1, + ); let present_queue = present_family_and_index .map(|(f, i)| Queue::new(&device, f, i)) .unwrap_or(main_queue.clone()); @@ -927,11 +1223,14 @@ impl Vulkan { .unwrap_or(compute_queue.clone()); DeviceAndQueues { - physical: pdev, - logical: Arc::new(Device::new( - device.clone(), - khr::swapchain::Device::new(&instance.instance, &device), - )), + device: Arc::new(Device { + device: device.clone(), + physical: pdev, + swapchain: khr::swapchain::Device::new( + &instance.instance, + &device, + ), + }), main_queue, present_queue, compute_queue, @@ -953,12 +1252,13 @@ impl Vulkan { let (pdev, properties) = pdevs .into_iter() .map(|pdev| { - let mut props = PhysicalDeviceProperties::default().extra_properties( - extra_properties - .iter() - .map(|b| dyn_clone::clone_box(&**b)) - .collect::>(), - ); + let mut props = PhysicalDeviceProperties::default() + .extra_properties( + extra_properties + .iter() + .map(|b| dyn_clone::clone_box(&**b)) + .collect::>(), + ); props.query(&instance.instance, pdev); (pdev, props) @@ -971,7 +1271,8 @@ impl Vulkan { // device which doesn't support all of the extensions. .filter(|(pdev, _)| { let query_features = - PhysicalDeviceFeatures::query(&instance.instance, *pdev).unwrap(); + PhysicalDeviceFeatures::query(&instance.instance, *pdev) + .unwrap(); requirements.compatible_with(&query_features) }) @@ -992,7 +1293,11 @@ impl Vulkan { .ok_or(Error::NoPhysicalDevice)?; Ok(PhysicalDevice { - queue_families: Self::select_pdev_queue_families(instance, display_handle, pdev), + queue_families: Self::select_pdev_queue_families( + instance, + display_handle, + pdev, + ), pdev, properties, }) @@ -1003,15 +1308,15 @@ impl Vulkan { layers: &[&CStr], ) -> Result> { unsafe { - let extensions = core::iter::once(entry.enumerate_instance_extension_properties(None)) - .chain( - layers - .iter() - .map(|&layer| entry.enumerate_instance_extension_properties(Some(layer))), - ) - .filter_map(|result| result.ok()) - .flatten() - .collect::>(); + let extensions = core::iter::once( + entry.enumerate_instance_extension_properties(None), + ) + .chain(layers.iter().map(|&layer| { + entry.enumerate_instance_extension_properties(Some(layer)) + })) + .filter_map(|result| result.ok()) + .flatten() + .collect::>(); Ok(extensions) } @@ -1022,10 +1327,13 @@ impl Vulkan { layers: &[&'a CStr], extensions: &[&'a CStr], display_handle: winit::raw_window_handle::DisplayHandle, - ) -> core::result::Result, (Vec<&'a CStr>, Vec<&'a CStr>)> { + ) -> core::result::Result, (Vec<&'a CStr>, Vec<&'a CStr>)> + { unsafe { - let available_extensions = Self::get_available_extensions(entry, layers) - .map_err(|_| (Vec::<&'a CStr>::new(), extensions.to_vec()))?; + let available_extensions = Self::get_available_extensions( + entry, layers, + ) + .map_err(|_| (Vec::<&'a CStr>::new(), extensions.to_vec()))?; let available_extension_names = available_extensions .iter() @@ -1034,7 +1342,8 @@ impl Vulkan { .map_err(|_| (Vec::<&'a CStr>::new(), extensions.to_vec()))?; let mut out_extensions = Vec::with_capacity(extensions.len()); - let mut unsupported_extensions = Vec::with_capacity(extensions.len()); + let mut unsupported_extensions = + Vec::with_capacity(extensions.len()); for &extension in extensions { if available_extension_names.contains(&extension) { out_extensions.push(extension); @@ -1044,7 +1353,9 @@ impl Vulkan { } let Ok(required_extension_names) = - ash_window::enumerate_required_extensions(display_handle.as_raw()) + ash_window::enumerate_required_extensions( + display_handle.as_raw(), + ) else { return Err((out_extensions, unsupported_extensions)); }; @@ -1069,7 +1380,8 @@ impl Vulkan { fn get_layers<'a>( entry: &ash::Entry, wants_layers: &[&'a CStr], - ) -> core::result::Result, (Vec<&'a CStr>, Vec<&'a CStr>)> { + ) -> core::result::Result, (Vec<&'a CStr>, Vec<&'a CStr>)> + { unsafe { let available_layers = entry .enumerate_instance_layer_properties() @@ -1099,13 +1411,103 @@ impl Vulkan { } } -pub struct Renderer {} +pub struct WindowContext { + surface: Arc, + current_swapchain: Arc, +} + +impl WindowContext { + pub fn new( + instance: Arc, + device: Arc, + extent: vk::Extent2D, + window: winit::raw_window_handle::RawWindowHandle, + display: winit::raw_window_handle::RawDisplayHandle, + ) -> Result { + let surface = + Arc::new(Surface::create(instance.clone(), display, window)?); + + let swapchain = Arc::new(Swapchain::create_new( + instance, + device.clone(), + surface.clone(), + device.physical.pdev, + extent, + )?); + + Ok(Self { + surface, + current_swapchain: swapchain, + }) + } + + pub fn recreate_swapchain(&mut self, extent: vk::Extent2D) -> Result<()> { + self.current_swapchain = + Arc::new(self.current_swapchain.recreate(extent)?); + + Ok(()) + } +} + +pub struct Renderer { + vulkan: Vulkan, + display: winit::raw_window_handle::RawDisplayHandle, + pub window_contexts: HashMap, +} + +pub use vk::Extent2D; + +impl Renderer { + pub fn new(display: DisplayHandle) -> Result { + let vulkan = Vulkan::new("Vidya", &[], &[], display)?; + Ok(Self { + vulkan, + display: display.as_raw(), + window_contexts: HashMap::new(), + }) + } + + pub fn debug_draw(&mut self) -> Result<()> { + let dev = self.vulkan.device.device.clone(); + + unsafe { dev.device.device_wait_idle()? }; + + todo!() + } + + pub fn new_window_context( + &mut self, + extent: vk::Extent2D, + window_id: winit::window::WindowId, + window: winit::raw_window_handle::WindowHandle, + ) -> Result<()> { + use std::collections::hash_map::Entry; + match self.window_contexts.entry(window_id) { + Entry::Vacant(entry) => { + let ctx = WindowContext::new( + self.vulkan.instance.clone(), + self.vulkan.device.device.clone(), + extent, + window.as_raw(), + self.display, + )?; + + entry.insert(ctx); + } + _ => {} + } + + Ok(()) + } +} mod debug { use ash::vk; use tracing::{event, Level}; - unsafe fn str_from_raw_parts<'a>(str: *const i8) -> std::borrow::Cow<'a, str> { + unsafe fn str_from_raw_parts<'a>( + str: *const i8, + ) -> std::borrow::Cow<'a, str> { use std::{borrow::Cow, ffi}; if str.is_null() { Cow::from("") @@ -1124,7 +1526,8 @@ mod debug { let callback_data = *callback_data; let message_id_number = callback_data.message_id_number; - let message_id_name = str_from_raw_parts(callback_data.p_message_id_name); + let message_id_name = + str_from_raw_parts(callback_data.p_message_id_name); let message = str_from_raw_parts(callback_data.p_message); match message_severity { @@ -1186,7 +1589,8 @@ pub mod utils { && lhs.dual_src_blend == rhs.dual_src_blend && lhs.logic_op == rhs.logic_op && lhs.multi_draw_indirect == rhs.multi_draw_indirect - && lhs.draw_indirect_first_instance == rhs.draw_indirect_first_instance + && lhs.draw_indirect_first_instance + == rhs.draw_indirect_first_instance && lhs.depth_clamp == rhs.depth_clamp && lhs.depth_bias_clamp == rhs.depth_bias_clamp && lhs.fill_mode_non_solid == rhs.fill_mode_non_solid @@ -1197,18 +1601,23 @@ pub mod utils { && lhs.multi_viewport == rhs.multi_viewport && lhs.sampler_anisotropy == rhs.sampler_anisotropy && lhs.texture_compression_etc2 == rhs.texture_compression_etc2 - && lhs.texture_compression_astc_ldr == rhs.texture_compression_astc_ldr + && lhs.texture_compression_astc_ldr + == rhs.texture_compression_astc_ldr && lhs.texture_compression_bc == rhs.texture_compression_bc && lhs.occlusion_query_precise == rhs.occlusion_query_precise && lhs.pipeline_statistics_query == rhs.pipeline_statistics_query - && lhs.vertex_pipeline_stores_and_atomics == rhs.vertex_pipeline_stores_and_atomics - && lhs.fragment_stores_and_atomics == rhs.fragment_stores_and_atomics + && lhs.vertex_pipeline_stores_and_atomics + == rhs.vertex_pipeline_stores_and_atomics + && lhs.fragment_stores_and_atomics + == rhs.fragment_stores_and_atomics && lhs.shader_tessellation_and_geometry_point_size == rhs.shader_tessellation_and_geometry_point_size - && lhs.shader_image_gather_extended == rhs.shader_image_gather_extended + && lhs.shader_image_gather_extended + == rhs.shader_image_gather_extended && lhs.shader_storage_image_extended_formats == rhs.shader_storage_image_extended_formats - && lhs.shader_storage_image_multisample == rhs.shader_storage_image_multisample + && lhs.shader_storage_image_multisample + == rhs.shader_storage_image_multisample && lhs.shader_storage_image_read_without_format == rhs.shader_storage_image_read_without_format && lhs.shader_storage_image_write_without_format @@ -1252,8 +1661,10 @@ pub mod utils { && lhs.storage_input_output16 == rhs.storage_input_output16 && lhs.multiview == rhs.multiview && lhs.multiview_geometry_shader == rhs.multiview_geometry_shader - && lhs.multiview_tessellation_shader == rhs.multiview_tessellation_shader - && lhs.variable_pointers_storage_buffer == rhs.variable_pointers_storage_buffer + && lhs.multiview_tessellation_shader + == rhs.multiview_tessellation_shader + && lhs.variable_pointers_storage_buffer + == rhs.variable_pointers_storage_buffer && lhs.variable_pointers == rhs.variable_pointers && lhs.protected_memory == rhs.protected_memory && lhs.sampler_ycbcr_conversion == rhs.sampler_ycbcr_conversion @@ -1270,8 +1681,10 @@ pub mod utils { && lhs.uniform_and_storage_buffer8_bit_access == rhs.uniform_and_storage_buffer8_bit_access && lhs.storage_push_constant8 == rhs.storage_push_constant8 - && lhs.shader_buffer_int64_atomics == rhs.shader_buffer_int64_atomics - && lhs.shader_shared_int64_atomics == rhs.shader_shared_int64_atomics + && lhs.shader_buffer_int64_atomics + == rhs.shader_buffer_int64_atomics + && lhs.shader_shared_int64_atomics + == rhs.shader_shared_int64_atomics && lhs.shader_float16 == rhs.shader_float16 && lhs.shader_int8 == rhs.shader_int8 && lhs.descriptor_indexing == rhs.descriptor_indexing @@ -1309,28 +1722,37 @@ pub mod utils { == rhs.descriptor_binding_storage_texel_buffer_update_after_bind && lhs.descriptor_binding_update_unused_while_pending == rhs.descriptor_binding_update_unused_while_pending - && lhs.descriptor_binding_partially_bound == rhs.descriptor_binding_partially_bound + && lhs.descriptor_binding_partially_bound + == rhs.descriptor_binding_partially_bound && lhs.descriptor_binding_variable_descriptor_count == rhs.descriptor_binding_variable_descriptor_count && lhs.runtime_descriptor_array == rhs.runtime_descriptor_array && lhs.sampler_filter_minmax == rhs.sampler_filter_minmax && lhs.scalar_block_layout == rhs.scalar_block_layout && lhs.imageless_framebuffer == rhs.imageless_framebuffer - && lhs.uniform_buffer_standard_layout == rhs.uniform_buffer_standard_layout - && lhs.shader_subgroup_extended_types == rhs.shader_subgroup_extended_types - && lhs.separate_depth_stencil_layouts == rhs.separate_depth_stencil_layouts + && lhs.uniform_buffer_standard_layout + == rhs.uniform_buffer_standard_layout + && lhs.shader_subgroup_extended_types + == rhs.shader_subgroup_extended_types + && lhs.separate_depth_stencil_layouts + == rhs.separate_depth_stencil_layouts && lhs.host_query_reset == rhs.host_query_reset && lhs.timeline_semaphore == rhs.timeline_semaphore && lhs.buffer_device_address == rhs.buffer_device_address - && lhs.buffer_device_address_capture_replay == rhs.buffer_device_address_capture_replay - && lhs.buffer_device_address_multi_device == rhs.buffer_device_address_multi_device + && lhs.buffer_device_address_capture_replay + == rhs.buffer_device_address_capture_replay + && lhs.buffer_device_address_multi_device + == rhs.buffer_device_address_multi_device && lhs.vulkan_memory_model == rhs.vulkan_memory_model - && lhs.vulkan_memory_model_device_scope == rhs.vulkan_memory_model_device_scope + && lhs.vulkan_memory_model_device_scope + == rhs.vulkan_memory_model_device_scope && lhs.vulkan_memory_model_availability_visibility_chains == rhs.vulkan_memory_model_availability_visibility_chains - && lhs.shader_output_viewport_index == rhs.shader_output_viewport_index + && lhs.shader_output_viewport_index + == rhs.shader_output_viewport_index && lhs.shader_output_layer == rhs.shader_output_layer - && lhs.subgroup_broadcast_dynamic_id == rhs.subgroup_broadcast_dynamic_id + && lhs.subgroup_broadcast_dynamic_id + == rhs.subgroup_broadcast_dynamic_id } pub fn eq_device_features13( @@ -1341,14 +1763,18 @@ pub mod utils { && lhs.inline_uniform_block == rhs.inline_uniform_block && lhs.descriptor_binding_inline_uniform_block_update_after_bind == rhs.descriptor_binding_inline_uniform_block_update_after_bind - && lhs.pipeline_creation_cache_control == rhs.pipeline_creation_cache_control + && lhs.pipeline_creation_cache_control + == rhs.pipeline_creation_cache_control && lhs.private_data == rhs.private_data - && lhs.shader_demote_to_helper_invocation == rhs.shader_demote_to_helper_invocation - && lhs.shader_terminate_invocation == rhs.shader_terminate_invocation + && lhs.shader_demote_to_helper_invocation + == rhs.shader_demote_to_helper_invocation + && lhs.shader_terminate_invocation + == rhs.shader_terminate_invocation && lhs.subgroup_size_control == rhs.subgroup_size_control && lhs.compute_full_subgroups == rhs.compute_full_subgroups && lhs.synchronization2 == rhs.synchronization2 - && lhs.texture_compression_astc_hdr == rhs.texture_compression_astc_hdr + && lhs.texture_compression_astc_hdr + == rhs.texture_compression_astc_hdr && lhs.shader_zero_initialize_workgroup_memory == rhs.shader_zero_initialize_workgroup_memory && lhs.dynamic_rendering == rhs.dynamic_rendering @@ -1362,30 +1788,48 @@ pub mod utils { ) -> vk::PhysicalDeviceFeatures { use core::ops::BitAnd; vk::PhysicalDeviceFeatures { - robust_buffer_access: lhs.robust_buffer_access.bitand(&rhs.robust_buffer_access), + robust_buffer_access: lhs + .robust_buffer_access + .bitand(&rhs.robust_buffer_access), full_draw_index_uint32: lhs .full_draw_index_uint32 .bitand(&rhs.full_draw_index_uint32), - image_cube_array: lhs.image_cube_array.bitand(&rhs.image_cube_array), - independent_blend: lhs.independent_blend.bitand(&rhs.independent_blend), + image_cube_array: lhs + .image_cube_array + .bitand(&rhs.image_cube_array), + independent_blend: lhs + .independent_blend + .bitand(&rhs.independent_blend), geometry_shader: lhs.geometry_shader.bitand(&rhs.geometry_shader), - tessellation_shader: lhs.tessellation_shader.bitand(&rhs.tessellation_shader), - sample_rate_shading: lhs.sample_rate_shading.bitand(&rhs.sample_rate_shading), + tessellation_shader: lhs + .tessellation_shader + .bitand(&rhs.tessellation_shader), + sample_rate_shading: lhs + .sample_rate_shading + .bitand(&rhs.sample_rate_shading), dual_src_blend: lhs.dual_src_blend.bitand(&rhs.dual_src_blend), logic_op: lhs.logic_op.bitand(&rhs.logic_op), - multi_draw_indirect: lhs.multi_draw_indirect.bitand(&rhs.multi_draw_indirect), + multi_draw_indirect: lhs + .multi_draw_indirect + .bitand(&rhs.multi_draw_indirect), draw_indirect_first_instance: lhs .draw_indirect_first_instance .bitand(&rhs.draw_indirect_first_instance), depth_clamp: lhs.depth_clamp.bitand(&rhs.depth_clamp), - depth_bias_clamp: lhs.depth_bias_clamp.bitand(&rhs.depth_bias_clamp), - fill_mode_non_solid: lhs.fill_mode_non_solid.bitand(&rhs.fill_mode_non_solid), + depth_bias_clamp: lhs + .depth_bias_clamp + .bitand(&rhs.depth_bias_clamp), + fill_mode_non_solid: lhs + .fill_mode_non_solid + .bitand(&rhs.fill_mode_non_solid), depth_bounds: lhs.depth_bounds.bitand(&rhs.depth_bounds), wide_lines: lhs.wide_lines.bitand(&rhs.wide_lines), large_points: lhs.large_points.bitand(&rhs.large_points), alpha_to_one: lhs.alpha_to_one.bitand(&rhs.alpha_to_one), multi_viewport: lhs.multi_viewport.bitand(&rhs.multi_viewport), - sampler_anisotropy: lhs.sampler_anisotropy.bitand(&rhs.sampler_anisotropy), + sampler_anisotropy: lhs + .sampler_anisotropy + .bitand(&rhs.sampler_anisotropy), texture_compression_etc2: lhs .texture_compression_etc2 .bitand(&rhs.texture_compression_etc2), @@ -1437,8 +1881,12 @@ pub mod utils { shader_storage_image_array_dynamic_indexing: lhs .shader_storage_image_array_dynamic_indexing .bitand(&rhs.shader_storage_image_array_dynamic_indexing), - shader_clip_distance: lhs.shader_clip_distance.bitand(&rhs.shader_clip_distance), - shader_cull_distance: lhs.shader_cull_distance.bitand(&rhs.shader_cull_distance), + shader_clip_distance: lhs + .shader_clip_distance + .bitand(&rhs.shader_clip_distance), + shader_cull_distance: lhs + .shader_cull_distance + .bitand(&rhs.shader_cull_distance), shader_float64: lhs.shader_float64.bitand(&rhs.shader_float64), shader_int64: lhs.shader_int64.bitand(&rhs.shader_int64), shader_int16: lhs.shader_int16.bitand(&rhs.shader_int16), @@ -1476,7 +1924,9 @@ pub mod utils { variable_multisample_rate: lhs .variable_multisample_rate .bitand(&rhs.variable_multisample_rate), - inherited_queries: lhs.inherited_queries.bitand(&rhs.inherited_queries), + inherited_queries: lhs + .inherited_queries + .bitand(&rhs.inherited_queries), } } @@ -1508,8 +1958,12 @@ pub mod utils { variable_pointers_storage_buffer: lhs .variable_pointers_storage_buffer .bitand(&rhs.variable_pointers_storage_buffer), - variable_pointers: lhs.variable_pointers.bitand(&rhs.variable_pointers), - protected_memory: lhs.protected_memory.bitand(&rhs.protected_memory), + variable_pointers: lhs + .variable_pointers + .bitand(&rhs.variable_pointers), + protected_memory: lhs + .protected_memory + .bitand(&rhs.protected_memory), sampler_ycbcr_conversion: lhs .sampler_ycbcr_conversion .bitand(&rhs.sampler_ycbcr_conversion),