Skip to content

Commit

Permalink
Refactor Vertex trait to allow user-defined formats (#2106)
Browse files Browse the repository at this point in the history
* Refactor Vertex trait to not rely on ShaderInterfaceEntryType::to_format and instead rely on Format provided by VertexMember trait.

* Add test for impl_vertex macro, remove tuple implementations as they do not implement Pod, minor cleanups to impl_vertex macro.

* #[derive(Vertex)] proc-macro implementation with support for format and name attributes. Tests are implemented for both attributes and inferral matching impl_vertex macro

* Rename num_elements into num_locations to make purpose clear, add helper function to calculate num_components and check them properly in BufferDefinition's VertexDefinition implementation.

* Rename num_locations back to num_elements to make distinction to locations clear. Updated VertexDefinition implementation for BuffersDefinition to support double precision formats exceeding a single location.

* Add additional validation for vertex attributes with formats exceeding their location.

* Collect unnecessary, using iterator in loop to avoid unnecessary allocations.

* Use field type directly and avoid any form of unsafe blocks.

* Match shader scalar type directly in GraphicsPipelineBuilder

* Rename impl_vertex test to fit macro name

* Add VertexMember implementatinos for nalgebra and cgmath (incl matrices).

* Add missing copyright headers to new files in proc macro crate

* Document derive vertex with field-attribute options on the Vertex trait

* Add example for vertex derive approach.

* Do not publish internal macros crate as it is re-exported by vulkano itself

* Deprecate impl_vertex and VertexMember and update documentation for Vertex accordingly

* Make format field-level attribute mandatory for derive vertex

* Update all examples to derive Vertex trait instead of impl_vertex macro

* Fix doctests by adding missing imports and re-exporting crate self as vulkano to workaround limitations of distinguishing doctests in proc-macros
  • Loading branch information
trevex authored Dec 28, 2022
1 parent 40fc712 commit dcc1b58
Show file tree
Hide file tree
Showing 41 changed files with 1,136 additions and 1,078 deletions.
17 changes: 8 additions & 9 deletions examples/src/bin/buffer-allocator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,12 @@ use vulkano::{
QueueFlags,
},
image::{view::ImageView, ImageAccess, ImageUsage, SwapchainImage},
impl_vertex,
instance::{Instance, InstanceCreateInfo},
memory::allocator::StandardMemoryAllocator,
pipeline::{
graphics::{
input_assembly::InputAssemblyState,
vertex_input::BuffersDefinition,
vertex_input::{BuffersDefinition, Vertex},
viewport::{Viewport, ViewportState},
},
GraphicsPipeline,
Expand All @@ -54,13 +53,6 @@ use winit::{
window::{Window, WindowBuilder},
};

#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
struct Vertex {
position: [f32; 2],
}
impl_vertex!(Vertex, position);

fn main() {
let library = VulkanLibrary::new().unwrap();
let required_extensions = vulkano_win::required_extensions(&library);
Expand Down Expand Up @@ -164,6 +156,13 @@ fn main() {

let memory_allocator = Arc::new(StandardMemoryAllocator::new_default(device.clone()));

#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod, Vertex)]
struct Vertex {
#[format(R32G32_SFLOAT)]
position: [f32; 2],
}

// Using a buffer allocator allows multiple buffers to be "in-flight" simultaneously and is
// suited to highly dynamic data like vertex, index and uniform buffers.
let buffer_allocator = CpuBufferAllocator::new(
Expand Down
21 changes: 7 additions & 14 deletions examples/src/bin/deferred/frame/ambient_lighting_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
// notice may not be copied, modified, or distributed except
// according to those terms.

use bytemuck::{Pod, Zeroable};
use std::sync::Arc;
use vulkano::{
buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess},
Expand All @@ -20,7 +19,6 @@ use vulkano::{
},
device::Queue,
image::ImageViewAbstract,
impl_vertex,
memory::allocator::MemoryAllocator,
pipeline::{
graphics::{
Expand All @@ -34,10 +32,12 @@ use vulkano::{
render_pass::Subpass,
};

use super::LightingVertex;

/// Allows applying an ambient lighting to a scene.
pub struct AmbientLightingSystem {
gfx_queue: Arc<Queue>,
vertex_buffer: Arc<CpuAccessibleBuffer<[Vertex]>>,
vertex_buffer: Arc<CpuAccessibleBuffer<[LightingVertex]>>,
subpass: Subpass,
pipeline: Arc<GraphicsPipeline>,
command_buffer_allocator: Arc<StandardCommandBufferAllocator>,
Expand All @@ -56,13 +56,13 @@ impl AmbientLightingSystem {
// TODO: vulkano doesn't allow us to draw without a vertex buffer, otherwise we could
// hard-code these values in the shader
let vertices = [
Vertex {
LightingVertex {
position: [-1.0, -1.0],
},
Vertex {
LightingVertex {
position: [-1.0, 3.0],
},
Vertex {
LightingVertex {
position: [3.0, -1.0],
},
];
Expand All @@ -81,7 +81,7 @@ impl AmbientLightingSystem {
let fs = fs::load(gfx_queue.device().clone()).expect("failed to create shader module");

GraphicsPipeline::start()
.vertex_input_state(BuffersDefinition::new().vertex::<Vertex>())
.vertex_input_state(BuffersDefinition::new().vertex::<LightingVertex>())
.vertex_shader(vs.entry_point("main").unwrap(), ())
.input_assembly_state(InputAssemblyState::new())
.viewport_state(ViewportState::viewport_dynamic_scissor_irrelevant())
Expand Down Expand Up @@ -174,13 +174,6 @@ impl AmbientLightingSystem {
}
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
struct Vertex {
position: [f32; 2],
}
impl_vertex!(Vertex, position);

mod vs {
vulkano_shaders::shader! {
ty: "vertex",
Expand Down
21 changes: 7 additions & 14 deletions examples/src/bin/deferred/frame/directional_lighting_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
// notice may not be copied, modified, or distributed except
// according to those terms.

use bytemuck::{Pod, Zeroable};
use cgmath::Vector3;
use std::sync::Arc;
use vulkano::{
Expand All @@ -21,7 +20,6 @@ use vulkano::{
},
device::Queue,
image::ImageViewAbstract,
impl_vertex,
memory::allocator::MemoryAllocator,
pipeline::{
graphics::{
Expand All @@ -35,10 +33,12 @@ use vulkano::{
render_pass::Subpass,
};

use super::LightingVertex;

/// Allows applying a directional light source to a scene.
pub struct DirectionalLightingSystem {
gfx_queue: Arc<Queue>,
vertex_buffer: Arc<CpuAccessibleBuffer<[Vertex]>>,
vertex_buffer: Arc<CpuAccessibleBuffer<[LightingVertex]>>,
subpass: Subpass,
pipeline: Arc<GraphicsPipeline>,
command_buffer_allocator: Arc<StandardCommandBufferAllocator>,
Expand All @@ -57,13 +57,13 @@ impl DirectionalLightingSystem {
// TODO: vulkano doesn't allow us to draw without a vertex buffer, otherwise we could
// hard-code these values in the shader
let vertices = [
Vertex {
LightingVertex {
position: [-1.0, -1.0],
},
Vertex {
LightingVertex {
position: [-1.0, 3.0],
},
Vertex {
LightingVertex {
position: [3.0, -1.0],
},
];
Expand All @@ -82,7 +82,7 @@ impl DirectionalLightingSystem {
let fs = fs::load(gfx_queue.device().clone()).expect("failed to create shader module");

GraphicsPipeline::start()
.vertex_input_state(BuffersDefinition::new().vertex::<Vertex>())
.vertex_input_state(BuffersDefinition::new().vertex::<LightingVertex>())
.vertex_shader(vs.entry_point("main").unwrap(), ())
.input_assembly_state(InputAssemblyState::new())
.viewport_state(ViewportState::viewport_dynamic_scissor_irrelevant())
Expand Down Expand Up @@ -188,13 +188,6 @@ impl DirectionalLightingSystem {
}
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
struct Vertex {
position: [f32; 2],
}
impl_vertex!(Vertex, position);

mod vs {
vulkano_shaders::shader! {
ty: "vertex",
Expand Down
10 changes: 10 additions & 0 deletions examples/src/bin/deferred/frame/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,19 @@
// The main code is in the `system` module, while the other modules implement the different kinds
// of lighting sources.

use bytemuck::{Pod, Zeroable};
use vulkano::pipeline::graphics::vertex_input::Vertex;

pub use self::system::{DrawPass, Frame, FrameSystem, LightingPass, Pass};

mod ambient_lighting_system;
mod directional_lighting_system;
mod point_lighting_system;
mod system;

#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod, Vertex)]
struct LightingVertex {
#[format(R32G32_SFLOAT)]
position: [f32; 2],
}
21 changes: 7 additions & 14 deletions examples/src/bin/deferred/frame/point_lighting_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
// notice may not be copied, modified, or distributed except
// according to those terms.

use bytemuck::{Pod, Zeroable};
use cgmath::{Matrix4, Vector3};
use std::sync::Arc;
use vulkano::{
Expand All @@ -21,7 +20,6 @@ use vulkano::{
},
device::Queue,
image::ImageViewAbstract,
impl_vertex,
memory::allocator::MemoryAllocator,
pipeline::{
graphics::{
Expand All @@ -35,9 +33,11 @@ use vulkano::{
render_pass::Subpass,
};

use super::LightingVertex;

pub struct PointLightingSystem {
gfx_queue: Arc<Queue>,
vertex_buffer: Arc<CpuAccessibleBuffer<[Vertex]>>,
vertex_buffer: Arc<CpuAccessibleBuffer<[LightingVertex]>>,
subpass: Subpass,
pipeline: Arc<GraphicsPipeline>,
command_buffer_allocator: Arc<StandardCommandBufferAllocator>,
Expand All @@ -56,13 +56,13 @@ impl PointLightingSystem {
// TODO: vulkano doesn't allow us to draw without a vertex buffer, otherwise we could
// hard-code these values in the shader
let vertices = [
Vertex {
LightingVertex {
position: [-1.0, -1.0],
},
Vertex {
LightingVertex {
position: [-1.0, 3.0],
},
Vertex {
LightingVertex {
position: [3.0, -1.0],
},
];
Expand All @@ -81,7 +81,7 @@ impl PointLightingSystem {
let fs = fs::load(gfx_queue.device().clone()).expect("failed to create shader module");

GraphicsPipeline::start()
.vertex_input_state(BuffersDefinition::new().vertex::<Vertex>())
.vertex_input_state(BuffersDefinition::new().vertex::<LightingVertex>())
.vertex_shader(vs.entry_point("main").unwrap(), ())
.input_assembly_state(InputAssemblyState::new())
.viewport_state(ViewportState::viewport_dynamic_scissor_irrelevant())
Expand Down Expand Up @@ -201,13 +201,6 @@ impl PointLightingSystem {
}
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
struct Vertex {
position: [f32; 2],
}
impl_vertex!(Vertex, position);

mod vs {
vulkano_shaders::shader! {
ty: "vertex",
Expand Down
19 changes: 9 additions & 10 deletions examples/src/bin/deferred/triangle_draw_system.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,12 @@ use vulkano::{
CommandBufferInheritanceInfo, CommandBufferUsage, SecondaryAutoCommandBuffer,
},
device::Queue,
impl_vertex,
memory::allocator::StandardMemoryAllocator,
pipeline::{
graphics::{
depth_stencil::DepthStencilState,
input_assembly::InputAssemblyState,
vertex_input::BuffersDefinition,
vertex_input::{BuffersDefinition, Vertex},
viewport::{Viewport, ViewportState},
},
GraphicsPipeline,
Expand All @@ -32,7 +31,7 @@ use vulkano::{

pub struct TriangleDrawSystem {
gfx_queue: Arc<Queue>,
vertex_buffer: Arc<CpuAccessibleBuffer<[Vertex]>>,
vertex_buffer: Arc<CpuAccessibleBuffer<[TriangleVertex]>>,
subpass: Subpass,
pipeline: Arc<GraphicsPipeline>,
command_buffer_allocator: Arc<StandardCommandBufferAllocator>,
Expand All @@ -47,13 +46,13 @@ impl TriangleDrawSystem {
command_buffer_allocator: Arc<StandardCommandBufferAllocator>,
) -> TriangleDrawSystem {
let vertices = [
Vertex {
TriangleVertex {
position: [-0.5, -0.25],
},
Vertex {
TriangleVertex {
position: [0.0, 0.5],
},
Vertex {
TriangleVertex {
position: [0.25, -0.1],
},
];
Expand All @@ -72,7 +71,7 @@ impl TriangleDrawSystem {
let fs = fs::load(gfx_queue.device().clone()).expect("failed to create shader module");

GraphicsPipeline::start()
.vertex_input_state(BuffersDefinition::new().vertex::<Vertex>())
.vertex_input_state(BuffersDefinition::new().vertex::<TriangleVertex>())
.vertex_shader(vs.entry_point("main").unwrap(), ())
.input_assembly_state(InputAssemblyState::new())
.viewport_state(ViewportState::viewport_dynamic_scissor_irrelevant())
Expand Down Expand Up @@ -122,11 +121,11 @@ impl TriangleDrawSystem {
}

#[repr(C)]
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod)]
struct Vertex {
#[derive(Clone, Copy, Debug, Default, Zeroable, Pod, Vertex)]
struct TriangleVertex {
#[format(R32G32_SFLOAT)]
position: [f32; 2],
}
impl_vertex!(Vertex, position);

mod vs {
vulkano_shaders::shader! {
Expand Down
Loading

0 comments on commit dcc1b58

Please sign in to comment.