finish uniform names refactor

This commit is contained in:
Carter Anderson 2020-02-22 15:01:11 -08:00
parent ba1f48f743
commit 7eb99f3eb5
8 changed files with 99 additions and 67 deletions

View file

@ -45,6 +45,10 @@ See our [ROADMAP.md](ROADMAP.md) for the current list of planned features.
## Getting Started ## Getting Started
### Nightly Compiler
Bevy requires nightly rust right now. It currently uses [specialization](https://github.com/rust-lang/rfcs/blob/master/text/1210-impl-specialization.md) features, which are unstable. If specialization goes stable soon then we can go back to a stable compiler. In the meantime, we will try our best to remove specialization usage so we can go back to stable.
### Examples: ### Examples:
``` ```
@ -53,7 +57,7 @@ cargo run --example simple
### Fast Compiles ### Fast Compiles
* Bevy can be built using stable rust with default configuration (ex: ```cargo build```), but for optimal build times we recommend using a nightly compiler with the following settings: * Bevy can be built using default configuration (ex: ```cargo build```), but for optimal build times we recommend using a nightly compiler with the following settings:
* LLD Linker: ```-Clink-arg=-fuse-ld=lld``` * LLD Linker: ```-Clink-arg=-fuse-ld=lld```
* LLD will significantly speed up compile times in Bevy, but it doesn't work out of the box on some platforms / os-es. * LLD will significantly speed up compile times in Bevy, but it doesn't work out of the box on some platforms / os-es.
* See [this issue](https://github.com/rust-lang/rust/issues/39915) and [this issue](https://github.com/rust-gamedev/wg/issues/50) for more information. * See [this issue](https://github.com/rust-lang/rust/issues/39915) and [this issue](https://github.com/rust-gamedev/wg/issues/50) for more information.

View file

@ -4,7 +4,7 @@ use darling::FromMeta;
use inflector::Inflector; use inflector::Inflector;
use proc_macro::TokenStream; use proc_macro::TokenStream;
use quote::{format_ident, quote}; use quote::{format_ident, quote};
use syn::{parse_macro_input, Data, DataStruct, DeriveInput, Field, Fields, Type}; use syn::{parse_macro_input, Data, DataStruct, DeriveInput, Field, Fields};
#[proc_macro_derive(EntityArchetype)] #[proc_macro_derive(EntityArchetype)]
pub fn derive_entity_archetype(input: TokenStream) -> TokenStream { pub fn derive_entity_archetype(input: TokenStream) -> TokenStream {
@ -108,22 +108,22 @@ 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 info_ident = format_ident!("{}_UNIFORM_INFO", struct_name_screaming_snake);
let field_uniform_names_ident = format_ident!("{}_FIELD_UNIFORM_NAMES", struct_name_screaming_snake); let field_uniform_names_ident = format_ident!("{}_FIELD_UNIFORM_NAMES", 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
}); }).collect::<Vec<_>>();
let active_uniform_field_name_strings = active_uniform_fields.iter().map(|field| { let active_uniform_field_name_strings = active_uniform_fields.iter().map(|field| {
field.ident.as_ref().unwrap().to_string() field.ident.as_ref().unwrap().to_string()
}).collect::<Vec<String>>(); }).collect::<Vec<String>>();
let mut uniform_name_strings = Vec::new();
let field_uniform_names = active_uniform_field_name_strings.iter().map(|f| { let field_uniform_names = active_uniform_field_name_strings.iter().map(|f| {
let uniform = format!("{}_{}", struct_name, f); let uniform = format!("{}_{}", struct_name, f);
let texture = format!("{}_texture", uniform); let texture = format!("{}_texture", uniform);
let sampler = format!("{}_sampler", uniform); let sampler = format!("{}_sampler", uniform);
uniform_name_strings.push(uniform.clone());
quote!(bevy::render::render_graph::FieldUniformName { quote!(bevy::render::render_graph::FieldUniformName {
field: #f, field: #f,
uniform: #uniform, uniform: #uniform,
@ -132,21 +132,21 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
}) })
}); });
TokenStream::from(quote! {
let x = quote! {
const #field_uniform_names_ident: &[bevy::render::render_graph::FieldUniformName] = &[ const #field_uniform_names_ident: &[bevy::render::render_graph::FieldUniformName] = &[
#(#field_uniform_names,)* #(#field_uniform_names,)*
]; ];
impl bevy::render::render_graph::AsUniforms for #struct_name { impl bevy::render::render_graph::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_uniform_infos(&self) -> &[bevy::render::render_graph::FieldUniformName] { fn get_field_uniform_names(&self) -> &[bevy::render::render_graph::FieldUniformName] {
#field_uniform_names_ident #field_uniform_names_ident
} }
fn get_field_bind_type(&self, name: &str) -> Option<bevy::render::render_graph::FieldBindType> { fn get_field_bind_type(&self, name: &str) -> Option<bevy::render::render_graph::FieldBindType> {
use bevy::render::render_graph::AsFieldBindType;
match name { match name {
#(#active_uniform_field_name_strings => #active_uniform_field_names.get_field_bind_type(),)* #(#active_uniform_field_name_strings => Some(self.#active_uniform_field_names.get_field_bind_type()),)*
_ => None, _ => None,
} }
} }
@ -155,7 +155,7 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
fn get_uniform_bytes(&self, name: &str) -> Option<Vec<u8>> { fn get_uniform_bytes(&self, name: &str) -> Option<Vec<u8>> {
use bevy::core::bytes::GetBytes; use bevy::core::bytes::GetBytes;
match name { match name {
// #(#uniform_name_uniform_info => Some(self.#get_uniform_bytes_field_name.get_bytes()),)* #(#uniform_name_strings => Some(self.#active_uniform_field_names.get_bytes()),)*
_ => None, _ => None,
} }
} }
@ -174,9 +174,7 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
.collect::<Vec<String>>()) .collect::<Vec<String>>())
} }
} }
}; })
eprintln!("{}", x.to_string());
TokenStream::from(x)
} }
#[proc_macro_derive(RegisterAppPlugin)] #[proc_macro_derive(RegisterAppPlugin)]

View file

@ -1,5 +1,8 @@
use crate::{
asset::{Texture, Handle},
math::Vec4,
};
use zerocopy::AsBytes; use zerocopy::AsBytes;
use crate::math::Vec4;
pub trait GetBytes { pub trait GetBytes {
fn get_bytes(&self) -> Vec<u8>; fn get_bytes(&self) -> Vec<u8>;
@ -27,3 +30,13 @@ impl GetBytes for Vec4 {
None None
} }
} }
impl GetBytes for Handle<Texture> {
fn get_bytes(&self) -> Vec<u8> {
Vec::new()
}
fn get_bytes_ref(&self) -> Option<&[u8]> {
None
}
}

View file

@ -1,3 +1,4 @@
#![feature(specialization)]
pub mod app; pub mod app;
pub mod asset; pub mod asset;
pub mod core; pub mod core;

View file

@ -30,7 +30,6 @@ impl ShaderDefSuffixProvider for ColorSource {
} }
} }
impl GetBytes for ColorSource { impl GetBytes for ColorSource {
fn get_bytes(&self) -> Vec<u8> { fn get_bytes(&self) -> Vec<u8> {
match *self { match *self {

View file

@ -1,8 +1,9 @@
use crate::render::render_graph::{ use crate::render::render_graph::{
AsUniforms, BindType, DynamicUniformBufferInfo, Renderable, Renderer, ResourceProvider, AsUniforms, BindType, DynamicUniformBufferInfo, Renderable, Renderer, ResourceProvider,
UniformInfoIter,
}; };
use legion::prelude::*; use legion::prelude::*;
use std::marker::PhantomData; use std::{marker::PhantomData, ops::Deref};
pub struct UniformResourceProvider<T> pub struct UniformResourceProvider<T>
where where
@ -48,9 +49,8 @@ where
let mut counts = Vec::new(); let mut counts = Vec::new();
for (uniforms, _renderable) in query.iter(world) { for (uniforms, _renderable) in query.iter(world) {
for (i, uniform_info) in uniforms let field_uniform_names = uniforms.get_field_uniform_names();
.get_uniform_infos() for (i, uniform_info) in UniformInfoIter::new(field_uniform_names, uniforms.deref())
.iter()
.filter(|u| { .filter(|u| {
if let BindType::Uniform { .. } = u.bind_type { if let BindType::Uniform { .. } = u.bind_type {
true true

View file

@ -1,10 +1,16 @@
use crate::render::{color::ColorSource, render_graph::{BindType, TextureViewDimension}}; use crate::{
math::Vec4,
render::{
color::ColorSource,
render_graph::{BindType, TextureViewDimension},
}, core::GetBytes,
};
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 // TODO: add ability to specify specific pipeline for uniforms
pub trait AsUniforms { pub trait AsUniforms {
fn get_uniform_infos(&self) -> &[FieldUniformName]; fn get_field_uniform_names(&self) -> &[FieldUniformName];
fn get_uniform_bytes(&self, name: &str) -> Option<Vec<u8>>; fn get_uniform_bytes(&self, name: &str) -> Option<Vec<u8>>;
fn get_shader_defs(&self) -> Option<Vec<String>>; fn get_shader_defs(&self) -> Option<Vec<String>>;
fn get_field_bind_type(&self, name: &str) -> Option<FieldBindType>; fn get_field_bind_type(&self, name: &str) -> Option<FieldBindType>;
@ -30,27 +36,31 @@ pub enum FieldBindType {
Texture, Texture,
} }
pub struct UniformInfoIter<'a, T: AsUniforms> { pub struct UniformInfoIter<'a, 'b, T: AsUniforms> {
pub field_uniform_names: &'a [FieldUniformName], pub field_uniform_names: &'a [FieldUniformName],
pub uniforms: &'a T, pub uniforms: &'b T,
pub index: usize, pub index: usize,
pub add_sampler: bool, pub add_sampler: bool,
} }
impl<'a, T> UniformInfoIter<'a, T> where T: AsUniforms { impl<'a, 'b, T> UniformInfoIter<'a, 'b, T>
pub fn new(field_uniform_names: &'a [FieldUniformName], uniforms: &'a T) -> Self { where
UniformInfoIter { T: AsUniforms,
field_uniform_names, {
uniforms, pub fn new(field_uniform_names: &'a [FieldUniformName], uniforms: &'b T) -> Self {
index: 0, UniformInfoIter {
add_sampler: false, field_uniform_names,
} uniforms,
index: 0,
add_sampler: false,
}
} }
} }
impl<'a, T> Iterator for UniformInfoIter<'a, T> where T: AsUniforms { impl<'a, 'b, T> Iterator for UniformInfoIter<'a, 'b, T>
where
T: AsUniforms,
{
type Item = UniformInfo<'a>; type Item = UniformInfo<'a>;
fn next(&mut self) -> Option<Self::Item> { fn next(&mut self) -> Option<Self::Item> {
if self.add_sampler { if self.add_sampler {
@ -65,8 +75,11 @@ impl<'a, T> Iterator for UniformInfoIter<'a, T> where T: AsUniforms {
} else { } else {
let index = self.index; let index = self.index;
self.index += 1; self.index += 1;
let field_uniform_name = self.field_uniform_names[index]; let ref field_uniform_name = self.field_uniform_names[index];
let bind_type = self.uniforms.get_field_bind_type(field_uniform_name.field).unwrap(); let bind_type = self
.uniforms
.get_field_bind_type(field_uniform_name.field)
.unwrap();
Some(match bind_type { Some(match bind_type {
FieldBindType::Uniform => UniformInfo { FieldBindType::Uniform => UniformInfo {
bind_type: BindType::Uniform { bind_type: BindType::Uniform {
@ -89,22 +102,21 @@ impl<'a, T> Iterator for UniformInfoIter<'a, T> where T: AsUniforms {
} }
} }
} }
} }
pub struct FieldUniformName { pub struct FieldUniformName {
field: &'static str, pub field: &'static str,
uniform: &'static str, pub uniform: &'static str,
texture: &'static str, pub texture: &'static str,
sampler: &'static str, pub sampler: &'static str,
} }
pub trait AsFieldBindType { pub trait AsFieldBindType {
fn get_field_uniform_type(&self) -> FieldBindType; fn get_field_bind_type(&self) -> FieldBindType;
} }
impl AsFieldBindType for ColorSource { impl AsFieldBindType for ColorSource {
fn get_field_uniform_type(&self) -> FieldBindType { fn get_field_bind_type(&self) -> FieldBindType {
match *self { match *self {
ColorSource::Texture(_) => FieldBindType::Texture, ColorSource::Texture(_) => FieldBindType::Texture,
ColorSource::Color(_) => FieldBindType::Uniform, ColorSource::Color(_) => FieldBindType::Uniform,
@ -112,14 +124,21 @@ impl AsFieldBindType for ColorSource {
} }
} }
// impl<T> AsFieldBindType for T default impl<T> AsFieldBindType for T
// where where
// T: GetBytes, T: GetBytes,
// { {
// fn get_field_uniform_type(&self) -> FieldBindType { fn get_field_bind_type(&self) -> FieldBindType {
// FieldBindType::Uniform FieldBindType::Uniform
// } }
// } }
impl AsFieldBindType for Vec4
{
fn get_field_bind_type(&self) -> FieldBindType {
FieldBindType::Uniform
}
}
pub struct UniformInfo<'a> { pub struct UniformInfo<'a> {
pub name: &'a str, pub name: &'a str,
@ -142,4 +161,4 @@ impl DynamicUniformBufferInfo {
offsets: HashMap::new(), offsets: HashMap::new(),
} }
} }
} }

View file

@ -1,22 +1,17 @@
use crate::render::render_graph::{ use crate::render::render_graph::{uniform::AsUniforms, FieldBindType, FieldUniformName};
uniform::{AsUniforms, UniformInfo},
BindType, FieldBindType,
};
use zerocopy::AsBytes; use zerocopy::AsBytes;
const LOCAL_TO_WORLD_UNIFORM_INFO: &[UniformInfo] = &[UniformInfo { const LOCAL_TO_WORLD_FIELD_UNIFORM_NAMES: &[FieldUniformName] = &[FieldUniformName {
name: "Object", field: "object",
bind_type: BindType::Uniform { uniform: "Object",
dynamic: false, texture: "",
// TODO: maybe fill this in with properties (vec.push cant be const though) sampler: "",
properties: Vec::new(),
},
}]; }];
impl AsUniforms for bevy_transform::prelude::LocalToWorld { impl AsUniforms for bevy_transform::prelude::LocalToWorld {
fn get_uniform_infos(&self) -> &[UniformInfo] { fn get_field_uniform_names(&self) -> &[FieldUniformName] {
LOCAL_TO_WORLD_UNIFORM_INFO LOCAL_TO_WORLD_FIELD_UNIFORM_NAMES
} }
fn get_uniform_bytes(&self, name: &str) -> Option<Vec<u8>> { fn get_uniform_bytes(&self, name: &str) -> Option<Vec<u8>> {
@ -29,7 +24,10 @@ impl AsUniforms for bevy_transform::prelude::LocalToWorld {
fn get_shader_defs(&self) -> Option<Vec<String>> { fn get_shader_defs(&self) -> Option<Vec<String>> {
None None
} }
fn get_field_bind_type(&self, name: &str) -> FieldBindType { fn get_field_bind_type(&self, name: &str) -> Option<FieldBindType> {
FieldBindType::Uniform match name {
"object" => Some(FieldBindType::Uniform),
_ => None,
}
} }
} }