Add generation of Format to autogen (#1687)

* Add generation of `Format` to autogen

* Better documentation
This commit is contained in:
Rua 2021-09-02 11:05:23 +02:00 committed by GitHub
parent b35d69b7b3
commit 7a50bd5cb5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 1448 additions and 926 deletions

View File

@ -147,7 +147,7 @@ fn main() {
let queue = queues.next().unwrap();
// Create an image in order to generate some additional logging:
let pixel_format = Format::R8G8B8A8Uint;
let pixel_format = Format::R8G8B8A8_UINT;
let dimensions = ImageDimensions::Dim2d {
width: 4096,
height: 4096,

View File

@ -110,21 +110,21 @@ impl FrameSystem {
diffuse: {
load: Clear,
store: DontCare,
format: Format::A2B10G10R10UnormPack32,
format: Format::A2B10G10R10_UNORM_PACK32,
samples: 1,
},
// Will be bound to `self.normals_buffer`.
normals: {
load: Clear,
store: DontCare,
format: Format::R16G16B16A16Sfloat,
format: Format::R16G16B16A16_SFLOAT,
samples: 1,
},
// Will be bound to `self.depth_buffer`.
depth: {
load: Clear,
store: DontCare,
format: Format::D16Unorm,
format: Format::D16_UNORM,
samples: 1,
}
},
@ -158,7 +158,7 @@ impl FrameSystem {
AttachmentImage::with_usage(
gfx_queue.device().clone(),
[1, 1],
Format::A2B10G10R10UnormPack32,
Format::A2B10G10R10_UNORM_PACK32,
atch_usage,
)
.unwrap(),
@ -168,7 +168,7 @@ impl FrameSystem {
AttachmentImage::with_usage(
gfx_queue.device().clone(),
[1, 1],
Format::R16G16B16A16Sfloat,
Format::R16G16B16A16_SFLOAT,
atch_usage,
)
.unwrap(),
@ -178,7 +178,7 @@ impl FrameSystem {
AttachmentImage::with_usage(
gfx_queue.device().clone(),
[1, 1],
Format::D16Unorm,
Format::D16_UNORM,
atch_usage,
)
.unwrap(),
@ -253,7 +253,7 @@ impl FrameSystem {
AttachmentImage::with_usage(
self.gfx_queue.device().clone(),
img_dims,
Format::A2B10G10R10UnormPack32,
Format::A2B10G10R10_UNORM_PACK32,
atch_usage,
)
.unwrap(),
@ -263,7 +263,7 @@ impl FrameSystem {
AttachmentImage::with_usage(
self.gfx_queue.device().clone(),
img_dims,
Format::R16G16B16A16Sfloat,
Format::R16G16B16A16_SFLOAT,
atch_usage,
)
.unwrap(),
@ -273,7 +273,7 @@ impl FrameSystem {
AttachmentImage::with_usage(
self.gfx_queue.device().clone(),
img_dims,
Format::D16Unorm,
Format::D16_UNORM,
atch_usage,
)
.unwrap(),

View File

@ -191,7 +191,7 @@ fn main() {
height: 1024,
array_layers: 1,
},
Format::R8G8B8A8Unorm,
Format::R8G8B8A8_UNORM,
Some(queue.family()),
)
.unwrap();

View File

@ -168,7 +168,7 @@ fn main() {
image_data.iter().cloned(),
dimensions,
MipmapsCount::One,
Format::R8G8B8A8Srgb,
Format::R8G8B8A8_SRGB,
queue.clone(),
)
.unwrap();

View File

@ -138,7 +138,7 @@ fn main() {
device.clone(),
[1024, 1024],
SampleCount::Sample4,
Format::R8G8B8A8Unorm,
Format::R8G8B8A8_UNORM,
)
.unwrap(),
)
@ -152,7 +152,7 @@ fn main() {
height: 1024,
array_layers: 1,
},
Format::R8G8B8A8Unorm,
Format::R8G8B8A8_UNORM,
Some(queue.family()),
)
.unwrap();
@ -170,14 +170,14 @@ fn main() {
intermediary: {
load: Clear,
store: DontCare,
format: Format::R8G8B8A8Unorm,
format: Format::R8G8B8A8_UNORM,
samples: 4, // This has to match the image definition.
},
// The second framebuffer attachment is the final image.
color: {
load: DontCare,
store: Store,
format: Format::R8G8B8A8Unorm,
format: Format::R8G8B8A8_UNORM,
samples: 1, // Same here, this has to match.
}
},

View File

@ -116,7 +116,7 @@ fn main() {
height: 512,
array_layers: 2,
},
Format::B8G8R8A8Srgb,
Format::B8G8R8A8_SRGB,
ImageUsage {
transfer_source: true,
color_attachment: true,

View File

@ -225,7 +225,7 @@ fn main() {
depth: {
load: Clear,
store: DontCare,
format: Format::D16Unorm,
format: Format::D16_UNORM,
samples: 1,
}
},
@ -448,7 +448,7 @@ fn window_size_dependent_setup(
AttachmentImage::with_usage(
render_pass.device().clone(),
dimensions,
Format::D16Unorm,
Format::D16_UNORM,
ImageUsage {
depth_stencil_attachment: true,
transient_attachment: true,

View File

@ -168,12 +168,12 @@ fn main() {
ShaderInterface::new_unchecked(vec![
ShaderInterfaceEntry {
location: 1..2,
format: Format::R32G32B32Sfloat,
format: Format::R32G32B32_SFLOAT,
name: Some(Cow::Borrowed("color")),
},
ShaderInterfaceEntry {
location: 0..1,
format: Format::R32G32Sfloat,
format: Format::R32G32_SFLOAT,
name: Some(Cow::Borrowed("position")),
},
])
@ -184,7 +184,7 @@ fn main() {
let vertex_output = unsafe {
ShaderInterface::new_unchecked(vec![ShaderInterfaceEntry {
location: 0..1,
format: Format::R32G32B32Sfloat,
format: Format::R32G32B32_SFLOAT,
name: Some(Cow::Borrowed("v_color")),
}])
};
@ -193,7 +193,7 @@ fn main() {
let fragment_input = unsafe {
ShaderInterface::new_unchecked(vec![ShaderInterfaceEntry {
location: 0..1,
format: Format::R32G32B32Sfloat,
format: Format::R32G32B32_SFLOAT,
name: Some(Cow::Borrowed("v_color")),
}])
};
@ -203,7 +203,7 @@ fn main() {
let fragment_output = unsafe {
ShaderInterface::new_unchecked(vec![ShaderInterfaceEntry {
location: 0..1,
format: Format::R32G32B32A32Sfloat,
format: Format::R32G32B32A32_SFLOAT,
name: Some(Cow::Borrowed("f_color")),
}])
};

View File

@ -12,6 +12,8 @@ use std::io::Cursor;
use std::sync::Arc;
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess};
use vulkano::command_buffer::{AutoCommandBufferBuilder, CommandBufferUsage, SubpassContents};
use vulkano::descriptor_set::layout::DescriptorSetLayout;
use vulkano::descriptor_set::layout::DescriptorSetLayoutError;
use vulkano::descriptor_set::PersistentDescriptorSet;
use vulkano::device::physical::{PhysicalDevice, PhysicalDeviceType};
use vulkano::device::{Device, DeviceExtensions, Features};
@ -20,6 +22,8 @@ use vulkano::image::{
view::ImageView, ImageDimensions, ImageUsage, ImmutableImage, MipmapsCount, SwapchainImage,
};
use vulkano::instance::Instance;
use vulkano::pipeline::layout::PipelineLayout;
use vulkano::pipeline::shader::EntryPointAbstract;
use vulkano::pipeline::viewport::Viewport;
use vulkano::pipeline::{GraphicsPipeline, PipelineBindPoint};
use vulkano::render_pass::{Framebuffer, FramebufferAbstract, RenderPass, Subpass};
@ -33,10 +37,6 @@ use vulkano_win::VkSurfaceBuild;
use winit::event::{Event, WindowEvent};
use winit::event_loop::{ControlFlow, EventLoop};
use winit::window::{Window, WindowBuilder};
use vulkano::pipeline::shader::EntryPointAbstract;
use vulkano::pipeline::layout::PipelineLayout;
use vulkano::descriptor_set::layout::DescriptorSetLayoutError;
use vulkano::descriptor_set::layout::DescriptorSetLayout;
fn main() {
// The start of this example is exactly the same as `triangle`. You should read the
@ -229,7 +229,7 @@ fn main() {
image_data.iter().cloned(),
dimensions,
MipmapsCount::One,
Format::R8G8B8A8Srgb,
Format::R8G8B8A8_SRGB,
queue.clone(),
)
.unwrap()
@ -256,7 +256,7 @@ fn main() {
image_data.iter().cloned(),
dimensions,
MipmapsCount::One,
Format::R8G8B8A8Srgb,
Format::R8G8B8A8_SRGB,
queue.clone(),
)
.unwrap()
@ -281,13 +281,12 @@ fn main() {
.unwrap();
let pipeline_layout = {
let mut descriptor_set_descs: Vec<_> =
(&fs.main_entry_point() as &dyn EntryPointAbstract)
.descriptor_set_layout_descs()
.iter()
.cloned()
.collect();
let mut descriptor_set_descs: Vec<_> = (&fs.main_entry_point() as &dyn EntryPointAbstract)
.descriptor_set_layout_descs()
.iter()
.cloned()
.collect();
// Set 0, Binding 0
descriptor_set_descs[0].set_variable_descriptor_count(0, 2);
@ -301,7 +300,7 @@ fn main() {
})
.collect::<Result<Vec<_>, DescriptorSetLayoutError>>()
.unwrap();
Arc::new(
PipelineLayout::new(
device.clone(),
@ -311,7 +310,7 @@ fn main() {
.iter()
.cloned(),
)
.unwrap()
.unwrap(),
)
};

View File

@ -135,7 +135,7 @@ fn main() {
depth: {
load: Clear,
store: DontCare,
format: Format::D16Unorm,
format: Format::D16_UNORM,
samples: 1,
}
},
@ -321,7 +321,7 @@ fn window_size_dependent_setup(
let dimensions = images[0].dimensions();
let depth_buffer = ImageView::new(
AttachmentImage::transient(device.clone(), dimensions, Format::D16Unorm).unwrap(),
AttachmentImage::transient(device.clone(), dimensions, Format::D16_UNORM).unwrap(),
)
.unwrap();

View File

@ -753,44 +753,44 @@ mod tests {
fn to_vulkan_format(spirv_format: ImageFormat) -> TokenStream {
match spirv_format {
ImageFormat::Unknown => quote! { None },
ImageFormat::Rgba32f => quote! { Some(Format::R32G32B32A32Sfloat) },
ImageFormat::Rgba16f => quote! { Some(Format::R16G16B16A16Sfloat) },
ImageFormat::R32f => quote! { Some(Format::R32Sfloat) },
ImageFormat::Rgba8 => quote! { Some(Format::R8G8B8A8Unorm) },
ImageFormat::Rgba8Snorm => quote! { Some(Format::R8G8B8A8Snorm) },
ImageFormat::Rg32f => quote! { Some(Format::R32G32Sfloat) },
ImageFormat::Rg16f => quote! { Some(Format::R16G16Sfloat) },
ImageFormat::R11fG11fB10f => quote! { Some(Format::B10G11R11UfloatPack32) },
ImageFormat::R16f => quote! { Some(Format::R16Sfloat) },
ImageFormat::Rgba16 => quote! { Some(Format::R16G16B16A16Unorm) },
ImageFormat::Rgb10A2 => quote! { Some(Format::A2B10G10R10UnormPack32) },
ImageFormat::Rg16 => quote! { Some(Format::R16G16Unorm) },
ImageFormat::Rg8 => quote! { Some(Format::R8G8Unorm) },
ImageFormat::R16 => quote! { Some(Format::R16Unorm) },
ImageFormat::R8 => quote! { Some(Format::R8Unorm) },
ImageFormat::Rgba16Snorm => quote! { Some(Format::R16G16B16A16Snorm) },
ImageFormat::Rg16Snorm => quote! { Some(Format::R16G16Snorm) },
ImageFormat::Rg8Snorm => quote! { Some(Format::R8G8Snorm) },
ImageFormat::R16Snorm => quote! { Some(Format::R16Snorm) },
ImageFormat::R8Snorm => quote! { Some(Format::R8Snorm) },
ImageFormat::Rgba32i => quote! { Some(Format::R32G32B32A32Sint) },
ImageFormat::Rgba16i => quote! { Some(Format::R16G16B16A16Sint) },
ImageFormat::Rgba8i => quote! { Some(Format::R8G8B8A8Sint) },
ImageFormat::R32i => quote! { Some(Format::R32Sint) },
ImageFormat::Rg32i => quote! { Some(Format::R32G32Sint) },
ImageFormat::Rg16i => quote! { Some(Format::R16G16Sint) },
ImageFormat::Rg8i => quote! { Some(Format::R8G8Sint) },
ImageFormat::R16i => quote! { Some(Format::R16Sint) },
ImageFormat::R8i => quote! { Some(Format::R8Sint) },
ImageFormat::Rgba32ui => quote! { Some(Format::R32G32B32A32Uint) },
ImageFormat::Rgba16ui => quote! { Some(Format::R16G16B16A16Uint) },
ImageFormat::Rgba8ui => quote! { Some(Format::R8G8B8A8Uint) },
ImageFormat::R32ui => quote! { Some(Format::R32Uint) },
ImageFormat::Rgb10a2ui => quote! { Some(Format::A2B10G10R10UintPack32) },
ImageFormat::Rg32ui => quote! { Some(Format::R32G32Uint) },
ImageFormat::Rg16ui => quote! { Some(Format::R16G16Uint) },
ImageFormat::Rg8ui => quote! { Some(Format::R8G8Uint) },
ImageFormat::R16ui => quote! { Some(Format::R16Uint) },
ImageFormat::R8ui => quote! { Some(Format::R8Uint) },
ImageFormat::Rgba32f => quote! { Some(Format::R32G32B32A32_SFLOAT) },
ImageFormat::Rgba16f => quote! { Some(Format::R16G16B16A16_SFLOAT) },
ImageFormat::R32f => quote! { Some(Format::R32_SFLOAT) },
ImageFormat::Rgba8 => quote! { Some(Format::R8G8B8A8_UNORM) },
ImageFormat::Rgba8Snorm => quote! { Some(Format::R8G8B8A8_SNORM) },
ImageFormat::Rg32f => quote! { Some(Format::R32G32_SFLOAT) },
ImageFormat::Rg16f => quote! { Some(Format::R16G16_SFLOAT) },
ImageFormat::R11fG11fB10f => quote! { Some(Format::B10G11R11_UFLOAT_PACK32) },
ImageFormat::R16f => quote! { Some(Format::R16_SFLOAT) },
ImageFormat::Rgba16 => quote! { Some(Format::R16G16B16A16_UNORM) },
ImageFormat::Rgb10A2 => quote! { Some(Format::A2B10G10R10_UNORMPack32) },
ImageFormat::Rg16 => quote! { Some(Format::R16G16_UNORM) },
ImageFormat::Rg8 => quote! { Some(Format::R8G8_UNORM) },
ImageFormat::R16 => quote! { Some(Format::R16_UNORM) },
ImageFormat::R8 => quote! { Some(Format::R8_UNORM) },
ImageFormat::Rgba16Snorm => quote! { Some(Format::R16G16B16A16_SNORM) },
ImageFormat::Rg16Snorm => quote! { Some(Format::R16G16_SNORM) },
ImageFormat::Rg8Snorm => quote! { Some(Format::R8G8_SNORM) },
ImageFormat::R16Snorm => quote! { Some(Format::R16_SNORM) },
ImageFormat::R8Snorm => quote! { Some(Format::R8_SNORM) },
ImageFormat::Rgba32i => quote! { Some(Format::R32G32B32A32_SINT) },
ImageFormat::Rgba16i => quote! { Some(Format::R16G16B16A16_SINT) },
ImageFormat::Rgba8i => quote! { Some(Format::R8G8B8A8_SINT) },
ImageFormat::R32i => quote! { Some(Format::R32_SINT) },
ImageFormat::Rg32i => quote! { Some(Format::R32G32_SINT) },
ImageFormat::Rg16i => quote! { Some(Format::R16G16_SINT) },
ImageFormat::Rg8i => quote! { Some(Format::R8G8_SINT) },
ImageFormat::R16i => quote! { Some(Format::R16_SINT) },
ImageFormat::R8i => quote! { Some(Format::R8_SINT) },
ImageFormat::Rgba32ui => quote! { Some(Format::R32G32B32A32_UINT) },
ImageFormat::Rgba16ui => quote! { Some(Format::R16G16B16A16_UINT) },
ImageFormat::Rgba8ui => quote! { Some(Format::R8G8B8A8_UINT) },
ImageFormat::R32ui => quote! { Some(Format::R32_UINT) },
ImageFormat::Rgb10a2ui => quote! { Some(Format::A2B10G10R10_UINT_PACK32) },
ImageFormat::Rg32ui => quote! { Some(Format::R32G32_UINT) },
ImageFormat::Rg16ui => quote! { Some(Format::R16G16_UINT) },
ImageFormat::Rg8ui => quote! { Some(Format::R8G8_UINT) },
ImageFormat::R16ui => quote! { Some(Format::R16_UINT) },
ImageFormat::R8ui => quote! { Some(Format::R8_UINT) },
}
}

View File

@ -25,14 +25,14 @@ pub fn format_from_id(doc: &Spirv, searched: u32, ignore_first_array: bool) -> (
} if result_id == searched => {
assert!(!ignore_first_array);
let format = match (width, signedness) {
(8, true) => "R8Sint",
(8, false) => "R8Uint",
(16, true) => "R16Sint",
(16, false) => "R16Uint",
(32, true) => "R32Sint",
(32, false) => "R32Uint",
(64, true) => "R64Sint",
(64, false) => "R64Uint",
(8, true) => "R8_SINT",
(8, false) => "R8_UINT",
(16, true) => "R16_SINT",
(16, false) => "R16_UINT",
(32, true) => "R32_SINT",
(32, false) => "R32_UINT",
(64, true) => "R64_SINT",
(64, false) => "R64_UINT",
_ => panic!(),
};
return (format.to_string(), 1);
@ -40,8 +40,8 @@ pub fn format_from_id(doc: &Spirv, searched: u32, ignore_first_array: bool) -> (
&Instruction::TypeFloat { result_id, width } if result_id == searched => {
assert!(!ignore_first_array);
let format = match width {
32 => "R32Sfloat",
64 => "R64Sfloat",
32 => "R32_SFLOAT",
64 => "R64_SFLOAT",
_ => panic!(),
};
return (format.to_string(), 1);

View File

@ -28,6 +28,7 @@ smallvec = "1.6"
[build-dependencies]
heck = "0.3"
indexmap = "1.7"
lazy_static = "1.4"
proc-macro2 = "1.0"
quote = "1.0"
regex = "1.5"

724
vulkano/autogen/formats.rs Normal file
View File

@ -0,0 +1,724 @@
// Copyright (c) 2021 The Vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.
use lazy_static::lazy_static;
use proc_macro2::{Ident, Literal, TokenStream};
use quote::{format_ident, quote};
use regex::Regex;
pub fn write(formats: &[&str]) -> TokenStream {
write_formats(&make_formats(formats))
}
#[derive(Clone, Debug)]
struct FormatMember {
name: Ident,
ffi_name: Ident,
aspect_color: bool,
aspect_depth: bool,
aspect_stencil: bool,
aspect_plane0: bool,
aspect_plane1: bool,
aspect_plane2: bool,
block_dimensions: [u32; 2],
compatibility: TokenStream,
components: [u8; 4],
compression: Option<Ident>,
planes: Vec<Ident>,
size: Option<u64>,
type_color: Option<Ident>,
type_depth: Option<Ident>,
type_stencil: Option<Ident>,
}
fn write_formats(members: &[FormatMember]) -> TokenStream {
let enum_items = members.iter().map(|FormatMember { name, ffi_name, .. }| {
quote! { #name = ash::vk::Format::#ffi_name.as_raw(), }
});
let aspects_color_items = members.iter().filter_map(
|FormatMember {
name, aspect_color, ..
}| {
if !aspect_color {
// Negated to reduce the length of the list
Some(name)
} else {
None
}
},
);
let aspects_depth_items = members.iter().filter_map(
|FormatMember {
name, aspect_depth, ..
}| {
if *aspect_depth {
Some(name)
} else {
None
}
},
);
let aspects_stencil_items = members.iter().filter_map(
|FormatMember {
name,
aspect_stencil,
..
}| {
if *aspect_stencil {
Some(name)
} else {
None
}
},
);
let aspects_plane0_items = members.iter().filter_map(
|FormatMember {
name,
aspect_plane0,
..
}| {
if *aspect_plane0 {
Some(name)
} else {
None
}
},
);
let aspects_plane1_items = members.iter().filter_map(
|FormatMember {
name,
aspect_plane1,
..
}| {
if *aspect_plane1 {
Some(name)
} else {
None
}
},
);
let aspects_plane2_items = members.iter().filter_map(
|FormatMember {
name,
aspect_plane2,
..
}| {
if *aspect_plane2 {
Some(name)
} else {
None
}
},
);
let block_dimensions_items = members.iter().filter_map(
|FormatMember {
name,
block_dimensions: [x, y],
..
}| {
if *x == 1 && *y == 1 {
None
} else {
let x = Literal::u32_unsuffixed(*x);
let y = Literal::u32_unsuffixed(*y);
Some(quote! { Self::#name => [#x, #y], })
}
},
);
let compatibility_items = members.iter().map(
|FormatMember {
name,
compatibility,
..
}| {
quote! {
Self::#name => &FormatCompatibilityInner::#compatibility,
}
},
);
let components_items = members.iter().map(
|FormatMember {
name, components, ..
}| {
let components = components.iter().map(|c| Literal::u8_unsuffixed(*c));
quote! {
Self::#name => [#(#components),*],
}
},
);
let compression_items = members.iter().filter_map(
|FormatMember {
name, compression, ..
}| {
compression
.as_ref()
.map(|x| quote! { Self::#name => Some(CompressionType::#x), })
},
);
let planes_items = members
.iter()
.filter_map(|FormatMember { name, planes, .. }| {
if planes.is_empty() {
None
} else {
Some(quote! { Self::#name => &[#(Self::#planes),*], })
}
});
let size_items = members
.iter()
.filter_map(|FormatMember { name, size, .. }| {
size.as_ref().map(|size| {
let size = Literal::u64_unsuffixed(*size);
quote! { Self::#name => Some(#size), }
})
});
let type_color_items = members.iter().filter_map(
|FormatMember {
name, type_color, ..
}| {
type_color
.as_ref()
.map(|ty| quote! { Self::#name => Some(NumericType::#ty), })
},
);
let type_depth_items = members.iter().filter_map(
|FormatMember {
name, type_depth, ..
}| {
type_depth
.as_ref()
.map(|ty| quote! { Self::#name => Some(NumericType::#ty), })
},
);
let type_stencil_items = members.iter().filter_map(
|FormatMember {
name, type_stencil, ..
}| {
type_stencil
.as_ref()
.map(|ty| quote! { Self::#name => Some(NumericType::#ty), })
},
);
let try_from_items = members.iter().map(|FormatMember { name, ffi_name, .. }| {
quote! { ash::vk::Format::#ffi_name => Ok(Self::#name), }
});
quote! {
/// An enumeration of all the possible formats.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[repr(i32)]
#[allow(non_camel_case_types)]
pub enum Format {
#(#enum_items)*
}
impl Format {
/// Returns the aspects that images of this format have.
pub fn aspects(&self) -> crate::image::ImageAspects {
crate::image::ImageAspects {
color: !matches!(self, #(Format::#aspects_color_items)|* ),
depth: matches!(self, #(Format::#aspects_depth_items)|* ),
stencil: matches!(self, #(Format::#aspects_stencil_items)|* ),
plane0: matches!(self, #(Format::#aspects_plane0_items)|* ),
plane1: matches!(self, #(Format::#aspects_plane1_items)|* ),
plane2: matches!(self, #(Format::#aspects_plane2_items)|* ),
..crate::image::ImageAspects::none()
}
}
/// Returns the dimensions in texels (horizontally and vertically) of a single texel
/// block of this format. A texel block is a rectangle of pixels that is represented by
/// a single element of this format. It is also the minimum granularity of the size of
/// an image; images must always have a size that's a multiple of the block size.
///
/// For normal formats, the block size is [1, 1], meaning that each element of the
/// format represents one texel. Block-compressed formats encode multiple texels into
/// a single element. The 422 and 420 YCbCr formats have a block size of [2, 1] and
/// [2, 2] respectively, as the red and blue components are shared across multiple
/// texels.
pub fn block_dimensions(&self) -> [u32; 2] {
match self {
#(#block_dimensions_items)*
_ => [1, 1],
}
}
/// Returns the an opaque object representing the compatibility class of the format.
/// This can be used to determine whether two formats are compatible for the purposes
/// of certain Vulkan operations, such as image copying.
pub fn compatibility(&self) -> crate::format::FormatCompatibility {
use crate::format::{CompressionType, FormatCompatibilityInner};
crate::format::FormatCompatibility(match self {
#(#compatibility_items)*
})
}
/// Returns the number of bits per texel block that each component (R, G, B, A) is
/// represented with. Components that are not present in the format have 0 bits.
///
/// For depth/stencil formats, the depth component is the first, stencil the second. For
/// multi-planar formats, this is the number of bits across all planes.
///
/// For block-compressed formats, the number of bits in individual components is not
/// well-defined, and the return value will is merely binary: 1 indicates a component
/// that is present in the format, 0 indicates one that is absent.
pub fn components(&self) -> [u8; 4] {
match self {
#(#components_items)*
}
}
/// Returns the block compression scheme used for this format, if any. Returns `None` if
/// the format does not use compression.
pub fn compression(&self) -> Option<crate::format::CompressionType> {
use crate::format::CompressionType;
match self {
#(#compression_items)*
_ => None,
}
}
/// For multi-planar formats, returns a slice of length 2 or 3, containing the
/// equivalent regular format of each plane.
///
/// For non-planar formats, returns the empty slice.
pub fn planes(&self) -> &'static [Self] {
match self {
#(#planes_items)*
_ => &[],
}
}
/// Returns the size in bytes of a single texel block of this format. Returns `None`
/// if the texel block size is not well-defined for this format.
///
/// For regular formats, this is the size of a single texel, but for more specialized
/// formats this may be the size of multiple texels.
///
/// Depth/stencil formats are considered to have an opaque memory representation, and do
/// not have a well-defined size. Multi-planar formats store the color components
/// disjointly in memory, and therefore do not have a well-defined size for all
/// components as a whole. The individual planes do have a well-defined size.
pub fn size(&self) -> Option<crate::DeviceSize> {
match self {
#(#size_items)*
_ => None,
}
}
/// Returns the numeric data type of the color aspect of this format. Returns `None`
/// for depth/stencil formats.
pub fn type_color(&self) -> Option<crate::format::NumericType> {
use crate::format::NumericType;
match self {
#(#type_color_items)*
_ => None,
}
}
/// Returns the numeric data type of the depth aspect of this format. Returns `None`
/// color and stencil-only formats.
pub fn type_depth(&self) -> Option<crate::format::NumericType> {
use crate::format::NumericType;
match self {
#(#type_depth_items)*
_ => None,
}
}
/// Returns the numeric data type of the stencil aspect of this format. Returns `None`
/// for color and depth-only formats.
pub fn type_stencil(&self) -> Option<crate::format::NumericType> {
use crate::format::NumericType;
match self {
#(#type_stencil_items)*
_ => None,
}
}
}
impl std::convert::TryFrom<ash::vk::Format> for Format {
type Error = ();
fn try_from(val: ash::vk::Format) -> Result<Format, ()> {
match val {
#(#try_from_items)*
_ => Err(()),
}
}
}
}
}
lazy_static! {
static ref DEPTH_REGEX: Regex = Regex::new(r"^D\d+$").unwrap();
static ref STENCIL_REGEX: Regex = Regex::new(r"^S\d+$").unwrap();
static ref PACK_REGEX: Regex = Regex::new(r"^(\d*)PACK(\d+)$").unwrap();
static ref COMPONENTS_REGEX: Regex = Regex::new(r"([ABDEGRSX])(\d+)").unwrap();
static ref RGB_COMPONENTS_REGEX: Regex = Regex::new(r"([BGR])(\d+)").unwrap();
}
fn make_formats(formats: &[&str]) -> Vec<FormatMember> {
let mut members = formats
.iter()
.map(|vulkan_name| {
let vulkan_name = vulkan_name.strip_prefix("VK_FORMAT_").unwrap();
let ffi_name = format_ident!("{}", vulkan_name.to_ascii_uppercase());
let mut parts = vulkan_name.split('_').collect::<Vec<_>>();
if ["EXT", "IMG"].contains(parts.last().unwrap()) {
parts.pop();
}
let name = format_ident!("{}", parts.join("_"));
let mut member = FormatMember {
name: name.clone(),
ffi_name: ffi_name.clone(),
aspect_color: false,
aspect_depth: false,
aspect_stencil: false,
aspect_plane0: false,
aspect_plane1: false,
aspect_plane2: false,
block_dimensions: [1, 1],
compatibility: Default::default(),
components: [0u8; 4],
compression: None,
planes: vec![],
size: None,
type_color: None,
type_depth: None,
type_stencil: None,
};
let depth_match = parts.iter().position(|part| DEPTH_REGEX.is_match(part));
let stencil_match = parts.iter().position(|part| STENCIL_REGEX.is_match(part));
if depth_match.is_some() || stencil_match.is_some() {
// Depth+stencil formats
member.compatibility = quote! {
DepthStencil { ty: Self::#name as u8 }
};
if let Some(pos) = depth_match {
let (_, components) = components(vulkan_name, &parts[pos..pos + 1]);
member.aspect_depth = true;
member.components[0] = components[0];
member.type_depth = Some(format_ident!("{}", parts[pos + 1]));
}
if let Some(pos) = stencil_match {
let (_, components) = components(vulkan_name, &parts[pos..pos + 1]);
member.aspect_stencil = true;
member.components[1] = components[1];
member.type_stencil = Some(format_ident!("{}", parts[pos + 1]));
}
} else if *parts.last().unwrap() == "BLOCK" {
// Block-compressed formats
parts.pop();
let numeric_type = format_ident!("{}", parts.pop().unwrap());
let ty = parts[0];
let mut subtype: u8 = 0;
let (block_size, components) = if ty == "ASTC" {
let dim = parts[1].split_once('x').unwrap();
member.block_dimensions = [dim.0.parse().unwrap(), dim.1.parse().unwrap()];
subtype =
(member.block_dimensions[0] as u8) << 4 | member.block_dimensions[1] as u8;
(16, [1, 1, 1, 1])
} else if ty == "BC1" && parts[1] == "RGB" {
member.block_dimensions = [4, 4];
subtype = 3;
(8, [1, 1, 1, 0])
} else if ty == "BC1" && parts[1] == "RGBA" {
member.block_dimensions = [4, 4];
subtype = 4;
(8, [1, 1, 1, 1])
} else if ty == "BC4" {
member.block_dimensions = [4, 4];
(8, [1, 0, 0, 0])
} else if ty == "BC5" {
member.block_dimensions = [4, 4];
(16, [1, 1, 0, 0])
} else if ty == "BC6H" {
member.block_dimensions = [4, 4];
(16, [1, 1, 1, 0])
} else if ty == "BC2" || ty == "BC3" || ty == "BC7" {
member.block_dimensions = [4, 4];
(16, [1, 1, 1, 1])
} else if ty == "EAC" && parts[1] == "R11" {
member.block_dimensions = [4, 4];
subtype = 1;
(8, [1, 0, 0, 0])
} else if ty == "EAC" && parts[1] == "R11G11" {
member.block_dimensions = [4, 4];
subtype = 2;
(16, [1, 1, 0, 0])
} else if ty == "ETC2" && parts[1] == "R8G8B8" {
member.block_dimensions = [4, 4];
subtype = 3;
(8, [1, 1, 1, 0])
} else if ty == "ETC2" && parts[1] == "R8G8B8A1" {
member.block_dimensions = [4, 4];
subtype = 31;
(8, [1, 1, 1, 1])
} else if ty == "ETC2" && parts[1] == "R8G8B8A8" {
member.block_dimensions = [4, 4];
subtype = 4;
(16, [1, 1, 1, 1])
} else if ty.starts_with("PVRTC") {
if parts[1] == "2BPP" {
member.block_dimensions = [8, 4];
subtype = 2;
} else if parts[1] == "4BPP" {
member.block_dimensions = [4, 4];
subtype = 4;
}
(8, [1, 1, 1, 1])
} else {
panic!("Unrecognised block compression format: {}", vulkan_name);
};
let compression = format_ident!("{}", ty);
member.aspect_color = true;
member.compatibility = quote! {
Compressed {
compression: CompressionType::#compression,
subtype: #subtype,
}
};
member.components = components;
member.compression = Some(compression);
member.size = Some(block_size);
member.type_color = Some(numeric_type);
} else {
// Other formats
let many_pack = PACK_REGEX
.captures(*parts.last().unwrap())
.map(|captures| {
parts.pop();
let first = captures.get(1).unwrap().as_str();
first == "3" || first == "4"
})
.unwrap_or(false);
let numeric_type = parts.pop().unwrap();
member.aspect_color = true;
member.type_color = Some(format_ident!("{}", numeric_type));
if ["420", "422", "444"].contains(parts.last().unwrap()) {
let ty = parts.pop().unwrap();
if ty == "420" {
member.block_dimensions = [2, 2];
} else if ty == "422" {
member.block_dimensions = [2, 1];
}
}
let size_factor =
member.block_dimensions[0] as u64 * member.block_dimensions[1] as u64;
if let Some(planes) = parts.last().unwrap().strip_suffix("PLANE") {
// Multi-planar formats
let planes: usize = planes.parse().unwrap();
parts.pop();
let captures = COMPONENTS_REGEX.captures(parts[0]).unwrap();
let bits: u8 = captures.get(2).unwrap().as_str().parse().unwrap();
{
member.aspect_plane0 = true;
member
.planes
.push(plane_format(&parts[0], numeric_type, bits));
}
{
member.aspect_plane1 = true;
member
.planes
.push(plane_format(&parts[1], numeric_type, bits));
}
if planes == 3 {
member.aspect_plane2 = true;
member
.planes
.push(plane_format(&parts[2], numeric_type, bits));
}
let compatibility = format_ident!("YCbCr{}Plane", planes);
let (_, mut components) = components(vulkan_name, &parts);
let plane0_index = component_index(captures.get(1).unwrap().as_str()).unwrap();
components[plane0_index] *= size_factor as u8;
let block_texels = size_factor as u8;
member.compatibility = quote! {
#compatibility {
bits: #bits,
block_texels: #block_texels,
}
};
member.components = components;
} else {
// Non-planar formats
{
let (block_size, components) = components(vulkan_name, &parts);
member.components = components;
member.size = Some(block_size * size_factor);
if size_factor != 1 {
let captures = COMPONENTS_REGEX.captures(parts[0]).unwrap();
let bits: u8 = captures.get(2).unwrap().as_str().parse().unwrap();
let g_even = captures.get(1).unwrap().as_str() != "G";
member.compatibility = quote! {
YCbCr1Plane {
bits: #bits,
g_even: #g_even,
}
};
} else if many_pack {
let captures = COMPONENTS_REGEX.captures(parts[0]).unwrap();
let bits: u8 = captures.get(2).unwrap().as_str().parse().unwrap();
member.compatibility = quote! {
YCbCrRGBA {
bits: #bits,
}
};
} else {
let size = block_size as u8;
member.compatibility = quote! {
Normal {
size: #size,
}
};
}
}
}
}
debug_assert!(
!member.components.iter().all(|x| *x == 0),
"format {} has 0 components",
vulkan_name
);
debug_assert!(
member.type_color.is_some()
|| member.type_depth.is_some()
|| member.type_stencil.is_some(),
"format {} has no numeric type",
vulkan_name,
);
member
})
.collect::<Vec<_>>();
members.sort_by_key(|member| {
if member.aspect_plane0 {
if member.block_dimensions == [2, 2] {
10
} else if member.block_dimensions == [2, 1] {
11
} else {
12
}
} else if member.compression.is_some() {
1
} else if member.block_dimensions != [1, 1] {
5
} else {
0
}
});
members
}
fn components(vulkan_name: &str, parts: &[&str]) -> (u64, [u8; 4]) {
let mut total_bits = 0;
let mut components = [0u8; 4];
for &part in parts {
for component in COMPONENTS_REGEX.captures_iter(part) {
let bits: u64 = component.get(2).unwrap().as_str().parse().unwrap();
total_bits += bits;
let index = match component_index(component.get(1).unwrap().as_str()) {
Some(x) => x,
None => continue,
};
components[index] += bits as u8;
}
}
if total_bits % 8 != 0 {
panic!("total bits is not divisible by 0 for {}", vulkan_name);
}
(total_bits / 8, components)
}
fn component_index(letter: &str) -> Option<usize> {
match letter {
"R" | "D" => Some(0),
"G" | "S" => Some(1),
"B" => Some(2),
"A" => Some(3),
_ => None,
}
}
fn plane_format(part: &str, numeric_type: &str, bits: u8) -> Ident {
let mut format = part.to_owned();
let mut num_components = 0;
for (index, component) in RGB_COMPONENTS_REGEX.captures_iter(part).enumerate() {
let capture = component.get(1).unwrap();
let letter = match index {
0 => "R",
1 => "G",
2 => "B",
_ => unimplemented!(),
};
num_components += 1;
unsafe {
format[capture.range()]
.as_bytes_mut()
.copy_from_slice(letter.as_bytes());
}
}
if bits % 8 == 0 {
format_ident!("{}_{}", format, numeric_type)
} else {
assert!(bits > 8 && bits < 16);
let prefix = format!("{}", num_components);
format_ident!(
"{}_{}_{}PACK16",
format,
numeric_type,
if num_components == 1 { "" } else { &prefix }
)
}
}

View File

@ -11,13 +11,14 @@ use indexmap::IndexMap;
use quote::quote;
use std::{collections::HashMap, io::Write, path::Path};
use vk_parse::{
Extension, ExtensionChild, Feature, InterfaceItem, Registry, RegistryChild, Type,
TypeCodeMarkup, TypeSpec, TypesChild,
EnumSpec, EnumsChild, Extension, ExtensionChild, Feature, InterfaceItem, Registry,
RegistryChild, Type, TypeCodeMarkup, TypeSpec, TypesChild,
};
mod extensions;
mod features;
mod fns;
mod formats;
mod properties;
pub fn write<W: Write>(writer: &mut W) {
@ -25,11 +26,17 @@ pub fn write<W: Write>(writer: &mut W) {
let aliases = get_aliases(&registry);
let extensions = get_extensions(&registry);
let features = get_features(&registry);
let formats = get_formats(
&registry,
features.values().map(|x| x.children.iter()).flatten(),
extensions.values().map(|x| x.children.iter()).flatten(),
);
let types = get_types(&registry, &aliases, &features, &extensions);
let header_version = get_header_version(&registry);
let out_extensions = extensions::write(&extensions);
let out_features = features::write(&types, &extensions);
let out_formats = formats::write(&formats);
let out_fns = fns::write(&extensions);
let out_properties = properties::write(&types, &extensions);
@ -44,6 +51,7 @@ pub fn write<W: Write>(writer: &mut W) {
quote! {
#out_extensions
#out_features
#out_formats
#out_fns
#out_properties
}
@ -135,6 +143,54 @@ fn get_features(registry: &Registry) -> IndexMap<&str, &Feature> {
.collect()
}
fn get_formats<'a>(
registry: &'a Registry,
features: impl IntoIterator<Item = &'a ExtensionChild>,
extensions: impl IntoIterator<Item = &'a ExtensionChild>,
) -> Vec<&'a str> {
registry
.0
.iter()
.filter_map(|child| {
if let RegistryChild::Enums(enums) = child {
if enums.name.as_ref().map(|s| s.as_str()) == Some("VkFormat") {
return Some(enums.children.iter().filter_map(|en| {
if let EnumsChild::Enum(en) = en {
if en.name != "VK_FORMAT_UNDEFINED" {
return Some(en.name.as_str());
}
}
None
}));
}
}
None
})
.flatten()
.chain(
features
.into_iter()
.chain(extensions.into_iter())
.filter_map(|child| {
if let ExtensionChild::Require { items, .. } = child {
return Some(items.iter().filter_map(|item| {
if let InterfaceItem::Enum(en) = item {
if let EnumSpec::Offset { extends, .. } = &en.spec {
if extends == "VkFormat" {
return Some(en.name.as_str());
}
}
}
None
}));
}
None
})
.flatten(),
)
.collect()
}
fn get_types<'a>(
registry: &'a Registry,
aliases: &'a HashMap<&str, &str>,

View File

@ -33,7 +33,7 @@
//!
//! let (buffer, _future) = ImmutableBuffer::<[u32]>::from_iter((0..128).map(|n| n), usage,
//! queue.clone()).unwrap();
//! let _view = BufferView::new(buffer, Format::R32Uint).unwrap();
//! let _view = BufferView::new(buffer, Format::R32_UINT).unwrap();
//! ```
use crate::buffer::BufferAccess;
@ -60,7 +60,7 @@ pub struct BufferView<B>
where
B: BufferAccess + ?Sized,
{
view: ash::vk::BufferView,
handle: ash::vk::BufferView,
buffer: Box<B>,
atomic_accesses: bool,
}
@ -87,64 +87,52 @@ where
where
B: BufferAccess,
{
let (view, format_props) = {
let size = org_buffer.size();
let BufferInner { buffer, offset } = org_buffer.inner();
let size = org_buffer.size();
let BufferInner { buffer, offset } = org_buffer.inner();
let device = buffer.device();
let device = buffer.device();
if (offset
% device
.physical_device()
.properties()
.min_texel_buffer_offset_alignment)
!= 0
{
return Err(BufferViewCreationError::WrongBufferAlignment);
if (offset
% device
.physical_device()
.properties()
.min_texel_buffer_offset_alignment)
!= 0
{
return Err(BufferViewCreationError::WrongBufferAlignment);
}
if !(buffer.usage().uniform_texel_buffer || buffer.usage().storage_texel_buffer) {
return Err(BufferViewCreationError::WrongBufferUsage);
}
let buffer_features = format.properties(device.physical_device()).buffer_features;
if buffer.usage().uniform_texel_buffer {
if !buffer_features.uniform_texel_buffer {
return Err(BufferViewCreationError::UnsupportedFormat);
}
}
if !buffer.usage().uniform_texel_buffer && !buffer.usage().storage_texel_buffer {
return Err(BufferViewCreationError::WrongBufferUsage);
if buffer.usage().storage_texel_buffer {
if !buffer_features.storage_texel_buffer {
return Err(BufferViewCreationError::UnsupportedFormat);
}
}
{
let nb = size
/ format
.size()
.expect("Can't use a compressed format for buffer views");
let l = device
.physical_device()
.properties()
.max_texel_buffer_elements;
if nb as u32 > l {
return Err(BufferViewCreationError::MaxTexelBufferElementsExceeded);
}
}
let format_props = {
let fns_i = device.instance().fns();
let mut output = MaybeUninit::uninit();
fns_i.v1_0.get_physical_device_format_properties(
device.physical_device().internal_object(),
format.into(),
output.as_mut_ptr(),
);
output.assume_init().buffer_features
};
if buffer.usage().uniform_texel_buffer {
if (format_props & ash::vk::FormatFeatureFlags::UNIFORM_TEXEL_BUFFER).is_empty() {
return Err(BufferViewCreationError::UnsupportedFormat);
}
}
if buffer.usage().storage_texel_buffer {
if (format_props & ash::vk::FormatFeatureFlags::STORAGE_TEXEL_BUFFER).is_empty() {
return Err(BufferViewCreationError::UnsupportedFormat);
}
}
let elements = size / format.size().expect(
"Format has no size. If you see this error, please submit a new bug report to Vulkano.",
);
if elements as u32
> device
.physical_device()
.properties()
.max_texel_buffer_elements
{
return Err(BufferViewCreationError::MaxTexelBufferElementsExceeded);
}
let handle = {
let infos = ash::vk::BufferViewCreateInfo {
flags: ash::vk::BufferViewCreateFlags::empty(),
buffer: buffer.internal_object(),
@ -162,15 +150,13 @@ where
ptr::null(),
output.as_mut_ptr(),
))?;
(output.assume_init(), format_props)
output.assume_init()
};
Ok(BufferView {
view,
handle,
buffer: Box::new(org_buffer),
atomic_accesses: !(format_props
& ash::vk::FormatFeatureFlags::STORAGE_TEXEL_BUFFER_ATOMIC)
.is_empty(),
atomic_accesses: buffer_features.storage_texel_buffer_atomic,
})
}
@ -207,7 +193,7 @@ where
#[inline]
fn internal_object(&self) -> ash::vk::BufferView {
self.view
self.handle
}
}
@ -227,7 +213,7 @@ where
{
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
fmt.debug_struct("BufferView")
.field("raw", &self.view)
.field("raw", &self.handle)
.field("buffer", &self.buffer)
.finish()
}
@ -243,7 +229,7 @@ where
let fns = self.buffer.inner().buffer.device().fns();
fns.v1_0.destroy_buffer_view(
self.buffer.inner().buffer.device().internal_object(),
self.view,
self.handle,
ptr::null(),
);
}
@ -373,7 +359,7 @@ mod tests {
let (buffer, _) =
ImmutableBuffer::<[[u8; 4]]>::from_iter((0..128).map(|_| [0; 4]), usage, queue.clone())
.unwrap();
let view = BufferView::new(buffer, Format::R8G8B8A8Unorm).unwrap();
let view = BufferView::new(buffer, Format::R8G8B8A8_UNORM).unwrap();
assert!(view.uniform_texel_buffer());
}
@ -391,7 +377,7 @@ mod tests {
let (buffer, _) =
ImmutableBuffer::<[[u8; 4]]>::from_iter((0..128).map(|_| [0; 4]), usage, queue.clone())
.unwrap();
let view = BufferView::new(buffer, Format::R8G8B8A8Unorm).unwrap();
let view = BufferView::new(buffer, Format::R8G8B8A8_UNORM).unwrap();
assert!(view.storage_texel_buffer());
}
@ -408,7 +394,7 @@ mod tests {
let (buffer, _) =
ImmutableBuffer::<[u32]>::from_iter((0..128).map(|_| 0), usage, queue.clone()).unwrap();
let view = BufferView::new(buffer, Format::R32Uint).unwrap();
let view = BufferView::new(buffer, Format::R32_UINT).unwrap();
assert!(view.storage_texel_buffer());
assert!(view.storage_texel_buffer_atomic());
@ -426,7 +412,7 @@ mod tests {
)
.unwrap();
match BufferView::new(buffer, Format::R8G8B8A8Unorm) {
match BufferView::new(buffer, Format::R8G8B8A8_UNORM) {
Err(BufferViewCreationError::WrongBufferUsage) => (),
_ => panic!(),
}
@ -449,8 +435,8 @@ mod tests {
)
.unwrap();
// TODO: what if R64G64B64A64Sfloat is supported?
match BufferView::new(buffer, Format::R64G64B64A64Sfloat) {
// TODO: what if R64G64B64A64_SFLOAT is supported?
match BufferView::new(buffer, Format::R64G64B64A64_SFLOAT) {
Err(BufferViewCreationError::UnsupportedFormat) => (),
_ => panic!(),
}

View File

@ -40,7 +40,7 @@ use crate::device::Device;
use crate::device::DeviceOwned;
use crate::device::Queue;
use crate::format::ClearValue;
use crate::format::FormatTy;
use crate::format::NumericType;
use crate::format::Pixel;
use crate::image::ImageAccess;
use crate::image::ImageAspect;
@ -852,7 +852,7 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
let blit = UnsafeCommandBufferBuilderImageBlit {
// TODO:
aspects: if source.has_color() {
aspects: if source.format().aspects().color {
ImageAspects {
color: true,
..ImageAspects::none()
@ -1072,7 +1072,7 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
buffer_offset: 0,
buffer_row_length: 0,
buffer_image_height: 0,
image_aspect: if destination.has_color() {
image_aspect: if destination.format().aspects().color {
ImageAspect::Color
} else {
unimplemented!()
@ -1150,15 +1150,19 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
layer_count,
)?;
let source_aspects = source.format().aspects();
let destination_aspects = destination.format().aspects();
let copy = UnsafeCommandBufferBuilderImageCopy {
// TODO: Allowing choosing a subset of the image aspects, but note that if color
// is included, neither depth nor stencil may.
aspects: ImageAspects {
color: source.has_color(),
depth: !source.has_color() && source.has_depth() && destination.has_depth(),
stencil: !source.has_color()
&& source.has_stencil()
&& destination.has_stencil(),
color: source_aspects.color,
depth: !source_aspects.color
&& source_aspects.depth
&& destination_aspects.depth,
stencil: !source_aspects.color
&& source_aspects.stencil
&& destination_aspects.stencil,
..ImageAspects::none()
},
source_mip_level,
@ -1234,16 +1238,17 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
mipmap,
)?;
let source_aspects = source.format().aspects();
let copy = UnsafeCommandBufferBuilderBufferImageCopy {
buffer_offset: 0,
buffer_row_length: 0,
buffer_image_height: 0,
// TODO: Allow the user to choose aspect
image_aspect: if source.has_color() {
image_aspect: if source_aspects.color {
ImageAspect::Color
} else if source.has_depth() {
} else if source_aspects.depth {
ImageAspect::Depth
} else if source.has_stencil() {
} else if source_aspects.stencil {
ImageAspect::Stencil
} else {
unimplemented!()
@ -2182,39 +2187,79 @@ where
match clear_values_copy.next() {
Some((clear_i, clear_value)) => {
if atch_desc.load == LoadOp::Clear {
match clear_value {
ClearValue::None => panic!("Bad ClearValue! index: {}, attachment index: {}, expected: {:?}, got: None",
clear_i, atch_i, atch_desc.format.ty()),
ClearValue::Float(_) => if atch_desc.format.ty() != FormatTy::Float {
panic!("Bad ClearValue! index: {}, attachment index: {}, expected: {:?}, got: Float",
clear_i, atch_i, atch_desc.format.ty());
}
ClearValue::Int(_) => if atch_desc.format.ty() != FormatTy::Sint {
panic!("Bad ClearValue! index: {}, attachment index: {}, expected: {:?}, got: Int",
clear_i, atch_i, atch_desc.format.ty());
}
ClearValue::Uint(_) => if atch_desc.format.ty() != FormatTy::Uint {
panic!("Bad ClearValue! index: {}, attachment index: {}, expected: {:?}, got: Uint",
clear_i, atch_i, atch_desc.format.ty());
}
ClearValue::Depth(_) => if atch_desc.format.ty() != FormatTy::Depth {
panic!("Bad ClearValue! index: {}, attachment index: {}, expected: {:?}, got: Depth",
clear_i, atch_i, atch_desc.format.ty());
}
ClearValue::Stencil(_) => if atch_desc.format.ty() != FormatTy::Stencil {
panic!("Bad ClearValue! index: {}, attachment index: {}, expected: {:?}, got: Stencil",
clear_i, atch_i, atch_desc.format.ty());
}
ClearValue::DepthStencil(_) => if atch_desc.format.ty() != FormatTy::DepthStencil {
panic!("Bad ClearValue! index: {}, attachment index: {}, expected: {:?}, got: DepthStencil",
clear_i, atch_i, atch_desc.format.ty());
let aspects = atch_desc.format.aspects();
if aspects.depth && aspects.stencil {
assert!(
matches!(clear_value, ClearValue::DepthStencil(_)),
"Bad ClearValue! index: {}, attachment index: {}, expected: DepthStencil, got: {:?}",
clear_i,
atch_i,
clear_value,
);
} else if aspects.depth {
assert!(
matches!(clear_value, ClearValue::Depth(_)),
"Bad ClearValue! index: {}, attachment index: {}, expected: Depth, got: {:?}",
clear_i,
atch_i,
clear_value,
);
} else if aspects.depth {
assert!(
matches!(clear_value, ClearValue::Stencil(_)),
"Bad ClearValue! index: {}, attachment index: {}, expected: Stencil, got: {:?}",
clear_i,
atch_i,
clear_value,
);
} else if let Some(numeric_type) = atch_desc.format.type_color() {
match numeric_type {
NumericType::SFLOAT
| NumericType::UFLOAT
| NumericType::SNORM
| NumericType::UNORM
| NumericType::SSCALED
| NumericType::USCALED
| NumericType::SRGB => {
assert!(
matches!(clear_value, ClearValue::Float(_)),
"Bad ClearValue! index: {}, attachment index: {}, expected: Float, got: {:?}",
clear_i,
atch_i,
clear_value,
);
}
NumericType::SINT => {
assert!(
matches!(clear_value, ClearValue::Int(_)),
"Bad ClearValue! index: {}, attachment index: {}, expected: Int, got: {:?}",
clear_i,
atch_i,
clear_value,
);
}
NumericType::UINT => {
assert!(
matches!(clear_value, ClearValue::Uint(_)),
"Bad ClearValue! index: {}, attachment index: {}, expected: Uint, got: {:?}",
clear_i,
atch_i,
clear_value,
);
}
}
} else {
panic!("Shouldn't happen!");
}
} else {
if clear_value != ClearValue::None {
panic!("Bad ClearValue! index: {}, attachment index: {}, expected: None, got: {:?}",
clear_i, atch_i, clear_value);
}
assert!(
matches!(clear_value, ClearValue::None),
"Bad ClearValue! index: {}, attachment index: {}, expected: None, got: {:?}",
clear_i,
atch_i,
clear_value,
);
}
}
None => panic!("Not enough clear values"),

View File

@ -21,7 +21,7 @@ use crate::descriptor_set::sys::UnsafeDescriptorSet;
use crate::device::Device;
use crate::device::DeviceOwned;
use crate::format::ClearValue;
use crate::format::FormatTy;
use crate::format::NumericType;
use crate::image::ImageAccess;
use crate::image::ImageAspect;
use crate::image::ImageAspects;
@ -455,17 +455,16 @@ impl UnsafeCommandBufferBuilder {
// TODO: The correct check here is that the uncompressed element size of the source is
// equal to the compressed element size of the destination.
debug_assert!(
source.format().ty() == FormatTy::Compressed
|| destination.format().ty() == FormatTy::Compressed
source.format().compression().is_some()
|| destination.format().compression().is_some()
|| source.format().size() == destination.format().size()
);
// Depth/Stencil formats are required to match exactly.
let source_aspects = source.format().aspects();
debug_assert!(
!matches!(
source.format().ty(),
FormatTy::Depth | FormatTy::Stencil | FormatTy::DepthStencil
) || source.format() == destination.format()
!source_aspects.depth && !source_aspects.stencil
|| source.format() == destination.format()
);
debug_assert_eq!(source.samples(), destination.samples());
@ -569,28 +568,22 @@ impl UnsafeCommandBufferBuilder {
D: ?Sized + ImageAccess,
R: IntoIterator<Item = UnsafeCommandBufferBuilderImageBlit>,
{
debug_assert!(
filter == Filter::Nearest
|| !matches!(
source.format().ty(),
FormatTy::Depth | FormatTy::Stencil | FormatTy::DepthStencil
)
);
debug_assert!(
(source.format().ty() == FormatTy::Uint)
== (destination.format().ty() == FormatTy::Uint)
);
debug_assert!(
(source.format().ty() == FormatTy::Sint)
== (destination.format().ty() == FormatTy::Sint)
);
debug_assert!(
source.format() == destination.format()
|| !matches!(
source.format().ty(),
FormatTy::Depth | FormatTy::Stencil | FormatTy::DepthStencil
)
);
let source_aspects = source.format().aspects();
if let (Some(source_type), Some(destination_type)) = (
source.format().type_color(),
destination.format().type_color(),
) {
debug_assert!(
(source_type == NumericType::UINT) == (destination_type == NumericType::UINT)
);
debug_assert!(
(source_type == NumericType::SINT) == (destination_type == NumericType::SINT)
);
} else {
debug_assert!(source.format() == destination.format());
debug_assert!(filter == Filter::Nearest);
}
debug_assert_eq!(source.samples(), SampleCount::Sample1);
let source = source.inner();
@ -726,11 +719,9 @@ impl UnsafeCommandBufferBuilder {
I: ?Sized + ImageAccess,
R: IntoIterator<Item = UnsafeCommandBufferBuilderColorImageClear>,
{
debug_assert!(
image.format().ty() == FormatTy::Float
|| image.format().ty() == FormatTy::Uint
|| image.format().ty() == FormatTy::Sint
);
let image_aspects = image.format().aspects();
debug_assert!(image_aspects.color && !image_aspects.plane0);
debug_assert!(image.format().compression().is_none());
let image = image.inner();
debug_assert!(image.image.usage().transfer_destination);
@ -1896,7 +1887,7 @@ impl UnsafeCommandBufferBuilderPipelineBarrier {
(ash::vk::QUEUE_FAMILY_IGNORED, ash::vk::QUEUE_FAMILY_IGNORED)
};
if image.format().ty() == FormatTy::Ycbcr {
if image.format().requires_sampler_ycbcr_conversion() {
unimplemented!();
}

View File

@ -8,7 +8,7 @@
// according to those terms.
use crate::device::Device;
use crate::format::FormatTy;
use crate::format::NumericType;
use crate::image::ImageAccess;
use crate::image::ImageDimensions;
use crate::image::SampleCount;
@ -76,13 +76,21 @@ where
return Err(CheckBlitImageError::UnexpectedMultisampled);
}
let source_format_ty = source.format().ty();
let destination_format_ty = destination.format().ty();
if matches!(
source_format_ty,
FormatTy::Depth | FormatTy::Stencil | FormatTy::DepthStencil
if let (Some(source_type), Some(destination_type)) = (
source.format().type_color(),
destination.format().type_color(),
) {
let types_should_be_same = source_type == NumericType::UINT
|| destination_type == NumericType::UINT
|| source_type == NumericType::SINT
|| destination_type == NumericType::SINT;
if types_should_be_same && (source_type != destination_type) {
return Err(CheckBlitImageError::IncompatibleFormatTypes {
source_type,
destination_type,
});
}
} else {
if source.format() != destination.format() {
return Err(CheckBlitImageError::DepthStencilFormatMismatch);
}
@ -92,17 +100,6 @@ where
}
}
let types_should_be_same = source_format_ty == FormatTy::Uint
|| destination_format_ty == FormatTy::Uint
|| source_format_ty == FormatTy::Sint
|| destination_format_ty == FormatTy::Sint;
if types_should_be_same && (source_format_ty != destination_format_ty) {
return Err(CheckBlitImageError::IncompatibleFormatsTypes {
source_format_ty: source.format().ty(),
destination_format_ty: destination.format().ty(),
});
}
let source_dimensions = match source.dimensions().mipmap_dimensions(source_mip_level) {
Some(d) => d,
None => return Err(CheckBlitImageError::SourceCoordinatesOutOfRange),
@ -237,9 +234,9 @@ pub enum CheckBlitImageError {
/// The format of the source and destination must be equal when blitting depth/stencil images.
DepthStencilFormatMismatch,
/// The types of the source format and the destination format aren't compatible.
IncompatibleFormatsTypes {
source_format_ty: FormatTy,
destination_format_ty: FormatTy,
IncompatibleFormatTypes {
source_type: NumericType,
destination_type: NumericType,
},
/// Blitting between multisampled images is forbidden.
UnexpectedMultisampled,
@ -279,7 +276,7 @@ impl fmt::Display for CheckBlitImageError {
"the format of the source and destination must be equal when blitting \
depth/stencil images"
}
CheckBlitImageError::IncompatibleFormatsTypes { .. } => {
CheckBlitImageError::IncompatibleFormatTypes { .. } => {
"the types of the source format and the destination format aren't compatible"
}
CheckBlitImageError::UnexpectedMultisampled => {

View File

@ -8,7 +8,7 @@
// according to those terms.
use crate::device::Device;
use crate::format::FormatTy;
use crate::format::NumericType;
use crate::image::ImageAccess;
use crate::image::ImageDimensions;
use crate::VulkanObject;
@ -64,31 +64,28 @@ where
return Err(CheckCopyImageError::SampleCountMismatch);
}
let source_format_ty = source.format().ty();
let destination_format_ty = destination.format().ty();
if matches!(
source_format_ty,
FormatTy::Depth | FormatTy::Stencil | FormatTy::DepthStencil
if let (Some(source_type), Some(destination_type)) = (
source.format().type_color(),
destination.format().type_color(),
) {
// TODO: The correct check here is that the uncompressed element size of the source is
// equal to the compressed element size of the destination. However, format doesn't
// currently expose this information, so to be safe, we simply disallow compressed formats.
if source.format().compression().is_some()
|| destination.format().compression().is_some()
|| (source.format().size() != destination.format().size())
{
return Err(CheckCopyImageError::SizeIncompatibleFormatTypes {
source_type,
destination_type,
});
}
} else {
if source.format() != destination.format() {
return Err(CheckCopyImageError::DepthStencilFormatMismatch);
}
}
// TODO: The correct check here is that the uncompressed element size of the source is
// equal to the compressed element size of the destination. However, format doesn't
// currently expose this information, so to be safe, we simply disallow compressed formats.
if source.format().ty() == FormatTy::Compressed
|| destination.format().ty() == FormatTy::Compressed
|| (source.format().size() != destination.format().size())
{
return Err(CheckCopyImageError::SizeIncompatibleFormatsTypes {
source_format_ty: source.format().ty(),
destination_format_ty: destination.format().ty(),
});
}
let source_dimensions = match source.dimensions().mipmap_dimensions(source_mip_level) {
Some(d) => d,
None => return Err(CheckCopyImageError::SourceCoordinatesOutOfRange),
@ -189,9 +186,9 @@ pub enum CheckCopyImageError {
/// The format of the source and destination must be equal when copying depth/stencil images.
DepthStencilFormatMismatch,
/// The types of the source format and the destination format aren't size-compatible.
SizeIncompatibleFormatsTypes {
source_format_ty: FormatTy,
destination_format_ty: FormatTy,
SizeIncompatibleFormatTypes {
source_type: NumericType,
destination_type: NumericType,
},
/// The offsets, array layers and/or mipmap levels are out of range in the source image.
SourceCoordinatesOutOfRange,
@ -223,7 +220,7 @@ impl fmt::Display for CheckCopyImageError {
"the format of the source and destination must be equal when copying \
depth/stencil images"
}
CheckCopyImageError::SizeIncompatibleFormatsTypes { .. } => {
CheckCopyImageError::SizeIncompatibleFormatTypes { .. } => {
"the types of the source format and the destination format aren't size-compatible"
}
CheckCopyImageError::SourceCoordinatesOutOfRange => {

View File

@ -134,7 +134,7 @@ fn required_len_for_format<Px>(
where
Px: Pixel,
{
let (block_width, block_height) = format.block_dimensions();
let [block_width, block_height] = format.block_dimensions();
let num_blocks = (image_size[0] + block_width - 1) / block_width
* ((image_size[1] + block_height - 1) / block_height)
* image_size[2]
@ -153,40 +153,40 @@ mod tests {
fn test_required_len_for_format() {
// issue #1292
assert_eq!(
required_len_for_format::<u8>(Format::BC1_RGBUnormBlock, [2048, 2048, 1], 1),
required_len_for_format::<u8>(Format::BC1_RGB_UNORM_BLOCK, [2048, 2048, 1], 1),
2097152
);
// other test cases
assert_eq!(
required_len_for_format::<u8>(Format::R8G8B8A8Unorm, [2048, 2048, 1], 1),
required_len_for_format::<u8>(Format::R8G8B8A8_UNORM, [2048, 2048, 1], 1),
16777216
);
assert_eq!(
required_len_for_format::<u8>(Format::R4G4UnormPack8, [512, 512, 1], 1),
required_len_for_format::<u8>(Format::R4G4_UNORM_PACK8, [512, 512, 1], 1),
262144
);
assert_eq!(
required_len_for_format::<u8>(Format::R8G8B8Uscaled, [512, 512, 1], 1),
required_len_for_format::<u8>(Format::R8G8B8_USCALED, [512, 512, 1], 1),
786432
);
assert_eq!(
required_len_for_format::<u8>(Format::R32G32Uint, [512, 512, 1], 1),
required_len_for_format::<u8>(Format::R32G32_UINT, [512, 512, 1], 1),
2097152
);
assert_eq!(
required_len_for_format::<u32>(Format::R32G32Uint, [512, 512, 1], 1),
required_len_for_format::<u32>(Format::R32G32_UINT, [512, 512, 1], 1),
524288
);
assert_eq!(
required_len_for_format::<[u32; 2]>(Format::R32G32Uint, [512, 512, 1], 1),
required_len_for_format::<[u32; 2]>(Format::R32G32_UINT, [512, 512, 1], 1),
262144
);
assert_eq!(
required_len_for_format::<u8>(Format::ASTC_8x8UnormBlock, [512, 512, 1], 1),
required_len_for_format::<u8>(Format::ASTC_8x8_UNORM_BLOCK, [512, 512, 1], 1),
65536
);
assert_eq!(
required_len_for_format::<u8>(Format::ASTC_12x12SrgbBlock, [512, 512, 1], 1),
required_len_for_format::<u8>(Format::ASTC_12x12_SRGB_BLOCK, [512, 512, 1], 1),
29584
);
}

View File

@ -7,397 +7,112 @@
// notice may not be copied, modified, or distributed except
// according to those terms.
//! All the formats of images supported by Vulkan.
//! All the formats supported by Vulkan.
//!
//! # Formats
//! A format is mostly used to describe the texel data of an image. However, formats also show up in
//! a few other places, most notably to describe the format of vertex buffers.
//!
//! List of suffixes:
//! # Format support
//!
//! - `Unorm` means that the values are unsigned integers that are converted into floating points.
//! The maximum possible representable value becomes `1.0`, and the minimum representable value
//! becomes `0.0`. For example the value `255` in a `R8Unorm` will be interpreted as `1.0`.
//! Not all formats are supported by every device. Those that devices do support may only be
//! supported for certain use cases. It is an error to use a format where it is not supported, but
//! you can query a device beforehand for its support by calling the `properties` method on a format
//! value. You can use this to select a usable format from one or more suitable alternatives.
//! Some formats are required to be always supported for a particular usage. These are listed in the
//! [tables in the Vulkan specification](https://www.khronos.org/registry/vulkan/specs/1.2-extensions/html/chap43.html#features-required-format-support).
//!
//! - `Snorm` is the same as `Unorm`, but the integers are signed and the range is from `-1.0` to
//! `1.0` instead.
//! # Special format types
//!
//! - `Uscaled` means that the values are unsigned integers that are converted into floating points.
//! No change in the value is done. For example the value `255` in a `R8Uscaled` will be
//! interpreted as `255.0`.
//! ## Depth/stencil formats
//!
//! - `Sscaled` is the same as `Uscaled` expect that the integers are signed.
//! Depth/stencil formats can be identified by the `D` and `S` components in their names. They are
//! used primarily as the format for framebuffer attachments, for the purposes of depth and stencil
//! testing.
//!
//! - `Uint` means that the values are unsigned integers. No conversion is performed.
//! Some formats have only a depth or stencil component, while others combine both. The two
//! components are represented as separate *aspects*, which means that they can be accessed
//! individually as separate images. These pseudo-images have the same resolution, but different
//! bit depth and numeric representation.
//!
//! - `Sint` means that the values are signed integers. No conversion is performed.
//! Depth/stencil formats deviate from the others in a few more ways. Their data representation is
//! considered opaque, meaning that they do not have a fixed layout in memory nor a fixed size per
//! texel. They also have special limitations in several operations such as copying; a depth/stencil
//! format is not compatible with any other format, only with itself.
//!
//! - `Ufloat` means that the values are unsigned floating points. No conversion is performed. This
//! format is very unusual.
//! ## Block-compressed formats
//!
//! - `Sfloat` means that the values are regular floating points. No conversion is performed.
//! A block-compressed format uses compression to encode a larger block of texels into a smaller
//! number of bytes. Individual texels are no longer represented in memory, only the block as a
//! whole. An image must consist of a whole number of blocks, so the dimensions of an image must be
//! a whole multiple of the block dimensions. Vulkan supports several different compression schemes,
//! represented in Vulkano by the `CompressionType` enum.
//!
//! - `Srgb` is the same as `Unorm`, except that the value is interpreted as being in the sRGB
//! color space. This means that its value will be converted to fit in the RGB color space when
//! it is read. The fourth channel (usually used for alpha), if present, is not concerned by the
//! conversion.
//! Overall, block-compressed formats do not behave significantly differently from regular formats.
//! They are mostly restricted in terms of compatibility. Because of the compression, the notion of
//! bits per component does not apply, so the `components` method will only return whether a
//! component is present or not.
//!
//! # Choosing a format
//! ## YCbCr formats
//!
//! The following formats are guaranteed to be supported for everything that is related to
//! texturing (ie. blitting source and sampling them linearly). You should choose one of these
//! formats if you have an image that you are going to sample from:
//! YCbCr, also known as YUV, is an alternative image representation with three components:
//! Y for luminance or *luma* (overall brightness) and two color or *chroma* components Cb and Cr
//! encoding the blueness and redness respectively. YCbCr formats are primarily used in video
//! applications. In Vulkan, the formats used to encode YCbCr data use the green channel to
//! represent the luma component, while the blue and red components hold the chroma.
//!
//! - B4G4R4A4UnormPack16
//! - R5G6B5UnormPack16
//! - A1R5G5B5UnormPack16
//! - R8Unorm
//! - R8Snorm
//! - R8G8Unorm
//! - R8G8Snorm
//! - R8G8B8A8Unorm
//! - R8G8B8A8Snorm
//! - R8G8B8A8Srgb
//! - B8G8R8A8Unorm
//! - B8G8R8A8Srgb
//! - A8B8G8R8UnormPack32
//! - A8B8G8R8SnormPack32
//! - A8B8G8R8SrgbPack32
//! - A2B10G10R10UnormPack32
//! - R16Sfloat
//! - R16G16Sfloat
//! - R16G16B16A16Sfloat
//! - B10G11R11UfloatPack32
//! - E5B9G9R9UfloatPack32
//! To use most YCbCr formats in an [image view](crate::image::view), a feature known as
//! *sampler YCbCr conversion* is needed. It must be enabled on both the image view and any
//! combined image samplers in shaders that the image view is attached to. This feature handles
//! the correct conversion between YCbCr input data and RGB data inside the shader. To query whether
//! a format requires the conversion, you can call `requires_sampler_ycbcr_conversion` on a format.
//! As a rule, any format with `444`, `422`, `420`, `3PACK` or `4PACK` in the name requires it.
//!
//! The following formats are guaranteed to be supported for everything that is related to
//! intermediate render targets (ie. blitting destination, color attachment and sampling linearly):
//! Almost all YCbCr formats make use of **chroma subsampling**. This is a technique whereby the two
//! chroma components are encoded using a lower resolution than the luma component. The human eye is
//! less sensitive to color detail than to detail in brightness, so this allows more detail to be
//! encoded in less data. Chroma subsampling is indicated with one of three numbered suffixes in a
//! format name:
//! - `444` indicates a YCbCr format without chroma subsampling. All components have the same
//! resolution.
//! - `422` indicates horizontal chroma subsampling. The horizontal resolution of the chroma
//! components is halved, so a single value is shared within a 2x1 block of texels.
//! - `420` indicates horizontal and vertical chroma subsampling. Both dimensions of the chroma
//! components are halved, so a single value is shared within a 2x2 block of texels.
//!
//! - R5G6B5UnormPack16
//! - A1R5G5B5UnormPack16
//! - R8Unorm
//! - R8G8Unorm
//! - R8G8B8A8Unorm
//! - R8G8B8A8Srgb
//! - B8G8R8A8Unorm
//! - B8G8R8A8Srgb
//! - A8B8G8R8UnormPack32
//! - A8B8G8R8SrgbPack32
//! - A2B10G10R10UnormPack32
//! - R16Sfloat
//! - R16G16Sfloat
//! - R16G16B16A16Sfloat
//!
//! For depth images, only `D16Unorm` is guaranteed to be supported. For depth-stencil images,
//! it is guaranteed that either `D24Unorm_S8Uint` or `D32Sfloat_S8Uint` are supported.
//!
//! // TODO: storage formats
//! Most YCbCr formats, including all of the `444` and `420` formats, are **multi-planar**. Instead
//! of storing the components of a single texel together in memory, the components are separated
//! into *planes*, which act like independent images. In 3-plane formats, the planes hold the Y,
//! Cb and Cr components respectively, while in 2-plane formats, Cb and Cr are combined into a
//! two-component plane. Where chroma subsampling is applied, plane 0 has the full resolution, while
//! planes 1 and 2 have reduced resolution. Effectively, they are standalone images with half the
//! resolution of the original.
//!
//! The texels of multi-planar images cannot be accessed individually, for example to copy or blit,
//! since the components of each texel are split across the planes. Instead, you must access each
//! plane as an individual *aspect* of the image. A single-plane aspect of a multi-planar image
//! behaves as a regular image, and even has its own format, which can be queried with the `plane`
//! method on a format.
pub use crate::autogen::Format;
use crate::device::physical::PhysicalDevice;
use crate::image::ImageAspects;
use crate::DeviceSize;
use crate::VulkanObject;
use half::f16;
use std::convert::TryFrom;
use std::mem::MaybeUninit;
use std::vec::IntoIter as VecIntoIter;
use std::{error, fmt, mem};
macro_rules! formats {
($($name:ident => { vk: $vk:ident, bdim: $bdim:expr, size: $sz:expr, ty: $f_ty:ident$(, planes: $planes:expr)?},)+) => (
/// An enumeration of all the possible formats.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
#[repr(i32)]
#[allow(missing_docs)]
#[allow(non_camel_case_types)]
pub enum Format {
$($name = ash::vk::Format::$vk.as_raw(),)+
}
impl Format {
/*pub fn is_supported_for_vertex_attributes(&self) -> bool {
}
.. other functions ..
*/
/// Returns the size in bytes of an element of this format. For block based formats
/// this will be the size of a single block. Returns `None` if the
/// size is irrelevant.
#[inline]
pub const fn size(&self) -> Option<DeviceSize> {
match *self {
$(
Format::$name => $sz,
)+
}
}
/// Returns (width, height) of the dimensions for block based formats. For
/// non block formats will return (1,1)
#[inline]
pub const fn block_dimensions(&self) -> (u32, u32) {
match *self {
$(
Format::$name => $bdim,
)+
}
}
/// Returns the data type of the format.
#[inline]
pub const fn ty(&self) -> FormatTy {
match *self {
$(
Format::$name => FormatTy::$f_ty,
)+
}
}
/// Returns the number of planes that images of this format have.
///
/// Returns 0 if the format is not multi-planar.
#[inline]
pub const fn planes(&self) -> u8 {
match *self {
$(
$(Format::$name => $planes,)?
)+
_ => 0,
}
}
}
impl TryFrom<ash::vk::Format> for Format {
type Error = ();
#[inline]
fn try_from(val: ash::vk::Format) -> Result<Format, ()> {
match val {
$(
ash::vk::Format::$vk => Ok(Format::$name),
)+
_ => Err(()),
}
}
}
impl From<Format> for ash::vk::Format {
#[inline]
fn from(val: Format) -> Self {
ash::vk::Format::from_raw(val as i32)
}
}
);
}
formats! {
R4G4UnormPack8 => {vk: R4G4_UNORM_PACK8, bdim: (1, 1), size: Some(1), ty: Float},
R4G4B4A4UnormPack16 => {vk: R4G4B4A4_UNORM_PACK16, bdim: (1, 1), size: Some(2), ty: Float},
B4G4R4A4UnormPack16 => {vk: B4G4R4A4_UNORM_PACK16, bdim: (1, 1), size: Some(2), ty: Float},
R5G6B5UnormPack16 => {vk: R5G6B5_UNORM_PACK16, bdim: (1, 1), size: Some(2), ty: Float},
B5G6R5UnormPack16 => {vk: B5G6R5_UNORM_PACK16, bdim: (1, 1), size: Some(2), ty: Float},
R5G5B5A1UnormPack16 => {vk: R5G5B5A1_UNORM_PACK16, bdim: (1, 1), size: Some(2), ty: Float},
B5G5R5A1UnormPack16 => {vk: B5G5R5A1_UNORM_PACK16, bdim: (1, 1), size: Some(2), ty: Float},
A1R5G5B5UnormPack16 => {vk: A1R5G5B5_UNORM_PACK16, bdim: (1, 1), size: Some(2), ty: Float},
R8Unorm => {vk: R8_UNORM, bdim: (1, 1), size: Some(1), ty: Float},
R8Snorm => {vk: R8_SNORM, bdim: (1, 1), size: Some(1), ty: Float},
R8Uscaled => {vk: R8_USCALED, bdim: (1, 1), size: Some(1), ty: Float},
R8Sscaled => {vk: R8_SSCALED, bdim: (1, 1), size: Some(1), ty: Float},
R8Uint => {vk: R8_UINT, bdim: (1, 1), size: Some(1), ty: Uint},
R8Sint => {vk: R8_SINT, bdim: (1, 1), size: Some(1), ty: Sint},
R8Srgb => {vk: R8_SRGB, bdim: (1, 1), size: Some(1), ty: Float},
R8G8Unorm => {vk: R8G8_UNORM, bdim: (1, 1), size: Some(2), ty: Float},
R8G8Snorm => {vk: R8G8_SNORM, bdim: (1, 1), size: Some(2), ty: Float},
R8G8Uscaled => {vk: R8G8_USCALED, bdim: (1, 1), size: Some(2), ty: Float},
R8G8Sscaled => {vk: R8G8_SSCALED, bdim: (1, 1), size: Some(2), ty: Float},
R8G8Uint => {vk: R8G8_UINT, bdim: (1, 1), size: Some(2), ty: Uint},
R8G8Sint => {vk: R8G8_SINT, bdim: (1, 1), size: Some(2), ty: Sint},
R8G8Srgb => {vk: R8G8_SRGB, bdim: (1, 1), size: Some(2), ty: Float},
R8G8B8Unorm => {vk: R8G8B8_UNORM, bdim: (1, 1), size: Some(3), ty: Float},
R8G8B8Snorm => {vk: R8G8B8_SNORM, bdim: (1, 1), size: Some(3), ty: Float},
R8G8B8Uscaled => {vk: R8G8B8_USCALED, bdim: (1, 1), size: Some(3), ty: Float},
R8G8B8Sscaled => {vk: R8G8B8_SSCALED, bdim: (1, 1), size: Some(3), ty: Float},
R8G8B8Uint => {vk: R8G8B8_UINT, bdim: (1, 1), size: Some(3), ty: Uint},
R8G8B8Sint => {vk: R8G8B8_SINT, bdim: (1, 1), size: Some(3), ty: Sint},
R8G8B8Srgb => {vk: R8G8B8_SRGB, bdim: (1, 1), size: Some(3), ty: Float},
B8G8R8Unorm => {vk: B8G8R8_UNORM, bdim: (1, 1), size: Some(3), ty: Float},
B8G8R8Snorm => {vk: B8G8R8_SNORM, bdim: (1, 1), size: Some(3), ty: Float},
B8G8R8Uscaled => {vk: B8G8R8_USCALED, bdim: (1, 1), size: Some(3), ty: Float},
B8G8R8Sscaled => {vk: B8G8R8_SSCALED, bdim: (1, 1), size: Some(3), ty: Float},
B8G8R8Uint => {vk: B8G8R8_UINT, bdim: (1, 1), size: Some(3), ty: Uint},
B8G8R8Sint => {vk: B8G8R8_SINT, bdim: (1, 1), size: Some(3), ty: Sint},
B8G8R8Srgb => {vk: B8G8R8_SRGB, bdim: (1, 1), size: Some(3), ty: Float},
R8G8B8A8Unorm => {vk: R8G8B8A8_UNORM, bdim: (1, 1), size: Some(4), ty: Float},
R8G8B8A8Snorm => {vk: R8G8B8A8_SNORM, bdim: (1, 1), size: Some(4), ty: Float},
R8G8B8A8Uscaled => {vk: R8G8B8A8_USCALED, bdim: (1, 1), size: Some(4), ty: Float},
R8G8B8A8Sscaled => {vk: R8G8B8A8_SSCALED, bdim: (1, 1), size: Some(4), ty: Float},
R8G8B8A8Uint => {vk: R8G8B8A8_UINT, bdim: (1, 1), size: Some(4), ty: Uint},
R8G8B8A8Sint => {vk: R8G8B8A8_SINT, bdim: (1, 1), size: Some(4), ty: Sint},
R8G8B8A8Srgb => {vk: R8G8B8A8_SRGB, bdim: (1, 1), size: Some(4), ty: Float},
B8G8R8A8Unorm => {vk: B8G8R8A8_UNORM, bdim: (1, 1), size: Some(4), ty: Float},
B8G8R8A8Snorm => {vk: B8G8R8A8_SNORM, bdim: (1, 1), size: Some(4), ty: Float},
B8G8R8A8Uscaled => {vk: B8G8R8A8_USCALED, bdim: (1, 1), size: Some(4), ty: Float},
B8G8R8A8Sscaled => {vk: B8G8R8A8_SSCALED, bdim: (1, 1), size: Some(4), ty: Float},
B8G8R8A8Uint => {vk: B8G8R8A8_UINT, bdim: (1, 1), size: Some(4), ty: Uint},
B8G8R8A8Sint => {vk: B8G8R8A8_SINT, bdim: (1, 1), size: Some(4), ty: Sint},
B8G8R8A8Srgb => {vk: B8G8R8A8_SRGB, bdim: (1, 1), size: Some(4), ty: Float},
A8B8G8R8UnormPack32 => {vk: A8B8G8R8_UNORM_PACK32, bdim: (1, 1), size: Some(4), ty: Float},
A8B8G8R8SnormPack32 => {vk: A8B8G8R8_SNORM_PACK32, bdim: (1, 1), size: Some(4), ty: Float},
A8B8G8R8UscaledPack32 => {vk: A8B8G8R8_USCALED_PACK32, bdim: (1, 1), size: Some(4), ty: Float},
A8B8G8R8SscaledPack32 => {vk: A8B8G8R8_SSCALED_PACK32, bdim: (1, 1), size: Some(4), ty: Float},
A8B8G8R8UintPack32 => {vk: A8B8G8R8_UINT_PACK32, bdim: (1, 1), size: Some(4), ty: Uint},
A8B8G8R8SintPack32 => {vk: A8B8G8R8_SINT_PACK32, bdim: (1, 1), size: Some(4), ty: Sint},
A8B8G8R8SrgbPack32 => {vk: A8B8G8R8_SRGB_PACK32, bdim: (1, 1), size: Some(4), ty: Float},
A2R10G10B10UnormPack32 => {vk: A2R10G10B10_UNORM_PACK32, bdim: (1, 1), size: Some(4), ty: Float},
A2R10G10B10SnormPack32 => {vk: A2R10G10B10_SNORM_PACK32, bdim: (1, 1), size: Some(4), ty: Float},
A2R10G10B10UscaledPack32 => {vk: A2R10G10B10_USCALED_PACK32, bdim: (1, 1), size: Some(4), ty: Float},
A2R10G10B10SscaledPack32 => {vk: A2R10G10B10_SSCALED_PACK32, bdim: (1, 1), size: Some(4), ty: Float},
A2R10G10B10UintPack32 => {vk: A2R10G10B10_UINT_PACK32, bdim: (1, 1), size: Some(4), ty: Uint},
A2R10G10B10SintPack32 => {vk: A2R10G10B10_SINT_PACK32, bdim: (1, 1), size: Some(4), ty: Sint},
A2B10G10R10UnormPack32 => {vk: A2B10G10R10_UNORM_PACK32, bdim: (1, 1), size: Some(4), ty: Float},
A2B10G10R10SnormPack32 => {vk: A2B10G10R10_SNORM_PACK32, bdim: (1, 1), size: Some(4), ty: Float},
A2B10G10R10UscaledPack32 => {vk: A2B10G10R10_USCALED_PACK32, bdim: (1, 1), size: Some(4), ty: Float},
A2B10G10R10SscaledPack32 => {vk: A2B10G10R10_SSCALED_PACK32, bdim: (1, 1), size: Some(4), ty: Float},
A2B10G10R10UintPack32 => {vk: A2B10G10R10_UINT_PACK32, bdim: (1, 1), size: Some(4), ty: Uint},
A2B10G10R10SintPack32 => {vk: A2B10G10R10_SINT_PACK32, bdim: (1, 1), size: Some(4), ty: Sint},
R16Unorm => {vk: R16_UNORM, bdim: (1, 1), size: Some(2), ty: Float},
R16Snorm => {vk: R16_SNORM, bdim: (1, 1), size: Some(2), ty: Float},
R16Uscaled => {vk: R16_USCALED, bdim: (1, 1), size: Some(2), ty: Float},
R16Sscaled => {vk: R16_SSCALED, bdim: (1, 1), size: Some(2), ty: Float},
R16Uint => {vk: R16_UINT, bdim: (1, 1), size: Some(2), ty: Uint},
R16Sint => {vk: R16_SINT, bdim: (1, 1), size: Some(2), ty: Sint},
R16Sfloat => {vk: R16_SFLOAT, bdim: (1, 1), size: Some(2), ty: Float},
R16G16Unorm => {vk: R16G16_UNORM, bdim: (1, 1), size: Some(4), ty: Float},
R16G16Snorm => {vk: R16G16_SNORM, bdim: (1, 1), size: Some(4), ty: Float},
R16G16Uscaled => {vk: R16G16_USCALED, bdim: (1, 1), size: Some(4), ty: Float},
R16G16Sscaled => {vk: R16G16_SSCALED, bdim: (1, 1), size: Some(4), ty: Float},
R16G16Uint => {vk: R16G16_UINT, bdim: (1, 1), size: Some(4), ty: Uint},
R16G16Sint => {vk: R16G16_SINT, bdim: (1, 1), size: Some(4), ty: Sint},
R16G16Sfloat => {vk: R16G16_SFLOAT, bdim: (1, 1), size: Some(4), ty: Float},
R16G16B16Unorm => {vk: R16G16B16_UNORM, bdim: (1, 1), size: Some(6), ty: Float},
R16G16B16Snorm => {vk: R16G16B16_SNORM, bdim: (1, 1), size: Some(6), ty: Float},
R16G16B16Uscaled => {vk: R16G16B16_USCALED, bdim: (1, 1), size: Some(6), ty: Float},
R16G16B16Sscaled => {vk: R16G16B16_SSCALED, bdim: (1, 1), size: Some(6), ty: Float},
R16G16B16Uint => {vk: R16G16B16_UINT, bdim: (1, 1), size: Some(6), ty: Uint},
R16G16B16Sint => {vk: R16G16B16_SINT, bdim: (1, 1), size: Some(6), ty: Sint},
R16G16B16Sfloat => {vk: R16G16B16_SFLOAT, bdim: (1, 1), size: Some(6), ty: Float},
R16G16B16A16Unorm => {vk: R16G16B16A16_UNORM, bdim: (1, 1), size: Some(8), ty: Float},
R16G16B16A16Snorm => {vk: R16G16B16A16_SNORM, bdim: (1, 1), size: Some(8), ty: Float},
R16G16B16A16Uscaled => {vk: R16G16B16A16_USCALED, bdim: (1, 1), size: Some(8), ty: Float},
R16G16B16A16Sscaled => {vk: R16G16B16A16_SSCALED, bdim: (1, 1), size: Some(8), ty: Float},
R16G16B16A16Uint => {vk: R16G16B16A16_UINT, bdim: (1, 1), size: Some(8), ty: Uint},
R16G16B16A16Sint => {vk: R16G16B16A16_SINT, bdim: (1, 1), size: Some(8), ty: Sint},
R16G16B16A16Sfloat => {vk: R16G16B16A16_SFLOAT, bdim: (1, 1), size: Some(8), ty: Float},
R32Uint => {vk: R32_UINT, bdim: (1, 1), size: Some(4), ty: Uint},
R32Sint => {vk: R32_SINT, bdim: (1, 1), size: Some(4), ty: Sint},
R32Sfloat => {vk: R32_SFLOAT, bdim: (1, 1), size: Some(4), ty: Float},
R32G32Uint => {vk: R32G32_UINT, bdim: (1, 1), size: Some(8), ty: Uint},
R32G32Sint => {vk: R32G32_SINT, bdim: (1, 1), size: Some(8), ty: Sint},
R32G32Sfloat => {vk: R32G32_SFLOAT, bdim: (1, 1), size: Some(8), ty: Float},
R32G32B32Uint => {vk: R32G32B32_UINT, bdim: (1, 1), size: Some(12), ty: Uint},
R32G32B32Sint => {vk: R32G32B32_SINT, bdim: (1, 1), size: Some(12), ty: Sint},
R32G32B32Sfloat => {vk: R32G32B32_SFLOAT, bdim: (1, 1), size: Some(12), ty: Float},
R32G32B32A32Uint => {vk: R32G32B32A32_UINT, bdim: (1, 1), size: Some(16), ty: Uint},
R32G32B32A32Sint => {vk: R32G32B32A32_SINT, bdim: (1, 1), size: Some(16), ty: Sint},
R32G32B32A32Sfloat => {vk: R32G32B32A32_SFLOAT, bdim: (1, 1), size: Some(16), ty: Float},
R64Uint => {vk: R64_UINT, bdim: (1, 1), size: Some(8), ty: Uint},
R64Sint => {vk: R64_SINT, bdim: (1, 1), size: Some(8), ty: Sint},
R64Sfloat => {vk: R64_SFLOAT, bdim: (1, 1), size: Some(8), ty: Float},
R64G64Uint => {vk: R64G64_UINT, bdim: (1, 1), size: Some(16), ty: Uint},
R64G64Sint => {vk: R64G64_SINT, bdim: (1, 1), size: Some(16), ty: Sint},
R64G64Sfloat => {vk: R64G64_SFLOAT, bdim: (1, 1), size: Some(16), ty: Float},
R64G64B64Uint => {vk: R64G64B64_UINT, bdim: (1, 1), size: Some(24), ty: Uint},
R64G64B64Sint => {vk: R64G64B64_SINT, bdim: (1, 1), size: Some(24), ty: Sint},
R64G64B64Sfloat => {vk: R64G64B64_SFLOAT, bdim: (1, 1), size: Some(24), ty: Float},
R64G64B64A64Uint => {vk: R64G64B64A64_UINT, bdim: (1, 1), size: Some(32), ty: Uint},
R64G64B64A64Sint => {vk: R64G64B64A64_SINT, bdim: (1, 1), size: Some(32), ty: Sint},
R64G64B64A64Sfloat => {vk: R64G64B64A64_SFLOAT, bdim: (1, 1), size: Some(32), ty: Float},
B10G11R11UfloatPack32 => {vk: B10G11R11_UFLOAT_PACK32, bdim: (1, 1), size: Some(4), ty: Float},
E5B9G9R9UfloatPack32 => {vk: E5B9G9R9_UFLOAT_PACK32, bdim: (1, 1), size: Some(4), ty: Float},
D16Unorm => {vk: D16_UNORM, bdim: (1, 1), size: Some(2), ty: Depth},
X8_D24UnormPack32 => {vk: X8_D24_UNORM_PACK32, bdim: (1, 1), size: Some(4), ty: Depth},
D32Sfloat => {vk: D32_SFLOAT, bdim: (1, 1), size: Some(4), ty: Depth},
S8Uint => {vk: S8_UINT, bdim: (1, 1), size: Some(1), ty: Stencil},
D16Unorm_S8Uint => {vk: D16_UNORM_S8_UINT, bdim: (1, 1), size: None, ty: DepthStencil},
D24Unorm_S8Uint => {vk: D24_UNORM_S8_UINT, bdim: (1, 1), size: None, ty: DepthStencil},
D32Sfloat_S8Uint => {vk: D32_SFLOAT_S8_UINT, bdim: (1, 1), size: None, ty: DepthStencil},
BC1_RGBUnormBlock => {vk: BC1_RGB_UNORM_BLOCK, bdim: (4, 4), size: Some(8), ty: Compressed},
BC1_RGBSrgbBlock => {vk: BC1_RGB_SRGB_BLOCK, bdim: (4, 4), size: Some(8), ty: Compressed},
BC1_RGBAUnormBlock => {vk: BC1_RGBA_UNORM_BLOCK, bdim: (4, 4), size: Some(8), ty: Compressed},
BC1_RGBASrgbBlock => {vk: BC1_RGBA_SRGB_BLOCK, bdim: (4, 4), size: Some(8), ty: Compressed},
BC2UnormBlock => {vk: BC2_UNORM_BLOCK, bdim: (4, 4), size: Some(16), ty: Compressed},
BC2SrgbBlock => {vk: BC2_SRGB_BLOCK, bdim: (4, 4), size: Some(16), ty: Compressed},
BC3UnormBlock => {vk: BC3_UNORM_BLOCK, bdim: (4, 4), size: Some(16), ty: Compressed},
BC3SrgbBlock => {vk: BC3_SRGB_BLOCK, bdim: (4, 4), size: Some(16), ty: Compressed},
BC4UnormBlock => {vk: BC4_UNORM_BLOCK, bdim: (4, 4), size: Some(8), ty: Compressed},
BC4SnormBlock => {vk: BC4_SNORM_BLOCK, bdim: (4, 4), size: Some(8), ty: Compressed},
BC5UnormBlock => {vk: BC5_UNORM_BLOCK, bdim: (4, 4), size: Some(16), ty: Compressed},
BC5SnormBlock => {vk: BC5_SNORM_BLOCK, bdim: (4, 4), size: Some(16), ty: Compressed},
BC6HUfloatBlock => {vk: BC6H_UFLOAT_BLOCK, bdim: (4, 4), size: Some(16), ty: Compressed},
BC6HSfloatBlock => {vk: BC6H_SFLOAT_BLOCK, bdim: (4, 4), size: Some(16), ty: Compressed},
BC7UnormBlock => {vk: BC7_UNORM_BLOCK, bdim: (4, 4), size: Some(16), ty: Compressed},
BC7SrgbBlock => {vk: BC7_SRGB_BLOCK, bdim: (4, 4), size: Some(16), ty: Compressed},
ETC2_R8G8B8UnormBlock => {vk: ETC2_R8G8B8_UNORM_BLOCK, bdim: (4, 4), size: Some(8), ty: Compressed},
ETC2_R8G8B8SrgbBlock => {vk: ETC2_R8G8B8_SRGB_BLOCK, bdim: (4, 4), size: Some(8), ty: Compressed},
ETC2_R8G8B8A1UnormBlock => {vk: ETC2_R8G8B8A1_UNORM_BLOCK, bdim: (4, 4), size: Some(8), ty: Compressed},
ETC2_R8G8B8A1SrgbBlock => {vk: ETC2_R8G8B8A1_SRGB_BLOCK, bdim: (4, 4), size: Some(8), ty: Compressed},
ETC2_R8G8B8A8UnormBlock => {vk: ETC2_R8G8B8A8_UNORM_BLOCK, bdim: (4, 4), size: Some(16), ty: Compressed},
ETC2_R8G8B8A8SrgbBlock => {vk: ETC2_R8G8B8A8_SRGB_BLOCK, bdim: (4, 4), size: Some(16), ty: Compressed},
EAC_R11UnormBlock => {vk: EAC_R11_UNORM_BLOCK, bdim: (4, 4), size: Some(8), ty: Compressed},
EAC_R11SnormBlock => {vk: EAC_R11_SNORM_BLOCK, bdim: (4, 4), size: Some(8), ty: Compressed},
EAC_R11G11UnormBlock => {vk: EAC_R11G11_UNORM_BLOCK, bdim: (4, 4), size: Some(16), ty: Compressed},
EAC_R11G11SnormBlock => {vk: EAC_R11G11_SNORM_BLOCK, bdim: (4, 4), size: Some(16), ty: Compressed},
ASTC_4x4UnormBlock => {vk: ASTC_4X4_UNORM_BLOCK, bdim: (4, 4), size: Some(16), ty: Compressed},
ASTC_4x4SrgbBlock => {vk: ASTC_4X4_SRGB_BLOCK, bdim: (4, 4), size: Some(16), ty: Compressed},
ASTC_5x4UnormBlock => {vk: ASTC_5X4_UNORM_BLOCK, bdim: (5, 4), size: Some(16), ty: Compressed},
ASTC_5x4SrgbBlock => {vk: ASTC_5X4_SRGB_BLOCK, bdim: (5, 4), size: Some(16), ty: Compressed},
ASTC_5x5UnormBlock => {vk: ASTC_5X5_UNORM_BLOCK, bdim: (5, 5), size: Some(16), ty: Compressed},
ASTC_5x5SrgbBlock => {vk: ASTC_5X5_SRGB_BLOCK, bdim: (5, 5), size: Some(16), ty: Compressed},
ASTC_6x5UnormBlock => {vk: ASTC_6X5_UNORM_BLOCK, bdim: (6, 5), size: Some(16), ty: Compressed},
ASTC_6x5SrgbBlock => {vk: ASTC_6X5_SRGB_BLOCK, bdim: (6, 5), size: Some(16), ty: Compressed},
ASTC_6x6UnormBlock => {vk: ASTC_6X6_UNORM_BLOCK, bdim: (6, 6), size: Some(16), ty: Compressed},
ASTC_6x6SrgbBlock => {vk: ASTC_6X6_SRGB_BLOCK, bdim: (6, 6), size: Some(16), ty: Compressed},
ASTC_8x5UnormBlock => {vk: ASTC_8X5_UNORM_BLOCK, bdim: (8, 5), size: Some(16), ty: Compressed},
ASTC_8x5SrgbBlock => {vk: ASTC_8X5_SRGB_BLOCK, bdim: (8, 5), size: Some(16), ty: Compressed},
ASTC_8x6UnormBlock => {vk: ASTC_8X6_UNORM_BLOCK, bdim: (8, 6), size: Some(16), ty: Compressed},
ASTC_8x6SrgbBlock => {vk: ASTC_8X6_SRGB_BLOCK, bdim: (8, 6), size: Some(16), ty: Compressed},
ASTC_8x8UnormBlock => {vk: ASTC_8X8_UNORM_BLOCK, bdim: (8, 8), size: Some(16), ty: Compressed},
ASTC_8x8SrgbBlock => {vk: ASTC_8X8_SRGB_BLOCK, bdim: (8, 8), size: Some(16), ty: Compressed},
ASTC_10x5UnormBlock => {vk: ASTC_10X5_UNORM_BLOCK, bdim: (10, 5), size: Some(16), ty: Compressed},
ASTC_10x5SrgbBlock => {vk: ASTC_10X5_SRGB_BLOCK, bdim: (10, 5), size: Some(16), ty: Compressed},
ASTC_10x6UnormBlock => {vk: ASTC_10X6_UNORM_BLOCK, bdim: (10, 6), size: Some(16), ty: Compressed},
ASTC_10x6SrgbBlock => {vk: ASTC_10X6_SRGB_BLOCK, bdim: (10, 6), size: Some(16), ty: Compressed},
ASTC_10x8UnormBlock => {vk: ASTC_10X8_UNORM_BLOCK, bdim: (10, 8), size: Some(16), ty: Compressed},
ASTC_10x8SrgbBlock => {vk: ASTC_10X8_SRGB_BLOCK, bdim: (10, 8), size: Some(16), ty: Compressed},
ASTC_10x10UnormBlock => {vk: ASTC_10X10_UNORM_BLOCK, bdim: (10, 10), size: Some(16), ty: Compressed},
ASTC_10x10SrgbBlock => {vk: ASTC_10X10_SRGB_BLOCK, bdim: (10, 10), size: Some(16), ty: Compressed},
ASTC_12x10UnormBlock => {vk: ASTC_12X10_UNORM_BLOCK, bdim: (12, 10), size: Some(16), ty: Compressed},
ASTC_12x10SrgbBlock => {vk: ASTC_12X10_SRGB_BLOCK, bdim: (12, 10), size: Some(16), ty: Compressed},
ASTC_12x12UnormBlock => {vk: ASTC_12X12_UNORM_BLOCK, bdim: (12, 12), size: Some(16), ty: Compressed},
ASTC_12x12SrgbBlock => {vk: ASTC_12X12_SRGB_BLOCK, bdim: (12, 12), size: Some(16), ty: Compressed},
G8B8R8_3PLANE420Unorm => {vk: G8_B8_R8_3PLANE_420_UNORM, bdim: (1, 1), size: None, ty: Ycbcr, planes: 3},
G8B8R8_2PLANE420Unorm => {vk: G8_B8R8_2PLANE_420_UNORM, bdim: (1, 1), size: None, ty: Ycbcr, planes: 2},
}
impl Format {
/// Returns the aspects that images of this format have.
/// Returns whether sampler YCbCr conversion is required for image views of this format.
#[inline]
pub const fn aspects(&self) -> ImageAspects {
let ty = self.ty();
let planes = self.planes();
ImageAspects {
color: matches!(
ty,
FormatTy::Float | FormatTy::Uint | FormatTy::Sint | FormatTy::Compressed
),
depth: matches!(ty, FormatTy::Depth | FormatTy::DepthStencil),
stencil: matches!(ty, FormatTy::Stencil | FormatTy::DepthStencil),
plane0: planes >= 1,
plane1: planes >= 2,
plane2: planes >= 3,
..ImageAspects::none()
}
pub fn requires_sampler_ycbcr_conversion(&self) -> bool {
matches!(
self.compatibility().0,
FormatCompatibilityInner::YCbCrRGBA { .. }
| FormatCompatibilityInner::YCbCr1Plane { .. }
| FormatCompatibilityInner::YCbCr2Plane { .. }
| FormatCompatibilityInner::YCbCr3Plane { .. }
)
}
/// Retrieves the properties of a format when used by a certain device.
@ -423,29 +138,136 @@ impl Format {
#[inline]
pub fn decode_clear_value(&self, value: ClearValue) -> ClearValue {
match (self.ty(), value) {
(FormatTy::Float, f @ ClearValue::Float(_)) => f,
(FormatTy::Compressed, f @ ClearValue::Float(_)) => f,
(FormatTy::Sint, f @ ClearValue::Int(_)) => f,
(FormatTy::Uint, f @ ClearValue::Uint(_)) => f,
(FormatTy::Depth, f @ ClearValue::Depth(_)) => f,
(FormatTy::Stencil, f @ ClearValue::Stencil(_)) => f,
(FormatTy::DepthStencil, f @ ClearValue::DepthStencil(_)) => f,
_ => panic!("Wrong clear value"),
let aspects = self.aspects();
if aspects.depth && aspects.stencil {
assert!(matches!(value, ClearValue::DepthStencil(_)));
} else if aspects.depth {
assert!(matches!(value, ClearValue::Depth(_)));
} else if aspects.stencil {
assert!(matches!(value, ClearValue::Stencil(_)));
} else if let Some(numeric_type) = self.type_color() {
match numeric_type {
NumericType::SFLOAT
| NumericType::UFLOAT
| NumericType::SNORM
| NumericType::UNORM
| NumericType::SSCALED
| NumericType::USCALED
| NumericType::SRGB => {
assert!(matches!(value, ClearValue::Float(_)));
}
NumericType::SINT => {
assert!(matches!(value, ClearValue::Int(_)));
}
NumericType::UINT => {
assert!(matches!(value, ClearValue::Uint(_)));
}
}
} else {
panic!("Shouldn't happen!");
}
value
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum FormatTy {
Float,
Uint,
Sint,
Depth,
Stencil,
DepthStencil,
Compressed,
Ycbcr,
impl From<Format> for ash::vk::Format {
#[inline]
fn from(val: Format) -> Self {
ash::vk::Format::from_raw(val as i32)
}
}
/// The block compression scheme used in a format.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum CompressionType {
/// Adaptive Scalable Texture Compression.
ASTC,
/// S3TC Block Compression 1, also known as DXT1.
BC1,
/// S3TC Block Compression 2,
/// also known as DXT2 (with premultiplied alpha) and DXT3 (no premultiplied alpha).
BC2,
/// S3TC Block Compression 3,
/// also known as DXT4 (with premultiplied alpha) and DXT5 (no premultiplied alpha).
BC3,
/// S3TC Block Compression 4.
BC4,
/// S3TC Block Compression 5.
BC5,
/// S3TC Block Compression 6 or 6H.
BC6H,
/// S3TC Block Compression 7.
BC7,
/// Ericsson Texture Compression 2.
ETC2,
/// ETC2 Alpha Compression.
EAC,
/// PowerVR Texture Compression 1.
PVRTC1,
/// PowerVR Texture Compression 2.
PVRTC2,
}
/// The numeric type that represents data of a format in memory.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum NumericType {
/// Signed floating-point number.
SFLOAT,
/// Unsigned floating-point number.
UFLOAT,
/// Signed integer.
SINT,
/// Unsigned integer.
UINT,
/// Signed integer that represents a normalized floating-point value in the range \[-1,1].
SNORM,
/// Unsigned integer that represents a normalized floating-point value in the range \[0,1].
UNORM,
/// Signed integer that is converted to a floating-point value directly.
SSCALED,
/// Unsigned integer that is converted to a floating-point value directly.
USCALED,
/// Unsigned integer where R, G, B components represent a normalized floating-point value in the
/// sRGB color space, while the A component is a simple normalized value as in `UNORM`.
SRGB,
}
/// An opaque type that represents a format compatibility class.
///
/// Two formats are compatible if their compatibility classes compare equal.
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[repr(transparent)]
pub struct FormatCompatibility(pub(crate) &'static FormatCompatibilityInner);
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub(crate) enum FormatCompatibilityInner {
Normal {
size: u8,
},
DepthStencil {
ty: u8,
},
Compressed {
compression: CompressionType,
subtype: u8,
},
YCbCrRGBA {
bits: u8,
},
YCbCr1Plane {
bits: u8,
g_even: bool,
},
YCbCr2Plane {
bits: u8,
block_texels: u8,
},
YCbCr3Plane {
bits: u8,
block_texels: u8,
},
}
/// Trait for Rust types that can represent a pixel in an image.
@ -517,11 +339,11 @@ impl_pixel! {
pub enum ClearValue {
/// Entry for attachments that aren't cleared.
None,
/// Value for floating-point attachments, including `Unorm`, `Snorm`, `Sfloat`.
/// Value for floating-point attachments, including `UNORM`, `SNORM`, `SFLOAT`.
Float([f32; 4]),
/// Value for integer attachments, including `Int`.
/// Value for integer attachments, including `SINT`.
Int([i32; 4]),
/// Value for unsigned integer attachments, including `Uint`.
/// Value for unsigned integer attachments, including `UINT`.
Uint([u32; 4]),
/// Value for depth attachments.
Depth(f32),
@ -691,7 +513,7 @@ pub struct FormatProperties {
pub buffer_features: FormatFeatures,
}
/// The features supported by images with a particular format.
/// The features supported by a device for images with a particular format.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
#[allow(missing_docs)]
pub struct FormatFeatures {

View File

@ -10,7 +10,6 @@
use crate::device::Device;
use crate::format::ClearValue;
use crate::format::Format;
use crate::format::FormatTy;
use crate::image::sys::ImageCreationError;
use crate::image::sys::UnsafeImage;
use crate::image::traits::ImageAccess;
@ -410,13 +409,12 @@ impl AttachmentImage {
) -> Result<Arc<AttachmentImage>, ImageCreationError> {
// TODO: check dimensions against the max_framebuffer_width/height/layers limits
let is_depth = match format.ty() {
FormatTy::Depth => true,
FormatTy::DepthStencil => true,
FormatTy::Stencil => true,
FormatTy::Compressed => panic!(),
_ => false,
};
let aspects = format.aspects();
let is_depth = aspects.depth || aspects.stencil;
if format.compression().is_some() {
panic!() // TODO: message?
}
let usage = ImageUsage {
color_attachment: !is_depth,
@ -642,18 +640,18 @@ mod tests {
#[test]
fn create_regular() {
let (device, _) = gfx_dev_and_queue!();
let _img = AttachmentImage::new(device, [32, 32], Format::R8G8B8A8Unorm).unwrap();
let _img = AttachmentImage::new(device, [32, 32], Format::R8G8B8A8_UNORM).unwrap();
}
#[test]
fn create_transient() {
let (device, _) = gfx_dev_and_queue!();
let _img = AttachmentImage::transient(device, [32, 32], Format::R8G8B8A8Unorm).unwrap();
let _img = AttachmentImage::transient(device, [32, 32], Format::R8G8B8A8_UNORM).unwrap();
}
#[test]
fn d16_unorm_always_supported() {
let (device, _) = gfx_dev_and_queue!();
let _img = AttachmentImage::new(device, [32, 32], Format::D16Unorm).unwrap();
let _img = AttachmentImage::new(device, [32, 32], Format::D16_UNORM).unwrap();
}
}

View File

@ -676,7 +676,7 @@ mod tests {
vec.into_iter(),
dimensions,
MipmapsCount::One,
Format::R8Unorm,
Format::R8_UNORM,
queue.clone(),
)
.unwrap();
@ -691,7 +691,7 @@ mod tests {
vec.into_iter(),
dimensions,
MipmapsCount::Log2,
Format::R8Unorm,
Format::R8_UNORM,
queue.clone(),
)
.unwrap();

View File

@ -11,7 +11,6 @@ use crate::device::physical::QueueFamily;
use crate::device::Device;
use crate::format::ClearValue;
use crate::format::Format;
use crate::format::FormatTy;
use crate::image::sys::ImageCreationError;
use crate::image::sys::UnsafeImage;
use crate::image::traits::ImageAccess;
@ -79,13 +78,12 @@ impl StorageImage {
where
I: IntoIterator<Item = QueueFamily<'a>>,
{
let is_depth = match format.ty() {
FormatTy::Depth => true,
FormatTy::DepthStencil => true,
FormatTy::Stencil => true,
FormatTy::Compressed => panic!(),
_ => false,
};
let aspects = format.aspects();
let is_depth = aspects.depth || aspects.stencil;
if format.compression().is_some() {
panic!() // TODO: message?
}
let usage = ImageUsage {
transfer_source: true,
@ -328,7 +326,7 @@ mod tests {
height: 32,
array_layers: 1,
},
Format::R8G8B8A8Unorm,
Format::R8G8B8A8_UNORM,
Some(queue.family()),
)
.unwrap();

View File

@ -17,7 +17,7 @@ use crate::check_errors;
use crate::device::Device;
use crate::format::Format;
use crate::format::FormatFeatures;
use crate::format::FormatTy;
use crate::format::NumericType;
use crate::image::ImageAspect;
use crate::image::ImageCreateFlags;
use crate::image::ImageDimensions;
@ -246,55 +246,49 @@ impl UnsafeImage {
let mut supported_samples = ash::vk::SampleCountFlags::from_raw(0x7f); // all bits up to VK_SAMPLE_COUNT_64_BIT
if usage.sampled {
match format.ty() {
FormatTy::Float | FormatTy::Compressed => {
supported_samples &= device
.physical_device()
.properties()
.sampled_image_color_sample_counts
.into();
let aspects = format.aspects();
if format.requires_sampler_ycbcr_conversion() {
supported_samples &= ash::vk::SampleCountFlags::TYPE_1;
} else if let Some(numeric_type) = format.type_color() {
match numeric_type {
NumericType::UINT | NumericType::SINT => {
supported_samples &= device
.physical_device()
.properties()
.sampled_image_integer_sample_counts
.into();
}
NumericType::SFLOAT
| NumericType::UFLOAT
| NumericType::SNORM
| NumericType::UNORM
| NumericType::SSCALED
| NumericType::USCALED
| NumericType::SRGB => {
supported_samples &= device
.physical_device()
.properties()
.sampled_image_color_sample_counts
.into();
}
}
FormatTy::Uint | FormatTy::Sint => {
supported_samples &= device
.physical_device()
.properties()
.sampled_image_integer_sample_counts
.into();
}
FormatTy::Depth => {
} else {
if aspects.depth {
supported_samples &= device
.physical_device()
.properties()
.sampled_image_depth_sample_counts
.into();
}
FormatTy::Stencil => {
if aspects.stencil {
supported_samples &= device
.physical_device()
.properties()
.sampled_image_stencil_sample_counts
.into();
}
FormatTy::DepthStencil => {
supported_samples &= device
.physical_device()
.properties()
.sampled_image_depth_sample_counts
.into();
supported_samples &= device
.physical_device()
.properties()
.sampled_image_stencil_sample_counts
.into();
}
FormatTy::Ycbcr => {
/*
* VUID-VkImageCreateInfo-format-02562: If the image format is one of
* those formats requiring sampler ycbcr conversion, samples *must* be
* VK_SAMPLE_COUNT_1_BIT
*/
supported_samples &= ash::vk::SampleCountFlags::TYPE_1;
}
}
if usage.storage {
@ -310,46 +304,35 @@ impl UnsafeImage {
|| usage.input_attachment
|| usage.transient_attachment
{
match format.ty() {
FormatTy::Float | FormatTy::Compressed | FormatTy::Uint | FormatTy::Sint => {
supported_samples &= device
.physical_device()
.properties()
.framebuffer_color_sample_counts
.into();
}
FormatTy::Depth => {
supported_samples &= device
.physical_device()
.properties()
.framebuffer_depth_sample_counts
.into();
}
FormatTy::Stencil => {
supported_samples &= device
.physical_device()
.properties()
.framebuffer_stencil_sample_counts
.into();
}
FormatTy::DepthStencil => {
supported_samples &= device
.physical_device()
.properties()
.framebuffer_depth_sample_counts
.into();
supported_samples &= device
.physical_device()
.properties()
.framebuffer_stencil_sample_counts
.into();
}
FormatTy::Ycbcr => {
/*
* It's generally not possible to use a Ycbcr image as a framebuffer color
* attachment.
*/
return Err(ImageCreationError::UnsupportedUsage);
if format.requires_sampler_ycbcr_conversion() {
/*
* It's generally not possible to use a Ycbcr image as a framebuffer color
* attachment.
*/
return Err(ImageCreationError::UnsupportedUsage);
} else if format.type_color().is_some() {
supported_samples &= device
.physical_device()
.properties()
.framebuffer_color_sample_counts
.into();
} else {
if aspects.depth || aspects.stencil {
if aspects.depth {
supported_samples &= device
.physical_device()
.properties()
.framebuffer_depth_sample_counts
.into();
}
if aspects.stencil {
supported_samples &= device
.physical_device()
.properties()
.framebuffer_stencil_sample_counts
.into();
}
}
}
}
@ -435,32 +418,19 @@ impl UnsafeImage {
}
// Checking the dimensions against the limits.
if array_layers
> device
.physical_device()
.properties()
.max_image_array_layers
{
if array_layers > device.physical_device().properties().max_image_array_layers {
let err = ImageCreationError::UnsupportedDimensions { dimensions };
capabilities_error = Some(err);
}
match ty {
ash::vk::ImageType::TYPE_1D => {
if extent.width
> device
.physical_device()
.properties()
.max_image_dimension1_d
{
if extent.width > device.physical_device().properties().max_image_dimension1_d {
let err = ImageCreationError::UnsupportedDimensions { dimensions };
capabilities_error = Some(err);
}
}
ash::vk::ImageType::TYPE_2D => {
let limit = device
.physical_device()
.properties()
.max_image_dimension2_d;
let limit = device.physical_device().properties().max_image_dimension2_d;
if extent.width > limit || extent.height > limit {
let err = ImageCreationError::UnsupportedDimensions { dimensions };
capabilities_error = Some(err);
@ -478,10 +448,7 @@ impl UnsafeImage {
}
}
ash::vk::ImageType::TYPE_3D => {
let limit = device
.physical_device()
.properties()
.max_image_dimension3_d;
let limit = device.physical_device().properties().max_image_dimension3_d;
if extent.width > limit || extent.height > limit || extent.depth > limit {
let err = ImageCreationError::UnsupportedDimensions { dimensions };
capabilities_error = Some(err);
@ -804,8 +771,8 @@ impl UnsafeImage {
self.linear_layout_impl(mip_level, ImageAspect::Stencil)
}
/// Same as `color_linear_layout`, except that it retrieves layout for the requested ycbcr
/// component too if the format is a YcbCr format.
/// Same as `color_linear_layout`, except that it retrieves layout for the requested YCbCr
/// component too if the format is a YCbCr format.
///
/// # Panic
///
@ -825,11 +792,7 @@ impl UnsafeImage {
aspect,
ImageAspect::Plane0 | ImageAspect::Plane1 | ImageAspect::Plane2
) {
assert_eq!(self.format.ty(), FormatTy::Ycbcr);
if aspect == ImageAspect::Plane2 {
// Vulkano only supports NV12 and YV12 currently. If that changes, this will too.
assert!(self.format == Format::G8B8R8_3PLANE420Unorm);
}
debug_assert!(self.format.requires_sampler_ycbcr_conversion());
}
self.linear_layout_impl(0, aspect)
@ -1082,7 +1045,7 @@ mod tests {
UnsafeImage::new(
device,
usage,
Format::R8G8B8A8Unorm,
Format::R8G8B8A8_UNORM,
ImageCreateFlags::none(),
ImageDimensions::Dim2d {
width: 32,
@ -1113,7 +1076,7 @@ mod tests {
UnsafeImage::new(
device,
usage,
Format::R8G8B8A8Unorm,
Format::R8G8B8A8_UNORM,
ImageCreateFlags::none(),
ImageDimensions::Dim2d {
width: 32,
@ -1143,7 +1106,7 @@ mod tests {
UnsafeImage::new(
device,
usage,
Format::R8G8B8A8Unorm,
Format::R8G8B8A8_UNORM,
ImageCreateFlags::none(),
ImageDimensions::Dim2d {
width: 32,
@ -1178,7 +1141,7 @@ mod tests {
UnsafeImage::new(
device,
usage,
Format::R8G8B8A8Unorm,
Format::R8G8B8A8_UNORM,
ImageCreateFlags::none(),
ImageDimensions::Dim2d {
width: 32,
@ -1218,7 +1181,7 @@ mod tests {
UnsafeImage::new(
device,
usage,
Format::R8G8B8A8Unorm,
Format::R8G8B8A8_UNORM,
ImageCreateFlags::none(),
ImageDimensions::Dim2d {
width: 32,
@ -1253,7 +1216,7 @@ mod tests {
UnsafeImage::new(
device,
usage,
Format::ASTC_5x4UnormBlock,
Format::ASTC_5x4_UNORM_BLOCK,
ImageCreateFlags::none(),
ImageDimensions::Dim2d {
width: 32,
@ -1289,7 +1252,7 @@ mod tests {
UnsafeImage::new(
device,
usage,
Format::R8G8B8A8Unorm,
Format::R8G8B8A8_UNORM,
ImageCreateFlags::none(),
ImageDimensions::Dim2d {
width: 32,
@ -1323,7 +1286,7 @@ mod tests {
UnsafeImage::new(
device,
usage,
Format::R8G8B8A8Unorm,
Format::R8G8B8A8_UNORM,
ImageCreateFlags {
cube_compatible: true,
..ImageCreateFlags::none()

View File

@ -9,7 +9,6 @@
use crate::format::ClearValue;
use crate::format::Format;
use crate::format::FormatTy;
use crate::image::sys::UnsafeImage;
use crate::image::ImageDescriptorLayouts;
use crate::image::ImageDimensions;
@ -31,32 +30,6 @@ pub unsafe trait ImageAccess {
self.inner().image.format()
}
/// Returns true if the image is a color image.
#[inline]
fn has_color(&self) -> bool {
matches!(
self.format().ty(),
FormatTy::Float | FormatTy::Uint | FormatTy::Sint | FormatTy::Compressed
)
}
/// Returns true if the image has a depth component. In other words, if it is a depth or a
/// depth-stencil format.
#[inline]
fn has_depth(&self) -> bool {
matches!(self.format().ty(), FormatTy::Depth | FormatTy::DepthStencil)
}
/// Returns true if the image has a stencil component. In other words, if it is a stencil or a
/// depth-stencil format.
#[inline]
fn has_stencil(&self) -> bool {
matches!(
self.format().ty(),
FormatTy::Stencil | FormatTy::DepthStencil
)
}
/// Returns the number of mipmap levels of this image.
#[inline]
fn mipmap_levels(&self) -> u32 {

View File

@ -16,7 +16,6 @@
use crate::check_errors;
use crate::device::Device;
use crate::format::Format;
use crate::format::FormatTy;
use crate::image::sys::UnsafeImage;
use crate::image::ImageAccess;
use crate::image::ImageDimensions;
@ -311,7 +310,7 @@ impl UnsafeImageView {
debug_assert!(array_layers.end > array_layers.start);
debug_assert!(array_layers.end <= image.dimensions().array_layers());
if image.format().ty() == FormatTy::Ycbcr {
if image.format().requires_sampler_ycbcr_conversion() {
unimplemented!();
}

View File

@ -66,7 +66,7 @@ fn create() {
render_pass: Subpass::from(
simple_rp::CustomRenderPass::new(&device, &{
simple_rp::Formats {
color: (Format::R8G8B8A8Unorm, 1),
color: (Format::R8G8B8A8_UNORM, 1),
}
})
.unwrap(),
@ -119,7 +119,7 @@ fn bad_primitive_restart() {
render_pass: Subpass::from(
simple_rp::CustomRenderPass::new(&device, &{
simple_rp::Formats {
color: (Format::R8G8B8A8Unorm, 1),
color: (Format::R8G8B8A8_UNORM, 1),
}
})
.unwrap(),
@ -173,7 +173,7 @@ fn multi_viewport_feature() {
render_pass: Subpass::from(
simple_rp::CustomRenderPass::new(&device, &{
simple_rp::Formats {
color: (Format::R8G8B8A8Unorm, 1),
color: (Format::R8G8B8A8_UNORM, 1),
}
})
.unwrap(),
@ -227,7 +227,7 @@ fn max_viewports() {
render_pass: Subpass::from(
simple_rp::CustomRenderPass::new(&device, &{
simple_rp::Formats {
color: (Format::R8G8B8A8Unorm, 1),
color: (Format::R8G8B8A8_UNORM, 1),
}
})
.unwrap(),
@ -281,7 +281,7 @@ fn no_depth_attachment() {
render_pass: Subpass::from(
simple_rp::CustomRenderPass::new(&device, &{
simple_rp::Formats {
color: (Format::R8G8B8A8Unorm, 1),
color: (Format::R8G8B8A8_UNORM, 1),
}
})
.unwrap(),

View File

@ -55,13 +55,15 @@ where
return Err(IncompatibleRenderPassAttachmentError::NotIdentitySwizzled);
}
let aspects = image_view.image().format().aspects(); // TODO: should use view format?
for subpass in render_pass_desc.subpasses() {
if subpass
.color_attachments
.iter()
.any(|&(n, _)| n == attachment_num)
{
debug_assert!(image_view.image().has_color()); // Was normally checked by the render pass.
debug_assert!(aspects.color); // Was normally checked by the render pass.
if !image_view.image().inner().image.usage().color_attachment {
return Err(IncompatibleRenderPassAttachmentError::MissingColorAttachmentUsage);
}
@ -70,7 +72,7 @@ where
if let Some((ds, _)) = subpass.depth_stencil {
if ds == attachment_num {
// Was normally checked by the render pass.
debug_assert!(image_view.image().has_depth() || image_view.image().has_stencil());
debug_assert!(aspects.depth || aspects.stencil);
if !image_view
.image()
.inner()
@ -191,7 +193,7 @@ mod tests {
color: {
load: Clear,
store: Store,
format: Format::R8G8B8A8Unorm,
format: Format::R8G8B8A8_UNORM,
samples: 1,
}
},
@ -203,7 +205,7 @@ mod tests {
.unwrap();
let view = ImageView::new(
AttachmentImage::new(device, [128, 128], Format::R8G8B8A8Unorm).unwrap(),
AttachmentImage::new(device, [128, 128], Format::R8G8B8A8_UNORM).unwrap(),
)
.unwrap();
@ -219,7 +221,7 @@ mod tests {
color: {
load: Clear,
store: Store,
format: Format::R16G16Sfloat,
format: Format::R16G16_SFLOAT,
samples: 1,
}
},
@ -231,14 +233,14 @@ mod tests {
.unwrap();
let view = ImageView::new(
AttachmentImage::new(device, [128, 128], Format::R8G8B8A8Unorm).unwrap(),
AttachmentImage::new(device, [128, 128], Format::R8G8B8A8_UNORM).unwrap(),
)
.unwrap();
match ensure_image_view_compatible(rp.desc(), 0, &view) {
Err(IncompatibleRenderPassAttachmentError::FormatMismatch {
expected: Format::R16G16Sfloat,
obtained: Format::R8G8B8A8Unorm,
expected: Format::R16G16_SFLOAT,
obtained: Format::R8G8B8A8_UNORM,
}) => (),
e => panic!("{:?}", e),
}
@ -250,7 +252,7 @@ mod tests {
let rp = RenderPassDesc::empty();
let view = ImageView::new(
AttachmentImage::new(device, [128, 128], Format::R8G8B8A8Unorm).unwrap(),
AttachmentImage::new(device, [128, 128], Format::R8G8B8A8_UNORM).unwrap(),
)
.unwrap();

View File

@ -619,7 +619,7 @@ mod tests {
color: {
load: Clear,
store: DontCare,
format: Format::R8G8B8A8Unorm,
format: Format::R8G8B8A8_UNORM,
samples: 1,
}
},
@ -632,7 +632,7 @@ mod tests {
);
let view = ImageView::new(
AttachmentImage::new(device.clone(), [1024, 768], Format::R8G8B8A8Unorm).unwrap(),
AttachmentImage::new(device.clone(), [1024, 768], Format::R8G8B8A8_UNORM).unwrap(),
)
.unwrap();
let _ = Framebuffer::start(render_pass)
@ -664,7 +664,7 @@ mod tests {
color: {
load: Clear,
store: DontCare,
format: Format::R8G8B8A8Unorm,
format: Format::R8G8B8A8_UNORM,
samples: 1,
}
},
@ -677,7 +677,7 @@ mod tests {
);
let view = ImageView::new(
AttachmentImage::new(device.clone(), [1024, 768], Format::R8Unorm).unwrap(),
AttachmentImage::new(device.clone(), [1024, 768], Format::R8_UNORM).unwrap(),
)
.unwrap();
@ -699,7 +699,7 @@ mod tests {
color: {
load: Clear,
store: DontCare,
format: Format::R8G8B8A8Unorm,
format: Format::R8G8B8A8_UNORM,
samples: 1,
}
},
@ -712,7 +712,7 @@ mod tests {
);
let view = ImageView::new(
AttachmentImage::new(device.clone(), [600, 600], Format::R8G8B8A8Unorm).unwrap(),
AttachmentImage::new(device.clone(), [600, 600], Format::R8G8B8A8_UNORM).unwrap(),
)
.unwrap();
@ -733,7 +733,7 @@ mod tests {
color: {
load: Clear,
store: DontCare,
format: Format::R8G8B8A8Unorm,
format: Format::R8G8B8A8_UNORM,
samples: 1,
}
},
@ -746,7 +746,7 @@ mod tests {
);
let view = ImageView::new(
AttachmentImage::new(device.clone(), [512, 700], Format::R8G8B8A8Unorm).unwrap(),
AttachmentImage::new(device.clone(), [512, 700], Format::R8G8B8A8_UNORM).unwrap(),
)
.unwrap();
@ -772,13 +772,13 @@ mod tests {
a: {
load: Clear,
store: DontCare,
format: Format::R8G8B8A8Unorm,
format: Format::R8G8B8A8_UNORM,
samples: 1,
},
b: {
load: Clear,
store: DontCare,
format: Format::R8G8B8A8Unorm,
format: Format::R8G8B8A8_UNORM,
samples: 1,
}
},
@ -791,11 +791,11 @@ mod tests {
);
let a = ImageView::new(
AttachmentImage::new(device.clone(), [512, 512], Format::R8G8B8A8Unorm).unwrap(),
AttachmentImage::new(device.clone(), [512, 512], Format::R8G8B8A8_UNORM).unwrap(),
)
.unwrap();
let b = ImageView::new(
AttachmentImage::new(device.clone(), [512, 513], Format::R8G8B8A8Unorm).unwrap(),
AttachmentImage::new(device.clone(), [512, 513], Format::R8G8B8A8_UNORM).unwrap(),
)
.unwrap();
@ -821,13 +821,13 @@ mod tests {
a: {
load: Clear,
store: DontCare,
format: Format::R8G8B8A8Unorm,
format: Format::R8G8B8A8_UNORM,
samples: 1,
},
b: {
load: Clear,
store: DontCare,
format: Format::R8G8B8A8Unorm,
format: Format::R8G8B8A8_UNORM,
samples: 1,
}
},
@ -840,11 +840,11 @@ mod tests {
);
let a = ImageView::new(
AttachmentImage::new(device.clone(), [256, 512], Format::R8G8B8A8Unorm).unwrap(),
AttachmentImage::new(device.clone(), [256, 512], Format::R8G8B8A8_UNORM).unwrap(),
)
.unwrap();
let b = ImageView::new(
AttachmentImage::new(device.clone(), [512, 128], Format::R8G8B8A8Unorm).unwrap(),
AttachmentImage::new(device.clone(), [512, 128], Format::R8G8B8A8_UNORM).unwrap(),
)
.unwrap();
@ -872,13 +872,13 @@ mod tests {
a: {
load: Clear,
store: DontCare,
format: Format::R8G8B8A8Unorm,
format: Format::R8G8B8A8_UNORM,
samples: 1,
},
b: {
load: Clear,
store: DontCare,
format: Format::R8G8B8A8Unorm,
format: Format::R8G8B8A8_UNORM,
samples: 1,
}
},
@ -891,7 +891,7 @@ mod tests {
);
let view = ImageView::new(
AttachmentImage::new(device.clone(), [256, 512], Format::R8G8B8A8Unorm).unwrap(),
AttachmentImage::new(device.clone(), [256, 512], Format::R8G8B8A8_UNORM).unwrap(),
)
.unwrap();
@ -919,7 +919,7 @@ mod tests {
a: {
load: Clear,
store: DontCare,
format: Format::R8G8B8A8Unorm,
format: Format::R8G8B8A8_UNORM,
samples: 1,
}
},
@ -932,11 +932,11 @@ mod tests {
);
let a = ImageView::new(
AttachmentImage::new(device.clone(), [256, 512], Format::R8G8B8A8Unorm).unwrap(),
AttachmentImage::new(device.clone(), [256, 512], Format::R8G8B8A8_UNORM).unwrap(),
)
.unwrap();
let b = ImageView::new(
AttachmentImage::new(device.clone(), [256, 512], Format::R8G8B8A8Unorm).unwrap(),
AttachmentImage::new(device.clone(), [256, 512], Format::R8G8B8A8_UNORM).unwrap(),
)
.unwrap();

View File

@ -216,13 +216,13 @@ mod tests {
a: {
load: Clear,
store: DontCare,
format: Format::R8G8B8A8Unorm,
format: Format::R8G8B8A8_UNORM,
samples: 4,
},
b: {
load: DontCare,
store: Store,
format: Format::R8G8B8A8Unorm,
format: Format::R8G8B8A8_UNORM,
samples: 1,
}
},

View File

@ -10,7 +10,6 @@
use crate::check_errors;
use crate::device::Device;
use crate::device::DeviceOwned;
use crate::format::FormatTy;
use crate::image::ImageLayout;
use crate::image::SampleCount;
use crate::pipeline::shader::ShaderInterface;
@ -69,7 +68,7 @@ use std::sync::Mutex;
/// foo: {
/// load: Clear,
/// store: Store,
/// format: Format::R8G8B8A8Unorm,
/// format: Format::R8G8B8A8_UNORM,
/// samples: 1,
/// }
/// },
@ -286,10 +285,7 @@ impl RenderPass {
for pass in description.subpasses() {
if pass.color_attachments.len() as u32
> device
.physical_device()
.properties()
.max_color_attachments
> device.physical_device().properties().max_color_attachments
{
return Err(RenderPassCreationError::ColorAttachmentsLimitExceeded);
}
@ -706,12 +702,7 @@ impl Subpass {
None => return false,
};
match self.attachment_desc(atch_num).format.ty() {
FormatTy::Depth => true,
FormatTy::Stencil => false,
FormatTy::DepthStencil => true,
_ => unreachable!(),
}
self.attachment_desc(atch_num).format.aspects().depth
}
/// Returns true if the subpass has a depth attachment or a depth-stencil attachment whose
@ -729,12 +720,7 @@ impl Subpass {
None => return false,
};
match self.attachment_desc(atch_num).format.ty() {
FormatTy::Depth => true,
FormatTy::Stencil => false,
FormatTy::DepthStencil => true,
_ => unreachable!(),
}
self.attachment_desc(atch_num).format.aspects().depth
}
/// Returns true if the subpass has a stencil attachment or a depth-stencil attachment.
@ -746,12 +732,7 @@ impl Subpass {
None => return false,
};
match self.attachment_desc(atch_num).format.ty() {
FormatTy::Depth => false,
FormatTy::Stencil => true,
FormatTy::DepthStencil => true,
_ => unreachable!(),
}
self.attachment_desc(atch_num).format.aspects().stencil
}
/// Returns true if the subpass has a stencil attachment or a depth-stencil attachment whose
@ -770,12 +751,7 @@ impl Subpass {
None => return false,
};
match self.attachment_desc(atch_num).format.ty() {
FormatTy::Depth => false,
FormatTy::Stencil => true,
FormatTy::DepthStencil => true,
_ => unreachable!(),
}
self.attachment_desc(atch_num).format.aspects().stencil
}
/// Returns true if the subpass has any color or depth/stencil attachment.
@ -853,28 +829,23 @@ mod tests {
fn too_many_color_atch() {
let (device, _) = gfx_dev_and_queue!();
if device
.physical_device()
.properties()
.max_color_attachments
>= 10
{
if device.physical_device().properties().max_color_attachments >= 10 {
return; // test ignored
}
let rp = single_pass_renderpass! {
device.clone(),
attachments: {
a1: { load: Clear, store: DontCare, format: Format::R8G8B8A8Unorm, samples: 1, },
a2: { load: Clear, store: DontCare, format: Format::R8G8B8A8Unorm, samples: 1, },
a3: { load: Clear, store: DontCare, format: Format::R8G8B8A8Unorm, samples: 1, },
a4: { load: Clear, store: DontCare, format: Format::R8G8B8A8Unorm, samples: 1, },
a5: { load: Clear, store: DontCare, format: Format::R8G8B8A8Unorm, samples: 1, },
a6: { load: Clear, store: DontCare, format: Format::R8G8B8A8Unorm, samples: 1, },
a7: { load: Clear, store: DontCare, format: Format::R8G8B8A8Unorm, samples: 1, },
a8: { load: Clear, store: DontCare, format: Format::R8G8B8A8Unorm, samples: 1, },
a9: { load: Clear, store: DontCare, format: Format::R8G8B8A8Unorm, samples: 1, },
a10: { load: Clear, store: DontCare, format: Format::R8G8B8A8Unorm, samples: 1, }
a1: { load: Clear, store: DontCare, format: Format::R8G8B8A8_UNORM, samples: 1, },
a2: { load: Clear, store: DontCare, format: Format::R8G8B8A8_UNORM, samples: 1, },
a3: { load: Clear, store: DontCare, format: Format::R8G8B8A8_UNORM, samples: 1, },
a4: { load: Clear, store: DontCare, format: Format::R8G8B8A8_UNORM, samples: 1, },
a5: { load: Clear, store: DontCare, format: Format::R8G8B8A8_UNORM, samples: 1, },
a6: { load: Clear, store: DontCare, format: Format::R8G8B8A8_UNORM, samples: 1, },
a7: { load: Clear, store: DontCare, format: Format::R8G8B8A8_UNORM, samples: 1, },
a8: { load: Clear, store: DontCare, format: Format::R8G8B8A8_UNORM, samples: 1, },
a9: { load: Clear, store: DontCare, format: Format::R8G8B8A8_UNORM, samples: 1, },
a10: { load: Clear, store: DontCare, format: Format::R8G8B8A8_UNORM, samples: 1, }
},
pass: {
color: [a1, a2, a3, a4, a5, a6, a7, a8, a9, a10],
@ -895,7 +866,7 @@ mod tests {
let rp = single_pass_renderpass! {
device.clone(),
attachments: {
a: { load: Clear, store: DontCare, format: Format::R8G8B8A8Unorm, samples: 1, }
a: { load: Clear, store: DontCare, format: Format::R8G8B8A8_UNORM, samples: 1, }
},
pass: {
color: [a],

View File

@ -592,7 +592,7 @@ impl<W> SwapchainBuilder<W> {
}
format
} else {
if let Some(format) = [Format::R8G8B8A8Unorm, Format::B8G8R8A8Unorm]
if let Some(format) = [Format::R8G8B8A8_UNORM, Format::B8G8R8A8_UNORM]
.iter()
.copied()
.find(|&format| {