command buffer abstraction, images/buffers start

This commit is contained in:
Janis 2024-12-22 02:02:27 +01:00
parent d29b121aca
commit f7e6a92018
6 changed files with 516 additions and 35 deletions

View file

@ -0,0 +1,88 @@
use std::{ops::Deref, sync::Arc};
use ash::{prelude::VkResult, vk};
use vk_mem::Alloc;
use crate::Device;
pub struct Buffer {
device: Device,
buffer: vk::Buffer,
allocation: vk_mem::Allocation,
usage: vk::BufferUsageFlags,
size: u64,
}
impl Drop for Buffer {
fn drop(&mut self) {
unsafe {
self.device
.alloc()
.destroy_buffer(self.buffer, &mut self.allocation);
}
}
}
impl Buffer {
pub fn new(
device: Device,
size: usize,
usage: vk::BufferUsageFlags,
queue_families: &[u32],
memory_usage: vk_mem::MemoryUsage,
alloc_flags: vk_mem::AllocationCreateFlags,
) -> VkResult<Arc<Self>> {
let sharing_mode = if queue_families.len() > 1 {
vk::SharingMode::EXCLUSIVE
} else {
vk::SharingMode::CONCURRENT
};
let (buffer, allocation) = unsafe {
device.alloc().create_buffer(
&vk::BufferCreateInfo::default()
.usage(usage)
.queue_family_indices(queue_families)
.sharing_mode(sharing_mode),
&vk_mem::AllocationCreateInfo {
flags: alloc_flags,
usage: memory_usage,
..Default::default()
},
)?
};
let buffer = Self {
device,
buffer,
allocation,
usage,
size: size as u64,
};
Ok(Arc::new(buffer))
}
pub fn map(&mut self) -> VkResult<MappedBuffer<'_>> {
let bytes = unsafe {
let data = self.device.alloc().map_memory(&mut self.allocation)?;
let slice = core::slice::from_raw_parts(data, self.size as usize);
slice
};
Ok(MappedBuffer { bytes })
}
}
pub struct MappedBuffer<'a> {
bytes: &'a [u8],
}
impl Deref for MappedBuffer<'_> {
type Target = [u8];
fn deref(&self) -> &Self::Target {
self.bytes
}
}

View file

@ -1,20 +1,28 @@
use std::{future::Future, marker::PhantomData, sync::Arc};
use crate::sync::{self, FenceFuture};
use crate::{
buffers::Buffer,
images::{Image2D, QueueOwnership},
sync::{self, FenceFuture},
util::{FormatExt, MutexExt},
};
use super::{Device, Queue};
use ash::{prelude::*, vk};
use parking_lot::Mutex;
pub struct SingleUseCommandPool {
device: Device,
pool: vk::CommandPool,
pool: Mutex<vk::CommandPool>,
queue: Queue,
}
impl Drop for SingleUseCommandPool {
fn drop(&mut self) {
unsafe {
self.device.dev().destroy_command_pool(self.pool, None);
self.pool.with_locked(|&pool| {
self.device.dev().destroy_command_pool(pool, None);
});
}
}
}
@ -30,7 +38,7 @@ impl SingleUseCommandPool {
Ok(Arc::new(Self {
device,
pool,
pool: Mutex::new(pool),
queue,
}))
}
@ -43,8 +51,9 @@ impl SingleUseCommandPool {
&self.queue
}
pub fn pool(&self) -> vk::CommandPool {
self.pool
/// get the underlying pool, bypassing the mutex
pub unsafe fn pool(&self) -> vk::CommandPool {
self.pool.data_ptr().read()
}
}
@ -54,12 +63,14 @@ pub struct SingleUseCommand {
buffer: vk::CommandBuffer,
}
impl !Sync for SingleUseCommand {}
impl Drop for SingleUseCommand {
fn drop(&mut self) {
unsafe {
self.device
.dev()
.free_command_buffers(self.pool.pool(), &[self.buffer])
self.pool.pool.with_locked(|&pool| {
self.device.dev().free_command_buffers(pool, &[self.buffer])
})
};
}
}
@ -91,10 +102,89 @@ impl SingleUseCommand {
})
}
pub fn buffer(&self) -> vk::CommandBuffer {
/// Safety: commandbuffer must not be accessed from multiple threads at the same time
pub unsafe fn buffer(&self) -> vk::CommandBuffer {
self.buffer
}
//pub fn copy_buffer_to_image(&self, image: &Image2D, buffer: &Buffer, )
pub fn image_barrier(
&self,
image: vk::Image,
aspects: vk::ImageAspectFlags,
src_stage: vk::PipelineStageFlags2,
src_access: vk::AccessFlags2,
dst_stage: vk::PipelineStageFlags2,
dst_access: vk::AccessFlags2,
old_layout: vk::ImageLayout,
new_layout: vk::ImageLayout,
queue_ownership_op: Option<QueueOwnership>,
) {
let (src_family, dst_family) = queue_ownership_op
.map(|t| (t.src, t.dst))
.unwrap_or((vk::QUEUE_FAMILY_IGNORED, vk::QUEUE_FAMILY_IGNORED));
let barrier = vk::ImageMemoryBarrier2::default()
.image(image)
.subresource_range(
vk::ImageSubresourceRange::default()
.aspect_mask(aspects)
.base_mip_level(0)
.base_array_layer(0)
.level_count(vk::REMAINING_MIP_LEVELS)
.layer_count(vk::REMAINING_ARRAY_LAYERS),
)
.src_stage_mask(src_stage)
.src_access_mask(src_access)
.dst_stage_mask(dst_stage)
.dst_access_mask(dst_access)
.dst_queue_family_index(dst_family)
.src_queue_family_index(src_family)
.old_layout(old_layout)
.new_layout(new_layout);
unsafe {
self.device.dev().cmd_pipeline_barrier2(
self.buffer,
&vk::DependencyInfo::default()
.dependency_flags(vk::DependencyFlags::BY_REGION)
.image_memory_barriers(core::slice::from_ref(&barrier)),
);
}
}
pub fn clear_color_image(
&self,
image: vk::Image,
format: vk::Format,
layout: vk::ImageLayout,
color: crate::Rgba,
subresources: &[vk::ImageSubresourceRange],
) {
let clear_colors = match format.get_component_kind() {
crate::util::FormatComponentKind::Float => vk::ClearColorValue {
float32: color.into_f32(),
},
crate::util::FormatComponentKind::UInt => vk::ClearColorValue {
uint32: color.into_u32(),
},
crate::util::FormatComponentKind::SInt => vk::ClearColorValue {
int32: color.into_i32(),
},
};
unsafe {
self.device.dev().cmd_clear_color_image(
self.buffer,
image,
layout,
&clear_colors,
subresources,
);
}
}
pub fn submit_fence(
&self,
wait: Option<(vk::Semaphore, vk::PipelineStageFlags)>,

View file

@ -1,5 +1,7 @@
use std::sync::Arc;
use crate::buffers::Buffer;
use super::{Device, Queue};
use ash::{prelude::*, vk};
use vk_mem::Alloc;
@ -70,6 +72,16 @@ impl Image2D {
}))
}
pub fn format(&self) -> vk::Format {
self.format
}
pub fn copy_from_buffer(&self, buffer: &Buffer) {
unsafe {
// self.device.dev().cmd_copy_buffer_to_image(command_buffer, src_buffer, dst_image, dst_image_layout, regions);
}
}
pub fn view(
self: &Arc<Self>,
device: &Device,
@ -121,8 +133,8 @@ impl Drop for ImageView2D {
impl ImageView2D {}
pub struct QueueOwnership {
src: u32,
dst: u32,
pub src: u32,
pub dst: u32,
}
pub fn image_barrier<'a>(
@ -159,3 +171,12 @@ pub fn image_barrier<'a>(
.old_layout(old_layout)
.new_layout(new_layout)
}
pub const SUBRESOURCERANGE_COLOR_ALL: vk::ImageSubresourceRange =
vk::ImageSubresourceRange {
aspect_mask: vk::ImageAspectFlags::COLOR,
base_mip_level: 0,
level_count: vk::REMAINING_MIP_LEVELS,
base_array_layer: 0,
layer_count: vk::REMAINING_ARRAY_LAYERS,
};

View file

@ -33,11 +33,14 @@ use raw_window_handle::{DisplayHandle, RawDisplayHandle};
use tinyvec::{array_vec, ArrayVec};
use tracing::info;
mod buffers;
mod commands;
mod images;
mod render_graph;
mod sync;
mod util;
use render_graph::Rgba;
#[derive(Debug, thiserror::Error)]
pub enum Error {
@ -720,6 +723,7 @@ pub struct SwapchainFrame {
pub swapchain: Arc<Swapchain>,
pub index: u32,
pub image: vk::Image,
pub format: vk::Format,
pub view: vk::ImageView,
pub acquire: vk::Semaphore,
pub release: vk::Semaphore,
@ -1042,6 +1046,7 @@ impl Swapchain {
SwapchainFrame {
index: idx as u32,
swapchain: self.clone(),
format: self.format,
image,
view,
acquire,
@ -2043,7 +2048,6 @@ impl<W> Renderer<W> {
if let Some(ctx) = self.window_contexts.get(window) {
let cmd = pool.alloc()?;
let buffer = cmd.buffer();
let (frame, suboptimal) = smol::block_on(
ctx.current_swapchain.read().clone().acquire_image(),
@ -2074,6 +2078,7 @@ impl<W> Renderer<W> {
ctx.surface.surface.as_raw(),
)
.gen::<[f32; 3]>();
let clear_color = Rgba([r, g, b, 1.0]);
let clear_values = vk::ClearColorValue {
float32: [r, g, b, 1.0],
};
@ -2095,21 +2100,25 @@ impl<W> Renderer<W> {
.dependency_flags(vk::DependencyFlags::BY_REGION)
.image_memory_barriers(&barriers);
dev.dev().cmd_pipeline_barrier2(buffer, &dependency_info);
dev.dev().cmd_clear_color_image(
buffer,
cmd.image_barrier(
frame.image,
vk::ImageAspectFlags::COLOR,
vk::PipelineStageFlags2::TRANSFER,
vk::AccessFlags2::empty(),
vk::PipelineStageFlags2::TRANSFER,
vk::AccessFlags2::TRANSFER_WRITE,
vk::ImageLayout::UNDEFINED,
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
&clear_values,
&[vk::ImageSubresourceRange::default()
.aspect_mask(vk::ImageAspectFlags::COLOR)
.base_mip_level(0)
.base_array_layer(0)
.level_count(vk::REMAINING_MIP_LEVELS)
.layer_count(vk::REMAINING_ARRAY_LAYERS)],
None,
);
let barriers = [images::image_barrier(
cmd.clear_color_image(
frame.image,
frame.format,
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
clear_color,
&[images::SUBRESOURCERANGE_COLOR_ALL],
);
cmd.image_barrier(
frame.image,
vk::ImageAspectFlags::COLOR,
vk::PipelineStageFlags2::TRANSFER,
@ -2119,16 +2128,10 @@ impl<W> Renderer<W> {
vk::ImageLayout::TRANSFER_DST_OPTIMAL,
vk::ImageLayout::PRESENT_SRC_KHR,
None,
)];
let dependency_info = vk::DependencyInfo::default()
.dependency_flags(vk::DependencyFlags::BY_REGION)
.image_memory_barriers(&barriers);
dev.dev().cmd_pipeline_barrier2(buffer, &dependency_info);
);
let future = cmd.submit_async(
Some((frame.acquire, vk::PipelineStageFlags::ALL_COMMANDS)),
Some((frame.acquire, vk::PipelineStageFlags::TRANSFER)),
Some(frame.release),
Arc::new(sync::Fence::create(dev.clone())?),
)?;

View file

@ -1,6 +1,44 @@
use std::hash::Hash;
use ash::vk;
struct Rgba([f32; 4]);
#[derive(Debug, Clone, Copy)]
pub struct Rgba(pub [f32; 4]);
impl std::hash::Hash for Rgba {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
fn hash_f32<H: std::hash::Hasher>(state: &mut H, f: f32) {
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),
}
}
self.0.map(|f| hash_f32(state, f));
}
}
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)
}
}
enum LoadOp {
Clear(Rgba),

241
crates/renderer/src/util.rs Normal file
View file

@ -0,0 +1,241 @@
use std::ops::Deref;
use ash::vk;
pub trait MutexExt<'a, T: 'a> {
type Guard: Deref<Target = T> + 'a;
fn lock(&'a self) -> Self::Guard;
fn with_locked<R, F: FnOnce(&T) -> R>(&'a self, f: F) -> R {
let lock = MutexExt::lock(self);
f(&*lock)
}
}
impl<'a, T: 'a> MutexExt<'a, T> for parking_lot::Mutex<T> {
type Guard = parking_lot::MutexGuard<'a, T>;
fn lock(&'a self) -> Self::Guard {
self.lock()
}
}
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
}
}