bevy/src/render/render_graph/uniform.rs
2020-02-22 12:42:40 -08:00

146 lines
4.1 KiB
Rust

use crate::render::{color::ColorSource, render_graph::{BindType, TextureViewDimension}};
use legion::prelude::Entity;
use std::collections::HashMap;
// TODO: add ability to specify specific pipeline for uniforms
pub trait AsUniforms {
fn get_uniform_infos(&self) -> &[FieldUniformName];
fn get_uniform_bytes(&self, name: &str) -> Option<Vec<u8>>;
fn get_shader_defs(&self) -> Option<Vec<String>>;
fn get_field_bind_type(&self, name: &str) -> Option<FieldBindType>;
// TODO: support zero-copy uniforms
// fn get_uniform_bytes_ref(&self, name: &str) -> Option<&[u8]>;
}
pub trait ShaderDefSuffixProvider {
fn get_shader_def(&self) -> Option<&'static str>;
}
impl ShaderDefSuffixProvider for bool {
fn get_shader_def(&self) -> Option<&'static str> {
match *self {
true => Some(""),
false => None,
}
}
}
pub enum FieldBindType {
Uniform,
Texture,
}
pub struct UniformInfoIter<'a, T: AsUniforms> {
pub field_uniform_names: &'a [FieldUniformName],
pub uniforms: &'a T,
pub index: usize,
pub add_sampler: bool,
}
impl<'a, T> UniformInfoIter<'a, T> where T: AsUniforms {
pub fn new(field_uniform_names: &'a [FieldUniformName], uniforms: &'a T) -> Self {
UniformInfoIter {
field_uniform_names,
uniforms,
index: 0,
add_sampler: false,
}
}
}
impl<'a, T> Iterator for UniformInfoIter<'a, T> where T: AsUniforms {
type Item = UniformInfo<'a>;
fn next(&mut self) -> Option<Self::Item> {
if self.add_sampler {
self.add_sampler = false;
Some(UniformInfo {
name: self.field_uniform_names[self.index - 1].sampler,
bind_type: BindType::Sampler,
})
} else {
if self.index == self.field_uniform_names.len() {
None
} else {
let index = self.index;
self.index += 1;
let field_uniform_name = self.field_uniform_names[index];
let bind_type = self.uniforms.get_field_bind_type(field_uniform_name.field).unwrap();
Some(match bind_type {
FieldBindType::Uniform => UniformInfo {
bind_type: BindType::Uniform {
dynamic: false,
properties: Vec::new(),
},
name: field_uniform_name.uniform,
},
FieldBindType::Texture => {
self.add_sampler = true;
UniformInfo {
bind_type: BindType::SampledTexture {
dimension: TextureViewDimension::D2,
multisampled: false,
},
name: field_uniform_name.texture,
}
}
})
}
}
}
}
pub struct FieldUniformName {
field: &'static str,
uniform: &'static str,
texture: &'static str,
sampler: &'static str,
}
pub trait AsFieldBindType {
fn get_field_uniform_type(&self) -> FieldBindType;
}
impl AsFieldBindType for ColorSource {
fn get_field_uniform_type(&self) -> FieldBindType {
match *self {
ColorSource::Texture(_) => FieldBindType::Texture,
ColorSource::Color(_) => FieldBindType::Uniform,
}
}
}
// impl<T> AsFieldBindType for T
// where
// T: GetBytes,
// {
// fn get_field_uniform_type(&self) -> FieldBindType {
// FieldBindType::Uniform
// }
// }
pub struct UniformInfo<'a> {
pub name: &'a str,
pub bind_type: BindType,
}
pub struct DynamicUniformBufferInfo {
pub indices: HashMap<usize, Entity>,
pub offsets: HashMap<Entity, u64>,
pub capacity: u64,
pub count: u64,
}
impl DynamicUniformBufferInfo {
pub fn new() -> Self {
DynamicUniformBufferInfo {
capacity: 0,
count: 0,
indices: HashMap::new(),
offsets: HashMap::new(),
}
}
}