remove unsafe Clone implementation on Res/ResMut in favor of UnsafeClone

This commit is contained in:
Carter Anderson 2020-07-12 12:06:43 -07:00
parent df17d166cf
commit 17f3860d12
12 changed files with 96 additions and 54 deletions

View file

@ -1,10 +1,10 @@
use crate::{ use crate::modules::{get_modules, get_path};
modules::{get_modules, get_path},
};
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, DeriveInput, Path, Data, DataStruct, Fields, Field, parse::ParseStream}; use syn::{
parse::ParseStream, parse_macro_input, Data, DataStruct, DeriveInput, Field, Fields, Path,
};
#[derive(Default)] #[derive(Default)]
struct VertexAttributes { struct VertexAttributes {
@ -31,22 +31,29 @@ pub fn derive_as_vertex_buffer_descriptor(input: TokenStream) -> TokenStream {
.map(|field| { .map(|field| {
( (
field, field,
field.attrs field
.attrs
.iter() .iter()
.find(|a| a.path.get_ident().as_ref().unwrap().to_string() == VERTEX_ATTRIBUTE_NAME) .find(|a| {
.map_or_else(|| VertexAttributes::default() ,|a| { a.path.get_ident().as_ref().unwrap().to_string() == VERTEX_ATTRIBUTE_NAME
syn::custom_keyword!(ignore); })
let mut vertex_attributes = VertexAttributes::default(); .map_or_else(
a.parse_args_with(|input: ParseStream| { || VertexAttributes::default(),
if let Some(_) = input.parse::<Option<ignore>>()? { |a| {
vertex_attributes.ignore = true; syn::custom_keyword!(ignore);
return Ok(()); let mut vertex_attributes = VertexAttributes::default();
} a.parse_args_with(|input: ParseStream| {
Ok(()) if let Some(_) = input.parse::<Option<ignore>>()? {
}).expect("invalid 'vertex' attribute format"); vertex_attributes.ignore = true;
return Ok(());
}
Ok(())
})
.expect("invalid 'vertex' attribute format");
vertex_attributes vertex_attributes
}), },
),
) )
}) })
.collect::<Vec<(&Field, VertexAttributes)>>(); .collect::<Vec<(&Field, VertexAttributes)>>();

View file

@ -1,5 +1,5 @@
use crate::{ use crate::{
resource_query::{FetchResource, ResourceQuery}, resource_query::{FetchResource, ResourceQuery, UnsafeClone},
system::{System, SystemId, ThreadLocalExecution}, system::{System, SystemId, ThreadLocalExecution},
Commands, Resources, Commands, Resources,
}; };
@ -74,6 +74,7 @@ macro_rules! impl_into_foreach_system {
{ {
#[allow(non_snake_case)] #[allow(non_snake_case)]
#[allow(unused_variables)] #[allow(unused_variables)]
#[allow(unused_unsafe)]
fn system(mut self) -> Box<dyn System> { fn system(mut self) -> Box<dyn System> {
let id = SystemId::new(); let id = SystemId::new();
Box::new(SystemFn { Box::new(SystemFn {
@ -136,6 +137,7 @@ macro_rules! impl_into_query_system {
{ {
#[allow(non_snake_case)] #[allow(non_snake_case)]
#[allow(unused_variables)] #[allow(unused_variables)]
#[allow(unused_unsafe)]
fn system(mut self) -> Box<dyn System> { fn system(mut self) -> Box<dyn System> {
let id = SystemId::new(); let id = SystemId::new();
Box::new(SystemFn { Box::new(SystemFn {
@ -163,10 +165,10 @@ macro_rules! impl_into_query_system {
macro_rules! fn_call { macro_rules! fn_call {
($self:ident, ($($commands: ident, $commands_var: ident)*), ($($resource: ident),*), ($($a: ident),*)) => { ($self:ident, ($($commands: ident, $commands_var: ident)*), ($($resource: ident),*), ($($a: ident),*)) => {
$self($($commands_var.clone(),)* $($resource.clone(),)* $($a,)*) unsafe { $self($($commands_var.clone(),)* $($resource.unsafe_clone(),)* $($a,)*) }
}; };
($self:ident, (), ($($resource: ident),*), ($($a: ident),*)) => { ($self:ident, (), ($($resource: ident),*), ($($a: ident),*)) => {
$self($($resource.clone(),)* $($a,)*) unsafe { $self($($resource.unsafe_clone(),)* $($a,)*) }
}; };
} }

View file

@ -4,7 +4,7 @@ mod commands;
mod into_system; mod into_system;
#[cfg(feature = "profiler")] #[cfg(feature = "profiler")]
pub mod profiler; pub mod profiler;
mod resource_query; pub mod resource_query;
mod resources; mod resources;
mod schedule; mod schedule;
mod system; mod system;

View file

@ -26,9 +26,13 @@ impl<'a, T: Component> Res<'a, T> {
} }
} }
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 // TODO: this is unsafe. lets think of a better solution that allows us to clone internally
impl<'a, T: Component> Clone for ResMut<'a, T> { impl<'a, T: Component> UnsafeClone for ResMut<'a, T> {
fn clone(&self) -> Self { unsafe fn unsafe_clone(&self) -> Self {
Self { Self {
archetype: self.archetype, archetype: self.archetype,
target: self.target, target: self.target,
@ -36,8 +40,8 @@ impl<'a, T: Component> Clone for ResMut<'a, T> {
} }
} }
impl<'a, T: Component> Clone for Res<'a, T> { impl<'a, T: Component> UnsafeClone for Res<'a, T> {
fn clone(&self) -> Self { unsafe fn unsafe_clone(&self) -> Self {
Self { Self {
archetype: self.archetype, archetype: self.archetype,
target: self.target, target: self.target,
@ -110,9 +114,8 @@ impl<'a, T: Component + FromResources> Local<'a, T> {
} }
} }
// TODO: this is unsafe. lets think of a better solution that allows us to clone internally impl<'a, T: Component + FromResources> UnsafeClone for Local<'a, T> {
impl<'a, T: Component + FromResources> Clone for Local<'a, T> { unsafe fn unsafe_clone(&self) -> Self {
fn clone(&self) -> Self {
Self { Self {
archetype: self.archetype, archetype: self.archetype,
target: self.target, target: self.target,
@ -143,7 +146,7 @@ pub trait ResourceQuery {
/// Streaming iterators over contiguous homogeneous ranges of components /// Streaming iterators over contiguous homogeneous ranges of components
pub trait FetchResource<'a>: Sized { pub trait FetchResource<'a>: Sized {
/// Type of value to be fetched /// Type of value to be fetched
type Item: Clone; type Item: UnsafeClone;
fn borrow(resource_archetypes: &HashMap<TypeId, Archetype>); fn borrow(resource_archetypes: &HashMap<TypeId, Archetype>);
fn release(resource_archetypes: &HashMap<TypeId, Archetype>); fn release(resource_archetypes: &HashMap<TypeId, Archetype>);
@ -276,6 +279,15 @@ macro_rules! tuple_impl {
$($name::initialize(resources, system_id);)* $($name::initialize(resources, system_id);)*
} }
} }
#[allow(unused_variables)]
#[allow(non_snake_case)]
impl<$($name: UnsafeClone),*> UnsafeClone for ($($name,)*) {
unsafe fn unsafe_clone(&self) -> Self {
let ($($name,)*) = self;
($($name.unsafe_clone(),)*)
}
}
}; };
} }

View file

@ -131,8 +131,10 @@ pub fn lights_node_system(
data[0..light_count_size].copy_from_slice([light_count as u32, 0, 0, 0].as_bytes()); data[0..light_count_size].copy_from_slice([light_count as u32, 0, 0, 0].as_bytes());
// light array // light array
for ((light, transform, translation), slot) in for ((light, transform, translation), slot) in query
query.iter().iter().zip(data[light_count_size..current_light_uniform_size].chunks_exact_mut(size)) .iter()
.iter()
.zip(data[light_count_size..current_light_uniform_size].chunks_exact_mut(size))
{ {
slot.copy_from_slice( slot.copy_from_slice(
LightRaw::from(&light, &transform.value, &translation).as_bytes(), LightRaw::from(&light, &transform.value, &translation).as_bytes(),

View file

@ -3,11 +3,11 @@ extern crate proc_macro;
mod modules; mod modules;
use modules::{get_modules, get_path}; use modules::{get_modules, get_path};
use proc_macro::{TokenStream}; use proc_macro::TokenStream;
use proc_macro_crate::crate_name; use proc_macro_crate::crate_name;
use quote::quote; use quote::quote;
use syn::{ use syn::{
parse::{ParseStream, Parse}, parse::{Parse, ParseStream},
parse_macro_input, parse_macro_input,
punctuated::Punctuated, punctuated::Punctuated,
token::{Comma, Where}, token::{Comma, Where},
@ -48,19 +48,20 @@ pub fn derive_properties(input: TokenStream) -> TokenStream {
f, f,
f.attrs f.attrs
.iter() .iter()
.find(|a| a.path.get_ident().as_ref().unwrap().to_string() == PROP_ATTRIBUTE_NAME) .find(|a| {
a.path.get_ident().as_ref().unwrap().to_string() == PROP_ATTRIBUTE_NAME
})
.map(|a| { .map(|a| {
syn::custom_keyword!(ignore); syn::custom_keyword!(ignore);
let mut attribute_args = PropAttributeArgs { let mut attribute_args = PropAttributeArgs { ignore: None };
ignore: None,
};
a.parse_args_with(|input: ParseStream| { a.parse_args_with(|input: ParseStream| {
if let Some(_) = input.parse::<Option<ignore>>()? { if let Some(_) = input.parse::<Option<ignore>>()? {
attribute_args.ignore = Some(true); attribute_args.ignore = Some(true);
return Ok(()); return Ok(());
} }
Ok(()) Ok(())
}).expect("invalid 'property' attribute format"); })
.expect("invalid 'property' attribute format");
attribute_args attribute_args
}), }),

View file

@ -11,7 +11,10 @@ use crate::{
shader::Shader, shader::Shader,
}; };
use bevy_asset::{Assets, Handle}; use bevy_asset::{Assets, Handle};
use bevy_ecs::{Archetype, FetchResource, Query, Res, ResMut, ResourceQuery, Resources, SystemId}; use bevy_ecs::{
resource_query::UnsafeClone, Archetype, FetchResource, Query, Res, ResMut, ResourceQuery,
Resources, SystemId,
};
use bevy_property::Properties; use bevy_property::Properties;
use std::{any::TypeId, collections::HashMap, ops::Range, sync::Arc}; use std::{any::TypeId, collections::HashMap, ops::Range, sync::Arc};
use thiserror::Error; use thiserror::Error;
@ -115,7 +118,6 @@ pub enum DrawError {
BufferAllocationFailure, BufferAllocationFailure,
} }
#[derive(Clone)]
pub struct DrawContext<'a> { pub struct DrawContext<'a> {
pub pipelines: ResMut<'a, Assets<PipelineDescriptor>>, pub pipelines: ResMut<'a, Assets<PipelineDescriptor>>,
pub shaders: ResMut<'a, Assets<Shader>>, pub shaders: ResMut<'a, Assets<Shader>>,
@ -126,6 +128,20 @@ pub struct DrawContext<'a> {
pub current_pipeline: Option<Handle<PipelineDescriptor>>, pub current_pipeline: Option<Handle<PipelineDescriptor>>,
} }
impl<'a> UnsafeClone for DrawContext<'a> {
unsafe fn unsafe_clone(&self) -> Self {
Self {
pipelines: self.pipelines.unsafe_clone(),
shaders: self.shaders.unsafe_clone(),
pipeline_compiler: self.pipeline_compiler.unsafe_clone(),
render_resource_context: self.render_resource_context.unsafe_clone(),
vertex_buffer_descriptors: self.vertex_buffer_descriptors.unsafe_clone(),
shared_buffers: self.shared_buffers.unsafe_clone(),
current_pipeline: self.current_pipeline.clone(),
}
}
}
impl<'a> ResourceQuery for DrawContext<'a> { impl<'a> ResourceQuery for DrawContext<'a> {
type Fetch = FetchDrawContext; type Fetch = FetchDrawContext;
} }

View file

@ -14,4 +14,4 @@ pub struct Operations<V> {
pub load: LoadOp<V>, pub load: LoadOp<V>,
/// Whether data will be written to through this attachment. /// Whether data will be written to through this attachment.
pub store: bool, pub store: bool,
} }

View file

@ -1,6 +1,6 @@
use crate::{ use crate::{
draw::{Draw, RenderCommand}, draw::{Draw, RenderCommand},
pass::{ClearColor, PassDescriptor, TextureAttachment, LoadOp}, pass::{ClearColor, LoadOp, PassDescriptor, TextureAttachment},
pipeline::{ pipeline::{
BindGroupDescriptor, BindType, BindingDescriptor, PipelineDescriptor, UniformProperty, BindGroupDescriptor, BindType, BindingDescriptor, PipelineDescriptor, UniformProperty,
}, },

View file

@ -599,7 +599,9 @@ fn asset_render_resources_node_system<T: RenderResources>(
state state
.uniform_buffer_arrays .uniform_buffer_arrays
.setup_buffer_arrays(render_resource_context, state.dynamic_uniforms); .setup_buffer_arrays(render_resource_context, state.dynamic_uniforms);
state.uniform_buffer_arrays.update_staging_buffer(render_resource_context); state
.uniform_buffer_arrays
.update_staging_buffer(render_resource_context);
for asset_handle in modified_assets.iter() { for asset_handle in modified_assets.iter() {
let asset = assets.get(&asset_handle).expect(EXPECT_ASSET_MESSAGE); let asset = assets.get(&asset_handle).expect(EXPECT_ASSET_MESSAGE);

View file

@ -24,14 +24,8 @@ pub trait RenderResourceContext: Downcast + Send + Sync + 'static {
range: Range<u64>, range: Range<u64>,
write: &mut dyn FnMut(&mut [u8], &dyn RenderResourceContext), write: &mut dyn FnMut(&mut [u8], &dyn RenderResourceContext),
); );
fn map_buffer( fn map_buffer(&self, id: BufferId);
&self, fn unmap_buffer(&self, id: BufferId);
id: BufferId,
);
fn unmap_buffer(
&self,
id: BufferId,
);
fn create_buffer_with_data(&self, buffer_info: BufferInfo, data: &[u8]) -> BufferId; fn create_buffer_with_data(&self, buffer_info: BufferInfo, data: &[u8]) -> BufferId;
fn create_shader_module(&self, shader_handle: Handle<Shader>, shaders: &Assets<Shader>); fn create_shader_module(&self, shader_handle: Handle<Shader>, shaders: &Assets<Shader>);
fn create_shader_module_from_source(&self, shader_handle: Handle<Shader>, shader: &Shader); fn create_shader_module_from_source(&self, shader_handle: Handle<Shader>, shader: &Shader);

View file

@ -228,7 +228,13 @@ fn create_wgpu_depth_stencil_attachment_descriptor<'a>(
wgpu::RenderPassDepthStencilAttachmentDescriptor { wgpu::RenderPassDepthStencilAttachmentDescriptor {
attachment, attachment,
depth_ops: depth_stencil_attachment_descriptor.depth_ops.as_ref().map(|ops| ops.wgpu_into()), depth_ops: depth_stencil_attachment_descriptor
stencil_ops: depth_stencil_attachment_descriptor.stencil_ops.as_ref().map(|ops| ops.wgpu_into()), .depth_ops
.as_ref()
.map(|ops| ops.wgpu_into()),
stencil_ops: depth_stencil_attachment_descriptor
.stencil_ops
.as_ref()
.map(|ops| ops.wgpu_into()),
} }
} }