mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-25 16:25:31 +00:00
Add vertex and instance parameters to draw commands (#1661)
* Add vertex and instance parameters to draw commands * Remove BufferlessDefinition
This commit is contained in:
parent
a6dc452605
commit
3da6c298a8
@ -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();
|
||||
|
@ -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()],
|
||||
|
@ -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()],
|
||||
|
@ -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()],
|
||||
|
@ -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 {
|
||||
|
@ -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(),
|
||||
|
@ -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.
|
||||
|
@ -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(),
|
||||
|
@ -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(),
|
||||
|
@ -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(),
|
||||
|
@ -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()
|
||||
|
@ -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(),
|
||||
|
@ -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()],
|
||||
|
@ -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(),
|
||||
|
@ -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(),
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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!();
|
||||
|
@ -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;
|
||||
|
@ -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"
|
||||
}
|
||||
}
|
||||
)
|
||||
|
@ -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(),
|
||||
|
@ -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,
|
||||
(),
|
||||
(),
|
||||
(),
|
||||
|
@ -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())
|
||||
}
|
||||
}
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user