bytes: remove AsBytes in favor of Bytes

This commit is contained in:
Carter Anderson 2020-06-01 14:33:00 -07:00
parent e68ae995f8
commit d5d0107ada
13 changed files with 242 additions and 192 deletions

View file

@ -3,8 +3,8 @@ use crate::{
Handle, HandleId,
};
use bevy_app::{AppBuilder, Events, FromResources};
use bevy_core::bytes::Bytes;
use bevy_type_registry::RegisterType;
use bevy_core::bytes::GetBytes;
use legion::prelude::*;
use std::{
collections::HashMap,
@ -121,13 +121,10 @@ impl<T> Assets<T> {
}
}
impl<T> GetBytes for Handle<T> {
fn get_bytes(&self) -> Vec<u8> {
Vec::new()
}
fn get_bytes_ref(&self) -> Option<&[u8]> {
None
impl<T> Bytes for Handle<T> {
fn write_bytes(&self, _buffer: &mut [u8]) {}
fn byte_len(&self) -> usize {
0
}
}

View file

@ -1,104 +1,127 @@
use glam::{Mat4, Vec2, Vec3, Vec4};
use zerocopy::AsBytes;
pub trait GetBytes {
fn get_bytes(&self) -> Vec<u8>;
fn get_bytes_ref(&self) -> Option<&[u8]>;
macro_rules! impl_bytes_zerocopy {
($ty:tt) => {
impl Bytes for $ty {
fn write_bytes(&self, buffer: &mut [u8]) {
buffer[0..self.byte_len()].copy_from_slice(self.as_bytes())
}
fn byte_len(&self) -> usize {
std::mem::size_of::<Self>()
}
}
};
}
impl GetBytes for f32 {
fn get_bytes(&self) -> Vec<u8> {
self.as_bytes().to_vec()
pub trait Bytes {
fn write_bytes(&self, buffer: &mut [u8]);
fn byte_len(&self) -> usize;
}
impl_bytes_zerocopy!(u8);
impl_bytes_zerocopy!(u16);
impl_bytes_zerocopy!(u32);
impl_bytes_zerocopy!(u64);
impl_bytes_zerocopy!(usize);
impl_bytes_zerocopy!(i8);
impl_bytes_zerocopy!(i16);
impl_bytes_zerocopy!(i32);
impl_bytes_zerocopy!(i64);
impl_bytes_zerocopy!(isize);
impl_bytes_zerocopy!(f32);
impl_bytes_zerocopy!(f64);
impl_bytes_zerocopy!([u8; 2]);
impl_bytes_zerocopy!([u16; 2]);
impl_bytes_zerocopy!([u32; 2]);
impl_bytes_zerocopy!([u64; 2]);
impl_bytes_zerocopy!([usize; 2]);
impl_bytes_zerocopy!([i8; 2]);
impl_bytes_zerocopy!([i16; 2]);
impl_bytes_zerocopy!([i32; 2]);
impl_bytes_zerocopy!([i64; 2]);
impl_bytes_zerocopy!([isize; 2]);
impl_bytes_zerocopy!([f32; 2]);
impl_bytes_zerocopy!([f64; 2]);
impl_bytes_zerocopy!([u8; 3]);
impl_bytes_zerocopy!([u16; 3]);
impl_bytes_zerocopy!([u32; 3]);
impl_bytes_zerocopy!([u64; 3]);
impl_bytes_zerocopy!([usize; 3]);
impl_bytes_zerocopy!([i8; 3]);
impl_bytes_zerocopy!([i16; 3]);
impl_bytes_zerocopy!([i32; 3]);
impl_bytes_zerocopy!([i64; 3]);
impl_bytes_zerocopy!([isize; 3]);
impl_bytes_zerocopy!([f32; 3]);
impl_bytes_zerocopy!([f64; 3]);
impl_bytes_zerocopy!([u8; 4]);
impl_bytes_zerocopy!([u16; 4]);
impl_bytes_zerocopy!([u32; 4]);
impl_bytes_zerocopy!([u64; 4]);
impl_bytes_zerocopy!([usize; 4]);
impl_bytes_zerocopy!([i8; 4]);
impl_bytes_zerocopy!([i16; 4]);
impl_bytes_zerocopy!([i32; 4]);
impl_bytes_zerocopy!([i64; 4]);
impl_bytes_zerocopy!([isize; 4]);
impl_bytes_zerocopy!([f32; 4]);
impl_bytes_zerocopy!([f64; 4]);
impl Bytes for Vec2 {
fn write_bytes(&self, buffer: &mut [u8]) {
let array: [f32; 2] = (*self).into();
buffer[0..self.byte_len()].copy_from_slice(array.as_bytes())
}
fn get_bytes_ref(&self) -> Option<&[u8]> {
Some(self.as_bytes())
fn byte_len(&self) -> usize {
std::mem::size_of::<Self>()
}
}
impl GetBytes for [f32; 2] {
fn get_bytes(&self) -> Vec<u8> {
self.as_bytes().to_vec()
impl Bytes for Vec3 {
fn write_bytes(&self, buffer: &mut [u8]) {
let array: [f32; 3] = (*self).into();
buffer[0..self.byte_len()].copy_from_slice(array.as_bytes())
}
fn get_bytes_ref(&self) -> Option<&[u8]> {
Some(self.as_bytes())
fn byte_len(&self) -> usize {
std::mem::size_of::<Self>()
}
}
impl GetBytes for [f32; 3] {
fn get_bytes(&self) -> Vec<u8> {
self.as_bytes().to_vec()
impl Bytes for Vec4 {
fn write_bytes(&self, buffer: &mut [u8]) {
let array: [f32; 4] = (*self).into();
buffer[0..self.byte_len()].copy_from_slice(array.as_bytes())
}
fn get_bytes_ref(&self) -> Option<&[u8]> {
Some(self.as_bytes())
fn byte_len(&self) -> usize {
std::mem::size_of::<Self>()
}
}
impl GetBytes for [f32; 4] {
fn get_bytes(&self) -> Vec<u8> {
self.as_bytes().to_vec()
impl Bytes for Mat4 {
fn write_bytes(&self, buffer: &mut [u8]) {
buffer[0..self.byte_len()].copy_from_slice(self.to_cols_array().as_bytes())
}
fn get_bytes_ref(&self) -> Option<&[u8]> {
Some(self.as_bytes())
fn byte_len(&self) -> usize {
std::mem::size_of::<Self>()
}
}
impl GetBytes for Vec3 {
fn get_bytes(&self) -> Vec<u8> {
let vec3_array: [f32; 3] = (*self).into();
vec3_array.as_bytes().into()
}
fn get_bytes_ref(&self) -> Option<&[u8]> {
Some(self.as_ref().as_bytes())
}
}
impl GetBytes for Vec2 {
fn get_bytes(&self) -> Vec<u8> {
let vec2_array: [f32; 2] = (*self).into();
vec2_array.as_bytes().into()
}
fn get_bytes_ref(&self) -> Option<&[u8]> {
Some(self.as_ref().as_bytes())
}
}
impl GetBytes for Vec4 {
fn get_bytes(&self) -> Vec<u8> {
let vec4_array: [f32; 4] = (*self).into();
vec4_array.as_bytes().into()
}
fn get_bytes_ref(&self) -> Option<&[u8]> {
Some(self.as_ref().as_bytes())
}
}
impl GetBytes for Mat4 {
fn get_bytes(&self) -> Vec<u8> {
self.as_ref()
.as_bytes()
.iter()
.cloned()
.collect::<Vec<u8>>()
}
fn get_bytes_ref(&self) -> Option<&[u8]> {
Some(self.as_ref().as_bytes())
}
}
impl<T> GetBytes for Option<T>
impl<T> Bytes for Option<T>
where
T: GetBytes,
T: Bytes,
{
fn get_bytes(&self) -> Vec<u8> {
Vec::new()
fn write_bytes(&self, buffer: &mut [u8]) {
if let Some(val) = self {
val.write_bytes(buffer)
}
}
fn get_bytes_ref(&self) -> Option<&[u8]> {
self.as_ref()
.and_then(|get_bytes| get_bytes.get_bytes_ref())
fn byte_len(&self) -> usize {
self.as_ref().map_or(0, |val| val.byte_len())
}
}

View file

@ -50,6 +50,44 @@ pub fn derive_resource(input: TokenStream) -> TokenStream {
})
}
#[proc_macro_derive(Bytes, attributes(module))]
pub fn derive_bytes(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as DeriveInput);
let fields = match &ast.data {
Data::Struct(DataStruct {
fields: Fields::Named(fields),
..
}) => &fields.named,
_ => panic!("expected a struct with named fields"),
};
let modules = get_modules(&ast);
let bevy_core_path = get_path(&modules.bevy_core);
let fields = fields.iter().map(|field| field.ident.as_ref().unwrap()).collect::<Vec<_>>();
let generics = ast.generics;
let (impl_generics, ty_generics, _where_clause) = generics.split_for_impl();
let struct_name = &ast.ident;
TokenStream::from(quote! {
impl #impl_generics #bevy_core_path::bytes::Bytes for #struct_name#ty_generics {
fn write_bytes(&self, buffer: &mut [u8]) {
let mut offset: usize = 0;
#(let byte_len = self.#fields.byte_len();
self.#fields.write_bytes(&mut buffer[offset..(offset + byte_len)]);
offset += byte_len;)*
}
fn byte_len(&self) -> usize {
let mut byte_len: usize = 0;
#(byte_len += self.#fields.byte_len();)*
byte_len
}
}
})
}
#[proc_macro_derive(Uniform, attributes(uniform, module))]
pub fn derive_uniform(input: TokenStream) -> TokenStream {
let ast = parse_macro_input!(input as DeriveInput);
@ -88,19 +126,18 @@ pub fn derive_uniform(input: TokenStream) -> TokenStream {
}
}
fn get_uniform_bytes(&self, name: &str) -> Option<Vec<u8>> {
use #bevy_core_path::bytes::GetBytes;
fn write_uniform_bytes(&self, name: &str, buffer: &mut [u8]) {
use #bevy_core_path::bytes::Bytes;
match name {
#struct_name_string => Some(self.get_bytes()),
_ => None,
#struct_name_string => self.write_bytes(buffer),
_ => {},
}
}
fn get_uniform_bytes_ref(&self, name: &str) -> Option<&[u8]> {
use #bevy_core_path::bytes::GetBytes;
fn uniform_byte_len(&self, name: &str) -> usize {
use #bevy_core_path::bytes::Bytes;
match name {
#struct_name_string => self.get_bytes_ref(),
_ => None,
#struct_name_string => self.byte_len(),
_ => 0,
}
}
@ -423,22 +460,6 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
}
}
fn get_uniform_bytes(&self, name: &str) -> Option<Vec<u8>> {
use #bevy_core_path::bytes::GetBytes;
match name {
#(#uniform_name_strings => Some(self.#active_uniform_field_names.get_bytes()),)*
_ => None,
}
}
fn get_uniform_bytes_ref(&self, name: &str) -> Option<&[u8]> {
use #bevy_core_path::bytes::GetBytes;
match name {
#(#uniform_name_strings => self.#active_uniform_field_names.get_bytes_ref(),)*
_ => None,
}
}
fn get_uniform_texture(&self, name: &str) -> Option<#bevy_asset_path::Handle<#bevy_render_path::texture::Texture>> {
use #bevy_render_path::shader::GetTexture;
match name {
@ -447,6 +468,21 @@ pub fn derive_uniforms(input: TokenStream) -> TokenStream {
}
}
fn write_uniform_bytes(&self, name: &str, buffer: &mut [u8]) {
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 {
use #bevy_core_path::bytes::Bytes;
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: this will be very allocation heavy. find a way to either make this allocation free
// or alternatively only run it when the shader_defs have changed

View file

@ -1,10 +1,10 @@
use super::texture::Texture;
use crate::shader::ShaderDefSuffixProvider;
use bevy_asset::Handle;
use bevy_core::bytes::GetBytes;
use serde::{Serialize, Deserialize};
use bevy_core::bytes::Bytes;
use bevy_property::Property;
use glam::Vec4;
use serde::{Deserialize, Serialize};
use std::ops::{Add, AddAssign};
use zerocopy::AsBytes;
@ -91,12 +91,27 @@ impl Into<[f32; 4]> for Color {
}
}
impl GetBytes for Color {
fn get_bytes(&self) -> Vec<u8> {
self.as_bytes().iter().map(|v| *v).collect::<Vec<u8>>()
impl Bytes for Color {
fn write_bytes(&self, buffer: &mut [u8]) {
buffer[0..self.byte_len()].copy_from_slice(self.as_bytes())
}
fn get_bytes_ref(&self) -> Option<&[u8]> {
Some(self.as_bytes())
fn byte_len(&self) -> usize {
std::mem::size_of::<Self>()
}
}
impl Bytes for ColorSource {
fn write_bytes(&self, buffer: &mut [u8]) {
match *self {
ColorSource::Color(ref color) => color.write_bytes(buffer),
ColorSource::Texture(_) => {}, // Texture is not a uniform
}
}
fn byte_len(&self) -> usize {
match *self {
ColorSource::Color(ref color) => color.byte_len(),
ColorSource::Texture(_) => 0, // Texture is not a uniform
}
}
}
@ -130,19 +145,4 @@ impl ShaderDefSuffixProvider for ColorSource {
ColorSource::Texture(_) => Some("_TEXTURE"),
}
}
}
impl GetBytes for ColorSource {
fn get_bytes(&self) -> Vec<u8> {
match *self {
ColorSource::Color(ref color) => color.get_bytes(),
ColorSource::Texture(_) => Vec::new(), // Texture is not a uniform
}
}
fn get_bytes_ref(&self) -> Option<&[u8]> {
match *self {
ColorSource::Color(ref color) => color.get_bytes_ref(),
ColorSource::Texture(ref texture) => texture.get_bytes_ref(), // Texture is not a uniform
}
}
}
}

View file

@ -40,7 +40,7 @@ use self::{
};
use base_render_graph::{BaseRenderGraphBuilder, BaseRenderGraphConfig};
use bevy_app::{stage, AppBuilder, AppPlugin};
use bevy_app::{AppBuilder, AppPlugin};
use bevy_asset::AddAsset;
use bevy_type_registry::RegisterType;
use legion::prelude::IntoSystem;
@ -50,8 +50,10 @@ use render_resource::EntitiesWaitingForAssets;
use texture::{PngTextureLoader, TextureResourceSystemState};
use std::ops::Range;
pub static RENDER_RESOURCE_STAGE: &str = "render_resource";
pub static RENDER_STAGE: &str = "render";
pub mod stage {
pub static RENDER_RESOURCE: &str = "render_resource";
pub static RENDER: &str = "render";
}
pub struct RenderPlugin {
/// configures the "base render graph". If this is not `None`, the "base render graph" will be added
@ -68,8 +70,8 @@ impl Default for RenderPlugin {
impl AppPlugin for RenderPlugin {
fn build(&self, app: &mut AppBuilder) {
app.add_stage_after(bevy_asset::stage::ASSET_EVENTS, RENDER_RESOURCE_STAGE)
.add_stage_after(RENDER_RESOURCE_STAGE, RENDER_STAGE)
app.add_stage_after(bevy_asset::stage::ASSET_EVENTS, stage::RENDER_RESOURCE)
.add_stage_after(stage::RENDER_RESOURCE, stage::RENDER)
.add_asset::<Mesh>()
.add_asset::<Texture>()
.add_asset::<Shader>()
@ -90,15 +92,15 @@ impl AppPlugin for RenderPlugin {
.init_resource::<EntitiesWaitingForAssets>()
.init_resource::<TextureResourceSystemState>()
.add_system(entity_render_resource_assignments_system())
.init_system_to_stage(stage::POST_UPDATE, camera::camera_system::<OrthographicProjection>)
.init_system_to_stage(stage::POST_UPDATE, camera::camera_system::<PerspectiveProjection>)
.init_system_to_stage(bevy_app::stage::POST_UPDATE, camera::camera_system::<OrthographicProjection>)
.init_system_to_stage(bevy_app::stage::POST_UPDATE, camera::camera_system::<PerspectiveProjection>)
.add_system_to_stage(
stage::PRE_UPDATE,
bevy_app::stage::PRE_UPDATE,
EntitiesWaitingForAssets::clear_system.system(),
)
.init_system_to_stage(RENDER_RESOURCE_STAGE, mesh_resource_provider_system)
.init_system_to_stage(stage::RENDER_RESOURCE, mesh_resource_provider_system)
.add_system_to_stage(
RENDER_RESOURCE_STAGE,
stage::RENDER_RESOURCE,
Texture::texture_resource_system.system(),
);

View file

@ -8,7 +8,7 @@ use crate::{
shader::AsUniforms,
Renderable, Vertex,
};
use bevy_app::Events;
use bevy_app::{GetEventReader, Events};
use bevy_asset::{AssetEvent, Assets, Handle};
use glam::*;
use legion::prelude::*;
@ -336,8 +336,7 @@ fn remove_current_mesh_resources(
pub fn mesh_resource_provider_system(resources: &mut Resources) -> Box<dyn Schedulable> {
let mut vertex_buffer_descriptors = resources.get_mut::<VertexBufferDescriptors>().unwrap();
let mesh_events = resources.get::<Events<AssetEvent<Mesh>>>().unwrap();
let mut mesh_event_reader = mesh_events.get_reader();
let mut mesh_event_reader = resources.get_event_reader::<AssetEvent<Mesh>>();
// TODO: allow pipelines to specialize on vertex_buffer_descriptor and index_format
let vertex_buffer_descriptor = Vertex::get_vertex_buffer_descriptor().unwrap();
vertex_buffer_descriptors.set(vertex_buffer_descriptor.clone());

View file

@ -231,26 +231,15 @@ where
let staging_buffer_start = uniform_buffer_status.staging_buffer_offset
+ (uniform_buffer_status.queued_buffer_writes.len()
* uniform_buffer_status.item_size);
if let Some(uniform_bytes) =
uniforms.get_uniform_bytes_ref(&field_info.uniform_name)
let uniform_byte_len = uniforms.uniform_byte_len(&field_info.uniform_name);
if uniform_byte_len > 0
{
if size != uniform_bytes.len() {
panic!("The number of bytes produced for {} do not match the expected count. Actual: {}. Expected: {}.", field_info.uniform_name, uniform_bytes.len(), 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);
}
staging_buffer
[staging_buffer_start..(staging_buffer_start + uniform_bytes.len())]
.copy_from_slice(uniform_bytes);
} else if let Some(uniform_bytes) =
uniforms.get_uniform_bytes(field_info.uniform_name)
{
if size != uniform_bytes.len() {
panic!("The number of bytes produced for {} do not match the expected count. Actual: {}. Expected: {}.", field_info.uniform_name, uniform_bytes.len(), size);
}
staging_buffer
[staging_buffer_start..(staging_buffer_start + uniform_bytes.len())]
.copy_from_slice(&uniform_bytes);
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: {}",

View file

@ -191,6 +191,13 @@ fn reflect_binding(binding: &ReflectDescriptorBinding) -> BindingDescriptor {
multisampled: false,
},
),
ReflectDescriptorType::StorageBuffer => (
&binding.name,
BindType::Buffer {
dynamic: false,
readonly: true,
},
),
// TODO: detect comparison "true" case: https://github.com/gpuweb/gpuweb/issues/552
ReflectDescriptorType::Sampler => (&binding.name, BindType::Sampler { comparison: false }),
_ => panic!("unsupported bind type {:?}", binding.descriptor_type),

View file

@ -6,16 +6,16 @@ use crate::{
};
use bevy_asset::{Assets, Handle};
use bevy_core::bytes::GetBytes;
use bevy_core::bytes::Bytes;
use legion::prelude::*;
pub trait AsUniforms: Send + Sync + 'static {
fn get_field_infos() -> &'static [FieldInfo];
fn get_uniform_bytes(&self, name: &str) -> Option<Vec<u8>>;
fn write_uniform_bytes(&self, name: &str, buffer: &mut [u8]);
fn uniform_byte_len(&self, name: &str) -> usize;
fn get_uniform_texture(&self, name: &str) -> Option<Handle<Texture>>;
fn get_shader_defs(&self) -> Option<Vec<String>>;
fn get_field_bind_type(&self, name: &str) -> Option<FieldBindType>;
fn get_uniform_bytes_ref(&self, name: &str) -> Option<&[u8]>;
fn get_vertex_buffer_descriptor() -> Option<&'static VertexBufferDescriptor>;
}
@ -112,12 +112,12 @@ impl AsFieldBindType for Handle<Texture> {
impl<T> AsFieldBindType for T
where
T: GetBytes,
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.get_bytes_ref().unwrap().len(),
size: self.byte_len(),
})
}
}
@ -130,7 +130,7 @@ pub trait GetTexture {
impl<T> GetTexture for T
where
T: GetBytes,
T: Bytes,
{
default fn get_texture(&self) -> Option<Handle<Texture>> {
None

View file

@ -4,7 +4,7 @@ use crate::{
texture::Texture,
};
use bevy_asset::Handle;
use bevy_core::bytes::GetBytes;
use bevy_core::bytes::Bytes;
use once_cell::sync::Lazy;
static LOCAL_TO_WORLD_FIELD_INFOS: &[FieldInfo] = &[FieldInfo {
@ -53,13 +53,6 @@ impl AsUniforms for bevy_transform::prelude::LocalToWorld {
LOCAL_TO_WORLD_FIELD_INFOS
}
fn get_uniform_bytes(&self, name: &str) -> Option<Vec<u8>> {
match name {
"Object" => Some(self.value.get_bytes()),
_ => None,
}
}
fn get_shader_defs(&self) -> Option<Vec<String>> {
None
}
@ -73,14 +66,19 @@ impl AsUniforms for bevy_transform::prelude::LocalToWorld {
None
}
fn get_uniform_bytes_ref(&self, name: &str) -> Option<&[u8]> {
match name {
"Object" => self.value.get_bytes_ref(),
_ => None,
}
}
fn get_vertex_buffer_descriptor() -> Option<&'static VertexBufferDescriptor> {
Some(&VERTEX_BUFFER_DESCRIPTOR)
}
fn write_uniform_bytes(&self, name: &str, buffer: &mut [u8]) {
match name {
"Object" => self.value.write_bytes(buffer),
_ => {}
}
}
fn uniform_byte_len(&self, name: &str) -> usize {
match name {
"Object" => self.value.byte_len(),
_ => 0,
}
}
}

View file

@ -1,9 +1,8 @@
use zerocopy::{AsBytes, FromBytes};
use zerocopy::AsBytes;
use bevy_derive::Uniforms;
#[repr(C)]
#[derive(Clone, Copy, AsBytes, FromBytes, Uniforms)]
#[derive(Clone, Copy, AsBytes, Uniforms)]
#[module(bevy_render = "crate")]
pub struct Vertex {
#[uniform(vertex)]

View file

@ -13,6 +13,6 @@ bevy_asset = { path = "../bevy_asset" }
bevy_type_registry = { path = "../bevy_type_registry" }
bevy_derive = { path = "../bevy_derive" }
bevy_render = { path = "../bevy_render" }
bevy_transform = { path = "../bevy_transform" }
glam = { path = "../bevy_glam" }
legion = { path = "../bevy_legion", features = ["serialize"] }
zerocopy = "0.3.0"
legion = { path = "../bevy_legion", features = ["serialize"] }

View file

@ -10,7 +10,7 @@ pub use wgpu_renderer::*;
pub use wgpu_resources::*;
use bevy_app::{AppBuilder, AppPlugin, Events};
use bevy_render::{renderer::RenderResources, RENDER_STAGE};
use bevy_render::{renderer::RenderResources};
use bevy_window::{WindowCreated, WindowResized};
use legion::prelude::*;
use renderer::WgpuRenderResourceContext;
@ -21,7 +21,7 @@ pub struct WgpuPlugin;
impl AppPlugin for WgpuPlugin {
fn build(&self, app: &mut AppBuilder) {
let render_system = wgpu_render_system(app.resources_mut());
app.add_system_to_stage(RENDER_STAGE, render_system);
app.add_system_to_stage(bevy_render::stage::RENDER, render_system);
}
}