more work on texture bindings
This commit is contained in:
parent
fb61204d53
commit
65284fcacb
@ -41,6 +41,13 @@ struct UniformAttributeArgs {
|
|||||||
pub shader_def: Option<bool>,
|
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))]
|
#[proc_macro_derive(Uniforms, attributes(uniform))]
|
||||||
pub fn derive_uniforms(input: TokenStream) -> TokenStream {
|
pub fn derive_uniforms(input: TokenStream) -> TokenStream {
|
||||||
const UNIFORM_ATTRIBUTE_NAME: &'static str = "uniform";
|
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 = &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 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
|
&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_info = Vec::new();
|
||||||
let mut uniform_name_uniform_info = Vec::new();
|
let mut uniform_name_uniform_info = Vec::new();
|
||||||
for field in active_uniform_fields.iter() {
|
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 {
|
if let Type::Path(ref type_path) = field.ty {
|
||||||
let field_type_name = type_path.path.get_ident().unwrap().to_string();
|
let field_type_name = type_path.path.get_ident().unwrap().to_string();
|
||||||
if field_type_name == "ColorSource" || field_type_name == "Handle<Texture>" {
|
if field_type_name == "ColorSource" || field_type_name == "Handle<Texture>" {
|
||||||
eprintln!("madeit");
|
|
||||||
let texture_name = format!("{}_texture", name);
|
let texture_name = format!("{}_texture", name);
|
||||||
let sampler_name = format!("{}_sampler", name);
|
let sampler_name = format!("{}_sampler", name);
|
||||||
uniform_name_uniform_info.push(texture_name.clone());
|
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 {
|
uniform_info.push(quote!(bevy::render::render_graph::UniformInfo {
|
||||||
name: #name,
|
name: #name,
|
||||||
bind_type: bevy::render::render_graph::BindType::Uniform {
|
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 =
|
uniform infos
|
||||||
(0..uniform_info.len()).map(|i| quote!(&#info_ident[#i]));
|
|
||||||
|
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! {
|
TokenStream::from(quote! {
|
||||||
const #info_ident: &[bevy::render::render_graph::UniformInfo] = &[
|
const #info_ident: &[bevy::render::render_graph::UniformInfo] = &[
|
||||||
#(#uniform_info,)*
|
#(#uniform_info,)*
|
||||||
];
|
];
|
||||||
|
|
||||||
const #layout_ident: &[&[bevy::render::render_graph::UniformPropertyType]] = &[
|
const #field_uniform_names_ident: &[FieldUniformName] = &[
|
||||||
#(#layout_arrays,)*
|
#(#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
|
||||||
fn get_uniform_infos(&self) -> &[bevy::render::render_graph::UniformInfo] {
|
fn get_uniform_infos(&self) -> &[bevy::render::render_graph::UniformInfo] {
|
||||||
#info_ident
|
#info_ident
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_uniform_layouts(&self) -> &[&[bevy::render::render_graph::UniformPropertyType]] {
|
fn get_field_bind_type(&self, name: &str) -> bevy::render::render_graph::FieldBindType {
|
||||||
#layout_ident
|
#(#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>> {
|
fn get_uniform_bytes(&self, name: &str) -> Option<Vec<u8>> {
|
||||||
use bevy::core::bytes::GetBytes;
|
use bevy::core::bytes::GetBytes;
|
||||||
match name {
|
match name {
|
||||||
@ -181,12 +227,6 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
|
|||||||
_ => None,
|
_ => 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
|
// 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
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use crate::render::shader_reflect::ShaderLayout;
|
use crate::render::shader_reflect::ShaderLayout;
|
||||||
use std::{
|
use std::{
|
||||||
collections::{HashMap, hash_map::DefaultHasher, BTreeSet},
|
collections::{hash_map::DefaultHasher, BTreeSet, HashMap},
|
||||||
hash::{Hash, Hasher},
|
hash::{Hash, Hasher},
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -23,7 +23,11 @@ impl PipelineLayout {
|
|||||||
match bind_groups.get_mut(&shader_bind_group.index) {
|
match bind_groups.get_mut(&shader_bind_group.index) {
|
||||||
Some(bind_group) => {
|
Some(bind_group) => {
|
||||||
for shader_binding in shader_bind_group.bindings.iter() {
|
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 let Some(binding) = bind_group
|
||||||
|
.bindings
|
||||||
|
.iter()
|
||||||
|
.find(|binding| binding.index == shader_binding.index)
|
||||||
|
{
|
||||||
if binding != shader_binding {
|
if binding != shader_binding {
|
||||||
panic!("Binding {} in BindGroup {} does not match across all shader types: {:?} {:?}", binding.index, bind_group.index, binding, shader_binding);
|
panic!("Binding {} in BindGroup {} does not match across all shader types: {:?} {:?}", binding.index, bind_group.index, binding, shader_binding);
|
||||||
}
|
}
|
||||||
@ -31,19 +35,22 @@ impl PipelineLayout {
|
|||||||
bind_group.bindings.insert(shader_binding.clone());
|
bind_group.bindings.insert(shader_binding.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
None => {
|
None => {
|
||||||
bind_groups.insert(shader_bind_group.index, shader_bind_group.clone());
|
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
|
// 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());
|
bind_groups_result.sort_by(|a, b| a.index.partial_cmp(&b.index).unwrap());
|
||||||
PipelineLayout {
|
PipelineLayout {
|
||||||
bind_groups: bind_groups_result
|
bind_groups: bind_groups_result,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
asset::{AssetStorage, Handle, Texture},
|
asset::{AssetStorage, Handle},
|
||||||
legion::prelude::*,
|
legion::prelude::*,
|
||||||
render::{
|
render::{
|
||||||
render_graph::{
|
render_graph::{
|
||||||
|
|||||||
@ -46,10 +46,8 @@ where
|
|||||||
.count = 0;
|
.count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut sizes = Vec::new();
|
|
||||||
let mut counts = Vec::new();
|
let mut counts = Vec::new();
|
||||||
for (uniforms, _renderable) in query.iter(world) {
|
for (uniforms, _renderable) in query.iter(world) {
|
||||||
let uniform_layouts = uniforms.get_uniform_layouts();
|
|
||||||
for (i, uniform_info) in uniforms
|
for (i, uniform_info) in uniforms
|
||||||
.get_uniform_infos()
|
.get_uniform_infos()
|
||||||
.iter()
|
.iter()
|
||||||
@ -64,15 +62,6 @@ where
|
|||||||
{
|
{
|
||||||
// only add the first time a uniform info is processed
|
// only add the first time a uniform info is processed
|
||||||
if self.uniform_buffer_info_names.len() <= i {
|
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
|
self.uniform_buffer_info_names
|
||||||
.push(uniform_info.name.to_string());
|
.push(uniform_info.name.to_string());
|
||||||
}
|
}
|
||||||
@ -89,8 +78,7 @@ where
|
|||||||
// the expense of hashing for large numbers of entities
|
// the expense of hashing for large numbers of entities
|
||||||
for (i, name) in self.uniform_buffer_info_names.iter().enumerate() {
|
for (i, name) in self.uniform_buffer_info_names.iter().enumerate() {
|
||||||
if let None = renderer.get_dynamic_uniform_buffer_info(name) {
|
if let None = renderer.get_dynamic_uniform_buffer_info(name) {
|
||||||
let mut info = DynamicUniformBufferInfo::new();
|
let info = DynamicUniformBufferInfo::new();
|
||||||
info.size = sizes[i];
|
|
||||||
renderer.add_dynamic_uniform_buffer_info(name, info);
|
renderer.add_dynamic_uniform_buffer_info(name, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,16 +1,13 @@
|
|||||||
use crate::{
|
use crate::render::{color::ColorSource, render_graph::BindType};
|
||||||
render::render_graph::{BindType, UniformPropertyType},
|
|
||||||
};
|
|
||||||
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) -> &[UniformInfo];
|
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_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) -> FieldBindType;
|
||||||
// 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]>;
|
||||||
}
|
}
|
||||||
@ -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 struct UniformInfo<'a> {
|
||||||
pub name: &'a str,
|
pub name: &'a str,
|
||||||
pub bind_type: BindType,
|
pub bind_type: BindType,
|
||||||
@ -38,7 +62,6 @@ pub struct DynamicUniformBufferInfo {
|
|||||||
pub offsets: HashMap<Entity, u64>,
|
pub offsets: HashMap<Entity, u64>,
|
||||||
pub capacity: u64,
|
pub capacity: u64,
|
||||||
pub count: u64,
|
pub count: u64,
|
||||||
pub size: u64,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DynamicUniformBufferInfo {
|
impl DynamicUniformBufferInfo {
|
||||||
@ -48,7 +71,6 @@ impl DynamicUniformBufferInfo {
|
|||||||
count: 0,
|
count: 0,
|
||||||
indices: HashMap::new(),
|
indices: HashMap::new(),
|
||||||
offsets: HashMap::new(),
|
offsets: HashMap::new(),
|
||||||
size: 0,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
use crate::render::render_graph::{
|
use crate::render::render_graph::{
|
||||||
uniform::{AsUniforms, UniformInfo},
|
uniform::{AsUniforms, UniformInfo},
|
||||||
BindType, UniformPropertyType,
|
BindType, FieldBindType,
|
||||||
};
|
};
|
||||||
|
|
||||||
use zerocopy::AsBytes;
|
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 {
|
impl AsUniforms for bevy_transform::prelude::LocalToWorld {
|
||||||
fn get_uniform_infos(&self) -> &[UniformInfo] {
|
fn get_uniform_infos(&self) -> &[UniformInfo] {
|
||||||
LOCAL_TO_WORLD_UNIFORM_INFO
|
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>> {
|
fn get_uniform_bytes(&self, name: &str) -> Option<Vec<u8>> {
|
||||||
match name {
|
match name {
|
||||||
"Object" => Some(self.0.to_cols_array_2d().as_bytes().into()),
|
"Object" => Some(self.0.to_cols_array_2d().as_bytes().into()),
|
||||||
_ => None,
|
_ => 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>> {
|
fn get_shader_defs(&self) -> Option<Vec<String>> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
fn get_field_bind_type(&self, name: &str) -> FieldBindType {
|
||||||
|
FieldBindType::Uniform
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user