add RenderResources/RenderResource traits to replace Uniforms/Uniform

This commit is contained in:
Carter Anderson 2020-06-07 19:12:41 -07:00
parent 5add29f8cf
commit fd8f87400d
30 changed files with 528 additions and 347 deletions

View File

@ -3,7 +3,6 @@ use crate::{
Handle, HandleId, Handle, HandleId,
}; };
use bevy_app::{AppBuilder, Events, FromResources}; use bevy_app::{AppBuilder, Events, FromResources};
use bevy_core::bytes::Bytes;
use bevy_type_registry::RegisterType; use bevy_type_registry::RegisterType;
use legion::prelude::*; use legion::prelude::*;
use std::collections::HashMap; 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 { pub trait AddAsset {
fn add_asset<T>(&mut self) -> &mut Self fn add_asset<T>(&mut self) -> &mut Self
where where

View File

@ -1,4 +1,7 @@
use glam::{Mat4, Vec2, Vec3, Vec4}; use glam::{Mat4, Vec2, Vec3, Vec4};
pub use bevy_derive::Bytes;
pub trait Bytes { pub trait Bytes {
fn write_bytes(&self, buffer: &mut [u8]); fn write_bytes(&self, buffer: &mut [u8]);
fn byte_len(&self) -> usize; fn byte_len(&self) -> usize;

View File

@ -2,8 +2,6 @@ pub mod bytes;
pub mod time; pub mod time;
pub mod transform; pub mod transform;
pub use bevy_derive::Bytes;
use bevy_app::{stage, AppBuilder, AppPlugin}; use bevy_app::{stage, AppBuilder, AppPlugin};
use bevy_transform::{ use bevy_transform::{
components::{ components::{

View File

@ -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 darling::FromMeta;
use inflector::Inflector; use inflector::Inflector;
use proc_macro::TokenStream; use proc_macro::TokenStream;
use quote::{format_ident, quote}; 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)] #[derive(FromMeta, Debug, Default)]
struct VertexAttributeArgs { 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 { pub fn derive_as_vertex_buffer_descriptor(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as DeriveInput); 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 bevy_render_path: Path = get_path(&modules.bevy_render);
let fields = match &ast.data { let field_attributes = get_field_attributes::<VertexAttributes, VertexAttributeArgs>(
Data::Struct(DataStruct { VERTEX_ATTRIBUTE_NAME,
fields: Fields::Named(fields), &ast.data,
.. );
}) => &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 struct_name = &ast.ident; let struct_name = &ast.ident;

View 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()
}

View File

@ -1,15 +1,8 @@
use crate::modules::{get_modules, get_path}; use crate::modules::{get_modules, get_path};
use darling::FromMeta;
use proc_macro::TokenStream; use proc_macro::TokenStream;
use quote::quote; use quote::quote;
use syn::{parse_macro_input, Data, DataStruct, DeriveInput, Fields, Ident}; 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 { pub fn derive_entity_archetype(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as DeriveInput); let ast = parse_macro_input!(input as DeriveInput);
let fields = match &ast.data { 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 bevy_app_path = get_path(&modules.bevy_app);
let legion_path = get_path(&modules.legion); 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 let component_fields = fields
.iter() .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()) .map(|field| field.ident.as_ref().unwrap())
.collect::<Vec<&Ident>>(); .collect::<Vec<&Ident>>();
@ -54,7 +30,7 @@ pub fn derive_entity_archetype(input: TokenStream) -> TokenStream {
TokenStream::from(quote! { TokenStream::from(quote! {
impl #impl_generics #bevy_app_path::EntityArchetype for #struct_name#ty_generics { 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 { fn insert(self, world: &mut #legion_path::prelude::World) -> #legion_path::prelude::Entity {
*world.insert((#(self.#tag_fields,)*), *world.insert((),
vec![( vec![(
#(self.#component_fields,)* #(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 { 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![( vec![(
#(self.#component_fields,)* #(self.#component_fields,)*
) )

View File

@ -1,9 +1,12 @@
extern crate proc_macro; extern crate proc_macro;
mod app_plugin; mod app_plugin;
mod attributes;
mod bytes; mod bytes;
mod entity_archetype; mod entity_archetype;
mod modules; mod modules;
mod render_resources;
mod render_resource;
mod resource; mod resource;
mod uniforms; mod uniforms;
mod as_vertex_buffer_descriptor; mod as_vertex_buffer_descriptor;
@ -30,6 +33,16 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
uniforms::derive_uniforms(input) 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))] #[proc_macro_derive(AsVertexBufferDescriptor, attributes(vertex, module))]
pub fn derive_as_vertex_buffer_descriptor(input: TokenStream) -> TokenStream { pub fn derive_as_vertex_buffer_descriptor(input: TokenStream) -> TokenStream {
as_vertex_buffer_descriptor::derive_as_vertex_buffer_descriptor(input) as_vertex_buffer_descriptor::derive_as_vertex_buffer_descriptor(input)

View 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
}
}
})
}

View 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)
}
}
})
}
}

View File

@ -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 darling::FromMeta;
use inflector::Inflector; use inflector::Inflector;
use proc_macro::TokenStream; use proc_macro::TokenStream;
use quote::{format_ident, quote}; 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)] #[derive(FromMeta, Debug, Default)]
struct UniformAttributeArgs { 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_core_path: Path = get_path(&modules.bevy_core);
let bevy_asset_path: Path = get_path(&modules.bevy_asset); let bevy_asset_path: Path = get_path(&modules.bevy_asset);
let fields = match &ast.data { let field_attributes = get_field_attributes::<UniformAttributes, UniformAttributeArgs>(
Data::Struct(DataStruct { UNIFORM_ATTRIBUTE_NAME,
fields: Fields::Named(fields), &ast.data,
.. );
}) => &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 struct_name = &ast.ident; 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> { fn get_field_bind_type(&self, name: &str) -> Option<#bevy_render_path::shader::FieldBindType> {
use #bevy_render_path::shader::GetFieldBindType; None
match name {
#(#active_uniform_field_name_strings => #get_field_bind_types,)*
_ => None,
}
} }
fn get_uniform_texture(&self, name: &str) -> Option<#bevy_asset_path::Handle<#bevy_render_path::texture::Texture>> { fn get_uniform_texture(&self, name: &str) -> Option<#bevy_asset_path::Handle<#bevy_render_path::texture::Texture>> {
use #bevy_render_path::shader::GetTexture; None
match name {
#(#texture_and_sampler_name_strings => self.#texture_and_sampler_name_idents.get_texture(),)*
_ => None,
}
} }
fn write_uniform_bytes(&self, name: &str, buffer: &mut [u8]) { fn write_uniform_bytes(&self, name: &str, buffer: &mut [u8]) {
use #bevy_core_path::bytes::Bytes; 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 { fn uniform_byte_len(&self, name: &str) -> usize {
use #bevy_core_path::bytes::Bytes; 0
match name {
#(#uniform_name_strings => self.#active_uniform_field_names.byte_len(),)*
_ => 0,
}
} }
// TODO: move this to field_info and add has_shader_def(&self, &str) -> bool // 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 modules = get_modules(&ast);
let bevy_asset_path = get_path(&modules.bevy_asset); 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 bevy_render_path = get_path(&modules.bevy_render);
let generics = ast.generics; 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> { fn get_field_bind_type(&self, name: &str) -> Option<#bevy_render_path::shader::FieldBindType> {
use #bevy_render_path::shader::GetFieldBindType; None
match name {
#struct_name_string => self.get_bind_type(),
_ => None,
}
} }
fn write_uniform_bytes(&self, name: &str, buffer: &mut [u8]) { 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 { fn uniform_byte_len(&self, name: &str) -> usize {
use #bevy_core_path::bytes::Bytes; 0
match name {
#struct_name_string => self.byte_len(),
_ => 0,
}
} }
fn get_uniform_texture(&self, name: &str) -> Option<#bevy_asset_path::Handle<#bevy_render_path::texture::Texture>> { fn get_uniform_texture(&self, name: &str) -> Option<#bevy_asset_path::Handle<#bevy_render_path::texture::Texture>> {

View File

@ -1,8 +1,7 @@
use bevy_asset::{self, Handle}; use bevy_asset::{self, Handle};
use bevy_derive::Uniforms; use bevy_render::{render_resource::RenderResources, shader::Uniforms, texture::Texture, Color};
use bevy_render::{texture::Texture, Color};
#[derive(Uniforms)] #[derive(Uniforms, RenderResources)]
pub struct StandardMaterial { pub struct StandardMaterial {
pub albedo: Color, pub albedo: Color,
#[uniform(shader_def)] #[uniform(shader_def)]

View File

@ -1,5 +1,5 @@
use super::texture::Texture; 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_asset::Handle;
use bevy_core::bytes::{Byteable, Bytes}; use bevy_core::bytes::{Byteable, Bytes};
use bevy_property::Property; use bevy_property::Property;
@ -138,3 +138,5 @@ impl ShaderDefSuffixProvider for ColorSource {
} }
} }
} }
impl_render_resource_bytes!(Color);

View File

@ -45,7 +45,7 @@ impl DrawTarget for MeshesDrawTarget {
render_resources.get_resource_info( render_resources.get_resource_info(
index_buffer_resource, index_buffer_resource,
&mut |resource_info| match resource_info { &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 current_mesh_index_len = (buffer_info.size / 2) as u32
} }
_ => panic!("expected a buffer type"), _ => panic!("expected a buffer type"),

View File

@ -1,16 +1,16 @@
use crate::{ use crate::{
render_graph::{CommandQueue, Node, ResourceSlots, SystemNode}, render_graph::{CommandQueue, Node, ResourceSlots, SystemNode},
render_resource::{ render_resource::{
BufferInfo, BufferUsage, EntitiesWaitingForAssets, RenderResourceId, self, BufferInfo, BufferUsage, EntitiesWaitingForAssets, RenderResourceAssignment,
RenderResourceAssignment, RenderResourceAssignments, RenderResourceAssignmentsId, RenderResourceAssignments, RenderResourceAssignmentsId, RenderResourceId, RenderResourceHints,
}, },
renderer::{RenderContext, RenderResourceContext, RenderResources}, renderer::{RenderContext, RenderResourceContext, RenderResources},
shader::{Uniforms, FieldBindType},
texture, Renderable, texture, Renderable,
}; };
use bevy_asset::{Assets, Handle}; use bevy_asset::{Assets, Handle};
use legion::prelude::*; use legion::prelude::*;
use render_resource::ResourceInfo;
use std::{collections::HashMap, marker::PhantomData}; use std::{collections::HashMap, marker::PhantomData};
pub const BIND_BUFFER_ALIGNMENT: usize = 256; pub const BIND_BUFFER_ALIGNMENT: usize = 256;
@ -53,25 +53,28 @@ impl BufferArrayStatus {
struct UniformBufferArrays<T> struct UniformBufferArrays<T>
where where
T: Uniforms, T: render_resource::RenderResources,
{ {
uniform_arrays: Vec<Option<(String, BufferArrayStatus)>>, uniform_arrays: Vec<Option<(String, BufferArrayStatus)>>,
_marker: PhantomData<T>, _marker: PhantomData<T>,
} }
impl<T> UniformBufferArrays<T> impl<T> Default for UniformBufferArrays<T>
where where
T: Uniforms, T: render_resource::RenderResources,
{ {
fn new() -> Self { fn default() -> Self {
let mut uniform_arrays = Vec::new(); Self {
let field_infos = T::get_field_infos(); uniform_arrays: Default::default(),
uniform_arrays.resize_with(field_infos.len(), || None); _marker: Default::default(),
UniformBufferArrays {
uniform_arrays,
_marker: PhantomData::default(),
} }
} }
}
impl<T> UniformBufferArrays<T>
where
T: render_resource::RenderResources,
{
fn reset_new_item_counts(&mut self) { fn reset_new_item_counts(&mut self) {
for buffer_status in self.uniform_arrays.iter_mut() { for buffer_status in self.uniform_arrays.iter_mut() {
if let Some((_name, buffer_status)) = buffer_status { if let Some((_name, buffer_status)) = buffer_status {
@ -81,15 +84,19 @@ where
} }
fn increment_uniform_counts(&mut self, uniforms: &T) { fn increment_uniform_counts(&mut self, uniforms: &T) {
for (i, field_info) in T::get_field_infos().iter().enumerate() { if self.uniform_arrays.len() != uniforms.render_resources_len() {
if let Some(FieldBindType::Uniform { size }) | Some(FieldBindType::Buffer { size }) = self.uniform_arrays
uniforms.get_field_bind_type(&field_info.name) .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] { if let Some((ref _name, ref mut buffer_array_status)) = self.uniform_arrays[i] {
buffer_array_status.new_item_count += 1; buffer_array_status.new_item_count += 1;
} else { } else {
self.uniform_arrays[i] = Some(( self.uniform_arrays[i] = Some((
field_info.uniform_name.to_string(), render_resource_name.to_string(),
BufferArrayStatus { BufferArrayStatus {
new_item_count: 1, new_item_count: 1,
queued_buffer_writes: Vec::new(), queued_buffer_writes: Vec::new(),
@ -182,10 +189,11 @@ where
render_resource_assignments: &mut RenderResourceAssignments, render_resource_assignments: &mut RenderResourceAssignments,
staging_buffer: &mut [u8], staging_buffer: &mut [u8],
) { ) {
for (i, field_info) in T::get_field_infos().iter().enumerate() { for (i, render_resource) in uniforms.iter_render_resources().enumerate() {
let bind_type = uniforms.get_field_bind_type(&field_info.name); match render_resource.resource_info() {
match bind_type { Some(ResourceInfo::Buffer(_)) => {
Some(FieldBindType::Uniform { size }) | Some(FieldBindType::Buffer { size }) => { 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 (_name, uniform_buffer_status) = self.uniform_arrays[i].as_mut().unwrap();
let range = 0..size as u64; let range = 0..size as u64;
let (target_buffer, target_offset) = if dynamic_uniforms { let (target_buffer, target_offset) = if dynamic_uniforms {
@ -193,7 +201,7 @@ where
let index = uniform_buffer_status let index = uniform_buffer_status
.get_or_assign_index(render_resource_assignments.id); .get_or_assign_index(render_resource_assignments.id);
render_resource_assignments.set( render_resource_assignments.set(
&field_info.uniform_name, render_resource_name,
RenderResourceAssignment::Buffer { RenderResourceAssignment::Buffer {
resource: buffer, resource: buffer,
dynamic_index: Some( dynamic_index: Some(
@ -204,16 +212,18 @@ where
); );
(buffer, index * uniform_buffer_status.aligned_size) (buffer, index * uniform_buffer_status.aligned_size)
} else { } else {
let resource = match render_resource_assignments let resource = match render_resource_assignments.get(render_resource_name) {
.get(field_info.uniform_name)
{
Some(assignment) => assignment.get_resource(), Some(assignment) => assignment.get_resource(),
None => { None => {
let usage = if let Some(FieldBindType::Buffer { .. }) = bind_type { // TODO: RE-ADD support for BufferUsage::STORAGE type
BufferUsage::STORAGE let mut usage = BufferUsage::UNIFORM;
} else {
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 { let resource = render_resources.create_buffer(BufferInfo {
size, size,
buffer_usage: BufferUsage::COPY_DST | usage, buffer_usage: BufferUsage::COPY_DST | usage,
@ -221,7 +231,7 @@ where
}); });
render_resource_assignments.set( render_resource_assignments.set(
&field_info.uniform_name, render_resource_name,
RenderResourceAssignment::Buffer { RenderResourceAssignment::Buffer {
resource, resource,
range, range,
@ -238,23 +248,9 @@ where
let staging_buffer_start = uniform_buffer_status.staging_buffer_offset let staging_buffer_start = uniform_buffer_status.staging_buffer_offset
+ (uniform_buffer_status.queued_buffer_writes.len() + (uniform_buffer_status.queued_buffer_writes.len()
* uniform_buffer_status.item_size); * uniform_buffer_status.item_size);
let uniform_byte_len = uniforms.uniform_byte_len(&field_info.uniform_name); render_resource.write_buffer_bytes(
if uniform_byte_len > 0 { &mut staging_buffer[staging_buffer_start..(staging_buffer_start + size)],
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
);
};
uniform_buffer_status uniform_buffer_status
.queued_buffer_writes .queued_buffer_writes
@ -263,7 +259,8 @@ where
offset: target_offset, offset: target_offset,
}); });
} }
Some(FieldBindType::Texture) => { /* ignore textures */ } Some(ResourceInfo::Texture(_)) => { /* ignore textures */ }
Some(ResourceInfo::Sampler) => { /* ignore samplers */ }
None => { /* ignore None */ } None => { /* ignore None */ }
} }
} }
@ -347,7 +344,7 @@ where
#[derive(Default)] #[derive(Default)]
pub struct UniformNode<T> pub struct UniformNode<T>
where where
T: Uniforms, T: render_resource::RenderResources,
{ {
command_queue: CommandQueue, command_queue: CommandQueue,
dynamic_uniforms: bool, dynamic_uniforms: bool,
@ -356,7 +353,7 @@ where
impl<T> UniformNode<T> impl<T> UniformNode<T>
where where
T: Uniforms, T: render_resource::RenderResources,
{ {
pub fn new(dynamic_uniforms: bool) -> Self { pub fn new(dynamic_uniforms: bool) -> Self {
UniformNode { UniformNode {
@ -369,7 +366,7 @@ where
impl<T> Node for UniformNode<T> impl<T> Node for UniformNode<T>
where where
T: Uniforms, T: render_resource::RenderResources,
{ {
fn update( fn update(
&mut self, &mut self,
@ -385,11 +382,11 @@ where
impl<T> SystemNode for UniformNode<T> impl<T> SystemNode for UniformNode<T>
where where
T: Uniforms, T: render_resource::RenderResources,
{ {
fn get_system(&self) -> Box<dyn Schedulable> { fn get_system(&self) -> Box<dyn Schedulable> {
let mut command_queue = self.command_queue.clone(); 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; let dynamic_uniforms = self.dynamic_uniforms;
// TODO: maybe run "update" here // TODO: maybe run "update" here
SystemBuilder::new(format!( SystemBuilder::new(format!(
@ -505,7 +502,7 @@ where
#[derive(Default)] #[derive(Default)]
pub struct AssetUniformNode<T> pub struct AssetUniformNode<T>
where where
T: Uniforms, T: render_resource::RenderResources,
{ {
command_queue: CommandQueue, command_queue: CommandQueue,
dynamic_uniforms: bool, dynamic_uniforms: bool,
@ -514,7 +511,7 @@ where
impl<T> AssetUniformNode<T> impl<T> AssetUniformNode<T>
where where
T: Uniforms, T: render_resource::RenderResources,
{ {
pub fn new(dynamic_uniforms: bool) -> Self { pub fn new(dynamic_uniforms: bool) -> Self {
AssetUniformNode { AssetUniformNode {
@ -527,7 +524,7 @@ where
impl<T> Node for AssetUniformNode<T> impl<T> Node for AssetUniformNode<T>
where where
T: Uniforms, T: render_resource::RenderResources,
{ {
fn update( fn update(
&mut self, &mut self,
@ -543,11 +540,11 @@ where
impl<T> SystemNode for AssetUniformNode<T> impl<T> SystemNode for AssetUniformNode<T>
where where
T: Uniforms, T: render_resource::RenderResources,
{ {
fn get_system(&self) -> Box<dyn Schedulable> { fn get_system(&self) -> Box<dyn Schedulable> {
let mut command_queue = self.command_queue.clone(); 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; let dynamic_uniforms = self.dynamic_uniforms;
// TODO: maybe run "update" here // TODO: maybe run "update" here
SystemBuilder::new("uniform_resource_provider") SystemBuilder::new("uniform_resource_provider")
@ -677,12 +674,13 @@ fn setup_uniform_texture_resources<T>(
entities_waiting_for_assets: &EntitiesWaitingForAssets, entities_waiting_for_assets: &EntitiesWaitingForAssets,
render_resource_assignments: &mut RenderResourceAssignments, render_resource_assignments: &mut RenderResourceAssignments,
) where ) where
T: Uniforms, T: render_resource::RenderResources,
{ {
for field_info in T::get_field_infos().iter() { for (i, render_resource) in uniforms.iter_render_resources().enumerate() {
let bind_type = uniforms.get_field_bind_type(&field_info.name); if let Some(ResourceInfo::Texture(_)) = render_resource.resource_info() {
if let Some(FieldBindType::Texture) = bind_type { let render_resource_name = uniforms.get_render_resource_name(i).unwrap();
if let Some(texture_handle) = uniforms.get_uniform_texture(&field_info.texture_name) { let sampler_name = format!("{}_sampler", render_resource_name);
if let Some(texture_handle) = render_resource.texture() {
if let Some(texture_resource) = render_resource_context if let Some(texture_resource) = render_resource_context
.get_asset_resource(texture_handle, texture::TEXTURE_ASSET_INDEX) .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) .get_asset_resource(texture_handle, texture::SAMPLER_ASSET_INDEX)
.unwrap(); .unwrap();
render_resource_assignments.set( render_resource_assignments.set(
field_info.texture_name, render_resource_name,
RenderResourceAssignment::Texture(texture_resource), RenderResourceAssignment::Texture(texture_resource),
); );
render_resource_assignments.set( render_resource_assignments.set(
field_info.sampler_name, &sampler_name,
RenderResourceAssignment::Sampler(sampler_resource), RenderResourceAssignment::Sampler(sampler_resource),
); );
continue; continue;

View File

@ -1,6 +1,12 @@
use super::ResourceInfo;
use crate::texture::Texture;
use bevy_asset::Handle;
use uuid::Uuid; 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)] #[derive(Copy, Clone, Hash, Eq, PartialEq, Debug)]
pub struct RenderResourceId(Uuid); pub struct RenderResourceId(Uuid);
@ -9,3 +15,101 @@ impl RenderResourceId {
RenderResourceId(Uuid::new_v4()) 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
}
}

View File

@ -17,7 +17,7 @@ impl Default for BufferInfo {
#[derive(Debug, Clone, Eq, PartialEq)] #[derive(Debug, Clone, Eq, PartialEq)]
pub enum ResourceInfo { pub enum ResourceInfo {
Buffer(BufferInfo), Buffer(Option<BufferInfo>),
Texture(TextureDescriptor), Texture(Option<TextureDescriptor>),
Sampler, Sampler,
} }

View File

@ -43,12 +43,12 @@ impl RenderResourceContext for HeadlessRenderResourceContext {
} }
fn create_texture(&self, texture_descriptor: TextureDescriptor) -> RenderResourceId { fn create_texture(&self, texture_descriptor: TextureDescriptor) -> RenderResourceId {
let resource = RenderResourceId::new(); let resource = RenderResourceId::new();
self.add_resource_info(resource, ResourceInfo::Texture(texture_descriptor)); self.add_resource_info(resource, ResourceInfo::Texture(Some(texture_descriptor)));
resource resource
} }
fn create_buffer(&self, buffer_info: BufferInfo) -> RenderResourceId { fn create_buffer(&self, buffer_info: BufferInfo) -> RenderResourceId {
let resource = RenderResourceId::new(); let resource = RenderResourceId::new();
self.add_resource_info(resource, ResourceInfo::Buffer(buffer_info)); self.add_resource_info(resource, ResourceInfo::Buffer(Some(buffer_info)));
resource resource
} }
fn create_buffer_mapped( fn create_buffer_mapped(
@ -62,7 +62,7 @@ impl RenderResourceContext for HeadlessRenderResourceContext {
} }
fn create_buffer_with_data(&self, buffer_info: BufferInfo, _data: &[u8]) -> RenderResourceId { fn create_buffer_with_data(&self, buffer_info: BufferInfo, _data: &[u8]) -> RenderResourceId {
let resource = RenderResourceId::new(); let resource = RenderResourceId::new();
self.add_resource_info(resource, ResourceInfo::Buffer(buffer_info)); self.add_resource_info(resource, ResourceInfo::Buffer(Some(buffer_info)));
resource resource
} }
fn create_shader_module(&self, _shader_handle: Handle<Shader>, _shaders: &Assets<Shader>) {} fn create_shader_module(&self, _shader_handle: Handle<Shader>, _shaders: &Assets<Shader>) {}

View File

@ -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_asset::{Assets, Handle};
use bevy_core::bytes::Bytes;
use legion::prelude::*; use legion::prelude::*;
pub use bevy_derive::{Uniform, Uniforms}; pub use bevy_derive::{Uniform, Uniforms};
@ -78,82 +76,6 @@ pub struct FieldInfo {
pub sampler_name: &'static str, 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 struct UniformInfo<'a> {
pub name: &'a str, pub name: &'a str,
pub bind_type: BindType, pub bind_type: BindType,

View File

@ -1,45 +1,27 @@
use crate::{ use crate::render_resource::{RenderResource, RenderResourceIterator, RenderResources};
shader::{FieldBindType, FieldInfo, GetFieldBindType, Uniforms},
texture::Texture,
};
use bevy_asset::Handle;
use bevy_core::bytes::Bytes;
static TRANSFORM_FIELD_INFOS: &[FieldInfo] = &[FieldInfo { impl RenderResources for bevy_transform::prelude::Transform {
name: "transform", fn render_resources_len(&self) -> usize {
uniform_name: "Transform", 1
texture_name: "",
sampler_name: "",
}];
impl Uniforms for bevy_transform::prelude::Transform {
fn get_field_infos() -> &'static [FieldInfo] {
TRANSFORM_FIELD_INFOS
} }
fn get_shader_defs(&self) -> Option<Vec<String>> { fn get_render_resource(&self, index: usize) -> Option<&dyn RenderResource> {
None if index == 0 {
} Some(&self.value)
fn get_field_bind_type(&self, name: &str) -> Option<FieldBindType> { } else {
match name { None
"transform" => self.value.get_bind_type(),
_ => 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]) { fn iter_render_resources(&self) -> RenderResourceIterator {
match name { RenderResourceIterator::new(self)
"Transform" => self.value.write_bytes(buffer),
_ => {}
}
}
fn uniform_byte_len(&self, name: &str) -> usize {
match name {
"Transform" => self.value.byte_len(),
_ => 0,
}
} }
} }

View File

@ -1,7 +1,7 @@
use super::{SamplerDescriptor, TextureDescriptor}; use super::{SamplerDescriptor, TextureDescriptor};
use crate::{ use crate::{
renderer::{RenderResourceContext, RenderResources}, renderer::{RenderResourceContext, RenderResources},
shader::ShaderDefSuffixProvider, shader::ShaderDefSuffixProvider, render_resource::{ResourceInfo, RenderResource},
}; };
use bevy_app::{EventReader, Events}; use bevy_app::{EventReader, Events};
use bevy_asset::{AssetEvent, Assets, Handle}; 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())
}
}

View File

@ -11,7 +11,6 @@ bevy_app = { path = "../bevy_app" }
bevy_core = { path = "../bevy_core" } bevy_core = { path = "../bevy_core" }
bevy_asset = { path = "../bevy_asset" } bevy_asset = { path = "../bevy_asset" }
bevy_type_registry = { path = "../bevy_type_registry" } bevy_type_registry = { path = "../bevy_type_registry" }
bevy_derive = { path = "../bevy_derive" }
bevy_render = { path = "../bevy_render" } bevy_render = { path = "../bevy_render" }
bevy_transform = { path = "../bevy_transform" } bevy_transform = { path = "../bevy_transform" }

View File

@ -1,8 +1,7 @@
use bevy_asset::{self, Handle}; use bevy_asset::{self, Handle};
use bevy_derive::Uniforms; use bevy_render::{texture::Texture, Color, render_resource::RenderResources, shader::Uniforms};
use bevy_render::{texture::Texture, Color};
#[derive(Uniforms)] #[derive(Uniforms, RenderResources)]
pub struct ColorMaterial { pub struct ColorMaterial {
pub color: Color, pub color: Color,
#[uniform(shader_def)] #[uniform(shader_def)]

View File

@ -3,7 +3,7 @@ use crate::{
TextureAtlasSprite, QUAD_HANDLE, SPRITE_SHEET_PIPELINE_HANDLE, TextureAtlasSprite, QUAD_HANDLE, SPRITE_SHEET_PIPELINE_HANDLE,
}; };
use bevy_asset::Handle; use bevy_asset::Handle;
use bevy_derive::EntityArchetype; use bevy_app::EntityArchetype;
use bevy_render::{mesh::Mesh, Renderable}; use bevy_render::{mesh::Mesh, Renderable};
#[derive(EntityArchetype)] #[derive(EntityArchetype)]

View File

@ -1,7 +1,9 @@
use bevy_derive::{Bytes, Uniform};
use glam::Vec2; use glam::Vec2;
use bevy_render::{shader::Uniform, render_resource::{RenderResources, RenderResource}};
use bevy_core::bytes::Bytes;
#[repr(C)] #[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 struct Quad {
pub position: Vec2, pub position: Vec2,
pub size: Vec2, pub size: Vec2,

View File

@ -1,24 +1,27 @@
use crate::Rect; use crate::Rect;
use bevy_asset::Handle; use bevy_asset::Handle;
use bevy_derive::{Bytes, Uniform, Uniforms}; use bevy_render::{texture::Texture, render_resource::{RenderResources, RenderResource}, shader::{Uniforms, Uniform}};
use bevy_render::texture::Texture; use bevy_core::bytes::Bytes;
use glam::{Vec2, Vec3}; use glam::{Vec2, Vec3};
use std::collections::HashMap; use std::collections::HashMap;
#[derive(Uniforms)] #[derive(Uniforms, RenderResources)]
pub struct TextureAtlas { pub struct TextureAtlas {
pub texture: Handle<Texture>, pub texture: Handle<Texture>,
// TODO: add support to Uniforms derive to write dimensions and sprites to the same buffer // TODO: add support to Uniforms derive to write dimensions and sprites to the same buffer
pub dimensions: Vec2, pub dimensions: Vec2,
#[uniform(buffer)] #[uniform(buffer)]
#[render_resources(buffer)]
pub textures: Vec<Rect>, pub textures: Vec<Rect>,
#[uniform(ignore)] #[uniform(ignore)]
#[render_resources(ignore)]
pub texture_handles: Option<HashMap<Handle<Texture>, usize>>, pub texture_handles: Option<HashMap<Handle<Texture>, usize>>,
} }
// NOTE: cannot do `unsafe impl Byteable` here because Vec3 takes up the space of a Vec4. If/when glam changes this we can swap out // NOTE: cannot do `unsafe impl Byteable` here because Vec3 takes up the space of a Vec4. If/when glam changes this we can swap out
// Bytes for Byteable as a micro-optimization. https://github.com/bitshifter/glam-rs/issues/36 // Bytes for Byteable as a micro-optimization. https://github.com/bitshifter/glam-rs/issues/36
#[derive(Uniform, Bytes, Default)] #[derive(Uniform, Bytes, RenderResources, RenderResource, Default)]
#[render_resources(from_self)]
pub struct TextureAtlasSprite { pub struct TextureAtlasSprite {
pub position: Vec3, pub position: Vec3,
pub scale: f32, pub scale: f32,

View File

@ -152,7 +152,7 @@ impl RenderResourceContext for WgpuRenderResourceContext {
let texture_view = texture.create_default_view(); let texture_view = texture.create_default_view();
let resource = RenderResourceId::new(); 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); texture_views.insert(resource, texture_view);
textures.insert(resource, texture); textures.insert(resource, texture);
resource resource
@ -171,7 +171,7 @@ impl RenderResourceContext for WgpuRenderResourceContext {
}); });
let resource = RenderResourceId::new(); 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); buffers.insert(resource, buffer);
resource resource
} }
@ -202,7 +202,7 @@ impl RenderResourceContext for WgpuRenderResourceContext {
let resource = RenderResourceId::new(); let resource = RenderResourceId::new();
let mut resource_info = self.resources.resource_info.write().unwrap(); let mut resource_info = self.resources.resource_info.write().unwrap();
let mut buffers = self.resources.buffers.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); buffers.insert(resource, buffer);
resource resource
} }
@ -218,7 +218,7 @@ impl RenderResourceContext for WgpuRenderResourceContext {
.create_buffer_with_data(data, buffer_info.buffer_usage.wgpu_into()); .create_buffer_with_data(data, buffer_info.buffer_usage.wgpu_into());
let resource = RenderResourceId::new(); 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); buffers.insert(resource, buffer);
resource resource
} }

View File

@ -83,7 +83,7 @@ impl<'a> RenderPass for WgpuRenderPass<'a> {
self.render_context.resources().get_resource_info( self.render_context.resources().get_resource_info(
index_buffer, index_buffer,
&mut |resource_info| match resource_info { &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) indices = Some(0..(buffer_info.size / 2) as u32)
} }
_ => panic!("expected a buffer type"), _ => panic!("expected a buffer type"),

View File

@ -8,7 +8,7 @@ fn main() {
.run(); .run();
} }
#[derive(Uniforms, Default)] #[derive(Uniforms, RenderResources, Default)]
struct MyMaterial { struct MyMaterial {
pub color: Color, pub color: Color,
} }

View File

@ -12,10 +12,11 @@ fn main() {
.run(); .run();
} }
#[derive(Uniforms, Default)] #[derive(Uniforms, RenderResources, Default)]
struct MyMaterial { struct MyMaterial {
pub color: Color, pub color: Color,
#[uniform(ignore, shader_def)] #[uniform(ignore, shader_def)]
#[render_resources(ignore)]
pub always_red: bool, pub always_red: bool,
} }

View File

@ -26,6 +26,7 @@ pub use crate::{
RenderGraph, RenderGraph,
}, },
shader::{Shader, ShaderDefSuffixProvider, ShaderStage, ShaderStages, Uniforms}, shader::{Shader, ShaderDefSuffixProvider, ShaderStage, ShaderStages, Uniforms},
render_resource::RenderResources,
texture::Texture, texture::Texture,
Camera, Color, ColorSource, OrthographicProjection, PerspectiveProjection, Renderable, Camera, Color, ColorSource, OrthographicProjection, PerspectiveProjection, Renderable,
}, },