use super::buffer::*;
use super::raw::*;
use super::framebuffer::*;
use super::pipeline::*;
use super::texture::*;
use super::compute_program::*;
use super::uniform::*;
use std::mem::size_of;
#[derive(Copy, Clone)]
pub enum DrawCommandType<'a> {
DrawArrays {
first: usize,
count: usize,
},
DrawArraysIndirect {
indirect: &'a Buffer,
offset: usize,
},
DrawArraysInstanced {
first: usize,
count: usize,
primitive_count: usize,
},
DrawArraysInstancedBaseInstance {
first: usize,
count: usize,
primitive_count: usize,
base_instance: usize,
},
MultiDrawArrays {
first: &'a [u32],
count: &'a [u32],
draw_count: usize,
},
MultiDrawArraysIndirect {
indirect: &'a Buffer,
draw_count: usize,
stride: usize,
},
MultiDrawElementsIndirect {
indices: &'a Buffer,
indirect: &'a Buffer,
draw_count: usize,
stride: usize,
},
Compute {
num_groups_x: usize,
num_groups_y: usize,
num_groups_z: usize,
},
}
pub struct DrawCommand<'a> {
pub framebuffer: Option<&'a GeneralFramebuffer>,
pub attachments: Option<&'a DrawTextureTarget<'a>>,
pub pipeline: Option<&'a Pipeline>,
pub compute: Option<&'a ComputeProgram>,
pub draw_command_type: DrawCommandType<'a>,
pub mode: DrawMode,
pub images: Vec<(&'a Texture, usize, usize, ImageInternalFormat)>,
pub images_3d: Vec<(&'a Texture3D, usize, usize, ImageInternalFormat)>,
pub images_read: Vec<(&'a Texture, usize, usize, ImageInternalFormat)>,
pub images_write: Vec<(&'a Texture, usize, usize, ImageInternalFormat)>,
pub textures_1d: Vec<(&'a Texture1D, usize)>,
pub textures_2d: Vec<(&'a Texture2D, usize)>,
pub textures_3d: Vec<(&'a Texture3D, usize)>,
pub textures_cubemap: Vec<(&'a TextureCubemap, usize)>,
pub texture_1d_arrays: Vec<(&'a [Option<&'a Texture1D>], usize)>,
pub texture_2d_arrays: Vec<(&'a [Option<&'a Texture2D>], usize)>,
pub texture_3d_arrays: Vec<(&'a [Option<&'a Texture3D>], usize)>,
pub texture_cubemap_arrays: Vec<(&'a [Option<&'a TextureCubemap>], usize)>,
pub storages: Vec<(&'a MutableBuffer, usize)>,
pub storages_read: Vec<(&'a Buffer, usize)>,
pub storage_ranges: Vec<(&'a MutableBuffer, usize, usize, usize)>,
pub storage_range_reads: Vec<(&'a Buffer, usize, usize, usize)>,
pub uniforms: Vec<(UniformValue<'a>, usize)>,
pub uniform_buffers: Vec<(&'a Buffer, usize)>,
pub uniform_ranges: Vec<(&'a Buffer, usize, usize, usize)>,
pub atomic_counters: Vec<(&'a MutableBuffer, usize)>,
pub barriers: Option<MemoryBarriers>,
}
impl<'a> DrawCommand<'a> {
pub fn arrays(pipeline: &'a Pipeline, first: usize, count: usize) -> DrawCommand<'a> {
DrawCommand {
framebuffer: None,
attachments: None,
pipeline: Some(pipeline),
compute: None,
draw_command_type: DrawCommandType::DrawArrays { first, count },
mode: DrawMode::Triangles,
images: Vec::new(),
images_3d: Vec::new(),
images_read: Vec::new(),
images_write: Vec::new(),
textures_1d: Vec::new(),
textures_2d: Vec::new(),
textures_3d: Vec::new(),
textures_cubemap: Vec::new(),
texture_1d_arrays: Vec::new(),
texture_2d_arrays: Vec::new(),
texture_3d_arrays: Vec::new(),
texture_cubemap_arrays: Vec::new(),
storages: Vec::new(),
storages_read: Vec::new(),
storage_ranges: Vec::new(),
storage_range_reads: Vec::new(),
uniforms: Vec::new(),
uniform_buffers: Vec::new(),
uniform_ranges: Vec::new(),
atomic_counters: Vec::new(),
barriers: None,
}
}
pub fn arrays_indirect(pipeline: &'a Pipeline, indirect: &'a Buffer, offset: usize) -> DrawCommand<'a> {
DrawCommand {
framebuffer: None,
attachments: None,
pipeline: Some(pipeline),
compute: None,
draw_command_type: DrawCommandType::DrawArraysIndirect { indirect, offset },
mode: DrawMode::Triangles,
images: Vec::new(),
images_3d: Vec::new(),
images_read: Vec::new(),
images_write: Vec::new(),
textures_1d: Vec::new(),
textures_2d: Vec::new(),
textures_3d: Vec::new(),
textures_cubemap: Vec::new(),
texture_1d_arrays: Vec::new(),
texture_2d_arrays: Vec::new(),
texture_3d_arrays: Vec::new(),
texture_cubemap_arrays: Vec::new(),
storages: Vec::new(),
storages_read: Vec::new(),
storage_ranges: Vec::new(),
storage_range_reads: Vec::new(),
uniforms: Vec::new(),
uniform_buffers: Vec::new(),
uniform_ranges: Vec::new(),
atomic_counters: Vec::new(),
barriers: None,
}
}
pub fn arrays_instanced(
pipeline: &'a Pipeline,
first: usize,
count: usize,
primitive_count: usize,
) -> DrawCommand<'a> {
DrawCommand {
framebuffer: None,
attachments: None,
pipeline: Some(pipeline),
compute: None,
draw_command_type: DrawCommandType::DrawArraysInstanced {
first,
count,
primitive_count,
},
mode: DrawMode::Triangles,
images: Vec::new(),
images_3d: Vec::new(),
images_read: Vec::new(),
images_write: Vec::new(),
textures_1d: Vec::new(),
textures_2d: Vec::new(),
textures_3d: Vec::new(),
textures_cubemap: Vec::new(),
texture_1d_arrays: Vec::new(),
texture_2d_arrays: Vec::new(),
texture_3d_arrays: Vec::new(),
texture_cubemap_arrays: Vec::new(),
storages: Vec::new(),
storages_read: Vec::new(),
storage_ranges: Vec::new(),
storage_range_reads: Vec::new(),
uniforms: Vec::new(),
uniform_buffers: Vec::new(),
uniform_ranges: Vec::new(),
atomic_counters: Vec::new(),
barriers: None,
}
}
pub fn multi_draw_arrays(
pipeline: &'a Pipeline,
first: &'a [u32],
count: &'a [u32],
draw_count: usize,
) -> DrawCommand<'a> {
DrawCommand {
framebuffer: None,
attachments: None,
pipeline: Some(pipeline),
compute: None,
draw_command_type: DrawCommandType::MultiDrawArrays {
first,
count,
draw_count,
},
mode: DrawMode::Triangles,
images: Vec::new(),
images_3d: Vec::new(),
images_read: Vec::new(),
images_write: Vec::new(),
textures_1d: Vec::new(),
textures_2d: Vec::new(),
textures_3d: Vec::new(),
textures_cubemap: Vec::new(),
texture_1d_arrays: Vec::new(),
texture_2d_arrays: Vec::new(),
texture_3d_arrays: Vec::new(),
texture_cubemap_arrays: Vec::new(),
storages: Vec::new(),
storages_read: Vec::new(),
storage_ranges: Vec::new(),
storage_range_reads: Vec::new(),
uniforms: Vec::new(),
uniform_buffers: Vec::new(),
uniform_ranges: Vec::new(),
atomic_counters: Vec::new(),
barriers: None,
}
}
pub fn multi_draw_arrays_indirect(
pipeline: &'a Pipeline,
indirect: &'a Buffer,
draw_count: usize,
stride: usize,
) -> DrawCommand<'a> {
DrawCommand {
framebuffer: None,
attachments: None,
pipeline: Some(pipeline),
compute: None,
draw_command_type: DrawCommandType::MultiDrawArraysIndirect {
indirect,
draw_count,
stride,
},
mode: DrawMode::Triangles,
images: Vec::new(),
images_3d: Vec::new(),
images_read: Vec::new(),
images_write: Vec::new(),
textures_1d: Vec::new(),
textures_2d: Vec::new(),
textures_3d: Vec::new(),
textures_cubemap: Vec::new(),
texture_1d_arrays: Vec::new(),
texture_2d_arrays: Vec::new(),
texture_3d_arrays: Vec::new(),
texture_cubemap_arrays: Vec::new(),
storages: Vec::new(),
storages_read: Vec::new(),
storage_ranges: Vec::new(),
storage_range_reads: Vec::new(),
uniforms: Vec::new(),
uniform_buffers: Vec::new(),
uniform_ranges: Vec::new(),
atomic_counters: Vec::new(),
barriers: None,
}
}
pub fn multi_draw_elements_indirect(
pipeline: &'a Pipeline,
indices: &'a Buffer,
indirect: &'a Buffer,
draw_count: usize,
stride: usize,
) -> DrawCommand<'a> {
DrawCommand {
framebuffer: None,
attachments: None,
pipeline: Some(pipeline),
compute: None,
draw_command_type: DrawCommandType::MultiDrawElementsIndirect {
indices,
indirect,
draw_count,
stride,
},
mode: DrawMode::Triangles,
images: Vec::new(),
images_3d: Vec::new(),
images_read: Vec::new(),
images_write: Vec::new(),
textures_1d: Vec::new(),
textures_2d: Vec::new(),
textures_3d: Vec::new(),
textures_cubemap: Vec::new(),
texture_1d_arrays: Vec::new(),
texture_2d_arrays: Vec::new(),
texture_3d_arrays: Vec::new(),
texture_cubemap_arrays: Vec::new(),
storages: Vec::new(),
storages_read: Vec::new(),
storage_ranges: Vec::new(),
storage_range_reads: Vec::new(),
uniforms: Vec::new(),
uniform_buffers: Vec::new(),
uniform_ranges: Vec::new(),
atomic_counters: Vec::new(),
barriers: None,
}
}
pub fn compute(
program: &'a ComputeProgram,
num_groups_x: usize,
num_groups_y: usize,
num_groups_z: usize,
) -> DrawCommand<'a> {
DrawCommand {
framebuffer: None,
attachments: None,
pipeline: None,
compute: Some(program),
draw_command_type: DrawCommandType::Compute {
num_groups_x,
num_groups_y,
num_groups_z,
},
mode: DrawMode::Triangles,
images: Vec::new(),
images_3d: Vec::new(),
images_read: Vec::new(),
images_write: Vec::new(),
textures_1d: Vec::new(),
textures_2d: Vec::new(),
textures_3d: Vec::new(),
textures_cubemap: Vec::new(),
texture_1d_arrays: Vec::new(),
texture_2d_arrays: Vec::new(),
texture_3d_arrays: Vec::new(),
texture_cubemap_arrays: Vec::new(),
storages: Vec::new(),
storages_read: Vec::new(),
storage_ranges: Vec::new(),
storage_range_reads: Vec::new(),
uniforms: Vec::new(),
uniform_buffers: Vec::new(),
uniform_ranges: Vec::new(),
atomic_counters: Vec::new(),
barriers: None,
}
}
pub fn framebuffer(mut self, framebuffer: &'a GeneralFramebuffer) -> Self {
self.framebuffer = Some(framebuffer);
self
}
pub fn attachments(mut self, attachments: &'a DrawTextureTarget<'a>) -> Self {
self.attachments = Some(attachments);
self
}
pub fn mode(mut self, mode: DrawMode) -> Self {
self.mode = mode;
self
}
pub fn image<T: Texture>(mut self, image: &'a T, unit: usize, level: usize, format: ImageInternalFormat) -> Self {
self.images.push((image, unit, level, format));
self
}
pub fn image_3d(mut self, image: &'a Texture3D, unit: usize, level: usize, format: ImageInternalFormat) -> Self {
self.images_3d.push((image, unit, level, format));
self
}
pub fn image_read<T: Texture>(
mut self,
image: &'a T,
unit: usize,
level: usize,
format: ImageInternalFormat,
) -> Self {
self.images_read.push((image, unit, level, format));
self
}
pub fn image_write<T: Texture>(
mut self,
image: &'a T,
unit: usize,
level: usize,
format: ImageInternalFormat,
) -> Self {
self.images_write.push((image, unit, level, format));
self
}
pub fn texture_1d<T: Into<Option<&'a Texture1D>>>(mut self, texture: T, unit: usize) -> Self {
let tex = texture.into();
if tex.is_some() {
self.textures_1d.push((tex.unwrap(), unit));
}
self
}
pub fn texture_2d<T: Into<Option<&'a Texture2D>>>(mut self, texture: T, unit: usize) -> Self {
let tex = texture.into();
if tex.is_some() {
self.textures_2d.push((tex.unwrap(), unit));
}
self
}
pub fn texture_3d<T: Into<Option<&'a Texture3D>>>(mut self, texture: T, unit: usize) -> Self {
let tex = texture.into();
if tex.is_some() {
self.textures_3d.push((tex.unwrap(), unit));
}
self
}
pub fn texture_cubemap(mut self, texture: &'a TextureCubemap, unit: usize) -> Self {
self.textures_cubemap.push((texture, unit));
self
}
pub fn texture_1d_array(mut self, textures: &'a [Option<&'a Texture1D>], starting_location: usize) -> Self {
self.texture_1d_arrays.push((textures, starting_location));
self
}
pub fn texture_2d_array(mut self, textures: &'a [Option<&'a Texture2D>], starting_location: usize) -> Self {
self.texture_2d_arrays.push((textures, starting_location));
self
}
pub fn texture_3d_array(mut self, textures: &'a [Option<&'a Texture3D>], starting_location: usize) -> Self {
self.texture_3d_arrays.push((textures, starting_location));
self
}
pub fn texture_cubemap_array(
mut self,
textures: &'a [Option<&'a TextureCubemap>],
starting_location: usize,
) -> Self {
self.texture_cubemap_arrays
.push((textures, starting_location));
self
}
pub fn storage(mut self, storage: &'a MutableBuffer, location: usize) -> Self {
self.storages.push((storage, location));
self
}
pub fn storage_read(mut self, storage: &'a Buffer, location: usize) -> Self {
self.storages_read.push((storage, location));
self
}
pub fn storage_range<T>(mut self, storage: &'a MutableBuffer, location: usize, offset: usize, size: usize) -> Self {
self.storage_ranges.push((
storage,
location,
offset * size_of::<T>(),
size * size_of::<T>(),
));
self
}
pub fn storage_range_read<T>(mut self, storage: &'a Buffer, location: usize, offset: usize, size: usize) -> Self {
self.storage_range_reads.push((
storage,
location,
offset * size_of::<T>(),
size * size_of::<T>(),
));
self
}
pub fn uniform_1f(mut self, v0: f32, location: usize) -> Self {
self.uniforms.push((UniformValue::Uniform1f(v0), location));
self
}
pub fn uniform_2f(mut self, v0: f32, v1: f32, location: usize) -> Self {
self.uniforms
.push((UniformValue::Uniform2f(v0, v1), location));
self
}
pub fn uniform_3f(mut self, v0: f32, v1: f32, v2: f32, location: usize) -> Self {
self.uniforms
.push((UniformValue::Uniform3f(v0, v1, v2), location));
self
}
pub fn uniform_4f(mut self, v0: f32, v1: f32, v2: f32, v3: f32, location: usize) -> Self {
self.uniforms
.push((UniformValue::Uniform4f(v0, v1, v2, v3), location));
self
}
pub fn uniform_1i(mut self, v0: i32, location: usize) -> Self {
self.uniforms.push((UniformValue::Uniform1i(v0), location));
self
}
pub fn uniform_2i(mut self, v0: i32, v1: i32, location: usize) -> Self {
self.uniforms
.push((UniformValue::Uniform2i(v0, v1), location));
self
}
pub fn uniform_3i(mut self, v0: i32, v1: i32, v2: i32, location: usize) -> Self {
self.uniforms
.push((UniformValue::Uniform3i(v0, v1, v2), location));
self
}
pub fn uniform_4i(mut self, v0: i32, v1: i32, v2: i32, v3: i32, location: usize) -> Self {
self.uniforms
.push((UniformValue::Uniform4i(v0, v1, v2, v3), location));
self
}
pub fn uniform_1ui(mut self, v0: u32, location: usize) -> Self {
self.uniforms.push((UniformValue::Uniform1ui(v0), location));
self
}
pub fn uniform_2ui(mut self, v0: u32, v1: u32, location: usize) -> Self {
self.uniforms
.push((UniformValue::Uniform2ui(v0, v1), location));
self
}
pub fn uniform_3ui(mut self, v0: u32, v1: u32, v2: u32, location: usize) -> Self {
self.uniforms
.push((UniformValue::Uniform3ui(v0, v1, v2), location));
self
}
pub fn uniform_4ui(mut self, v0: u32, v1: u32, v2: u32, v3: u32, location: usize) -> Self {
self.uniforms
.push((UniformValue::Uniform4ui(v0, v1, v2, v3), location));
self
}
pub fn uniform_1fv(mut self, array: &'a [f32], location: usize) -> Self {
self.uniforms
.push((UniformValue::Uniform1fv(array), location));
self
}
pub fn uniform_2fv(mut self, array: &'a [[f32; 2]], location: usize) -> Self {
self.uniforms
.push((UniformValue::Uniform2fv(array), location));
self
}
pub fn uniform_3fv(mut self, array: &'a [[f32; 3]], location: usize) -> Self {
self.uniforms
.push((UniformValue::Uniform3fv(array), location));
self
}
pub fn uniform_4fv(mut self, array: &'a [[f32; 4]], location: usize) -> Self {
self.uniforms
.push((UniformValue::Uniform4fv(array), location));
self
}
pub fn uniform_1iv(mut self, array: &'a [i32], location: usize) -> Self {
self.uniforms
.push((UniformValue::Uniform1iv(array), location));
self
}
pub fn uniform_2iv(mut self, array: &'a [[i32; 2]], location: usize) -> Self {
self.uniforms
.push((UniformValue::Uniform2iv(array), location));
self
}
pub fn uniform_3iv(mut self, array: &'a [[i32; 3]], location: usize) -> Self {
self.uniforms
.push((UniformValue::Uniform3iv(array), location));
self
}
pub fn uniform_4iv(mut self, array: &'a [[i32; 4]], location: usize) -> Self {
self.uniforms
.push((UniformValue::Uniform4iv(array), location));
self
}
pub fn uniform_1uiv(mut self, array: &'a [u32], location: usize) -> Self {
self.uniforms
.push((UniformValue::Uniform1uiv(array), location));
self
}
pub fn uniform_2uiv(mut self, array: &'a [[u32; 2]], location: usize) -> Self {
self.uniforms
.push((UniformValue::Uniform2uiv(array), location));
self
}
pub fn uniform_3uiv(mut self, array: &'a [[u32; 3]], location: usize) -> Self {
self.uniforms
.push((UniformValue::Uniform3uiv(array), location));
self
}
pub fn uniform_4uiv(mut self, array: &'a [[u32; 4]], location: usize) -> Self {
self.uniforms
.push((UniformValue::Uniform4uiv(array), location));
self
}
pub fn uniform_matrix_2f(mut self, mat2: [f32; 4], location: usize) -> Self {
self.uniforms
.push((UniformValue::UniformMatrix2f(mat2), location));
self
}
pub fn uniform_matrix_3f(mut self, mat3: [f32; 9], location: usize) -> Self {
self.uniforms
.push((UniformValue::UniformMatrix3f(mat3), location));
self
}
pub fn uniform_matrix_4f(mut self, mat4: [f32; 16], location: usize) -> Self {
self.uniforms
.push((UniformValue::UniformMatrix4f(mat4), location));
self
}
pub fn uniform(mut self, storage: &'a Buffer, location: usize) -> Self {
self.uniform_buffers.push((storage, location));
self
}
pub fn uniform_range<T>(mut self, storage: &'a Buffer, location: usize, offset: usize, size: usize) -> Self {
self.uniform_ranges.push((
storage,
location,
offset * size_of::<T>(),
size * size_of::<T>(),
));
self
}
pub fn atomic_counter(mut self, storage: &'a MutableBuffer, location: usize) -> Self {
self.atomic_counters.push((storage, location));
self
}
pub fn barriers(mut self, barriers: MemoryBarriers) -> Self {
self.barriers = Some(barriers);
self
}
}