shader_defs: new leaner shader defs. they are now separate from uniforms
This commit is contained in:
parent
fd8f87400d
commit
62c434274f
@ -8,6 +8,7 @@ mod modules;
|
|||||||
mod render_resources;
|
mod render_resources;
|
||||||
mod render_resource;
|
mod render_resource;
|
||||||
mod resource;
|
mod resource;
|
||||||
|
mod shader_defs;
|
||||||
mod uniforms;
|
mod uniforms;
|
||||||
mod as_vertex_buffer_descriptor;
|
mod as_vertex_buffer_descriptor;
|
||||||
|
|
||||||
@ -43,6 +44,11 @@ pub fn derive_render_resource(input: TokenStream) -> TokenStream {
|
|||||||
render_resource::derive_render_resource(input)
|
render_resource::derive_render_resource(input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[proc_macro_derive(ShaderDefs, attributes(shader_def, module))]
|
||||||
|
pub fn derive_shader_defs(input: TokenStream) -> TokenStream {
|
||||||
|
shader_defs::derive_shader_defs(input)
|
||||||
|
}
|
||||||
|
|
||||||
#[proc_macro_derive(AsVertexBufferDescriptor, attributes(vertex, module))]
|
#[proc_macro_derive(AsVertexBufferDescriptor, attributes(vertex, module))]
|
||||||
pub fn derive_as_vertex_buffer_descriptor(input: TokenStream) -> TokenStream {
|
pub fn derive_as_vertex_buffer_descriptor(input: TokenStream) -> TokenStream {
|
||||||
as_vertex_buffer_descriptor::derive_as_vertex_buffer_descriptor(input)
|
as_vertex_buffer_descriptor::derive_as_vertex_buffer_descriptor(input)
|
||||||
|
|||||||
71
crates/bevy_derive/src/shader_defs.rs
Normal file
71
crates/bevy_derive/src/shader_defs.rs
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
use crate::modules::{get_modules, get_path};
|
||||||
|
use proc_macro::TokenStream;
|
||||||
|
use proc_macro2::Ident;
|
||||||
|
use inflector::Inflector;
|
||||||
|
use quote::quote;
|
||||||
|
use syn::{parse_macro_input, Data, DataStruct, DeriveInput, Fields, Path};
|
||||||
|
|
||||||
|
static SHADER_DEF_ATTRIBUTE_NAME: &'static str = "shader_def";
|
||||||
|
|
||||||
|
pub fn derive_shader_defs(input: TokenStream) -> TokenStream {
|
||||||
|
let ast = parse_macro_input!(input as DeriveInput);
|
||||||
|
let modules = get_modules(&ast);
|
||||||
|
let bevy_render_path: Path = get_path(&modules.bevy_render);
|
||||||
|
|
||||||
|
let fields = match &ast.data {
|
||||||
|
Data::Struct(DataStruct {
|
||||||
|
fields: Fields::Named(fields),
|
||||||
|
..
|
||||||
|
}) => &fields.named,
|
||||||
|
_ => panic!("expected a struct with named fields"),
|
||||||
|
};
|
||||||
|
|
||||||
|
let shader_def_idents = fields
|
||||||
|
.iter()
|
||||||
|
.filter(|f| {
|
||||||
|
f.attrs
|
||||||
|
.iter()
|
||||||
|
.find(|a| {
|
||||||
|
a.path.get_ident().as_ref().unwrap().to_string() == SHADER_DEF_ATTRIBUTE_NAME
|
||||||
|
})
|
||||||
|
.is_some()
|
||||||
|
})
|
||||||
|
.map(|f| f.ident.as_ref().unwrap())
|
||||||
|
.collect::<Vec<&Ident>>();
|
||||||
|
let struct_name = &ast.ident;
|
||||||
|
let struct_name_pascal_case = ast.ident.to_string().to_pascal_case();
|
||||||
|
let shader_defs = shader_def_idents
|
||||||
|
.iter()
|
||||||
|
.map(|i| format!("{}_{}", struct_name_pascal_case, i.to_string()).to_uppercase());
|
||||||
|
|
||||||
|
let shader_defs_len = shader_defs.len();
|
||||||
|
let shader_def_indices = 0..shader_defs_len;
|
||||||
|
|
||||||
|
let generics = ast.generics;
|
||||||
|
let (impl_generics, ty_generics, _where_clause) = generics.split_for_impl();
|
||||||
|
|
||||||
|
|
||||||
|
TokenStream::from(quote! {
|
||||||
|
impl #impl_generics #bevy_render_path::shader::ShaderDefs for #struct_name#ty_generics {
|
||||||
|
fn shader_defs_len(&self) -> usize {
|
||||||
|
#shader_defs_len
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_shader_def(&self, index: usize) -> Option<&str> {
|
||||||
|
use #bevy_render_path::shader::ShaderDef;
|
||||||
|
match index {
|
||||||
|
#(#shader_def_indices => if self.#shader_def_idents.is_defined() {
|
||||||
|
Some(#shader_defs)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
},)*
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn iter_shader_defs(&self) -> #bevy_render_path::shader::ShaderDefIterator {
|
||||||
|
#bevy_render_path::shader::ShaderDefIterator::new(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
@ -138,15 +138,7 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
|
|||||||
// TODO: this will be very allocation heavy. find a way to either make this allocation free
|
// TODO: this will be very allocation heavy. find a way to either make this allocation free
|
||||||
// or alternatively only run it when the shader_defs have changed
|
// or alternatively only run it when the shader_defs have changed
|
||||||
fn get_shader_defs(&self) -> Option<Vec<String>> {
|
fn get_shader_defs(&self) -> Option<Vec<String>> {
|
||||||
use #bevy_render_path::shader::ShaderDefSuffixProvider;
|
None
|
||||||
let mut potential_shader_defs: Vec<(&'static str, Option<&'static str>)> = vec![
|
|
||||||
#((#shader_def_field_names_screaming_snake, self.#shader_def_field_names.get_shader_def()),)*
|
|
||||||
];
|
|
||||||
|
|
||||||
Some(potential_shader_defs.drain(..)
|
|
||||||
.filter(|(f, shader_def)| shader_def.is_some())
|
|
||||||
.map(|(f, shader_def)| format!("{}_{}{}", #struct_name_uppercase, f, shader_def.unwrap()))
|
|
||||||
.collect::<Vec<String>>())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
use bevy_asset::{self, Handle};
|
use bevy_asset::{self, Handle};
|
||||||
use bevy_render::{render_resource::RenderResources, shader::Uniforms, texture::Texture, Color};
|
use bevy_render::{render_resource::RenderResources, shader::ShaderDefs, texture::Texture, Color};
|
||||||
|
|
||||||
#[derive(Uniforms, RenderResources)]
|
#[derive(RenderResources, ShaderDefs)]
|
||||||
pub struct StandardMaterial {
|
pub struct StandardMaterial {
|
||||||
pub albedo: Color,
|
pub albedo: Color,
|
||||||
#[uniform(shader_def)]
|
#[shader_def]
|
||||||
pub albedo_texture: Option<Handle<Texture>>,
|
pub albedo_texture: Option<Handle<Texture>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,10 @@
|
|||||||
mod shader;
|
mod shader;
|
||||||
|
mod shader_defs;
|
||||||
mod shader_reflect;
|
mod shader_reflect;
|
||||||
mod uniform;
|
mod uniform;
|
||||||
pub mod uniforms;
|
pub mod uniforms;
|
||||||
|
|
||||||
pub use shader::*;
|
pub use shader::*;
|
||||||
|
pub use shader_defs::*;
|
||||||
pub use shader_reflect::*;
|
pub use shader_reflect::*;
|
||||||
pub use uniform::*;
|
pub use uniform::*;
|
||||||
|
|||||||
92
crates/bevy_render/src/shader/shader_defs.rs
Normal file
92
crates/bevy_render/src/shader/shader_defs.rs
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
|
||||||
|
use bevy_asset::{Assets, Handle};
|
||||||
|
use crate::{Renderable, texture::Texture};
|
||||||
|
use legion::prelude::{Res, Com, ComMut};
|
||||||
|
|
||||||
|
pub use bevy_derive::ShaderDefs;
|
||||||
|
|
||||||
|
pub trait ShaderDef {
|
||||||
|
fn is_defined(&self) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait ShaderDefs {
|
||||||
|
fn shader_defs_len(&self) -> usize;
|
||||||
|
fn get_shader_def(&self, index: usize) -> Option<&str>;
|
||||||
|
fn iter_shader_defs(&self) -> ShaderDefIterator;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub struct ShaderDefIterator<'a> {
|
||||||
|
shader_defs: &'a dyn ShaderDefs,
|
||||||
|
index: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ShaderDefIterator<'a> {
|
||||||
|
pub fn new(shader_defs: &'a dyn ShaderDefs) -> Self {
|
||||||
|
Self {
|
||||||
|
shader_defs,
|
||||||
|
index: 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'a> Iterator for ShaderDefIterator<'a> {
|
||||||
|
type Item = &'a str;
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
loop {
|
||||||
|
if self.index == self.shader_defs.shader_defs_len() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let shader_def = self
|
||||||
|
.shader_defs
|
||||||
|
.get_shader_def(self.index);
|
||||||
|
self.index += 1;
|
||||||
|
if shader_def.is_some() {
|
||||||
|
return shader_def;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ShaderDef for bool {
|
||||||
|
fn is_defined(&self) -> bool {
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ShaderDef for Option<Handle<Texture>> {
|
||||||
|
fn is_defined(&self) -> bool {
|
||||||
|
self.is_some()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn shader_def_system<T>(shader_defs: Com<T>, mut renderable: ComMut<Renderable>)
|
||||||
|
where
|
||||||
|
T: ShaderDefs + Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
for shader_def in shader_defs.iter_shader_defs() {
|
||||||
|
renderable
|
||||||
|
.render_resource_assignments
|
||||||
|
.pipeline_specialization
|
||||||
|
.shader_specialization
|
||||||
|
.shader_defs
|
||||||
|
.insert(shader_def.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn asset_shader_def_system<T>(
|
||||||
|
assets: Res<Assets<T>>,
|
||||||
|
asset_handle: Com<Handle<T>>,
|
||||||
|
mut renderable: ComMut<Renderable>,
|
||||||
|
) where
|
||||||
|
T: ShaderDefs + Send + Sync + 'static,
|
||||||
|
{
|
||||||
|
let shader_defs = assets.get(&asset_handle).unwrap();
|
||||||
|
for shader_def in shader_defs.iter_shader_defs() {
|
||||||
|
renderable
|
||||||
|
.render_resource_assignments
|
||||||
|
.pipeline_specialization
|
||||||
|
.shader_specialization
|
||||||
|
.shader_defs
|
||||||
|
.insert(shader_def.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,5 @@
|
|||||||
use crate::{pipeline::BindType, texture::Texture, Renderable};
|
use crate::{pipeline::BindType, texture::Texture};
|
||||||
use bevy_asset::{Assets, Handle};
|
use bevy_asset::Handle;
|
||||||
use legion::prelude::*;
|
|
||||||
|
|
||||||
pub use bevy_derive::{Uniform, Uniforms};
|
pub use bevy_derive::{Uniform, Uniforms};
|
||||||
|
|
||||||
@ -13,42 +12,6 @@ pub trait Uniforms: Send + Sync + 'static {
|
|||||||
fn get_field_bind_type(&self, name: &str) -> Option<FieldBindType>;
|
fn get_field_bind_type(&self, name: &str) -> Option<FieldBindType>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn shader_def_system<T>(uniforms: Com<T>, mut renderable: ComMut<Renderable>)
|
|
||||||
where
|
|
||||||
T: Uniforms + Send + Sync + 'static,
|
|
||||||
{
|
|
||||||
if let Some(shader_defs) = uniforms.get_shader_defs() {
|
|
||||||
renderable
|
|
||||||
.render_resource_assignments
|
|
||||||
.pipeline_specialization
|
|
||||||
.shader_specialization
|
|
||||||
.shader_defs
|
|
||||||
.extend(shader_defs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn asset_shader_def_system<T>(
|
|
||||||
assets: Res<Assets<T>>,
|
|
||||||
asset_handle: Com<Handle<T>>,
|
|
||||||
mut renderable: ComMut<Renderable>,
|
|
||||||
) where
|
|
||||||
T: Uniforms + Send + Sync + 'static,
|
|
||||||
{
|
|
||||||
if !renderable.is_visible || renderable.is_instanced {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
let uniforms = assets.get(&asset_handle).unwrap();
|
|
||||||
if let Some(shader_defs) = uniforms.get_shader_defs() {
|
|
||||||
renderable
|
|
||||||
.render_resource_assignments
|
|
||||||
.pipeline_specialization
|
|
||||||
.shader_specialization
|
|
||||||
.shader_defs
|
|
||||||
.extend(shader_defs)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait ShaderDefSuffixProvider {
|
pub trait ShaderDefSuffixProvider {
|
||||||
fn get_shader_def(&self) -> Option<&'static str>;
|
fn get_shader_def(&self) -> Option<&'static str>;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
use bevy_asset::{self, Handle};
|
use bevy_asset::{self, Handle};
|
||||||
use bevy_render::{texture::Texture, Color, render_resource::RenderResources, shader::Uniforms};
|
use bevy_render::{render_resource::RenderResources, shader::ShaderDefs, texture::Texture, Color};
|
||||||
|
|
||||||
#[derive(Uniforms, RenderResources)]
|
#[derive(RenderResources, ShaderDefs)]
|
||||||
pub struct ColorMaterial {
|
pub struct ColorMaterial {
|
||||||
pub color: Color,
|
pub color: Color,
|
||||||
#[uniform(shader_def)]
|
#[shader_def]
|
||||||
pub texture: Option<Handle<Texture>>,
|
pub texture: Option<Handle<Texture>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,26 +1,27 @@
|
|||||||
use crate::Rect;
|
use crate::Rect;
|
||||||
use bevy_asset::Handle;
|
use bevy_asset::Handle;
|
||||||
use bevy_render::{texture::Texture, render_resource::{RenderResources, RenderResource}, shader::{Uniforms, Uniform}};
|
|
||||||
use bevy_core::bytes::Bytes;
|
use bevy_core::bytes::Bytes;
|
||||||
|
use bevy_render::{
|
||||||
|
render_resource::{RenderResource, RenderResources},
|
||||||
|
texture::Texture,
|
||||||
|
};
|
||||||
use glam::{Vec2, Vec3};
|
use glam::{Vec2, Vec3};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[derive(Uniforms, RenderResources)]
|
#[derive(RenderResources)]
|
||||||
pub struct TextureAtlas {
|
pub struct TextureAtlas {
|
||||||
pub texture: Handle<Texture>,
|
pub texture: Handle<Texture>,
|
||||||
// TODO: add support to Uniforms derive to write dimensions and sprites to the same buffer
|
// TODO: add support to Uniforms derive to write dimensions and sprites to the same buffer
|
||||||
pub dimensions: Vec2,
|
pub dimensions: Vec2,
|
||||||
#[uniform(buffer)]
|
|
||||||
#[render_resources(buffer)]
|
#[render_resources(buffer)]
|
||||||
pub textures: Vec<Rect>,
|
pub textures: Vec<Rect>,
|
||||||
#[uniform(ignore)]
|
|
||||||
#[render_resources(ignore)]
|
#[render_resources(ignore)]
|
||||||
pub texture_handles: Option<HashMap<Handle<Texture>, usize>>,
|
pub texture_handles: Option<HashMap<Handle<Texture>, usize>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// NOTE: cannot do `unsafe impl Byteable` here because Vec3 takes up the space of a Vec4. If/when glam changes this we can swap out
|
// NOTE: cannot do `unsafe impl Byteable` here because Vec3 takes up the space of a Vec4. If/when glam changes this we can swap out
|
||||||
// Bytes for Byteable as a micro-optimization. https://github.com/bitshifter/glam-rs/issues/36
|
// Bytes for Byteable as a micro-optimization. https://github.com/bitshifter/glam-rs/issues/36
|
||||||
#[derive(Uniform, Bytes, RenderResources, RenderResource, Default)]
|
#[derive(Bytes, RenderResources, RenderResource, Default)]
|
||||||
#[render_resources(from_self)]
|
#[render_resources(from_self)]
|
||||||
pub struct TextureAtlasSprite {
|
pub struct TextureAtlasSprite {
|
||||||
pub position: Vec3,
|
pub position: Vec3,
|
||||||
|
|||||||
@ -8,7 +8,7 @@ fn main() {
|
|||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Uniforms, RenderResources, Default)]
|
#[derive(RenderResources, Default)]
|
||||||
struct MyMaterial {
|
struct MyMaterial {
|
||||||
pub color: Color,
|
pub color: Color,
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,11 +12,11 @@ fn main() {
|
|||||||
.run();
|
.run();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Uniforms, RenderResources, Default)]
|
#[derive(RenderResources, ShaderDefs, Default)]
|
||||||
struct MyMaterial {
|
struct MyMaterial {
|
||||||
pub color: Color,
|
pub color: Color,
|
||||||
#[uniform(ignore, shader_def)]
|
|
||||||
#[render_resources(ignore)]
|
#[render_resources(ignore)]
|
||||||
|
#[shader_def]
|
||||||
pub always_red: bool,
|
pub always_red: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
pub use crate::{
|
pub use crate::{
|
||||||
app::{
|
app::{
|
||||||
schedule_runner::ScheduleRunnerPlugin, stage, App, AppBuilder, AppPlugin, EntityArchetype,
|
schedule_runner::ScheduleRunnerPlugin, stage, App, AppBuilder, AppPlugin, DynamicAppPlugin,
|
||||||
EventReader, Events, FromResources, System, DynamicAppPlugin
|
EntityArchetype, EventReader, Events, FromResources, System,
|
||||||
},
|
},
|
||||||
asset::{AddAsset, AssetEvent, AssetServer, Assets, Handle},
|
asset::{AddAsset, AssetEvent, AssetServer, Assets, Handle},
|
||||||
core::{
|
core::{
|
||||||
@ -25,8 +25,10 @@ pub use crate::{
|
|||||||
},
|
},
|
||||||
RenderGraph,
|
RenderGraph,
|
||||||
},
|
},
|
||||||
shader::{Shader, ShaderDefSuffixProvider, ShaderStage, ShaderStages, Uniforms},
|
|
||||||
render_resource::RenderResources,
|
render_resource::RenderResources,
|
||||||
|
shader::{
|
||||||
|
Shader, ShaderDefSuffixProvider, ShaderDefs, ShaderStage, ShaderStages, Uniforms,
|
||||||
|
},
|
||||||
texture::Texture,
|
texture::Texture,
|
||||||
Camera, Color, ColorSource, OrthographicProjection, PerspectiveProjection, Renderable,
|
Camera, Color, ColorSource, OrthographicProjection, PerspectiveProjection, Renderable,
|
||||||
},
|
},
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user