diff options
Diffstat (limited to 'src/command_buffer/validity/vertex_buffers.rs')
-rw-r--r-- | src/command_buffer/validity/vertex_buffers.rs | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/src/command_buffer/validity/vertex_buffers.rs b/src/command_buffer/validity/vertex_buffers.rs new file mode 100644 index 0000000..9031498 --- /dev/null +++ b/src/command_buffer/validity/vertex_buffers.rs @@ -0,0 +1,118 @@ +// 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 std::error; +use std::fmt; + +use crate::buffer::BufferAccess; +use crate::device::DeviceOwned; +use crate::pipeline::vertex::VertexSource; +use crate::pipeline::GraphicsPipelineAbstract; +use crate::VulkanObject; + +/// Checks whether vertex buffers can be bound. +/// +/// # Panic +/// +/// - Panics if one of the vertex buffers was not created with the same device as `pipeline`. +/// +pub fn check_vertex_buffers<GP, V>( + pipeline: &GP, + vertex_buffers: V, +) -> Result<CheckVertexBuffer, CheckVertexBufferError> +where + GP: GraphicsPipelineAbstract + DeviceOwned + VertexSource<V>, +{ + let (vertex_buffers, vertex_count, instance_count) = pipeline.decode(vertex_buffers); + + for (num, buf) in vertex_buffers.iter().enumerate() { + assert_eq!( + buf.inner().buffer.device().internal_object(), + pipeline.device().internal_object() + ); + + if !buf.inner().buffer.usage().vertex_buffer { + return Err(CheckVertexBufferError::BufferMissingUsage { num_buffer: num }); + } + } + + if let Some(multiview) = pipeline.subpass().render_pass().desc().multiview() { + let max_instance_index = pipeline + .device() + .physical_device() + .properties() + .max_multiview_instance_index + .unwrap_or(0) as usize; + + // vulkano currently always uses `0` as the first instance which means the highest + // used index will just be `instance_count - 1` + if instance_count > max_instance_index + 1 { + return Err(CheckVertexBufferError::TooManyInstances { + instance_count, + max_instance_count: max_instance_index + 1, + }); + } + } + + Ok(CheckVertexBuffer { + vertex_buffers, + vertex_count: vertex_count as u32, + instance_count: instance_count as u32, + }) +} + +/// Information returned if `check_vertex_buffer` succeeds. +pub struct CheckVertexBuffer { + /// The list of vertex buffers. + pub vertex_buffers: Vec<Box<dyn BufferAccess + Send + Sync>>, + /// Number of vertices available in the intersection of the buffers. + pub vertex_count: u32, + /// Number of instances available in the intersection of the buffers. + pub instance_count: u32, +} + +/// Error that can happen when checking whether the vertex buffers are valid. +#[derive(Debug, Copy, Clone)] +pub enum CheckVertexBufferError { + /// The "vertex buffer" usage must be enabled on the buffer. + BufferMissingUsage { + /// Index of the buffer that is missing usage. + num_buffer: usize, + }, + + /// The vertex buffer has too many instances. + /// When the `multiview` feature is used the maximum amount of instances may be reduced + /// because the implementation may use instancing internally to implement `multiview`. + TooManyInstances { + /// The used amount of instances. + instance_count: usize, + /// The allowed amount of instances. + max_instance_count: usize, + }, +} + +impl error::Error for CheckVertexBufferError {} + +impl fmt::Display for CheckVertexBufferError { + #[inline] + fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> { + write!( + fmt, + "{}", + match *self { + CheckVertexBufferError::BufferMissingUsage { .. } => { + "the vertex buffer usage is missing on a vertex buffer" + } + CheckVertexBufferError::TooManyInstances { .. } => { + "the vertex buffer has too many instances" + } + } + ) + } +} |