mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2025-02-16 09:02:25 +00:00
Add generation of Format
to autogen (#1687)
* Add generation of `Format` to autogen * Better documentation
This commit is contained in:
parent
b35d69b7b3
commit
7a50bd5cb5
@ -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,
|
||||
|
@ -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(),
|
||||
|
@ -191,7 +191,7 @@ fn main() {
|
||||
height: 1024,
|
||||
array_layers: 1,
|
||||
},
|
||||
Format::R8G8B8A8Unorm,
|
||||
Format::R8G8B8A8_UNORM,
|
||||
Some(queue.family()),
|
||||
)
|
||||
.unwrap();
|
||||
|
@ -168,7 +168,7 @@ fn main() {
|
||||
image_data.iter().cloned(),
|
||||
dimensions,
|
||||
MipmapsCount::One,
|
||||
Format::R8G8B8A8Srgb,
|
||||
Format::R8G8B8A8_SRGB,
|
||||
queue.clone(),
|
||||
)
|
||||
.unwrap();
|
||||
|
@ -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.
|
||||
}
|
||||
},
|
||||
|
@ -116,7 +116,7 @@ fn main() {
|
||||
height: 512,
|
||||
array_layers: 2,
|
||||
},
|
||||
Format::B8G8R8A8Srgb,
|
||||
Format::B8G8R8A8_SRGB,
|
||||
ImageUsage {
|
||||
transfer_source: true,
|
||||
color_attachment: true,
|
||||
|
@ -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,
|
||||
|
@ -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")),
|
||||
}])
|
||||
};
|
||||
|
@ -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(),
|
||||
)
|
||||
};
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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) },
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
724
vulkano/autogen/formats.rs
Normal 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 }
|
||||
)
|
||||
}
|
||||
}
|
@ -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(®istry);
|
||||
let extensions = get_extensions(®istry);
|
||||
let features = get_features(®istry);
|
||||
let formats = get_formats(
|
||||
®istry,
|
||||
features.values().map(|x| x.children.iter()).flatten(),
|
||||
extensions.values().map(|x| x.children.iter()).flatten(),
|
||||
);
|
||||
let types = get_types(®istry, &aliases, &features, &extensions);
|
||||
let header_version = get_header_version(®istry);
|
||||
|
||||
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>,
|
||||
|
@ -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!(),
|
||||
}
|
||||
|
@ -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"),
|
||||
|
@ -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!();
|
||||
}
|
||||
|
||||
|
@ -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 => {
|
||||
|
@ -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 => {
|
||||
|
@ -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
|
||||
);
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -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()
|
||||
|
@ -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 {
|
||||
|
@ -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!();
|
||||
}
|
||||
|
||||
|
@ -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(),
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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,
|
||||
}
|
||||
},
|
||||
|
@ -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],
|
||||
|
@ -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| {
|
||||
|
Loading…
Reference in New Issue
Block a user