use crate::buffer::{Buffer, BufferViewMut};
use crate::pipeline::graphics::util::BufferDescriptor;
use crate::pipeline::graphics::{TransformFeedback, TypedTransformFeedbackLayout};
use staticvec::StaticVec;
pub trait TransformFeedbackBuffers {
fn encode<'a>(
self,
context: &'a mut TransformFeedbackBuffersEncodingContext,
) -> TransformFeedbackBuffersEncoding<'a>;
}
pub trait TransformFeedbackBuffer {
fn encode(self, encoding: &mut TransformFeedbackBuffersEncoding);
}
pub unsafe trait TypedTransformFeedbackBuffers: TransformFeedbackBuffers {
type Layout: TypedTransformFeedbackLayout;
}
pub unsafe trait TypedTransformFeedbackBuffer: TransformFeedbackBuffer {
type TransformFeedback: TransformFeedback;
}
pub struct TransformFeedbackBuffersEncodingContext(());
impl TransformFeedbackBuffersEncodingContext {
pub(crate) fn new() -> Self {
TransformFeedbackBuffersEncodingContext(())
}
}
pub struct TransformFeedbackBuffersEncoding<'a> {
#[allow(unused)]
context: &'a mut TransformFeedbackBuffersEncodingContext,
descriptors: StaticVec<BufferDescriptor, 16>,
}
impl<'a> TransformFeedbackBuffersEncoding<'a> {
pub fn new(context: &'a mut TransformFeedbackBuffersEncodingContext) -> Self {
TransformFeedbackBuffersEncoding {
context,
descriptors: StaticVec::new(),
}
}
pub fn add_feedback_buffer<'b, V, T>(&mut self, buffer: V)
where
V: Into<BufferViewMut<'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<'a, T> TransformFeedbackBuffer for &'a mut Buffer<[T]> {
fn encode(self, encoding: &mut TransformFeedbackBuffersEncoding) {
encoding.add_feedback_buffer(self);
}
}
unsafe impl<'a, T> TypedTransformFeedbackBuffer for &'a mut Buffer<[T]>
where
T: TransformFeedback,
{
type TransformFeedback = T;
}
impl<'a, T> TransformFeedbackBuffer for BufferViewMut<'a, [T]> {
fn encode(self, encoding: &mut TransformFeedbackBuffersEncoding) {
encoding.add_feedback_buffer(self);
}
}
unsafe impl<'a, T> TypedTransformFeedbackBuffer for BufferViewMut<'a, [T]>
where
T: TransformFeedback,
{
type TransformFeedback = T;
}
macro_rules! impl_transform_feedback_buffers {
($($T:ident),*) => {
#[allow(unused_parens)]
impl<$($T),*> TransformFeedbackBuffers for ($($T),*)
where
$($T: TransformFeedbackBuffer),*
{
fn encode<'a>(
self,
context: &'a mut TransformFeedbackBuffersEncodingContext
) -> TransformFeedbackBuffersEncoding<'a> {
let mut encoding = TransformFeedbackBuffersEncoding::new(context);
#[allow(unused_parens, non_snake_case)]
let ($($T),*) = self;
$(
$T.encode(&mut encoding);
)*
encoding
}
}
#[allow(unused_parens)]
unsafe impl<$($T),*> TypedTransformFeedbackBuffers for ($($T),*)
where
$($T: TypedTransformFeedbackBuffer),*
{
#[allow(unused_parens)]
type Layout = ($($T::TransformFeedback),*);
}
}
}
impl_transform_feedback_buffers!(T0);
impl_transform_feedback_buffers!(T0, T1);
impl_transform_feedback_buffers!(T0, T1, T2);
impl_transform_feedback_buffers!(T0, T1, T2, T3);
impl_transform_feedback_buffers!(T0, T1, T2, T3, T4);
impl_transform_feedback_buffers!(T0, T1, T2, T3, T4, T5);
impl_transform_feedback_buffers!(T0, T1, T2, T3, T4, T5, T6);
impl_transform_feedback_buffers!(T0, T1, T2, T3, T4, T5, T6, T7);
impl_transform_feedback_buffers!(T0, T1, T2, T3, T4, T5, T6, T7, T8);
impl_transform_feedback_buffers!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9);
impl_transform_feedback_buffers!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10);
impl_transform_feedback_buffers!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11);
impl_transform_feedback_buffers!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12);
impl_transform_feedback_buffers!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13);
impl_transform_feedback_buffers!(T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14);
impl_transform_feedback_buffers!(
T0, T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15
);