#![feature( negative_impls, map_try_insert, debug_closure_helpers, slice_partition_dedup )] use std::{collections::HashMap, fmt::Debug, path::PathBuf, sync::Arc}; use raw_window_handle::{RawDisplayHandle, RawWindowHandle}; use ash::{ ext, prelude::VkResult, vk::{self, SurfaceCapabilitiesKHR}, }; use dyn_clone::DynClone; pub use ash; mod buffers; pub mod commands; mod debug; pub mod device; #[path = "egui.rs"] mod egui_pass; mod images; pub mod instance; mod pipeline; pub mod render_graph; pub mod rendering; pub mod swapchain; pub mod sync; mod text; pub mod util; use device::{Device, DeviceOwned}; mod texture { use std::{collections::BTreeMap, sync::Arc}; use crate::{Device, def_monotonic_id, images::Image}; def_monotonic_id!(pub TextureId); pub struct TextureManager { pub textures: BTreeMap>, #[allow(unused)] dev: Device, } impl TextureManager { pub fn new(dev: Device) -> Self { Self { dev, textures: BTreeMap::new(), } } pub fn insert_image(&mut self, image: Arc) -> TextureId { let id = TextureId::new(); self.textures.insert(id, image); id } pub fn insert_image_with_id(&mut self, id: TextureId, image: Arc) { self.textures.insert(id, image); } pub fn remove_texture(&mut self, id: TextureId) -> Option> { self.textures.remove(&id) } pub fn get_texture(&self, id: TextureId) -> Option> { self.textures.get(&id).cloned() } } } use util::Rgba; #[derive(Debug, thiserror::Error)] pub enum Error { #[error("No Physical Device found for this instance.")] NoAdapter, #[error("Swapchain suboptimal.")] SuboptimalSwapchain, #[error(transparent)] LoadingError(#[from] ash::LoadingError), #[error(transparent)] Result(#[from] ash::vk::Result), #[error(transparent)] CStrError(#[from] core::ffi::c_str::FromBytesUntilNulError), #[error(transparent)] Utf8Error(#[from] core::str::Utf8Error), #[error(transparent)] NulError(#[from] std::ffi::NulError), #[error(transparent)] GpuAllocatorError(#[from] gpu_allocator::AllocationError), #[error("No Physical Device found.")] NoPhysicalDevice, #[error(transparent)] Io(#[from] std::io::Error), #[error( "Image dimensions ({width}x{height}) exceed the maximum allowed size of {max_size}x{max_size}." )] ImageTooLarge { width: u32, height: u32, max_size: u32, }, #[error("Image dimensions cannot be zero.")] ImageZeroSized, #[error("Incompatible image view kind {view_kind:?} for image kind {image_kind:?}.")] IncompatibleImageViewKind { view_kind: vk::ImageViewType, image_kind: vk::ImageType, }, #[error("Asset missing at path {0:?}")] AssetMissing(PathBuf), #[error("Unspecified Error")] Unspecified, #[error("BEEP BOOP create an error variant for {0} BEEP BOOP")] Todo(&'static str), } pub type Result = core::result::Result; #[derive(Debug, Clone)] #[allow(dead_code)] struct DeviceExtension<'a> { name: &'a core::ffi::CStr, version: u32, } /// returns true if lhs and rhs have the same name and lhs spec_version is less /// than or equal to rhs spec_version #[allow(dead_code)] fn compatible_extension_properties( lhs: &vk::ExtensionProperties, rhs: &vk::ExtensionProperties, ) -> bool { let Some(lhs_name) = lhs.extension_name_as_c_str().ok() else { return false; }; let Some(rhs_name) = rhs.extension_name_as_c_str().ok() else { return false; }; if lhs_name == rhs_name { lhs.spec_version <= rhs.spec_version } else { false } } pub mod queue; pub trait ExtendsDeviceFeatures2Debug: vk::ExtendsPhysicalDeviceFeatures2 + Debug + Send + Sync { } pub trait ExtendsDeviceProperties2Debug: vk::ExtendsPhysicalDeviceProperties2 + Debug + DynClone + Send + Sync { } impl ExtendsDeviceFeatures2Debug for T { } impl ExtendsDeviceProperties2Debug for T { } #[derive(Debug)] pub struct PhysicalDeviceInfo { pub pdev: vk::PhysicalDevice, pub properties: PhysicalDeviceProperties, pub features: PhysicalDeviceFeatures, } #[derive(Debug)] pub struct SurfaceCapabilities { pub capabilities: SurfaceCapabilitiesKHR, /// The minimum number of images that must be present in the swapchain for /// the surface for any present mode supported by the surface. pub min_image_count: u32, pub formats: Vec, pub present_modes: Vec, } #[derive(Default, Debug)] pub struct PhysicalDeviceFeatures { pub core: vk::PhysicalDeviceFeatures, pub core11: vk::PhysicalDeviceVulkan11Features<'static>, pub core12: vk::PhysicalDeviceVulkan12Features<'static>, pub core13: vk::PhysicalDeviceVulkan13Features<'static>, pub mesh_shader: Option>, } impl PhysicalDeviceFeatures { pub fn push_to_device_create_info<'a>( &'a mut self, mut create_info: vk::DeviceCreateInfo<'a>, ) -> vk::DeviceCreateInfo<'a> { create_info = create_info .enabled_features(&self.core) .push_next(&mut self.core11) .push_next(&mut self.core12) .push_next(&mut self.core13); if let Some(mesh_shader) = &mut self.mesh_shader { create_info = create_info.push_next(mesh_shader); } create_info } pub fn superset_of(&self, other: &PhysicalDeviceFeatures) -> bool { fn core_superset_of( a: &vk::PhysicalDeviceFeatures, b: &vk::PhysicalDeviceFeatures, ) -> bool { (b.robust_buffer_access == vk::FALSE || a.robust_buffer_access != b.robust_buffer_access) && (b.full_draw_index_uint32 == vk::FALSE || a.full_draw_index_uint32 != b.full_draw_index_uint32) && (b.image_cube_array == vk::FALSE || a.image_cube_array != b.image_cube_array) && (b.independent_blend == vk::FALSE || a.independent_blend != b.independent_blend) && (b.geometry_shader == vk::FALSE || a.geometry_shader != b.geometry_shader) && (b.tessellation_shader == vk::FALSE || a.tessellation_shader != b.tessellation_shader) && (b.sample_rate_shading == vk::FALSE || a.sample_rate_shading != b.sample_rate_shading) && (b.dual_src_blend == vk::FALSE || a.dual_src_blend != b.dual_src_blend) && (b.logic_op == vk::FALSE || a.logic_op != b.logic_op) && (b.multi_draw_indirect == vk::FALSE || a.multi_draw_indirect != b.multi_draw_indirect) && (b.draw_indirect_first_instance == vk::FALSE || a.draw_indirect_first_instance != b.draw_indirect_first_instance) && (b.depth_clamp == vk::FALSE || a.depth_clamp != b.depth_clamp) && (b.depth_bias_clamp == vk::FALSE || a.depth_bias_clamp != b.depth_bias_clamp) && (b.fill_mode_non_solid == vk::FALSE || a.fill_mode_non_solid != b.fill_mode_non_solid) && (b.depth_bounds == vk::FALSE || a.depth_bounds != b.depth_bounds) && (b.wide_lines == vk::FALSE || a.wide_lines != b.wide_lines) && (b.large_points == vk::FALSE || a.large_points != b.large_points) && (b.alpha_to_one == vk::FALSE || a.alpha_to_one != b.alpha_to_one) && (b.multi_viewport == vk::FALSE || a.multi_viewport != b.multi_viewport) && (b.sampler_anisotropy == vk::FALSE || a.sampler_anisotropy != b.sampler_anisotropy) && (b.texture_compression_etc2 == vk::FALSE || a.texture_compression_etc2 != b.texture_compression_etc2) && (b.texture_compression_astc_ldr == vk::FALSE || a.texture_compression_astc_ldr != b.texture_compression_astc_ldr) && (b.texture_compression_bc == vk::FALSE || a.texture_compression_bc != b.texture_compression_bc) && (b.occlusion_query_precise == vk::FALSE || a.occlusion_query_precise != b.occlusion_query_precise) && (b.pipeline_statistics_query == vk::FALSE || a.pipeline_statistics_query != b.pipeline_statistics_query) && (b.vertex_pipeline_stores_and_atomics == vk::FALSE || a.vertex_pipeline_stores_and_atomics != b.vertex_pipeline_stores_and_atomics) && (b.fragment_stores_and_atomics == vk::FALSE || a.fragment_stores_and_atomics != b.fragment_stores_and_atomics) && (b.shader_tessellation_and_geometry_point_size == vk::FALSE || a.shader_tessellation_and_geometry_point_size != b.shader_tessellation_and_geometry_point_size) && (b.shader_image_gather_extended == vk::FALSE || a.shader_image_gather_extended != b.shader_image_gather_extended) && (b.shader_storage_image_extended_formats == vk::FALSE || a.shader_storage_image_extended_formats != b.shader_storage_image_extended_formats) && (b.shader_storage_image_multisample == vk::FALSE || a.shader_storage_image_multisample != b.shader_storage_image_multisample) && (b.shader_storage_image_read_without_format == vk::FALSE || a.shader_storage_image_read_without_format != b.shader_storage_image_read_without_format) && (b.shader_storage_image_write_without_format == vk::FALSE || a.shader_storage_image_write_without_format != b.shader_storage_image_write_without_format) && (b.shader_uniform_buffer_array_dynamic_indexing == vk::FALSE || a.shader_uniform_buffer_array_dynamic_indexing != b.shader_uniform_buffer_array_dynamic_indexing) && (b.shader_sampled_image_array_dynamic_indexing == vk::FALSE || a.shader_sampled_image_array_dynamic_indexing != b.shader_sampled_image_array_dynamic_indexing) && (b.shader_storage_buffer_array_dynamic_indexing == vk::FALSE || a.shader_storage_buffer_array_dynamic_indexing != b.shader_storage_buffer_array_dynamic_indexing) && (b.shader_storage_image_array_dynamic_indexing == vk::FALSE || a.shader_storage_image_array_dynamic_indexing != b.shader_storage_image_array_dynamic_indexing) && (b.shader_clip_distance == vk::FALSE || a.shader_clip_distance != b.shader_clip_distance) && (b.shader_cull_distance == vk::FALSE || a.shader_cull_distance != b.shader_cull_distance) && (b.shader_float64 == vk::FALSE || a.shader_float64 != b.shader_float64) && (b.shader_int64 == vk::FALSE || a.shader_int64 != b.shader_int64) && (b.shader_int16 == vk::FALSE || a.shader_int16 != b.shader_int16) && (b.shader_resource_residency == vk::FALSE || a.shader_resource_residency != b.shader_resource_residency) && (b.shader_resource_min_lod == vk::FALSE || a.shader_resource_min_lod != b.shader_resource_min_lod) && (b.sparse_binding == vk::FALSE || a.sparse_binding != b.sparse_binding) && (b.sparse_residency_buffer == vk::FALSE || a.sparse_residency_buffer != b.sparse_residency_buffer) && (b.sparse_residency_image2_d == vk::FALSE || a.sparse_residency_image2_d != b.sparse_residency_image2_d) && (b.sparse_residency_image3_d == vk::FALSE || a.sparse_residency_image3_d != b.sparse_residency_image3_d) && (b.sparse_residency2_samples == vk::FALSE || a.sparse_residency2_samples != b.sparse_residency2_samples) && (b.sparse_residency4_samples == vk::FALSE || a.sparse_residency4_samples != b.sparse_residency4_samples) && (b.sparse_residency8_samples == vk::FALSE || a.sparse_residency8_samples != b.sparse_residency8_samples) && (b.sparse_residency16_samples == vk::FALSE || a.sparse_residency16_samples != b.sparse_residency16_samples) && (b.sparse_residency_aliased == vk::FALSE || a.sparse_residency_aliased != b.sparse_residency_aliased) && (b.variable_multisample_rate == vk::FALSE || a.variable_multisample_rate != b.variable_multisample_rate) && (b.inherited_queries == vk::FALSE || a.inherited_queries != b.inherited_queries) } fn core11_superset_of( a: &vk::PhysicalDeviceVulkan11Features, b: &vk::PhysicalDeviceVulkan11Features, ) -> bool { (b.storage_buffer16_bit_access == vk::FALSE || a.storage_buffer16_bit_access != b.storage_buffer16_bit_access) && (b.uniform_and_storage_buffer16_bit_access == vk::FALSE || a.uniform_and_storage_buffer16_bit_access != b.uniform_and_storage_buffer16_bit_access) && (b.storage_push_constant16 == vk::FALSE || a.storage_push_constant16 != b.storage_push_constant16) && (b.storage_input_output16 == vk::FALSE || a.storage_input_output16 != b.storage_input_output16) && (b.multiview == vk::FALSE || a.multiview != b.multiview) && (b.multiview_geometry_shader == vk::FALSE || a.multiview_geometry_shader != b.multiview_geometry_shader) && (b.multiview_tessellation_shader == vk::FALSE || a.multiview_tessellation_shader != b.multiview_tessellation_shader) && (b.variable_pointers_storage_buffer == vk::FALSE || a.variable_pointers_storage_buffer != b.variable_pointers_storage_buffer) && (b.variable_pointers == vk::FALSE || a.variable_pointers != b.variable_pointers) && (b.protected_memory == vk::FALSE || a.protected_memory != b.protected_memory) && (b.sampler_ycbcr_conversion == vk::FALSE || a.sampler_ycbcr_conversion != b.sampler_ycbcr_conversion) && (b.shader_draw_parameters == vk::FALSE || a.shader_draw_parameters != b.shader_draw_parameters) } fn core12_superset_of( a: &vk::PhysicalDeviceVulkan12Features, b: &vk::PhysicalDeviceVulkan12Features, ) -> bool { (b.sampler_mirror_clamp_to_edge == vk::FALSE || a.sampler_mirror_clamp_to_edge != b.sampler_mirror_clamp_to_edge) && (b.draw_indirect_count == vk::FALSE || a.draw_indirect_count != b.draw_indirect_count) && (b.storage_buffer8_bit_access == vk::FALSE || a.storage_buffer8_bit_access != b.storage_buffer8_bit_access) && (b.uniform_and_storage_buffer8_bit_access == vk::FALSE || a.uniform_and_storage_buffer8_bit_access != b.uniform_and_storage_buffer8_bit_access) && (b.storage_push_constant8 == vk::FALSE || a.storage_push_constant8 != b.storage_push_constant8) && (b.shader_buffer_int64_atomics == vk::FALSE || a.shader_buffer_int64_atomics != b.shader_buffer_int64_atomics) && (b.shader_shared_int64_atomics == vk::FALSE || a.shader_shared_int64_atomics != b.shader_shared_int64_atomics) && (b.shader_float16 == vk::FALSE || a.shader_float16 != b.shader_float16) && (b.shader_int8 == vk::FALSE || a.shader_int8 != b.shader_int8) && (b.descriptor_indexing == vk::FALSE || a.descriptor_indexing != b.descriptor_indexing) && (b.shader_input_attachment_array_dynamic_indexing == vk::FALSE || a.shader_input_attachment_array_dynamic_indexing != b.shader_input_attachment_array_dynamic_indexing) && (b.shader_uniform_texel_buffer_array_dynamic_indexing == vk::FALSE || a.shader_uniform_texel_buffer_array_dynamic_indexing != b.shader_uniform_texel_buffer_array_dynamic_indexing) && (b.shader_storage_texel_buffer_array_dynamic_indexing == vk::FALSE || a.shader_storage_texel_buffer_array_dynamic_indexing != b.shader_storage_texel_buffer_array_dynamic_indexing) && (b.shader_uniform_buffer_array_non_uniform_indexing == vk::FALSE || a.shader_uniform_buffer_array_non_uniform_indexing != b.shader_uniform_buffer_array_non_uniform_indexing) && (b.shader_sampled_image_array_non_uniform_indexing == vk::FALSE || a.shader_sampled_image_array_non_uniform_indexing != b.shader_sampled_image_array_non_uniform_indexing) && (b.shader_storage_buffer_array_non_uniform_indexing == vk::FALSE || a.shader_storage_buffer_array_non_uniform_indexing != b.shader_storage_buffer_array_non_uniform_indexing) && (b.shader_storage_image_array_non_uniform_indexing == vk::FALSE || a.shader_storage_image_array_non_uniform_indexing != b.shader_storage_image_array_non_uniform_indexing) && (b.shader_input_attachment_array_non_uniform_indexing == vk::FALSE || a.shader_input_attachment_array_non_uniform_indexing != b.shader_input_attachment_array_non_uniform_indexing) && (b.shader_uniform_texel_buffer_array_non_uniform_indexing == vk::FALSE || a.shader_uniform_texel_buffer_array_non_uniform_indexing != b.shader_uniform_texel_buffer_array_non_uniform_indexing) && (b.shader_storage_texel_buffer_array_non_uniform_indexing == vk::FALSE || a.shader_storage_texel_buffer_array_non_uniform_indexing != b.shader_storage_texel_buffer_array_non_uniform_indexing) && (b.descriptor_binding_uniform_buffer_update_after_bind == vk::FALSE || a.descriptor_binding_uniform_buffer_update_after_bind != b.descriptor_binding_uniform_buffer_update_after_bind) && (b.descriptor_binding_sampled_image_update_after_bind == vk::FALSE || a.descriptor_binding_sampled_image_update_after_bind != b.descriptor_binding_sampled_image_update_after_bind) && (b.descriptor_binding_storage_image_update_after_bind == vk::FALSE || a.descriptor_binding_storage_image_update_after_bind != b.descriptor_binding_storage_image_update_after_bind) && (b.descriptor_binding_storage_buffer_update_after_bind == vk::FALSE || a.descriptor_binding_storage_buffer_update_after_bind != b.descriptor_binding_storage_buffer_update_after_bind) && (b.descriptor_binding_uniform_texel_buffer_update_after_bind == vk::FALSE || a.descriptor_binding_uniform_texel_buffer_update_after_bind != b.descriptor_binding_uniform_texel_buffer_update_after_bind) && (b.descriptor_binding_storage_texel_buffer_update_after_bind == vk::FALSE || a.descriptor_binding_storage_texel_buffer_update_after_bind != b.descriptor_binding_storage_texel_buffer_update_after_bind) && (b.descriptor_binding_update_unused_while_pending == vk::FALSE || a.descriptor_binding_update_unused_while_pending != b.descriptor_binding_update_unused_while_pending) && (b.descriptor_binding_partially_bound == vk::FALSE || a.descriptor_binding_partially_bound != b.descriptor_binding_partially_bound) && (b.descriptor_binding_variable_descriptor_count == vk::FALSE || a.descriptor_binding_variable_descriptor_count != b.descriptor_binding_variable_descriptor_count) && (b.runtime_descriptor_array == vk::FALSE || a.runtime_descriptor_array != b.runtime_descriptor_array) && (b.sampler_filter_minmax == vk::FALSE || a.sampler_filter_minmax != b.sampler_filter_minmax) && (b.scalar_block_layout == vk::FALSE || a.scalar_block_layout != b.scalar_block_layout) && (b.imageless_framebuffer == vk::FALSE || a.imageless_framebuffer != b.imageless_framebuffer) && (b.uniform_buffer_standard_layout == vk::FALSE || a.uniform_buffer_standard_layout != b.uniform_buffer_standard_layout) && (b.shader_subgroup_extended_types == vk::FALSE || a.shader_subgroup_extended_types != b.shader_subgroup_extended_types) && (b.separate_depth_stencil_layouts == vk::FALSE || a.separate_depth_stencil_layouts != b.separate_depth_stencil_layouts) && (b.host_query_reset == vk::FALSE || a.host_query_reset != b.host_query_reset) && (b.timeline_semaphore == vk::FALSE || a.timeline_semaphore != b.timeline_semaphore) && (b.buffer_device_address == vk::FALSE || a.buffer_device_address != b.buffer_device_address) && (b.buffer_device_address_capture_replay == vk::FALSE || a.buffer_device_address_capture_replay != b.buffer_device_address_capture_replay) && (b.buffer_device_address_multi_device == vk::FALSE || a.buffer_device_address_multi_device != b.buffer_device_address_multi_device) && (b.vulkan_memory_model == vk::FALSE || a.vulkan_memory_model != b.vulkan_memory_model) && (b.vulkan_memory_model_device_scope == vk::FALSE || a.vulkan_memory_model_device_scope != b.vulkan_memory_model_device_scope) && (b.vulkan_memory_model_availability_visibility_chains == vk::FALSE || a.vulkan_memory_model_availability_visibility_chains != b.vulkan_memory_model_availability_visibility_chains) && (b.shader_output_viewport_index == vk::FALSE || a.shader_output_viewport_index != b.shader_output_viewport_index) && (b.shader_output_layer == vk::FALSE || a.shader_output_layer != b.shader_output_layer) && (b.subgroup_broadcast_dynamic_id == vk::FALSE || a.subgroup_broadcast_dynamic_id != b.subgroup_broadcast_dynamic_id) } fn core13_superset_of( a: &vk::PhysicalDeviceVulkan13Features, b: &vk::PhysicalDeviceVulkan13Features, ) -> bool { (b.robust_image_access == vk::FALSE || a.robust_image_access != b.robust_image_access) && (b.inline_uniform_block == vk::FALSE || a.inline_uniform_block != b.inline_uniform_block) && (b.descriptor_binding_inline_uniform_block_update_after_bind == vk::FALSE || a.descriptor_binding_inline_uniform_block_update_after_bind != b.descriptor_binding_inline_uniform_block_update_after_bind) && (b.pipeline_creation_cache_control == vk::FALSE || a.pipeline_creation_cache_control != b.pipeline_creation_cache_control) && (b.private_data == vk::FALSE || a.private_data != b.private_data) && (b.shader_demote_to_helper_invocation == vk::FALSE || a.shader_demote_to_helper_invocation != b.shader_demote_to_helper_invocation) && (b.shader_terminate_invocation == vk::FALSE || a.shader_terminate_invocation != b.shader_terminate_invocation) && (b.subgroup_size_control == vk::FALSE || a.subgroup_size_control != b.subgroup_size_control) && (b.compute_full_subgroups == vk::FALSE || a.compute_full_subgroups != b.compute_full_subgroups) && (b.synchronization2 == vk::FALSE || a.synchronization2 != b.synchronization2) && (b.texture_compression_astc_hdr == vk::FALSE || a.texture_compression_astc_hdr != b.texture_compression_astc_hdr) && (b.shader_zero_initialize_workgroup_memory == vk::FALSE || a.shader_zero_initialize_workgroup_memory != b.shader_zero_initialize_workgroup_memory) && (b.dynamic_rendering == vk::FALSE || a.dynamic_rendering != b.dynamic_rendering) && (b.shader_integer_dot_product == vk::FALSE || a.shader_integer_dot_product != b.shader_integer_dot_product) && (b.maintenance4 == vk::FALSE || a.maintenance4 != b.maintenance4) } fn mesh_shader_superset_of( a: &vk::PhysicalDeviceMeshShaderFeaturesEXT, b: &vk::PhysicalDeviceMeshShaderFeaturesEXT, ) -> bool { (b.task_shader == vk::FALSE || a.task_shader != b.task_shader) && (b.mesh_shader == vk::FALSE || a.mesh_shader != b.mesh_shader) && (b.multiview_mesh_shader == vk::FALSE || a.multiview_mesh_shader != b.multiview_mesh_shader) && (b.primitive_fragment_shading_rate_mesh_shader == vk::FALSE || a.primitive_fragment_shading_rate_mesh_shader != b.primitive_fragment_shading_rate_mesh_shader) && (b.mesh_shader_queries == vk::FALSE || a.mesh_shader_queries != b.mesh_shader_queries) } core_superset_of(&self.core, &other.core) && core11_superset_of(&self.core11, &other.core11) && core12_superset_of(&self.core12, &other.core12) && core13_superset_of(&self.core13, &other.core13) && match (&self.mesh_shader, &other.mesh_shader) { (Some(a), Some(b)) => mesh_shader_superset_of(a, b), (None, Some(_)) => false, _ => true, } } } #[derive(Debug, Default)] pub struct PhysicalDeviceProperties { /// Extensions supported by the device, as reported by `enumerate_device_extension_properties`. supported_extensions: Vec, /// Vulkan 1.0 properties. core: vk::PhysicalDeviceProperties, /// Vulkan 1.1 properties. core11: vk::PhysicalDeviceVulkan11Properties<'static>, /// Vulkan 1.2 properties. core12: vk::PhysicalDeviceVulkan12Properties<'static>, /// Vulkan 1.3 properties. core13: vk::PhysicalDeviceVulkan13Properties<'static>, /// Mesh shader properties from the `VK_EXT_mesh_shader` extension, if supported. mesh_shader: Option>, /// Memory properties of the device, as reported by `get_physical_device_memory_properties`. memory_properties: vk::PhysicalDeviceMemoryProperties, /// The API version supported by the device. device_api_version: u32, } impl PhysicalDeviceProperties { pub(crate) fn get_device_local_memory_count(&self) -> u64 { self.memory_properties .memory_heaps .iter() .filter(|heap| heap.flags.contains(vk::MemoryHeapFlags::DEVICE_LOCAL)) .map(|heap| heap.size) .sum::() } } fn get_physical_device_features( instance: &InstanceInner, pdev: vk::PhysicalDevice, properties: &PhysicalDeviceProperties, ) -> PhysicalDeviceFeatures { let mut features = PhysicalDeviceFeatures::default(); let mut features2 = vk::PhysicalDeviceFeatures2::default(); features2 = features2 .push_next(&mut features.core11) .push_next(&mut features.core12) .push_next(&mut features.core13); if properties.supports_extension(make_extension!(ext::mesh_shader)) { features2 = features2.push_next( features .mesh_shader .insert(vk::PhysicalDeviceMeshShaderFeaturesEXT::default()), ); } unsafe { instance .raw .get_physical_device_features2(pdev, &mut features2); } features.core = features2.features; features } fn get_physical_device_properties( instance: &InstanceInner, pdev: vk::PhysicalDevice, ) -> Result { let mut props = PhysicalDeviceProperties::default(); props.core = unsafe { instance.raw.get_physical_device_properties(pdev) }; props.device_api_version = props.core.api_version; props.supported_extensions = unsafe { instance.raw.enumerate_device_extension_properties(pdev)? }; props.memory_properties = unsafe { instance.raw.get_physical_device_memory_properties(pdev) }; let supports_mesh_shader = props.supports_extension(make_extension!(ext::mesh_shader)); // TODO: fallibly check anything beyond 1.0 let mut props2 = vk::PhysicalDeviceProperties2::default() .push_next(&mut props.core11) .push_next(&mut props.core12) .push_next(&mut props.core13); if supports_mesh_shader { let next = props .mesh_shader .insert(vk::PhysicalDeviceMeshShaderPropertiesEXT::default()); props2 = props2.push_next(next); } unsafe { instance .raw .get_physical_device_properties2(pdev, &mut props2); } Ok(props) } #[allow(dead_code)] pub(crate) fn extension_intersection<'a>( supported: &'a [vk::ExtensionProperties], required: &[Extension<'a>], ) -> Vec { supported .iter() .filter(|ext| { required.iter().any(|req| { ext.extension_name_as_c_str() == Ok(req.name) && ext.spec_version >= req.version }) }) .cloned() .collect() } impl PhysicalDeviceProperties { pub(crate) fn supports_extension(&self, e: Extension) -> bool { self.supported_extensions .iter() .any(|ext| ext.extension_name_as_c_str() == Ok(e.name) && ext.spec_version >= e.version) } } pub(crate) use instance::DebugUtils; pub use instance::{DebugUtilsCreateInfo, Instance}; pub struct SamplerCache { device: Device, samplers: HashMap, } impl SamplerCache { pub fn new(device: Device) -> SamplerCache { Self { device, samplers: HashMap::new(), } } pub fn get_sampler(&mut self, desc: pipeline::SamplerDesc) -> VkResult { use std::collections::hash_map::Entry; let entry = match self.samplers.entry(desc) { Entry::Occupied(entry) => entry.get().raw(), Entry::Vacant(entry) => { let sampler = pipeline::Sampler::new(self.device.clone(), entry.key())?; entry.insert(sampler).raw() } }; Ok(entry) } } #[derive(Debug)] pub struct EguiState { textures: HashMap, #[allow(unused)] descriptor_pool: pipeline::DescriptorPool, descriptor_set: vk::DescriptorSet, #[allow(unused)] descriptor_layout: pipeline::DescriptorSetLayout, pipeline_layout: Arc, pipeline: Arc, } #[derive(Debug, Clone, Copy)] pub struct EguiTextureInfo { id: texture::TextureId, options: egui::epaint::textures::TextureOptions, } impl EguiTextureInfo { fn as_sampler_desc(&self) -> pipeline::SamplerDesc { let address_mode = match self.options.wrap_mode { egui::TextureWrapMode::ClampToEdge => vk::SamplerAddressMode::CLAMP_TO_EDGE, egui::TextureWrapMode::Repeat => vk::SamplerAddressMode::REPEAT, egui::TextureWrapMode::MirroredRepeat => vk::SamplerAddressMode::MIRRORED_REPEAT, }; pipeline::SamplerDesc { min_filter: match self.options.minification { egui::TextureFilter::Nearest => vk::Filter::NEAREST, egui::TextureFilter::Linear => vk::Filter::LINEAR, }, mag_filter: match self.options.magnification { egui::TextureFilter::Nearest => vk::Filter::NEAREST, egui::TextureFilter::Linear => vk::Filter::LINEAR, }, mipmap_mode: match self.options.mipmap_mode { Some(egui::TextureFilter::Linear) => vk::SamplerMipmapMode::LINEAR, Some(egui::TextureFilter::Nearest) => vk::SamplerMipmapMode::NEAREST, None => Default::default(), }, address_u: address_mode, address_v: address_mode, address_w: address_mode, max_lod: vk::LOD_CLAMP_NONE, ..Default::default() } } } impl EguiState { const TEXTURE_BINDING: u32 = 0; const UNIFORM_BINDING: u32 = 1; pub fn new(device: Device) -> Result { let (descriptor_pool, descriptor_layout, sets) = util::timed("Create Descriptor Set", || { let descriptor_pool = pipeline::DescriptorPool::new( device.clone(), pipeline::DescriptorPoolDesc { flags: vk::DescriptorPoolCreateFlags::UPDATE_AFTER_BIND, name: Some("egui-descriptorpool".into()), sizes: &[ vk::DescriptorPoolSize { ty: vk::DescriptorType::COMBINED_IMAGE_SAMPLER, descriptor_count: 10, }, vk::DescriptorPoolSize { ty: vk::DescriptorType::STORAGE_BUFFER, descriptor_count: 1, }, ], max_sets: 1, }, )?; let descriptor_layout = pipeline::DescriptorSetLayout::new( device.clone(), pipeline::DescriptorSetLayoutDesc { flags: vk::DescriptorSetLayoutCreateFlags::UPDATE_AFTER_BIND_POOL, name: Some("egui-descriptor-layout".into()), bindings: &[ pipeline::DescriptorSetLayoutBindingDesc { binding: Self::TEXTURE_BINDING, count: 10, kind: vk::DescriptorType::COMBINED_IMAGE_SAMPLER, stage: vk::ShaderStageFlags::FRAGMENT, flags: Some( vk::DescriptorBindingFlags::PARTIALLY_BOUND | vk::DescriptorBindingFlags::UPDATE_AFTER_BIND, ), }, pipeline::DescriptorSetLayoutBindingDesc { binding: Self::UNIFORM_BINDING, count: 1, kind: vk::DescriptorType::STORAGE_BUFFER, stage: vk::ShaderStageFlags::FRAGMENT, flags: None, }, ], }, )?; let sets = descriptor_pool.allocate(&[pipeline::DescriptorSetAllocDesc { name: None, layout: &descriptor_layout, }])?; Result::Ok((descriptor_pool, descriptor_layout, sets)) })?; let pipeline_layout = pipeline::PipelineLayout::new( device.clone(), pipeline::PipelineLayoutDesc { descriptor_set_layouts: &[&descriptor_layout], push_constant_ranges: &[vk::PushConstantRange { offset: 0, size: 128, stage_flags: vk::ShaderStageFlags::VERTEX, }], name: Some("egui-pipeline-layout".into()), }, )?; let frag_shader = pipeline::ShaderModule::new_from_path( device.clone(), "crates/renderer/shaders/egui_frag.spv", )?; let vert_shader = pipeline::ShaderModule::new_from_path( device.clone(), "crates/renderer/shaders/egui_vert.spv", )?; let pipeline = pipeline::Pipeline::new_graphics( device.clone(), pipeline::GraphicsPipelineDesc { flags: Default::default(), name: Some("egui-pipeline".into()), shader_stages: &[ pipeline::ShaderStageDesc { flags: vk::PipelineShaderStageCreateFlags::empty(), module: &frag_shader, stage: vk::ShaderStageFlags::FRAGMENT, entry: c"main".into(), }, pipeline::ShaderStageDesc { flags: vk::PipelineShaderStageCreateFlags::empty(), module: &vert_shader, stage: vk::ShaderStageFlags::VERTEX, entry: c"main".into(), }, ], render_pass: None, layout: &pipeline_layout, subpass: None, base_pipeline: None, vertex_input: Some(pipeline::VertexInputState { bindings: &[vk::VertexInputBindingDescription { binding: 0, stride: 20, input_rate: vk::VertexInputRate::VERTEX, }], attributes: &[ vk::VertexInputAttributeDescription { location: 0, binding: 0, format: vk::Format::R32G32_SFLOAT, offset: 0, }, vk::VertexInputAttributeDescription { location: 1, binding: 0, format: vk::Format::R32G32_SFLOAT, offset: 8, }, vk::VertexInputAttributeDescription { location: 2, binding: 0, format: vk::Format::R8G8B8A8_UNORM, offset: 16, }, ], }), input_assembly: Some(pipeline::InputAssemblyState { topology: vk::PrimitiveTopology::TRIANGLE_LIST, primitive_restart: false, }), tessellation: None, viewport: Some(pipeline::ViewportState { num_viewports: 1, num_scissors: 1, ..Default::default() }), rasterization: Some(pipeline::RasterizationState { cull_mode: vk::CullModeFlags::NONE, ..Default::default() }), multisample: Some(pipeline::MultisampleState { ..Default::default() }), depth_stencil: Some(pipeline::DepthStencilState { depth: Some(pipeline::DepthState { write_enable: false, compare_op: Some(vk::CompareOp::LESS), bounds: Some(pipeline::DepthBounds { min: 0.0, max: 1.0 }), }), ..Default::default() }), color_blend: Some(pipeline::ColorBlendState { attachments: &[vk::PipelineColorBlendAttachmentState::default() .color_write_mask(vk::ColorComponentFlags::RGBA) .blend_enable(true) .color_blend_op(vk::BlendOp::ADD) .src_color_blend_factor(vk::BlendFactor::ONE) .dst_color_blend_factor(vk::BlendFactor::ONE_MINUS_SRC_ALPHA) .alpha_blend_op(vk::BlendOp::ADD) .src_alpha_blend_factor(vk::BlendFactor::ONE) .dst_alpha_blend_factor(vk::BlendFactor::ONE_MINUS_SRC_ALPHA)], ..Default::default() }), rendering: Some(pipeline::RenderingState { color_formats: &[vk::Format::R8G8B8A8_UNORM], ..Default::default() }), dynamic: Some(pipeline::DynamicState { dynamic_states: &[vk::DynamicState::VIEWPORT, vk::DynamicState::SCISSOR], ..Default::default() }), }, )?; Ok(Self { textures: HashMap::new(), descriptor_pool, descriptor_layout, descriptor_set: sets[0], pipeline: Arc::new(pipeline), pipeline_layout: Arc::new(pipeline_layout), }) } pub fn lookup_texture(&self, id: egui::epaint::TextureId) -> Option { self.textures.get(&id).map(|entry| entry.id) } } pub struct Renderer2 { pub device: Device, pub samplers: SamplerCache, pub texture_manager: texture::TextureManager, #[allow(unused)] // keep this around because the vulkan device has been created with this // display handle in mind. Might not be necessary. display: RawDisplayHandle, } impl Renderer2 { pub fn new(display: RawDisplayHandle) -> Result { let instance = Instance::new(&InstanceDesc { ..Default::default() })?; let adapter = instance.choose_adapter_default(None, &[], None)?; let device = adapter.create_logical_device( &instance, &[], PhysicalDeviceFeatures { core: vk::PhysicalDeviceFeatures { multi_draw_indirect: vk::TRUE, ..Default::default() }, core11: vk::PhysicalDeviceVulkan11Features { shader_draw_parameters: vk::TRUE, ..Default::default() }, core12: vk::PhysicalDeviceVulkan12Features { descriptor_binding_partially_bound: vk::TRUE, descriptor_binding_sampled_image_update_after_bind: vk::TRUE, runtime_descriptor_array: vk::TRUE, ..Default::default() }, core13: vk::PhysicalDeviceVulkan13Features { synchronization2: vk::TRUE, dynamic_rendering: vk::TRUE, maintenance4: vk::TRUE, ..Default::default() }, ..Default::default() }, Some(display), )?; Ok(Self { samplers: SamplerCache::new(device.clone()), texture_manager: texture::TextureManager::new(device.clone()), display, device, }) } pub fn device(&self) -> &Device { &self.device } pub fn samplers_mut(&mut self) -> &mut SamplerCache { &mut self.samplers } pub fn samplers(&self) -> &SamplerCache { &self.samplers } pub fn texture_manager_mut(&mut self) -> &mut texture::TextureManager { &mut self.texture_manager } pub fn texture_manager(&self) -> &texture::TextureManager { &self.texture_manager } pub fn create_surface( &self, window: RawWindowHandle, extent: vk::Extent2D, ) -> Result { let surface = unsafe { swapchain::Surface::new_from_raw_window_handle( &self.device.instance, self.display, window, )? }; surface.configure( &self.device, swapchain::SwapchainConfiguration { extent, ..Default::default() }, )?; Ok(surface) } pub async fn draw_graph T>( &mut self, surface: &swapchain::Surface, cb: F, ) -> Result { let Some(frame) = surface.acquire_image() else { return Err(Error::SuboptimalSwapchain); }; let (frame, _suboptimal) = frame.await?; let mut rg = render_graph::RenderGraph::new(); let _framebuffer = rg.import_framebuffer(frame.image().clone()); let out = cb(self, &mut rg); let cmds = rg.resolve(self.device.clone())?; let future = cmds.submit( Some((frame.acquire, vk::PipelineStageFlags::TRANSFER)), Some(frame.release), Arc::new(sync::Fence::from_pool(&self.device.pools.fences, None)?), )?; future.await; // window.window.pre_present_notify(); let wait = Some(frame.release); frame.present(wait)?; Ok(out) } } pub use vk::Extent2D; use crate::{ device::Extension, instance::{InstanceDesc, InstanceInner}, }; pub mod utils { #![allow(dead_code)] use ash::vk; pub trait SplitCollect: Iterator { fn collect2(self, mut pred: F) -> (Vec, Vec) where Self: Sized, F: FnMut(&Self::Item) -> bool, { let mut left = Vec::new(); let mut right = Vec::new(); for item in self { if pred(&item) { left.push(item); } else { right.push(item); } } (left, right) } } pub fn eq_device_features10( lhs: &vk::PhysicalDeviceFeatures, rhs: &vk::PhysicalDeviceFeatures, ) -> bool { lhs.robust_buffer_access == rhs.robust_buffer_access && lhs.full_draw_index_uint32 == rhs.full_draw_index_uint32 && lhs.image_cube_array == rhs.image_cube_array && lhs.independent_blend == rhs.independent_blend && lhs.geometry_shader == rhs.geometry_shader && lhs.tessellation_shader == rhs.tessellation_shader && lhs.sample_rate_shading == rhs.sample_rate_shading && 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.depth_clamp == rhs.depth_clamp && lhs.depth_bias_clamp == rhs.depth_bias_clamp && lhs.fill_mode_non_solid == rhs.fill_mode_non_solid && lhs.depth_bounds == rhs.depth_bounds && lhs.wide_lines == rhs.wide_lines && lhs.large_points == rhs.large_points && lhs.alpha_to_one == rhs.alpha_to_one && 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_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.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_storage_image_extended_formats == rhs.shader_storage_image_extended_formats && 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 == rhs.shader_storage_image_write_without_format && lhs.shader_uniform_buffer_array_dynamic_indexing == rhs.shader_uniform_buffer_array_dynamic_indexing && lhs.shader_sampled_image_array_dynamic_indexing == rhs.shader_sampled_image_array_dynamic_indexing && lhs.shader_storage_buffer_array_dynamic_indexing == rhs.shader_storage_buffer_array_dynamic_indexing && lhs.shader_storage_image_array_dynamic_indexing == rhs.shader_storage_image_array_dynamic_indexing && lhs.shader_clip_distance == rhs.shader_clip_distance && lhs.shader_cull_distance == rhs.shader_cull_distance && lhs.shader_float64 == rhs.shader_float64 && lhs.shader_int64 == rhs.shader_int64 && lhs.shader_int16 == rhs.shader_int16 && lhs.shader_resource_residency == rhs.shader_resource_residency && lhs.shader_resource_min_lod == rhs.shader_resource_min_lod && lhs.sparse_binding == rhs.sparse_binding && lhs.sparse_residency_buffer == rhs.sparse_residency_buffer && lhs.sparse_residency_image2_d == rhs.sparse_residency_image2_d && lhs.sparse_residency_image3_d == rhs.sparse_residency_image3_d && lhs.sparse_residency2_samples == rhs.sparse_residency2_samples && lhs.sparse_residency4_samples == rhs.sparse_residency4_samples && lhs.sparse_residency8_samples == rhs.sparse_residency8_samples && lhs.sparse_residency16_samples == rhs.sparse_residency16_samples && lhs.sparse_residency_aliased == rhs.sparse_residency_aliased && lhs.variable_multisample_rate == rhs.variable_multisample_rate && lhs.inherited_queries == rhs.inherited_queries } pub fn eq_device_features11( lhs: &vk::PhysicalDeviceVulkan11Features, rhs: &vk::PhysicalDeviceVulkan11Features, ) -> bool { lhs.storage_buffer16_bit_access == rhs.storage_buffer16_bit_access && lhs.uniform_and_storage_buffer16_bit_access == rhs.uniform_and_storage_buffer16_bit_access && lhs.storage_push_constant16 == rhs.storage_push_constant16 && 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.variable_pointers == rhs.variable_pointers && lhs.protected_memory == rhs.protected_memory && lhs.sampler_ycbcr_conversion == rhs.sampler_ycbcr_conversion && lhs.shader_draw_parameters == rhs.shader_draw_parameters } pub fn eq_device_features12( lhs: &vk::PhysicalDeviceVulkan12Features, rhs: &vk::PhysicalDeviceVulkan12Features, ) -> bool { lhs.sampler_mirror_clamp_to_edge == rhs.sampler_mirror_clamp_to_edge && lhs.draw_indirect_count == rhs.draw_indirect_count && lhs.storage_buffer8_bit_access == rhs.storage_buffer8_bit_access && 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_float16 == rhs.shader_float16 && lhs.shader_int8 == rhs.shader_int8 && lhs.descriptor_indexing == rhs.descriptor_indexing && lhs.shader_input_attachment_array_dynamic_indexing == rhs.shader_input_attachment_array_dynamic_indexing && lhs.shader_uniform_texel_buffer_array_dynamic_indexing == rhs.shader_uniform_texel_buffer_array_dynamic_indexing && lhs.shader_storage_texel_buffer_array_dynamic_indexing == rhs.shader_storage_texel_buffer_array_dynamic_indexing && lhs.shader_uniform_buffer_array_non_uniform_indexing == rhs.shader_uniform_buffer_array_non_uniform_indexing && lhs.shader_sampled_image_array_non_uniform_indexing == rhs.shader_sampled_image_array_non_uniform_indexing && lhs.shader_storage_buffer_array_non_uniform_indexing == rhs.shader_storage_buffer_array_non_uniform_indexing && lhs.shader_storage_image_array_non_uniform_indexing == rhs.shader_storage_image_array_non_uniform_indexing && lhs.shader_input_attachment_array_non_uniform_indexing == rhs.shader_input_attachment_array_non_uniform_indexing && lhs.shader_uniform_texel_buffer_array_non_uniform_indexing == rhs.shader_uniform_texel_buffer_array_non_uniform_indexing && lhs.shader_storage_texel_buffer_array_non_uniform_indexing == rhs.shader_storage_texel_buffer_array_non_uniform_indexing && lhs.descriptor_binding_uniform_buffer_update_after_bind == rhs.descriptor_binding_uniform_buffer_update_after_bind && lhs.descriptor_binding_sampled_image_update_after_bind == rhs.descriptor_binding_sampled_image_update_after_bind && lhs.descriptor_binding_storage_image_update_after_bind == rhs.descriptor_binding_storage_image_update_after_bind && lhs.descriptor_binding_storage_buffer_update_after_bind == rhs.descriptor_binding_storage_buffer_update_after_bind && lhs.descriptor_binding_uniform_texel_buffer_update_after_bind == rhs.descriptor_binding_uniform_texel_buffer_update_after_bind && lhs.descriptor_binding_storage_texel_buffer_update_after_bind == 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_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.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.vulkan_memory_model == rhs.vulkan_memory_model && 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_layer == rhs.shader_output_layer && lhs.subgroup_broadcast_dynamic_id == rhs.subgroup_broadcast_dynamic_id } pub fn eq_device_features13( lhs: &vk::PhysicalDeviceVulkan13Features, rhs: &vk::PhysicalDeviceVulkan13Features, ) -> bool { lhs.robust_image_access == rhs.robust_image_access && 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.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.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.shader_zero_initialize_workgroup_memory == rhs.shader_zero_initialize_workgroup_memory && lhs.dynamic_rendering == rhs.dynamic_rendering && lhs.shader_integer_dot_product == rhs.shader_integer_dot_product && lhs.maintenance4 == rhs.maintenance4 } pub fn bitand_device_features10( lhs: &vk::PhysicalDeviceFeatures, rhs: &vk::PhysicalDeviceFeatures, ) -> vk::PhysicalDeviceFeatures { use core::ops::BitAnd; vk::PhysicalDeviceFeatures { 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), 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), 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), 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_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), texture_compression_etc2: lhs .texture_compression_etc2 .bitand(&rhs.texture_compression_etc2), texture_compression_astc_ldr: lhs .texture_compression_astc_ldr .bitand(&rhs.texture_compression_astc_ldr), texture_compression_bc: lhs .texture_compression_bc .bitand(&rhs.texture_compression_bc), occlusion_query_precise: lhs .occlusion_query_precise .bitand(&rhs.occlusion_query_precise), pipeline_statistics_query: lhs .pipeline_statistics_query .bitand(&rhs.pipeline_statistics_query), vertex_pipeline_stores_and_atomics: lhs .vertex_pipeline_stores_and_atomics .bitand(&rhs.vertex_pipeline_stores_and_atomics), fragment_stores_and_atomics: lhs .fragment_stores_and_atomics .bitand(&rhs.fragment_stores_and_atomics), shader_tessellation_and_geometry_point_size: lhs .shader_tessellation_and_geometry_point_size .bitand(&rhs.shader_tessellation_and_geometry_point_size), shader_image_gather_extended: lhs .shader_image_gather_extended .bitand(&rhs.shader_image_gather_extended), shader_storage_image_extended_formats: lhs .shader_storage_image_extended_formats .bitand(&rhs.shader_storage_image_extended_formats), shader_storage_image_multisample: lhs .shader_storage_image_multisample .bitand(&rhs.shader_storage_image_multisample), shader_storage_image_read_without_format: lhs .shader_storage_image_read_without_format .bitand(&rhs.shader_storage_image_read_without_format), shader_storage_image_write_without_format: lhs .shader_storage_image_write_without_format .bitand(&rhs.shader_storage_image_write_without_format), shader_uniform_buffer_array_dynamic_indexing: lhs .shader_uniform_buffer_array_dynamic_indexing .bitand(&rhs.shader_uniform_buffer_array_dynamic_indexing), shader_sampled_image_array_dynamic_indexing: lhs .shader_sampled_image_array_dynamic_indexing .bitand(&rhs.shader_sampled_image_array_dynamic_indexing), shader_storage_buffer_array_dynamic_indexing: lhs .shader_storage_buffer_array_dynamic_indexing .bitand(&rhs.shader_storage_buffer_array_dynamic_indexing), 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_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), shader_resource_residency: lhs .shader_resource_residency .bitand(&rhs.shader_resource_residency), shader_resource_min_lod: lhs .shader_resource_min_lod .bitand(&rhs.shader_resource_min_lod), sparse_binding: lhs.sparse_binding.bitand(&rhs.sparse_binding), sparse_residency_buffer: lhs .sparse_residency_buffer .bitand(&rhs.sparse_residency_buffer), sparse_residency_image2_d: lhs .sparse_residency_image2_d .bitand(&rhs.sparse_residency_image2_d), sparse_residency_image3_d: lhs .sparse_residency_image3_d .bitand(&rhs.sparse_residency_image3_d), sparse_residency2_samples: lhs .sparse_residency2_samples .bitand(&rhs.sparse_residency2_samples), sparse_residency4_samples: lhs .sparse_residency4_samples .bitand(&rhs.sparse_residency4_samples), sparse_residency8_samples: lhs .sparse_residency8_samples .bitand(&rhs.sparse_residency8_samples), sparse_residency16_samples: lhs .sparse_residency16_samples .bitand(&rhs.sparse_residency16_samples), sparse_residency_aliased: lhs .sparse_residency_aliased .bitand(&rhs.sparse_residency_aliased), variable_multisample_rate: lhs .variable_multisample_rate .bitand(&rhs.variable_multisample_rate), inherited_queries: lhs.inherited_queries.bitand(&rhs.inherited_queries), } } pub fn bitand_device_features11( lhs: &vk::PhysicalDeviceVulkan11Features, rhs: &vk::PhysicalDeviceVulkan11Features, ) -> vk::PhysicalDeviceVulkan11Features<'static> { use core::ops::BitAnd; vk::PhysicalDeviceVulkan11Features { storage_buffer16_bit_access: lhs .storage_buffer16_bit_access .bitand(&rhs.storage_buffer16_bit_access), uniform_and_storage_buffer16_bit_access: lhs .uniform_and_storage_buffer16_bit_access .bitand(&rhs.uniform_and_storage_buffer16_bit_access), storage_push_constant16: lhs .storage_push_constant16 .bitand(&rhs.storage_push_constant16), storage_input_output16: lhs .storage_input_output16 .bitand(&rhs.storage_input_output16), multiview: lhs.multiview.bitand(&rhs.multiview), multiview_geometry_shader: lhs .multiview_geometry_shader .bitand(&rhs.multiview_geometry_shader), multiview_tessellation_shader: lhs .multiview_tessellation_shader .bitand(&rhs.multiview_tessellation_shader), 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), sampler_ycbcr_conversion: lhs .sampler_ycbcr_conversion .bitand(&rhs.sampler_ycbcr_conversion), shader_draw_parameters: lhs .shader_draw_parameters .bitand(&rhs.shader_draw_parameters), ..Default::default() } } pub fn bitand_device_features12( lhs: &vk::PhysicalDeviceVulkan12Features, rhs: &vk::PhysicalDeviceVulkan12Features, ) -> vk::PhysicalDeviceVulkan12Features<'static> { use core::ops::BitAnd; vk::PhysicalDeviceVulkan12Features { sampler_mirror_clamp_to_edge: lhs .sampler_mirror_clamp_to_edge .bitand(&rhs.sampler_mirror_clamp_to_edge), draw_indirect_count: lhs.draw_indirect_count.bitand(&rhs.draw_indirect_count), storage_buffer8_bit_access: lhs .storage_buffer8_bit_access .bitand(&rhs.storage_buffer8_bit_access), uniform_and_storage_buffer8_bit_access: lhs .uniform_and_storage_buffer8_bit_access .bitand(&rhs.uniform_and_storage_buffer8_bit_access), storage_push_constant8: lhs .storage_push_constant8 .bitand(&rhs.storage_push_constant8), shader_buffer_int64_atomics: lhs .shader_buffer_int64_atomics .bitand(&rhs.shader_buffer_int64_atomics), shader_shared_int64_atomics: lhs .shader_shared_int64_atomics .bitand(&rhs.shader_shared_int64_atomics), shader_float16: lhs.shader_float16.bitand(&rhs.shader_float16), shader_int8: lhs.shader_int8.bitand(&rhs.shader_int8), descriptor_indexing: lhs.descriptor_indexing.bitand(&rhs.descriptor_indexing), shader_input_attachment_array_dynamic_indexing: lhs .shader_input_attachment_array_dynamic_indexing .bitand(&rhs.shader_input_attachment_array_dynamic_indexing), shader_uniform_texel_buffer_array_dynamic_indexing: lhs .shader_uniform_texel_buffer_array_dynamic_indexing .bitand(&rhs.shader_uniform_texel_buffer_array_dynamic_indexing), shader_storage_texel_buffer_array_dynamic_indexing: lhs .shader_storage_texel_buffer_array_dynamic_indexing .bitand(&rhs.shader_storage_texel_buffer_array_dynamic_indexing), shader_uniform_buffer_array_non_uniform_indexing: lhs .shader_uniform_buffer_array_non_uniform_indexing .bitand(&rhs.shader_uniform_buffer_array_non_uniform_indexing), shader_sampled_image_array_non_uniform_indexing: lhs .shader_sampled_image_array_non_uniform_indexing .bitand(&rhs.shader_sampled_image_array_non_uniform_indexing), shader_storage_buffer_array_non_uniform_indexing: lhs .shader_storage_buffer_array_non_uniform_indexing .bitand(&rhs.shader_storage_buffer_array_non_uniform_indexing), shader_storage_image_array_non_uniform_indexing: lhs .shader_storage_image_array_non_uniform_indexing .bitand(&rhs.shader_storage_image_array_non_uniform_indexing), shader_input_attachment_array_non_uniform_indexing: lhs .shader_input_attachment_array_non_uniform_indexing .bitand(&rhs.shader_input_attachment_array_non_uniform_indexing), shader_uniform_texel_buffer_array_non_uniform_indexing: lhs .shader_uniform_texel_buffer_array_non_uniform_indexing .bitand(&rhs.shader_uniform_texel_buffer_array_non_uniform_indexing), shader_storage_texel_buffer_array_non_uniform_indexing: lhs .shader_storage_texel_buffer_array_non_uniform_indexing .bitand(&rhs.shader_storage_texel_buffer_array_non_uniform_indexing), descriptor_binding_uniform_buffer_update_after_bind: lhs .descriptor_binding_uniform_buffer_update_after_bind .bitand(&rhs.descriptor_binding_uniform_buffer_update_after_bind), descriptor_binding_sampled_image_update_after_bind: lhs .descriptor_binding_sampled_image_update_after_bind .bitand(&rhs.descriptor_binding_sampled_image_update_after_bind), descriptor_binding_storage_image_update_after_bind: lhs .descriptor_binding_storage_image_update_after_bind .bitand(&rhs.descriptor_binding_storage_image_update_after_bind), descriptor_binding_storage_buffer_update_after_bind: lhs .descriptor_binding_storage_buffer_update_after_bind .bitand(&rhs.descriptor_binding_storage_buffer_update_after_bind), descriptor_binding_uniform_texel_buffer_update_after_bind: lhs .descriptor_binding_uniform_texel_buffer_update_after_bind .bitand(&rhs.descriptor_binding_uniform_texel_buffer_update_after_bind), descriptor_binding_storage_texel_buffer_update_after_bind: lhs .descriptor_binding_storage_texel_buffer_update_after_bind .bitand(&rhs.descriptor_binding_storage_texel_buffer_update_after_bind), descriptor_binding_update_unused_while_pending: lhs .descriptor_binding_update_unused_while_pending .bitand(&rhs.descriptor_binding_update_unused_while_pending), descriptor_binding_partially_bound: lhs .descriptor_binding_partially_bound .bitand(&rhs.descriptor_binding_partially_bound), descriptor_binding_variable_descriptor_count: lhs .descriptor_binding_variable_descriptor_count .bitand(&rhs.descriptor_binding_variable_descriptor_count), runtime_descriptor_array: lhs .runtime_descriptor_array .bitand(&rhs.runtime_descriptor_array), sampler_filter_minmax: lhs.sampler_filter_minmax.bitand(&rhs.sampler_filter_minmax), scalar_block_layout: lhs.scalar_block_layout.bitand(&rhs.scalar_block_layout), imageless_framebuffer: lhs.imageless_framebuffer.bitand(&rhs.imageless_framebuffer), uniform_buffer_standard_layout: lhs .uniform_buffer_standard_layout .bitand(&rhs.uniform_buffer_standard_layout), shader_subgroup_extended_types: lhs .shader_subgroup_extended_types .bitand(&rhs.shader_subgroup_extended_types), separate_depth_stencil_layouts: lhs .separate_depth_stencil_layouts .bitand(&rhs.separate_depth_stencil_layouts), host_query_reset: lhs.host_query_reset.bitand(&rhs.host_query_reset), timeline_semaphore: lhs.timeline_semaphore.bitand(&rhs.timeline_semaphore), buffer_device_address: lhs.buffer_device_address.bitand(&rhs.buffer_device_address), buffer_device_address_capture_replay: lhs .buffer_device_address_capture_replay .bitand(&rhs.buffer_device_address_capture_replay), buffer_device_address_multi_device: lhs .buffer_device_address_multi_device .bitand(&rhs.buffer_device_address_multi_device), vulkan_memory_model: lhs.vulkan_memory_model.bitand(&rhs.vulkan_memory_model), vulkan_memory_model_device_scope: lhs .vulkan_memory_model_device_scope .bitand(&rhs.vulkan_memory_model_device_scope), vulkan_memory_model_availability_visibility_chains: lhs .vulkan_memory_model_availability_visibility_chains .bitand(&rhs.vulkan_memory_model_availability_visibility_chains), shader_output_viewport_index: lhs .shader_output_viewport_index .bitand(&rhs.shader_output_viewport_index), shader_output_layer: lhs.shader_output_layer.bitand(&rhs.shader_output_layer), subgroup_broadcast_dynamic_id: lhs .subgroup_broadcast_dynamic_id .bitand(&rhs.subgroup_broadcast_dynamic_id), ..Default::default() } } pub fn bitand_device_features13( lhs: &vk::PhysicalDeviceVulkan13Features, rhs: &vk::PhysicalDeviceVulkan13Features, ) -> vk::PhysicalDeviceVulkan13Features<'static> { use core::ops::BitAnd; vk::PhysicalDeviceVulkan13Features { robust_image_access: lhs.robust_image_access.bitand(&rhs.robust_image_access), inline_uniform_block: lhs.inline_uniform_block.bitand(&rhs.inline_uniform_block), descriptor_binding_inline_uniform_block_update_after_bind: lhs .descriptor_binding_inline_uniform_block_update_after_bind .bitand(&rhs.descriptor_binding_inline_uniform_block_update_after_bind), pipeline_creation_cache_control: lhs .pipeline_creation_cache_control .bitand(&rhs.pipeline_creation_cache_control), private_data: lhs.private_data.bitand(&rhs.private_data), shader_demote_to_helper_invocation: lhs .shader_demote_to_helper_invocation .bitand(&rhs.shader_demote_to_helper_invocation), shader_terminate_invocation: lhs .shader_terminate_invocation .bitand(&rhs.shader_terminate_invocation), subgroup_size_control: lhs.subgroup_size_control.bitand(&rhs.subgroup_size_control), compute_full_subgroups: lhs .compute_full_subgroups .bitand(&rhs.compute_full_subgroups), synchronization2: lhs.synchronization2.bitand(&rhs.synchronization2), texture_compression_astc_hdr: lhs .texture_compression_astc_hdr .bitand(&rhs.texture_compression_astc_hdr), shader_zero_initialize_workgroup_memory: lhs .shader_zero_initialize_workgroup_memory .bitand(&rhs.shader_zero_initialize_workgroup_memory), dynamic_rendering: lhs.dynamic_rendering.bitand(&rhs.dynamic_rendering), shader_integer_dot_product: lhs .shader_integer_dot_product .bitand(&rhs.shader_integer_dot_product), maintenance4: lhs.maintenance4.bitand(&rhs.maintenance4), ..Default::default() } } }