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
### 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:
```
@ -53,7 +57,7 @@ cargo run --example simple
### 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 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.

View file

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

View file

@ -1,5 +1,8 @@
use crate::{
asset::{Texture, Handle},
math::Vec4,
};
use zerocopy::AsBytes;
use crate::math::Vec4;
pub trait GetBytes {
fn get_bytes(&self) -> Vec<u8>;
@ -27,3 +30,13 @@ impl GetBytes for Vec4 {
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 asset;
pub mod core;

View file

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

View file

@ -1,8 +1,9 @@
use crate::render::render_graph::{
AsUniforms, BindType, DynamicUniformBufferInfo, Renderable, Renderer, ResourceProvider,
UniformInfoIter,
};
use legion::prelude::*;
use std::marker::PhantomData;
use std::{marker::PhantomData, ops::Deref};
pub struct UniformResourceProvider<T>
where
@ -48,9 +49,8 @@ where
let mut counts = Vec::new();
for (uniforms, _renderable) in query.iter(world) {
for (i, uniform_info) in uniforms
.get_uniform_infos()
.iter()
let field_uniform_names = uniforms.get_field_uniform_names();
for (i, uniform_info) in UniformInfoIter::new(field_uniform_names, uniforms.deref())
.filter(|u| {
if let BindType::Uniform { .. } = u.bind_type {
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 std::collections::HashMap;
// TODO: add ability to specify specific pipeline for uniforms
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_shader_defs(&self) -> Option<Vec<String>>;
fn get_field_bind_type(&self, name: &str) -> Option<FieldBindType>;
@ -30,27 +36,31 @@ pub enum FieldBindType {
Texture,
}
pub struct UniformInfoIter<'a, T: AsUniforms> {
pub struct UniformInfoIter<'a, 'b, T: AsUniforms> {
pub field_uniform_names: &'a [FieldUniformName],
pub uniforms: &'a T,
pub uniforms: &'b 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, 'b, T> UniformInfoIter<'a, 'b, T>
where
T: AsUniforms,
{
pub fn new(field_uniform_names: &'a [FieldUniformName], uniforms: &'b T) -> Self {
UniformInfoIter {
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>;
fn next(&mut self) -> Option<Self::Item> {
if self.add_sampler {
@ -65,8 +75,11 @@ impl<'a, T> Iterator for UniformInfoIter<'a, T> where T: AsUniforms {
} 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();
let ref 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 {
@ -89,22 +102,21 @@ impl<'a, T> Iterator for UniformInfoIter<'a, T> where T: AsUniforms {
}
}
}
}
pub struct FieldUniformName {
field: &'static str,
uniform: &'static str,
texture: &'static str,
sampler: &'static str,
pub field: &'static str,
pub uniform: &'static str,
pub texture: &'static str,
pub sampler: &'static str,
}
pub trait AsFieldBindType {
fn get_field_uniform_type(&self) -> FieldBindType;
fn get_field_bind_type(&self) -> FieldBindType;
}
impl AsFieldBindType for ColorSource {
fn get_field_uniform_type(&self) -> FieldBindType {
fn get_field_bind_type(&self) -> FieldBindType {
match *self {
ColorSource::Texture(_) => FieldBindType::Texture,
ColorSource::Color(_) => FieldBindType::Uniform,
@ -112,14 +124,21 @@ impl AsFieldBindType for ColorSource {
}
}
// impl<T> AsFieldBindType for T
// where
// T: GetBytes,
// {
// fn get_field_uniform_type(&self) -> FieldBindType {
// FieldBindType::Uniform
// }
// }
default impl<T> AsFieldBindType for T
where
T: GetBytes,
{
fn get_field_bind_type(&self) -> FieldBindType {
FieldBindType::Uniform
}
}
impl AsFieldBindType for Vec4
{
fn get_field_bind_type(&self) -> FieldBindType {
FieldBindType::Uniform
}
}
pub struct UniformInfo<'a> {
pub name: &'a str,

View file

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