diff options
Diffstat (limited to 'src/pipeline/graphics/vertex_input/impl_vertex.rs')
-rw-r--r-- | src/pipeline/graphics/vertex_input/impl_vertex.rs | 200 |
1 files changed, 200 insertions, 0 deletions
diff --git a/src/pipeline/graphics/vertex_input/impl_vertex.rs b/src/pipeline/graphics/vertex_input/impl_vertex.rs new file mode 100644 index 0000000..f8e5246 --- /dev/null +++ b/src/pipeline/graphics/vertex_input/impl_vertex.rs @@ -0,0 +1,200 @@ +// Copyright (c) 2017 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 crate::format::Format; + +/// Implements the `Vertex` trait on a struct. +/// +/// # Examples +/// +/// ``` +/// # use vulkano::buffer::BufferContents; +/// #[derive(BufferContents, Default)] +/// #[repr(C)] +/// struct Vertex { +/// position: [f32; 3], +/// color: [f32; 4], +/// } +/// +/// vulkano::impl_vertex!(Vertex, position, color); +/// ``` +#[deprecated( + since = "0.33.0", + note = "derive `Vertex` instead and use field-level attributes to specify format" +)] +#[macro_export] +macro_rules! impl_vertex { + ($out:ty $(, $member:ident)*) => ( + #[allow(unsafe_code)] + unsafe impl $crate::pipeline::graphics::vertex_input::Vertex for $out { + #[inline(always)] + #[allow(deprecated)] + fn per_vertex() -> $crate::pipeline::graphics::vertex_input::VertexBufferDescription { + #[allow(unused_imports)] + use std::collections::HashMap; + use $crate::format::Format; + use $crate::pipeline::graphics::vertex_input::VertexMember; + use $crate::pipeline::graphics::vertex_input::{VertexInputRate, VertexMemberInfo}; + + let mut members = HashMap::default(); + $( + { + let dummy = <$out>::default(); + #[inline] fn f<T: VertexMember>(_: &T) -> Format { T::format() } + let format = f(&dummy.$member); + let field_size = { + let p = unsafe { + core::ptr::addr_of!((*(&dummy as *const _ as *const $out)).$member) + }; + const fn size_of_raw<T>(_: *const T) -> usize { + core::mem::size_of::<T>() + } + size_of_raw(p) + } as u32; + let format_size = format.block_size().expect("no block size for format") as u32; + let num_elements = field_size / format_size; + let remainder = field_size % format_size; + assert!(remainder == 0, "struct field `{}` size does not fit multiple of format size", stringify!($member)); + + let dummy_ptr = (&dummy) as *const _; + let member_ptr = (&dummy.$member) as *const _; + + members.insert(stringify!($member).to_string(), VertexMemberInfo { + offset: member_ptr as usize - dummy_ptr as usize, + format, + num_elements, + }); + } + )* + + $crate::pipeline::graphics::vertex_input::VertexBufferDescription { + members, + stride: std::mem::size_of::<$out>() as u32, + input_rate: VertexInputRate::Vertex, + } + } + #[inline(always)] + #[allow(deprecated)] + fn per_instance() -> $crate::pipeline::graphics::vertex_input::VertexBufferDescription { + <$out as $crate::pipeline::graphics::vertex_input::Vertex>::per_vertex().per_instance() + } + #[inline(always)] + #[allow(deprecated)] + fn per_instance_with_divisor(divisor: u32) -> $crate::pipeline::graphics::vertex_input::VertexBufferDescription { + <$out as $crate::pipeline::graphics::vertex_input::Vertex>::per_vertex().per_instance_with_divisor(divisor) + } + + } + ) +} + +/// Trait for data types that can be used as vertex members. Used by the `impl_vertex!` macro. +#[deprecated( + since = "0.33.0", + note = "Derive `Vertex` instead and use field-level attributes to specify format" +)] +pub unsafe trait VertexMember { + /// Returns the format and array size of the member. + fn format() -> Format; +} + +#[macro_export] +macro_rules! impl_vertex_member { + ($out:ty, $format:ident) => { + #[allow(deprecated)] + unsafe impl VertexMember for $out { + #[inline] + fn format() -> Format { + Format::$format + } + } + }; +} + +impl_vertex_member!(i8, R8_SINT); +impl_vertex_member!(u8, R8_UINT); +impl_vertex_member!(i16, R16_SINT); +impl_vertex_member!(u16, R16_UINT); +impl_vertex_member!(i32, R32_SINT); +impl_vertex_member!(u32, R32_UINT); +impl_vertex_member!(f32, R32_SFLOAT); +impl_vertex_member!(f64, R64_SFLOAT); +impl_vertex_member!([i8; 2], R8G8_SINT); +impl_vertex_member!([u8; 2], R8G8_UINT); +impl_vertex_member!([i16; 2], R16G16_SINT); +impl_vertex_member!([u16; 2], R16G16_UINT); +impl_vertex_member!([i32; 2], R32G32_SINT); +impl_vertex_member!([u32; 2], R32G32_UINT); +impl_vertex_member!([f32; 2], R32G32_SFLOAT); +impl_vertex_member!([f64; 2], R64G64_SFLOAT); +impl_vertex_member!([i8; 3], R8G8B8_SINT); +impl_vertex_member!([u8; 3], R8G8B8_UINT); +impl_vertex_member!([i16; 3], R16G16B16_SINT); +impl_vertex_member!([u16; 3], R16G16B16_UINT); +impl_vertex_member!([i32; 3], R32G32B32_SINT); +impl_vertex_member!([u32; 3], R32G32B32_UINT); +impl_vertex_member!([f32; 3], R32G32B32_SFLOAT); +impl_vertex_member!([f64; 3], R64G64B64_SFLOAT); +impl_vertex_member!([i8; 4], R8G8B8A8_SINT); +impl_vertex_member!([u8; 4], R8G8B8A8_UINT); +impl_vertex_member!([i16; 4], R16G16B16A16_SINT); +impl_vertex_member!([u16; 4], R16G16B16A16_UINT); +impl_vertex_member!([i32; 4], R32G32B32A32_SINT); +impl_vertex_member!([u32; 4], R32G32B32A32_UINT); +impl_vertex_member!([f32; 4], R32G32B32A32_SFLOAT); +impl_vertex_member!([f64; 4], R64G64B64A64_SFLOAT); +impl_vertex_member!([f32; 9], R32G32B32_SFLOAT); +impl_vertex_member!([f32; 16], R32G32B32A32_SFLOAT); + +#[allow(deprecated)] +unsafe impl<T> VertexMember for [T; 1] +where + T: VertexMember, +{ + fn format() -> Format { + <T as VertexMember>::format() + } +} + +#[cfg(test)] +mod tests { + use crate::format::Format; + #[allow(deprecated)] + use crate::pipeline::graphics::vertex_input::Vertex; + + use bytemuck::{Pod, Zeroable}; + + #[test] + #[allow(deprecated)] + fn impl_vertex() { + #[repr(C)] + #[derive(Clone, Copy, Debug, Default, Zeroable, Pod)] + struct TestVertex { + matrix: [f32; 16], + vector: [f32; 4], + scalar: u16, + _padding: u16, + } + impl_vertex!(TestVertex, scalar, vector, matrix); + + let info = TestVertex::per_vertex(); + let matrix = info.members.get("matrix").unwrap(); + let vector = info.members.get("vector").unwrap(); + let scalar = info.members.get("scalar").unwrap(); + assert_eq!(matrix.format, Format::R32G32B32A32_SFLOAT); + assert_eq!(matrix.offset, 0); + assert_eq!(matrix.num_elements, 4); + assert_eq!(vector.format, Format::R32G32B32A32_SFLOAT); + assert_eq!(vector.offset, 16 * 4); + assert_eq!(vector.num_elements, 1); + assert_eq!(scalar.format, Format::R16_UINT); + assert_eq!(scalar.offset, 16 * 5); + assert_eq!(scalar.num_elements, 1); + } +} |