mallumo-gls 0.43.0

Small low level library for modern (4.5 Core) OpenGL
Documentation
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
    }
}