#![feature( negative_impls, map_try_insert, debug_closure_helpers, )] use std::{collections::HashMap, sync::Arc}; use ash::{prelude::VkResult, vk}; use raw_window_handle::{RawDisplayHandle, RawWindowHandle}; pub use ash; pub mod commands; #[path = "egui.rs"] mod egui_pass; pub mod render_graph; pub mod rendering; pub mod swapchain; mod text; pub mod util; pub(crate) use renderer_resources::{buffers, images, pipeline}; pub use renderer_device::{device, instance, queue, sync}; pub use renderer_device::{ compatible_extension_properties, extension_intersection, get_physical_device_features, get_physical_device_properties, make_extension, DebugUtils, DebugUtilsCreateInfo, Device, DeviceOwned, DeviceRef, Error, ExtendsDeviceFeatures2Debug, ExtendsDeviceProperties2Debug, Extension, Instance, PhysicalDeviceFeatures, PhysicalDeviceInfo, PhysicalDeviceProperties, Result, SurfaceCapabilities, }; pub use renderer_macros::DeviceRef; 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; 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: 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 = Arc::new(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), }) } pub fn lookup_texture(&self, id: egui::epaint::TextureId) -> Option { self.textures.get(&id).map(|entry| entry.id) } } #[derive(renderer_macros::DeviceRef)] pub struct Renderer2 { #[device] 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, None)?), )?; future.await; // window.window.pre_present_notify(); let wait = Some(frame.release); frame.present(wait)?; Ok(out) } } pub use vk::Extent2D; use crate::{ instance::InstanceDesc, }; 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() } } }