Merge pull request #428 from tomaka/draw-indirect

Add back draw_indirect command
This commit is contained in:
tomaka 2017-04-23 16:12:55 +02:00 committed by GitHub
commit ffee50e21d
6 changed files with 139 additions and 6 deletions

View File

@ -14,6 +14,7 @@ use std::sync::Arc;
use buffer::Buffer;
use buffer::TypedBuffer;
use device::DeviceOwned;
use command_buffer::DrawIndirectCommand;
use command_buffer::DynamicState;
use command_buffer::cb::AddCommand;
use command_buffer::cb::CommandBufferBuild;
@ -199,6 +200,24 @@ pub unsafe trait CommandBufferBuilder: DeviceOwned {
self.add(cmd)
}
/// Adds an indirect draw command.
///
/// Can only be used from inside a render pass.
#[inline]
fn draw_indirect<P, S, Pc, V, B, I, O>(self, pipeline: P, dynamic: DynamicState,
vertices: V, indirect_buffer: B, sets: S, push_constants: Pc) -> Result<O, CommandAddError>
where Self: Sized + AddCommand<commands_extra::CmdDrawIndirect<V, B::Access, P, S, Pc>, Out = O>,
S: DescriptorSetsCollection,
P: VertexSource<V> + GraphicsPipelineAbstract + Clone,
B: Buffer,
B::Access: TypedBuffer<Content = [DrawIndirectCommand]>,
I: Index + 'static
{
let cmd = commands_extra::CmdDrawIndirect::new(pipeline, dynamic, vertices, indirect_buffer.access(),
sets, push_constants);
self.add(cmd)
}
/// Executes a compute shader.
fn dispatch<P, S, Pc, O>(self, dimensions: [u32; 3], pipeline: P, sets: S, push_constants: Pc)
-> Result<O, CommandBufferBuilderError<commands_extra::CmdDispatchError>>

View File

@ -107,6 +107,7 @@ pass_through!((S, D), commands_raw::CmdCopyImage<S, D>);
pass_through!((), commands_raw::CmdDispatchRaw);
pass_through!((), commands_raw::CmdDrawRaw);
pass_through!((), commands_raw::CmdDrawIndexedRaw);
pass_through!((B), commands_raw::CmdDrawIndirectRaw<B>);
pass_through!((), commands_raw::CmdEndRenderPass);
pass_through!((C), commands_raw::CmdExecuteCommands<C>);
pass_through!((B), commands_raw::CmdFillBuffer<B>);

View File

@ -317,6 +317,24 @@ unsafe impl<I, O> AddCommand<commands_raw::CmdDrawIndexedRaw> for SubmitSyncBuil
}
}
unsafe impl<I, O, B> AddCommand<commands_raw::CmdDrawIndirectRaw<B>> for SubmitSyncBuilderLayer<I>
where I: AddCommand<commands_raw::CmdDrawIndirectRaw<B>, Out = O>,
B: BufferAccess + Send + Sync + Clone + 'static
{
type Out = SubmitSyncBuilderLayer<O>;
#[inline]
fn add(mut self, command: commands_raw::CmdDrawIndirectRaw<B>) -> Result<Self::Out, CommandAddError> {
self.add_buffer(command.buffer(), true);
Ok(SubmitSyncBuilderLayer {
inner: AddCommand::add(self.inner, command)?,
buffers: self.buffers,
images: self.images,
})
}
}
unsafe impl<I, O> AddCommand<commands_raw::CmdEndRenderPass> for SubmitSyncBuilderLayer<I>
where I: AddCommand<commands_raw::CmdEndRenderPass, Out = O>
{

View File

@ -0,0 +1,87 @@
// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://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 buffer::BufferAccess;
use buffer::TypedBuffer;
use command_buffer::CommandAddError;
use command_buffer::DynamicState;
use command_buffer::DrawIndirectCommand;
use command_buffer::cb::AddCommand;
use command_buffer::commands_raw::CmdBindDescriptorSets;
use command_buffer::commands_raw::CmdBindPipeline;
use command_buffer::commands_raw::CmdBindVertexBuffers;
use command_buffer::commands_raw::CmdDrawIndirectRaw;
use command_buffer::commands_raw::CmdPushConstants;
use command_buffer::commands_raw::CmdSetState;
use descriptor::descriptor_set::DescriptorSetsCollection;
use pipeline::GraphicsPipelineAbstract;
use pipeline::vertex::VertexSource;
/// Command that draws non-indexed vertices.
pub struct CmdDrawIndirect<V, I, P, S, Pc> {
vertex_buffers: CmdBindVertexBuffers<V>,
push_constants: CmdPushConstants<Pc, P>,
descriptor_sets: CmdBindDescriptorSets<S, P>,
set_state: CmdSetState,
bind_pipeline: CmdBindPipeline<P>,
draw_raw: CmdDrawIndirectRaw<I>,
}
impl<V, I, P, S, Pc> CmdDrawIndirect<V, I, P, S, Pc>
where P: GraphicsPipelineAbstract, S: DescriptorSetsCollection,
I: BufferAccess + TypedBuffer<Content = [DrawIndirectCommand]>
{
/// See the documentation of the `draw` method.
pub fn new(pipeline: P, dynamic: DynamicState, vertices: V, indirect_buffer: I, sets: S,
push_constants: Pc) -> CmdDrawIndirect<V, I, P, S, Pc>
where P: VertexSource<V> + Clone
{
let draw_count = indirect_buffer.len() as u32;
// TODO: err, how to ensure safety for ranges in the command?
let bind_pipeline = CmdBindPipeline::bind_graphics_pipeline(pipeline.clone());
let device = bind_pipeline.device().clone();
let set_state = CmdSetState::new(device, dynamic);
let descriptor_sets = CmdBindDescriptorSets::new(true, pipeline.clone(), sets).unwrap() /* TODO: error */;
let push_constants = CmdPushConstants::new(pipeline.clone(), push_constants).unwrap() /* TODO: error */;
let vertex_buffers = CmdBindVertexBuffers::new(&pipeline, vertices);
let draw_raw = unsafe { CmdDrawIndirectRaw::new(indirect_buffer, draw_count) };
CmdDrawIndirect {
vertex_buffers: vertex_buffers,
push_constants: push_constants,
descriptor_sets: descriptor_sets,
set_state: set_state,
bind_pipeline: bind_pipeline,
draw_raw: draw_raw,
}
}
}
unsafe impl<Cb, V, I, P, S, Pc, O, O1, O2, O3, O4, O5> AddCommand<CmdDrawIndirect<V, I, P, S, Pc>> for Cb
where Cb: AddCommand<CmdBindVertexBuffers<V>, Out = O1>,
O1: AddCommand<CmdPushConstants<Pc, P>, Out = O2>,
O2: AddCommand<CmdBindDescriptorSets<S, P>, Out = O3>,
O3: AddCommand<CmdSetState, Out = O4>,
O4: AddCommand<CmdBindPipeline<P>, Out = O5>,
O5: AddCommand<CmdDrawIndirectRaw<I>, Out = O>
{
type Out = O;
#[inline]
fn add(self, command: CmdDrawIndirect<V, I, P, S, Pc>) -> Result<Self::Out, CommandAddError> {
Ok(self.add(command.vertex_buffers)?
.add(command.push_constants)?
.add(command.descriptor_sets)?
.add(command.set_state)?
.add(command.bind_pipeline)?
.add(command.draw_raw)?)
}
}

View File

@ -15,8 +15,10 @@ pub use self::dispatch::{CmdDispatch, CmdDispatchError};
//pub use self::dispatch_indirect::{CmdDispatchIndirect, CmdDispatchIndirectError};
pub use self::draw::CmdDraw;
pub use self::draw_indexed::CmdDrawIndexed;
pub use self::draw_indirect::CmdDrawIndirect;
mod dispatch;
//mod dispatch_indirect;
mod draw;
mod draw_indexed;
mod draw_indirect;

View File

@ -21,28 +21,33 @@ use vk;
pub struct CmdDrawIndirectRaw<B> {
buffer: B,
offset: vk::DeviceSize,
draw_count: u32,
stride: u32,
}
impl<B> CmdDrawIndirectRaw<B> where B: BufferAccess {
#[inline]
pub unsafe fn new(buffer: B, offset: usize, draw_count: u32) -> CmdDrawIndirectRaw<B> {
let real_offset = offset + buffer.inner().offset;
assert_eq!(real_offset % 4, 0);
pub unsafe fn new(buffer: B, draw_count: u32) -> CmdDrawIndirectRaw<B> {
assert_eq!(buffer.inner().offset % 4, 0);
// FIXME: all checks are missing here
CmdDrawIndirectRaw {
buffer: buffer,
offset: real_offset as vk::DeviceSize,
draw_count: draw_count,
stride: 16, // TODO:
}
}
}
impl<B> CmdDrawIndirectRaw<B> {
/// Returns the buffer that contains the indirect command.
#[inline]
pub fn buffer(&self) -> &B {
&self.buffer
}
}
unsafe impl<B> DeviceOwned for CmdDrawIndirectRaw<B>
where B: DeviceOwned
{
@ -64,7 +69,8 @@ unsafe impl<'a, B, P> AddCommand<&'a CmdDrawIndirectRaw<B>> for UnsafeCommandBuf
let vk = self.device().pointers();
let cmd = self.internal_object();
vk.CmdDrawIndirect(cmd, command.buffer.inner().buffer.internal_object(),
command.offset, command.draw_count, command.stride);
command.buffer.inner().offset as vk::DeviceSize,
command.draw_count, command.stride);
}
Ok(self)