pub use self::buffer::UniformBuffer;
pub use self::sampler::{SamplerWrapFunction, MagnifySamplerFilter, MinifySamplerFilter, DepthTextureComparison};
pub use self::sampler::{Sampler, SamplerBehavior};
pub use self::uniforms::{EmptyUniforms, UniformsStorage, DynamicUniforms};
pub use self::image_unit::{ImageUnitAccess, ImageUnitFormat, ImageUnitError};
pub use self::image_unit::{ImageUnit, ImageUnitBehavior};
pub use self::value::{UniformValue, UniformType};
use std::error::Error;
use std::fmt;
use crate::buffer::Content as BufferContent;
use crate::buffer::Buffer;
use crate::program;
use crate::program::BlockLayout;
mod bind;
mod buffer;
mod image_unit;
mod sampler;
mod uniforms;
mod value;
pub trait Uniforms {
fn visit_values<'a, F: FnMut(&str, UniformValue<'a>)>(&'a self, _: F);
}
#[derive(Clone, Debug)]
pub enum LayoutMismatchError {
TypeMismatch {
expected: UniformType,
obtained: UniformType,
},
LayoutMismatch {
expected: BlockLayout,
obtained: BlockLayout,
},
OffsetMismatch {
expected: usize,
obtained: usize,
},
MemberMismatch {
member: String,
err: Box<LayoutMismatchError>,
},
MissingField {
name: String,
},
}
impl Error for LayoutMismatchError {
fn source(&self) -> Option<&(dyn Error + 'static)> {
use self::LayoutMismatchError::*;
match *self {
MemberMismatch{ ref err, .. } => Some(err.as_ref()),
_ => None,
}
}
}
impl fmt::Display for LayoutMismatchError {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
use self::LayoutMismatchError::*;
let desc = match *self {
TypeMismatch { .. } =>
"There is a mismatch in the type of one element",
LayoutMismatch { .. } =>
"The expected layout is totally different from what we have",
OffsetMismatch { .. } =>
"The type of data is good, but there is a misalignment",
MemberMismatch { .. } =>
"There is a mismatch in a submember of this layout",
MissingField { .. } =>
"A field is missing in either the expected of the input data layout",
};
match *self {
TypeMismatch { ref expected, ref obtained } =>
write!(
fmt,
"{}, got: {:?}, expected: {:?}",
desc,
obtained,
expected,
),
LayoutMismatch { ref expected, ref obtained } =>
write!(
fmt,
"{}, got: {:?}, expected: {:?}",
desc,
obtained,
expected,
),
OffsetMismatch { ref expected, ref obtained } =>
write!(
fmt,
"{}, got: {}, expected: {}",
desc,
obtained,
expected,
),
MemberMismatch { ref member, ref err } =>
write!(
fmt,
"{}, {}: {}",
desc,
member,
err,
),
MissingField { ref name } =>
write!(
fmt,
"{}: {}",
desc,
name,
),
}
}
}
pub trait AsUniformValue {
fn as_uniform_value(&self) -> UniformValue<'_>;
}
impl<'a, T: ?Sized> AsUniformValue for &'a Buffer<T> where T: UniformBlock + BufferContent {
#[inline]
fn as_uniform_value(&self) -> UniformValue<'_> {
#[inline]
fn f<T: ?Sized>(block: &program::UniformBlock)
-> Result<(), LayoutMismatchError> where T: UniformBlock + BufferContent
{
T::matches(&block.layout, 0)
}
UniformValue::Block(self.as_slice_any(), f::<T>)
}
}
pub trait UniformBlock { fn matches(_: &BlockLayout, base_offset: usize) -> Result<(), LayoutMismatchError>;
fn build_layout(base_offset: usize) -> BlockLayout;
}
impl<T> UniformBlock for [T] where T: UniformBlock {
fn matches(layout: &BlockLayout, base_offset: usize)
-> Result<(), LayoutMismatchError>
{
if let BlockLayout::Struct { members } = layout {
if members.len() == 1 {
return Self::matches(&members[0].1, base_offset);
}
}
if let BlockLayout::DynamicSizedArray { content } = layout {
<T as UniformBlock>::matches(content, base_offset)
.map_err(|err| {
LayoutMismatchError::MemberMismatch {
member: "<dynamic array content>".to_owned(),
err: Box::new(err),
}
})
} else if let BlockLayout::Array { content, .. } = layout {
<T as UniformBlock>::matches(content, base_offset)
.map_err(|err| {
LayoutMismatchError::MemberMismatch {
member: "<dynamic array content>".to_owned(),
err: Box::new(err),
}
})
} else {
Err(LayoutMismatchError::LayoutMismatch {
expected: layout.clone(),
obtained: <Self as UniformBlock>::build_layout(base_offset),
})
}
}
#[inline]
fn build_layout(base_offset: usize) -> BlockLayout {
BlockLayout::DynamicSizedArray {
content: Box::new(<T as UniformBlock>::build_layout(base_offset)),
}
}
}
macro_rules! impl_uniform_block_array {
($len:expr) => (
impl<T> UniformBlock for [T; $len] where T: UniformBlock {
fn matches(layout: &program::BlockLayout, base_offset: usize)
-> Result<(), LayoutMismatchError>
{
if let &BlockLayout::Struct { ref members } = layout {
if members.len() == 1 {
return Self::matches(&members[0].1, base_offset);
}
}
if let &BlockLayout::Array { ref content, length } = layout {
if let Err(err) = T::matches(content, base_offset) {
return Err(LayoutMismatchError::MemberMismatch {
member: "<array content>".to_owned(),
err: Box::new(err),
});
}
if length != $len {
return Err(LayoutMismatchError::LayoutMismatch {
expected: layout.clone(),
obtained: Self::build_layout(base_offset),
});
}
Ok(())
} else {
Err(LayoutMismatchError::LayoutMismatch {
expected: layout.clone(),
obtained: Self::build_layout(base_offset),
})
}
}
#[inline]
fn build_layout(base_offset: usize) -> program::BlockLayout {
BlockLayout::Array {
content: Box::new(T::build_layout(base_offset)),
length: $len,
}
}
}
);
}
impl_uniform_block_array!(5);
impl_uniform_block_array!(6);
impl_uniform_block_array!(7);
impl_uniform_block_array!(8);
impl_uniform_block_array!(9);
impl_uniform_block_array!(10);
impl_uniform_block_array!(11);
impl_uniform_block_array!(12);
impl_uniform_block_array!(13);
impl_uniform_block_array!(14);
impl_uniform_block_array!(15);
impl_uniform_block_array!(16);
impl_uniform_block_array!(17);
impl_uniform_block_array!(18);
impl_uniform_block_array!(19);
impl_uniform_block_array!(20);
impl_uniform_block_array!(21);
impl_uniform_block_array!(22);
impl_uniform_block_array!(23);
impl_uniform_block_array!(24);
impl_uniform_block_array!(25);
impl_uniform_block_array!(26);
impl_uniform_block_array!(27);
impl_uniform_block_array!(28);
impl_uniform_block_array!(29);
impl_uniform_block_array!(30);
impl_uniform_block_array!(31);
impl_uniform_block_array!(32);
impl_uniform_block_array!(64);
impl_uniform_block_array!(128);
impl_uniform_block_array!(256);
impl_uniform_block_array!(512);
impl_uniform_block_array!(1024);
impl_uniform_block_array!(2048);
impl_uniform_block_array!(4096);