Rework vertex attributes system

This commit is contained in:
Pierre Krieger 2016-04-30 10:09:00 +02:00
parent 3749f26063
commit 3f4b9e126b
7 changed files with 614 additions and 430 deletions

View File

@ -188,11 +188,8 @@ fn write_entry_point(doc: &parse::Spirv, instruction: &parse::Instruction) -> St
let (ty, f_call) = match *execution {
enums::ExecutionModel::ExecutionModelVertex => {
let mut input_types = Vec::new();
let mut attributes = Vec::new();
// TODO: sort types by location
for interface in interface.iter() {
for i in doc.instructions.iter() {
match i {
@ -204,30 +201,41 @@ fn write_entry_point(doc: &parse::Spirv, instruction: &parse::Instruction) -> St
continue;
}
input_types.push(type_from_id(doc, result_type_id));
let name = name_from_id(doc, result_id);
let loc = match location_decoration(doc, result_id) {
Some(l) => l,
None => panic!("vertex attribute `{}` is missing a location", name)
};
attributes.push((loc, name));
attributes.push((loc, name, format_from_id(doc, result_type_id)));
},
_ => ()
}
}
}
let input = {
let input = input_types.join(", ");
if input.is_empty() { input } else { input + "," }
};
// Checking for overlapping attributes.
for (offset, &(loc, ref name, (_, loc_len))) in attributes.iter().enumerate() {
for &(loc2, ref name2, (_, loc_len2)) in attributes.iter().skip(offset + 1) {
if loc == loc2 || (loc < loc2 && loc + loc_len as u32 > loc2) ||
(loc2 < loc && loc2 + loc_len2 as u32 > loc)
{
panic!("The locations of vertex attributes `{}` and `{}` overlap",
name, name2);
}
}
}
let attributes = attributes.iter().map(|&(loc, ref name)| {
format!("({}, ::std::borrow::Cow::Borrowed(\"{}\"))", loc, name)
let attributes = attributes.iter().map(|&(loc, ref name, (ref ty, num_locs))| {
assert!(num_locs >= 1);
format!("::vulkano::pipeline::shader::ShaderInterfaceDefEntry {{
location: {} .. {},
format: ::vulkano::format::Format::{},
name: Some(::std::borrow::Cow::Borrowed(\"{}\"))
}}", loc, loc as usize + num_locs, ty, name)
}).collect::<Vec<_>>().join(", ");
let t = format!("::vulkano::pipeline::shader::VertexShaderEntryPoint<(), ({input}), Layout>",
input = input);
let t = "::vulkano::pipeline::shader::VertexShaderEntryPoint<(), Vec<::vulkano::pipeline::shader::ShaderInterfaceDefEntry>, Layout>".to_owned();
let f = format!("vertex_shader_entry_point(::std::ffi::CStr::from_ptr(NAME.as_ptr() as *const _), Layout, vec![{}])", attributes);
(t, f)
},
@ -295,6 +303,56 @@ fn write_entry_point(doc: &parse::Spirv, instruction: &parse::Instruction) -> St
f_call = f_call)
}
/// Returns the vulkano `Format` and number of occupied locations from an id.
fn format_from_id(doc: &parse::Spirv, searched: u32) -> (String, usize) {
for instruction in doc.instructions.iter() {
match instruction {
&parse::Instruction::TypeInt { result_id, width, signedness } if result_id == searched => {
return ("R32Sint".to_owned(), 1);
},
&parse::Instruction::TypeFloat { result_id, width } if result_id == searched => {
return ("R32Sfloat".to_owned(), 1);
},
&parse::Instruction::TypeVector { result_id, component_id, count } if result_id == searched => {
let (format, sz) = format_from_id(doc, component_id);
assert!(format.starts_with("R32"));
assert_eq!(sz, 1);
let format = if count == 1 {
format
} else if count == 2 {
format!("R32G32{}", &format[3..])
} else if count == 3 {
format!("R32G32B32{}", &format[3..])
} else if count == 4 {
format!("R32G32B32A32{}", &format[3..])
} else {
panic!("Found vector type with more than 4 elements")
};
return (format, sz);
},
&parse::Instruction::TypeMatrix { result_id, column_type_id, column_count } if result_id == searched => {
let (format, sz) = format_from_id(doc, column_type_id);
return (format, sz * column_count as usize);
},
&parse::Instruction::TypeArray { result_id, type_id, length_id } if result_id == searched => {
let (format, sz) = format_from_id(doc, type_id);
let len = doc.instructions.iter().filter_map(|e| {
match e { &parse::Instruction::Constant { result_id, ref data, .. } if result_id == length_id => Some(data.clone()), _ => None }
}).next().expect("failed to find array length");
let len = len.iter().rev().fold(0u64, |a, &b| (a << 32) | b as u64);
return (format, sz * len as usize);
},
&parse::Instruction::TypePointer { result_id, type_id, .. } if result_id == searched => {
return format_from_id(doc, type_id);
},
_ => ()
}
}
panic!("Type #{} not found or invalid", searched)
}
// TODO: remove when no longer necessary
// TODO: struct definitions don't use this function, so irrelevant elements should be removed
fn type_from_id(doc: &parse::Spirv, searched: u32) -> String {
for instruction in doc.instructions.iter() {

View File

@ -769,7 +769,7 @@ impl InnerCommandBufferBuilder {
pub unsafe fn draw<V, Pv, Pl, L, Rp, Pc>(mut self, pipeline: &Arc<GraphicsPipeline<Pv, Pl, Rp>>,
vertices: V, dynamic: &DynamicState,
sets: L, push_constants: &Pc) -> InnerCommandBufferBuilder
where Pv: 'static + VertexDefinition + VertexSource<V>, L: DescriptorSetsCollection + Send + Sync,
where Pv: 'static + VertexSource<V>, L: DescriptorSetsCollection + Send + Sync,
Pl: 'static + PipelineLayout + Send + Sync, Rp: 'static + Send + Sync,
Pc: 'static + Clone + Send + Sync
{
@ -812,7 +812,7 @@ impl InnerCommandBufferBuilder {
vertices: V, indices: Ib, dynamic: &DynamicState,
sets: L, push_constants: &Pc) -> InnerCommandBufferBuilder
where L: DescriptorSetsCollection + Send + Sync,
Pv: 'static + VertexDefinition + VertexSource<V>,
Pv: 'static + VertexSource<V>,
Pl: 'static + PipelineLayout + Send + Sync, Rp: 'static + Send + Sync,
Ib: Into<BufferSlice<'a, [I], Ibb>>, I: 'static + Index, Ibb: Buffer + 'static,
Pc: 'static + Clone + Send + Sync
@ -869,7 +869,7 @@ impl InnerCommandBufferBuilder {
pub unsafe fn draw_indirect<I, V, Pv, Pl, L, Rp, Pc>(mut self, buffer: &Arc<I>, pipeline: &Arc<GraphicsPipeline<Pv, Pl, Rp>>,
vertices: V, dynamic: &DynamicState,
sets: L, push_constants: &Pc) -> InnerCommandBufferBuilder
where Pv: 'static + VertexDefinition + VertexSource<V>, L: DescriptorSetsCollection + Send + Sync,
where Pv: 'static + VertexSource<V>, L: DescriptorSetsCollection + Send + Sync,
Pl: 'static + PipelineLayout + Send + Sync, Rp: 'static + Send + Sync, Pc: 'static + Clone + Send + Sync,
I: 'static + TypedBuffer<Content = [DrawIndirectCommand]>
{
@ -962,7 +962,7 @@ impl InnerCommandBufferBuilder {
fn bind_gfx_pipeline_state<V, Pl, L, Rp, Pc>(&mut self, pipeline: &Arc<GraphicsPipeline<V, Pl, Rp>>,
dynamic: &DynamicState, sets: L, push_constants: &Pc)
where V: 'static + VertexDefinition + Send + Sync, L: DescriptorSetsCollection + Send + Sync,
where V: 'static + Send + Sync, L: DescriptorSetsCollection + Send + Sync,
Pl: 'static + PipelineLayout + Send + Sync, Rp: 'static + Send + Sync, Pc: 'static + Clone + Send + Sync
{
unsafe {

View File

@ -325,7 +325,7 @@ impl PrimaryCommandBufferBuilderInlineDraw {
pub fn draw<V, L, Pv, Pl, Rp, Pc>(self, pipeline: &Arc<GraphicsPipeline<Pv, Pl, Rp>>,
vertices: V, dynamic: &DynamicState, sets: L, push_constants: &Pc)
-> PrimaryCommandBufferBuilderInlineDraw
where Pv: VertexDefinition + VertexSource<V> + 'static, Pl: PipelineLayout + 'static + Send + Sync, Rp: 'static + Send + Sync,
where Pv: VertexSource<V> + 'static, Pl: PipelineLayout + 'static + Send + Sync, Rp: 'static + Send + Sync,
L: DescriptorSetsCollection + Send + Sync, Pc: 'static + Clone + Send + Sync
{
// FIXME: check subpass
@ -343,7 +343,7 @@ impl PrimaryCommandBufferBuilderInlineDraw {
pub fn draw_indexed<'a, V, L, Pv, Pl, Rp, I, Ib, Ibb, Pc>(self, pipeline: &Arc<GraphicsPipeline<Pv, Pl, Rp>>,
vertices: V, indices: Ib, dynamic: &DynamicState,
sets: L, push_constants: &Pc) -> PrimaryCommandBufferBuilderInlineDraw
where Pv: 'static + VertexDefinition + VertexSource<V> + Send + Sync, Pl: 'static + PipelineLayout + Send + Sync, Rp: 'static + Send + Sync,
where Pv: 'static + VertexSource<V> + Send + Sync, Pl: 'static + PipelineLayout + Send + Sync, Rp: 'static + Send + Sync,
Ib: Into<BufferSlice<'a, [I], Ibb>>, I: 'static + Index, Ibb: Buffer + 'static + Send + Sync,
L: DescriptorSetsCollection + Send + Sync, Pc: 'static + Clone + Send + Sync
{
@ -587,7 +587,7 @@ impl<R> SecondaryGraphicsCommandBufferBuilder<R>
pub fn draw<V, L, Pv, Pl, Rp, Pc>(self, pipeline: &Arc<GraphicsPipeline<Pv, Pl, Rp>>,
vertices: V, dynamic: &DynamicState, sets: L, push_constants: &Pc)
-> SecondaryGraphicsCommandBufferBuilder<R>
where Pv: VertexDefinition + VertexSource<V> + 'static, Pl: PipelineLayout + 'static + Send + Sync,
where Pv: VertexSource<V> + 'static, Pl: PipelineLayout + 'static + Send + Sync,
Rp: RenderPass + RenderPassDesc + 'static + Send + Sync, L: DescriptorSetsCollection + Send + Sync,
R: RenderPassCompatible<Rp>, Pc: 'static + Clone + Send + Sync
{
@ -608,7 +608,7 @@ impl<R> SecondaryGraphicsCommandBufferBuilder<R>
pub fn draw_indexed<'a, V, L, Pv, Pl, Rp, I, Ib, Ibb, Pc>(self, pipeline: &Arc<GraphicsPipeline<Pv, Pl, Rp>>,
vertices: V, indices: Ib, dynamic: &DynamicState,
sets: L, push_constants: &Pc) -> SecondaryGraphicsCommandBufferBuilder<R>
where Pv: 'static + VertexDefinition + VertexSource<V>, Pl: 'static + PipelineLayout + Send + Sync,
where Pv: 'static + VertexSource<V>, Pl: 'static + PipelineLayout + Send + Sync,
Rp: RenderPass + RenderPassDesc + 'static + Send + Sync,
Ib: Into<BufferSlice<'a, [I], Ibb>>, I: 'static + Index, Ibb: Buffer + 'static,
L: DescriptorSetsCollection + Send + Sync, Pc: 'static + Clone + Send + Sync
@ -630,7 +630,7 @@ impl<R> SecondaryGraphicsCommandBufferBuilder<R>
pub fn draw_indirect<I, V, Pv, Pl, L, Rp, Pc>(self, buffer: &Arc<I>, pipeline: &Arc<GraphicsPipeline<Pv, Pl, Rp>>,
vertices: V, dynamic: &DynamicState,
sets: L, push_constants: &Pc) -> SecondaryGraphicsCommandBufferBuilder<R>
where Pv: 'static + VertexDefinition + VertexSource<V>, L: DescriptorSetsCollection + Send + Sync,
where Pv: 'static + VertexSource<V>, L: DescriptorSetsCollection + Send + Sync,
Pl: 'static + PipelineLayout + Send + Sync, Rp: RenderPass + RenderPassDesc + 'static + Send + Sync,
Pc: 'static + Clone + Send + Sync,
I: 'static + TypedBuffer<Content = [DrawIndirectCommand]>

View File

@ -128,7 +128,7 @@ unsafe impl Data for u8 {
}
macro_rules! formats {
($($name:ident => $vk:ident [$($f_ty:tt)*] {$($d_ty:tt)*},)+) => (
($($name:ident => $vk:ident [$sz:expr] [$($f_ty:tt)*] {$($d_ty:tt)*},)+) => (
/// An enumeration of all the possible formats.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)]
@ -146,6 +146,17 @@ macro_rules! formats {
.. other functions ..
*/
/// Returns the size in bytes of an element of this format. Returns `None` if the
/// size is irrelevant (for example for compressed formats).
#[inline]
pub fn size(&self) -> Option<usize> {
match *self {
$(
Format::$name => $sz,
)+
}
}
/// Returns the `Format` corresponding to a Vulkan constant.
#[doc(hidden)]
pub fn from_num(val: u32) -> Option<Format> {
@ -350,190 +361,190 @@ macro_rules! formats {
}
formats! {
R4G4UnormPack8 => FORMAT_R4G4_UNORM_PACK8 [float=2] {u8},
R4G4B4A4UnormPack16 => FORMAT_R4G4B4A4_UNORM_PACK16 [float=4] {u16},
B4G4R4A4UnormPack16 => FORMAT_B4G4R4A4_UNORM_PACK16 [float=4] {u16},
R5G6B5UnormPack16 => FORMAT_R5G6B5_UNORM_PACK16 [float=3] {u16},
B5G6R5UnormPack16 => FORMAT_B5G6R5_UNORM_PACK16 [float=3] {u16},
R5G5B5A1UnormPack16 => FORMAT_R5G5B5A1_UNORM_PACK16 [float=4] {u16},
B5G5R5A1UnormPack16 => FORMAT_B5G5R5A1_UNORM_PACK16 [float=4] {u16},
A1R5G5B5UnormPack16 => FORMAT_A1R5G5B5_UNORM_PACK16 [float=4] {u16},
R8Unorm => FORMAT_R8_UNORM [float=1] {u8},
R8Snorm => FORMAT_R8_SNORM [float=1] {i8},
R8Uscaled => FORMAT_R8_USCALED [float=1] {u8},
R8Sscaled => FORMAT_R8_SSCALED [float=1] {i8},
R8Uint => FORMAT_R8_UINT [uint=1] {u8},
R8Sint => FORMAT_R8_SINT [sint=1] {i8},
R8Srgb => FORMAT_R8_SRGB [float=1] {u8},
R8G8Unorm => FORMAT_R8G8_UNORM [float=2] {[u8; 2]},
R8G8Snorm => FORMAT_R8G8_SNORM [float=2] {[i8; 2]},
R8G8Uscaled => FORMAT_R8G8_USCALED [float=2] {[u8; 2]},
R8G8Sscaled => FORMAT_R8G8_SSCALED [float=2] {[i8; 2]},
R8G8Uint => FORMAT_R8G8_UINT [uint=2] {[u8; 2]},
R8G8Sint => FORMAT_R8G8_SINT [sint=2] {[i8; 2]},
R8G8Srgb => FORMAT_R8G8_SRGB [float=2] {[u8; 2]},
R8G8B8Unorm => FORMAT_R8G8B8_UNORM [float=3] {[u8; 3]},
R8G8B8Snorm => FORMAT_R8G8B8_SNORM [float=3] {[i8; 3]},
R8G8B8Uscaled => FORMAT_R8G8B8_USCALED [float=3] {[u8; 3]},
R8G8B8Sscaled => FORMAT_R8G8B8_SSCALED [float=3] {[i8; 3]},
R8G8B8Uint => FORMAT_R8G8B8_UINT [uint=3] {[u8; 3]},
R8G8B8Sint => FORMAT_R8G8B8_SINT [sint=3] {[i8; 3]},
R8G8B8Srgb => FORMAT_R8G8B8_SRGB [float=3] {[u8; 3]},
B8G8R8Unorm => FORMAT_B8G8R8_UNORM [float=3] {[u8; 3]},
B8G8R8Snorm => FORMAT_B8G8R8_SNORM [float=3] {[i8; 3]},
B8G8R8Uscaled => FORMAT_B8G8R8_USCALED [float=3] {[u8; 3]},
B8G8R8Sscaled => FORMAT_B8G8R8_SSCALED [float=3] {[i8; 3]},
B8G8R8Uint => FORMAT_B8G8R8_UINT [uint=3] {[u8; 3]},
B8G8R8Sint => FORMAT_B8G8R8_SINT [sint=3] {[i8; 3]},
B8G8R8Srgb => FORMAT_B8G8R8_SRGB [float=3] {[u8; 3]},
R8G8B8A8Unorm => FORMAT_R8G8B8A8_UNORM [float=4] {[u8; 4]},
R8G8B8A8Snorm => FORMAT_R8G8B8A8_SNORM [float=4] {[i8; 4]},
R8G8B8A8Uscaled => FORMAT_R8G8B8A8_USCALED [float=4] {[u8; 4]},
R8G8B8A8Sscaled => FORMAT_R8G8B8A8_SSCALED [float=4] {[i8; 4]},
R8G8B8A8Uint => FORMAT_R8G8B8A8_UINT [uint=4] {[u8; 4]},
R8G8B8A8Sint => FORMAT_R8G8B8A8_SINT [sint=4] {[i8; 4]},
R8G8B8A8Srgb => FORMAT_R8G8B8A8_SRGB [float=4] {[u8; 4]},
B8G8R8A8Unorm => FORMAT_B8G8R8A8_UNORM [float=4] {[u8; 4]},
B8G8R8A8Snorm => FORMAT_B8G8R8A8_SNORM [float=4] {[i8; 4]},
B8G8R8A8Uscaled => FORMAT_B8G8R8A8_USCALED [float=4] {[u8; 4]},
B8G8R8A8Sscaled => FORMAT_B8G8R8A8_SSCALED [float=4] {[i8; 4]},
B8G8R8A8Uint => FORMAT_B8G8R8A8_UINT [uint=4] {[u8; 4]},
B8G8R8A8Sint => FORMAT_B8G8R8A8_SINT [sint=4] {[i8; 4]},
B8G8R8A8Srgb => FORMAT_B8G8R8A8_SRGB [float=4] {[u8; 4]},
A8B8G8R8UnormPack32 => FORMAT_A8B8G8R8_UNORM_PACK32 [float=4] {[u8; 4]},
A8B8G8R8SnormPack32 => FORMAT_A8B8G8R8_SNORM_PACK32 [float=4] {[i8; 4]},
A8B8G8R8UscaledPack32 => FORMAT_A8B8G8R8_USCALED_PACK32 [float=4] {[u8; 4]},
A8B8G8R8SscaledPack32 => FORMAT_A8B8G8R8_SSCALED_PACK32 [float=4] {[i8; 4]},
A8B8G8R8UintPack32 => FORMAT_A8B8G8R8_UINT_PACK32 [uint=4] {[u8; 4]},
A8B8G8R8SintPack32 => FORMAT_A8B8G8R8_SINT_PACK32 [sint=4] {[i8; 4]},
A8B8G8R8SrgbPack32 => FORMAT_A8B8G8R8_SRGB_PACK32 [float=4] {[u8; 4]},
A2R10G10B10UnormPack32 => FORMAT_A2R10G10B10_UNORM_PACK32 [float=4] {u32},
A2R10G10B10SnormPack32 => FORMAT_A2R10G10B10_SNORM_PACK32 [float=4] {u32},
A2R10G10B10UscaledPack32 => FORMAT_A2R10G10B10_USCALED_PACK32 [float=4] {u32},
A2R10G10B10SscaledPack32 => FORMAT_A2R10G10B10_SSCALED_PACK32 [float=4] {u32},
A2R10G10B10UintPack32 => FORMAT_A2R10G10B10_UINT_PACK32 [uint=4] {u32},
A2R10G10B10SintPack32 => FORMAT_A2R10G10B10_SINT_PACK32 [sint=4] {u32},
A2B10G10R10UnormPack32 => FORMAT_A2B10G10R10_UNORM_PACK32 [float=4] {u32},
A2B10G10R10SnormPack32 => FORMAT_A2B10G10R10_SNORM_PACK32 [float=4] {u32},
A2B10G10R10UscaledPack32 => FORMAT_A2B10G10R10_USCALED_PACK32 [float=4] {u32},
A2B10G10R10SscaledPack32 => FORMAT_A2B10G10R10_SSCALED_PACK32 [float=4] {u32},
A2B10G10R10UintPack32 => FORMAT_A2B10G10R10_UINT_PACK32 [uint=4] {u32},
A2B10G10R10SintPack32 => FORMAT_A2B10G10R10_SINT_PACK32 [sint=4] {u32},
R16Unorm => FORMAT_R16_UNORM [float=1] {u16},
R16Snorm => FORMAT_R16_SNORM [float=1] {i16},
R16Uscaled => FORMAT_R16_USCALED [float=1] {u16},
R16Sscaled => FORMAT_R16_SSCALED [float=1] {i16},
R16Uint => FORMAT_R16_UINT [uint=1] {u16},
R16Sint => FORMAT_R16_SINT [sint=1] {i16},
R16Sfloat => FORMAT_R16_SFLOAT [float=1] {},
R16G16Unorm => FORMAT_R16G16_UNORM [float=2] {[u16; 2]},
R16G16Snorm => FORMAT_R16G16_SNORM [float=2] {[i16; 2]},
R16G16Uscaled => FORMAT_R16G16_USCALED [float=2] {[u16; 2]},
R16G16Sscaled => FORMAT_R16G16_SSCALED [float=2] {[i16; 2]},
R16G16Uint => FORMAT_R16G16_UINT [uint=2] {[u16; 2]},
R16G16Sint => FORMAT_R16G16_SINT [sint=2] {[i16; 2]},
R16G16Sfloat => FORMAT_R16G16_SFLOAT [float=2] {},
R16G16B16Unorm => FORMAT_R16G16B16_UNORM [float=3] {[u16; 3]},
R16G16B16Snorm => FORMAT_R16G16B16_SNORM [float=3] {[i16; 3]},
R16G16B16Uscaled => FORMAT_R16G16B16_USCALED [float=3] {[u16; 3]},
R16G16B16Sscaled => FORMAT_R16G16B16_SSCALED [float=3] {[i16; 3]},
R16G16B16Uint => FORMAT_R16G16B16_UINT [uint=3] {[u16; 3]},
R16G16B16Sint => FORMAT_R16G16B16_SINT [sint=3] {[i16; 3]},
R16G16B16Sfloat => FORMAT_R16G16B16_SFLOAT [float=3] {},
R16G16B16A16Unorm => FORMAT_R16G16B16A16_UNORM [float=4] {[u16; 4]},
R16G16B16A16Snorm => FORMAT_R16G16B16A16_SNORM [float=4] {[i16; 4]},
R16G16B16A16Uscaled => FORMAT_R16G16B16A16_USCALED [float=4] {[u16; 4]},
R16G16B16A16Sscaled => FORMAT_R16G16B16A16_SSCALED [float=4] {[i16; 4]},
R16G16B16A16Uint => FORMAT_R16G16B16A16_UINT [uint=4] {[u16; 4]},
R16G16B16A16Sint => FORMAT_R16G16B16A16_SINT [sint=4] {[i16; 4]},
R16G16B16A16Sfloat => FORMAT_R16G16B16A16_SFLOAT [float=4] {},
R32Uint => FORMAT_R32_UINT [uint=1] {u32},
R32Sint => FORMAT_R32_SINT [sint=1] {i32},
R32Sfloat => FORMAT_R32_SFLOAT [float=1] {f32},
R32G32Uint => FORMAT_R32G32_UINT [uint=2] {[u32; 2]},
R32G32Sint => FORMAT_R32G32_SINT [sint=2] {[i32; 2]},
R32G32Sfloat => FORMAT_R32G32_SFLOAT [float=2] {[f32; 2]},
R32G32B32Uint => FORMAT_R32G32B32_UINT [uint=3] {[u32; 3]},
R32G32B32Sint => FORMAT_R32G32B32_SINT [sint=3] {[i32; 3]},
R32G32B32Sfloat => FORMAT_R32G32B32_SFLOAT [float=3] {[f32; 3]},
R32G32B32A32Uint => FORMAT_R32G32B32A32_UINT [uint=4] {[u32; 4]},
R32G32B32A32Sint => FORMAT_R32G32B32A32_SINT [sint=4] {[i32; 4]},
R32G32B32A32Sfloat => FORMAT_R32G32B32A32_SFLOAT [float=4] {[f32; 4]},
R64Uint => FORMAT_R64_UINT [uint=1] {u64},
R64Sint => FORMAT_R64_SINT [sint=1] {i64},
R64Sfloat => FORMAT_R64_SFLOAT [float=1] {f64},
R64G64Uint => FORMAT_R64G64_UINT [uint=2] {[u64; 2]},
R64G64Sint => FORMAT_R64G64_SINT [sint=2] {[i64; 2]},
R64G64Sfloat => FORMAT_R64G64_SFLOAT [float=2] {[f64; 2]},
R64G64B64Uint => FORMAT_R64G64B64_UINT [uint=3] {[u64; 3]},
R64G64B64Sint => FORMAT_R64G64B64_SINT [sint=3] {[i64; 3]},
R64G64B64Sfloat => FORMAT_R64G64B64_SFLOAT [float=3] {[f64; 3]},
R64G64B64A64Uint => FORMAT_R64G64B64A64_UINT [uint=4] {[u64; 4]},
R64G64B64A64Sint => FORMAT_R64G64B64A64_SINT [sint=4] {[i64; 4]},
R64G64B64A64Sfloat => FORMAT_R64G64B64A64_SFLOAT [float=4] {[f64; 4]},
B10G11R11UfloatPack32 => FORMAT_B10G11R11_UFLOAT_PACK32 [float=3] {u32},
E5B9G9R9UfloatPack32 => FORMAT_E5B9G9R9_UFLOAT_PACK32 [float=3] {u32},
D16Unorm => FORMAT_D16_UNORM [depth] {},
X8_D24UnormPack32 => FORMAT_X8_D24_UNORM_PACK32 [depth] {},
D32Sfloat => FORMAT_D32_SFLOAT [depth] {},
S8Uint => FORMAT_S8_UINT [stencil] {},
D16Unorm_S8Uint => FORMAT_D16_UNORM_S8_UINT [depthstencil] {},
D24Unorm_S8Uint => FORMAT_D24_UNORM_S8_UINT [depthstencil] {},
D32Sfloat_S8Uint => FORMAT_D32_SFLOAT_S8_UINT [depthstencil] {},
BC1_RGBUnormBlock => FORMAT_BC1_RGB_UNORM_BLOCK [compressed=texture_compression_bc] {},
BC1_RGBSrgbBlock => FORMAT_BC1_RGB_SRGB_BLOCK [compressed=texture_compression_bc] {},
BC1_RGBAUnormBlock => FORMAT_BC1_RGBA_UNORM_BLOCK [compressed=texture_compression_bc] {},
BC1_RGBASrgbBlock => FORMAT_BC1_RGBA_SRGB_BLOCK [compressed=texture_compression_bc] {},
BC2UnormBlock => FORMAT_BC2_UNORM_BLOCK [compressed=texture_compression_bc] {},
BC2SrgbBlock => FORMAT_BC2_SRGB_BLOCK [compressed=texture_compression_bc] {},
BC3UnormBlock => FORMAT_BC3_UNORM_BLOCK [compressed=texture_compression_bc] {},
BC3SrgbBlock => FORMAT_BC3_SRGB_BLOCK [compressed=texture_compression_bc] {},
BC4UnormBlock => FORMAT_BC4_UNORM_BLOCK [compressed=texture_compression_bc] {},
BC4SnormBlock => FORMAT_BC4_SNORM_BLOCK [compressed=texture_compression_bc] {},
BC5UnormBlock => FORMAT_BC5_UNORM_BLOCK [compressed=texture_compression_bc] {},
BC5SnormBlock => FORMAT_BC5_SNORM_BLOCK [compressed=texture_compression_bc] {},
BC6HUfloatBlock => FORMAT_BC6H_UFLOAT_BLOCK [compressed=texture_compression_bc] {},
BC6HSfloatBlock => FORMAT_BC6H_SFLOAT_BLOCK [compressed=texture_compression_bc] {},
BC7UnormBlock => FORMAT_BC7_UNORM_BLOCK [compressed=texture_compression_bc] {},
BC7SrgbBlock => FORMAT_BC7_SRGB_BLOCK [compressed=texture_compression_bc] {},
ETC2_R8G8B8UnormBlock => FORMAT_ETC2_R8G8B8_UNORM_BLOCK [compressed=texture_compression_etc2] {},
ETC2_R8G8B8SrgbBlock => FORMAT_ETC2_R8G8B8_SRGB_BLOCK [compressed=texture_compression_etc2] {},
ETC2_R8G8B8A1UnormBlock => FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK [compressed=texture_compression_etc2] {},
ETC2_R8G8B8A1SrgbBlock => FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK [compressed=texture_compression_etc2] {},
ETC2_R8G8B8A8UnormBlock => FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK [compressed=texture_compression_etc2] {},
ETC2_R8G8B8A8SrgbBlock => FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK [compressed=texture_compression_etc2] {},
EAC_R11UnormBlock => FORMAT_EAC_R11_UNORM_BLOCK [compressed=texture_compression_etc2] {},
EAC_R11SnormBlock => FORMAT_EAC_R11_SNORM_BLOCK [compressed=texture_compression_etc2] {},
EAC_R11G11UnormBlock => FORMAT_EAC_R11G11_UNORM_BLOCK [compressed=texture_compression_etc2] {},
EAC_R11G11SnormBlock => FORMAT_EAC_R11G11_SNORM_BLOCK [compressed=texture_compression_etc2] {},
ASTC_4x4UnormBlock => FORMAT_ASTC_4x4_UNORM_BLOCK [compressed=texture_compression_astc_ldr] {},
ASTC_4x4SrgbBlock => FORMAT_ASTC_4x4_SRGB_BLOCK [compressed=texture_compression_astc_ldr] {},
ASTC_5x4UnormBlock => FORMAT_ASTC_5x4_UNORM_BLOCK [compressed=texture_compression_astc_ldr] {},
ASTC_5x4SrgbBlock => FORMAT_ASTC_5x4_SRGB_BLOCK [compressed=texture_compression_astc_ldr] {},
ASTC_5x5UnormBlock => FORMAT_ASTC_5x5_UNORM_BLOCK [compressed=texture_compression_astc_ldr] {},
ASTC_5x5SrgbBlock => FORMAT_ASTC_5x5_SRGB_BLOCK [compressed=texture_compression_astc_ldr] {},
ASTC_6x5UnormBlock => FORMAT_ASTC_6x5_UNORM_BLOCK [compressed=texture_compression_astc_ldr] {},
ASTC_6x5SrgbBlock => FORMAT_ASTC_6x5_SRGB_BLOCK [compressed=texture_compression_astc_ldr] {},
ASTC_6x6UnormBlock => FORMAT_ASTC_6x6_UNORM_BLOCK [compressed=texture_compression_astc_ldr] {},
ASTC_6x6SrgbBlock => FORMAT_ASTC_6x6_SRGB_BLOCK [compressed=texture_compression_astc_ldr] {},
ASTC_8x5UnormBlock => FORMAT_ASTC_8x5_UNORM_BLOCK [compressed=texture_compression_astc_ldr] {},
ASTC_8x5SrgbBlock => FORMAT_ASTC_8x5_SRGB_BLOCK [compressed=texture_compression_astc_ldr] {},
ASTC_8x6UnormBlock => FORMAT_ASTC_8x6_UNORM_BLOCK [compressed=texture_compression_astc_ldr] {},
ASTC_8x6SrgbBlock => FORMAT_ASTC_8x6_SRGB_BLOCK [compressed=texture_compression_astc_ldr] {},
ASTC_8x8UnormBlock => FORMAT_ASTC_8x8_UNORM_BLOCK [compressed=texture_compression_astc_ldr] {},
ASTC_8x8SrgbBlock => FORMAT_ASTC_8x8_SRGB_BLOCK [compressed=texture_compression_astc_ldr] {},
ASTC_10x5UnormBlock => FORMAT_ASTC_10x5_UNORM_BLOCK [compressed=texture_compression_astc_ldr] {},
ASTC_10x5SrgbBlock => FORMAT_ASTC_10x5_SRGB_BLOCK [compressed=texture_compression_astc_ldr] {},
ASTC_10x6UnormBlock => FORMAT_ASTC_10x6_UNORM_BLOCK [compressed=texture_compression_astc_ldr] {},
ASTC_10x6SrgbBlock => FORMAT_ASTC_10x6_SRGB_BLOCK [compressed=texture_compression_astc_ldr] {},
ASTC_10x8UnormBlock => FORMAT_ASTC_10x8_UNORM_BLOCK [compressed=texture_compression_astc_ldr] {},
ASTC_10x8SrgbBlock => FORMAT_ASTC_10x8_SRGB_BLOCK [compressed=texture_compression_astc_ldr] {},
ASTC_10x10UnormBlock => FORMAT_ASTC_10x10_UNORM_BLOCK [compressed=texture_compression_astc_ldr] {},
ASTC_10x10SrgbBlock => FORMAT_ASTC_10x10_SRGB_BLOCK [compressed=texture_compression_astc_ldr] {},
ASTC_12x10UnormBlock => FORMAT_ASTC_12x10_UNORM_BLOCK [compressed=texture_compression_astc_ldr] {},
ASTC_12x10SrgbBlock => FORMAT_ASTC_12x10_SRGB_BLOCK [compressed=texture_compression_astc_ldr] {},
ASTC_12x12UnormBlock => FORMAT_ASTC_12x12_UNORM_BLOCK [compressed=texture_compression_astc_ldr] {},
ASTC_12x12SrgbBlock => FORMAT_ASTC_12x12_SRGB_BLOCK [compressed=texture_compression_astc_ldr] {},
R4G4UnormPack8 => FORMAT_R4G4_UNORM_PACK8 [Some(1)] [float=2] {u8},
R4G4B4A4UnormPack16 => FORMAT_R4G4B4A4_UNORM_PACK16 [Some(2)] [float=4] {u16},
B4G4R4A4UnormPack16 => FORMAT_B4G4R4A4_UNORM_PACK16 [Some(2)] [float=4] {u16},
R5G6B5UnormPack16 => FORMAT_R5G6B5_UNORM_PACK16 [Some(2)] [float=3] {u16},
B5G6R5UnormPack16 => FORMAT_B5G6R5_UNORM_PACK16 [Some(2)] [float=3] {u16},
R5G5B5A1UnormPack16 => FORMAT_R5G5B5A1_UNORM_PACK16 [Some(2)] [float=4] {u16},
B5G5R5A1UnormPack16 => FORMAT_B5G5R5A1_UNORM_PACK16 [Some(2)] [float=4] {u16},
A1R5G5B5UnormPack16 => FORMAT_A1R5G5B5_UNORM_PACK16 [Some(2)] [float=4] {u16},
R8Unorm => FORMAT_R8_UNORM [Some(1)] [float=1] {u8},
R8Snorm => FORMAT_R8_SNORM [Some(1)] [float=1] {i8},
R8Uscaled => FORMAT_R8_USCALED [Some(1)] [float=1] {u8},
R8Sscaled => FORMAT_R8_SSCALED [Some(1)] [float=1] {i8},
R8Uint => FORMAT_R8_UINT [Some(1)] [uint=1] {u8},
R8Sint => FORMAT_R8_SINT [Some(1)] [sint=1] {i8},
R8Srgb => FORMAT_R8_SRGB [Some(1)] [float=1] {u8},
R8G8Unorm => FORMAT_R8G8_UNORM [Some(2)] [float=2] {[u8; 2]},
R8G8Snorm => FORMAT_R8G8_SNORM [Some(2)] [float=2] {[i8; 2]},
R8G8Uscaled => FORMAT_R8G8_USCALED [Some(2)] [float=2] {[u8; 2]},
R8G8Sscaled => FORMAT_R8G8_SSCALED [Some(2)] [float=2] {[i8; 2]},
R8G8Uint => FORMAT_R8G8_UINT [Some(2)] [uint=2] {[u8; 2]},
R8G8Sint => FORMAT_R8G8_SINT [Some(2)] [sint=2] {[i8; 2]},
R8G8Srgb => FORMAT_R8G8_SRGB [Some(2)] [float=2] {[u8; 2]},
R8G8B8Unorm => FORMAT_R8G8B8_UNORM [Some(3)] [float=3] {[u8; 3]},
R8G8B8Snorm => FORMAT_R8G8B8_SNORM [Some(3)] [float=3] {[i8; 3]},
R8G8B8Uscaled => FORMAT_R8G8B8_USCALED [Some(3)] [float=3] {[u8; 3]},
R8G8B8Sscaled => FORMAT_R8G8B8_SSCALED [Some(3)] [float=3] {[i8; 3]},
R8G8B8Uint => FORMAT_R8G8B8_UINT [Some(3)] [uint=3] {[u8; 3]},
R8G8B8Sint => FORMAT_R8G8B8_SINT [Some(3)] [sint=3] {[i8; 3]},
R8G8B8Srgb => FORMAT_R8G8B8_SRGB [Some(3)] [float=3] {[u8; 3]},
B8G8R8Unorm => FORMAT_B8G8R8_UNORM [Some(3)] [float=3] {[u8; 3]},
B8G8R8Snorm => FORMAT_B8G8R8_SNORM [Some(3)] [float=3] {[i8; 3]},
B8G8R8Uscaled => FORMAT_B8G8R8_USCALED [Some(3)] [float=3] {[u8; 3]},
B8G8R8Sscaled => FORMAT_B8G8R8_SSCALED [Some(3)] [float=3] {[i8; 3]},
B8G8R8Uint => FORMAT_B8G8R8_UINT [Some(3)] [uint=3] {[u8; 3]},
B8G8R8Sint => FORMAT_B8G8R8_SINT [Some(3)] [sint=3] {[i8; 3]},
B8G8R8Srgb => FORMAT_B8G8R8_SRGB [Some(3)] [float=3] {[u8; 3]},
R8G8B8A8Unorm => FORMAT_R8G8B8A8_UNORM [Some(4)] [float=4] {[u8; 4]},
R8G8B8A8Snorm => FORMAT_R8G8B8A8_SNORM [Some(4)] [float=4] {[i8; 4]},
R8G8B8A8Uscaled => FORMAT_R8G8B8A8_USCALED [Some(4)] [float=4] {[u8; 4]},
R8G8B8A8Sscaled => FORMAT_R8G8B8A8_SSCALED [Some(4)] [float=4] {[i8; 4]},
R8G8B8A8Uint => FORMAT_R8G8B8A8_UINT [Some(4)] [uint=4] {[u8; 4]},
R8G8B8A8Sint => FORMAT_R8G8B8A8_SINT [Some(4)] [sint=4] {[i8; 4]},
R8G8B8A8Srgb => FORMAT_R8G8B8A8_SRGB [Some(4)] [float=4] {[u8; 4]},
B8G8R8A8Unorm => FORMAT_B8G8R8A8_UNORM [Some(4)] [float=4] {[u8; 4]},
B8G8R8A8Snorm => FORMAT_B8G8R8A8_SNORM [Some(4)] [float=4] {[i8; 4]},
B8G8R8A8Uscaled => FORMAT_B8G8R8A8_USCALED [Some(4)] [float=4] {[u8; 4]},
B8G8R8A8Sscaled => FORMAT_B8G8R8A8_SSCALED [Some(4)] [float=4] {[i8; 4]},
B8G8R8A8Uint => FORMAT_B8G8R8A8_UINT [Some(4)] [uint=4] {[u8; 4]},
B8G8R8A8Sint => FORMAT_B8G8R8A8_SINT [Some(4)] [sint=4] {[i8; 4]},
B8G8R8A8Srgb => FORMAT_B8G8R8A8_SRGB [Some(4)] [float=4] {[u8; 4]},
A8B8G8R8UnormPack32 => FORMAT_A8B8G8R8_UNORM_PACK32 [Some(4)] [float=4] {[u8; 4]},
A8B8G8R8SnormPack32 => FORMAT_A8B8G8R8_SNORM_PACK32 [Some(4)] [float=4] {[i8; 4]},
A8B8G8R8UscaledPack32 => FORMAT_A8B8G8R8_USCALED_PACK32 [Some(4)] [float=4] {[u8; 4]},
A8B8G8R8SscaledPack32 => FORMAT_A8B8G8R8_SSCALED_PACK32 [Some(4)] [float=4] {[i8; 4]},
A8B8G8R8UintPack32 => FORMAT_A8B8G8R8_UINT_PACK32 [Some(4)] [uint=4] {[u8; 4]},
A8B8G8R8SintPack32 => FORMAT_A8B8G8R8_SINT_PACK32 [Some(4)] [sint=4] {[i8; 4]},
A8B8G8R8SrgbPack32 => FORMAT_A8B8G8R8_SRGB_PACK32 [Some(4)] [float=4] {[u8; 4]},
A2R10G10B10UnormPack32 => FORMAT_A2R10G10B10_UNORM_PACK32 [Some(4)] [float=4] {u32},
A2R10G10B10SnormPack32 => FORMAT_A2R10G10B10_SNORM_PACK32 [Some(4)] [float=4] {u32},
A2R10G10B10UscaledPack32 => FORMAT_A2R10G10B10_USCALED_PACK32 [Some(4)] [float=4] {u32},
A2R10G10B10SscaledPack32 => FORMAT_A2R10G10B10_SSCALED_PACK32 [Some(4)] [float=4] {u32},
A2R10G10B10UintPack32 => FORMAT_A2R10G10B10_UINT_PACK32 [Some(4)] [uint=4] {u32},
A2R10G10B10SintPack32 => FORMAT_A2R10G10B10_SINT_PACK32 [Some(4)] [sint=4] {u32},
A2B10G10R10UnormPack32 => FORMAT_A2B10G10R10_UNORM_PACK32 [Some(4)] [float=4] {u32},
A2B10G10R10SnormPack32 => FORMAT_A2B10G10R10_SNORM_PACK32 [Some(4)] [float=4] {u32},
A2B10G10R10UscaledPack32 => FORMAT_A2B10G10R10_USCALED_PACK32 [Some(4)] [float=4] {u32},
A2B10G10R10SscaledPack32 => FORMAT_A2B10G10R10_SSCALED_PACK32 [Some(4)] [float=4] {u32},
A2B10G10R10UintPack32 => FORMAT_A2B10G10R10_UINT_PACK32 [Some(4)] [uint=4] {u32},
A2B10G10R10SintPack32 => FORMAT_A2B10G10R10_SINT_PACK32 [Some(4)] [sint=4] {u32},
R16Unorm => FORMAT_R16_UNORM [Some(2)] [float=1] {u16},
R16Snorm => FORMAT_R16_SNORM [Some(2)] [float=1] {i16},
R16Uscaled => FORMAT_R16_USCALED [Some(2)] [float=1] {u16},
R16Sscaled => FORMAT_R16_SSCALED [Some(2)] [float=1] {i16},
R16Uint => FORMAT_R16_UINT [Some(2)] [uint=1] {u16},
R16Sint => FORMAT_R16_SINT [Some(2)] [sint=1] {i16},
R16Sfloat => FORMAT_R16_SFLOAT [Some(2)] [float=1] {},
R16G16Unorm => FORMAT_R16G16_UNORM [Some(4)] [float=2] {[u16; 2]},
R16G16Snorm => FORMAT_R16G16_SNORM [Some(4)] [float=2] {[i16; 2]},
R16G16Uscaled => FORMAT_R16G16_USCALED [Some(4)] [float=2] {[u16; 2]},
R16G16Sscaled => FORMAT_R16G16_SSCALED [Some(4)] [float=2] {[i16; 2]},
R16G16Uint => FORMAT_R16G16_UINT [Some(4)] [uint=2] {[u16; 2]},
R16G16Sint => FORMAT_R16G16_SINT [Some(4)] [sint=2] {[i16; 2]},
R16G16Sfloat => FORMAT_R16G16_SFLOAT [Some(4)] [float=2] {},
R16G16B16Unorm => FORMAT_R16G16B16_UNORM [Some(6)] [float=3] {[u16; 3]},
R16G16B16Snorm => FORMAT_R16G16B16_SNORM [Some(6)] [float=3] {[i16; 3]},
R16G16B16Uscaled => FORMAT_R16G16B16_USCALED [Some(6)] [float=3] {[u16; 3]},
R16G16B16Sscaled => FORMAT_R16G16B16_SSCALED [Some(6)] [float=3] {[i16; 3]},
R16G16B16Uint => FORMAT_R16G16B16_UINT [Some(6)] [uint=3] {[u16; 3]},
R16G16B16Sint => FORMAT_R16G16B16_SINT [Some(6)] [sint=3] {[i16; 3]},
R16G16B16Sfloat => FORMAT_R16G16B16_SFLOAT [Some(6)] [float=3] {},
R16G16B16A16Unorm => FORMAT_R16G16B16A16_UNORM [Some(8)] [float=4] {[u16; 4]},
R16G16B16A16Snorm => FORMAT_R16G16B16A16_SNORM [Some(8)] [float=4] {[i16; 4]},
R16G16B16A16Uscaled => FORMAT_R16G16B16A16_USCALED [Some(8)] [float=4] {[u16; 4]},
R16G16B16A16Sscaled => FORMAT_R16G16B16A16_SSCALED [Some(8)] [float=4] {[i16; 4]},
R16G16B16A16Uint => FORMAT_R16G16B16A16_UINT [Some(8)] [uint=4] {[u16; 4]},
R16G16B16A16Sint => FORMAT_R16G16B16A16_SINT [Some(8)] [sint=4] {[i16; 4]},
R16G16B16A16Sfloat => FORMAT_R16G16B16A16_SFLOAT [Some(8)] [float=4] {},
R32Uint => FORMAT_R32_UINT [Some(4)] [uint=1] {u32},
R32Sint => FORMAT_R32_SINT [Some(4)] [sint=1] {i32},
R32Sfloat => FORMAT_R32_SFLOAT [Some(4)] [float=1] {f32},
R32G32Uint => FORMAT_R32G32_UINT [Some(8)] [uint=2] {[u32; 2]},
R32G32Sint => FORMAT_R32G32_SINT [Some(8)] [sint=2] {[i32; 2]},
R32G32Sfloat => FORMAT_R32G32_SFLOAT [Some(8)] [float=2] {[f32; 2]},
R32G32B32Uint => FORMAT_R32G32B32_UINT [Some(12)] [uint=3] {[u32; 3]},
R32G32B32Sint => FORMAT_R32G32B32_SINT [Some(12)] [sint=3] {[i32; 3]},
R32G32B32Sfloat => FORMAT_R32G32B32_SFLOAT [Some(12)] [float=3] {[f32; 3]},
R32G32B32A32Uint => FORMAT_R32G32B32A32_UINT [Some(16)] [uint=4] {[u32; 4]},
R32G32B32A32Sint => FORMAT_R32G32B32A32_SINT [Some(16)] [sint=4] {[i32; 4]},
R32G32B32A32Sfloat => FORMAT_R32G32B32A32_SFLOAT [Some(16)] [float=4] {[f32; 4]},
R64Uint => FORMAT_R64_UINT [Some(8)] [uint=1] {u64},
R64Sint => FORMAT_R64_SINT [Some(8)] [sint=1] {i64},
R64Sfloat => FORMAT_R64_SFLOAT [Some(8)] [float=1] {f64},
R64G64Uint => FORMAT_R64G64_UINT [Some(16)] [uint=2] {[u64; 2]},
R64G64Sint => FORMAT_R64G64_SINT [Some(16)] [sint=2] {[i64; 2]},
R64G64Sfloat => FORMAT_R64G64_SFLOAT [Some(16)] [float=2] {[f64; 2]},
R64G64B64Uint => FORMAT_R64G64B64_UINT [Some(24)] [uint=3] {[u64; 3]},
R64G64B64Sint => FORMAT_R64G64B64_SINT [Some(24)] [sint=3] {[i64; 3]},
R64G64B64Sfloat => FORMAT_R64G64B64_SFLOAT [Some(24)] [float=3] {[f64; 3]},
R64G64B64A64Uint => FORMAT_R64G64B64A64_UINT [Some(32)] [uint=4] {[u64; 4]},
R64G64B64A64Sint => FORMAT_R64G64B64A64_SINT [Some(32)] [sint=4] {[i64; 4]},
R64G64B64A64Sfloat => FORMAT_R64G64B64A64_SFLOAT [Some(32)] [float=4] {[f64; 4]},
B10G11R11UfloatPack32 => FORMAT_B10G11R11_UFLOAT_PACK32 [Some(4)] [float=3] {u32},
E5B9G9R9UfloatPack32 => FORMAT_E5B9G9R9_UFLOAT_PACK32 [Some(4)] [float=3] {u32},
D16Unorm => FORMAT_D16_UNORM [Some(2)] [depth] {},
X8_D24UnormPack32 => FORMAT_X8_D24_UNORM_PACK32 [Some(4)] [depth] {},
D32Sfloat => FORMAT_D32_SFLOAT [Some(4)] [depth] {},
S8Uint => FORMAT_S8_UINT [Some(1)] [stencil] {},
D16Unorm_S8Uint => FORMAT_D16_UNORM_S8_UINT [None] [depthstencil] {},
D24Unorm_S8Uint => FORMAT_D24_UNORM_S8_UINT [None] [depthstencil] {},
D32Sfloat_S8Uint => FORMAT_D32_SFLOAT_S8_UINT [None] [depthstencil] {},
BC1_RGBUnormBlock => FORMAT_BC1_RGB_UNORM_BLOCK [None] [compressed=texture_compression_bc] {},
BC1_RGBSrgbBlock => FORMAT_BC1_RGB_SRGB_BLOCK [None] [compressed=texture_compression_bc] {},
BC1_RGBAUnormBlock => FORMAT_BC1_RGBA_UNORM_BLOCK [None] [compressed=texture_compression_bc] {},
BC1_RGBASrgbBlock => FORMAT_BC1_RGBA_SRGB_BLOCK [None] [compressed=texture_compression_bc] {},
BC2UnormBlock => FORMAT_BC2_UNORM_BLOCK [None] [compressed=texture_compression_bc] {},
BC2SrgbBlock => FORMAT_BC2_SRGB_BLOCK [None] [compressed=texture_compression_bc] {},
BC3UnormBlock => FORMAT_BC3_UNORM_BLOCK [None] [compressed=texture_compression_bc] {},
BC3SrgbBlock => FORMAT_BC3_SRGB_BLOCK [None] [compressed=texture_compression_bc] {},
BC4UnormBlock => FORMAT_BC4_UNORM_BLOCK [None] [compressed=texture_compression_bc] {},
BC4SnormBlock => FORMAT_BC4_SNORM_BLOCK [None] [compressed=texture_compression_bc] {},
BC5UnormBlock => FORMAT_BC5_UNORM_BLOCK [None] [compressed=texture_compression_bc] {},
BC5SnormBlock => FORMAT_BC5_SNORM_BLOCK [None] [compressed=texture_compression_bc] {},
BC6HUfloatBlock => FORMAT_BC6H_UFLOAT_BLOCK [None] [compressed=texture_compression_bc] {},
BC6HSfloatBlock => FORMAT_BC6H_SFLOAT_BLOCK [None] [compressed=texture_compression_bc] {},
BC7UnormBlock => FORMAT_BC7_UNORM_BLOCK [None] [compressed=texture_compression_bc] {},
BC7SrgbBlock => FORMAT_BC7_SRGB_BLOCK [None] [compressed=texture_compression_bc] {},
ETC2_R8G8B8UnormBlock => FORMAT_ETC2_R8G8B8_UNORM_BLOCK [None] [compressed=texture_compression_etc2] {},
ETC2_R8G8B8SrgbBlock => FORMAT_ETC2_R8G8B8_SRGB_BLOCK [None] [compressed=texture_compression_etc2] {},
ETC2_R8G8B8A1UnormBlock => FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK [None] [compressed=texture_compression_etc2] {},
ETC2_R8G8B8A1SrgbBlock => FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK [None] [compressed=texture_compression_etc2] {},
ETC2_R8G8B8A8UnormBlock => FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK [None] [compressed=texture_compression_etc2] {},
ETC2_R8G8B8A8SrgbBlock => FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK [None] [compressed=texture_compression_etc2] {},
EAC_R11UnormBlock => FORMAT_EAC_R11_UNORM_BLOCK [None] [compressed=texture_compression_etc2] {},
EAC_R11SnormBlock => FORMAT_EAC_R11_SNORM_BLOCK [None] [compressed=texture_compression_etc2] {},
EAC_R11G11UnormBlock => FORMAT_EAC_R11G11_UNORM_BLOCK [None] [compressed=texture_compression_etc2] {},
EAC_R11G11SnormBlock => FORMAT_EAC_R11G11_SNORM_BLOCK [None] [compressed=texture_compression_etc2] {},
ASTC_4x4UnormBlock => FORMAT_ASTC_4x4_UNORM_BLOCK [None] [compressed=texture_compression_astc_ldr] {},
ASTC_4x4SrgbBlock => FORMAT_ASTC_4x4_SRGB_BLOCK [None] [compressed=texture_compression_astc_ldr] {},
ASTC_5x4UnormBlock => FORMAT_ASTC_5x4_UNORM_BLOCK [None] [compressed=texture_compression_astc_ldr] {},
ASTC_5x4SrgbBlock => FORMAT_ASTC_5x4_SRGB_BLOCK [None] [compressed=texture_compression_astc_ldr] {},
ASTC_5x5UnormBlock => FORMAT_ASTC_5x5_UNORM_BLOCK [None] [compressed=texture_compression_astc_ldr] {},
ASTC_5x5SrgbBlock => FORMAT_ASTC_5x5_SRGB_BLOCK [None] [compressed=texture_compression_astc_ldr] {},
ASTC_6x5UnormBlock => FORMAT_ASTC_6x5_UNORM_BLOCK [None] [compressed=texture_compression_astc_ldr] {},
ASTC_6x5SrgbBlock => FORMAT_ASTC_6x5_SRGB_BLOCK [None] [compressed=texture_compression_astc_ldr] {},
ASTC_6x6UnormBlock => FORMAT_ASTC_6x6_UNORM_BLOCK [None] [compressed=texture_compression_astc_ldr] {},
ASTC_6x6SrgbBlock => FORMAT_ASTC_6x6_SRGB_BLOCK [None] [compressed=texture_compression_astc_ldr] {},
ASTC_8x5UnormBlock => FORMAT_ASTC_8x5_UNORM_BLOCK [None] [compressed=texture_compression_astc_ldr] {},
ASTC_8x5SrgbBlock => FORMAT_ASTC_8x5_SRGB_BLOCK [None] [compressed=texture_compression_astc_ldr] {},
ASTC_8x6UnormBlock => FORMAT_ASTC_8x6_UNORM_BLOCK [None] [compressed=texture_compression_astc_ldr] {},
ASTC_8x6SrgbBlock => FORMAT_ASTC_8x6_SRGB_BLOCK [None] [compressed=texture_compression_astc_ldr] {},
ASTC_8x8UnormBlock => FORMAT_ASTC_8x8_UNORM_BLOCK [None] [compressed=texture_compression_astc_ldr] {},
ASTC_8x8SrgbBlock => FORMAT_ASTC_8x8_SRGB_BLOCK [None] [compressed=texture_compression_astc_ldr] {},
ASTC_10x5UnormBlock => FORMAT_ASTC_10x5_UNORM_BLOCK [None] [compressed=texture_compression_astc_ldr] {},
ASTC_10x5SrgbBlock => FORMAT_ASTC_10x5_SRGB_BLOCK [None] [compressed=texture_compression_astc_ldr] {},
ASTC_10x6UnormBlock => FORMAT_ASTC_10x6_UNORM_BLOCK [None] [compressed=texture_compression_astc_ldr] {},
ASTC_10x6SrgbBlock => FORMAT_ASTC_10x6_SRGB_BLOCK [None] [compressed=texture_compression_astc_ldr] {},
ASTC_10x8UnormBlock => FORMAT_ASTC_10x8_UNORM_BLOCK [None] [compressed=texture_compression_astc_ldr] {},
ASTC_10x8SrgbBlock => FORMAT_ASTC_10x8_SRGB_BLOCK [None] [compressed=texture_compression_astc_ldr] {},
ASTC_10x10UnormBlock => FORMAT_ASTC_10x10_UNORM_BLOCK [None] [compressed=texture_compression_astc_ldr] {},
ASTC_10x10SrgbBlock => FORMAT_ASTC_10x10_SRGB_BLOCK [None] [compressed=texture_compression_astc_ldr] {},
ASTC_12x10UnormBlock => FORMAT_ASTC_12x10_UNORM_BLOCK [None] [compressed=texture_compression_astc_ldr] {},
ASTC_12x10SrgbBlock => FORMAT_ASTC_12x10_SRGB_BLOCK [None] [compressed=texture_compression_astc_ldr] {},
ASTC_12x12UnormBlock => FORMAT_ASTC_12x12_UNORM_BLOCK [None] [compressed=texture_compression_astc_ldr] {},
ASTC_12x12SrgbBlock => FORMAT_ASTC_12x12_SRGB_BLOCK [None] [compressed=texture_compression_astc_ldr] {},
}
pub unsafe trait FormatDesc {

View File

@ -90,7 +90,7 @@ pub struct GraphicsPipeline<VertexDefinition, Layout, RenderP> {
}
impl<Vdef, L, Rp> GraphicsPipeline<Vdef, L, Rp>
where Vdef: VertexDefinition, L: PipelineLayout, Rp: RenderPass + RenderPassDesc
where L: PipelineLayout, Rp: RenderPass + RenderPassDesc
{
/// Builds a new graphics pipeline object.
#[inline]
@ -99,7 +99,8 @@ impl<Vdef, L, Rp> GraphicsPipeline<Vdef, L, Rp>
params: GraphicsPipelineParams<'a, Vdef, Vsp, Vi, Vl, (), (), (), (), Fs, Fo, Fl,
L, Rp>)
-> Result<Arc<GraphicsPipeline<Vdef, L, Rp>>, GraphicsPipelineCreationError>
where L: PipelineLayout + PipelineLayoutSuperset<Vl> + PipelineLayoutSuperset<Fl>,
where Vdef: VertexDefinition<Vi>,
L: PipelineLayout + PipelineLayoutSuperset<Vl> + PipelineLayoutSuperset<Fl>,
Vl: PipelineLayoutDesc, Fl: PipelineLayoutDesc
{
GraphicsPipeline::new_inner::<_, _, _, (), (), (), (), _, _, _>(device, params)
@ -111,7 +112,8 @@ impl<Vdef, L, Rp> GraphicsPipeline<Vdef, L, Rp>
(device: &Arc<Device>,
params: GraphicsPipelineParams<'a, Vdef, Vsp, Vi, Vl, Gsp, Gi, Go, Gl, Fs, Fo, Fl, L, Rp>)
-> Result<Arc<GraphicsPipeline<Vdef, L, Rp>>, GraphicsPipelineCreationError>
where L: PipelineLayout + PipelineLayoutSuperset<Vl> + PipelineLayoutSuperset<Fl>,
where Vdef: VertexDefinition<Vi>,
L: PipelineLayout + PipelineLayoutSuperset<Vl> + PipelineLayoutSuperset<Fl>,
Vl: PipelineLayoutDesc, Fl: PipelineLayoutDesc
{
GraphicsPipeline::new_inner(device, params)
@ -121,7 +123,8 @@ impl<Vdef, L, Rp> GraphicsPipeline<Vdef, L, Rp>
(device: &Arc<Device>,
params: GraphicsPipelineParams<'a, Vdef, Vsp, Vi, Vl, Gsp, Gi, Go, Gl, Fs, Fo, Fl, L, Rp>)
-> Result<Arc<GraphicsPipeline<Vdef, L, Rp>>, GraphicsPipelineCreationError>
where L: PipelineLayout + PipelineLayoutSuperset<Vl> + PipelineLayoutSuperset<Fl>,
where Vdef: VertexDefinition<Vi>,
L: PipelineLayout + PipelineLayoutSuperset<Vl> + PipelineLayoutSuperset<Fl>,
Vl: PipelineLayoutDesc, Fl: PipelineLayoutDesc
{
let vk = device.pointers();
@ -177,12 +180,14 @@ impl<Vdef, L, Rp> GraphicsPipeline<Vdef, L, Rp>
};
// Vertex bindings.
let binding_descriptions = {
let (binding_descriptions, attribute_descriptions) = {
let (buffers_iter, attribs_iter) = params.vertex_input.definition(params.vertex_shader.input_definition());
let mut binding_descriptions = SmallVec::<[_; 8]>::new();
for (num, (stride, rate)) in params.vertex_input.buffers().enumerate() {
for (num, stride, rate) in buffers_iter {
if stride > device.physical_device().limits().max_vertex_input_binding_stride() as usize {
return Err(GraphicsPipelineCreationError::MaxVertexInputBindingStrideExceeded {
binding: num,
binding: num as usize,
max: device.physical_device().limits().max_vertex_input_binding_stride() as usize,
obtained: stride,
});
@ -195,7 +200,28 @@ impl<Vdef, L, Rp> GraphicsPipeline<Vdef, L, Rp>
});
}
binding_descriptions
let mut attribute_descriptions = SmallVec::<[_; 8]>::new();
for (loc, binding, info) in attribs_iter {
// TODO: check attribute format support
if info.offset > device.physical_device().limits().max_vertex_input_attribute_offset() as usize {
return Err(GraphicsPipelineCreationError::MaxVertexInputAttributeOffsetExceeded {
max: device.physical_device().limits().max_vertex_input_attribute_offset() as usize,
obtained: info.offset,
});
}
debug_assert!(binding_descriptions.iter().find(|b| b.binding == binding).is_some());
attribute_descriptions.push(vk::VertexInputAttributeDescription {
location: loc as u32,
binding: binding as u32,
format: info.format as u32,
offset: info.offset as u32,
});
}
(binding_descriptions, attribute_descriptions)
};
if binding_descriptions.len() > device.physical_device().limits()
@ -207,41 +233,6 @@ impl<Vdef, L, Rp> GraphicsPipeline<Vdef, L, Rp>
});
}
// Vertex attributes.
// TODO: check vertex attribute formats somewhere (match and support)?
let attribute_descriptions = {
let mut attribute_descriptions = SmallVec::<[_; 8]>::new();
for &(loc, ref name) in params.vertex_shader.attributes().iter() {
let (binding, info) = match params.vertex_input.attrib(name) {
Some(i) => i,
None => return Err(GraphicsPipelineCreationError::MissingVertexAttribute {
name: name.clone().into_owned()
})
};
// TODO: check attribute format support
if info.offset > device.physical_device().limits().max_vertex_input_attribute_offset() as usize {
return Err(GraphicsPipelineCreationError::MaxVertexInputAttributeOffsetExceeded {
max: device.physical_device().limits().max_vertex_input_attribute_offset() as usize,
obtained: info.offset,
});
}
debug_assert!(binding < params.vertex_input.buffers().len());
attribute_descriptions.push(vk::VertexInputAttributeDescription {
location: loc as u32,
binding: binding as u32,
format: info.format as u32,
offset: info.offset as u32,
});
}
attribute_descriptions
};
if attribute_descriptions.len() > device.physical_device().limits()
.max_vertex_input_attributes() as usize
{
@ -631,9 +622,7 @@ impl<Vdef, L, Rp> GraphicsPipeline<Vdef, L, Rp>
}
}
impl<Mv, L, Rp> GraphicsPipeline<Mv, L, Rp>
where Mv: VertexDefinition
{
impl<Mv, L, Rp> GraphicsPipeline<Mv, L, Rp> {
/// Returns the vertex definition used in the constructor.
#[inline]
pub fn vertex_definition(&self) -> &Mv {

View File

@ -10,10 +10,13 @@
use std::borrow::Cow;
use std::marker::PhantomData;
use std::mem;
use std::ops::Range;
use std::ptr;
use std::sync::Arc;
use std::ffi::CStr;
use std::vec::IntoIter as VecIntoIter;
use format::Format;
use pipeline::input_assembly::PrimitiveTopology;
use device::Device;
@ -70,14 +73,14 @@ impl ShaderModule {
}
pub unsafe fn vertex_shader_entry_point<'a, S, V, L>(&'a self, name: &'a CStr, layout: L,
attributes: Vec<(u32, Cow<'static, str>)>)
vertex_input: V)
-> VertexShaderEntryPoint<'a, S, V, L>
{
VertexShaderEntryPoint {
module: self,
name: name,
vertex_input: vertex_input,
layout: layout,
attributes: attributes,
marker: PhantomData,
}
}
@ -174,9 +177,9 @@ impl Drop for ShaderModule {
pub struct VertexShaderEntryPoint<'a, S, V, L> {
module: &'a ShaderModule,
name: &'a CStr,
attributes: Vec<(u32, Cow<'static, str>)>,
vertex_input: V,
layout: L,
marker: PhantomData<(S, V)>,
marker: PhantomData<S>,
}
impl<'a, S, V, L> VertexShaderEntryPoint<'a, S, V, L> {
@ -195,10 +198,9 @@ impl<'a, S, V, L> VertexShaderEntryPoint<'a, S, V, L> {
&self.layout
}
// TODO: change API
#[inline]
pub fn attributes(&self) -> &[(u32, Cow<'static, str>)] {
&self.attributes
pub fn input_definition(&self) -> &V {
&self.vertex_input
}
}
@ -363,13 +365,83 @@ impl<'a, S, L> ComputeShaderEntryPoint<'a, S, L> {
}
}
/// Structs that contain the definition of an interface between two shader stages, or between
/// the outside and a shader stage.
///
/// # Safety
///
/// - Must only provide one entry per location.
/// - The format must not be larger than 128 bits.
///
pub unsafe trait ShaderInterfaceDef {
/// Iterator returned by `elements`.
type Iter: ExactSizeIterator<Item = ShaderInterfaceDefEntry>;
/// Iterates over the elements of the interface.
fn elements(&self) -> Self::Iter;
}
pub unsafe trait PossibleMatchShaderInterface<I>: ShaderInterfaceDef where I: ShaderInterfaceDef {
// FIXME: temporary ; remove as it is unsafe
unsafe impl ShaderInterfaceDef for Vec<ShaderInterfaceDefEntry> {
type Iter = VecIntoIter<ShaderInterfaceDefEntry>;
#[inline]
fn elements(&self) -> Self::Iter {
self.clone().into_iter()
}
}
/// Entry of a shader interface definition.
#[derive(Debug, Clone)]
pub struct ShaderInterfaceDefEntry {
/// Range of locations covered by the element.
pub location: Range<u32>,
/// Format of a each location of the element.
pub format: Format,
/// Name of the element, or `None` if the name is unknown.
pub name: Option<Cow<'static, str>>,
}
/// Extension trait for `ShaderInterfaceDef` that specifies that the interface is potentially
/// compatible with another one.
pub unsafe trait ShaderInterfaceDefMatch<I>: ShaderInterfaceDef where I: ShaderInterfaceDef {
/// Returns true if the two definitions match.
// TODO: return a descriptive error instead
fn matches(&self, other: &I) -> bool;
}
// TODO: turn this into a default impl that can be specialized
unsafe impl<T, I> ShaderInterfaceDefMatch<I> for T
where T: ShaderInterfaceDef, I: ShaderInterfaceDef
{
fn matches(&self, other: &I) -> bool {
if self.elements().len() != other.elements().len() {
return false;
}
for a in self.elements() {
for loc in a.location.clone() {
let b = match other.elements().find(|e| loc >= e.location.start && loc < e.location.end) {
None => return false,
Some(b) => b,
};
if a.format != b.format {
return false;
}
// TODO: enforce this?
/*match (a.name, b.name) {
(Some(ref an), Some(ref bn)) => if an != bn { return false },
_ => ()
};*/
}
}
true
}
}
/// Trait to describe structs that contain specialization data for shaders.
///
/// It is implemented on `()` for shaders that don't have any specialization constant.

View File

@ -8,25 +8,30 @@
// according to those terms.
//! # Vertex sources definition
//!
//!
//! When you create a graphics pipeline object, you need to pass an object which indicates the
//! layout of the vertex buffer(s) that will serve as input for the vertex shader. This is done
//! by passing an implementation of the `Definition` trait.
//!
//!
//! In addition to this, the object that you pass when you create the graphics pipeline must also
//! implement the `Source` trait. This trait has a template parameter which corresponds to the
//! list of vertex buffers.
//!
//! The vulkano library provides some structs that already implement these traits.
//! The most common situation is a single vertex buffer and no instancing, in which case you can
//! pass a `SingleBufferDefinition` when you create the pipeline.
//!
//!
//! # Implementing `Vertex`
//!
//!
//! The implementations of the `Definition` trait that are provided by vulkano (like
//! `SingleBufferDefinition`) require you to use a buffer whose content is `[V]` where `V`
//! implements the `Vertex` trait.
//!
//!
//! The `Vertex` trait is unsafe, but can be implemented on a struct with the `impl_vertex!`
//! macro.
//!
//!
//! # Example
//!
//!
//! ```ignore // TODO:
//! # #[macro_use] extern crate vulkano
//! # fn main() {
@ -67,6 +72,7 @@ use std::vec::IntoIter as VecIntoIter;
use buffer::Buffer;
use buffer::TypedBuffer;
use format::Format;
use pipeline::shader::ShaderInterfaceDef;
use vk;
#[derive(Copy, Clone, Debug)]
@ -78,39 +84,74 @@ pub enum InputRate {
/// Describes an individual `Vertex`. In other words a collection of attributes that can be read
/// from a vertex shader.
///
/// At this stage, the vertex is in a "raw" format. For example a `[f32; 4]` can match both a
/// `vec4` or a `float[4]`. The way the things are binded depends on the shader.
pub unsafe trait Vertex: 'static + Send + Sync {
/// Returns the characteristics of a vertex attribute.
fn attrib(name: &str) -> Option<AttributeInfo>;
/// Returns the characteristics of a vertex member by its name.
fn member(name: &str) -> Option<VertexMemberInfo>;
}
/// Information about a member of a vertex struct.
pub struct VertexMemberInfo {
/// Offset of the member in bytes from the start of the struct.
pub offset: usize,
/// Type of data. This is used to check that the interface is matching.
pub ty: VertexMemberTy,
/// Number of consecutive elements of that type.
pub array_size: usize,
}
/// Type of a member of a vertex struct.
pub enum VertexMemberTy {
I8,
U8,
I16,
U16,
I32,
U32,
F32,
F64,
}
impl VertexMemberTy {
/// Returns true if a combination of `(type, array_size)` matches a format.
#[inline]
pub fn matches(&self, array_size: usize, format: Format) -> bool {
true // FIXME:
}
}
/// Information about a single attribute within a vertex.
/// TODO: change that API
pub struct AttributeInfo {
/// Number of bytes between the start of a vertex and the location of attribute.
pub offset: usize,
/// Data type of the attribute.
/// VertexMember type of the attribute.
pub format: Format,
}
/// Trait for types that contain a definition of the vertex input used by a graphics pipeline.
pub unsafe trait Definition: 'static + Send + Sync {
/// Iterator used to enumerate the list of buffers.
type InfoIter: ExactSizeIterator<Item = (usize, InputRate)>;
/// Trait for types that describe the definition of the vertex input used by a graphics pipeline.
pub unsafe trait Definition<I>: 'static + Send + Sync {
/// Iterator that returns the offset, the stride (in bytes) and input rate of each buffer.
type BuffersIter: ExactSizeIterator<Item = (u32, usize, InputRate)>;
/// Iterator that returns the attribute location, buffer id, and infos.
type AttribsIter: ExactSizeIterator<Item = (u32, u32, AttributeInfo)>;
/// Returns information about an attribute, and the index of the buffer (within the iterator
/// returned by `buffers`) in which the attribute is found.
fn attrib(&self, name: &str) -> Option<(usize, AttributeInfo)>;
/// Produces an iterator that returns the stride (in bytes) and input rate of each buffer.
fn buffers(&self) -> Self::InfoIter;
/// Builds the vertex definition to use to link this definition to a vertex shader's input
/// interface.
// TODO: return error if problem
fn definition(&self, interface: &I) -> (Self::BuffersIter, Self::AttribsIter);
}
/// Extension for `Definition` trait. The `L` parameter is an acceptable vertex source for this
/// Extension trait of `Definition`. The `L` parameter is an acceptable vertex source for this
/// vertex definition.
pub unsafe trait Source<L>: Definition {
pub unsafe trait Source<L>: 'static + Send + Sync {
/// Iterator used by `decode`.
type Iter: ExactSizeIterator<Item = Arc<Buffer>>;
/// Checks and returns the list of buffers, number of vertices and number of instances.
// TODO: return error if problem
fn decode(&self, L) -> (Self::Iter, usize, usize);
}
@ -122,17 +163,30 @@ impl<T> SingleBufferDefinition<T> {
pub fn new() -> SingleBufferDefinition<T> { SingleBufferDefinition(PhantomData) }
}
unsafe impl<T> Definition for SingleBufferDefinition<T> where T: Vertex {
type InfoIter = OptionIntoIter<(usize, InputRate)>;
unsafe impl<T, I> Definition<I> for SingleBufferDefinition<T>
where T: Vertex, I: ShaderInterfaceDef
{
type BuffersIter = OptionIntoIter<(u32, usize, InputRate)>;
type AttribsIter = VecIntoIter<(u32, u32, AttributeInfo)>;
#[inline]
fn attrib(&self, name: &str) -> Option<(usize, AttributeInfo)> {
<T as Vertex>::attrib(name).map(|info| (0, info))
}
fn definition(&self, interface: &I) -> (Self::BuffersIter, Self::AttribsIter) {
let attrib = {
let mut attribs = Vec::with_capacity(interface.elements().len());
for e in interface.elements() {
let infos = <T as Vertex>::member(e.name.as_ref().unwrap()).expect("missing vertex attrib");
assert!(infos.ty.matches(infos.array_size, e.format));
#[inline]
fn buffers(&self) -> Self::InfoIter {
Some((mem::size_of::<T>(), InputRate::Vertex)).into_iter()
let mut offset = infos.offset;
for loc in e.location.clone() {
attribs.push((loc, 0, AttributeInfo { offset: offset, format: e.format }));
offset += e.format.size().unwrap();
}
}
attribs
}.into_iter(); // TODO: meh
let buffers = Some((0, mem::size_of::<T>(), InputRate::Vertex)).into_iter();
(buffers, attrib)
}
}
@ -157,26 +211,40 @@ impl<T, U> TwoBuffersDefinition<T, U> {
pub fn new() -> TwoBuffersDefinition<T, U> { TwoBuffersDefinition(PhantomData) }
}
unsafe impl<T, U> Definition for TwoBuffersDefinition<T, U> where T: Vertex, U: Vertex {
type InfoIter = VecIntoIter<(usize, InputRate)>;
unsafe impl<T, U, I> Definition<I> for TwoBuffersDefinition<T, U>
where T: Vertex, U: Vertex, I: ShaderInterfaceDef
{
type BuffersIter = VecIntoIter<(u32, usize, InputRate)>;
type AttribsIter = VecIntoIter<(u32, u32, AttributeInfo)>;
#[inline]
fn attrib(&self, name: &str) -> Option<(usize, AttributeInfo)> {
if let Some(a) = <T as Vertex>::attrib(name) {
Some((0, a))
} else if let Some(a) = <U as Vertex>::attrib(name) {
Some((1, a))
} else {
None
}
}
fn definition(&self, interface: &I) -> (Self::BuffersIter, Self::AttribsIter) {
let attrib = {
let mut attribs = Vec::with_capacity(interface.elements().len());
for e in interface.elements() {
let (infos, buf_offset) = if let Some(infos) = <T as Vertex>::member(e.name.as_ref().unwrap()) {
(infos, 0)
} else if let Some(infos) = <U as Vertex>::member(e.name.as_ref().unwrap()) {
(infos, 1)
} else {
panic!("missing vertex attrib")
};
assert!(infos.ty.matches(infos.array_size, e.format));
#[inline]
fn buffers(&self) -> Self::InfoIter {
vec![
(mem::size_of::<T>(), InputRate::Vertex),
(mem::size_of::<U>(), InputRate::Vertex)
].into_iter()
let mut offset = infos.offset;
for loc in e.location.clone() {
attribs.push((loc, buf_offset, AttributeInfo { offset: offset, format: e.format }));
offset += e.format.size().unwrap();
}
}
attribs
}.into_iter(); // TODO: meh
let buffers = vec![
(0, mem::size_of::<T>(), InputRate::Vertex),
(1, mem::size_of::<U>(), InputRate::Vertex)
].into_iter();
(buffers, attrib)
}
}
@ -204,26 +272,40 @@ impl<T, U> OneVertexOneInstanceDefinition<T, U> {
pub fn new() -> OneVertexOneInstanceDefinition<T, U> { OneVertexOneInstanceDefinition(PhantomData) }
}
unsafe impl<T, U> Definition for OneVertexOneInstanceDefinition<T, U> where T: Vertex, U: Vertex {
type InfoIter = VecIntoIter<(usize, InputRate)>;
unsafe impl<T, U, I> Definition<I> for OneVertexOneInstanceDefinition<T, U>
where T: Vertex, U: Vertex, I: ShaderInterfaceDef
{
type BuffersIter = VecIntoIter<(u32, usize, InputRate)>;
type AttribsIter = VecIntoIter<(u32, u32, AttributeInfo)>;
#[inline]
fn attrib(&self, name: &str) -> Option<(usize, AttributeInfo)> {
if let Some(a) = <T as Vertex>::attrib(name) {
Some((0, a))
} else if let Some(a) = <U as Vertex>::attrib(name) {
Some((1, a))
} else {
None
}
}
fn definition(&self, interface: &I) -> (Self::BuffersIter, Self::AttribsIter) {
let attrib = {
let mut attribs = Vec::with_capacity(interface.elements().len());
for e in interface.elements() {
let (infos, buf_offset) = if let Some(infos) = <T as Vertex>::member(e.name.as_ref().unwrap()) {
(infos, 0)
} else if let Some(infos) = <U as Vertex>::member(e.name.as_ref().unwrap()) {
(infos, 1)
} else {
panic!("missing vertex attrib")
};
assert!(infos.ty.matches(infos.array_size, e.format));
#[inline]
fn buffers(&self) -> Self::InfoIter {
vec![
(mem::size_of::<T>(), InputRate::Vertex),
(mem::size_of::<U>(), InputRate::Instance)
].into_iter()
let mut offset = infos.offset;
for loc in e.location.clone() {
attribs.push((loc, buf_offset, AttributeInfo { offset: offset, format: e.format }));
offset += e.format.size().unwrap();
}
}
attribs
}.into_iter(); // TODO: meh
let buffers = vec![
(0, mem::size_of::<T>(), InputRate::Vertex),
(1, mem::size_of::<U>(), InputRate::Instance)
].into_iter();
(buffers, attrib)
}
}
@ -249,21 +331,30 @@ macro_rules! impl_vertex {
($out:ident $(, $member:ident)*) => (
unsafe impl $crate::pipeline::vertex::Vertex for $out {
#[inline(always)]
fn attrib(name: &str) -> Option<$crate::pipeline::vertex::AttributeInfo> {
fn member(name: &str) -> Option<$crate::pipeline::vertex::VertexMemberInfo> {
use $crate::format::Format;
use $crate::pipeline::vertex::VertexMemberInfo;
use $crate::pipeline::vertex::VertexMemberTy;
use $crate::pipeline::vertex::VertexMember;
$(
if name == stringify!($member) {
return Some($crate::pipeline::vertex::AttributeInfo {
let (ty, array_size) = unsafe {
#[inline] fn f<T: VertexMember>(_: &T) -> (VertexMemberTy, usize)
{ T::format() }
let dummy = 0usize as *const $out;
f(&(&*dummy).$member)
};
return Some(VertexMemberInfo {
offset: unsafe {
let dummy = 0usize as *const $out;
let member = (&(&*dummy).$member) as *const _;
member as usize
},
format: unsafe {
#[inline] fn f<T: $crate::pipeline::vertex::Data>(_: &T) -> $crate::format::Format { T::format() }
let dummy = 0usize as *const $out;
f(&(&*dummy).$member)
},
ty: ty,
array_size: array_size,
});
}
)*
@ -274,134 +365,97 @@ macro_rules! impl_vertex {
)
}
/// Trait for data types that can be used as vertex attributes. Used by the `impl_vertex!` macro.
pub unsafe trait Data {
/// Returns the format of the attribute.
fn format() -> Format;
/// Trait for data types that can be used as vertex members. Used by the `impl_vertex!` macro.
pub unsafe trait VertexMember {
/// Returns the format and array size of the member.
fn format() -> (VertexMemberTy, usize);
}
unsafe impl Data for f32 {
unsafe impl VertexMember for i8 {
#[inline]
fn format() -> Format {
Format::R32Sfloat
fn format() -> (VertexMemberTy, usize) {
(VertexMemberTy::I8, 1)
}
}
unsafe impl Data for [f32; 1] {
unsafe impl VertexMember for u8 {
#[inline]
fn format() -> Format {
Format::R32Sfloat
fn format() -> (VertexMemberTy, usize) {
(VertexMemberTy::U8, 1)
}
}
unsafe impl Data for [f32; 2] {
unsafe impl VertexMember for i16 {
#[inline]
fn format() -> Format {
Format::R32G32Sfloat
fn format() -> (VertexMemberTy, usize) {
(VertexMemberTy::I16, 1)
}
}
unsafe impl Data for [f32; 3] {
unsafe impl VertexMember for u16 {
#[inline]
fn format() -> Format {
Format::R32G32B32Sfloat
fn format() -> (VertexMemberTy, usize) {
(VertexMemberTy::U16, 1)
}
}
unsafe impl Data for [f32; 4] {
unsafe impl VertexMember for i32 {
#[inline]
fn format() -> Format {
Format::R32G32B32A32Sfloat
fn format() -> (VertexMemberTy, usize) {
(VertexMemberTy::I32, 1)
}
}
unsafe impl Data for (f32,) {
unsafe impl VertexMember for u32 {
#[inline]
fn format() -> Format {
Format::R32Sfloat
fn format() -> (VertexMemberTy, usize) {
(VertexMemberTy::U32, 1)
}
}
unsafe impl Data for (f32, f32) {
unsafe impl VertexMember for f32 {
#[inline]
fn format() -> Format {
Format::R32G32Sfloat
fn format() -> (VertexMemberTy, usize) {
(VertexMemberTy::F32, 1)
}
}
unsafe impl Data for (f32, f32, f32) {
unsafe impl VertexMember for f64 {
#[inline]
fn format() -> Format {
Format::R32G32B32Sfloat
fn format() -> (VertexMemberTy, usize) {
(VertexMemberTy::F64, 1)
}
}
unsafe impl Data for (f32, f32, f32, f32) {
#[inline]
fn format() -> Format {
Format::R32G32B32A32Sfloat
}
macro_rules! impl_vm_array {
($sz:expr) => (
unsafe impl<T> VertexMember for [T; $sz]
where T: VertexMember
{
#[inline]
fn format() -> (VertexMemberTy, usize) {
let (ty, sz) = <T as VertexMember>::format();
(ty, sz * $sz)
}
}
);
}
unsafe impl Data for u32 {
#[inline]
fn format() -> Format {
Format::R32Uint
}
}
unsafe impl Data for [u32; 1] {
#[inline]
fn format() -> Format {
Format::R32Uint
}
}
unsafe impl Data for [u32; 2] {
#[inline]
fn format() -> Format {
Format::R32G32Uint
}
}
unsafe impl Data for [u32; 3] {
#[inline]
fn format() -> Format {
Format::R32G32B32Uint
}
}
unsafe impl Data for [u32; 4] {
#[inline]
fn format() -> Format {
Format::R32G32B32A32Uint
}
}
unsafe impl Data for (u32,) {
#[inline]
fn format() -> Format {
Format::R32Uint
}
}
unsafe impl Data for (u32, u32) {
#[inline]
fn format() -> Format {
Format::R32G32Uint
}
}
unsafe impl Data for (u32, u32, u32) {
#[inline]
fn format() -> Format {
Format::R32G32B32Uint
}
}
unsafe impl Data for (u32, u32, u32, u32) {
#[inline]
fn format() -> Format {
Format::R32G32B32A32Uint
}
}
impl_vm_array!(1);
impl_vm_array!(2);
impl_vm_array!(3);
impl_vm_array!(4);
impl_vm_array!(5);
impl_vm_array!(6);
impl_vm_array!(7);
impl_vm_array!(8);
impl_vm_array!(9);
impl_vm_array!(10);
impl_vm_array!(11);
impl_vm_array!(12);
impl_vm_array!(13);
impl_vm_array!(14);
impl_vm_array!(15);
impl_vm_array!(16);
impl_vm_array!(32);
impl_vm_array!(64);