use crate::buffer::{Buffer, BufferView, BufferViewMut};
use crate::pipeline::graphics::util::BufferDescriptor;
use crate::pipeline::graphics::{TypedVertexInputLayout, Vertex};
use staticvec::StaticVec;
pub trait VertexBuffers {
fn encode<'a>(self, context: &'a mut VertexBuffersEncodingContext)
-> VertexBuffersEncoding<'a>;
}
pub trait VertexBuffer {
fn encode(self, encoding: &mut VertexBuffersEncoding);
}
pub unsafe trait TypedVertexBuffers: VertexBuffers {
type Layout: TypedVertexInputLayout;
}
pub unsafe trait TypedVertexBuffer: VertexBuffer {
type Vertex: Vertex;
}
pub struct VertexBuffersEncodingContext(());
impl VertexBuffersEncodingContext {
pub(crate) fn new() -> Self {
VertexBuffersEncodingContext(())
}
}
pub struct VertexBuffersEncoding<'a> {
#[allow(unused)]
context: &'a mut VertexBuffersEncodingContext,
descriptors: StaticVec<BufferDescriptor, 16>,
}
impl<'a> VertexBuffersEncoding<'a> {
pub fn new(context: &'a mut VertexBuffersEncodingContext) -> Self {
VertexBuffersEncoding {
context,
descriptors: StaticVec::new(),
}
}
pub fn add_vertex_buffer<'b, V, T>(&mut self, buffer: V)
where
V: Into<BufferView<'b, [T]>>,
T: 'b,
{
self.descriptors
.push(BufferDescriptor::from_buffer_view(buffer.into()));
}
pub(crate) fn into_descriptors(self) -> StaticVec<BufferDescriptor, 16> {
self.descriptors
}
}
impl<T> VertexBuffer for Buffer<[T]> {
fn encode(self, encoding: &mut VertexBuffersEncoding) {
encoding.add_vertex_buffer(&self);
}
}
impl<'a, T> VertexBuffer for &'a Buffer<[T]> {
fn encode(self, encoding: &mut VertexBuffersEncoding) {
encoding.add_vertex_buffer(self);
}
}
impl<'a, T> VertexBuffer for &'a mut Buffer<[T]> {
fn encode(self, encoding: &mut VertexBuffersEncoding) {
encoding.add_vertex_buffer(self);
}
}
unsafe impl<T> TypedVertexBuffer for Buffer<[T]>
where
T: Vertex,
{
type Vertex = T;
}
unsafe impl<'a, T> TypedVertexBuffer for &'a Buffer<[T]>
where
T: Vertex,
{
type Vertex = T;
}
unsafe impl<'a, T> TypedVertexBuffer for &'a mut Buffer<[T]>
where
T: Vertex,
{
type Vertex = T;
}
impl<'a, T> VertexBuffer for BufferView<'a, [T]> {
fn encode(self, encoding: &mut VertexBuffersEncoding) {
encoding.add_vertex_buffer(self);
}
}
impl<'a, 'b, T> VertexBuffer for &'a BufferView<'b, [T]> {
fn encode(self, encoding: &mut VertexBuffersEncoding) {
encoding.add_vertex_buffer(*self);
}
}
impl<'a, 'b, T> VertexBuffer for &'a mut BufferView<'b, [T]> {
fn encode(self, encoding: &mut VertexBuffersEncoding) {
encoding.add_vertex_buffer(*self);
}
}
impl<'a, T> VertexBuffer for BufferViewMut<'a, [T]> {
fn encode(self, encoding: &mut VertexBuffersEncoding) {
encoding.add_vertex_buffer(*self);
}
}
impl<'a, 'b, T> VertexBuffer for &'a BufferViewMut<'b, [T]> {
fn encode(self, encoding: &mut VertexBuffersEncoding) {
encoding.add_vertex_buffer(**self);
}
}
impl<'a, 'b, T> VertexBuffer for &'a mut BufferViewMut<'b, [T]> {
fn encode(self, encoding: &mut VertexBuffersEncoding) {
encoding.add_vertex_buffer(**self);
}
}
unsafe impl<'a, T> TypedVertexBuffer for BufferView<'a, [T]>
where
T: Vertex,
{
type Vertex = T;
}
unsafe impl<'a, 'b, T> TypedVertexBuffer for &'a BufferView<'b, [T]>
where
T: Vertex,
{
type Vertex = T;
}
unsafe impl<'a, 'b, T> TypedVertexBuffer for &'a mut BufferView<'b, [T]>
where
T: Vertex,
{
type Vertex = T;
}
unsafe impl<'a, T> TypedVertexBuffer for BufferViewMut<'a, [T]>
where
T: Vertex,
{
type Vertex = T;
}
unsafe impl<'a, 'b, T> TypedVertexBuffer for &'a BufferViewMut<'b, [T]>
where
T: Vertex,
{
type Vertex = T;
}
unsafe impl<'a, 'b, T> TypedVertexBuffer for &'a mut BufferViewMut<'b, [T]>
where
T: Vertex,
{
type Vertex = T;
}
macro_rules! impl_vertex_buffers {
($($T:ident),*) => {
#[allow(unused_parens)]
impl<$($T),*> VertexBuffers for ($($T),*)
where
$($T: VertexBuffer),*
{
fn encode<'a>(self, context: &'a mut VertexBuffersEncodingContext) -> VertexBuffersEncoding<'a> {
let mut encoding = VertexBuffersEncoding::new(context);
#[allow(unused_parens, non_snake_case)]
let ($($T),*) = self;
$(
$T.encode(&mut encoding);
)*
encoding
}
}
#[allow(unused_parens)]
unsafe impl<$($T),*> TypedVertexBuffers for ($($T),*)
where
$($T: TypedVertexBuffer),*
{
#[allow(unused_parens)]
type Layout = ($($T::Vertex),*);
}
}
}
impl_vertex_buffers!(T0);
impl_vertex_buffers!(T0, T1);
impl_vertex_buffers!(T0, T1, T2);
impl_vertex_buffers!(T0, T1, T2, T3);
impl_vertex_buffers!(T0, T1, T2, T3, T4);
impl_vertex_buffers!(T0, T1, T2, T3, T4, T5);
impl_vertex_buffers!(T0, T1, T2, T3, T4, T5, T6);
impl_vertex_buffers!(T0, T1, T2, T3, T4, T5, T6, T7);
impl_vertex_buffers!(T0, T1, T2, T3, T4, T5, T6, T7, T8);
impl_vertex_buffers!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9);
impl_vertex_buffers!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
impl_vertex_buffers!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
impl_vertex_buffers!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);
impl_vertex_buffers!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13);
impl_vertex_buffers!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14);
impl_vertex_buffers!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15);