use std::ops::{Deref, DerefMut}; use ash::vk; #[macro_export] macro_rules! def_monotonic_id { ($vis:vis $ty:ident) => { #[derive(Copy, Clone, Hash, Eq, PartialEq, PartialOrd, Ord, Debug)] $vis struct $ty(::core::num::NonZero); impl $ty { pub fn new() -> Self { use ::core::sync::atomic::{AtomicU32, Ordering}; static COUNTER: AtomicU32 = AtomicU32::new(1); let inner = COUNTER.fetch_add(1, Ordering::Relaxed); Self( ::core::num::NonZero::::new(inner) .expect(&format!("integer overwarp for {}", stringify!($ty))), ) } pub fn as_u32(&self) -> u32 { self.0.get() } } }; } pub trait MutexExt<'a, T: 'a> { type Guard: Deref + 'a; fn lock(&'a self) -> Self::Guard; fn with_locked R>(&'a self, f: F) -> R { let lock = MutexExt::lock(self); f(&*lock) } } impl<'a, T: 'a> MutexExt<'a, T> for parking_lot::Mutex { type Guard = parking_lot::MutexGuard<'a, T>; fn lock(&'a self) -> Self::Guard { self.lock() } } #[allow(dead_code)] pub trait FormatExt { fn get_component_kind(&self) -> FormatComponentKind; fn is_f32(&self) -> bool; fn is_u32(&self) -> bool; fn is_i32(&self) -> bool; } #[derive(Debug, PartialEq, Eq)] pub enum FormatComponentKind { Float, UInt, SInt, } fn format_to_primitive(format: vk::Format) -> FormatComponentKind { use FormatComponentKind::*; match format { vk::Format::BC6H_SFLOAT_BLOCK => Float, vk::Format::D32_SFLOAT => Float, vk::Format::R16G16B16A16_SFLOAT => Float, vk::Format::R16G16B16_SFLOAT => Float, vk::Format::R16G16_SFLOAT => Float, vk::Format::R16_SFLOAT => Float, vk::Format::R32G32B32A32_SFLOAT => Float, vk::Format::R32G32B32_SFLOAT => Float, vk::Format::R32G32_SFLOAT => Float, vk::Format::R32_SFLOAT => Float, vk::Format::R64G64B64A64_SFLOAT => Float, vk::Format::R64G64B64_SFLOAT => Float, vk::Format::R64G64_SFLOAT => Float, vk::Format::R64_SFLOAT => Float, vk::Format::D32_SFLOAT_S8_UINT => Float, vk::Format::A2B10G10R10_SINT_PACK32 => SInt, vk::Format::A2R10G10B10_SINT_PACK32 => SInt, vk::Format::A8B8G8R8_SINT_PACK32 => SInt, vk::Format::B8G8R8A8_SINT => SInt, vk::Format::B8G8R8_SINT => SInt, vk::Format::R16G16B16A16_SINT => SInt, vk::Format::R16G16B16_SINT => SInt, vk::Format::R16G16_SINT => SInt, vk::Format::R16_SINT => SInt, vk::Format::R32G32B32A32_SINT => SInt, vk::Format::R32G32B32_SINT => SInt, vk::Format::R32G32_SINT => SInt, vk::Format::R32_SINT => SInt, vk::Format::R64G64B64A64_SINT => SInt, vk::Format::R64G64B64_SINT => SInt, vk::Format::R64G64_SINT => SInt, vk::Format::R64_SINT => SInt, vk::Format::R8G8B8A8_SINT => SInt, vk::Format::R8G8B8_SINT => SInt, vk::Format::R8G8_SINT => SInt, vk::Format::R8_SINT => SInt, vk::Format::A2B10G10R10_SNORM_PACK32 => Float, vk::Format::A2R10G10B10_SNORM_PACK32 => Float, vk::Format::A8B8G8R8_SNORM_PACK32 => Float, vk::Format::B8G8R8A8_SNORM => Float, vk::Format::B8G8R8_SNORM => Float, vk::Format::BC4_SNORM_BLOCK => Float, vk::Format::BC5_SNORM_BLOCK => Float, vk::Format::EAC_R11G11_SNORM_BLOCK => Float, vk::Format::EAC_R11_SNORM_BLOCK => Float, vk::Format::R16G16B16A16_SNORM => Float, vk::Format::R16G16B16_SNORM => Float, vk::Format::R16G16_SNORM => Float, vk::Format::R16_SNORM => Float, vk::Format::R8G8B8A8_SNORM => Float, vk::Format::R8G8B8_SNORM => Float, vk::Format::R8G8_SNORM => Float, vk::Format::R8_SNORM => Float, vk::Format::A8B8G8R8_SRGB_PACK32 => Float, vk::Format::ASTC_10X10_SRGB_BLOCK => Float, vk::Format::ASTC_10X5_SRGB_BLOCK => Float, vk::Format::ASTC_10X6_SRGB_BLOCK => Float, vk::Format::ASTC_10X8_SRGB_BLOCK => Float, vk::Format::ASTC_12X10_SRGB_BLOCK => Float, vk::Format::ASTC_12X12_SRGB_BLOCK => Float, vk::Format::ASTC_4X4_SRGB_BLOCK => Float, vk::Format::ASTC_5X4_SRGB_BLOCK => Float, vk::Format::ASTC_5X5_SRGB_BLOCK => Float, vk::Format::ASTC_6X5_SRGB_BLOCK => Float, vk::Format::ASTC_6X6_SRGB_BLOCK => Float, vk::Format::ASTC_8X5_SRGB_BLOCK => Float, vk::Format::ASTC_8X6_SRGB_BLOCK => Float, vk::Format::ASTC_8X8_SRGB_BLOCK => Float, vk::Format::B8G8R8A8_SRGB => Float, vk::Format::B8G8R8_SRGB => Float, vk::Format::BC1_RGBA_SRGB_BLOCK => Float, vk::Format::BC1_RGB_SRGB_BLOCK => Float, vk::Format::BC2_SRGB_BLOCK => Float, vk::Format::BC3_SRGB_BLOCK => Float, vk::Format::BC7_SRGB_BLOCK => Float, vk::Format::ETC2_R8G8B8A1_SRGB_BLOCK => Float, vk::Format::ETC2_R8G8B8A8_SRGB_BLOCK => Float, vk::Format::ETC2_R8G8B8_SRGB_BLOCK => Float, vk::Format::R8G8B8A8_SRGB => Float, vk::Format::R8G8B8_SRGB => Float, vk::Format::R8G8_SRGB => Float, vk::Format::R8_SRGB => Float, vk::Format::A2B10G10R10_SSCALED_PACK32 => Float, vk::Format::A2R10G10B10_SSCALED_PACK32 => Float, vk::Format::A8B8G8R8_SSCALED_PACK32 => Float, vk::Format::B8G8R8A8_SSCALED => Float, vk::Format::B8G8R8_SSCALED => Float, vk::Format::R16G16B16A16_SSCALED => Float, vk::Format::R16G16B16_SSCALED => Float, vk::Format::R16G16_SSCALED => Float, vk::Format::R16_SSCALED => Float, vk::Format::R8G8B8A8_SSCALED => Float, vk::Format::R8G8B8_SSCALED => Float, vk::Format::R8G8_SSCALED => Float, vk::Format::R8_SSCALED => Float, vk::Format::B10G11R11_UFLOAT_PACK32 => Float, vk::Format::BC6H_UFLOAT_BLOCK => Float, vk::Format::E5B9G9R9_UFLOAT_PACK32 => Float, vk::Format::A2B10G10R10_UINT_PACK32 => UInt, vk::Format::A2R10G10B10_UINT_PACK32 => UInt, vk::Format::A8B8G8R8_UINT_PACK32 => UInt, vk::Format::B8G8R8A8_UINT => UInt, vk::Format::B8G8R8_UINT => UInt, vk::Format::R16G16B16A16_UINT => UInt, vk::Format::R16G16B16_UINT => UInt, vk::Format::R16G16_UINT => UInt, vk::Format::R16_UINT => UInt, vk::Format::R32G32B32A32_UINT => UInt, vk::Format::R32G32B32_UINT => UInt, vk::Format::R32G32_UINT => UInt, vk::Format::R32_UINT => UInt, vk::Format::R64G64B64A64_UINT => UInt, vk::Format::R64G64B64_UINT => UInt, vk::Format::R64G64_UINT => UInt, vk::Format::R64_UINT => UInt, vk::Format::R8G8B8A8_UINT => UInt, vk::Format::R8G8B8_UINT => UInt, vk::Format::R8G8_UINT => UInt, vk::Format::R8_UINT => UInt, vk::Format::S8_UINT => UInt, vk::Format::A1R5G5B5_UNORM_PACK16 => Float, vk::Format::A2B10G10R10_UNORM_PACK32 => Float, vk::Format::A2R10G10B10_UNORM_PACK32 => Float, vk::Format::A8B8G8R8_UNORM_PACK32 => Float, vk::Format::ASTC_10X10_UNORM_BLOCK => Float, vk::Format::ASTC_10X5_UNORM_BLOCK => Float, vk::Format::ASTC_10X6_UNORM_BLOCK => Float, vk::Format::ASTC_10X8_UNORM_BLOCK => Float, vk::Format::ASTC_12X10_UNORM_BLOCK => Float, vk::Format::ASTC_12X12_UNORM_BLOCK => Float, vk::Format::ASTC_4X4_UNORM_BLOCK => Float, vk::Format::ASTC_5X4_UNORM_BLOCK => Float, vk::Format::ASTC_5X5_UNORM_BLOCK => Float, vk::Format::ASTC_6X5_UNORM_BLOCK => Float, vk::Format::ASTC_6X6_UNORM_BLOCK => Float, vk::Format::ASTC_8X5_UNORM_BLOCK => Float, vk::Format::ASTC_8X6_UNORM_BLOCK => Float, vk::Format::ASTC_8X8_UNORM_BLOCK => Float, vk::Format::B4G4R4A4_UNORM_PACK16 => Float, vk::Format::B5G5R5A1_UNORM_PACK16 => Float, vk::Format::B5G6R5_UNORM_PACK16 => Float, vk::Format::B8G8R8A8_UNORM => Float, vk::Format::B8G8R8_UNORM => Float, vk::Format::BC1_RGBA_UNORM_BLOCK => Float, vk::Format::BC1_RGB_UNORM_BLOCK => Float, vk::Format::BC2_UNORM_BLOCK => Float, vk::Format::BC3_UNORM_BLOCK => Float, vk::Format::BC4_UNORM_BLOCK => Float, vk::Format::BC5_UNORM_BLOCK => Float, vk::Format::BC7_UNORM_BLOCK => Float, vk::Format::D16_UNORM => Float, vk::Format::D16_UNORM_S8_UINT => Float, vk::Format::D24_UNORM_S8_UINT => Float, vk::Format::EAC_R11G11_UNORM_BLOCK => Float, vk::Format::EAC_R11_UNORM_BLOCK => Float, vk::Format::ETC2_R8G8B8A1_UNORM_BLOCK => Float, vk::Format::ETC2_R8G8B8A8_UNORM_BLOCK => Float, vk::Format::ETC2_R8G8B8_UNORM_BLOCK => Float, vk::Format::R16G16B16A16_UNORM => Float, vk::Format::R16G16B16_UNORM => Float, vk::Format::R16G16_UNORM => Float, vk::Format::R16_UNORM => Float, vk::Format::R4G4B4A4_UNORM_PACK16 => Float, vk::Format::R4G4_UNORM_PACK8 => Float, vk::Format::R5G5B5A1_UNORM_PACK16 => Float, vk::Format::R5G6B5_UNORM_PACK16 => Float, vk::Format::R8G8B8A8_UNORM => Float, vk::Format::R8G8B8_UNORM => Float, vk::Format::R8G8_UNORM => Float, vk::Format::R8_UNORM => Float, vk::Format::X8_D24_UNORM_PACK32 => Float, vk::Format::A2B10G10R10_USCALED_PACK32 => Float, vk::Format::A2R10G10B10_USCALED_PACK32 => Float, vk::Format::A8B8G8R8_USCALED_PACK32 => Float, vk::Format::B8G8R8A8_USCALED => Float, vk::Format::B8G8R8_USCALED => Float, vk::Format::R16G16B16A16_USCALED => Float, vk::Format::R16G16B16_USCALED => Float, vk::Format::R16G16_USCALED => Float, vk::Format::R16_USCALED => Float, vk::Format::R8G8B8A8_USCALED => Float, vk::Format::R8G8B8_USCALED => Float, vk::Format::R8G8_USCALED => Float, vk::Format::R8_USCALED => Float, _ => unimplemented!(), } } impl FormatExt for vk::Format { fn get_component_kind(&self) -> FormatComponentKind { format_to_primitive(*self) } fn is_f32(&self) -> bool { format_to_primitive(*self) == FormatComponentKind::Float } fn is_u32(&self) -> bool { format_to_primitive(*self) == FormatComponentKind::UInt } fn is_i32(&self) -> bool { format_to_primitive(*self) == FormatComponentKind::SInt } } #[derive(Debug, Default, PartialEq, Eq, Hash, Clone, Copy)] pub struct Rect2D { top_left: glam::IVec2, bottom_right: glam::IVec2, } impl Rect2D { pub fn new(left: i32, top: i32, right: i32, bottom: i32) -> Self { use glam::ivec2; Self { top_left: ivec2(left, top), bottom_right: ivec2(right, bottom), } } pub fn new_from_size(pos: glam::IVec2, size: glam::IVec2) -> Self { Self { top_left: pos, bottom_right: pos + size, } } pub fn into_offsets_3d(&self) -> [vk::Offset3D; 2] { [ vk::Offset3D { x: self.top_left.x, y: self.top_left.y, z: 0, }, vk::Offset3D { x: self.bottom_right.x, y: self.bottom_right.y, z: 1, }, ] } #[allow(dead_code)] pub fn top_left(&self) -> glam::IVec2 { self.top_left } #[allow(dead_code)] pub fn size(&self) -> glam::IVec2 { self.bottom_right - self.top_left } #[allow(dead_code)] pub fn width(&self) -> i32 { self.bottom_right.x - self.top_left.x } #[allow(dead_code)] pub fn height(&self) -> i32 { self.bottom_right.y - self.top_left.y } } pub fn eq_f32(lhs: f32, rhs: f32) -> bool { use core::num::FpCategory::*; match (lhs.classify(), rhs.classify()) { (Zero, Zero) | (Nan, Nan) => true, (Infinite, Infinite) => lhs.signum() == rhs.signum(), _ => lhs == rhs, } } pub fn hash_f32(state: &mut H, f: f32) { use std::hash::Hash; let classify = f.classify(); match classify { std::num::FpCategory::Nan => (classify as u8).hash(state), std::num::FpCategory::Infinite | std::num::FpCategory::Zero => { (classify as u8, f.signum() as i8).hash(state) } std::num::FpCategory::Subnormal | std::num::FpCategory::Normal => f.to_bits().hash(state), } } pub fn timed T>(label: &str, f: F) -> T { let now = std::time::Instant::now(); let out = f(); tracing::info!("{label}: {}ms", now.elapsed().as_micros() as f32 / 1e3); out } #[derive(Debug, Clone, Copy)] pub struct Rgba(pub [f32; 4]); impl std::hash::Hash for Rgba { fn hash(&self, state: &mut H) { self.0.map(|f| hash_f32(state, f)); } } #[allow(dead_code)] impl Rgba { pub fn new(r: f32, g: f32, b: f32, a: f32) -> Self { Self([r, g, b, a]) } pub fn into_u32(&self) -> [u32; 4] { self.0.map(|f| (f.clamp(0.0, 1.0) * 255.0) as u32) } pub fn into_f32(&self) -> [f32; 4] { self.0 } pub fn into_snorm(&self) -> [f32; 4] { self.0.map(|f| (f - 0.5) * 2.0) } pub fn into_i32(&self) -> [i32; 4] { self.0.map(|f| (f.clamp(0.0, 1.0) * 255.0) as i32 - 128) } } #[allow(dead_code)] pub fn image_aspect_from_format(format: vk::Format) -> vk::ImageAspectFlags { use vk::{Format, ImageAspectFlags}; match format { Format::D32_SFLOAT | Format::X8_D24_UNORM_PACK32 | Format::D16_UNORM => { ImageAspectFlags::DEPTH } Format::S8_UINT => ImageAspectFlags::STENCIL, Format::D32_SFLOAT_S8_UINT | Format::D16_UNORM_S8_UINT | Format::D24_UNORM_S8_UINT => { ImageAspectFlags::DEPTH | ImageAspectFlags::STENCIL } _ => ImageAspectFlags::COLOR, } } #[repr(transparent)] pub struct WithLifetime<'a, T>(T, std::marker::PhantomData<&'a ()>); impl WithLifetime<'_, T> { pub fn new(t: T) -> Self { Self(t, std::marker::PhantomData) } } impl<'a, T: 'a> Deref for WithLifetime<'a, T> { type Target = T; fn deref(&self) -> &Self::Target { &self.0 } } impl<'a, T: 'a> DerefMut for WithLifetime<'a, T> { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } }