use super::ResourceInfo; use crate::texture::Texture; use bevy_asset::Handle; use uuid::Uuid; 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); impl RenderResourceId { pub fn new() -> Self { RenderResourceId(Uuid::new_v4()) } } bitflags::bitflags! { #[repr(transparent)] pub struct RenderResourceHints: u32 { const BUFFER = 1; } } pub trait RenderResource { fn resource_info(&self) -> Option; fn write_buffer_bytes(&self, buffer: &mut [u8]); fn buffer_byte_len(&self) -> Option; // TODO: consider making these panic by default, but return non-options fn texture(&self) -> Option>; } 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 { 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 { 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 { Some(ResourceInfo::Buffer(None)) } fn write_buffer_bytes(&self, buffer: &mut [u8]) { self.write_bytes(buffer); } fn buffer_byte_len(&self) -> Option { Some(self.byte_len()) } fn texture(&self) -> Option> { None } } }; } // TODO: when specialization lands, replace these with impl 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_render_resource_bytes!(u8); impl_render_resource_bytes!(u16); impl_render_resource_bytes!(u32); impl_render_resource_bytes!(u64); impl_render_resource_bytes!(i8); impl_render_resource_bytes!(i16); impl_render_resource_bytes!(i32); impl_render_resource_bytes!(i64); impl_render_resource_bytes!(f32); impl_render_resource_bytes!(f64); impl RenderResource for Vec where T: Sized + Byteable, { fn resource_info(&self) -> Option { Some(ResourceInfo::Buffer(None)) } fn write_buffer_bytes(&self, buffer: &mut [u8]) { self.write_bytes(buffer); } fn buffer_byte_len(&self) -> Option { Some(self.byte_len()) } fn texture(&self) -> Option> { None } } impl RenderResources for bevy_transform::prelude::Transform { fn render_resources_len(&self) -> usize { 1 } fn get_render_resource(&self, index: usize) -> Option<&dyn RenderResource> { if index == 0 { Some(&self.value) } else { None } } fn get_render_resource_name(&self, index: usize) -> Option<&str> { if index == 0 { Some("Transform") } else { None } } fn iter_render_resources(&self) -> RenderResourceIterator { RenderResourceIterator::new(self) } }