ecs: refactor resources

fixes unintialized global resource memory
This commit is contained in:
Carter Anderson 2020-07-19 14:23:06 -07:00
parent 2ec530da8c
commit 946d5d1024
7 changed files with 209 additions and 261 deletions

View file

@ -45,7 +45,7 @@ impl AppPlugin for ScheduleRunnerPlugin {
app.schedule.run(&mut app.world, &mut app.resources);
}
RunMode::Loop { wait } => loop {
if let Ok(app_exit_events) = app.resources.get_mut::<Events<AppExit>>() {
if let Some(app_exit_events) = app.resources.get_mut::<Events<AppExit>>() {
if app_exit_event_reader.latest(&app_exit_events).is_some() {
break;
}
@ -53,7 +53,7 @@ impl AppPlugin for ScheduleRunnerPlugin {
app.schedule.run(&mut app.world, &mut app.resources);
if let Ok(app_exit_events) = app.resources.get_mut::<Events<AppExit>>() {
if let Some(app_exit_events) = app.resources.get_mut::<Events<AppExit>>() {
if app_exit_event_reader.latest(&app_exit_events).is_some() {
break;
}

View file

@ -1,31 +1,26 @@
use super::{FromResources, Resources};
use crate::{
system::{SystemId, TypeAccess},
ResourceIndex,
};
use core::{
any::TypeId,
ops::{Deref, DerefMut},
ptr::NonNull,
};
use hecs::{smaller_tuples_too, MissingComponent, Component, Archetype};
use std::collections::HashMap;
use super::{Resources, FromResources};
use hecs::{smaller_tuples_too, Component};
use std::marker::PhantomData;
/// Shared borrow of an entity's component
pub struct Res<'a, T: Component> {
archetype: &'a Archetype,
target: NonNull<T>,
value: &'a T,
}
impl<'a, T: Component> Res<'a, T> {
#[allow(missing_docs)]
pub unsafe fn new(archetype: &'a Archetype, index: u32) -> Result<Self, MissingComponent> {
let target = NonNull::new_unchecked(
archetype
.get::<T>()
.ok_or_else(MissingComponent::new::<T>)?
.as_ptr()
.add(index as usize),
);
Ok(Self { archetype, target })
pub unsafe fn new(value: NonNull<T>) -> Self {
Self {
value: &*value.as_ptr(),
}
}
}
@ -33,22 +28,9 @@ pub trait UnsafeClone {
unsafe fn unsafe_clone(&self) -> Self;
}
// TODO: this is unsafe. lets think of a better solution that allows us to clone internally
impl<'a, T: Component> UnsafeClone for ResMut<'a, T> {
unsafe fn unsafe_clone(&self) -> Self {
Self {
archetype: self.archetype,
target: self.target,
}
}
}
impl<'a, T: Component> UnsafeClone for Res<'a, T> {
unsafe fn unsafe_clone(&self) -> Self {
Self {
archetype: self.archetype,
target: self.target,
}
Self { value: self.value }
}
}
@ -58,27 +40,22 @@ unsafe impl<T: Component> Sync for Res<'_, T> {}
impl<'a, T: Component> Deref for Res<'a, T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { self.target.as_ref() }
self.value
}
}
/// Unique borrow of a resource
pub struct ResMut<'a, T: Component> {
archetype: &'a Archetype,
target: NonNull<T>,
_marker: PhantomData<&'a T>,
value: *mut T,
}
impl<'a, T: Component> ResMut<'a, T> {
#[allow(missing_docs)]
pub unsafe fn new(archetype: &'a Archetype, index: u32) -> Result<Self, MissingComponent> {
let target = NonNull::new_unchecked(
archetype
.get::<T>()
.ok_or_else(MissingComponent::new::<T>)?
.as_ptr()
.add(index as usize),
);
Ok(Self { archetype, target })
pub unsafe fn new(value: NonNull<T>) -> Self {
Self {
value: value.as_ptr(),
_marker: Default::default(),
}
}
}
@ -88,40 +65,35 @@ unsafe impl<T: Component> Sync for ResMut<'_, T> {}
impl<'a, T: Component> Deref for ResMut<'a, T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { self.target.as_ref() }
unsafe { &*self.value }
}
}
impl<'a, T: Component> DerefMut for ResMut<'a, T> {
fn deref_mut(&mut self) -> &mut T {
unsafe { self.target.as_mut() }
unsafe { &mut *self.value }
}
}
impl<'a, T: Component> UnsafeClone for ResMut<'a, T> {
unsafe fn unsafe_clone(&self) -> Self {
Self {
value: self.value,
_marker: Default::default(),
}
}
}
pub struct Local<'a, T: Component + FromResources> {
archetype: &'a Archetype,
target: NonNull<T>,
}
impl<'a, T: Component + FromResources> Local<'a, T> {
#[allow(missing_docs)]
pub unsafe fn new(archetype: &'a Archetype, index: u32) -> Result<Self, MissingComponent> {
let target = NonNull::new_unchecked(
archetype
.get::<T>()
.ok_or_else(MissingComponent::new::<T>)?
.as_ptr()
.add(index as usize),
);
Ok(Self { archetype, target })
}
value: *mut T,
_marker: PhantomData<&'a T>,
}
impl<'a, T: Component + FromResources> UnsafeClone for Local<'a, T> {
unsafe fn unsafe_clone(&self) -> Self {
Self {
archetype: self.archetype,
target: self.target,
value: self.value,
_marker: Default::default(),
}
}
}
@ -129,13 +101,13 @@ impl<'a, T: Component + FromResources> UnsafeClone for Local<'a, T> {
impl<'a, T: Component + FromResources> Deref for Local<'a, T> {
type Target = T;
fn deref(&self) -> &T {
unsafe { self.target.as_ref() }
unsafe { &*self.value }
}
}
impl<'a, T: Component + FromResources> DerefMut for Local<'a, T> {
fn deref_mut(&mut self) -> &mut T {
unsafe { self.target.as_mut() }
unsafe { &mut *self.value }
}
}
@ -152,8 +124,8 @@ pub trait FetchResource<'a>: Sized {
type Item: UnsafeClone;
fn access() -> TypeAccess;
fn borrow(resource_archetypes: &HashMap<TypeId, Archetype>);
fn release(resource_archetypes: &HashMap<TypeId, Archetype>);
fn borrow(resources: &Resources);
fn release(resources: &Resources);
/// Construct a `Fetch` for `archetype` if it should be traversed
///
@ -171,19 +143,17 @@ pub struct FetchResourceRead<T>(NonNull<T>);
impl<'a, T: Component> FetchResource<'a> for FetchResourceRead<T> {
type Item = Res<'a, T>;
unsafe fn get(resources: &'a Resources, _system_id: Option<SystemId>) -> Self::Item {
resources.get_res::<T>()
Res::new(resources.get_unsafe_ref::<T>(ResourceIndex::Global))
}
fn borrow(resource_archetypes: &HashMap<TypeId, Archetype>) {
if let Some(archetype) = resource_archetypes.get(&TypeId::of::<T>()) {
archetype.borrow::<T>();
}
fn borrow(resources: &Resources) {
resources.borrow::<T>();
}
fn release(resource_archetypes: &HashMap<TypeId, Archetype>) {
if let Some(archetype) = resource_archetypes.get(&TypeId::of::<T>()) {
archetype.release::<T>();
}
fn release(resources: &Resources) {
resources.release::<T>();
}
fn access() -> TypeAccess {
let mut access = TypeAccess::default();
access.immutable.insert(TypeId::of::<T>());
@ -200,19 +170,17 @@ pub struct FetchResourceWrite<T>(NonNull<T>);
impl<'a, T: Component> FetchResource<'a> for FetchResourceWrite<T> {
type Item = ResMut<'a, T>;
unsafe fn get(resources: &'a Resources, _system_id: Option<SystemId>) -> Self::Item {
resources.get_res_mut::<T>()
ResMut::new(resources.get_unsafe_ref::<T>(ResourceIndex::Global))
}
fn borrow(resource_archetypes: &HashMap<TypeId, Archetype>) {
if let Some(archetype) = resource_archetypes.get(&TypeId::of::<T>()) {
archetype.borrow_mut::<T>();
}
fn borrow(resources: &Resources) {
resources.borrow_mut::<T>();
}
fn release(resource_archetypes: &HashMap<TypeId, Archetype>) {
if let Some(archetype) = resource_archetypes.get(&TypeId::of::<T>()) {
archetype.release_mut::<T>();
}
fn release(resources: &Resources) {
resources.release_mut::<T>();
}
fn access() -> TypeAccess {
let mut access = TypeAccess::default();
access.mutable.insert(TypeId::of::<T>());
@ -235,33 +203,23 @@ pub struct FetchResourceLocalMut<T>(NonNull<T>);
impl<'a, T: Component + FromResources> FetchResource<'a> for FetchResourceLocalMut<T> {
type Item = Local<'a, T>;
unsafe fn get(resources: &'a Resources, system_id: Option<SystemId>) -> Self::Item {
if let Some(system_id) = system_id {
let archetype = resources
.resource_archetypes
.get(&TypeId::of::<T>())
.unwrap_or_else(|| {
panic!("Resource does not exist {}", std::any::type_name::<T>())
});
let index = resources
.system_id_to_archetype_index
.get(&system_id.0)
.expect("System does not have this resource");
Local::new(archetype, *index).expect("Resource does not exist")
} else {
panic!("Only Systems can use Local<T> resources");
let id = system_id.expect("Local<T> resources can only be used by systems");
Local {
value: resources
.get_unsafe_ref::<T>(ResourceIndex::System(id))
.as_ptr(),
_marker: Default::default(),
}
}
fn borrow(resource_archetypes: &HashMap<TypeId, Archetype>) {
if let Some(archetype) = resource_archetypes.get(&TypeId::of::<T>()) {
archetype.borrow_mut::<T>();
}
fn borrow(resources: &Resources) {
resources.borrow_mut::<T>();
}
fn release(resource_archetypes: &HashMap<TypeId, Archetype>) {
if let Some(archetype) = resource_archetypes.get(&TypeId::of::<T>()) {
archetype.release_mut::<T>();
}
fn release(resources: &Resources) {
resources.release_mut::<T>();
}
fn access() -> TypeAccess {
let mut access = TypeAccess::default();
access.mutable.insert(TypeId::of::<T>());
@ -275,13 +233,13 @@ macro_rules! tuple_impl {
type Item = ($($name::Item,)*);
#[allow(unused_variables)]
fn borrow(resource_archetypes: &HashMap<TypeId, Archetype>) {
$($name::borrow(resource_archetypes);)*
fn borrow(resources: &Resources) {
$($name::borrow(resources);)*
}
#[allow(unused_variables)]
fn release(resource_archetypes: &HashMap<TypeId, Archetype>) {
$($name::release(resource_archetypes);)*
fn release(resources: &Resources) {
$($name::release(resources);)*
}
#[allow(unused_variables)]

View file

@ -1,78 +1,79 @@
use super::{FetchResource, Res, ResMut, ResourceQuery};
use super::{FetchResource, ResourceQuery};
use crate::system::SystemId;
use core::any::TypeId;
use hecs::{Archetype, ComponentError, Ref, RefMut, TypeInfo};
use std::collections::HashMap;
use hecs::{Archetype, Ref, RefMut, TypeInfo};
use std::{collections::HashMap, ptr::NonNull};
pub trait Resource: Send + Sync + 'static {}
impl<T: Send + Sync + 'static> Resource for T {}
pub struct ResourceData {
archetype: Archetype,
default_index: Option<u32>,
system_id_to_archetype_index: HashMap<u32, u32>,
}
pub enum ResourceIndex {
Global,
System(SystemId),
}
#[derive(Default)]
pub struct Resources {
pub(crate) resource_archetypes: HashMap<TypeId, Archetype>,
pub(crate) system_id_to_archetype_index: HashMap<u32, u32>,
pub(crate) resource_data: HashMap<TypeId, ResourceData>,
}
impl Resources {
pub fn insert<T: Resource>(&mut self, resource: T) {
self.insert_index(resource, 0);
self.insert_resource(resource, ResourceIndex::Global);
}
pub fn contains<T: Resource>(&self) -> bool {
self.get_index::<T>(0).is_ok()
self.get_resource::<T>(ResourceIndex::Global).is_some()
}
pub fn get<T: Resource>(&self) -> Result<Ref<'_, T>, ComponentError> {
self.get_index(0)
pub fn get<T: Resource>(&self) -> Option<Ref<'_, T>> {
self.get_resource(ResourceIndex::Global)
}
pub fn get_mut<T: Resource>(&self) -> Result<RefMut<'_, T>, ComponentError> {
self.get_index_mut(0)
pub fn get_mut<T: Resource>(&self) -> Option<RefMut<'_, T>> {
self.get_resource_mut(ResourceIndex::Global)
}
pub fn get_local<'a, T: Resource>(
&'a self,
id: SystemId,
) -> Result<Ref<'a, T>, ComponentError> {
self.system_id_to_archetype_index
.get(&id.0)
.ok_or_else(|| ComponentError::NoSuchEntity)
.and_then(|index| self.get_index(*index))
pub fn get_local<'a, T: Resource>(&'a self, id: SystemId) -> Option<Ref<'a, T>> {
self.get_resource(ResourceIndex::System(id))
}
pub fn get_local_mut<'a, T: Resource>(
&'a self,
id: SystemId,
) -> Result<RefMut<'a, T>, ComponentError> {
self.system_id_to_archetype_index
.get(&id.0)
.ok_or_else(|| ComponentError::NoSuchEntity)
.and_then(|index| self.get_index_mut(*index))
pub fn get_local_mut<'a, T: Resource>(&'a self, id: SystemId) -> Option<RefMut<'a, T>> {
self.get_resource_mut(ResourceIndex::System(id))
}
pub fn insert_local<T: Resource>(&mut self, id: SystemId, resource: T) {
if let Some(index) = self.system_id_to_archetype_index.get(&id.0).cloned() {
self.insert_index(resource, index);
} else {
let mut index = self.archetype_len::<T>();
// index 0 is reserved for the global non-system resource
if index == 0 {
self.allocate_next::<T>();
index += 1;
}
self.insert_index(resource, index);
self.system_id_to_archetype_index.insert(id.0, index);
}
self.insert_resource(resource, ResourceIndex::System(id))
}
fn insert_index<T: Resource>(&mut self, mut resource: T, index: u32) {
fn insert_resource<T: Resource>(&mut self, mut resource: T, resource_index: ResourceIndex) {
let type_id = TypeId::of::<T>();
let archetype = self.resource_archetypes.entry(type_id).or_insert_with(|| {
let data = self.resource_data.entry(type_id).or_insert_with(|| {
let mut types = Vec::new();
types.push(TypeInfo::of::<T>());
Archetype::new(types)
ResourceData {
archetype: Archetype::new(types),
default_index: None,
system_id_to_archetype_index: HashMap::new(),
}
});
let archetype = &mut data.archetype;
let index = match resource_index {
ResourceIndex::Global => *data.default_index.get_or_insert_with(|| archetype.len()),
ResourceIndex::System(id) => *data
.system_id_to_archetype_index
.entry(id.0)
.or_insert_with(|| archetype.len()),
};
if index == archetype.len() {
unsafe { archetype.allocate(index) };
} else if index > archetype.len() {
@ -86,42 +87,33 @@ impl Resources {
}
}
fn allocate_next<T: Resource>(&mut self) {
let type_id = TypeId::of::<T>();
let archetype = self.resource_archetypes.entry(type_id).or_insert_with(|| {
let mut types = Vec::new();
types.push(TypeInfo::of::<T>());
Archetype::new(types)
});
let index = archetype.len();
unsafe { archetype.allocate(index) };
}
fn get_index<T: Resource>(&self, index: u32) -> Result<Ref<'_, T>, ComponentError> {
self.resource_archetypes
fn get_resource<T: Resource>(&self, resource_index: ResourceIndex) -> Option<Ref<'_, T>> {
self.resource_data
.get(&TypeId::of::<T>())
.ok_or_else(|| ComponentError::NoSuchEntity)
.and_then(|archetype| unsafe {
Ref::new(archetype, index).map_err(|err| ComponentError::MissingComponent(err))
.and_then(|data| unsafe {
let index = match resource_index {
ResourceIndex::Global => data.default_index?,
ResourceIndex::System(id) => *data.system_id_to_archetype_index.get(&id.0)?,
};
Ref::new(&data.archetype, index).ok()
})
}
fn get_index_mut<T: Resource>(&self, index: u32) -> Result<RefMut<'_, T>, ComponentError> {
self.resource_archetypes
fn get_resource_mut<T: Resource>(
&self,
resource_index: ResourceIndex,
) -> Option<RefMut<'_, T>> {
self.resource_data
.get(&TypeId::of::<T>())
.ok_or_else(|| ComponentError::NoSuchEntity)
.and_then(|archetype| unsafe {
RefMut::new(archetype, index).map_err(|err| ComponentError::MissingComponent(err))
.and_then(|data| unsafe {
let index = match resource_index {
ResourceIndex::Global => data.default_index?,
ResourceIndex::System(id) => *data.system_id_to_archetype_index.get(&id.0)?,
};
RefMut::new(&data.archetype, index).ok()
})
}
fn archetype_len<T: Resource>(&self) -> u32 {
self.resource_archetypes
.get(&TypeId::of::<T>())
.map_or(0, |a| a.len())
}
pub fn query<Q: ResourceQuery>(&self) -> <Q::Fetch as FetchResource>::Item {
unsafe { Q::Fetch::get(&self, None) }
}
@ -134,21 +126,45 @@ impl Resources {
}
#[inline]
pub unsafe fn get_res<T: Resource>(&self) -> Res<'_, T> {
let archetype = self
.resource_archetypes
pub unsafe fn get_unsafe_ref<T: Resource>(&self, resource_index: ResourceIndex) -> NonNull<T> {
self.resource_data
.get(&TypeId::of::<T>())
.unwrap_or_else(|| panic!("Resource does not exist {}", std::any::type_name::<T>()));
Res::new(archetype, 0).expect("Resource does not exist")
.and_then(|data| {
let index = match resource_index {
ResourceIndex::Global => data.default_index?,
ResourceIndex::System(id) => {
data.system_id_to_archetype_index.get(&id.0).cloned()?
}
};
Some(NonNull::new_unchecked(
data.archetype.get::<T>()?.as_ptr().add(index as usize),
))
})
.unwrap_or_else(|| panic!("Resource does not exist {}", std::any::type_name::<T>()))
}
#[inline]
pub unsafe fn get_res_mut<T: Resource>(&self) -> ResMut<'_, T> {
let archetype = self
.resource_archetypes
.get(&TypeId::of::<T>())
.unwrap_or_else(|| panic!("Resource does not exist {}", std::any::type_name::<T>()));
ResMut::new(archetype, 0).expect("Resource does not exist")
pub fn borrow<T: Resource>(&self) {
if let Some(data) = self.resource_data.get(&TypeId::of::<T>()) {
data.archetype.borrow::<T>();
}
}
pub fn release<T: Resource>(&self) {
if let Some(data) = self.resource_data.get(&TypeId::of::<T>()) {
data.archetype.release::<T>();
}
}
pub fn borrow_mut<T: Resource>(&self) {
if let Some(data) = self.resource_data.get(&TypeId::of::<T>()) {
data.archetype.borrow_mut::<T>();
}
}
pub fn release_mut<T: Resource>(&self) {
if let Some(data) = self.resource_data.get(&TypeId::of::<T>()) {
data.archetype.release_mut::<T>();
}
}
}
@ -176,7 +192,7 @@ mod tests {
#[test]
fn resource() {
let mut resources = Resources::default();
assert!(resources.get::<i32>().is_err());
assert!(resources.get::<i32>().is_none());
resources.insert(123);
assert_eq!(*resources.get::<i32>().expect("resource exists"), 123);
@ -195,7 +211,7 @@ mod tests {
assert_eq!(*resources.get::<f64>().expect("resource exists"), -1.0);
assert!(resources.get_local::<i32>(SystemId(0)).is_err());
assert!(resources.get_local::<i32>(SystemId(0)).is_none());
resources.insert_local(SystemId(0), 111);
assert_eq!(
*resources

View file

@ -105,14 +105,14 @@ macro_rules! impl_into_foreach_system {
name: core::any::type_name::<Self>().into(),
id,
func: move |world, resources, _archetype_access, state| {
<<($($resource,)*) as ResourceQuery>::Fetch as FetchResource>::borrow(&resources.resource_archetypes);
<<($($resource,)*) as ResourceQuery>::Fetch as FetchResource>::borrow(&resources);
{
let ($($resource,)*) = resources.query_system::<($($resource,)*)>(id);
for ($($component,)*) in world.query::<($($component,)*)>().iter() {
fn_call!(self, ($($commands, state)*), ($($resource),*), ($($component),*))
}
}
<<($($resource,)*) as ResourceQuery>::Fetch as FetchResource>::release(&resources.resource_archetypes);
<<($($resource,)*) as ResourceQuery>::Fetch as FetchResource>::release(&resources);
},
thread_local_func: move |world, resources, state| {
state.apply(world, resources);
@ -251,7 +251,7 @@ macro_rules! impl_into_query_system {
id,
name: core::any::type_name::<Self>().into(),
func: move |world, resources, archetype_access, state| {
<<($($resource,)*) as ResourceQuery>::Fetch as FetchResource>::borrow(&resources.resource_archetypes);
<<($($resource,)*) as ResourceQuery>::Fetch as FetchResource>::borrow(&resources);
{
let ($($resource,)*) = resources.query_system::<($($resource,)*)>(id);
let mut i = 0;
@ -267,7 +267,7 @@ macro_rules! impl_into_query_system {
let commands = &state.commands;
fn_call!(self, ($($commands, commands)*), ($($resource),*), ($($query),*))
}
<<($($resource,)*) as ResourceQuery>::Fetch as FetchResource>::release(&resources.resource_archetypes);
<<($($resource,)*) as ResourceQuery>::Fetch as FetchResource>::release(&resources);
},
thread_local_func: move |world, resources, state| {
state.commands.apply(world, resources);

View file

@ -11,11 +11,11 @@ use crate::{
};
use bevy_asset::{Assets, Handle};
use bevy_ecs::{
Archetype, FetchResource, Query, Res, ResMut, ResourceQuery, Resources, SystemId, TypeAccess,
UnsafeClone,
FetchResource, Query, Res, ResMut, ResourceIndex, ResourceQuery, Resources, SystemId,
TypeAccess, UnsafeClone,
};
use bevy_property::Properties;
use std::{any::TypeId, collections::HashMap, ops::Range, sync::Arc};
use std::{any::TypeId, ops::Range, sync::Arc};
use thiserror::Error;
#[derive(Debug, Clone, Eq, PartialEq)]
@ -150,66 +150,40 @@ pub struct FetchDrawContext;
// TODO: derive this impl
impl<'a> FetchResource<'a> for FetchDrawContext {
type Item = DrawContext<'a>;
fn borrow(resource_archetypes: &HashMap<TypeId, Archetype>) {
resource_archetypes
.get(&TypeId::of::<Assets<PipelineDescriptor>>())
.unwrap()
.borrow_mut::<Assets<PipelineDescriptor>>();
resource_archetypes
.get(&TypeId::of::<Assets<Shader>>())
.unwrap()
.borrow_mut::<Assets<Shader>>();
resource_archetypes
.get(&TypeId::of::<PipelineCompiler>())
.unwrap()
.borrow_mut::<PipelineCompiler>();
resource_archetypes
.get(&TypeId::of::<Box<dyn RenderResourceContext>>())
.unwrap()
.borrow::<Box<dyn RenderResourceContext>>();
resource_archetypes
.get(&TypeId::of::<VertexBufferDescriptors>())
.unwrap()
.borrow::<VertexBufferDescriptors>();
resource_archetypes
.get(&TypeId::of::<SharedBuffers>())
.unwrap()
.borrow::<SharedBuffers>();
fn borrow(resources: &Resources) {
resources.borrow_mut::<Assets<PipelineDescriptor>>();
resources.borrow_mut::<Assets<Shader>>();
resources.borrow_mut::<PipelineCompiler>();
resources.borrow::<Box<dyn RenderResourceContext>>();
resources.borrow::<VertexBufferDescriptors>();
resources.borrow::<SharedBuffers>();
}
fn release(resource_archetypes: &HashMap<TypeId, Archetype>) {
resource_archetypes
.get(&TypeId::of::<Assets<PipelineDescriptor>>())
.unwrap()
.release_mut::<Assets<PipelineDescriptor>>();
resource_archetypes
.get(&TypeId::of::<Assets<Shader>>())
.unwrap()
.release_mut::<Assets<Shader>>();
resource_archetypes
.get(&TypeId::of::<PipelineCompiler>())
.unwrap()
.release_mut::<PipelineCompiler>();
resource_archetypes
.get(&TypeId::of::<Box<dyn RenderResourceContext>>())
.unwrap()
.release::<Box<dyn RenderResourceContext>>();
resource_archetypes
.get(&TypeId::of::<VertexBufferDescriptors>())
.unwrap()
.release::<VertexBufferDescriptors>();
resource_archetypes
.get(&TypeId::of::<SharedBuffers>())
.unwrap()
.release::<SharedBuffers>();
fn release(resources: &Resources) {
resources.release_mut::<Assets<PipelineDescriptor>>();
resources.release_mut::<Assets<Shader>>();
resources.release_mut::<PipelineCompiler>();
resources.release::<Box<dyn RenderResourceContext>>();
resources.release::<VertexBufferDescriptors>();
resources.release::<SharedBuffers>();
}
unsafe fn get(resources: &'a Resources, _system_id: Option<SystemId>) -> Self::Item {
DrawContext {
pipelines: resources.get_res_mut::<Assets<PipelineDescriptor>>(),
shaders: resources.get_res_mut::<Assets<Shader>>(),
pipeline_compiler: resources.get_res_mut::<PipelineCompiler>(),
render_resource_context: resources.get_res::<Box<dyn RenderResourceContext>>(),
vertex_buffer_descriptors: resources.get_res::<VertexBufferDescriptors>(),
shared_buffers: resources.get_res::<SharedBuffers>(),
pipelines: ResMut::new(
resources.get_unsafe_ref::<Assets<PipelineDescriptor>>(ResourceIndex::Global),
),
shaders: ResMut::new(resources.get_unsafe_ref::<Assets<Shader>>(ResourceIndex::Global)),
pipeline_compiler: ResMut::new(
resources.get_unsafe_ref::<PipelineCompiler>(ResourceIndex::Global),
),
render_resource_context: Res::new(
resources.get_unsafe_ref::<Box<dyn RenderResourceContext>>(ResourceIndex::Global),
),
vertex_buffer_descriptors: Res::new(
resources.get_unsafe_ref::<VertexBufferDescriptors>(ResourceIndex::Global),
),
shared_buffers: Res::new(
resources.get_unsafe_ref::<SharedBuffers>(ResourceIndex::Global),
),
current_pipeline: None,
}
}

View file

@ -109,7 +109,7 @@ impl Node for PassNode {
for (i, color_attachment) in self.descriptor.color_attachments.iter_mut().enumerate() {
if self.default_clear_color_inputs.contains(&i) {
if let Ok(default_clear_color) = resources.get::<ClearColor>() {
if let Some(default_clear_color) = resources.get::<ClearColor>() {
color_attachment.ops.load = LoadOp::Clear(default_clear_color.0);
}
}

View file

@ -52,7 +52,7 @@ pub fn winit_runner(mut app: App) {
ControlFlow::Poll
};
if let Ok(app_exit_events) = app.resources.get_mut::<Events<AppExit>>() {
if let Some(app_exit_events) = app.resources.get_mut::<Events<AppExit>>() {
if app_exit_event_reader.latest(&app_exit_events).is_some() {
*control_flow = ControlFlow::Exit;
}