mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 15:14:50 +00:00
more work on texture bindings
This commit is contained in:
parent
fb61204d53
commit
65284fcacb
6 changed files with 118 additions and 71 deletions
|
@ -41,6 +41,13 @@ struct UniformAttributeArgs {
|
|||
pub shader_def: Option<bool>,
|
||||
}
|
||||
|
||||
struct FieldUniformName {
|
||||
field: &'static str,
|
||||
uniform: &'static str,
|
||||
texture: &'static str,
|
||||
sampler: &'static str,
|
||||
}
|
||||
|
||||
#[proc_macro_derive(Uniforms, attributes(uniform))]
|
||||
pub fn derive_uniforms(input: TokenStream) -> TokenStream {
|
||||
const UNIFORM_ATTRIBUTE_NAME: &'static str = "uniform";
|
||||
|
@ -109,12 +116,25 @@ 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 layout_ident = format_ident!("{}_UNIFORM_LAYOUTS", struct_name_screaming_snake);
|
||||
let field_uniform_names_ident = format_ident!("{}_FIELD_UNIFORM_NAMES", struct_name_screaming_snake);
|
||||
|
||||
let get_uniform_bytes_field_name = active_uniform_fields.iter().map(|field| {
|
||||
let active_uniform_field_names = active_uniform_fields.iter().map(|field| {
|
||||
&field.ident
|
||||
});
|
||||
eprintln!("hitit");
|
||||
|
||||
|
||||
let field_uniform_names = active_uniform_fields.iter().map(|f| {
|
||||
let name = f.ident.as_ref().unwrap().to_string();
|
||||
let texture = format!("{}_texture", name);
|
||||
let sampler = format!("{}_sampler", name);
|
||||
quote!(FieldUniformName {
|
||||
field: #name,
|
||||
uniform: #name,
|
||||
texture: #texture,
|
||||
sampler: #sampler,
|
||||
})
|
||||
});
|
||||
|
||||
let mut uniform_info = Vec::new();
|
||||
let mut uniform_name_uniform_info = Vec::new();
|
||||
for field in active_uniform_fields.iter() {
|
||||
|
@ -122,7 +142,6 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
|
|||
if let Type::Path(ref type_path) = field.ty {
|
||||
let field_type_name = type_path.path.get_ident().unwrap().to_string();
|
||||
if field_type_name == "ColorSource" || field_type_name == "Handle<Texture>" {
|
||||
eprintln!("madeit");
|
||||
let texture_name = format!("{}_texture", name);
|
||||
let sampler_name = format!("{}_sampler", name);
|
||||
uniform_name_uniform_info.push(texture_name.clone());
|
||||
|
@ -142,6 +161,7 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
|
|||
}
|
||||
}
|
||||
|
||||
uniform_name_uniform_info.push(name.clone());
|
||||
uniform_info.push(quote!(bevy::render::render_graph::UniformInfo {
|
||||
name: #name,
|
||||
bind_type: bevy::render::render_graph::BindType::Uniform {
|
||||
|
@ -152,28 +172,54 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
|
|||
}));
|
||||
};
|
||||
|
||||
let layout_arrays = (0..uniform_info.len()).map(|_| quote!(&[]));
|
||||
let get_uniform_info_array_refs =
|
||||
(0..uniform_info.len()).map(|i| quote!(&#info_ident[#i]));
|
||||
/*
|
||||
uniform infos
|
||||
|
||||
x: ColorSource
|
||||
y: Vec4
|
||||
|
||||
|
||||
infos: [
|
||||
"x_color",
|
||||
"x_texture",
|
||||
"x_sampler",
|
||||
"y"
|
||||
]
|
||||
|
||||
field_names = ["x", "y"]
|
||||
|
||||
InfoIter { field_names, index = 0, needs_sampler = false}
|
||||
|
||||
uniform-provider
|
||||
for entity in entities
|
||||
for info in entity.t.get_uniform_info_iter()
|
||||
if info.bind_type == Uniform
|
||||
entity.t.get_bytes()
|
||||
elif info.bind_type == Texture
|
||||
entity.get_texture()
|
||||
|
||||
*/
|
||||
|
||||
TokenStream::from(quote! {
|
||||
const #info_ident: &[bevy::render::render_graph::UniformInfo] = &[
|
||||
#(#uniform_info,)*
|
||||
];
|
||||
|
||||
const #layout_ident: &[&[bevy::render::render_graph::UniformPropertyType]] = &[
|
||||
#(#layout_arrays,)*
|
||||
const #field_uniform_names_ident: &[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::UniformInfo] {
|
||||
#info_ident
|
||||
}
|
||||
|
||||
fn get_uniform_layouts(&self) -> &[&[bevy::render::render_graph::UniformPropertyType]] {
|
||||
#layout_ident
|
||||
fn get_field_bind_type(&self, name: &str) -> bevy::render::render_graph::FieldBindType {
|
||||
#(#field_names => #get_uniform_bytes_field_name,)*
|
||||
}
|
||||
|
||||
// TODO: Fix this so uniform_name_uniform_info lines up with getbytes
|
||||
fn get_uniform_bytes(&self, name: &str) -> Option<Vec<u8>> {
|
||||
use bevy::core::bytes::GetBytes;
|
||||
match name {
|
||||
|
@ -181,12 +227,6 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
|
|||
_ => None,
|
||||
}
|
||||
}
|
||||
fn get_uniform_info(&self, name: &str) -> Option<&bevy::render::render_graph::UniformInfo> {
|
||||
match name {
|
||||
#(#uniform_name_uniform_info => Some(#get_uniform_info_array_refs),)*
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::render::shader_reflect::ShaderLayout;
|
||||
use std::{
|
||||
collections::{HashMap, hash_map::DefaultHasher, BTreeSet},
|
||||
collections::{hash_map::DefaultHasher, BTreeSet, HashMap},
|
||||
hash::{Hash, Hasher},
|
||||
};
|
||||
|
||||
|
@ -20,30 +20,37 @@ impl PipelineLayout {
|
|||
let mut bind_groups = HashMap::<u32, BindGroup>::new();
|
||||
for shader_layout in shader_layouts {
|
||||
for shader_bind_group in shader_layout.bind_groups.iter_mut() {
|
||||
match bind_groups.get_mut(&shader_bind_group.index) {
|
||||
Some(bind_group) => {
|
||||
for shader_binding in shader_bind_group.bindings.iter() {
|
||||
if let Some(binding) = bind_group.bindings.iter().find(|binding| binding.index == shader_binding.index) {
|
||||
if binding != shader_binding {
|
||||
panic!("Binding {} in BindGroup {} does not match across all shader types: {:?} {:?}", binding.index, bind_group.index, binding, shader_binding);
|
||||
}
|
||||
} else {
|
||||
bind_group.bindings.insert(shader_binding.clone());
|
||||
}
|
||||
}
|
||||
},
|
||||
None => {
|
||||
bind_groups.insert(shader_bind_group.index, shader_bind_group.clone());
|
||||
}
|
||||
}
|
||||
match bind_groups.get_mut(&shader_bind_group.index) {
|
||||
Some(bind_group) => {
|
||||
for shader_binding in shader_bind_group.bindings.iter() {
|
||||
if let Some(binding) = bind_group
|
||||
.bindings
|
||||
.iter()
|
||||
.find(|binding| binding.index == shader_binding.index)
|
||||
{
|
||||
if binding != shader_binding {
|
||||
panic!("Binding {} in BindGroup {} does not match across all shader types: {:?} {:?}", binding.index, bind_group.index, binding, shader_binding);
|
||||
}
|
||||
} else {
|
||||
bind_group.bindings.insert(shader_binding.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
None => {
|
||||
bind_groups.insert(shader_bind_group.index, shader_bind_group.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut bind_groups_result = bind_groups.drain().map(|(_, value)| value).collect::<Vec<BindGroup>>();
|
||||
let mut bind_groups_result = bind_groups
|
||||
.drain()
|
||||
.map(|(_, value)| value)
|
||||
.collect::<Vec<BindGroup>>();
|
||||
|
||||
// NOTE: for some reason bind groups need to be sorted by index. this is likely an issue with bevy and not with wgpu
|
||||
bind_groups_result.sort_by(|a, b| a.index.partial_cmp(&b.index).unwrap());
|
||||
PipelineLayout {
|
||||
bind_groups: bind_groups_result
|
||||
bind_groups: bind_groups_result,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::{
|
||||
asset::{AssetStorage, Handle, Texture},
|
||||
asset::{AssetStorage, Handle},
|
||||
legion::prelude::*,
|
||||
render::{
|
||||
render_graph::{
|
||||
|
|
|
@ -46,10 +46,8 @@ where
|
|||
.count = 0;
|
||||
}
|
||||
|
||||
let mut sizes = Vec::new();
|
||||
let mut counts = Vec::new();
|
||||
for (uniforms, _renderable) in query.iter(world) {
|
||||
let uniform_layouts = uniforms.get_uniform_layouts();
|
||||
for (i, uniform_info) in uniforms
|
||||
.get_uniform_infos()
|
||||
.iter()
|
||||
|
@ -64,15 +62,6 @@ where
|
|||
{
|
||||
// only add the first time a uniform info is processed
|
||||
if self.uniform_buffer_info_names.len() <= i {
|
||||
let uniform_layout = uniform_layouts[i];
|
||||
// TODO: size is 0 right now because uniform layout isn't populated
|
||||
// also size isn't even being used right now?
|
||||
let size = uniform_layout
|
||||
.iter()
|
||||
.map(|u| u.get_size())
|
||||
.fold(0, |total, current| total + current);
|
||||
sizes.push(size);
|
||||
|
||||
self.uniform_buffer_info_names
|
||||
.push(uniform_info.name.to_string());
|
||||
}
|
||||
|
@ -89,8 +78,7 @@ where
|
|||
// the expense of hashing for large numbers of entities
|
||||
for (i, name) in self.uniform_buffer_info_names.iter().enumerate() {
|
||||
if let None = renderer.get_dynamic_uniform_buffer_info(name) {
|
||||
let mut info = DynamicUniformBufferInfo::new();
|
||||
info.size = sizes[i];
|
||||
let info = DynamicUniformBufferInfo::new();
|
||||
renderer.add_dynamic_uniform_buffer_info(name, info);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,16 +1,13 @@
|
|||
use crate::{
|
||||
render::render_graph::{BindType, UniformPropertyType},
|
||||
};
|
||||
use crate::render::{color::ColorSource, render_graph::BindType};
|
||||
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) -> &[UniformInfo];
|
||||
fn get_uniform_info(&self, name: &str) -> Option<&UniformInfo>;
|
||||
fn get_uniform_layouts(&self) -> &[&[UniformPropertyType]];
|
||||
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) -> FieldBindType;
|
||||
// TODO: support zero-copy uniforms
|
||||
// fn get_uniform_bytes_ref(&self, name: &str) -> Option<&[u8]>;
|
||||
}
|
||||
|
@ -28,6 +25,33 @@ impl ShaderDefSuffixProvider for bool {
|
|||
}
|
||||
}
|
||||
|
||||
pub enum FieldBindType {
|
||||
Uniform,
|
||||
Texture,
|
||||
}
|
||||
|
||||
pub trait AsFieldBindType {
|
||||
fn get_field_uniform_type(&self) -> FieldBindType;
|
||||
}
|
||||
|
||||
impl AsFieldBindType for ColorSource {
|
||||
fn get_field_uniform_type(&self) -> FieldBindType {
|
||||
match *self {
|
||||
ColorSource::Texture(_) => FieldBindType::Texture,
|
||||
ColorSource::Color(_) => FieldBindType::Uniform,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// impl<T> AsFieldBindType for T
|
||||
// where
|
||||
// T: GetBytes,
|
||||
// {
|
||||
// fn get_field_uniform_type(&self) -> FieldBindType {
|
||||
// FieldBindType::Uniform
|
||||
// }
|
||||
// }
|
||||
|
||||
pub struct UniformInfo<'a> {
|
||||
pub name: &'a str,
|
||||
pub bind_type: BindType,
|
||||
|
@ -38,7 +62,6 @@ pub struct DynamicUniformBufferInfo {
|
|||
pub offsets: HashMap<Entity, u64>,
|
||||
pub capacity: u64,
|
||||
pub count: u64,
|
||||
pub size: u64,
|
||||
}
|
||||
|
||||
impl DynamicUniformBufferInfo {
|
||||
|
@ -48,7 +71,6 @@ impl DynamicUniformBufferInfo {
|
|||
count: 0,
|
||||
indices: HashMap::new(),
|
||||
offsets: HashMap::new(),
|
||||
size: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::render::render_graph::{
|
||||
uniform::{AsUniforms, UniformInfo},
|
||||
BindType, UniformPropertyType,
|
||||
BindType, FieldBindType,
|
||||
};
|
||||
|
||||
use zerocopy::AsBytes;
|
||||
|
@ -14,32 +14,22 @@ const LOCAL_TO_WORLD_UNIFORM_INFO: &[UniformInfo] = &[UniformInfo {
|
|||
},
|
||||
}];
|
||||
|
||||
// these are separate from BindType::Uniform{properties} because they need to be const
|
||||
const LOCAL_TO_WORLD_UNIFORM_LAYOUTS: &[&[UniformPropertyType]] = &[&[]];
|
||||
|
||||
impl AsUniforms for bevy_transform::prelude::LocalToWorld {
|
||||
fn get_uniform_infos(&self) -> &[UniformInfo] {
|
||||
LOCAL_TO_WORLD_UNIFORM_INFO
|
||||
}
|
||||
|
||||
fn get_uniform_layouts(&self) -> &[&[UniformPropertyType]] {
|
||||
LOCAL_TO_WORLD_UNIFORM_LAYOUTS
|
||||
}
|
||||
|
||||
fn get_uniform_bytes(&self, name: &str) -> Option<Vec<u8>> {
|
||||
match name {
|
||||
"Object" => Some(self.0.to_cols_array_2d().as_bytes().into()),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
fn get_uniform_info(&self, name: &str) -> Option<&UniformInfo> {
|
||||
match name {
|
||||
"Object" => Some(&LOCAL_TO_WORLD_UNIFORM_INFO[0]),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_shader_defs(&self) -> Option<Vec<String>> {
|
||||
None
|
||||
}
|
||||
fn get_field_bind_type(&self, name: &str) -> FieldBindType {
|
||||
FieldBindType::Uniform
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue