This commit is contained in:
Carter Anderson 2020-03-15 01:12:56 -07:00
parent 4d92ef0119
commit 1332630fa3
5 changed files with 41 additions and 39 deletions

View file

@ -108,7 +108,7 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
let struct_name = &ast.ident; let struct_name = &ast.ident;
let struct_name_screaming_snake = struct_name.to_string().to_screaming_snake_case(); let struct_name_screaming_snake = struct_name.to_string().to_screaming_snake_case();
let field_uniform_names_ident = format_ident!("{}_FIELD_UNIFORM_NAMES", struct_name_screaming_snake); let field_infos_ident = format_ident!("{}_FIELD_INFO", struct_name_screaming_snake);
let active_uniform_field_names = active_uniform_fields.iter().map(|field| { let active_uniform_field_names = active_uniform_fields.iter().map(|field| {
&field.ident &field.ident
@ -121,7 +121,7 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
let mut uniform_name_strings = Vec::new(); let mut uniform_name_strings = Vec::new();
let mut texture_and_sampler_name_strings = Vec::new(); let mut texture_and_sampler_name_strings = Vec::new();
let mut texture_and_sampler_name_idents = Vec::new(); let mut texture_and_sampler_name_idents = Vec::new();
let field_uniform_names = active_uniform_fields.iter().map(|f| { let field_infos = active_uniform_fields.iter().map(|f| {
let field_name = f.ident.as_ref().unwrap().to_string(); let field_name = f.ident.as_ref().unwrap().to_string();
let uniform = format!("{}_{}", struct_name, field_name); let uniform = format!("{}_{}", struct_name, field_name);
let texture = format!("{}_texture", uniform); let texture = format!("{}_texture", uniform);
@ -131,23 +131,24 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
texture_and_sampler_name_strings.push(sampler.clone()); texture_and_sampler_name_strings.push(sampler.clone());
texture_and_sampler_name_idents.push(f.ident.clone()); texture_and_sampler_name_idents.push(f.ident.clone());
texture_and_sampler_name_idents.push(f.ident.clone()); texture_and_sampler_name_idents.push(f.ident.clone());
quote!(bevy::render::shader::FieldUniformName { quote!(bevy::render::shader::FieldInfo {
field: #field_name, name: #field_name,
uniform: #uniform, uniform_name: #uniform,
texture: #texture, texture_name: #texture,
sampler: #sampler, sampler_name: #sampler,
is_vertex_buffer_member: false,
}) })
}); });
TokenStream::from(quote! { TokenStream::from(quote! {
const #field_uniform_names_ident: &[bevy::render::shader::FieldUniformName] = &[ const #field_infos_ident: &[bevy::render::shader::FieldInfo] = &[
#(#field_uniform_names,)* #(#field_infos,)*
]; ];
impl bevy::render::shader::AsUniforms for #struct_name { impl bevy::render::shader::AsUniforms for #struct_name {
// TODO: max this an iterator that feeds on field_uniform_names_ident // TODO: max this an iterator that feeds on field_uniform_names_ident
fn get_field_uniform_names(&self) -> &[bevy::render::shader::FieldUniformName] { fn get_field_infos(&self) -> &[bevy::render::shader::FieldInfo] {
#field_uniform_names_ident #field_infos_ident
} }
fn get_field_bind_type(&self, name: &str) -> Option<bevy::render::shader::FieldBindType> { fn get_field_bind_type(&self, name: &str) -> Option<bevy::render::shader::FieldBindType> {

View file

@ -9,8 +9,8 @@ pub use crate::{
pipeline::PipelineDescriptor, pipeline::PipelineDescriptor,
render_resource::{resource_name, resource_providers::UniformResourceProvider}, render_resource::{resource_name, resource_providers::UniformResourceProvider},
shader::{uniforms::StandardMaterial, Shader, ShaderDefSuffixProvider, ShaderStage}, shader::{uniforms::StandardMaterial, Shader, ShaderDefSuffixProvider, ShaderStage},
ActiveCamera, ActiveCamera2d, Camera, CameraType, Color, ColorSource, Light, texture::{Texture, TextureType},
Renderable, ActiveCamera, ActiveCamera2d, Camera, CameraType, Color, ColorSource, Light, Renderable,
}, },
ui::{Anchors, Margins, Node}, ui::{Anchors, Margins, Node},
}; };

View file

@ -67,8 +67,8 @@ where
} }
for (entity, (uniforms, _renderable)) in query.iter_entities(world) { for (entity, (uniforms, _renderable)) in query.iter_entities(world) {
let field_uniform_names = uniforms.get_field_uniform_names(); let field_infos = uniforms.get_field_infos();
for uniform_info in UniformInfoIter::new(field_uniform_names, uniforms.deref()) { for uniform_info in UniformInfoIter::new(field_infos, uniforms.deref()) {
match uniform_info.bind_type { match uniform_info.bind_type {
BindType::Uniform { .. } => { BindType::Uniform { .. } => {
// only add the first time a uniform info is processed // only add the first time a uniform info is processed

View file

@ -10,9 +10,8 @@ use crate::{
use legion::prelude::Entity; use legion::prelude::Entity;
use std::collections::HashMap; use std::collections::HashMap;
// TODO: add ability to specify specific pipeline for uniforms
pub trait AsUniforms { pub trait AsUniforms {
fn get_field_uniform_names(&self) -> &[FieldUniformName]; fn get_field_infos(&self) -> &[FieldInfo];
fn get_uniform_bytes(&self, name: &str) -> Option<Vec<u8>>; fn get_uniform_bytes(&self, name: &str) -> Option<Vec<u8>>;
fn get_uniform_texture(&self, name: &str) -> Option<Handle<Texture>>; fn get_uniform_texture(&self, name: &str) -> Option<Handle<Texture>>;
fn get_shader_defs(&self) -> Option<Vec<String>>; fn get_shader_defs(&self) -> Option<Vec<String>>;
@ -39,7 +38,7 @@ pub enum FieldBindType {
} }
pub struct UniformInfoIter<'a, 'b, T: AsUniforms> { pub struct UniformInfoIter<'a, 'b, T: AsUniforms> {
pub field_uniform_names: &'a [FieldUniformName], pub field_infos: &'a [FieldInfo],
pub uniforms: &'b T, pub uniforms: &'b T,
pub index: usize, pub index: usize,
pub add_sampler: bool, pub add_sampler: bool,
@ -49,9 +48,9 @@ impl<'a, 'b, T> UniformInfoIter<'a, 'b, T>
where where
T: AsUniforms, T: AsUniforms,
{ {
pub fn new(field_uniform_names: &'a [FieldUniformName], uniforms: &'b T) -> Self { pub fn new(field_infos: &'a [FieldInfo], uniforms: &'b T) -> Self {
UniformInfoIter { UniformInfoIter {
field_uniform_names, field_infos,
uniforms, uniforms,
index: 0, index: 0,
add_sampler: false, add_sampler: false,
@ -68,19 +67,19 @@ where
if self.add_sampler { if self.add_sampler {
self.add_sampler = false; self.add_sampler = false;
Some(UniformInfo { Some(UniformInfo {
name: self.field_uniform_names[self.index - 1].sampler, name: self.field_infos[self.index - 1].sampler_name,
bind_type: BindType::Sampler, bind_type: BindType::Sampler,
}) })
} else { } else {
if self.index == self.field_uniform_names.len() { if self.index == self.field_infos.len() {
None None
} else { } else {
let index = self.index; let index = self.index;
self.index += 1; self.index += 1;
let ref field_uniform_name = self.field_uniform_names[index]; let ref field_info = self.field_infos[index];
let bind_type = self let bind_type = self
.uniforms .uniforms
.get_field_bind_type(field_uniform_name.field) .get_field_bind_type(field_info.name)
.unwrap(); .unwrap();
Some(match bind_type { Some(match bind_type {
FieldBindType::Uniform => UniformInfo { FieldBindType::Uniform => UniformInfo {
@ -88,7 +87,7 @@ where
dynamic: false, dynamic: false,
properties: Vec::new(), properties: Vec::new(),
}, },
name: field_uniform_name.uniform, name: field_info.uniform_name,
}, },
FieldBindType::Texture => { FieldBindType::Texture => {
self.add_sampler = true; self.add_sampler = true;
@ -97,7 +96,7 @@ where
dimension: TextureViewDimension::D2, dimension: TextureViewDimension::D2,
multisampled: false, multisampled: false,
}, },
name: field_uniform_name.texture, name: field_info.texture_name,
} }
} }
}) })
@ -106,11 +105,12 @@ where
} }
} }
pub struct FieldUniformName { pub struct FieldInfo {
pub field: &'static str, pub name: &'static str,
pub uniform: &'static str, pub uniform_name: &'static str,
pub texture: &'static str, pub texture_name: &'static str,
pub sampler: &'static str, pub sampler_name: &'static str,
pub is_vertex_buffer_member: bool,
} }
pub trait AsFieldBindType { pub trait AsFieldBindType {

View file

@ -1,23 +1,24 @@
use crate::{ use crate::{
asset::Handle, asset::Handle,
render::{ render::{
shader::{AsUniforms, FieldBindType, FieldUniformName}, shader::{AsUniforms, FieldBindType, FieldInfo},
texture::Texture, texture::Texture,
}, },
}; };
use zerocopy::AsBytes; use zerocopy::AsBytes;
const LOCAL_TO_WORLD_FIELD_UNIFORM_NAMES: &[FieldUniformName] = &[FieldUniformName { const LOCAL_TO_WORLD_FIELD_INFOS: &[FieldInfo] = &[FieldInfo {
field: "object", name: "object",
uniform: "Object", uniform_name: "Object",
texture: "", texture_name: "",
sampler: "", sampler_name: "",
is_vertex_buffer_member: false,
}]; }];
impl AsUniforms for bevy_transform::prelude::LocalToWorld { impl AsUniforms for bevy_transform::prelude::LocalToWorld {
fn get_field_uniform_names(&self) -> &[FieldUniformName] { fn get_field_infos(&self) -> &[FieldInfo] {
LOCAL_TO_WORLD_FIELD_UNIFORM_NAMES LOCAL_TO_WORLD_FIELD_INFOS
} }
fn get_uniform_bytes(&self, name: &str) -> Option<Vec<u8>> { fn get_uniform_bytes(&self, name: &str) -> Option<Vec<u8>> {