vidya/crates/renderer/src/lib.rs
2026-04-11 17:28:29 +02:00

1599 lines
77 KiB
Rust

#![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<TextureId, Arc<Image>>,
#[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<Image>) -> TextureId {
let id = TextureId::new();
self.textures.insert(id, image);
id
}
pub fn insert_image_with_id(&mut self, id: TextureId, image: Arc<Image>) {
self.textures.insert(id, image);
}
pub fn remove_texture(&mut self, id: TextureId) -> Option<Arc<Image>> {
self.textures.remove(&id)
}
pub fn get_texture(&self, id: TextureId) -> Option<Arc<Image>> {
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<T> = core::result::Result<T, Error>;
#[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<T: vk::ExtendsPhysicalDeviceFeatures2 + Debug + Send + Sync> ExtendsDeviceFeatures2Debug
for T
{
}
impl<T: vk::ExtendsPhysicalDeviceProperties2 + Debug + DynClone + Send + Sync>
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<vk::SurfaceFormatKHR>,
pub present_modes: Vec<vk::PresentModeKHR>,
}
#[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<vk::PhysicalDeviceMeshShaderFeaturesEXT<'static>>,
}
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<vk::ExtensionProperties>,
/// 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<vk::PhysicalDeviceMeshShaderPropertiesEXT<'static>>,
/// 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::<u64>()
}
}
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<PhysicalDeviceProperties> {
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<vk::ExtensionProperties> {
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<pipeline::SamplerDesc, pipeline::Sampler>,
}
impl SamplerCache {
pub fn new(device: Device) -> SamplerCache {
Self {
device,
samplers: HashMap::new(),
}
}
pub fn get_sampler(&mut self, desc: pipeline::SamplerDesc) -> VkResult<vk::Sampler> {
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<egui::TextureId, EguiTextureInfo>,
#[allow(unused)]
descriptor_pool: pipeline::DescriptorPool,
descriptor_set: vk::DescriptorSet,
#[allow(unused)]
descriptor_layout: pipeline::DescriptorSetLayout,
pipeline_layout: Arc<pipeline::PipelineLayout>,
pipeline: Arc<pipeline::Pipeline>,
}
#[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<Self> {
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<texture::TextureId> {
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<Self> {
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<swapchain::Surface> {
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, F: FnOnce(&mut Renderer2, &mut render_graph::RenderGraph) -> T>(
&mut self,
surface: &swapchain::Surface,
cb: F,
) -> Result<T> {
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<F>(self, mut pred: F) -> (Vec<Self::Item>, Vec<Self::Item>)
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()
}
}
}