mirror of
https://github.com/bevyengine/bevy
synced 2024-11-22 04:33:37 +00:00
finish uniform names refactor
This commit is contained in:
parent
ba1f48f743
commit
7eb99f3eb5
8 changed files with 99 additions and 67 deletions
|
@ -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.
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
#![feature(specialization)]
|
||||||
pub mod app;
|
pub mod app;
|
||||||
pub mod asset;
|
pub mod asset;
|
||||||
pub mod core;
|
pub mod core;
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue