Add vertex and instance parameters to draw commands (#1661)

* Add vertex and instance parameters to draw commands

* Remove BufferlessDefinition
This commit is contained in:
Rua 2021-08-12 16:14:02 +02:00 committed by GitHub
parent a6dc452605
commit 3da6c298a8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 286 additions and 206 deletions

View File

@ -21,7 +21,7 @@
use std::sync::Arc;
use std::time::{SystemTime, UNIX_EPOCH};
use vulkano::buffer::CpuBufferPool;
use vulkano::buffer::{CpuBufferPool, TypedBufferAccess};
use vulkano::command_buffer::{
AutoCommandBufferBuilder, CommandBufferUsage, DynamicState, SubpassContents,
};
@ -291,7 +291,17 @@ fn main() {
)
.unwrap()
// Draw our buffer
.draw(pipeline.clone(), &dynamic_state, buffer, (), ())
.draw(
buffer.len() as u32,
1,
0,
0,
pipeline.clone(),
&dynamic_state,
buffer,
(),
(),
)
.unwrap()
.end_render_pass()
.unwrap();

View File

@ -24,6 +24,7 @@ use vulkano::pipeline::GraphicsPipelineAbstract;
use vulkano::render_pass::Subpass;
use std::sync::Arc;
use vulkano::buffer::TypedBufferAccess;
/// Allows applying an ambient lighting to a scene.
pub struct AmbientLightingSystem {
@ -153,6 +154,10 @@ impl AmbientLightingSystem {
.unwrap();
builder
.draw(
self.vertex_buffer.len() as u32,
1,
0,
0,
self.pipeline.clone(),
&dynamic_state,
vec![self.vertex_buffer.clone()],

View File

@ -25,6 +25,7 @@ use vulkano::pipeline::GraphicsPipelineAbstract;
use vulkano::render_pass::Subpass;
use std::sync::Arc;
use vulkano::buffer::TypedBufferAccess;
/// Allows applying a directional light source to a scene.
pub struct DirectionalLightingSystem {
@ -167,6 +168,10 @@ impl DirectionalLightingSystem {
.unwrap();
builder
.draw(
self.vertex_buffer.len() as u32,
1,
0,
0,
self.pipeline.clone(),
&dynamic_state,
vec![self.vertex_buffer.clone()],

View File

@ -26,6 +26,7 @@ use vulkano::pipeline::GraphicsPipelineAbstract;
use vulkano::render_pass::Subpass;
use std::sync::Arc;
use vulkano::buffer::TypedBufferAccess;
pub struct PointLightingSystem {
gfx_queue: Arc<Queue>,
@ -182,6 +183,10 @@ impl PointLightingSystem {
.unwrap();
builder
.draw(
self.vertex_buffer.len() as u32,
1,
0,
0,
self.pipeline.clone(),
&dynamic_state,
vec![self.vertex_buffer.clone()],

View File

@ -19,6 +19,7 @@ use vulkano::pipeline::GraphicsPipelineAbstract;
use vulkano::render_pass::Subpass;
use std::sync::Arc;
use vulkano::buffer::TypedBufferAccess;
pub struct TriangleDrawSystem {
gfx_queue: Arc<Queue>,
@ -89,6 +90,10 @@ impl TriangleDrawSystem {
.unwrap();
builder
.draw(
self.vertex_buffer.len() as u32,
1,
0,
0,
self.pipeline.clone(),
&DynamicState {
viewports: Some(vec![Viewport {

View File

@ -10,7 +10,7 @@
use png;
use std::io::Cursor;
use std::sync::Arc;
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess};
use vulkano::command_buffer::{
AutoCommandBufferBuilder, CommandBufferUsage, DynamicState, SubpassContents,
};
@ -292,6 +292,10 @@ fn main() {
)
.unwrap()
.draw(
vertex_buffer.len() as u32,
1,
0,
0,
pipeline.clone(),
&dynamic_state,
vertex_buffer.clone(),

View File

@ -19,7 +19,7 @@ extern crate vulkano_win;
extern crate winit;
use std::sync::Arc;
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess};
use vulkano::command_buffer::{
AutoCommandBufferBuilder, CommandBufferUsage, DynamicState, SubpassContents,
};
@ -334,6 +334,10 @@ fn main() {
)
.unwrap()
.draw(
triangle_vertex_buffer.len() as u32,
instance_data_buffer.len() as u32,
0,
0,
pipeline.clone(),
&dynamic_state,
// We pass both our lists of vertices here.

View File

@ -69,7 +69,7 @@ use std::fs::File;
use std::io::BufWriter;
use std::path::Path;
use std::sync::Arc;
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess};
use vulkano::command_buffer::{
AutoCommandBufferBuilder, CommandBufferUsage, DynamicState, PrimaryCommandBuffer,
SubpassContents,
@ -312,6 +312,10 @@ fn main() {
)
.unwrap()
.draw(
vertex_buffer.len() as u32,
1,
0,
0,
pipeline.clone(),
&dynamic_state,
vertex_buffer.clone(),

View File

@ -18,7 +18,7 @@
use std::collections::HashMap;
use std::sync::Arc;
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess};
use vulkano::command_buffer::{
AutoCommandBufferBuilder, CommandBufferUsage, DynamicState, SubpassContents,
};
@ -381,6 +381,10 @@ fn main() {
)
.unwrap()
.draw(
vertex_buffer.len() as u32,
1,
0,
0,
pipeline.clone(),
&dynamic_state,
vertex_buffer.clone(),

View File

@ -19,7 +19,7 @@ use std::iter;
use std::path::Path;
use std::sync::Arc;
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess};
use vulkano::command_buffer::{
AutoCommandBufferBuilder, CommandBufferUsage, DynamicState, SubpassContents,
};
@ -289,6 +289,10 @@ fn main() {
.begin_render_pass(framebuffer.clone(), SubpassContents::Inline, clear_values)
.unwrap()
.draw(
vertex_buffer.len() as u32,
1,
0,
0,
pipeline.clone(),
&dynamic_state,
vertex_buffer.clone(),

View File

@ -345,7 +345,17 @@ fn main() {
// the `occlusion_query_precise` feature to be enabled on the device.
.begin_query(query_pool.clone(), 0, QueryControlFlags { precise: false })
.unwrap()
.draw(pipeline.clone(), &dynamic_state, triangle1.clone(), (), ())
.draw(
triangle1.len() as u32,
1,
0,
0,
pipeline.clone(),
&dynamic_state,
triangle1.clone(),
(),
(),
)
.unwrap()
// End query 0.
.end_query(query_pool.clone(), 0)
@ -353,14 +363,34 @@ fn main() {
// Begin query 1 for the cyan triangle.
.begin_query(query_pool.clone(), 1, QueryControlFlags { precise: false })
.unwrap()
.draw(pipeline.clone(), &dynamic_state, triangle2.clone(), (), ())
.draw(
triangle2.len() as u32,
1,
0,
0,
pipeline.clone(),
&dynamic_state,
triangle2.clone(),
(),
(),
)
.unwrap()
.end_query(query_pool.clone(), 1)
.unwrap()
// Finally, query 2 for the green triangle.
.begin_query(query_pool.clone(), 2, QueryControlFlags { precise: false })
.unwrap()
.draw(pipeline.clone(), &dynamic_state, triangle3.clone(), (), ())
.draw(
triangle3.len() as u32,
1,
0,
0,
pipeline.clone(),
&dynamic_state,
triangle3.clone(),
(),
(),
)
.unwrap()
.end_query(query_pool.clone(), 2)
.unwrap()

View File

@ -25,7 +25,7 @@ use std::fs::File;
use std::io::Read;
use std::sync::Arc;
use vulkano::buffer::cpu_access::CpuAccessibleBuffer;
use vulkano::buffer::BufferUsage;
use vulkano::buffer::{BufferUsage, TypedBufferAccess};
use vulkano::command_buffer::{
AutoCommandBufferBuilder, CommandBufferUsage, DynamicState, SubpassContents,
};
@ -360,6 +360,10 @@ fn main() {
)
.unwrap()
.draw(
vertex_buffer.len() as u32,
1,
0,
0,
graphics_pipeline.clone(),
&dynamic_state,
vertex_buffer.clone(),

View File

@ -13,6 +13,7 @@ use std::iter;
use std::sync::Arc;
use std::time::Instant;
use vulkano::buffer::cpu_pool::CpuBufferPool;
use vulkano::buffer::TypedBufferAccess;
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
use vulkano::command_buffer::{
AutoCommandBufferBuilder, CommandBufferUsage, DynamicState, SubpassContents,
@ -263,6 +264,11 @@ fn main() {
)
.unwrap()
.draw_indexed(
index_buffer.len() as u32,
1,
0,
0,
0,
pipeline.clone(),
&DynamicState::none(),
vec![vertex_buffer.clone(), normals_buffer.clone()],

View File

@ -19,7 +19,7 @@
// * tessellation_shaders(..), patch_list(3) and polygon_mode_line() are called on the pipeline builder
use std::sync::Arc;
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess};
use vulkano::command_buffer::{
AutoCommandBufferBuilder, CommandBufferUsage, DynamicState, SubpassContents,
};
@ -367,6 +367,10 @@ fn main() {
)
.unwrap()
.draw(
vertex_buffer.len() as u32,
1,
0,
0,
pipeline.clone(),
&dynamic_state,
vertex_buffer.clone(),

View File

@ -17,7 +17,7 @@
// what a vertex or a shader is.
use std::sync::Arc;
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer};
use vulkano::buffer::{BufferUsage, CpuAccessibleBuffer, TypedBufferAccess};
use vulkano::command_buffer::{
AutoCommandBufferBuilder, CommandBufferUsage, DynamicState, SubpassContents,
};
@ -490,6 +490,10 @@ fn main() {
// The last two parameters contain the list of resources to pass to the shaders.
// Since we used an `EmptyPipeline` object, the objects have to be `()`.
.draw(
vertex_buffer.len() as u32,
1,
0,
0,
pipeline.clone(),
&dynamic_state,
vertex_buffer.clone(),

View File

@ -79,6 +79,7 @@ use crate::DeviceSize;
use crate::VulkanObject;
use crate::{OomError, SafeDeref};
use fnv::FnvHashMap;
use std::convert::TryInto;
use std::error;
use std::ffi::CStr;
use std::fmt;
@ -1155,6 +1156,10 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
#[inline]
pub fn draw<V, Gp, S, Pc>(
&mut self,
vertex_count: u32,
instance_count: u32,
first_vertex: u32,
first_instance: u32,
pipeline: Gp,
dynamic: &DynamicState,
vertex_buffers: V,
@ -1166,6 +1171,48 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
S: DescriptorSetsCollection,
{
let descriptor_sets = descriptor_sets.into_vec();
let vertex_buffers = pipeline.decode(vertex_buffers).0;
let (max_vertex_count, max_instance_count) =
pipeline.vertex_input().max_vertices_instances(
vertex_buffers
.iter()
.enumerate()
.map(|(i, v)| (i as u32, v as _)),
);
if first_vertex + vertex_count > max_vertex_count {
return Err(CheckVertexBufferError::TooManyVertices {
vertex_count,
max_vertex_count,
}
.into());
}
if first_instance + instance_count > max_instance_count {
return Err(CheckVertexBufferError::TooManyInstances {
instance_count,
max_instance_count,
}
.into());
}
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);
if first_instance + instance_count > max_instance_index + 1 {
return Err(CheckVertexBufferError::TooManyInstances {
instance_count,
max_instance_count: max_instance_index + 1, // TODO: this can overflow
}
.into());
}
}
unsafe {
// TODO: must check that pipeline is compatible with render pass
@ -1174,7 +1221,7 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
check_dynamic_state_validity(&pipeline, dynamic)?;
check_push_constants_validity(pipeline.layout(), &push_constants)?;
check_descriptor_sets_validity(pipeline.layout(), &descriptor_sets)?;
let vb_infos = check_vertex_buffers(&pipeline, vertex_buffers)?;
check_vertex_buffers(&pipeline, &vertex_buffers)?;
if let StateCacherOutcome::NeedChange =
self.state_cacher.bind_graphics_pipeline(&pipeline)
@ -1193,20 +1240,12 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
pipeline.layout(),
descriptor_sets,
)?;
bind_vertex_buffers(
&mut self.inner,
&mut self.state_cacher,
vb_infos.vertex_buffers,
)?;
bind_vertex_buffers(&mut self.inner, &mut self.state_cacher, vertex_buffers)?;
debug_assert!(self.queue_family().supports_graphics());
self.inner.draw(
vb_infos.vertex_count as u32,
vb_infos.instance_count as u32,
0,
0,
);
self.inner
.draw(vertex_count, instance_count, first_vertex, first_instance);
Ok(self)
}
}
@ -1245,6 +1284,7 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
+ 'static,
{
let descriptor_sets = descriptor_sets.into_vec();
let vertex_buffers = pipeline.decode(vertex_buffers).0;
unsafe {
// TODO: must check that pipeline is compatible with render pass
@ -1254,7 +1294,7 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
check_dynamic_state_validity(&pipeline, dynamic)?;
check_push_constants_validity(pipeline.layout(), &push_constants)?;
check_descriptor_sets_validity(pipeline.layout(), &descriptor_sets)?;
let vb_infos = check_vertex_buffers(&pipeline, vertex_buffers)?;
check_vertex_buffers(&pipeline, &vertex_buffers)?;
let requested = indirect_buffer.len() as u32;
let limit = self
@ -1290,11 +1330,7 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
pipeline.layout(),
descriptor_sets,
)?;
bind_vertex_buffers(
&mut self.inner,
&mut self.state_cacher,
vb_infos.vertex_buffers,
)?;
bind_vertex_buffers(&mut self.inner, &mut self.state_cacher, vertex_buffers)?;
debug_assert!(self.queue_family().supports_graphics());
@ -1318,6 +1354,11 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
#[inline]
pub fn draw_indexed<V, Gp, S, Pc, Ib, I>(
&mut self,
index_count: u32,
instance_count: u32,
first_index: u32,
vertex_offset: i32,
first_instance: u32,
pipeline: Gp,
dynamic: &DynamicState,
vertex_buffers: V,
@ -1332,16 +1373,78 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
I: Index + 'static,
{
let descriptor_sets = descriptor_sets.into_vec();
let vertex_buffers = pipeline.decode(vertex_buffers).0;
let (max_vertex_count, max_instance_count) =
pipeline.vertex_input().max_vertices_instances(
vertex_buffers
.iter()
.enumerate()
.map(|(i, v)| (i as u32, v as _)),
);
let max_index_count = index_buffer.len().try_into().unwrap_or(u32::MAX);
if first_index + index_count > max_index_count {
return Err(CheckVertexBufferError::TooManyIndices {
index_count,
max_index_count,
}
.into());
}
if first_instance + instance_count > max_instance_count {
return Err(CheckVertexBufferError::TooManyInstances {
instance_count,
max_instance_count,
}
.into());
}
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);
if first_instance + instance_count > max_instance_index + 1 {
return Err(CheckVertexBufferError::TooManyInstances {
instance_count,
max_instance_count: max_instance_index + 1, // TODO: this can overflow
}
.into());
}
}
unsafe {
// TODO: must check that pipeline is compatible with render pass
self.ensure_inside_render_pass_inline(&pipeline)?;
let ib_infos = check_index_buffer(self.device(), &index_buffer)?;
check_index_buffer(self.device(), &index_buffer)?;
check_dynamic_state_validity(&pipeline, dynamic)?;
check_push_constants_validity(pipeline.layout(), &push_constants)?;
check_descriptor_sets_validity(pipeline.layout(), &descriptor_sets)?;
let vb_infos = check_vertex_buffers(&pipeline, vertex_buffers)?;
check_vertex_buffers(&pipeline, &vertex_buffers)?;
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);
// 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,
}
.into());
}
}
if let StateCacherOutcome::NeedChange =
self.state_cacher.bind_graphics_pipeline(&pipeline)
@ -1366,21 +1469,17 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
pipeline.layout(),
descriptor_sets,
)?;
bind_vertex_buffers(
&mut self.inner,
&mut self.state_cacher,
vb_infos.vertex_buffers,
)?;
bind_vertex_buffers(&mut self.inner, &mut self.state_cacher, vertex_buffers)?;
// TODO: how to handle an index out of range of the vertex buffers?
debug_assert!(self.queue_family().supports_graphics());
self.inner.draw_indexed(
ib_infos.num_indices as u32,
vb_infos.instance_count as u32,
0,
0,
0,
index_count,
instance_count,
first_index,
vertex_offset,
first_instance,
);
Ok(self)
}
@ -1424,17 +1523,18 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
I: Index + 'static,
{
let descriptor_sets = descriptor_sets.into_vec();
let vertex_buffers = pipeline.decode(vertex_buffers).0;
unsafe {
// TODO: must check that pipeline is compatible with render pass
self.ensure_inside_render_pass_inline(&pipeline)?;
let ib_infos = check_index_buffer(self.device(), &index_buffer)?;
check_index_buffer(self.device(), &index_buffer)?;
check_indirect_buffer(self.device(), &indirect_buffer)?;
check_dynamic_state_validity(&pipeline, dynamic)?;
check_push_constants_validity(pipeline.layout(), &push_constants)?;
check_descriptor_sets_validity(pipeline.layout(), &descriptor_sets)?;
let vb_infos = check_vertex_buffers(&pipeline, vertex_buffers)?;
check_vertex_buffers(&pipeline, &vertex_buffers)?;
let requested = indirect_buffer.len() as u32;
let limit = self
@ -1476,11 +1576,7 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
pipeline.layout(),
descriptor_sets,
)?;
bind_vertex_buffers(
&mut self.inner,
&mut self.state_cacher,
vb_infos.vertex_buffers,
)?;
bind_vertex_buffers(&mut self.inner, &mut self.state_cacher, vertex_buffers)?;
debug_assert!(self.queue_family().supports_graphics());

View File

@ -23,10 +23,7 @@ use crate::VulkanObject;
///
/// - Panics if the buffer was not created with `device`.
///
pub fn check_index_buffer<B, I>(
device: &Device,
buffer: &B,
) -> Result<CheckIndexBuffer, CheckIndexBufferError>
pub fn check_index_buffer<B, I>(device: &Device, buffer: &B) -> Result<(), CheckIndexBufferError>
where
B: ?Sized + BufferAccess + TypedBufferAccess<Content = [I]>,
I: Index,
@ -45,15 +42,7 @@ where
// TODO: full_draw_index_uint32 feature
Ok(CheckIndexBuffer {
num_indices: buffer.len() as u32,
})
}
/// Information returned if `check_index_buffer` succeeds.
pub struct CheckIndexBuffer {
/// Number of indices in the index buffer.
pub num_indices: u32,
Ok(())
}
/// Error that can happen when checking whether binding an index buffer is valid.
@ -97,25 +86,6 @@ mod tests {
use crate::buffer::BufferUsage;
use crate::buffer::CpuAccessibleBuffer;
#[test]
fn num_indices() {
let (device, queue) = gfx_dev_and_queue!();
let buffer = CpuAccessibleBuffer::from_iter(
device.clone(),
BufferUsage::index_buffer(),
false,
0..500u32,
)
.unwrap();
match check_index_buffer(&device, &buffer) {
Ok(CheckIndexBuffer { num_indices }) => {
assert_eq!(num_indices, 500);
}
_ => panic!(),
}
}
#[test]
fn missing_usage() {
let (device, queue) = gfx_dev_and_queue!();

View File

@ -21,7 +21,7 @@ pub use self::descriptor_sets::{check_descriptor_sets_validity, CheckDescriptorS
pub use self::dispatch::{check_dispatch, CheckDispatchError};
pub use self::dynamic_state::{check_dynamic_state_validity, CheckDynamicStateValidityError};
pub use self::fill_buffer::{check_fill_buffer, CheckFillBufferError};
pub use self::index_buffer::{check_index_buffer, CheckIndexBuffer, CheckIndexBufferError};
pub use self::index_buffer::{check_index_buffer, CheckIndexBufferError};
pub use self::indirect_buffer::{check_indirect_buffer, CheckIndirectBufferError};
pub use self::push_constants::{check_push_constants_validity, CheckPushConstantsValidityError};
pub use self::query::{
@ -30,7 +30,7 @@ pub use self::query::{
CheckEndQueryError, CheckResetQueryPoolError, CheckWriteTimestampError,
};
pub use self::update_buffer::{check_update_buffer, CheckUpdateBufferError};
pub use self::vertex_buffers::{check_vertex_buffers, CheckVertexBuffer, CheckVertexBufferError};
pub use self::vertex_buffers::{check_vertex_buffers, CheckVertexBufferError};
mod blit_image;
mod clear_color_image;

View File

@ -7,14 +7,12 @@
// 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;
use std::error;
use std::fmt;
/// Checks whether vertex buffers can be bound.
///
@ -22,15 +20,13 @@ use crate::VulkanObject;
///
/// - Panics if one of the vertex buffers was not created with the same device as `pipeline`.
///
pub fn check_vertex_buffers<GP, V>(
pub fn check_vertex_buffers<GP>(
pipeline: &GP,
vertex_buffers: V,
) -> Result<CheckVertexBuffer, CheckVertexBufferError>
vertex_buffers: &[Box<dyn BufferAccess + Send + Sync>],
) -> Result<(), CheckVertexBufferError>
where
GP: GraphicsPipelineAbstract + DeviceOwned + VertexSource<V>,
GP: GraphicsPipelineAbstract,
{
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(),
@ -42,39 +38,7 @@ where
}
}
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,
Ok(())
}
/// Error that can happen when checking whether the vertex buffers are valid.
@ -86,14 +50,31 @@ pub enum CheckVertexBufferError {
num_buffer: usize,
},
/// The vertex buffer has too many instances.
/// A draw command requested too many vertices.
TooManyVertices {
/// The used amount of vertices.
vertex_count: u32,
/// The allowed amount of vertices.
max_vertex_count: u32,
},
/// A draw command requested 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,
instance_count: u32,
/// The allowed amount of instances.
max_instance_count: usize,
max_instance_count: u32,
},
/// A draw command requested too many indices.
TooManyIndices {
/// The used amount of indices.
index_count: u32,
/// The allowed amount of indices.
max_index_count: u32,
},
}
@ -109,8 +90,14 @@ impl fmt::Display for CheckVertexBufferError {
CheckVertexBufferError::BufferMissingUsage { .. } => {
"the vertex buffer usage is missing on a vertex buffer"
}
CheckVertexBufferError::TooManyVertices { .. } => {
"the draw command requested too many vertices"
}
CheckVertexBufferError::TooManyInstances { .. } => {
"the vertex buffer has too many instances"
"the draw command requested too many instances"
}
CheckVertexBufferError::TooManyIndices { .. } => {
"the draw command requested too many indices"
}
}
)

View File

@ -39,7 +39,6 @@ use crate::pipeline::shader::EntryPointAbstract;
use crate::pipeline::shader::GraphicsEntryPoint;
use crate::pipeline::shader::GraphicsShaderType;
use crate::pipeline::shader::SpecializationConstants;
use crate::pipeline::vertex::BufferlessDefinition;
use crate::pipeline::vertex::BuffersDefinition;
use crate::pipeline::vertex::Vertex;
use crate::pipeline::vertex::VertexDefinition;
@ -93,7 +92,7 @@ impl
'static,
'static,
'static,
BufferlessDefinition,
BuffersDefinition,
(),
(),
(),
@ -104,7 +103,7 @@ impl
/// Builds a new empty builder.
pub(super) fn new() -> Self {
GraphicsPipelineBuilder {
vertex_definition: BufferlessDefinition,
vertex_definition: BuffersDefinition::new(),
vertex_shader: None,
input_assembly: ash::vk::PipelineInputAssemblyStateCreateInfo {
topology: PrimitiveTopology::TriangleList.into(),

View File

@ -14,7 +14,7 @@ use crate::device::Device;
use crate::device::DeviceOwned;
use crate::pipeline::layout::PipelineLayout;
use crate::pipeline::shader::ShaderInterface;
use crate::pipeline::vertex::BufferlessDefinition;
use crate::pipeline::vertex::BuffersDefinition;
use crate::pipeline::vertex::IncompatibleVertexDefinitionError;
use crate::pipeline::vertex::VertexDefinition;
use crate::pipeline::vertex::VertexInput;
@ -75,7 +75,7 @@ impl GraphicsPipeline<()> {
'static,
'static,
'static,
BufferlessDefinition,
BuffersDefinition,
(),
(),
(),

View File

@ -1,67 +0,0 @@
// 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::buffer::BufferAccess;
use crate::pipeline::shader::ShaderInterface;
use crate::pipeline::vertex::IncompatibleVertexDefinitionError;
use crate::pipeline::vertex::VertexDefinition;
use crate::pipeline::vertex::VertexInput;
use crate::pipeline::vertex::VertexSource;
/// Implementation of `VertexDefinition` for drawing with no buffers at all.
///
/// This is only useful if your shaders come up with vertex data on their own, e.g. by inspecting
/// `gl_VertexIndex`
#[derive(Copy, Clone)]
pub struct BufferlessDefinition;
/// Value to be passed as the vertex source for bufferless draw commands.
///
/// Note that the concrete type of the graphics pipeline using `BufferlessDefinition` must be
/// visible to the command buffer builder for this to be usable.
#[derive(Copy, Clone)]
pub struct BufferlessVertices {
pub vertices: usize,
pub instances: usize,
}
unsafe impl VertexSource<BufferlessVertices> for BufferlessDefinition {
fn decode(
&self,
n: BufferlessVertices,
) -> (
Vec<Box<dyn BufferAccess + Sync + Send + 'static>>,
usize,
usize,
) {
(Vec::new(), n.vertices, n.instances)
}
}
unsafe impl<T> VertexSource<Vec<T>> for BufferlessDefinition {
fn decode<'l>(
&self,
_: Vec<T>,
) -> (
Vec<Box<dyn BufferAccess + Sync + Send + 'static>>,
usize,
usize,
) {
panic!("bufferless drawing should not be supplied with buffers")
}
}
unsafe impl VertexDefinition for BufferlessDefinition {
fn definition(
&self,
_: &ShaderInterface,
) -> Result<VertexInput, IncompatibleVertexDefinitionError> {
Ok(VertexInput::empty())
}
}

View File

@ -63,8 +63,6 @@
//! # }
//! ```
pub use self::bufferless::BufferlessDefinition;
pub use self::bufferless::BufferlessVertices;
pub use self::buffers::BuffersDefinition;
pub use self::definition::IncompatibleVertexDefinitionError;
pub use self::definition::VertexDefinition;
@ -79,7 +77,6 @@ use crate::DeviceSize;
use fnv::FnvHashMap;
use std::convert::TryInto;
mod bufferless;
mod buffers;
mod definition;
mod impl_vertex;