use std::ops::Range;
use std::sync::Arc;
use smallvec::SmallVec;
use buffer::Buffer;
use buffer::BufferSlice;
use buffer::TypedBuffer;
use command_buffer::DrawIndirectCommand;
use command_buffer::DynamicState;
use command_buffer::inner::InnerCommandBufferBuilder;
use command_buffer::inner::InnerCommandBuffer;
use command_buffer::inner::Submission;
use command_buffer::inner::submit as inner_submit;
use command_buffer::pool::CommandPool;
use command_buffer::pool::StandardCommandPool;
use descriptor::descriptor_set::DescriptorSetsCollection;
use descriptor::PipelineLayout;
use device::Device;
use device::Queue;
use framebuffer::Framebuffer;
use framebuffer::UnsafeRenderPass;
use framebuffer::RenderPassCompatible;
use framebuffer::RenderPass;
use framebuffer::RenderPassDesc;
use framebuffer::RenderPassClearValues;
use framebuffer::Subpass;
use image::traits::Image;
use image::traits::ImageClearValue;
use image::traits::ImageContent;
use instance::QueueFamily;
use pipeline::ComputePipeline;
use pipeline::GraphicsPipeline;
use pipeline::input_assembly::Index;
use pipeline::vertex::Source as VertexSource;
use OomError;
pub struct PrimaryCommandBufferBuilder<P = Arc<StandardCommandPool>> where P: CommandPool {
inner: InnerCommandBufferBuilder<P>,
}
impl PrimaryCommandBufferBuilder<Arc<StandardCommandPool>> {
#[inline]
pub fn new(device: &Arc<Device>, queue_family: QueueFamily)
-> PrimaryCommandBufferBuilder<Arc<StandardCommandPool>>
{
PrimaryCommandBufferBuilder::raw(Device::standard_command_pool(device, queue_family)).unwrap()
}
}
impl<P> PrimaryCommandBufferBuilder<P> where P: CommandPool {
#[inline]
pub fn raw(pool: P) -> Result<PrimaryCommandBufferBuilder<P>, OomError> {
let inner = try!(InnerCommandBufferBuilder::new::<UnsafeRenderPass>(pool, false, None, None));
Ok(PrimaryCommandBufferBuilder { inner: inner })
}
#[inline]
pub fn update_buffer<'a, B, T, Bb>(self, buffer: B, data: &T) -> PrimaryCommandBufferBuilder<P>
where B: Into<BufferSlice<'a, T, Bb>>, Bb: Buffer + 'static, T: Clone + 'static + Send + Sync
{
unsafe {
PrimaryCommandBufferBuilder {
inner: self.inner.update_buffer(buffer, data)
}
}
}
pub unsafe fn fill_buffer<B>(self, buffer: &Arc<B>, offset: usize,
size: usize, data: u32) -> PrimaryCommandBufferBuilder<P>
where B: Buffer + 'static
{
PrimaryCommandBufferBuilder {
inner: self.inner.fill_buffer(buffer, offset, size, data)
}
}
pub fn copy_buffer<T: ?Sized + 'static, Bs, Bd>(self, source: &Arc<Bs>, destination: &Arc<Bd>)
-> PrimaryCommandBufferBuilder<P>
where Bs: TypedBuffer<Content = T> + 'static, Bd: TypedBuffer<Content = T> + 'static
{
unsafe {
PrimaryCommandBufferBuilder {
inner: self.inner.copy_buffer(source, destination),
}
}
}
pub fn copy_buffer_to_color_image<'a, Pi, S, Img, Sb>(self, source: S, destination: &Arc<Img>, mip_level: u32, array_layers_range: Range<u32>,
offset: [u32; 3], extent: [u32; 3])
-> PrimaryCommandBufferBuilder<P>
where S: Into<BufferSlice<'a, [Pi], Sb>>, Sb: Buffer + 'static,
Img: ImageContent<Pi> + 'static
{
unsafe {
PrimaryCommandBufferBuilder {
inner: self.inner.copy_buffer_to_color_image(source, destination, mip_level,
array_layers_range, offset, extent),
}
}
}
pub fn copy_color_image_to_buffer<'a, Pi, S, Img, Sb>(self, dest: S, destination: &Arc<Img>, mip_level: u32, array_layers_range: Range<u32>,
offset: [u32; 3], extent: [u32; 3])
-> PrimaryCommandBufferBuilder<P>
where S: Into<BufferSlice<'a, [Pi], Sb>>, Sb: Buffer + 'static,
Img: ImageContent<Pi> + 'static
{
unsafe {
PrimaryCommandBufferBuilder {
inner: self.inner.copy_color_image_to_buffer(dest, destination, mip_level,
array_layers_range, offset, extent),
}
}
}
pub fn blit<Si, Di>(self, source: &Arc<Si>, source_mip_level: u32,
source_array_layers: Range<u32>, src_coords: [Range<i32>; 3],
destination: &Arc<Di>, dest_mip_level: u32,
dest_array_layers: Range<u32>, dest_coords: [Range<i32>; 3])
-> PrimaryCommandBufferBuilder<P>
where Si: Image + 'static, Di: Image + 'static
{
unsafe {
PrimaryCommandBufferBuilder {
inner: self.inner.blit(source, source_mip_level, source_array_layers, src_coords,
destination, dest_mip_level, dest_array_layers, dest_coords),
}
}
}
pub fn clear_color_image<'a, I, V>(self, image: &Arc<I>, color: V)
-> PrimaryCommandBufferBuilder<P>
where I: ImageClearValue<V> + 'static
{
unsafe {
PrimaryCommandBufferBuilder {
inner: self.inner.clear_color_image(image, color),
}
}
}
#[inline]
pub fn execute_commands<S>(self, cb: &Arc<SecondaryComputeCommandBuffer<S>>)
-> PrimaryCommandBufferBuilder<P>
where S: CommandPool + 'static,
S::Finished: Send + Sync + 'static,
{
unsafe {
PrimaryCommandBufferBuilder {
inner: self.inner.execute_commands(cb.clone() as Arc<_>, &cb.inner)
}
}
}
#[inline]
pub fn dispatch<Pl, L, Pc>(self, pipeline: &Arc<ComputePipeline<Pl>>, sets: L,
dimensions: [u32; 3], push_constants: &Pc) -> PrimaryCommandBufferBuilder<P>
where L: DescriptorSetsCollection + Send + Sync,
Pl: 'static + PipelineLayout + Send + Sync,
Pc: 'static + Clone + Send + Sync
{
unsafe {
PrimaryCommandBufferBuilder {
inner: self.inner.dispatch(pipeline, sets, dimensions, push_constants)
}
}
}
#[inline]
pub fn draw_inline<R, F, C>(self, renderpass: &Arc<R>,
framebuffer: &Arc<Framebuffer<F>>, clear_values: C)
-> PrimaryCommandBufferBuilderInlineDraw<P>
where F: RenderPass + RenderPassDesc + RenderPassClearValues<C> + 'static,
R: RenderPass + RenderPassDesc + 'static
{
let clear_values = framebuffer.render_pass().convert_clear_values(clear_values)
.collect::<SmallVec<[_; 16]>>();
unsafe {
let inner = self.inner.begin_renderpass(renderpass, framebuffer, false, &clear_values);
PrimaryCommandBufferBuilderInlineDraw {
inner: inner,
current_subpass: 0,
num_subpasses: framebuffer.render_pass().num_subpasses(),
}
}
}
#[inline]
pub fn draw_secondary<R, F, C>(self, renderpass: &Arc<R>,
framebuffer: &Arc<Framebuffer<F>>, clear_values: C)
-> PrimaryCommandBufferBuilderSecondaryDraw<P>
where F: RenderPass + RenderPassDesc + RenderPassClearValues<C> + 'static,
R: RenderPass + RenderPassDesc + 'static
{
let clear_values = framebuffer.render_pass().convert_clear_values(clear_values)
.collect::<SmallVec<[_; 16]>>();
unsafe {
let inner = self.inner.begin_renderpass(renderpass, framebuffer, true, &clear_values);
PrimaryCommandBufferBuilderSecondaryDraw {
inner: inner,
current_subpass: 0,
num_subpasses: framebuffer.render_pass().num_subpasses(),
}
}
}
#[inline]
pub fn build_raw(self) -> Result<PrimaryCommandBuffer<P>, OomError> {
let inner = try!(self.inner.build());
Ok(PrimaryCommandBuffer { inner: inner })
}
#[inline]
pub fn build(self) -> Arc<PrimaryCommandBuffer<P>> {
Arc::new(self.build_raw().unwrap())
}
}
pub struct PrimaryCommandBufferBuilderInlineDraw<P = Arc<StandardCommandPool>>
where P: CommandPool
{
inner: InnerCommandBufferBuilder<P>,
current_subpass: u32,
num_subpasses: u32,
}
impl<P> PrimaryCommandBufferBuilderInlineDraw<P> where P: CommandPool {
pub fn draw<V, L, Pv, Pl, Rp, Pc>(self, pipeline: &Arc<GraphicsPipeline<Pv, Pl, Rp>>,
vertices: V, dynamic: &DynamicState, sets: L, push_constants: &Pc)
-> PrimaryCommandBufferBuilderInlineDraw<P>
where Pv: VertexSource<V> + 'static, Pl: PipelineLayout + 'static + Send + Sync, Rp: 'static + Send + Sync,
L: DescriptorSetsCollection + Send + Sync, Pc: 'static + Clone + Send + Sync
{
unsafe {
PrimaryCommandBufferBuilderInlineDraw {
inner: self.inner.draw(pipeline, vertices, dynamic, sets, push_constants),
num_subpasses: self.num_subpasses,
current_subpass: self.current_subpass,
}
}
}
pub fn draw_indexed<'a, V, L, Pv, Pl, Rp, I, Ib, Ibb, Pc>(self, pipeline: &Arc<GraphicsPipeline<Pv, Pl, Rp>>,
vertices: V, indices: Ib, dynamic: &DynamicState,
sets: L, push_constants: &Pc) -> PrimaryCommandBufferBuilderInlineDraw<P>
where Pv: 'static + VertexSource<V> + Send + Sync, Pl: 'static + PipelineLayout + Send + Sync, Rp: 'static + Send + Sync,
Ib: Into<BufferSlice<'a, [I], Ibb>>, I: 'static + Index, Ibb: Buffer + 'static + Send + Sync,
L: DescriptorSetsCollection + Send + Sync, Pc: 'static + Clone + Send + Sync
{
unsafe {
PrimaryCommandBufferBuilderInlineDraw {
inner: self.inner.draw_indexed(pipeline, vertices, indices, dynamic, sets, push_constants),
num_subpasses: self.num_subpasses,
current_subpass: self.current_subpass,
}
}
}
#[inline]
pub fn next_subpass_inline(self) -> PrimaryCommandBufferBuilderInlineDraw<P> {
assert!(self.current_subpass + 1 < self.num_subpasses);
unsafe {
let inner = self.inner.next_subpass(false);
PrimaryCommandBufferBuilderInlineDraw {
inner: inner,
num_subpasses: self.num_subpasses,
current_subpass: self.current_subpass + 1,
}
}
}
#[inline]
pub fn next_subpass_secondary(self) -> PrimaryCommandBufferBuilderSecondaryDraw<P> {
assert!(self.current_subpass + 1 < self.num_subpasses);
unsafe {
let inner = self.inner.next_subpass(true);
PrimaryCommandBufferBuilderSecondaryDraw {
inner: inner,
num_subpasses: self.num_subpasses,
current_subpass: self.current_subpass + 1,
}
}
}
#[inline]
pub fn draw_end(self) -> PrimaryCommandBufferBuilder<P> {
assert!(self.current_subpass + 1 == self.num_subpasses);
unsafe {
let inner = self.inner.end_renderpass();
PrimaryCommandBufferBuilder {
inner: inner,
}
}
}
}
pub struct PrimaryCommandBufferBuilderSecondaryDraw<P = Arc<StandardCommandPool>>
where P: CommandPool
{
inner: InnerCommandBufferBuilder<P>,
current_subpass: u32,
num_subpasses: u32,
}
impl<P> PrimaryCommandBufferBuilderSecondaryDraw<P> where P: CommandPool {
#[inline]
pub fn next_subpass_inline(self) -> PrimaryCommandBufferBuilderInlineDraw<P> {
assert!(self.current_subpass + 1 < self.num_subpasses);
unsafe {
let inner = self.inner.next_subpass(false);
PrimaryCommandBufferBuilderInlineDraw {
inner: inner,
num_subpasses: self.num_subpasses,
current_subpass: self.current_subpass + 1,
}
}
}
#[inline]
pub fn next_subpass_secondary(self) -> PrimaryCommandBufferBuilderSecondaryDraw<P> {
assert!(self.current_subpass + 1 < self.num_subpasses);
unsafe {
let inner = self.inner.next_subpass(true);
PrimaryCommandBufferBuilderSecondaryDraw {
inner: inner,
num_subpasses: self.num_subpasses,
current_subpass: self.current_subpass + 1,
}
}
}
#[inline]
pub fn execute_commands<R, Ps>(mut self, cb: &Arc<SecondaryGraphicsCommandBuffer<R, Ps>>)
-> PrimaryCommandBufferBuilderSecondaryDraw<P>
where R: 'static + Send + Sync,
Ps: CommandPool + 'static,
Ps::Finished: Send + Sync + 'static,
{
unsafe {
self.inner = self.inner.execute_commands(cb.clone() as Arc<_>, &cb.inner);
self
}
}
#[inline]
pub fn draw_end(self) -> PrimaryCommandBufferBuilder<P> {
assert!(self.current_subpass + 1 == self.num_subpasses);
unsafe {
let inner = self.inner.end_renderpass();
PrimaryCommandBufferBuilder {
inner: inner,
}
}
}
}
pub struct PrimaryCommandBuffer<P = Arc<StandardCommandPool>> where P: CommandPool {
inner: InnerCommandBuffer<P>,
}
#[inline]
pub fn submit<P>(cmd: &Arc<PrimaryCommandBuffer<P>>, queue: &Arc<Queue>)
-> Result<Arc<Submission>, OomError>
where P: CommandPool + 'static,
P::Finished: Send + Sync + 'static
{ inner_submit(&cmd.inner, cmd.clone() as Arc<_>, queue)
}
pub struct SecondaryGraphicsCommandBufferBuilder<R, P = Arc<StandardCommandPool>>
where P: CommandPool
{
inner: InnerCommandBufferBuilder<P>,
render_pass: Arc<R>,
render_pass_subpass: u32,
framebuffer: Option<Arc<Framebuffer<R>>>,
}
impl<R> SecondaryGraphicsCommandBufferBuilder<R, Arc<StandardCommandPool>>
where R: RenderPass + RenderPassDesc + 'static
{
#[inline]
pub fn new(device: &Arc<Device>, queue_family: QueueFamily, subpass: Subpass<R>,
framebuffer: Option<&Arc<Framebuffer<R>>>)
-> SecondaryGraphicsCommandBufferBuilder<R, Arc<StandardCommandPool>>
where R: 'static + Send + Sync
{
SecondaryGraphicsCommandBufferBuilder::raw(Device::standard_command_pool(device,
queue_family), subpass, framebuffer).unwrap()
}
}
impl<R, P> SecondaryGraphicsCommandBufferBuilder<R, P>
where R: RenderPass + RenderPassDesc + 'static,
P: CommandPool
{
#[inline]
pub fn raw(pool: P, subpass: Subpass<R>, framebuffer: Option<&Arc<Framebuffer<R>>>)
-> Result<SecondaryGraphicsCommandBufferBuilder<R, P>, OomError>
where R: 'static + Send + Sync
{
let inner = try!(InnerCommandBufferBuilder::new(pool, true, Some(subpass), framebuffer.clone()));
Ok(SecondaryGraphicsCommandBufferBuilder {
inner: inner,
render_pass: subpass.render_pass().clone(),
render_pass_subpass: subpass.index(),
framebuffer: framebuffer.map(|fb| fb.clone()),
})
}
pub fn draw<V, L, Pv, Pl, Rp, Pc>(self, pipeline: &Arc<GraphicsPipeline<Pv, Pl, Rp>>,
vertices: V, dynamic: &DynamicState, sets: L, push_constants: &Pc)
-> SecondaryGraphicsCommandBufferBuilder<R, P>
where Pv: VertexSource<V> + 'static, Pl: PipelineLayout + 'static + Send + Sync,
Rp: RenderPass + RenderPassDesc + 'static + Send + Sync, L: DescriptorSetsCollection + Send + Sync,
R: RenderPassCompatible<Rp>, Pc: 'static + Clone + Send + Sync
{
assert!(self.render_pass.is_compatible_with(pipeline.subpass().render_pass()));
assert_eq!(self.render_pass_subpass, pipeline.subpass().index());
unsafe {
SecondaryGraphicsCommandBufferBuilder {
inner: self.inner.draw(pipeline, vertices, dynamic, sets, push_constants),
render_pass: self.render_pass,
render_pass_subpass: self.render_pass_subpass,
framebuffer: self.framebuffer,
}
}
}
pub fn draw_indexed<'a, V, L, Pv, Pl, Rp, I, Ib, Ibb, Pc>(self, pipeline: &Arc<GraphicsPipeline<Pv, Pl, Rp>>,
vertices: V, indices: Ib, dynamic: &DynamicState,
sets: L, push_constants: &Pc) -> SecondaryGraphicsCommandBufferBuilder<R, P>
where Pv: 'static + VertexSource<V>, Pl: 'static + PipelineLayout + Send + Sync,
Rp: RenderPass + RenderPassDesc + 'static + Send + Sync,
Ib: Into<BufferSlice<'a, [I], Ibb>>, I: 'static + Index, Ibb: Buffer + 'static,
L: DescriptorSetsCollection + Send + Sync, Pc: 'static + Clone + Send + Sync
{
assert!(self.render_pass.is_compatible_with(pipeline.subpass().render_pass()));
assert_eq!(self.render_pass_subpass, pipeline.subpass().index());
unsafe {
SecondaryGraphicsCommandBufferBuilder {
inner: self.inner.draw_indexed(pipeline, vertices, indices, dynamic, sets, push_constants),
render_pass: self.render_pass,
render_pass_subpass: self.render_pass_subpass,
framebuffer: self.framebuffer,
}
}
}
pub fn draw_indirect<I, V, Pv, Pl, L, Rp, Pc>(self, buffer: &Arc<I>, pipeline: &Arc<GraphicsPipeline<Pv, Pl, Rp>>,
vertices: V, dynamic: &DynamicState,
sets: L, push_constants: &Pc) -> SecondaryGraphicsCommandBufferBuilder<R, P>
where Pv: 'static + VertexSource<V>, L: DescriptorSetsCollection + Send + Sync,
Pl: 'static + PipelineLayout + Send + Sync, Rp: RenderPass + RenderPassDesc + 'static + Send + Sync,
Pc: 'static + Clone + Send + Sync,
I: 'static + TypedBuffer<Content = [DrawIndirectCommand]>
{
assert!(self.render_pass.is_compatible_with(pipeline.subpass().render_pass()));
assert_eq!(self.render_pass_subpass, pipeline.subpass().index());
unsafe {
SecondaryGraphicsCommandBufferBuilder {
inner: self.inner.draw_indirect(buffer, pipeline, vertices, dynamic, sets, push_constants),
render_pass: self.render_pass,
render_pass_subpass: self.render_pass_subpass,
framebuffer: self.framebuffer,
}
}
}
#[inline]
pub fn build_raw(self) -> Result<SecondaryGraphicsCommandBuffer<R, P>, OomError> {
let inner = try!(self.inner.build());
Ok(SecondaryGraphicsCommandBuffer {
inner: inner,
render_pass: self.render_pass,
render_pass_subpass: self.render_pass_subpass,
})
}
#[inline]
pub fn build(self) -> Arc<SecondaryGraphicsCommandBuffer<R, P>> {
Arc::new(self.build_raw().unwrap())
}
}
pub struct SecondaryGraphicsCommandBuffer<R, P = Arc<StandardCommandPool>> where P: CommandPool {
inner: InnerCommandBuffer<P>,
render_pass: Arc<R>,
render_pass_subpass: u32,
}
pub struct SecondaryComputeCommandBufferBuilder<P = Arc<StandardCommandPool>> where P: CommandPool {
inner: InnerCommandBufferBuilder<P>,
}
impl SecondaryComputeCommandBufferBuilder<Arc<StandardCommandPool>> {
#[inline]
pub fn new(device: &Arc<Device>, queue_family: QueueFamily)
-> SecondaryComputeCommandBufferBuilder<Arc<StandardCommandPool>>
{
SecondaryComputeCommandBufferBuilder::raw(Device::standard_command_pool(device,
queue_family)).unwrap()
}
}
impl<P> SecondaryComputeCommandBufferBuilder<P> where P: CommandPool {
#[inline]
pub fn raw(pool: P) -> Result<SecondaryComputeCommandBufferBuilder<P>, OomError> {
let inner = try!(InnerCommandBufferBuilder::new::<UnsafeRenderPass>(pool, true, None, None));
Ok(SecondaryComputeCommandBufferBuilder { inner: inner })
}
#[inline]
pub fn update_buffer<'a, B, T, Bb>(self, buffer: B, data: &T) -> SecondaryComputeCommandBufferBuilder<P>
where B: Into<BufferSlice<'a, T, Bb>>, Bb: Buffer + 'static, T: Clone + 'static + Send + Sync
{
unsafe {
SecondaryComputeCommandBufferBuilder {
inner: self.inner.update_buffer(buffer, data)
}
}
}
pub unsafe fn fill_buffer<B>(self, buffer: &Arc<B>, offset: usize, size: usize, data: u32)
-> SecondaryComputeCommandBufferBuilder<P>
where B: Buffer + 'static
{
SecondaryComputeCommandBufferBuilder {
inner: self.inner.fill_buffer(buffer, offset, size, data)
}
}
#[inline]
pub fn build_raw(self) -> Result<SecondaryComputeCommandBuffer<P>, OomError> {
let inner = try!(self.inner.build());
Ok(SecondaryComputeCommandBuffer { inner: inner })
}
#[inline]
pub fn build(self) -> Arc<SecondaryComputeCommandBuffer<P>> {
Arc::new(self.build_raw().unwrap())
}
}
pub struct SecondaryComputeCommandBuffer<P = Arc<StandardCommandPool>>
where P: CommandPool
{
inner: InnerCommandBuffer<P>,
}