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

View file

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

View file

@ -4,7 +4,7 @@ mod commands;
mod into_system;
#[cfg(feature = "profiler")]
pub mod profiler;
mod resource_query;
pub mod resource_query;
mod resources;
mod schedule;
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
impl<'a, T: Component> Clone for ResMut<'a, T> {
fn clone(&self) -> Self {
impl<'a, T: Component> UnsafeClone for ResMut<'a, T> {
unsafe fn unsafe_clone(&self) -> Self {
Self {
archetype: self.archetype,
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> {
fn clone(&self) -> Self {
impl<'a, T: Component> UnsafeClone for Res<'a, T> {
unsafe fn unsafe_clone(&self) -> Self {
Self {
archetype: self.archetype,
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> Clone for Local<'a, T> {
fn clone(&self) -> Self {
impl<'a, T: Component + FromResources> UnsafeClone for Local<'a, T> {
unsafe fn unsafe_clone(&self) -> Self {
Self {
archetype: self.archetype,
target: self.target,
@ -143,7 +146,7 @@ pub trait ResourceQuery {
/// Streaming iterators over contiguous homogeneous ranges of components
pub trait FetchResource<'a>: Sized {
/// Type of value to be fetched
type Item: Clone;
type Item: UnsafeClone;
fn borrow(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);)*
}
}
#[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());
// light array
for ((light, transform, translation), slot) in
query.iter().iter().zip(data[light_count_size..current_light_uniform_size].chunks_exact_mut(size))
for ((light, transform, translation), slot) in query
.iter()
.iter()
.zip(data[light_count_size..current_light_uniform_size].chunks_exact_mut(size))
{
slot.copy_from_slice(
LightRaw::from(&light, &transform.value, &translation).as_bytes(),

View file

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

View file

@ -11,7 +11,10 @@ use crate::{
shader::Shader,
};
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 std::{any::TypeId, collections::HashMap, ops::Range, sync::Arc};
use thiserror::Error;
@ -115,7 +118,6 @@ pub enum DrawError {
BufferAllocationFailure,
}
#[derive(Clone)]
pub struct DrawContext<'a> {
pub pipelines: ResMut<'a, Assets<PipelineDescriptor>>,
pub shaders: ResMut<'a, Assets<Shader>>,
@ -126,6 +128,20 @@ pub struct DrawContext<'a> {
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> {
type Fetch = FetchDrawContext;
}

View file

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

View file

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

View file

@ -599,7 +599,9 @@ fn asset_render_resources_node_system<T: RenderResources>(
state
.uniform_buffer_arrays
.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() {
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>,
write: &mut dyn FnMut(&mut [u8], &dyn RenderResourceContext),
);
fn map_buffer(
&self,
id: BufferId,
);
fn unmap_buffer(
&self,
id: BufferId,
);
fn map_buffer(&self, id: BufferId);
fn unmap_buffer(&self, id: 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_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 {
attachment,
depth_ops: depth_stencil_attachment_descriptor.depth_ops.as_ref().map(|ops| ops.wgpu_into()),
stencil_ops: depth_stencil_attachment_descriptor.stencil_ops.as_ref().map(|ops| ops.wgpu_into()),
depth_ops: depth_stencil_attachment_descriptor
.depth_ops
.as_ref()
.map(|ops| ops.wgpu_into()),
stencil_ops: depth_stencil_attachment_descriptor
.stencil_ops
.as_ref()
.map(|ops| ops.wgpu_into()),
}
}