mirror of
https://github.com/bevyengine/bevy
synced 2024-09-20 06:22:01 +00:00
add RenderResources/RenderResource traits to replace Uniforms/Uniform
This commit is contained in:
parent
5add29f8cf
commit
fd8f87400d
30 changed files with 528 additions and 347 deletions
|
@ -3,7 +3,6 @@ use crate::{
|
|||
Handle, HandleId,
|
||||
};
|
||||
use bevy_app::{AppBuilder, Events, FromResources};
|
||||
use bevy_core::bytes::Bytes;
|
||||
use bevy_type_registry::RegisterType;
|
||||
use legion::prelude::*;
|
||||
use std::collections::HashMap;
|
||||
|
@ -108,13 +107,6 @@ impl<T> Assets<T> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<T> Bytes for Handle<T> {
|
||||
fn write_bytes(&self, _buffer: &mut [u8]) {}
|
||||
fn byte_len(&self) -> usize {
|
||||
0
|
||||
}
|
||||
}
|
||||
|
||||
pub trait AddAsset {
|
||||
fn add_asset<T>(&mut self) -> &mut Self
|
||||
where
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
use glam::{Mat4, Vec2, Vec3, Vec4};
|
||||
|
||||
pub use bevy_derive::Bytes;
|
||||
|
||||
pub trait Bytes {
|
||||
fn write_bytes(&self, buffer: &mut [u8]);
|
||||
fn byte_len(&self) -> usize;
|
||||
|
|
|
@ -2,8 +2,6 @@ pub mod bytes;
|
|||
pub mod time;
|
||||
pub mod transform;
|
||||
|
||||
pub use bevy_derive::Bytes;
|
||||
|
||||
use bevy_app::{stage, AppBuilder, AppPlugin};
|
||||
use bevy_transform::{
|
||||
components::{
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
use crate::modules::{get_modules, get_path};
|
||||
use crate::{
|
||||
attributes::get_field_attributes,
|
||||
modules::{get_modules, get_path},
|
||||
};
|
||||
use darling::FromMeta;
|
||||
use inflector::Inflector;
|
||||
use proc_macro::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
use syn::{parse_macro_input, Data, DataStruct, DeriveInput, Field, Fields, Path};
|
||||
use syn::{parse_macro_input, DeriveInput, Path};
|
||||
|
||||
#[derive(FromMeta, Debug, Default)]
|
||||
struct VertexAttributeArgs {
|
||||
|
@ -28,7 +31,7 @@ impl From<VertexAttributeArgs> for VertexAttributes {
|
|||
}
|
||||
}
|
||||
|
||||
static UNIFORM_ATTRIBUTE_NAME: &'static str = "uniform";
|
||||
static VERTEX_ATTRIBUTE_NAME: &'static str = "vertex";
|
||||
|
||||
pub fn derive_as_vertex_buffer_descriptor(input: TokenStream) -> TokenStream {
|
||||
let ast = parse_macro_input!(input as DeriveInput);
|
||||
|
@ -36,34 +39,10 @@ pub fn derive_as_vertex_buffer_descriptor(input: TokenStream) -> TokenStream {
|
|||
|
||||
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 field_attributes = fields
|
||||
.iter()
|
||||
.map(|f| {
|
||||
(
|
||||
f,
|
||||
f.attrs
|
||||
.iter()
|
||||
.find(|a| {
|
||||
a.path.get_ident().as_ref().unwrap().to_string() == UNIFORM_ATTRIBUTE_NAME
|
||||
})
|
||||
.map(|a| {
|
||||
VertexAttributes::from(
|
||||
VertexAttributeArgs::from_meta(&a.parse_meta().unwrap())
|
||||
.unwrap_or_else(|_err| VertexAttributeArgs::default()),
|
||||
)
|
||||
})
|
||||
.unwrap_or_else(|| VertexAttributes::default()),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<(&Field, VertexAttributes)>>();
|
||||
let field_attributes = get_field_attributes::<VertexAttributes, VertexAttributeArgs>(
|
||||
VERTEX_ATTRIBUTE_NAME,
|
||||
&ast.data,
|
||||
);
|
||||
|
||||
let struct_name = &ast.ident;
|
||||
|
||||
|
@ -133,4 +112,4 @@ pub fn derive_as_vertex_buffer_descriptor(input: TokenStream) -> TokenStream {
|
|||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
50
crates/bevy_derive/src/attributes.rs
Normal file
50
crates/bevy_derive/src/attributes.rs
Normal file
|
@ -0,0 +1,50 @@
|
|||
use darling::FromMeta;
|
||||
use syn::{Attribute, Data, DataStruct, Field, Fields};
|
||||
|
||||
pub fn get_field_attributes<'a, T, TArgs>(
|
||||
attribute_name: &str,
|
||||
data: &'a Data,
|
||||
) -> Vec<(&'a Field, T)>
|
||||
where
|
||||
T: Default,
|
||||
TArgs: FromMeta + Into<T> + Default,
|
||||
{
|
||||
let fields = match data {
|
||||
Data::Struct(DataStruct {
|
||||
fields: Fields::Named(fields),
|
||||
..
|
||||
}) => &fields.named,
|
||||
_ => panic!("expected a struct with named fields"),
|
||||
};
|
||||
|
||||
fields
|
||||
.iter()
|
||||
.map(|f| {
|
||||
(
|
||||
f,
|
||||
f.attrs
|
||||
.iter()
|
||||
.find(|a| a.path.get_ident().as_ref().unwrap().to_string() == attribute_name)
|
||||
.map(|a| {
|
||||
TArgs::from_meta(&a.parse_meta().unwrap())
|
||||
.unwrap_or_else(|_err| TArgs::default())
|
||||
})
|
||||
.unwrap_or_else(|| TArgs::default())
|
||||
.into(),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<(&Field, T)>>()
|
||||
}
|
||||
|
||||
pub fn get_attributes<'a, T, TArgs>(attribute_name: &str, attrs: &[Attribute]) -> T
|
||||
where
|
||||
T: Default,
|
||||
TArgs: FromMeta + Into<T> + Default,
|
||||
{
|
||||
attrs
|
||||
.iter()
|
||||
.find(|a| a.path.get_ident().as_ref().unwrap().to_string() == attribute_name)
|
||||
.map(|a| TArgs::from_meta(&a.parse_meta().unwrap()).unwrap_or_else(|_err| TArgs::default()))
|
||||
.unwrap_or_else(|| TArgs::default())
|
||||
.into()
|
||||
}
|
|
@ -1,15 +1,8 @@
|
|||
use crate::modules::{get_modules, get_path};
|
||||
use darling::FromMeta;
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{parse_macro_input, Data, DataStruct, DeriveInput, Fields, Ident};
|
||||
|
||||
#[derive(FromMeta, Debug, Default)]
|
||||
struct EntityArchetypeAttributeArgs {
|
||||
#[darling(default)]
|
||||
pub tag: Option<bool>,
|
||||
}
|
||||
|
||||
pub fn derive_entity_archetype(input: TokenStream) -> TokenStream {
|
||||
let ast = parse_macro_input!(input as DeriveInput);
|
||||
let fields = match &ast.data {
|
||||
|
@ -24,25 +17,8 @@ pub fn derive_entity_archetype(input: TokenStream) -> TokenStream {
|
|||
let bevy_app_path = get_path(&modules.bevy_app);
|
||||
let legion_path = get_path(&modules.legion);
|
||||
|
||||
let tag_fields = fields
|
||||
.iter()
|
||||
.filter(|f| {
|
||||
f.attrs
|
||||
.iter()
|
||||
.find(|a| a.path.get_ident().as_ref().unwrap().to_string() == "tag")
|
||||
.is_some()
|
||||
})
|
||||
.map(|field| field.ident.as_ref().unwrap())
|
||||
.collect::<Vec<&Ident>>();
|
||||
|
||||
let component_fields = fields
|
||||
.iter()
|
||||
.filter(|f| {
|
||||
f.attrs
|
||||
.iter()
|
||||
.find(|a| a.path.get_ident().as_ref().unwrap().to_string() == "tag")
|
||||
.is_none()
|
||||
})
|
||||
.map(|field| field.ident.as_ref().unwrap())
|
||||
.collect::<Vec<&Ident>>();
|
||||
|
||||
|
@ -54,7 +30,7 @@ pub fn derive_entity_archetype(input: TokenStream) -> TokenStream {
|
|||
TokenStream::from(quote! {
|
||||
impl #impl_generics #bevy_app_path::EntityArchetype for #struct_name#ty_generics {
|
||||
fn insert(self, world: &mut #legion_path::prelude::World) -> #legion_path::prelude::Entity {
|
||||
*world.insert((#(self.#tag_fields,)*),
|
||||
*world.insert((),
|
||||
vec![(
|
||||
#(self.#component_fields,)*
|
||||
)
|
||||
|
@ -62,7 +38,7 @@ pub fn derive_entity_archetype(input: TokenStream) -> TokenStream {
|
|||
}
|
||||
|
||||
fn insert_command_buffer(self, command_buffer: &mut #legion_path::prelude::CommandBuffer) -> #legion_path::prelude::Entity {
|
||||
*command_buffer.insert((#(self.#tag_fields,)*),
|
||||
*command_buffer.insert((),
|
||||
vec![(
|
||||
#(self.#component_fields,)*
|
||||
)
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
extern crate proc_macro;
|
||||
|
||||
mod app_plugin;
|
||||
mod attributes;
|
||||
mod bytes;
|
||||
mod entity_archetype;
|
||||
mod modules;
|
||||
mod render_resources;
|
||||
mod render_resource;
|
||||
mod resource;
|
||||
mod uniforms;
|
||||
mod as_vertex_buffer_descriptor;
|
||||
|
@ -30,6 +33,16 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
|
|||
uniforms::derive_uniforms(input)
|
||||
}
|
||||
|
||||
#[proc_macro_derive(RenderResources, attributes(render_resources, module))]
|
||||
pub fn derive_render_resources(input: TokenStream) -> TokenStream {
|
||||
render_resources::derive_render_resources(input)
|
||||
}
|
||||
|
||||
#[proc_macro_derive(RenderResource, attributes(module))]
|
||||
pub fn derive_render_resource(input: TokenStream) -> TokenStream {
|
||||
render_resource::derive_render_resource(input)
|
||||
}
|
||||
|
||||
#[proc_macro_derive(AsVertexBufferDescriptor, attributes(vertex, module))]
|
||||
pub fn derive_as_vertex_buffer_descriptor(input: TokenStream) -> TokenStream {
|
||||
as_vertex_buffer_descriptor::derive_as_vertex_buffer_descriptor(input)
|
||||
|
@ -44,4 +57,4 @@ pub fn derive_entity_archetype(input: TokenStream) -> TokenStream {
|
|||
#[proc_macro_derive(DynamicAppPlugin)]
|
||||
pub fn derive_app_plugin(input: TokenStream) -> TokenStream {
|
||||
app_plugin::derive_dynamic_app_plugin(input)
|
||||
}
|
||||
}
|
33
crates/bevy_derive/src/render_resource.rs
Normal file
33
crates/bevy_derive/src/render_resource.rs
Normal file
|
@ -0,0 +1,33 @@
|
|||
use crate::modules::{get_modules, get_path};
|
||||
use proc_macro::TokenStream;
|
||||
use quote::quote;
|
||||
use syn::{parse_macro_input, DeriveInput, Path};
|
||||
|
||||
pub fn derive_render_resource(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 bevy_asset_path: Path = get_path(&modules.bevy_asset);
|
||||
let bevy_core_path: Path = get_path(&modules.bevy_core);
|
||||
let struct_name = &ast.ident;
|
||||
|
||||
TokenStream::from(quote! {
|
||||
impl #bevy_render_path::render_resource::RenderResource for #struct_name {
|
||||
fn resource_info(&self) -> Option<#bevy_render_path::render_resource::ResourceInfo> {
|
||||
Some(#bevy_render_path::render_resource::ResourceInfo::Buffer(None))
|
||||
}
|
||||
fn write_buffer_bytes(&self, buffer: &mut [u8]) {
|
||||
use #bevy_core_path::bytes::Bytes;
|
||||
self.write_bytes(buffer);
|
||||
}
|
||||
fn buffer_byte_len(&self) -> Option<usize> {
|
||||
Some(self.byte_len())
|
||||
}
|
||||
fn texture(&self) -> Option<#bevy_asset_path::Handle<#bevy_render_path::texture::Texture>> {
|
||||
None
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
}
|
148
crates/bevy_derive/src/render_resources.rs
Normal file
148
crates/bevy_derive/src/render_resources.rs
Normal file
|
@ -0,0 +1,148 @@
|
|||
use crate::{
|
||||
attributes::{get_attributes, get_field_attributes},
|
||||
modules::{get_modules, get_path},
|
||||
};
|
||||
use darling::FromMeta;
|
||||
use proc_macro::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
use syn::{parse_macro_input, DeriveInput, Path};
|
||||
|
||||
#[derive(FromMeta, Debug, Default)]
|
||||
struct RenderResourceAttributeArgs {
|
||||
#[darling(default)]
|
||||
pub ignore: Option<bool>,
|
||||
#[darling(default)]
|
||||
pub buffer: Option<bool>,
|
||||
#[darling(default)]
|
||||
pub from_self: Option<bool>,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
struct RenderResourceAttributes {
|
||||
pub ignore: bool,
|
||||
pub buffer: bool,
|
||||
pub from_self: bool,
|
||||
}
|
||||
|
||||
impl From<RenderResourceAttributeArgs> for RenderResourceAttributes {
|
||||
fn from(args: RenderResourceAttributeArgs) -> Self {
|
||||
Self {
|
||||
ignore: args.ignore.unwrap_or(false),
|
||||
buffer: args.buffer.unwrap_or(false),
|
||||
from_self: args.from_self.unwrap_or(false),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static RENDER_RESOURCE_ATTRIBUTE_NAME: &'static str = "render_resources";
|
||||
|
||||
pub fn derive_render_resources(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 attributes = get_attributes::<RenderResourceAttributes, RenderResourceAttributeArgs>(
|
||||
RENDER_RESOURCE_ATTRIBUTE_NAME,
|
||||
&ast.attrs,
|
||||
);
|
||||
let struct_name = &ast.ident;
|
||||
let struct_name_string = struct_name.to_string();
|
||||
|
||||
if attributes.from_self {
|
||||
TokenStream::from(quote! {
|
||||
impl #bevy_render_path::render_resource::RenderResources for #struct_name {
|
||||
fn render_resources_len(&self) -> usize {
|
||||
1
|
||||
}
|
||||
|
||||
fn get_render_resource(&self, index: usize) -> Option<&dyn #bevy_render_path::render_resource::RenderResource> {
|
||||
if index == 0 {
|
||||
Some(self)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn get_render_resource_name(&self, index: usize) -> Option<&str> {
|
||||
if index == 0 {
|
||||
Some(#struct_name_string)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn iter_render_resources(&self) -> #bevy_render_path::render_resource::RenderResourceIterator {
|
||||
#bevy_render_path::render_resource::RenderResourceIterator::new(self)
|
||||
}
|
||||
}
|
||||
})
|
||||
} else {
|
||||
let field_attributes = get_field_attributes::<
|
||||
RenderResourceAttributes,
|
||||
RenderResourceAttributeArgs,
|
||||
>(RENDER_RESOURCE_ATTRIBUTE_NAME, &ast.data);
|
||||
|
||||
let mut render_resource_names = Vec::new();
|
||||
let mut render_resource_fields = Vec::new();
|
||||
let mut render_resource_hints = Vec::new();
|
||||
for (field, attrs) in field_attributes.iter() {
|
||||
if attrs.ignore {
|
||||
continue;
|
||||
}
|
||||
|
||||
let field_ident = field.ident.as_ref().unwrap();
|
||||
let field_name = field_ident.to_string();
|
||||
render_resource_fields.push(field_ident);
|
||||
render_resource_names.push(format!("{}_{}", struct_name, field_name));
|
||||
if attrs.buffer {
|
||||
render_resource_hints.push(quote! {Some(#bevy_render_path::render_resource::RenderResourceHints::BUFFER)})
|
||||
} else {
|
||||
render_resource_hints.push(quote! {None})
|
||||
}
|
||||
}
|
||||
|
||||
let render_resource_count = render_resource_names.len();
|
||||
let render_resource_indices = 0..render_resource_count;
|
||||
|
||||
let struct_name_uppercase = struct_name_string.to_uppercase();
|
||||
let render_resource_names_ident =
|
||||
format_ident!("{}_RENDER_RESOURCE_NAMES", struct_name_uppercase);
|
||||
let render_resource_hints_ident =
|
||||
format_ident!("{}_RENDER_RESOURCE_HINTS", struct_name_uppercase);
|
||||
|
||||
TokenStream::from(quote! {
|
||||
static #render_resource_names_ident: &[&str] = &[
|
||||
#(#render_resource_names,)*
|
||||
];
|
||||
|
||||
static #render_resource_hints_ident: &[Option<#bevy_render_path::render_resource::RenderResourceHints>] = &[
|
||||
#(#render_resource_hints,)*
|
||||
];
|
||||
|
||||
impl #bevy_render_path::render_resource::RenderResources for #struct_name {
|
||||
fn render_resources_len(&self) -> usize {
|
||||
#render_resource_count
|
||||
}
|
||||
|
||||
fn get_render_resource(&self, index: usize) -> Option<&dyn #bevy_render_path::render_resource::RenderResource> {
|
||||
match index {
|
||||
#(#render_resource_indices => Some(&self.#render_resource_fields),)*
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
fn get_render_resource_name(&self, index: usize) -> Option<&str> {
|
||||
Some(#render_resource_names_ident[index])
|
||||
}
|
||||
|
||||
fn get_render_resource_hints(&self, index: usize) -> Option<#bevy_render_path::render_resource::RenderResourceHints> {
|
||||
#render_resource_hints_ident[index].clone()
|
||||
}
|
||||
|
||||
fn iter_render_resources(&self) -> #bevy_render_path::render_resource::RenderResourceIterator {
|
||||
#bevy_render_path::render_resource::RenderResourceIterator::new(self)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,9 +1,12 @@
|
|||
use crate::modules::{get_modules, get_path};
|
||||
use crate::{
|
||||
attributes::get_field_attributes,
|
||||
modules::{get_modules, get_path},
|
||||
};
|
||||
use darling::FromMeta;
|
||||
use inflector::Inflector;
|
||||
use proc_macro::TokenStream;
|
||||
use quote::{format_ident, quote};
|
||||
use syn::{parse_macro_input, Data, DataStruct, DeriveInput, Field, Fields, Path};
|
||||
use syn::{parse_macro_input, DeriveInput, Path};
|
||||
|
||||
#[derive(FromMeta, Debug, Default)]
|
||||
struct UniformAttributeArgs {
|
||||
|
@ -42,34 +45,10 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
|
|||
let bevy_core_path: Path = get_path(&modules.bevy_core);
|
||||
let bevy_asset_path: Path = get_path(&modules.bevy_asset);
|
||||
|
||||
let fields = match &ast.data {
|
||||
Data::Struct(DataStruct {
|
||||
fields: Fields::Named(fields),
|
||||
..
|
||||
}) => &fields.named,
|
||||
_ => panic!("expected a struct with named fields"),
|
||||
};
|
||||
|
||||
let field_attributes = fields
|
||||
.iter()
|
||||
.map(|f| {
|
||||
(
|
||||
f,
|
||||
f.attrs
|
||||
.iter()
|
||||
.find(|a| {
|
||||
a.path.get_ident().as_ref().unwrap().to_string() == UNIFORM_ATTRIBUTE_NAME
|
||||
})
|
||||
.map(|a| {
|
||||
UniformAttributes::from(
|
||||
UniformAttributeArgs::from_meta(&a.parse_meta().unwrap())
|
||||
.unwrap_or_else(|_err| UniformAttributeArgs::default()),
|
||||
)
|
||||
})
|
||||
.unwrap_or_else(|| UniformAttributes::default()),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<(&Field, UniformAttributes)>>();
|
||||
let field_attributes = get_field_attributes::<UniformAttributes, UniformAttributeArgs>(
|
||||
UNIFORM_ATTRIBUTE_NAME,
|
||||
&ast.data,
|
||||
);
|
||||
|
||||
let struct_name = &ast.ident;
|
||||
|
||||
|
@ -141,34 +120,18 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
|
|||
}
|
||||
|
||||
fn get_field_bind_type(&self, name: &str) -> Option<#bevy_render_path::shader::FieldBindType> {
|
||||
use #bevy_render_path::shader::GetFieldBindType;
|
||||
match name {
|
||||
#(#active_uniform_field_name_strings => #get_field_bind_types,)*
|
||||
_ => None,
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn get_uniform_texture(&self, name: &str) -> Option<#bevy_asset_path::Handle<#bevy_render_path::texture::Texture>> {
|
||||
use #bevy_render_path::shader::GetTexture;
|
||||
match name {
|
||||
#(#texture_and_sampler_name_strings => self.#texture_and_sampler_name_idents.get_texture(),)*
|
||||
_ => None,
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn write_uniform_bytes(&self, name: &str, buffer: &mut [u8]) {
|
||||
use #bevy_core_path::bytes::Bytes;
|
||||
match name {
|
||||
#(#uniform_name_strings => self.#active_uniform_field_names.write_bytes(buffer),)*
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
fn uniform_byte_len(&self, name: &str) -> usize {
|
||||
use #bevy_core_path::bytes::Bytes;
|
||||
match name {
|
||||
#(#uniform_name_strings => self.#active_uniform_field_names.byte_len(),)*
|
||||
_ => 0,
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
// TODO: move this to field_info and add has_shader_def(&self, &str) -> bool
|
||||
|
@ -194,7 +157,6 @@ pub fn derive_uniform(input: TokenStream) -> TokenStream {
|
|||
|
||||
let modules = get_modules(&ast);
|
||||
let bevy_asset_path = get_path(&modules.bevy_asset);
|
||||
let bevy_core_path = get_path(&modules.bevy_core);
|
||||
let bevy_render_path = get_path(&modules.bevy_render);
|
||||
|
||||
let generics = ast.generics;
|
||||
|
@ -218,26 +180,13 @@ pub fn derive_uniform(input: TokenStream) -> TokenStream {
|
|||
}
|
||||
|
||||
fn get_field_bind_type(&self, name: &str) -> Option<#bevy_render_path::shader::FieldBindType> {
|
||||
use #bevy_render_path::shader::GetFieldBindType;
|
||||
match name {
|
||||
#struct_name_string => self.get_bind_type(),
|
||||
_ => None,
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn write_uniform_bytes(&self, name: &str, buffer: &mut [u8]) {
|
||||
use #bevy_core_path::bytes::Bytes;
|
||||
match name {
|
||||
#struct_name_string => self.write_bytes(buffer),
|
||||
_ => {},
|
||||
}
|
||||
}
|
||||
fn uniform_byte_len(&self, name: &str) -> usize {
|
||||
use #bevy_core_path::bytes::Bytes;
|
||||
match name {
|
||||
#struct_name_string => self.byte_len(),
|
||||
_ => 0,
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
fn get_uniform_texture(&self, name: &str) -> Option<#bevy_asset_path::Handle<#bevy_render_path::texture::Texture>> {
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use bevy_asset::{self, Handle};
|
||||
use bevy_derive::Uniforms;
|
||||
use bevy_render::{texture::Texture, Color};
|
||||
use bevy_render::{render_resource::RenderResources, shader::Uniforms, texture::Texture, Color};
|
||||
|
||||
#[derive(Uniforms)]
|
||||
#[derive(Uniforms, RenderResources)]
|
||||
pub struct StandardMaterial {
|
||||
pub albedo: Color,
|
||||
#[uniform(shader_def)]
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use super::texture::Texture;
|
||||
use crate::shader::ShaderDefSuffixProvider;
|
||||
use crate::{render_resource::{ResourceInfo, RenderResource}, shader::ShaderDefSuffixProvider, impl_render_resource_bytes};
|
||||
use bevy_asset::Handle;
|
||||
use bevy_core::bytes::{Byteable, Bytes};
|
||||
use bevy_property::Property;
|
||||
|
@ -138,3 +138,5 @@ impl ShaderDefSuffixProvider for ColorSource {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_render_resource_bytes!(Color);
|
|
@ -45,7 +45,7 @@ impl DrawTarget for MeshesDrawTarget {
|
|||
render_resources.get_resource_info(
|
||||
index_buffer_resource,
|
||||
&mut |resource_info| match resource_info {
|
||||
Some(ResourceInfo::Buffer(buffer_info)) => {
|
||||
Some(ResourceInfo::Buffer(Some(buffer_info))) => {
|
||||
current_mesh_index_len = (buffer_info.size / 2) as u32
|
||||
}
|
||||
_ => panic!("expected a buffer type"),
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
use crate::{
|
||||
render_graph::{CommandQueue, Node, ResourceSlots, SystemNode},
|
||||
render_resource::{
|
||||
BufferInfo, BufferUsage, EntitiesWaitingForAssets, RenderResourceId,
|
||||
RenderResourceAssignment, RenderResourceAssignments, RenderResourceAssignmentsId,
|
||||
self, BufferInfo, BufferUsage, EntitiesWaitingForAssets, RenderResourceAssignment,
|
||||
RenderResourceAssignments, RenderResourceAssignmentsId, RenderResourceId, RenderResourceHints,
|
||||
},
|
||||
renderer::{RenderContext, RenderResourceContext, RenderResources},
|
||||
shader::{Uniforms, FieldBindType},
|
||||
texture, Renderable,
|
||||
};
|
||||
|
||||
use bevy_asset::{Assets, Handle};
|
||||
use legion::prelude::*;
|
||||
use render_resource::ResourceInfo;
|
||||
use std::{collections::HashMap, marker::PhantomData};
|
||||
|
||||
pub const BIND_BUFFER_ALIGNMENT: usize = 256;
|
||||
|
@ -53,25 +53,28 @@ impl BufferArrayStatus {
|
|||
|
||||
struct UniformBufferArrays<T>
|
||||
where
|
||||
T: Uniforms,
|
||||
T: render_resource::RenderResources,
|
||||
{
|
||||
uniform_arrays: Vec<Option<(String, BufferArrayStatus)>>,
|
||||
_marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> UniformBufferArrays<T>
|
||||
impl<T> Default for UniformBufferArrays<T>
|
||||
where
|
||||
T: Uniforms,
|
||||
T: render_resource::RenderResources,
|
||||
{
|
||||
fn new() -> Self {
|
||||
let mut uniform_arrays = Vec::new();
|
||||
let field_infos = T::get_field_infos();
|
||||
uniform_arrays.resize_with(field_infos.len(), || None);
|
||||
UniformBufferArrays {
|
||||
uniform_arrays,
|
||||
_marker: PhantomData::default(),
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
uniform_arrays: Default::default(),
|
||||
_marker: Default::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> UniformBufferArrays<T>
|
||||
where
|
||||
T: render_resource::RenderResources,
|
||||
{
|
||||
fn reset_new_item_counts(&mut self) {
|
||||
for buffer_status in self.uniform_arrays.iter_mut() {
|
||||
if let Some((_name, buffer_status)) = buffer_status {
|
||||
|
@ -81,15 +84,19 @@ where
|
|||
}
|
||||
|
||||
fn increment_uniform_counts(&mut self, uniforms: &T) {
|
||||
for (i, field_info) in T::get_field_infos().iter().enumerate() {
|
||||
if let Some(FieldBindType::Uniform { size }) | Some(FieldBindType::Buffer { size }) =
|
||||
uniforms.get_field_bind_type(&field_info.name)
|
||||
{
|
||||
if self.uniform_arrays.len() != uniforms.render_resources_len() {
|
||||
self.uniform_arrays
|
||||
.resize_with(uniforms.render_resources_len(), || None);
|
||||
}
|
||||
for (i, render_resource) in uniforms.iter_render_resources().enumerate() {
|
||||
if let Some(ResourceInfo::Buffer(_)) = render_resource.resource_info() {
|
||||
let render_resource_name = uniforms.get_render_resource_name(i).unwrap();
|
||||
let size = render_resource.buffer_byte_len().unwrap();
|
||||
if let Some((ref _name, ref mut buffer_array_status)) = self.uniform_arrays[i] {
|
||||
buffer_array_status.new_item_count += 1;
|
||||
} else {
|
||||
self.uniform_arrays[i] = Some((
|
||||
field_info.uniform_name.to_string(),
|
||||
render_resource_name.to_string(),
|
||||
BufferArrayStatus {
|
||||
new_item_count: 1,
|
||||
queued_buffer_writes: Vec::new(),
|
||||
|
@ -182,10 +189,11 @@ where
|
|||
render_resource_assignments: &mut RenderResourceAssignments,
|
||||
staging_buffer: &mut [u8],
|
||||
) {
|
||||
for (i, field_info) in T::get_field_infos().iter().enumerate() {
|
||||
let bind_type = uniforms.get_field_bind_type(&field_info.name);
|
||||
match bind_type {
|
||||
Some(FieldBindType::Uniform { size }) | Some(FieldBindType::Buffer { size }) => {
|
||||
for (i, render_resource) in uniforms.iter_render_resources().enumerate() {
|
||||
match render_resource.resource_info() {
|
||||
Some(ResourceInfo::Buffer(_)) => {
|
||||
let size = render_resource.buffer_byte_len().unwrap();
|
||||
let render_resource_name = uniforms.get_render_resource_name(i).unwrap();
|
||||
let (_name, uniform_buffer_status) = self.uniform_arrays[i].as_mut().unwrap();
|
||||
let range = 0..size as u64;
|
||||
let (target_buffer, target_offset) = if dynamic_uniforms {
|
||||
|
@ -193,7 +201,7 @@ where
|
|||
let index = uniform_buffer_status
|
||||
.get_or_assign_index(render_resource_assignments.id);
|
||||
render_resource_assignments.set(
|
||||
&field_info.uniform_name,
|
||||
render_resource_name,
|
||||
RenderResourceAssignment::Buffer {
|
||||
resource: buffer,
|
||||
dynamic_index: Some(
|
||||
|
@ -204,16 +212,18 @@ where
|
|||
);
|
||||
(buffer, index * uniform_buffer_status.aligned_size)
|
||||
} else {
|
||||
let resource = match render_resource_assignments
|
||||
.get(field_info.uniform_name)
|
||||
{
|
||||
let resource = match render_resource_assignments.get(render_resource_name) {
|
||||
Some(assignment) => assignment.get_resource(),
|
||||
None => {
|
||||
let usage = if let Some(FieldBindType::Buffer { .. }) = bind_type {
|
||||
BufferUsage::STORAGE
|
||||
} else {
|
||||
BufferUsage::UNIFORM
|
||||
};
|
||||
// TODO: RE-ADD support for BufferUsage::STORAGE type
|
||||
let mut usage = BufferUsage::UNIFORM;
|
||||
|
||||
if let Some(render_resource_hints) = uniforms.get_render_resource_hints(i) {
|
||||
if render_resource_hints.contains(RenderResourceHints::BUFFER) {
|
||||
usage = BufferUsage::STORAGE
|
||||
}
|
||||
}
|
||||
|
||||
let resource = render_resources.create_buffer(BufferInfo {
|
||||
size,
|
||||
buffer_usage: BufferUsage::COPY_DST | usage,
|
||||
|
@ -221,7 +231,7 @@ where
|
|||
});
|
||||
|
||||
render_resource_assignments.set(
|
||||
&field_info.uniform_name,
|
||||
render_resource_name,
|
||||
RenderResourceAssignment::Buffer {
|
||||
resource,
|
||||
range,
|
||||
|
@ -238,23 +248,9 @@ where
|
|||
let staging_buffer_start = uniform_buffer_status.staging_buffer_offset
|
||||
+ (uniform_buffer_status.queued_buffer_writes.len()
|
||||
* uniform_buffer_status.item_size);
|
||||
let uniform_byte_len = uniforms.uniform_byte_len(&field_info.uniform_name);
|
||||
if uniform_byte_len > 0 {
|
||||
if size != uniform_byte_len {
|
||||
panic!("The number of bytes produced for {} do not match the expected count. Actual: {}. Expected: {}.", field_info.uniform_name, uniform_byte_len, size);
|
||||
}
|
||||
|
||||
uniforms.write_uniform_bytes(
|
||||
&field_info.uniform_name,
|
||||
&mut staging_buffer
|
||||
[staging_buffer_start..(staging_buffer_start + uniform_byte_len)],
|
||||
);
|
||||
} else {
|
||||
panic!(
|
||||
"failed to get data from uniform: {}",
|
||||
field_info.uniform_name
|
||||
);
|
||||
};
|
||||
render_resource.write_buffer_bytes(
|
||||
&mut staging_buffer[staging_buffer_start..(staging_buffer_start + size)],
|
||||
);
|
||||
|
||||
uniform_buffer_status
|
||||
.queued_buffer_writes
|
||||
|
@ -263,7 +259,8 @@ where
|
|||
offset: target_offset,
|
||||
});
|
||||
}
|
||||
Some(FieldBindType::Texture) => { /* ignore textures */ }
|
||||
Some(ResourceInfo::Texture(_)) => { /* ignore textures */ }
|
||||
Some(ResourceInfo::Sampler) => { /* ignore samplers */ }
|
||||
None => { /* ignore None */ }
|
||||
}
|
||||
}
|
||||
|
@ -347,7 +344,7 @@ where
|
|||
#[derive(Default)]
|
||||
pub struct UniformNode<T>
|
||||
where
|
||||
T: Uniforms,
|
||||
T: render_resource::RenderResources,
|
||||
{
|
||||
command_queue: CommandQueue,
|
||||
dynamic_uniforms: bool,
|
||||
|
@ -356,7 +353,7 @@ where
|
|||
|
||||
impl<T> UniformNode<T>
|
||||
where
|
||||
T: Uniforms,
|
||||
T: render_resource::RenderResources,
|
||||
{
|
||||
pub fn new(dynamic_uniforms: bool) -> Self {
|
||||
UniformNode {
|
||||
|
@ -369,7 +366,7 @@ where
|
|||
|
||||
impl<T> Node for UniformNode<T>
|
||||
where
|
||||
T: Uniforms,
|
||||
T: render_resource::RenderResources,
|
||||
{
|
||||
fn update(
|
||||
&mut self,
|
||||
|
@ -385,11 +382,11 @@ where
|
|||
|
||||
impl<T> SystemNode for UniformNode<T>
|
||||
where
|
||||
T: Uniforms,
|
||||
T: render_resource::RenderResources,
|
||||
{
|
||||
fn get_system(&self) -> Box<dyn Schedulable> {
|
||||
let mut command_queue = self.command_queue.clone();
|
||||
let mut uniform_buffer_arrays = UniformBufferArrays::<T>::new();
|
||||
let mut uniform_buffer_arrays = UniformBufferArrays::<T>::default();
|
||||
let dynamic_uniforms = self.dynamic_uniforms;
|
||||
// TODO: maybe run "update" here
|
||||
SystemBuilder::new(format!(
|
||||
|
@ -505,7 +502,7 @@ where
|
|||
#[derive(Default)]
|
||||
pub struct AssetUniformNode<T>
|
||||
where
|
||||
T: Uniforms,
|
||||
T: render_resource::RenderResources,
|
||||
{
|
||||
command_queue: CommandQueue,
|
||||
dynamic_uniforms: bool,
|
||||
|
@ -514,7 +511,7 @@ where
|
|||
|
||||
impl<T> AssetUniformNode<T>
|
||||
where
|
||||
T: Uniforms,
|
||||
T: render_resource::RenderResources,
|
||||
{
|
||||
pub fn new(dynamic_uniforms: bool) -> Self {
|
||||
AssetUniformNode {
|
||||
|
@ -527,7 +524,7 @@ where
|
|||
|
||||
impl<T> Node for AssetUniformNode<T>
|
||||
where
|
||||
T: Uniforms,
|
||||
T: render_resource::RenderResources,
|
||||
{
|
||||
fn update(
|
||||
&mut self,
|
||||
|
@ -543,11 +540,11 @@ where
|
|||
|
||||
impl<T> SystemNode for AssetUniformNode<T>
|
||||
where
|
||||
T: Uniforms,
|
||||
T: render_resource::RenderResources,
|
||||
{
|
||||
fn get_system(&self) -> Box<dyn Schedulable> {
|
||||
let mut command_queue = self.command_queue.clone();
|
||||
let mut uniform_buffer_arrays = UniformBufferArrays::<T>::new();
|
||||
let mut uniform_buffer_arrays = UniformBufferArrays::<T>::default();
|
||||
let dynamic_uniforms = self.dynamic_uniforms;
|
||||
// TODO: maybe run "update" here
|
||||
SystemBuilder::new("uniform_resource_provider")
|
||||
|
@ -677,12 +674,13 @@ fn setup_uniform_texture_resources<T>(
|
|||
entities_waiting_for_assets: &EntitiesWaitingForAssets,
|
||||
render_resource_assignments: &mut RenderResourceAssignments,
|
||||
) where
|
||||
T: Uniforms,
|
||||
T: render_resource::RenderResources,
|
||||
{
|
||||
for field_info in T::get_field_infos().iter() {
|
||||
let bind_type = uniforms.get_field_bind_type(&field_info.name);
|
||||
if let Some(FieldBindType::Texture) = bind_type {
|
||||
if let Some(texture_handle) = uniforms.get_uniform_texture(&field_info.texture_name) {
|
||||
for (i, render_resource) in uniforms.iter_render_resources().enumerate() {
|
||||
if let Some(ResourceInfo::Texture(_)) = render_resource.resource_info() {
|
||||
let render_resource_name = uniforms.get_render_resource_name(i).unwrap();
|
||||
let sampler_name = format!("{}_sampler", render_resource_name);
|
||||
if let Some(texture_handle) = render_resource.texture() {
|
||||
if let Some(texture_resource) = render_resource_context
|
||||
.get_asset_resource(texture_handle, texture::TEXTURE_ASSET_INDEX)
|
||||
{
|
||||
|
@ -690,11 +688,11 @@ fn setup_uniform_texture_resources<T>(
|
|||
.get_asset_resource(texture_handle, texture::SAMPLER_ASSET_INDEX)
|
||||
.unwrap();
|
||||
render_resource_assignments.set(
|
||||
field_info.texture_name,
|
||||
render_resource_name,
|
||||
RenderResourceAssignment::Texture(texture_resource),
|
||||
);
|
||||
render_resource_assignments.set(
|
||||
field_info.sampler_name,
|
||||
&sampler_name,
|
||||
RenderResourceAssignment::Sampler(sampler_resource),
|
||||
);
|
||||
continue;
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
use super::ResourceInfo;
|
||||
use crate::texture::Texture;
|
||||
use bevy_asset::Handle;
|
||||
use uuid::Uuid;
|
||||
|
||||
// TODO: Rename to RenderResourceId
|
||||
use bevy_core::bytes::{Byteable, Bytes};
|
||||
pub use bevy_derive::{RenderResource, RenderResources};
|
||||
use glam::{Mat4, Vec2, Vec3, Vec4};
|
||||
|
||||
#[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
|
||||
pub struct RenderResourceId(Uuid);
|
||||
|
||||
|
@ -9,3 +15,101 @@ impl RenderResourceId {
|
|||
RenderResourceId(Uuid::new_v4())
|
||||
}
|
||||
}
|
||||
|
||||
bitflags::bitflags! {
|
||||
#[repr(transparent)]
|
||||
pub struct RenderResourceHints: u32 {
|
||||
const BUFFER = 1;
|
||||
}
|
||||
}
|
||||
|
||||
pub trait RenderResource {
|
||||
fn resource_info(&self) -> Option<ResourceInfo>;
|
||||
fn write_buffer_bytes(&self, buffer: &mut [u8]);
|
||||
fn buffer_byte_len(&self) -> Option<usize>;
|
||||
// TODO: consider making these panic by default, but return non-options
|
||||
fn texture(&self) -> Option<Handle<Texture>>;
|
||||
}
|
||||
|
||||
pub trait RenderResources: Send + Sync + 'static {
|
||||
fn render_resources_len(&self) -> usize;
|
||||
fn get_render_resource(&self, index: usize) -> Option<&dyn RenderResource>;
|
||||
fn get_render_resource_name(&self, index: usize) -> Option<&str>;
|
||||
fn get_render_resource_hints(&self, _index: usize) -> Option<RenderResourceHints> {
|
||||
None
|
||||
}
|
||||
fn iter_render_resources(&self) -> RenderResourceIterator;
|
||||
}
|
||||
|
||||
pub struct RenderResourceIterator<'a> {
|
||||
render_resources: &'a dyn RenderResources,
|
||||
index: usize,
|
||||
}
|
||||
|
||||
impl<'a> RenderResourceIterator<'a> {
|
||||
pub fn new(render_resources: &'a dyn RenderResources) -> Self {
|
||||
Self {
|
||||
render_resources,
|
||||
index: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl<'a> Iterator for RenderResourceIterator<'a> {
|
||||
type Item = &'a dyn RenderResource;
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if self.index == self.render_resources.render_resources_len() {
|
||||
None
|
||||
} else {
|
||||
let render_resource = self
|
||||
.render_resources
|
||||
.get_render_resource(self.index)
|
||||
.unwrap();
|
||||
self.index += 1;
|
||||
Some(render_resource)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_render_resource_bytes {
|
||||
($ty:ident) => {
|
||||
impl RenderResource for $ty {
|
||||
fn resource_info(&self) -> Option<ResourceInfo> {
|
||||
Some(ResourceInfo::Buffer(None))
|
||||
}
|
||||
fn write_buffer_bytes(&self, buffer: &mut [u8]) {
|
||||
self.write_bytes(buffer);
|
||||
}
|
||||
fn buffer_byte_len(&self) -> Option<usize> {
|
||||
Some(self.byte_len())
|
||||
}
|
||||
fn texture(&self) -> Option<Handle<Texture>> {
|
||||
None
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// TODO: when specialization lands, replace these with impl<T> RenderResource for T where T: Bytes
|
||||
impl_render_resource_bytes!(Vec2);
|
||||
impl_render_resource_bytes!(Vec3);
|
||||
impl_render_resource_bytes!(Vec4);
|
||||
impl_render_resource_bytes!(Mat4);
|
||||
|
||||
impl<T> RenderResource for Vec<T>
|
||||
where
|
||||
T: Sized + Byteable,
|
||||
{
|
||||
fn resource_info(&self) -> Option<ResourceInfo> {
|
||||
Some(ResourceInfo::Buffer(None))
|
||||
}
|
||||
fn write_buffer_bytes(&self, buffer: &mut [u8]) {
|
||||
self.write_bytes(buffer);
|
||||
}
|
||||
fn buffer_byte_len(&self) -> Option<usize> {
|
||||
Some(self.byte_len())
|
||||
}
|
||||
fn texture(&self) -> Option<Handle<Texture>> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,7 +17,7 @@ impl Default for BufferInfo {
|
|||
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub enum ResourceInfo {
|
||||
Buffer(BufferInfo),
|
||||
Texture(TextureDescriptor),
|
||||
Buffer(Option<BufferInfo>),
|
||||
Texture(Option<TextureDescriptor>),
|
||||
Sampler,
|
||||
}
|
||||
}
|
|
@ -43,12 +43,12 @@ impl RenderResourceContext for HeadlessRenderResourceContext {
|
|||
}
|
||||
fn create_texture(&self, texture_descriptor: TextureDescriptor) -> RenderResourceId {
|
||||
let resource = RenderResourceId::new();
|
||||
self.add_resource_info(resource, ResourceInfo::Texture(texture_descriptor));
|
||||
self.add_resource_info(resource, ResourceInfo::Texture(Some(texture_descriptor)));
|
||||
resource
|
||||
}
|
||||
fn create_buffer(&self, buffer_info: BufferInfo) -> RenderResourceId {
|
||||
let resource = RenderResourceId::new();
|
||||
self.add_resource_info(resource, ResourceInfo::Buffer(buffer_info));
|
||||
self.add_resource_info(resource, ResourceInfo::Buffer(Some(buffer_info)));
|
||||
resource
|
||||
}
|
||||
fn create_buffer_mapped(
|
||||
|
@ -62,7 +62,7 @@ impl RenderResourceContext for HeadlessRenderResourceContext {
|
|||
}
|
||||
fn create_buffer_with_data(&self, buffer_info: BufferInfo, _data: &[u8]) -> RenderResourceId {
|
||||
let resource = RenderResourceId::new();
|
||||
self.add_resource_info(resource, ResourceInfo::Buffer(buffer_info));
|
||||
self.add_resource_info(resource, ResourceInfo::Buffer(Some(buffer_info)));
|
||||
resource
|
||||
}
|
||||
fn create_shader_module(&self, _shader_handle: Handle<Shader>, _shaders: &Assets<Shader>) {}
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
use crate::{color::ColorSource, pipeline::BindType, texture::Texture, Renderable};
|
||||
|
||||
use crate::{pipeline::BindType, texture::Texture, Renderable};
|
||||
use bevy_asset::{Assets, Handle};
|
||||
use bevy_core::bytes::Bytes;
|
||||
use legion::prelude::*;
|
||||
|
||||
pub use bevy_derive::{Uniform, Uniforms};
|
||||
|
@ -78,82 +76,6 @@ pub struct FieldInfo {
|
|||
pub sampler_name: &'static str,
|
||||
}
|
||||
|
||||
pub trait GetFieldBindType {
|
||||
fn get_bind_type(&self) -> Option<FieldBindType>;
|
||||
}
|
||||
|
||||
impl GetFieldBindType for ColorSource {
|
||||
fn get_bind_type(&self) -> Option<FieldBindType> {
|
||||
match *self {
|
||||
ColorSource::Texture(_) => Some(FieldBindType::Texture),
|
||||
ColorSource::Color(color) => color.get_bind_type(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GetFieldBindType for Option<Handle<Texture>> {
|
||||
fn get_bind_type(&self) -> Option<FieldBindType> {
|
||||
match *self {
|
||||
Some(_) => Some(FieldBindType::Texture),
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GetFieldBindType for Handle<Texture> {
|
||||
fn get_bind_type(&self) -> Option<FieldBindType> {
|
||||
Some(FieldBindType::Texture)
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> GetFieldBindType for T
|
||||
where
|
||||
T: Bytes,
|
||||
{
|
||||
// TODO: this breaks if get_bytes_ref() isn't supported for a datatype
|
||||
default fn get_bind_type(&self) -> Option<FieldBindType> {
|
||||
Some(FieldBindType::Uniform {
|
||||
size: self.byte_len(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub trait GetTexture {
|
||||
fn get_texture(&self) -> Option<Handle<Texture>> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> GetTexture for T
|
||||
where
|
||||
T: Bytes,
|
||||
{
|
||||
default fn get_texture(&self) -> Option<Handle<Texture>> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl GetTexture for Handle<Texture> {
|
||||
fn get_texture(&self) -> Option<Handle<Texture>> {
|
||||
Some(self.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl GetTexture for Option<Handle<Texture>> {
|
||||
fn get_texture(&self) -> Option<Handle<Texture>> {
|
||||
*self
|
||||
}
|
||||
}
|
||||
|
||||
impl GetTexture for ColorSource {
|
||||
fn get_texture(&self) -> Option<Handle<Texture>> {
|
||||
match self {
|
||||
ColorSource::Color(_) => None,
|
||||
ColorSource::Texture(texture) => Some(texture.clone()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct UniformInfo<'a> {
|
||||
pub name: &'a str,
|
||||
pub bind_type: BindType,
|
||||
|
|
|
@ -1,45 +1,27 @@
|
|||
use crate::{
|
||||
shader::{FieldBindType, FieldInfo, GetFieldBindType, Uniforms},
|
||||
texture::Texture,
|
||||
};
|
||||
use bevy_asset::Handle;
|
||||
use bevy_core::bytes::Bytes;
|
||||
use crate::render_resource::{RenderResource, RenderResourceIterator, RenderResources};
|
||||
|
||||
static TRANSFORM_FIELD_INFOS: &[FieldInfo] = &[FieldInfo {
|
||||
name: "transform",
|
||||
uniform_name: "Transform",
|
||||
texture_name: "",
|
||||
sampler_name: "",
|
||||
}];
|
||||
|
||||
impl Uniforms for bevy_transform::prelude::Transform {
|
||||
fn get_field_infos() -> &'static [FieldInfo] {
|
||||
TRANSFORM_FIELD_INFOS
|
||||
impl RenderResources for bevy_transform::prelude::Transform {
|
||||
fn render_resources_len(&self) -> usize {
|
||||
1
|
||||
}
|
||||
|
||||
fn get_shader_defs(&self) -> Option<Vec<String>> {
|
||||
None
|
||||
}
|
||||
fn get_field_bind_type(&self, name: &str) -> Option<FieldBindType> {
|
||||
match name {
|
||||
"transform" => self.value.get_bind_type(),
|
||||
_ => None,
|
||||
fn get_render_resource(&self, index: usize) -> Option<&dyn RenderResource> {
|
||||
if index == 0 {
|
||||
Some(&self.value)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
fn get_uniform_texture(&self, _name: &str) -> Option<Handle<Texture>> {
|
||||
None
|
||||
|
||||
fn get_render_resource_name(&self, index: usize) -> Option<&str> {
|
||||
if index == 0 {
|
||||
Some("Transform")
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn write_uniform_bytes(&self, name: &str, buffer: &mut [u8]) {
|
||||
match name {
|
||||
"Transform" => self.value.write_bytes(buffer),
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
fn uniform_byte_len(&self, name: &str) -> usize {
|
||||
match name {
|
||||
"Transform" => self.value.byte_len(),
|
||||
_ => 0,
|
||||
}
|
||||
fn iter_render_resources(&self) -> RenderResourceIterator {
|
||||
RenderResourceIterator::new(self)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use super::{SamplerDescriptor, TextureDescriptor};
|
||||
use crate::{
|
||||
renderer::{RenderResourceContext, RenderResources},
|
||||
shader::ShaderDefSuffixProvider,
|
||||
shader::ShaderDefSuffixProvider, render_resource::{ResourceInfo, RenderResource},
|
||||
};
|
||||
use bevy_app::{EventReader, Events};
|
||||
use bevy_asset::{AssetEvent, Assets, Handle};
|
||||
|
@ -121,3 +121,31 @@ impl ShaderDefSuffixProvider for Option<Handle<Texture>> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderResource for Option<Handle<Texture>> {
|
||||
fn resource_info(&self) -> Option<ResourceInfo> {
|
||||
self.map(|_texture| ResourceInfo::Texture(None))
|
||||
}
|
||||
fn write_buffer_bytes(&self, _buffer: &mut [u8]) {
|
||||
}
|
||||
fn buffer_byte_len(&self) -> Option<usize> {
|
||||
None
|
||||
}
|
||||
fn texture(&self) -> Option<Handle<Texture>> {
|
||||
self.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderResource for Handle<Texture> {
|
||||
fn resource_info(&self) -> Option<ResourceInfo> {
|
||||
Some(ResourceInfo::Texture(None))
|
||||
}
|
||||
fn write_buffer_bytes(&self, _buffer: &mut [u8]) {
|
||||
}
|
||||
fn buffer_byte_len(&self) -> Option<usize> {
|
||||
None
|
||||
}
|
||||
fn texture(&self) -> Option<Handle<Texture>> {
|
||||
Some(self.clone())
|
||||
}
|
||||
}
|
|
@ -11,7 +11,6 @@ bevy_app = { path = "../bevy_app" }
|
|||
bevy_core = { path = "../bevy_core" }
|
||||
bevy_asset = { path = "../bevy_asset" }
|
||||
bevy_type_registry = { path = "../bevy_type_registry" }
|
||||
bevy_derive = { path = "../bevy_derive" }
|
||||
bevy_render = { path = "../bevy_render" }
|
||||
bevy_transform = { path = "../bevy_transform" }
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use bevy_asset::{self, Handle};
|
||||
use bevy_derive::Uniforms;
|
||||
use bevy_render::{texture::Texture, Color};
|
||||
use bevy_render::{texture::Texture, Color, render_resource::RenderResources, shader::Uniforms};
|
||||
|
||||
#[derive(Uniforms)]
|
||||
#[derive(Uniforms, RenderResources)]
|
||||
pub struct ColorMaterial {
|
||||
pub color: Color,
|
||||
#[uniform(shader_def)]
|
||||
|
|
|
@ -3,7 +3,7 @@ use crate::{
|
|||
TextureAtlasSprite, QUAD_HANDLE, SPRITE_SHEET_PIPELINE_HANDLE,
|
||||
};
|
||||
use bevy_asset::Handle;
|
||||
use bevy_derive::EntityArchetype;
|
||||
use bevy_app::EntityArchetype;
|
||||
use bevy_render::{mesh::Mesh, Renderable};
|
||||
|
||||
#[derive(EntityArchetype)]
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
use bevy_derive::{Bytes, Uniform};
|
||||
use glam::Vec2;
|
||||
use bevy_render::{shader::Uniform, render_resource::{RenderResources, RenderResource}};
|
||||
use bevy_core::bytes::Bytes;
|
||||
#[repr(C)]
|
||||
#[derive(Default, Clone, Copy, Debug, Uniform, Bytes)]
|
||||
#[derive(Default, Clone, Copy, Debug, Uniform, RenderResources, RenderResource, Bytes)]
|
||||
#[render_resources(from_self)]
|
||||
pub struct Quad {
|
||||
pub position: Vec2,
|
||||
pub size: Vec2,
|
||||
|
|
|
@ -1,24 +1,27 @@
|
|||
use crate::Rect;
|
||||
use bevy_asset::Handle;
|
||||
use bevy_derive::{Bytes, Uniform, Uniforms};
|
||||
use bevy_render::texture::Texture;
|
||||
use bevy_render::{texture::Texture, render_resource::{RenderResources, RenderResource}, shader::{Uniforms, Uniform}};
|
||||
use bevy_core::bytes::Bytes;
|
||||
use glam::{Vec2, Vec3};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Uniforms)]
|
||||
#[derive(Uniforms, RenderResources)]
|
||||
pub struct TextureAtlas {
|
||||
pub texture: Handle<Texture>,
|
||||
// TODO: add support to Uniforms derive to write dimensions and sprites to the same buffer
|
||||
pub dimensions: Vec2,
|
||||
#[uniform(buffer)]
|
||||
#[render_resources(buffer)]
|
||||
pub textures: Vec<Rect>,
|
||||
#[uniform(ignore)]
|
||||
#[render_resources(ignore)]
|
||||
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
|
||||
// Bytes for Byteable as a micro-optimization. https://github.com/bitshifter/glam-rs/issues/36
|
||||
#[derive(Uniform, Bytes, Default)]
|
||||
#[derive(Uniform, Bytes, RenderResources, RenderResource, Default)]
|
||||
#[render_resources(from_self)]
|
||||
pub struct TextureAtlasSprite {
|
||||
pub position: Vec3,
|
||||
pub scale: f32,
|
||||
|
|
|
@ -152,7 +152,7 @@ impl RenderResourceContext for WgpuRenderResourceContext {
|
|||
let texture_view = texture.create_default_view();
|
||||
|
||||
let resource = RenderResourceId::new();
|
||||
resource_info.insert(resource, ResourceInfo::Texture(texture_descriptor));
|
||||
resource_info.insert(resource, ResourceInfo::Texture(Some(texture_descriptor)));
|
||||
texture_views.insert(resource, texture_view);
|
||||
textures.insert(resource, texture);
|
||||
resource
|
||||
|
@ -171,7 +171,7 @@ impl RenderResourceContext for WgpuRenderResourceContext {
|
|||
});
|
||||
|
||||
let resource = RenderResourceId::new();
|
||||
resource_info.insert(resource, ResourceInfo::Buffer(buffer_info));
|
||||
resource_info.insert(resource, ResourceInfo::Buffer(Some(buffer_info)));
|
||||
buffers.insert(resource, buffer);
|
||||
resource
|
||||
}
|
||||
|
@ -202,7 +202,7 @@ impl RenderResourceContext for WgpuRenderResourceContext {
|
|||
let resource = RenderResourceId::new();
|
||||
let mut resource_info = self.resources.resource_info.write().unwrap();
|
||||
let mut buffers = self.resources.buffers.write().unwrap();
|
||||
resource_info.insert(resource, ResourceInfo::Buffer(buffer_info));
|
||||
resource_info.insert(resource, ResourceInfo::Buffer(Some(buffer_info)));
|
||||
buffers.insert(resource, buffer);
|
||||
resource
|
||||
}
|
||||
|
@ -218,7 +218,7 @@ impl RenderResourceContext for WgpuRenderResourceContext {
|
|||
.create_buffer_with_data(data, buffer_info.buffer_usage.wgpu_into());
|
||||
|
||||
let resource = RenderResourceId::new();
|
||||
resource_info.insert(resource, ResourceInfo::Buffer(buffer_info));
|
||||
resource_info.insert(resource, ResourceInfo::Buffer(Some(buffer_info)));
|
||||
buffers.insert(resource, buffer);
|
||||
resource
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ impl<'a> RenderPass for WgpuRenderPass<'a> {
|
|||
self.render_context.resources().get_resource_info(
|
||||
index_buffer,
|
||||
&mut |resource_info| match resource_info {
|
||||
Some(ResourceInfo::Buffer(buffer_info)) => {
|
||||
Some(ResourceInfo::Buffer(Some(buffer_info))) => {
|
||||
indices = Some(0..(buffer_info.size / 2) as u32)
|
||||
}
|
||||
_ => panic!("expected a buffer type"),
|
||||
|
|
|
@ -8,7 +8,7 @@ fn main() {
|
|||
.run();
|
||||
}
|
||||
|
||||
#[derive(Uniforms, Default)]
|
||||
#[derive(Uniforms, RenderResources, Default)]
|
||||
struct MyMaterial {
|
||||
pub color: Color,
|
||||
}
|
||||
|
|
|
@ -12,10 +12,11 @@ fn main() {
|
|||
.run();
|
||||
}
|
||||
|
||||
#[derive(Uniforms, Default)]
|
||||
#[derive(Uniforms, RenderResources, Default)]
|
||||
struct MyMaterial {
|
||||
pub color: Color,
|
||||
#[uniform(ignore, shader_def)]
|
||||
#[render_resources(ignore)]
|
||||
pub always_red: bool,
|
||||
}
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ pub use crate::{
|
|||
RenderGraph,
|
||||
},
|
||||
shader::{Shader, ShaderDefSuffixProvider, ShaderStage, ShaderStages, Uniforms},
|
||||
render_resource::RenderResources,
|
||||
texture::Texture,
|
||||
Camera, Color, ColorSource, OrthographicProjection, PerspectiveProjection, Renderable,
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue