add shader def fields / proc macro
This commit is contained in:
parent
4a12d16307
commit
eedec80e89
@ -35,7 +35,7 @@ struct UniformAttributeArgs {
|
|||||||
#[darling(default)]
|
#[darling(default)]
|
||||||
pub ignore: Option<bool>,
|
pub ignore: Option<bool>,
|
||||||
#[darling(default)]
|
#[darling(default)]
|
||||||
pub shader_def: Option<String>,
|
pub shader_def: Option<bool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[proc_macro_derive(Uniforms, attributes(uniform))]
|
#[proc_macro_derive(Uniforms, attributes(uniform))]
|
||||||
@ -81,28 +81,29 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
|
|||||||
.map(|(f, _attr)| *f)
|
.map(|(f, _attr)| *f)
|
||||||
.collect::<Vec<&Field>>();
|
.collect::<Vec<&Field>>();
|
||||||
|
|
||||||
let shader_defs = uniform_fields
|
let shader_def_fields = uniform_fields
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_f, attrs)| match attrs {
|
.filter(|(_field, attrs)| {
|
||||||
Some(attrs) => attrs.shader_def.is_some(),
|
match attrs {
|
||||||
|
Some(attrs) => match attrs.shader_def {
|
||||||
|
Some(shader_def) => shader_def,
|
||||||
|
None => false,
|
||||||
|
},
|
||||||
None => false,
|
None => false,
|
||||||
})
|
|
||||||
.map(|(f, attrs)| {
|
|
||||||
// attrs is guaranteed to be set because we checked in filter
|
|
||||||
let shader_def = attrs.as_ref().unwrap().shader_def.as_ref().unwrap();
|
|
||||||
if shader_def.len() == 0 {
|
|
||||||
f.ident.as_ref().unwrap().to_string()
|
|
||||||
} else {
|
|
||||||
shader_def.to_string()
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.collect::<Vec<String>>();
|
.map(|(f, _attr)| *f)
|
||||||
|
.collect::<Vec<&Field>>();
|
||||||
|
|
||||||
|
let shader_def_field_names = shader_def_fields.iter().map(|field| &field.ident);
|
||||||
|
let shader_def_field_name_strs = shader_def_fields.iter().map(|field| field.ident.as_ref().unwrap().to_string());
|
||||||
|
|
||||||
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 info_ident = format_ident!("{}_UNIFORM_INFO", struct_name_screaming_snake);
|
||||||
let layout_ident = format_ident!("{}_UNIFORM_LAYOUTS", struct_name_screaming_snake);
|
let layout_ident = format_ident!("{}_UNIFORM_LAYOUTS", struct_name_screaming_snake);
|
||||||
let layout_arrays = (0..active_uniform_fields.len()).map(|_| quote!(&[]));
|
let layout_arrays = (0..active_uniform_fields.len()).map(|_| quote!(&[]));
|
||||||
|
|
||||||
let uniform_name_uniform_info = active_uniform_fields
|
let uniform_name_uniform_info = active_uniform_fields
|
||||||
.iter()
|
.iter()
|
||||||
.map(|field| format!("{}_{}", struct_name, field.ident.as_ref().unwrap()))
|
.map(|field| format!("{}_{}", struct_name, field.ident.as_ref().unwrap()))
|
||||||
@ -151,10 +152,17 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_shader_defs(&self) -> Vec<&'static str> {
|
// TODO: this will be very allocation heavy. find a way to either make this allocation free
|
||||||
vec![
|
// or alternatively only run it when the shader_defs have changed
|
||||||
#(#shader_defs,)*
|
fn get_shader_defs(&self) -> Option<Vec<String>> {
|
||||||
]
|
let mut potential_shader_defs: Vec<(&'static str, Option<&'static str>)> = vec![
|
||||||
|
#((#shader_def_field_name_strs, 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!("{}{}", f, shader_def.unwrap()))
|
||||||
|
.collect::<Vec<String>>())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -23,6 +23,7 @@ fn setup(world: &mut World) {
|
|||||||
mesh: plane_handle.clone(),
|
mesh: plane_handle.clone(),
|
||||||
material: StandardMaterial {
|
material: StandardMaterial {
|
||||||
albedo: math::vec4(0.1, 0.2, 0.1, 1.0),
|
albedo: math::vec4(0.1, 0.2, 0.1, 1.0),
|
||||||
|
everything_is_red: true,
|
||||||
},
|
},
|
||||||
shader_uniforms: ShaderUniforms::new(),
|
shader_uniforms: ShaderUniforms::new(),
|
||||||
local_to_world: LocalToWorld::identity(),
|
local_to_world: LocalToWorld::identity(),
|
||||||
@ -33,6 +34,7 @@ fn setup(world: &mut World) {
|
|||||||
mesh: cube_handle.clone(),
|
mesh: cube_handle.clone(),
|
||||||
material: StandardMaterial {
|
material: StandardMaterial {
|
||||||
albedo: math::vec4(0.5, 0.3, 0.3, 1.0),
|
albedo: math::vec4(0.5, 0.3, 0.3, 1.0),
|
||||||
|
everything_is_red: true,
|
||||||
},
|
},
|
||||||
shader_uniforms: ShaderUniforms::new(),
|
shader_uniforms: ShaderUniforms::new(),
|
||||||
local_to_world: LocalToWorld::identity(),
|
local_to_world: LocalToWorld::identity(),
|
||||||
|
@ -23,9 +23,9 @@ impl ForwardPipeline {
|
|||||||
impl Pipeline for ForwardPipeline {
|
impl Pipeline for ForwardPipeline {
|
||||||
fn initialize(&mut self, render_graph: &mut RenderGraphData, _: &mut World) {
|
fn initialize(&mut self, render_graph: &mut RenderGraphData, _: &mut World) {
|
||||||
let vs_bytes =
|
let vs_bytes =
|
||||||
shader::glsl_to_spirv(include_str!("forward.vert"), shader::ShaderStage::Vertex);
|
shader::glsl_to_spirv(include_str!("forward.vert"), shader::ShaderStage::Vertex, None);
|
||||||
let fs_bytes =
|
let fs_bytes =
|
||||||
shader::glsl_to_spirv(include_str!("forward.frag"), shader::ShaderStage::Fragment);
|
shader::glsl_to_spirv(include_str!("forward.frag"), shader::ShaderStage::Fragment, None);
|
||||||
|
|
||||||
let bind_group_layout =
|
let bind_group_layout =
|
||||||
render_graph
|
render_graph
|
||||||
|
@ -139,10 +139,12 @@ impl Pipeline for ForwardInstancedPipeline {
|
|||||||
let vs_bytes = shader::glsl_to_spirv(
|
let vs_bytes = shader::glsl_to_spirv(
|
||||||
include_str!("forward_instanced.vert"),
|
include_str!("forward_instanced.vert"),
|
||||||
shader::ShaderStage::Vertex,
|
shader::ShaderStage::Vertex,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
let fs_bytes = shader::glsl_to_spirv(
|
let fs_bytes = shader::glsl_to_spirv(
|
||||||
include_str!("forward_instanced.frag"),
|
include_str!("forward_instanced.frag"),
|
||||||
shader::ShaderStage::Fragment,
|
shader::ShaderStage::Fragment,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
let bind_group_layout =
|
let bind_group_layout =
|
||||||
|
@ -26,10 +26,12 @@ impl Pipeline for ForwardShadowPassNew {
|
|||||||
let vs_bytes = shader::glsl_to_spirv(
|
let vs_bytes = shader::glsl_to_spirv(
|
||||||
include_str!("forward_shadow.vert"),
|
include_str!("forward_shadow.vert"),
|
||||||
shader::ShaderStage::Vertex,
|
shader::ShaderStage::Vertex,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
let fs_bytes = shader::glsl_to_spirv(
|
let fs_bytes = shader::glsl_to_spirv(
|
||||||
include_str!("forward_shadow.frag"),
|
include_str!("forward_shadow.frag"),
|
||||||
shader::ShaderStage::Fragment,
|
shader::ShaderStage::Fragment,
|
||||||
|
None,
|
||||||
);
|
);
|
||||||
|
|
||||||
let bind_group_layout =
|
let bind_group_layout =
|
||||||
|
@ -103,9 +103,9 @@ impl Pipeline for ShadowPipeline {
|
|||||||
|
|
||||||
// Create the render pipeline
|
// Create the render pipeline
|
||||||
let vs_bytes =
|
let vs_bytes =
|
||||||
shader::glsl_to_spirv(include_str!("shadow.vert"), shader::ShaderStage::Vertex);
|
shader::glsl_to_spirv(include_str!("shadow.vert"), shader::ShaderStage::Vertex, None);
|
||||||
let fs_bytes =
|
let fs_bytes =
|
||||||
shader::glsl_to_spirv(include_str!("shadow.frag"), shader::ShaderStage::Fragment);
|
shader::glsl_to_spirv(include_str!("shadow.frag"), shader::ShaderStage::Fragment, None);
|
||||||
let vs_module = render_graph.device.create_shader_module(&vs_bytes);
|
let vs_module = render_graph.device.create_shader_module(&vs_bytes);
|
||||||
let fs_module = render_graph.device.create_shader_module(&fs_bytes);
|
let fs_module = render_graph.device.create_shader_module(&fs_bytes);
|
||||||
|
|
||||||
|
@ -95,9 +95,9 @@ impl UiPipeline {
|
|||||||
|
|
||||||
impl Pipeline for UiPipeline {
|
impl Pipeline for UiPipeline {
|
||||||
fn initialize(&mut self, render_graph: &mut RenderGraphData, world: &mut World) {
|
fn initialize(&mut self, render_graph: &mut RenderGraphData, world: &mut World) {
|
||||||
let vs_bytes = shader::glsl_to_spirv(include_str!("ui.vert"), shader::ShaderStage::Vertex);
|
let vs_bytes = shader::glsl_to_spirv(include_str!("ui.vert"), shader::ShaderStage::Vertex, None);
|
||||||
let fs_bytes =
|
let fs_bytes =
|
||||||
shader::glsl_to_spirv(include_str!("ui.frag"), shader::ShaderStage::Fragment);
|
shader::glsl_to_spirv(include_str!("ui.frag"), shader::ShaderStage::Fragment, None);
|
||||||
|
|
||||||
let bind_group_layout =
|
let bind_group_layout =
|
||||||
render_graph
|
render_graph
|
||||||
|
@ -43,4 +43,8 @@ void main() {
|
|||||||
}
|
}
|
||||||
// multiply the light by material color
|
// multiply the light by material color
|
||||||
o_Target = vec4(color, 1.0) * Albedo;
|
o_Target = vec4(color, 1.0) * Albedo;
|
||||||
|
|
||||||
|
# ifdef everything_is_red
|
||||||
|
o_Target = vec4(1.0, 0.0, 0.0, 1.0);
|
||||||
|
# endif
|
||||||
}
|
}
|
||||||
|
@ -41,9 +41,23 @@ pub trait AsUniforms {
|
|||||||
fn get_uniform_info(&self, name: &str) -> Option<&UniformInfo>;
|
fn get_uniform_info(&self, name: &str) -> Option<&UniformInfo>;
|
||||||
fn get_uniform_layouts(&self) -> &[&[UniformPropertyType]];
|
fn get_uniform_layouts(&self) -> &[&[UniformPropertyType]];
|
||||||
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) -> Vec<&'static str>;
|
fn get_shader_defs(&self) -> Option<Vec<String>>;
|
||||||
// TODO: support zero-copy uniforms
|
// TODO: support zero-copy uniforms
|
||||||
// fn get_uniform_bytes_ref(&self, name: &str) -> Option<&[u8]>;
|
// fn get_uniform_bytes_ref(&self, name: &str) -> Option<&[u8]>;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait ShaderDefSuffixProvider {
|
||||||
|
fn get_shader_def(&self) -> Option<&'static str>;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ShaderDefSuffixProvider for bool {
|
||||||
|
fn get_shader_def(&self) -> Option<&'static str> {
|
||||||
|
match *self {
|
||||||
|
true => Some(""),
|
||||||
|
false => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub struct UniformInfo<'a> {
|
// pub struct UniformInfo<'a> {
|
||||||
|
@ -41,7 +41,7 @@ impl AsUniforms for bevy_transform::prelude::LocalToWorld {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_shader_defs(&self) -> std::vec::Vec<&'static str> {
|
fn get_shader_defs(&self) -> Option<Vec<String>> {
|
||||||
Vec::new()
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -2,7 +2,7 @@ use crate::{
|
|||||||
math::Vec4,
|
math::Vec4,
|
||||||
render::render_graph_2::{
|
render::render_graph_2::{
|
||||||
uniform::{AsUniforms, GetBytes, UniformInfo},
|
uniform::{AsUniforms, GetBytes, UniformInfo},
|
||||||
BindType, UniformPropertyType,
|
BindType, UniformPropertyType, ShaderDefSuffixProvider
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -11,6 +11,6 @@ use bevy_derive::Uniforms;
|
|||||||
#[derive(Uniforms)]
|
#[derive(Uniforms)]
|
||||||
pub struct StandardMaterial {
|
pub struct StandardMaterial {
|
||||||
pub albedo: Vec4,
|
pub albedo: Vec4,
|
||||||
// #[uniform(ignore,shader_def="Hi")]
|
#[uniform(ignore,shader_def)]
|
||||||
// pub enable_thing: bool,
|
pub everything_is_red: bool,
|
||||||
}
|
}
|
@ -17,10 +17,15 @@ impl Into<shaderc::ShaderKind> for ShaderStage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn glsl_to_spirv(glsl_source: &str, stage: ShaderStage) -> Vec<u32> {
|
pub fn glsl_to_spirv(glsl_source: &str, stage: ShaderStage, shader_defs: Option<&Vec<String>>) -> Vec<u32> {
|
||||||
let shader_kind: shaderc::ShaderKind = stage.into();
|
let shader_kind: shaderc::ShaderKind = stage.into();
|
||||||
let mut compiler = shaderc::Compiler::new().unwrap();
|
let mut compiler = shaderc::Compiler::new().unwrap();
|
||||||
let options = shaderc::CompileOptions::new().unwrap();
|
let mut options = shaderc::CompileOptions::new().unwrap();
|
||||||
|
if let Some(shader_defs) = shader_defs {
|
||||||
|
for shader_def in shader_defs.iter() {
|
||||||
|
options.add_macro_definition(shader_def.as_str(), None);
|
||||||
|
}
|
||||||
|
}
|
||||||
let binary_result = compiler
|
let binary_result = compiler
|
||||||
.compile_into_spirv(
|
.compile_into_spirv(
|
||||||
glsl_source,
|
glsl_source,
|
||||||
@ -59,7 +64,7 @@ impl Shader {
|
|||||||
pub fn get_spirv(&self) -> Vec<u32> {
|
pub fn get_spirv(&self) -> Vec<u32> {
|
||||||
match self.source {
|
match self.source {
|
||||||
ShaderSource::Spirv(ref bytes) => bytes.clone(),
|
ShaderSource::Spirv(ref bytes) => bytes.clone(),
|
||||||
ShaderSource::Glsl(ref source) => glsl_to_spirv(&source, self.stage),
|
ShaderSource::Glsl(ref source) => glsl_to_spirv(&source, self.stage, self.macros.as_ref()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user