From 394b7ce9405543f1823d0acbc416a273f7314d30 Mon Sep 17 00:00:00 2001 From: Carter Anderson Date: Sat, 11 Apr 2020 18:40:30 -0700 Subject: [PATCH] RenderContext, RenderResourceContext and wgpu implementations --- .../src/render_resource/render_resource.rs | 6 +- .../camera2d_resource_provider.rs | 6 +- .../camera_resource_provider.rs | 6 +- .../frame_texture_resource_provider.rs | 5 +- .../light_resource_provider.rs | 11 +- .../mesh_resource_provider.rs | 19 +- .../uniform_resource_provider.rs | 197 ++++++++--- bevy_render/src/renderer.rs | 6 +- bevy_render/src/renderer_2/mod.rs | 4 +- bevy_render/src/renderer_2/render_context.rs | 35 +- .../src/renderer_2/render_resource_context.rs | 37 ++ bevy_wgpu/src/renderer_2/mod.rs | 6 +- .../src/renderer_2/wgpu_render_context.rs | 191 ++++------- .../wgpu_render_resource_context.rs | 133 ++++++++ ...u_transactional_render_resource_context.rs | 162 +++++++++ bevy_wgpu/src/wgpu_renderer.rs | 323 ++++++++++++------ bevy_wgpu/src/wgpu_resources.rs | 49 ++- examples/scene.rs | 13 +- 18 files changed, 850 insertions(+), 359 deletions(-) create mode 100644 bevy_render/src/renderer_2/render_resource_context.rs create mode 100644 bevy_wgpu/src/renderer_2/wgpu_render_resource_context.rs create mode 100644 bevy_wgpu/src/renderer_2/wgpu_transactional_render_resource_context.rs diff --git a/bevy_render/src/render_resource/render_resource.rs b/bevy_render/src/render_resource/render_resource.rs index d31da88e20..d050526446 100644 --- a/bevy_render/src/render_resource/render_resource.rs +++ b/bevy_render/src/render_resource/render_resource.rs @@ -16,15 +16,15 @@ impl RenderResource { // TODO: consider scoping breaking these mappings up by type: Texture, Sampler, etc // the overlap could cause accidents. #[derive(Default)] -pub struct RenderResources { +pub struct AssetResources { pub texture_to_resource: HashMap, RenderResource>, pub texture_to_sampler_resource: HashMap, RenderResource>, pub mesh_to_vertices_resource: HashMap, RenderResource>, pub mesh_to_indices_resource: HashMap, RenderResource>, } -impl RenderResources { - pub fn consume(&mut self, render_resources: RenderResources) { +impl AssetResources { + pub fn consume(&mut self, render_resources: AssetResources) { // TODO: this is brittle. consider a single change-stream-based approach instead? self.texture_to_resource.extend(render_resources.texture_to_resource); self.texture_to_sampler_resource.extend(render_resources.texture_to_sampler_resource); diff --git a/bevy_render/src/render_resource/resource_providers/camera2d_resource_provider.rs b/bevy_render/src/render_resource/resource_providers/camera2d_resource_provider.rs index a8ccba20af..2e35c8ecbc 100644 --- a/bevy_render/src/render_resource/resource_providers/camera2d_resource_provider.rs +++ b/bevy_render/src/render_resource/resource_providers/camera2d_resource_provider.rs @@ -48,10 +48,10 @@ impl Camera2dResourceProvider { let camera_matrix: [[f32; 4]; 4] = camera.view_matrix.to_cols_array_2d(); if let Some(old_tmp_buffer) = self.tmp_buffer { - render_context.remove_buffer(old_tmp_buffer); + render_context.resources_mut().remove_buffer(old_tmp_buffer); } - self.tmp_buffer = Some(render_context.create_buffer_mapped( + self.tmp_buffer = Some(render_context.resources_mut().create_buffer_mapped( BufferInfo { size: matrix_size, buffer_usage: BufferUsage::COPY_SRC, @@ -81,7 +81,7 @@ impl ResourceProvider for Camera2dResourceProvider { _world: &mut World, resources: &Resources, ) { - let buffer = render_context.create_buffer(BufferInfo { + let buffer = render_context.resources_mut().create_buffer(BufferInfo { size: std::mem::size_of::<[[f32; 4]; 4]>(), buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM, ..Default::default() diff --git a/bevy_render/src/render_resource/resource_providers/camera_resource_provider.rs b/bevy_render/src/render_resource/resource_providers/camera_resource_provider.rs index 16a2b19aef..47e7556ef8 100644 --- a/bevy_render/src/render_resource/resource_providers/camera_resource_provider.rs +++ b/bevy_render/src/render_resource/resource_providers/camera_resource_provider.rs @@ -45,10 +45,10 @@ impl CameraResourceProvider { (camera.view_matrix * local_to_world.0).to_cols_array_2d(); if let Some(old_tmp_buffer) = self.tmp_buffer { - render_context.remove_buffer(old_tmp_buffer); + render_context.resources_mut().remove_buffer(old_tmp_buffer); } - self.tmp_buffer = Some(render_context.create_buffer_mapped( + self.tmp_buffer = Some(render_context.resources_mut().create_buffer_mapped( BufferInfo { size: matrix_size, buffer_usage: BufferUsage::COPY_SRC, @@ -78,7 +78,7 @@ impl ResourceProvider for CameraResourceProvider { _world: &mut World, resources: &Resources, ) { - let buffer = render_context.create_buffer(BufferInfo { + let buffer = render_context.resources_mut().create_buffer(BufferInfo { size: std::mem::size_of::<[[f32; 4]; 4]>(), buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM, ..Default::default() diff --git a/bevy_render/src/render_resource/resource_providers/frame_texture_resource_provider.rs b/bevy_render/src/render_resource/resource_providers/frame_texture_resource_provider.rs index bc177f1e17..d7a295fe2c 100644 --- a/bevy_render/src/render_resource/resource_providers/frame_texture_resource_provider.rs +++ b/bevy_render/src/render_resource/resource_providers/frame_texture_resource_provider.rs @@ -34,11 +34,12 @@ impl FrameTextureResourceProvider { let mut render_resource_assignments = resources.get_mut::().unwrap(); + let render_resources = render_context.resources_mut(); if let Some(old_resource) = render_resource_assignments.get(&self.name) { - render_context.remove_texture(old_resource); + render_resources.remove_texture(old_resource); } - let texture_resource = render_context.create_texture(&self.descriptor); + let texture_resource = render_resources.create_texture(&self.descriptor); render_resource_assignments.set(&self.name, texture_resource); } } diff --git a/bevy_render/src/render_resource/resource_providers/light_resource_provider.rs b/bevy_render/src/render_resource/resource_providers/light_resource_provider.rs index 3a2cfdb1e1..03e99637a0 100644 --- a/bevy_render/src/render_resource/resource_providers/light_resource_provider.rs +++ b/bevy_render/src/render_resource/resource_providers/light_resource_provider.rs @@ -46,16 +46,17 @@ impl LightResourceProvider { let size = std::mem::size_of::(); let total_size = size * light_count; let light_count_size = std::mem::size_of::(); + let render_resources = render_context.resources_mut(); if let Some(old_tmp_light_buffer) = self.tmp_light_buffer { - render_context.remove_buffer(old_tmp_light_buffer); + render_resources.remove_buffer(old_tmp_light_buffer); } if let Some(old_tmp_count_buffer) = self.tmp_count_buffer { - render_context.remove_buffer(old_tmp_count_buffer); + render_resources.remove_buffer(old_tmp_count_buffer); } - self.tmp_light_buffer = Some(render_context.create_buffer_mapped( + self.tmp_light_buffer = Some(render_resources.create_buffer_mapped( BufferInfo { size: total_size, buffer_usage: BufferUsage::COPY_SRC, @@ -71,7 +72,7 @@ impl LightResourceProvider { } }, )); - self.tmp_count_buffer = Some(render_context.create_buffer_mapped( + self.tmp_count_buffer = Some(render_resources.create_buffer_mapped( BufferInfo { size: light_count_size, buffer_usage: BufferUsage::COPY_SRC, @@ -111,7 +112,7 @@ impl ResourceProvider for LightResourceProvider { let light_uniform_size = std::mem::size_of::() + self.max_lights * std::mem::size_of::(); - let buffer = render_context.create_buffer(BufferInfo { + let buffer = render_context.resources_mut().create_buffer(BufferInfo { size: light_uniform_size, buffer_usage: BufferUsage::UNIFORM | BufferUsage::COPY_SRC | BufferUsage::COPY_DST, ..Default::default() diff --git a/bevy_render/src/render_resource/resource_providers/mesh_resource_provider.rs b/bevy_render/src/render_resource/resource_providers/mesh_resource_provider.rs index 8c98496a53..b066db95a9 100644 --- a/bevy_render/src/render_resource/resource_providers/mesh_resource_provider.rs +++ b/bevy_render/src/render_resource/resource_providers/mesh_resource_provider.rs @@ -44,24 +44,25 @@ impl MeshResourceProvider { handle: Handle, render_resource_assignments: &mut RenderResourceAssignments, ) { - let (vertex_buffer, index_buffer) = if let Some(vertex_buffer) = render_context + let render_resources = render_context.resources_mut(); + let (vertex_buffer, index_buffer) = if let Some(vertex_buffer) = render_resources .get_mesh_vertices_resource(handle) { ( vertex_buffer, - render_context + render_resources .get_mesh_indices_resource(handle), ) } else { let mesh_asset = mesh_storage.get(&handle).unwrap(); - let vertex_buffer = render_context.create_buffer_with_data( + let vertex_buffer = render_resources.create_buffer_with_data( BufferInfo { buffer_usage: BufferUsage::VERTEX, ..Default::default() }, mesh_asset.vertices.as_bytes(), ); - let index_buffer = render_context.create_buffer_with_data( + let index_buffer = render_resources.create_buffer_with_data( BufferInfo { buffer_usage: BufferUsage::INDEX, ..Default::default() @@ -69,9 +70,9 @@ impl MeshResourceProvider { mesh_asset.indices.as_bytes(), ); - let render_resources = render_context.local_render_resources_mut(); - render_resources.set_mesh_vertices_resource(handle, vertex_buffer); - render_resources.set_mesh_indices_resource(handle, index_buffer); + let asset_resources = render_resources.asset_resources_mut(); + asset_resources.set_mesh_vertices_resource(handle, vertex_buffer); + asset_resources.set_mesh_indices_resource(handle, index_buffer); (vertex_buffer, Some(index_buffer)) }; @@ -90,7 +91,7 @@ impl ResourceProvider for MeshResourceProvider { vertex_buffer_descriptors.set(Vertex::get_vertex_buffer_descriptor().cloned().unwrap()); } - fn update(&mut self, _render_context: &mut dyn RenderContext, world: &mut World, resources: &Resources) { + fn update(&mut self, _render_context: &mut dyn RenderContext, _world: &mut World, _resources: &Resources) { } fn finish_update( @@ -99,7 +100,7 @@ impl ResourceProvider for MeshResourceProvider { _world: &mut World, resources: &Resources, ) { - let mut mesh_storage = resources.get::>().unwrap(); + let mesh_storage = resources.get::>().unwrap(); let mut asset_batchers = resources.get_mut::().unwrap(); // this scope is necessary because the Fetch pointer behaves weirdly diff --git a/bevy_render/src/render_resource/resource_providers/uniform_resource_provider.rs b/bevy_render/src/render_resource/resource_providers/uniform_resource_provider.rs index 5aff3c03dc..faddcd4bc9 100644 --- a/bevy_render/src/render_resource/resource_providers/uniform_resource_provider.rs +++ b/bevy_render/src/render_resource/resource_providers/uniform_resource_provider.rs @@ -2,11 +2,12 @@ use crate::{ pipeline::VertexBufferDescriptors, render_resource::{ AssetBatchers, BufferArrayInfo, BufferInfo, BufferUsage, RenderResource, - RenderResourceAssignments, ResourceInfo, ResourceProvider, RenderResourceAssignmentsId, + RenderResourceAssignments, RenderResourceAssignmentsId, ResourceInfo, ResourceProvider, }, + renderer_2::{RenderContext, RenderResourceContext}, shader::{AsUniforms, FieldBindType}, texture::{SamplerDescriptor, Texture, TextureDescriptor}, - Renderable, renderer_2::RenderContext, + Renderable, }; use bevy_asset::{AssetStorage, Handle}; use legion::{filter::*, prelude::*}; @@ -51,6 +52,7 @@ struct QueuedBufferWrite { offset: usize, } +// TODO: make these queries only update changed T components type UniformQuery = Query< (Read, Write), EntityFilterTuple< @@ -262,11 +264,10 @@ where } } - fn setup_uniform_resources( + fn setup_uniform_buffer_resources( &mut self, uniforms: &T, - render_context: &mut dyn RenderContext, - resources: &Resources, + render_resources: &mut dyn RenderResourceContext, render_resource_assignments: &mut RenderResourceAssignments, staging_buffer: &mut [u8], ) { @@ -282,10 +283,10 @@ where array_info: Some(ref array_info), is_dynamic: true, .. - })) = render_context.get_resource_info(buffer) + })) = render_resources.get_resource_info(buffer) { - let index = - uniform_buffer_status.get_or_assign_index(render_resource_assignments.id); + let index = uniform_buffer_status + .get_or_assign_index(render_resource_assignments.id); render_resource_assignments.set_indexed( &field_info.uniform_name, buffer, @@ -301,7 +302,7 @@ where { Some(render_resource) => render_resource, None => { - let resource = render_context.create_buffer(BufferInfo { + let resource = render_resources.create_buffer(BufferInfo { size, buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM, ..Default::default() @@ -351,16 +352,33 @@ where offset: target_offset, }); } + _ => {} + } + } + } + + fn setup_uniform_texture_resources( + &mut self, + uniforms: &T, + render_context: &mut dyn RenderContext, + resources: &Resources, + render_resource_assignments: &mut RenderResourceAssignments, + ) { + for field_info in T::get_field_infos().iter() { + let bind_type = uniforms.get_field_bind_type(&field_info.name); + match bind_type { Some(FieldBindType::Texture) => { let texture_handle = uniforms .get_uniform_texture(&field_info.texture_name) .unwrap(); let (texture_resource, sampler_resource) = match render_context + .resources() .get_texture_resource(texture_handle) { Some(texture_resource) => ( texture_resource, render_context + .resources() .get_texture_sampler_resource(texture_handle) .unwrap(), ), @@ -369,15 +387,17 @@ where let texture = storage.get(&texture_handle).unwrap(); let texture_descriptor: TextureDescriptor = texture.into(); - let texture_resource = - render_context.create_texture_with_data(&texture_descriptor, &texture.data); + let texture_resource = render_context + .create_texture_with_data(&texture_descriptor, &texture.data); + let render_resources = render_context.resources_mut(); let sampler_descriptor: SamplerDescriptor = texture.into(); - let sampler_resource = render_context.create_sampler(&sampler_descriptor); + let sampler_resource = + render_resources.create_sampler(&sampler_descriptor); - let render_resources = render_context.local_render_resources_mut(); - render_resources.set_texture_resource(texture_handle, texture_resource); - render_resources + let asset_resources = render_resources.asset_resources_mut(); + asset_resources.set_texture_resource(texture_handle, texture_resource); + asset_resources .set_texture_sampler_resource(texture_handle, sampler_resource); (texture_resource, sampler_resource) } @@ -386,16 +406,17 @@ where render_resource_assignments.set(field_info.texture_name, texture_resource); render_resource_assignments.set(field_info.sampler_name, sampler_resource); } - None => {} + _ => {} } } } - fn setup_uniforms_resources( + // TODO: the current WgpuRenderContext mapped-memory interface forced these to be separate, but thats inefficient / redundant + // try to merge setup_uniforms_buffer_resources and setup_uniforms_texture_resources if possible + fn setup_uniforms_buffer_resources( &mut self, world: &mut World, - resources: &Resources, - render_context: &mut dyn RenderContext, + render_resources: &mut dyn RenderResourceContext, staging_buffer: &mut [u8], ) { let query_finish = self.query_finish.take().unwrap(); @@ -410,12 +431,41 @@ where std::any::type_name::() ); } else { - self.setup_uniform_resources( + self.setup_uniform_buffer_resources( + &uniforms, + render_resources, + &mut renderable.render_resource_assignments, + staging_buffer, + ); + } + } + + self.query_finish = Some(query_finish); + } + + fn setup_uniforms_texture_resources( + &mut self, + world: &mut World, + resources: &Resources, + render_context: &mut dyn RenderContext, + ) { + let query_finish = self.query_finish.take().unwrap(); + for (uniforms, mut renderable) in query_finish.iter_mut(world) { + if !renderable.is_visible { + return; + } + + if renderable.is_instanced { + panic!( + "Cannot instance uniforms of type {0}. Only Handle<{0}> can be instanced.", + std::any::type_name::() + ); + } else { + self.setup_uniform_texture_resources( &uniforms, render_context, resources, &mut renderable.render_resource_assignments, - staging_buffer, ) } } @@ -423,11 +473,11 @@ where self.query_finish = Some(query_finish); } - fn setup_handles_resources( + fn setup_handles_buffer_resources( &mut self, world: &mut World, resources: &Resources, - render_context: &mut dyn RenderContext, + render_resources: &mut dyn RenderResourceContext, staging_buffer: &mut [u8], ) { let assets = resources.get::>(); @@ -441,12 +491,40 @@ where let uniforms = assets .get(&handle) .expect("Handle points to a non-existent resource"); - self.setup_uniform_resources( + self.setup_uniform_buffer_resources( + &uniforms, + render_resources, + &mut renderable.render_resource_assignments, + staging_buffer, + ); + } + + self.handle_query_finish = Some(handle_query_finish); + } + } + + fn setup_handles_texture_resources( + &mut self, + world: &mut World, + resources: &Resources, + render_context: &mut dyn RenderContext, + ) { + let assets = resources.get::>(); + if let Some(assets) = assets { + let handle_query_finish = self.handle_query_finish.take().unwrap(); + for (handle, mut renderable) in handle_query_finish.iter_mut(world) { + if !renderable.is_visible || renderable.is_instanced { + return; + } + + let uniforms = assets + .get(&handle) + .expect("Handle points to a non-existent resource"); + self.setup_uniform_texture_resources( &uniforms, render_context, resources, &mut renderable.render_resource_assignments, - staging_buffer, ) } @@ -476,12 +554,17 @@ where .unwrap(); if let Some(uniforms) = asset_storage.get(&handle) { - self.setup_uniform_resources( - uniforms, + self.setup_uniform_buffer_resources( + &uniforms, + render_context.resources_mut(), + &mut batch.render_resource_assignments, + staging_buffer, + ); + self.setup_uniform_texture_resources( + &uniforms, render_context, resources, &mut batch.render_resource_assignments, - staging_buffer, ); Self::update_shader_defs(&uniforms, &mut batch.render_resource_assignments); @@ -516,7 +599,7 @@ where if let Some(ResourceInfo::Buffer(BufferInfo { array_info: Some(array_info), .. - })) = render_context.get_resource_info(buffer) + })) = render_context.resources().get_resource_info(buffer) { if array_info.item_capacity < buffer_array_status.new_item_count { // over capacity. lets resize @@ -544,7 +627,7 @@ where let total_size = item_size * new_capacity; - let buffer = render_context.create_buffer(BufferInfo { + let buffer = render_context.resources_mut().create_buffer(BufferInfo { array_info: Some(BufferArrayInfo { item_capacity: new_capacity, item_size, @@ -634,7 +717,12 @@ where self.update(render_context, world, resources); } - fn update(&mut self, _render_context: &mut dyn RenderContext, world: &mut World, resources: &Resources) { + fn update( + &mut self, + _render_context: &mut dyn RenderContext, + world: &mut World, + resources: &Resources, + ) { self.reset_buffer_array_status_counts(); self.update_uniforms_info(world); self.update_uniform_handles_info(world, resources); @@ -650,27 +738,56 @@ where self.setup_buffer_arrays(render_context); let staging_buffer_size = self.update_staging_buffer_offsets(); + self.setup_uniforms_texture_resources( + world, + resources, + render_context, + ); + self.setup_handles_texture_resources( + world, + resources, + render_context, + ); + // self.setup_batched_texture_resources(world, resources, renderer, staging_buffer); if staging_buffer_size == 0 { let mut staging_buffer: [u8; 0] = []; - self.setup_uniforms_resources(world, resources, render_context, &mut staging_buffer); - self.setup_handles_resources(world, resources, render_context, &mut staging_buffer); - // self.setup_batched_resources(world, resources, renderer, &mut staging_buffer); + self.setup_uniforms_buffer_resources( + world, + render_context.resources_mut(), + &mut staging_buffer, + ); + self.setup_handles_buffer_resources( + world, + resources, + render_context.resources_mut(), + &mut staging_buffer, + ); + // self.setup_batched_buffer_resources(world, resources, renderer, &mut staging_buffer); } else { - let staging_buffer = render_context.create_buffer_mapped( + let staging_buffer = render_context.resources_mut().create_buffer_mapped( BufferInfo { buffer_usage: BufferUsage::COPY_SRC, size: staging_buffer_size, ..Default::default() }, - &mut |staging_buffer, renderer| { - self.setup_uniforms_resources(world, resources, renderer, staging_buffer); - self.setup_handles_resources(world, resources, renderer, staging_buffer); - // self.setup_batched_resources(world, resources, renderer, staging_buffer); + &mut |staging_buffer, render_resources| { + self.setup_uniforms_buffer_resources( + world, + render_resources, + staging_buffer, + ); + self.setup_handles_buffer_resources( + world, + resources, + render_resources, + staging_buffer, + ); + // self.setup_batched_buffer_resources(world, resources, renderer, staging_buffer); }, ); self.copy_staging_buffer_to_final_buffers(render_context, staging_buffer); - render_context.remove_buffer(staging_buffer); + render_context.resources_mut().remove_buffer(staging_buffer); } } } diff --git a/bevy_render/src/renderer.rs b/bevy_render/src/renderer.rs index 0c1fe9dd3d..ff826726f2 100644 --- a/bevy_render/src/renderer.rs +++ b/bevy_render/src/renderer.rs @@ -1,7 +1,7 @@ use crate::{ pipeline::PipelineDescriptor, render_resource::{ - BufferInfo, RenderResource, RenderResourceAssignments, RenderResources, ResourceInfo, + BufferInfo, RenderResource, RenderResourceAssignments, AssetResources, ResourceInfo, }, shader::Shader, texture::{SamplerDescriptor, TextureDescriptor}, @@ -38,8 +38,8 @@ pub trait Renderer { destination_offset: u64, size: u64, ); - fn get_render_resources(&self) -> &RenderResources; - fn get_render_resources_mut(&mut self) -> &mut RenderResources; + fn get_render_resources(&self) -> &AssetResources; + fn get_render_resources_mut(&mut self) -> &mut AssetResources; fn setup_render_pipeline( &mut self, pipeline_handle: Handle, diff --git a/bevy_render/src/renderer_2/mod.rs b/bevy_render/src/renderer_2/mod.rs index c757304f6e..851a3785d6 100644 --- a/bevy_render/src/renderer_2/mod.rs +++ b/bevy_render/src/renderer_2/mod.rs @@ -1,3 +1,5 @@ mod render_context; +mod render_resource_context; -pub use render_context::*; \ No newline at end of file +pub use render_context::*; +pub use render_resource_context::*; \ No newline at end of file diff --git a/bevy_render/src/renderer_2/render_context.rs b/bevy_render/src/renderer_2/render_context.rs index cffd003add..460976e818 100644 --- a/bevy_render/src/renderer_2/render_context.rs +++ b/bevy_render/src/renderer_2/render_context.rs @@ -1,35 +1,7 @@ -use crate::{ - render_resource::{ - BufferInfo, RenderResource, RenderResources, ResourceInfo, - }, - texture::{SamplerDescriptor, TextureDescriptor, Texture}, mesh::Mesh, -}; -use bevy_asset::Handle; +use crate::{render_resource::RenderResource, texture::TextureDescriptor}; +use super::RenderResourceContext; pub trait RenderContext { - fn create_sampler(&mut self, sampler_descriptor: &SamplerDescriptor) -> RenderResource; - fn create_texture( - &mut self, - texture_descriptor: &TextureDescriptor, - ) -> RenderResource; - fn create_buffer(&mut self, buffer_info: BufferInfo) -> RenderResource; - fn create_buffer_mapped( - &mut self, - buffer_info: BufferInfo, - setup_data: &mut dyn FnMut(&mut [u8], &mut dyn RenderContext), - ) -> RenderResource; - fn create_buffer_with_data(&mut self, buffer_info: BufferInfo, data: &[u8]) -> RenderResource; - fn remove_buffer(&mut self, resource: RenderResource); - fn remove_texture(&mut self, resource: RenderResource); - fn remove_sampler(&mut self, resource: RenderResource); - fn get_resource_info(&self, resource: RenderResource) -> Option<&ResourceInfo>; - fn get_local_resource_info(&self, resource: RenderResource) -> Option<&ResourceInfo>; - fn local_render_resources(&self) -> &RenderResources; - fn local_render_resources_mut(&mut self) -> &mut RenderResources; - fn get_texture_resource(&self, texture: Handle) -> Option; - fn get_texture_sampler_resource(&self, texture: Handle) -> Option; - fn get_mesh_vertices_resource(&self, mesh: Handle) -> Option; - fn get_mesh_indices_resource(&self, mesh: Handle) -> Option; // fn setup_render_pipeline( // &mut self, // pipeline_handle: Handle, @@ -42,6 +14,9 @@ pub trait RenderContext { // pipeline_descriptor: &PipelineDescriptor, // ); + fn resources(&self) -> &dyn RenderResourceContext; + fn resources_mut(&mut self) -> &mut dyn RenderResourceContext; + fn create_texture_with_data( &mut self, texture_descriptor: &TextureDescriptor, diff --git a/bevy_render/src/renderer_2/render_resource_context.rs b/bevy_render/src/renderer_2/render_resource_context.rs new file mode 100644 index 0000000000..cdcc61e3a3 --- /dev/null +++ b/bevy_render/src/renderer_2/render_resource_context.rs @@ -0,0 +1,37 @@ +use crate::{ + render_resource::{ + BufferInfo, RenderResource, AssetResources, ResourceInfo, + }, + texture::{SamplerDescriptor, TextureDescriptor, Texture}, mesh::Mesh, +}; +use bevy_asset::Handle; + +pub struct GlobalRenderResourceContext { + pub context: Box, +} + +// TODO: Rename to RenderResources after cleaning up AssetResources rename +pub trait RenderResourceContext { + fn create_sampler(&mut self, sampler_descriptor: &SamplerDescriptor) -> RenderResource; + fn create_texture( + &mut self, + texture_descriptor: &TextureDescriptor, + ) -> RenderResource; + fn create_buffer(&mut self, buffer_info: BufferInfo) -> RenderResource; + fn create_buffer_mapped( + &mut self, + buffer_info: BufferInfo, + setup_data: &mut dyn FnMut(&mut [u8], &mut dyn RenderResourceContext), + ) -> RenderResource; + fn create_buffer_with_data(&mut self, buffer_info: BufferInfo, data: &[u8]) -> RenderResource; + fn remove_buffer(&mut self, resource: RenderResource); + fn remove_texture(&mut self, resource: RenderResource); + fn remove_sampler(&mut self, resource: RenderResource); + fn get_resource_info(&self, resource: RenderResource) -> Option<&ResourceInfo>; + fn asset_resources(&self) -> &AssetResources; + fn asset_resources_mut(&mut self) -> &mut AssetResources; + fn get_texture_resource(&self, texture: Handle) -> Option; + fn get_texture_sampler_resource(&self, texture: Handle) -> Option; + fn get_mesh_vertices_resource(&self, mesh: Handle) -> Option; + fn get_mesh_indices_resource(&self, mesh: Handle) -> Option; +} diff --git a/bevy_wgpu/src/renderer_2/mod.rs b/bevy_wgpu/src/renderer_2/mod.rs index 04757d0794..63b80faffe 100644 --- a/bevy_wgpu/src/renderer_2/mod.rs +++ b/bevy_wgpu/src/renderer_2/mod.rs @@ -1,3 +1,7 @@ mod wgpu_render_context; +mod wgpu_render_resource_context; +mod wgpu_transactional_render_resource_context; -pub use wgpu_render_context::*; \ No newline at end of file +pub use wgpu_render_context::*; +pub use wgpu_render_resource_context::*; +pub use wgpu_transactional_render_resource_context::*; \ No newline at end of file diff --git a/bevy_wgpu/src/renderer_2/wgpu_render_context.rs b/bevy_wgpu/src/renderer_2/wgpu_render_context.rs index fbcbce78b2..16d1e25b67 100644 --- a/bevy_wgpu/src/renderer_2/wgpu_render_context.rs +++ b/bevy_wgpu/src/renderer_2/wgpu_render_context.rs @@ -1,12 +1,10 @@ -use crate::WgpuResources; - +use super::WgpuRenderResourceContextTrait; use bevy_render::{ - render_resource::{BufferInfo, RenderResource, RenderResources, ResourceInfo}, - renderer_2::RenderContext, - texture::{SamplerDescriptor, TextureDescriptor, Texture}, mesh::Mesh, + render_resource::RenderResource, + renderer_2::{RenderContext, RenderResourceContext}, + texture::TextureDescriptor, }; use std::sync::Arc; -use bevy_asset::Handle; #[derive(Default)] struct LazyCommandEncoder { @@ -31,149 +29,71 @@ impl LazyCommandEncoder { } } -pub struct WgpuRenderContext<'a> { +pub struct WgpuRenderContext +where + T: RenderResourceContext, +{ pub device: Arc, - local_wgpu_resources: WgpuResources, command_encoder: LazyCommandEncoder, - global_wgpu_resources: &'a WgpuResources, - removed_resources: Vec, + pub render_resources: T, } -impl<'a> WgpuRenderContext<'a> { - pub fn new(device: Arc, global_wgpu_resources: &'a WgpuResources) -> Self { +impl WgpuRenderContext +where + T: RenderResourceContext, +{ + pub fn new(device: Arc, resources: T) -> Self { WgpuRenderContext { device, - global_wgpu_resources: global_wgpu_resources, + render_resources: resources, command_encoder: LazyCommandEncoder::default(), - local_wgpu_resources: WgpuResources::default(), - removed_resources: Vec::new(), } } - pub fn finish(mut self) -> (Option, WgpuResources) { - (self.command_encoder.take().map(|encoder| encoder.finish()), self.local_wgpu_resources) + /// Consume this context, finalize the current CommandEncoder (if it exists), and take the current WgpuResources. + /// This is intended to be called from a worker thread right before synchronizing with the main thread. + pub fn finish(mut self) -> (Option, T) { + ( + self.command_encoder.take().map(|encoder| encoder.finish()), + self.render_resources, + ) } - fn get_buffer<'b>(render_resource: RenderResource, local_resources: &'b WgpuResources, global_resources: &'b WgpuResources) -> Option<&'b wgpu::Buffer> { - let buffer = local_resources.buffers.get(&render_resource); - if buffer.is_some() { - return buffer; - } - - global_resources.buffers.get(&render_resource) + /// Consume this context, finalize the current CommandEncoder (if it exists), and take the current WgpuResources. + /// This is intended to be called from a worker thread right before synchronizing with the main thread. + pub fn finish_encoder(&mut self) -> Option { + self.command_encoder.take().map(|encoder| encoder.finish()) } + + // fn get_buffer<'b>( + // render_resource: RenderResource, + // local_resources: &'b WgpuResources, + // global_resources: &'b WgpuResources, + // ) -> Option<&'b wgpu::Buffer> { + // let buffer = local_resources.buffers.get(&render_resource); + // if buffer.is_some() { + // return buffer; + // } + + // global_resources.buffers.get(&render_resource) + // } } -impl<'a> RenderContext for WgpuRenderContext<'a> { - fn create_sampler(&mut self, sampler_descriptor: &SamplerDescriptor) -> RenderResource { - self.local_wgpu_resources - .create_sampler(&self.device, sampler_descriptor) - } - fn create_texture(&mut self, texture_descriptor: &TextureDescriptor) -> RenderResource { - self.local_wgpu_resources - .create_texture(&self.device, texture_descriptor) - } - fn create_buffer(&mut self, buffer_info: BufferInfo) -> RenderResource { - self.local_wgpu_resources.create_buffer(&self.device, buffer_info) - } - - // TODO: clean this up - fn create_buffer_mapped( - &mut self, - buffer_info: BufferInfo, - setup_data: &mut dyn FnMut(&mut [u8], &mut dyn RenderContext), - ) -> RenderResource { - let buffer = WgpuResources::begin_create_buffer_mapped_render_context( - &buffer_info, - self, - setup_data, - ); - self.local_wgpu_resources.assign_buffer(buffer, buffer_info) - } - +impl RenderContext for WgpuRenderContext +where + T: RenderResourceContext + WgpuRenderResourceContextTrait, +{ fn create_texture_with_data( &mut self, texture_descriptor: &TextureDescriptor, bytes: &[u8], ) -> RenderResource { - self.local_wgpu_resources.create_texture_with_data( - &self.device, + self.render_resources.create_texture_with_data( self.command_encoder.get_or_create(&self.device), texture_descriptor, bytes, ) } - fn remove_buffer(&mut self, resource: RenderResource) { - self.local_wgpu_resources.remove_buffer(resource); - self.removed_resources.push(resource); - } - fn remove_texture(&mut self, resource: RenderResource) { - self.local_wgpu_resources.remove_texture(resource); - self.removed_resources.push(resource); - } - fn remove_sampler(&mut self, resource: RenderResource) { - self.local_wgpu_resources.remove_sampler(resource); - self.removed_resources.push(resource); - } - - // TODO: this pattern is redundant and a bit confusing. make this cleaner if you can - fn get_texture_resource(&self, texture: Handle) -> Option { - let local = self.local_wgpu_resources.render_resources.get_texture_resource(texture); - if local.is_some() { - return local; - } - - self.global_wgpu_resources.render_resources.get_texture_resource(texture) - } - - fn get_texture_sampler_resource(&self, texture: Handle) -> Option { - let local = self.local_wgpu_resources.render_resources.get_texture_sampler_resource(texture); - if local.is_some() { - return local; - } - - self.global_wgpu_resources.render_resources.get_texture_sampler_resource(texture) - } - - - fn get_mesh_vertices_resource(&self, mesh: Handle) -> Option { - let local = self.local_wgpu_resources.render_resources.get_mesh_vertices_resource(mesh); - if local.is_some() { - return local; - } - - self.global_wgpu_resources.render_resources.get_mesh_vertices_resource(mesh) - } - - fn get_mesh_indices_resource(&self, mesh: Handle) -> Option { - let local = self.local_wgpu_resources.render_resources.get_mesh_indices_resource(mesh); - if local.is_some() { - return local; - } - - self.global_wgpu_resources.render_resources.get_mesh_indices_resource(mesh) - } - - fn get_resource_info(&self, resource: RenderResource) -> Option<&ResourceInfo> { - let local_info = self.local_wgpu_resources.get_resource_info(resource); - if local_info.is_some() { - return local_info; - } - - self.global_wgpu_resources.get_resource_info(resource) - } - - - fn get_local_resource_info(&self, resource: RenderResource) -> Option<&ResourceInfo> { - self.local_wgpu_resources.resource_info.get(&resource) - } - - fn local_render_resources(&self) -> &RenderResources { - &self.local_wgpu_resources.render_resources - } - fn local_render_resources_mut(&mut self) -> &mut RenderResources { - &mut self.local_wgpu_resources.render_resources - } fn copy_buffer_to_buffer( &mut self, source_buffer: RenderResource, @@ -183,12 +103,23 @@ impl<'a> RenderContext for WgpuRenderContext<'a> { size: u64, ) { let command_encoder = self.command_encoder.get_or_create(&self.device); - let source_buffer = Self::get_buffer(source_buffer, &self.local_wgpu_resources, &self.global_wgpu_resources).unwrap(); - let destination_buffer = Self::get_buffer(destination_buffer, &self.local_wgpu_resources, &self.global_wgpu_resources).unwrap(); - command_encoder.copy_buffer_to_buffer(source_buffer, source_offset, destination_buffer, destination_offset, size); + let source = self.render_resources.get_buffer(source_buffer).unwrap(); + let destination = self + .render_resources + .get_buffer(destination_buffer) + .unwrap(); + command_encoder.copy_buffer_to_buffer( + source, + source_offset, + destination, + destination_offset, + size, + ); } - fn create_buffer_with_data(&mut self, buffer_info: BufferInfo, data: &[u8]) -> RenderResource { - self.local_wgpu_resources - .create_buffer_with_data(&self.device, buffer_info, data) + fn resources(&self) -> &dyn RenderResourceContext { + &self.render_resources + } + fn resources_mut(&mut self) -> &mut dyn RenderResourceContext { + &mut self.render_resources } } diff --git a/bevy_wgpu/src/renderer_2/wgpu_render_resource_context.rs b/bevy_wgpu/src/renderer_2/wgpu_render_resource_context.rs new file mode 100644 index 0000000000..a699fbb86c --- /dev/null +++ b/bevy_wgpu/src/renderer_2/wgpu_render_resource_context.rs @@ -0,0 +1,133 @@ +use crate::WgpuResources; + +use bevy_asset::Handle; +use bevy_render::{ + mesh::Mesh, + render_resource::{AssetResources, BufferInfo, RenderResource, ResourceInfo}, + renderer_2::RenderResourceContext, + texture::{SamplerDescriptor, Texture, TextureDescriptor}, +}; +use std::sync::Arc; + +pub struct WgpuRenderResourceContext { + pub device: Arc, + pub wgpu_resources: WgpuResources, +} + +// TODO: make this name not terrible +pub trait WgpuRenderResourceContextTrait { + fn get_buffer(&self, render_resource: RenderResource) -> Option<&wgpu::Buffer>; + fn create_texture_with_data( + &mut self, + command_encoder: &mut wgpu::CommandEncoder, + texture_descriptor: &TextureDescriptor, + bytes: &[u8], + ) -> RenderResource; +} + +impl WgpuRenderResourceContextTrait for WgpuRenderResourceContext { + fn get_buffer(&self, render_resource: RenderResource) -> Option<&wgpu::Buffer> { + self.wgpu_resources.buffers.get(&render_resource) + } + fn create_texture_with_data( + &mut self, + command_encoder: &mut wgpu::CommandEncoder, + texture_descriptor: &TextureDescriptor, + bytes: &[u8], + ) -> RenderResource { + self.wgpu_resources + .create_texture_with_data( + &self.device, + command_encoder, + texture_descriptor, + bytes, + ) + } +} + +impl WgpuRenderResourceContext { + pub fn new(device: Arc) -> Self { + WgpuRenderResourceContext { + device, + wgpu_resources: WgpuResources::default(), + } + } +} + +impl RenderResourceContext for WgpuRenderResourceContext { + fn create_sampler(&mut self, sampler_descriptor: &SamplerDescriptor) -> RenderResource { + self.wgpu_resources + .create_sampler(&self.device, sampler_descriptor) + } + fn create_texture(&mut self, texture_descriptor: &TextureDescriptor) -> RenderResource { + self.wgpu_resources + .create_texture(&self.device, texture_descriptor) + } + fn create_buffer(&mut self, buffer_info: BufferInfo) -> RenderResource { + self.wgpu_resources.create_buffer(&self.device, buffer_info) + } + + // TODO: clean this up + fn create_buffer_mapped( + &mut self, + buffer_info: BufferInfo, + setup_data: &mut dyn FnMut(&mut [u8], &mut dyn RenderResourceContext), + ) -> RenderResource { + let buffer = WgpuResources::begin_create_buffer_mapped_render_context( + &buffer_info, + self, + setup_data, + ); + self.wgpu_resources.assign_buffer(buffer, buffer_info) + } + + fn create_buffer_with_data(&mut self, buffer_info: BufferInfo, data: &[u8]) -> RenderResource { + self.wgpu_resources + .create_buffer_with_data(&self.device, buffer_info, data) + } + + fn remove_buffer(&mut self, resource: RenderResource) { + self.wgpu_resources.remove_buffer(resource); + } + fn remove_texture(&mut self, resource: RenderResource) { + self.wgpu_resources.remove_texture(resource); + } + fn remove_sampler(&mut self, resource: RenderResource) { + self.wgpu_resources.remove_sampler(resource); + } + + fn get_texture_resource(&self, texture: Handle) -> Option { + self.wgpu_resources + .asset_resources + .get_texture_resource(texture) + } + + fn get_texture_sampler_resource(&self, texture: Handle) -> Option { + self.wgpu_resources + .asset_resources + .get_texture_sampler_resource(texture) + } + + fn get_mesh_vertices_resource(&self, mesh: Handle) -> Option { + self.wgpu_resources + .asset_resources + .get_mesh_vertices_resource(mesh) + } + + fn get_mesh_indices_resource(&self, mesh: Handle) -> Option { + self.wgpu_resources + .asset_resources + .get_mesh_indices_resource(mesh) + } + + fn get_resource_info(&self, resource: RenderResource) -> Option<&ResourceInfo> { + self.wgpu_resources.get_resource_info(resource) + } + + fn asset_resources(&self) -> &AssetResources { + &self.wgpu_resources.asset_resources + } + fn asset_resources_mut(&mut self) -> &mut AssetResources { + &mut self.wgpu_resources.asset_resources + } +} diff --git a/bevy_wgpu/src/renderer_2/wgpu_transactional_render_resource_context.rs b/bevy_wgpu/src/renderer_2/wgpu_transactional_render_resource_context.rs new file mode 100644 index 0000000000..be1ddf2aea --- /dev/null +++ b/bevy_wgpu/src/renderer_2/wgpu_transactional_render_resource_context.rs @@ -0,0 +1,162 @@ +use crate::WgpuResources; + +use bevy_asset::Handle; +use bevy_render::{ + mesh::Mesh, + render_resource::{AssetResources, BufferInfo, RenderResource, ResourceInfo}, + renderer_2::RenderResourceContext, + texture::{SamplerDescriptor, Texture, TextureDescriptor}, +}; +use std::sync::Arc; +use super::WgpuRenderResourceContextTrait; + +pub struct WgpuTransactionalRenderResourceContext<'a> { + pub device: Arc, + pub local_resources: WgpuResources, + pub parent_resources: &'a WgpuResources, + removed_resources: Vec, +} + +impl<'a> WgpuRenderResourceContextTrait for WgpuTransactionalRenderResourceContext<'a> { + fn get_buffer(&self, render_resource: RenderResource) -> Option<&wgpu::Buffer> { + let local = self.local_resources.buffers.get(&render_resource); + if local.is_some() { + return local; + } + + self.parent_resources.buffers.get(&render_resource) + } + + fn create_texture_with_data( + &mut self, + command_encoder: &mut wgpu::CommandEncoder, + texture_descriptor: &TextureDescriptor, + bytes: &[u8], + ) -> RenderResource { + self.local_resources + .create_texture_with_data( + &self.device, + command_encoder, + texture_descriptor, + bytes, + ) + } +} + +impl<'a> WgpuTransactionalRenderResourceContext<'a> { + pub fn new(device: Arc, parent_resources: &'a WgpuResources) -> Self { + WgpuTransactionalRenderResourceContext { + device, + local_resources: WgpuResources::default(), + parent_resources, + removed_resources: Vec::new(), + } + } +} + +impl<'a> RenderResourceContext for WgpuTransactionalRenderResourceContext<'a> { + fn create_sampler(&mut self, sampler_descriptor: &SamplerDescriptor) -> RenderResource { + self.local_resources + .create_sampler(&self.device, sampler_descriptor) + } + fn create_texture(&mut self, texture_descriptor: &TextureDescriptor) -> RenderResource { + self.local_resources + .create_texture(&self.device, texture_descriptor) + } + fn create_buffer(&mut self, buffer_info: BufferInfo) -> RenderResource { + self.local_resources.create_buffer(&self.device, buffer_info) + } + + // TODO: clean this up + fn create_buffer_mapped( + &mut self, + buffer_info: BufferInfo, + setup_data: &mut dyn FnMut(&mut [u8], &mut dyn RenderResourceContext), + ) -> RenderResource { + let buffer = WgpuResources::begin_create_buffer_mapped_transactional_render_context( + &buffer_info, + self, + setup_data, + ); + self.local_resources.assign_buffer(buffer, buffer_info) + } + + fn create_buffer_with_data(&mut self, buffer_info: BufferInfo, data: &[u8]) -> RenderResource { + self.local_resources + .create_buffer_with_data(&self.device, buffer_info, data) + } + + fn remove_buffer(&mut self, resource: RenderResource) { + self.local_resources.remove_buffer(resource); + self.removed_resources.push(resource); + } + fn remove_texture(&mut self, resource: RenderResource) { + self.local_resources.remove_texture(resource); + self.removed_resources.push(resource); + } + fn remove_sampler(&mut self, resource: RenderResource) { + self.local_resources.remove_sampler(resource); + self.removed_resources.push(resource); + } + + fn get_texture_resource(&self, texture: Handle) -> Option { + let local = self.local_resources + .asset_resources + .get_texture_resource(texture); + if local.is_some() { + return local; + } + + self.parent_resources.asset_resources.get_texture_resource(texture) + } + + fn get_texture_sampler_resource(&self, texture: Handle) -> Option { + let local = self.local_resources + .asset_resources + .get_texture_sampler_resource(texture); + + if local.is_some() { + return local; + } + + self.parent_resources.asset_resources.get_texture_sampler_resource(texture) + } + + fn get_mesh_vertices_resource(&self, mesh: Handle) -> Option { + let local = self.local_resources + .asset_resources + .get_mesh_vertices_resource(mesh); + if local.is_some() { + return local; + } + + self.parent_resources.asset_resources.get_mesh_vertices_resource(mesh) + } + + fn get_mesh_indices_resource(&self, mesh: Handle) -> Option { + let local = self.local_resources + .asset_resources + .get_mesh_indices_resource(mesh); + if local.is_some() { + return local; + } + + self.parent_resources.asset_resources.get_mesh_indices_resource(mesh) + } + + fn get_resource_info(&self, resource: RenderResource) -> Option<&ResourceInfo> { + let local = self.local_resources.get_resource_info(resource); + if local.is_some() { + return local; + } + + self.parent_resources.get_resource_info(resource) + } + + fn asset_resources(&self) -> &AssetResources { + &self.local_resources.asset_resources + } + fn asset_resources_mut(&mut self) -> &mut AssetResources { + &mut self.local_resources.asset_resources + } +} diff --git a/bevy_wgpu/src/wgpu_renderer.rs b/bevy_wgpu/src/wgpu_renderer.rs index df20a86f58..c1467632bd 100644 --- a/bevy_wgpu/src/wgpu_renderer.rs +++ b/bevy_wgpu/src/wgpu_renderer.rs @@ -2,7 +2,7 @@ use super::{ wgpu_type_converter::{OwnedWgpuVertexBufferDescriptor, WgpuInto}, WgpuRenderPass, WgpuResources, }; -use crate::renderer_2::WgpuRenderContext; +use crate::renderer_2::{WgpuRenderContext, WgpuRenderResourceContext, WgpuTransactionalRenderResourceContext}; use bevy_app::{EventReader, Events}; use bevy_asset::{AssetStorage, Handle}; use bevy_render::{ @@ -13,7 +13,7 @@ use bevy_render::{ pipeline::{update_shader_assignments, PipelineCompiler, PipelineDescriptor}, render_graph::RenderGraph, render_resource::{ - resource_name, BufferInfo, RenderResource, RenderResourceAssignments, RenderResources, + resource_name, AssetResources, BufferInfo, RenderResource, RenderResourceAssignments, ResourceInfo, }, renderer::Renderer, @@ -29,11 +29,10 @@ use std::{ }; pub struct WgpuRenderer { - pub device: Arc, + pub global_context: WgpuRenderContext, pub queue: wgpu::Queue, pub encoder: Option, pub render_pipelines: HashMap, wgpu::RenderPipeline>, - pub wgpu_resources: WgpuResources, pub window_resized_event_reader: EventReader, pub window_created_event_reader: EventReader, pub intialized: bool, @@ -62,15 +61,17 @@ impl WgpuRenderer { limits: wgpu::Limits::default(), }) .await; - + let device = Arc::new(device); WgpuRenderer { - device: Arc::new(device), + global_context: WgpuRenderContext::new( + device.clone(), + WgpuRenderResourceContext::new(device), + ), queue, encoder: None, window_resized_event_reader, window_created_event_reader, intialized: false, - wgpu_resources: WgpuResources::default(), render_pipelines: HashMap::new(), } } @@ -214,7 +215,7 @@ impl WgpuRenderer { pub fn initialize_resource_providers( world: &mut World, resources: &mut Resources, - render_context: &mut WgpuRenderContext, + render_context: &mut WgpuRenderContext, ) { let mut render_graph = resources.get_mut::().unwrap(); for resource_provider in render_graph.resource_providers.iter_mut() { @@ -235,58 +236,74 @@ impl WgpuRenderer { let chunk_size = (render_graph.resource_providers.len() + thread_count - 1) / thread_count; // divide ints rounding remainder up let mut results = Vec::new(); // crossbeam_utils::thread::scope(|s| { - for resource_provider_chunk in render_graph.resource_providers.chunks_mut(chunk_size) { - let device = device.clone(); - // let sender = sender.clone(); - // s.spawn(|_| { - let mut render_context = WgpuRenderContext::new(device, global_wgpu_resources); - for resource_provider in resource_provider_chunk.iter_mut() { - resource_provider.update(&mut render_context, world, resources); - } - results.push(render_context.finish()); - // sender.send(render_context.finish()).unwrap(); - // }); + for resource_provider_chunk in render_graph.resource_providers.chunks_mut(chunk_size) { + let device = device.clone(); + let resource_device = device.clone(); + // let sender = sender.clone(); + // s.spawn(|_| { + // TODO: replace WgpuResources with Global+Local resources + let mut render_context = + WgpuRenderContext::new(device, WgpuTransactionalRenderResourceContext::new(resource_device, global_wgpu_resources)); + for resource_provider in resource_provider_chunk.iter_mut() { + resource_provider.update(&mut render_context, world, resources); } + results.push(render_context.finish()); + // sender.send(render_context.finish()).unwrap(); + // }); + } // }); let mut command_buffers = Vec::new(); - for (command_buffer, wgpu_resources) in results { - // for i in 0..thread_count { - // let (command_buffer, wgpu_resources) = receiver.recv().unwrap(); + let mut local_resources = Vec::new(); + for (command_buffer, render_resources) in results { + // for i in 0..thread_count { + // let (command_buffer, wgpu_resources) = receiver.recv().unwrap(); if let Some(command_buffer) = command_buffer { command_buffers.push(command_buffer); } - global_wgpu_resources.consume(wgpu_resources); + local_resources.push(render_resources.local_resources); // println!("got {}", i); } + for local_resource in local_resources { + global_wgpu_resources.consume(local_resource); + } + let mut results = Vec::new(); // crossbeam_utils::thread::scope(|s| { - for resource_provider_chunk in render_graph.resource_providers.chunks_mut(chunk_size) { - let device = device.clone(); - // let sender = sender.clone(); - // s.spawn(|_| { - let mut render_context = WgpuRenderContext::new(device, global_wgpu_resources); - for resource_provider in resource_provider_chunk.iter_mut() { - resource_provider.finish_update(&mut render_context, world, resources); - } - results.push(render_context.finish()); - // sender.send(render_context.finish()).unwrap(); - // }); + for resource_provider_chunk in render_graph.resource_providers.chunks_mut(chunk_size) { + // TODO: try to unify this Device usage + let device = device.clone(); + let resource_device = device.clone(); + // let sender = sender.clone(); + // s.spawn(|_| { + // TODO: replace WgpuResources with Global+Local resources + let mut render_context = + WgpuRenderContext::new(device, WgpuTransactionalRenderResourceContext::new(resource_device, global_wgpu_resources)); + for resource_provider in resource_provider_chunk.iter_mut() { + resource_provider.finish_update(&mut render_context, world, resources); } + results.push(render_context.finish()); + // sender.send(render_context.finish()).unwrap(); + // }); + } // }); - for (command_buffer, wgpu_resources) in results { - // for i in 0..thread_count { + let mut local_resources = Vec::new(); + for (command_buffer, render_resources) in results { + // for i in 0..thread_count { // let (command_buffer, wgpu_resources) = receiver.recv().unwrap(); if let Some(command_buffer) = command_buffer { command_buffers.push(command_buffer); } - global_wgpu_resources.consume(wgpu_resources); + local_resources.push(render_resources.local_resources); // println!("got {}", i); } + for local_resource in local_resources { + global_wgpu_resources.consume(local_resource); + } queue.submit(&command_buffers); } @@ -366,6 +383,8 @@ impl WgpuRenderer { let primary_swap_chain = primary_window_id.map(|primary_window_id| primary_window_id.to_string()); let swap_chain_outputs = self + .global_context + .render_resources .wgpu_resources .window_swap_chains .iter_mut() @@ -386,21 +405,19 @@ impl Renderer for WgpuRenderer { fn update(&mut self, world: &mut World, resources: &mut Resources) { Self::handle_window_created_events( resources, - &self.device, - &mut self.wgpu_resources, + &self.global_context.device, + &mut self.global_context.render_resources.wgpu_resources, &mut self.window_created_event_reader, ); Self::handle_window_resized_events( resources, - &self.device, - &mut self.wgpu_resources, + &self.global_context.device, + &mut self.global_context.render_resources.wgpu_resources, &mut self.window_resized_event_reader, ); if !self.intialized { - let mut render_context = WgpuRenderContext::new(self.device.clone(), &self.wgpu_resources); - Self::initialize_resource_providers(world, resources, &mut render_context); - let (buffer, wgpu_resources) = render_context.finish(); - self.wgpu_resources.consume(wgpu_resources); + Self::initialize_resource_providers(world, resources, &mut self.global_context); + let buffer = self.global_context.finish_encoder(); if let Some(buffer) = buffer { self.queue.submit(&[buffer]); } @@ -411,12 +428,13 @@ impl Renderer for WgpuRenderer { world, resources, &mut self.queue, - self.device.clone(), - &mut self.wgpu_resources, + self.global_context.device.clone(), + &mut self.global_context.render_resources.wgpu_resources, ); self.encoder = Some( - self.device + self.global_context + .device .create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None }), ); update_shader_assignments(world, resources, self); @@ -438,7 +456,7 @@ impl Renderer for WgpuRenderer { let global_render_resource_assignments = resources.get::().unwrap(); Self::create_render_pass( - &self.wgpu_resources, + &self.global_context.render_resources.wgpu_resources, pass_descriptor, &global_render_resource_assignments, &mut encoder, @@ -461,7 +479,10 @@ impl Renderer for WgpuRenderer { let mut wgpu_render_pass = WgpuRenderPass { render_pass: &mut render_pass, pipeline_descriptor, - wgpu_resources: &self.wgpu_resources, + wgpu_resources: &self + .global_context + .render_resources + .wgpu_resources, renderer: &self, bound_bind_groups: HashMap::default(), }; @@ -487,24 +508,40 @@ impl Renderer for WgpuRenderer { } fn create_buffer_with_data(&mut self, buffer_info: BufferInfo, data: &[u8]) -> RenderResource { - self.wgpu_resources - .create_buffer_with_data(&self.device, buffer_info, data) + self.global_context + .render_resources + .wgpu_resources + .create_buffer_with_data(&self.global_context.device, buffer_info, data) } fn create_buffer(&mut self, buffer_info: BufferInfo) -> RenderResource { - self.wgpu_resources.create_buffer(&self.device, buffer_info) + self.global_context + .render_resources + .wgpu_resources + .create_buffer(&self.global_context.device, buffer_info) } fn get_resource_info(&self, resource: RenderResource) -> Option<&ResourceInfo> { - self.wgpu_resources.resource_info.get(&resource) + self.global_context + .render_resources + .wgpu_resources + .resource_info + .get(&resource) } fn get_resource_info_mut(&mut self, resource: RenderResource) -> Option<&mut ResourceInfo> { - self.wgpu_resources.resource_info.get_mut(&resource) + self.global_context + .render_resources + .wgpu_resources + .resource_info + .get_mut(&resource) } fn remove_buffer(&mut self, resource: RenderResource) { - self.wgpu_resources.remove_buffer(resource); + self.global_context + .render_resources + .wgpu_resources + .remove_buffer(resource); } fn create_buffer_mapped( @@ -513,7 +550,10 @@ impl Renderer for WgpuRenderer { setup_data: &mut dyn FnMut(&mut [u8], &mut dyn Renderer), ) -> RenderResource { let buffer = WgpuResources::begin_create_buffer_mapped(&buffer_info, self, setup_data); - self.wgpu_resources.assign_buffer(buffer, buffer_info) + self.global_context + .render_resources + .wgpu_resources + .assign_buffer(buffer, buffer_info) } fn copy_buffer_to_buffer( @@ -524,19 +564,24 @@ impl Renderer for WgpuRenderer { destination_offset: u64, size: u64, ) { - self.wgpu_resources.copy_buffer_to_buffer( - self.encoder.as_mut().unwrap(), - source_buffer, - source_offset, - destination_buffer, - destination_offset, - size, - ); + self.global_context + .render_resources + .wgpu_resources + .copy_buffer_to_buffer( + self.encoder.as_mut().unwrap(), + source_buffer, + source_offset, + destination_buffer, + destination_offset, + size, + ); } fn create_sampler(&mut self, sampler_descriptor: &SamplerDescriptor) -> RenderResource { - self.wgpu_resources - .create_sampler(&self.device, sampler_descriptor) + self.global_context + .render_resources + .wgpu_resources + .create_sampler(&self.global_context.device, sampler_descriptor) } fn create_texture( @@ -545,32 +590,51 @@ impl Renderer for WgpuRenderer { bytes: Option<&[u8]>, ) -> RenderResource { if let Some(bytes) = bytes { - self.wgpu_resources.create_texture_with_data( - &self.device, - self.encoder.as_mut().unwrap(), - texture_descriptor, - bytes, - ) + self.global_context + .render_resources + .wgpu_resources + .create_texture_with_data( + &self.global_context.device, + self.encoder.as_mut().unwrap(), + texture_descriptor, + bytes, + ) } else { - self.wgpu_resources - .create_texture(&self.device, texture_descriptor) + self.global_context + .render_resources + .wgpu_resources + .create_texture(&self.global_context.device, texture_descriptor) } } fn remove_texture(&mut self, resource: RenderResource) { - self.wgpu_resources.remove_texture(resource); + self.global_context + .render_resources + .wgpu_resources + .remove_texture(resource); } fn remove_sampler(&mut self, resource: RenderResource) { - self.wgpu_resources.remove_sampler(resource); + self.global_context + .render_resources + .wgpu_resources + .remove_sampler(resource); } - fn get_render_resources(&self) -> &RenderResources { - &self.wgpu_resources.render_resources + fn get_render_resources(&self) -> &AssetResources { + &self + .global_context + .render_resources + .wgpu_resources + .asset_resources } - fn get_render_resources_mut(&mut self) -> &mut RenderResources { - &mut self.wgpu_resources.render_resources + fn get_render_resources_mut(&mut self) -> &mut AssetResources { + &mut self + .global_context + .render_resources + .wgpu_resources + .asset_resources } fn setup_bind_groups( @@ -584,14 +648,19 @@ impl Renderer for WgpuRenderer { render_resource_assignments.get_or_update_render_resource_set_id(bind_group) { if let None = self + .global_context + .render_resources .wgpu_resources .get_bind_group(bind_group.id, render_resource_set_id) { - self.wgpu_resources.create_bind_group( - &self.device, - bind_group, - render_resource_assignments, - ); + self.global_context + .render_resources + .wgpu_resources + .create_bind_group( + &self.global_context.device, + bind_group, + render_resource_assignments, + ); } else { log::trace!( "reusing RenderResourceSet {:?} for bind group {}", @@ -615,7 +684,13 @@ impl Renderer for WgpuRenderer { let layout = pipeline_descriptor.get_layout().unwrap(); for bind_group in layout.bind_groups.iter() { - if let None = self.wgpu_resources.bind_group_layouts.get(&bind_group.id) { + if let None = self + .global_context + .render_resources + .wgpu_resources + .bind_group_layouts + .get(&bind_group.id) + { let bind_group_layout_binding = bind_group .bindings .iter() @@ -625,14 +700,16 @@ impl Renderer for WgpuRenderer { ty: (&binding.bind_type).wgpu_into(), }) .collect::>(); - let wgpu_bind_group_layout = - self.device - .create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { - bindings: bind_group_layout_binding.as_slice(), - label: None, - }); + let wgpu_bind_group_layout = self.global_context.device.create_bind_group_layout( + &wgpu::BindGroupLayoutDescriptor { + bindings: bind_group_layout_binding.as_slice(), + label: None, + }, + ); - self.wgpu_resources + self.global_context + .render_resources + .wgpu_resources .bind_group_layouts .insert(bind_group.id, wgpu_bind_group_layout); } @@ -643,18 +720,21 @@ impl Renderer for WgpuRenderer { .bind_groups .iter() .map(|bind_group| { - self.wgpu_resources + self.global_context + .render_resources + .wgpu_resources .bind_group_layouts .get(&bind_group.id) .unwrap() }) .collect::>(); - let pipeline_layout = self - .device - .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - bind_group_layouts: bind_group_layouts.as_slice(), - }); + let pipeline_layout = + self.global_context + .device + .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { + bind_group_layouts: bind_group_layouts.as_slice(), + }); let owned_vertex_buffer_descriptors = layout .vertex_buffer_descriptors @@ -669,28 +749,44 @@ impl Renderer for WgpuRenderer { .collect::>(); if let None = self + .global_context + .render_resources .wgpu_resources .shader_modules .get(&pipeline_descriptor.shader_stages.vertex) { - self.wgpu_resources.create_shader_module( - &self.device, - pipeline_descriptor.shader_stages.vertex, - shader_storage, - ); + self.global_context + .render_resources + .wgpu_resources + .create_shader_module( + &self.global_context.device, + pipeline_descriptor.shader_stages.vertex, + shader_storage, + ); } if let Some(fragment_handle) = pipeline_descriptor.shader_stages.fragment { - if let None = self.wgpu_resources.shader_modules.get(&fragment_handle) { - self.wgpu_resources.create_shader_module( - &self.device, - fragment_handle, - shader_storage, - ); + if let None = self + .global_context + .render_resources + .wgpu_resources + .shader_modules + .get(&fragment_handle) + { + self.global_context + .render_resources + .wgpu_resources + .create_shader_module( + &self.global_context.device, + fragment_handle, + shader_storage, + ); } }; let vertex_shader_module = self + .global_context + .render_resources .wgpu_resources .shader_modules .get(&pipeline_descriptor.shader_stages.vertex) @@ -698,7 +794,9 @@ impl Renderer for WgpuRenderer { let fragment_shader_module = match pipeline_descriptor.shader_stages.fragment { Some(fragment_handle) => Some( - self.wgpu_resources + self.global_context + .render_resources + .wgpu_resources .shader_modules .get(&fragment_handle) .unwrap(), @@ -742,6 +840,7 @@ impl Renderer for WgpuRenderer { }; let render_pipeline = self + .global_context .device .create_render_pipeline(&mut render_pipeline_descriptor); self.render_pipelines diff --git a/bevy_wgpu/src/wgpu_resources.rs b/bevy_wgpu/src/wgpu_resources.rs index 8236460769..6be88a2a3a 100644 --- a/bevy_wgpu/src/wgpu_resources.rs +++ b/bevy_wgpu/src/wgpu_resources.rs @@ -1,14 +1,17 @@ use super::WgpuRenderer; -use crate::{renderer_2::WgpuRenderContext, wgpu_type_converter::WgpuInto}; +use crate::{ + renderer_2::{WgpuRenderResourceContext, WgpuTransactionalRenderResourceContext}, + wgpu_type_converter::WgpuInto, +}; use bevy_asset::{AssetStorage, Handle}; use bevy_render::{ pipeline::{BindGroupDescriptor, BindGroupDescriptorId, BindType}, render_resource::{ - BufferInfo, RenderResource, RenderResourceAssignments, RenderResourceSetId, - RenderResources, ResourceInfo, + AssetResources, BufferInfo, RenderResource, RenderResourceAssignments, RenderResourceSetId, + ResourceInfo, }, renderer::Renderer, - renderer_2::RenderContext, + renderer_2::RenderResourceContext, shader::Shader, texture::{SamplerDescriptor, TextureDescriptor}, }; @@ -23,7 +26,7 @@ pub struct WgpuBindGroupInfo { #[derive(Default)] pub struct WgpuResources { // TODO: remove this from WgpuResources. it doesn't need to be here - pub render_resources: RenderResources, + pub asset_resources: AssetResources, pub window_surfaces: HashMap, pub window_swap_chains: HashMap, pub buffers: HashMap, @@ -38,8 +41,7 @@ pub struct WgpuResources { impl WgpuResources { pub fn consume(&mut self, wgpu_resources: WgpuResources) { // TODO: this is brittle. consider a single change-stream-based approach instead? - self.render_resources - .consume(wgpu_resources.render_resources); + self.asset_resources.consume(wgpu_resources.asset_resources); self.window_surfaces.extend(wgpu_resources.window_surfaces); self.window_swap_chains .extend(wgpu_resources.window_swap_chains); @@ -234,7 +236,7 @@ impl WgpuResources { renderer: &mut WgpuRenderer, setup_data: &mut dyn FnMut(&mut [u8], &mut dyn Renderer), ) -> wgpu::Buffer { - let device = renderer.device.clone(); + let device = renderer.global_context.device.clone(); let mut mapped = device.create_buffer_mapped(&wgpu::BufferDescriptor { size: buffer_info.size as u64, usage: buffer_info.buffer_usage.wgpu_into(), @@ -247,16 +249,31 @@ impl WgpuResources { // TODO: clean this up pub fn begin_create_buffer_mapped_render_context( buffer_info: &BufferInfo, - render_context: &mut WgpuRenderContext, - setup_data: &mut dyn FnMut(&mut [u8], &mut dyn RenderContext), + render_resources: &mut WgpuRenderResourceContext, + setup_data: &mut dyn FnMut(&mut [u8], &mut dyn RenderResourceContext), ) -> wgpu::Buffer { - let device = render_context.device.clone(); + let device = render_resources.device.clone(); let mut mapped = device.create_buffer_mapped(&wgpu::BufferDescriptor { size: buffer_info.size as u64, usage: buffer_info.buffer_usage.wgpu_into(), label: None, }); - setup_data(&mut mapped.data, render_context); + setup_data(&mut mapped.data, render_resources); + mapped.finish() + } + + pub fn begin_create_buffer_mapped_transactional_render_context( + buffer_info: &BufferInfo, + render_resources: &mut WgpuTransactionalRenderResourceContext, + setup_data: &mut dyn FnMut(&mut [u8], &mut dyn RenderResourceContext), + ) -> wgpu::Buffer { + let device = render_resources.device.clone(); + let mut mapped = device.create_buffer_mapped(&wgpu::BufferDescriptor { + size: buffer_info.size as u64, + usage: buffer_info.buffer_usage.wgpu_into(), + label: None, + }); + setup_data(&mut mapped.data, render_resources); mapped.finish() } @@ -356,11 +373,11 @@ impl WgpuResources { self.resource_info.remove(&resource); } - pub fn get_render_resources(&self) -> &RenderResources { - &self.render_resources + pub fn get_render_resources(&self) -> &AssetResources { + &self.asset_resources } - pub fn get_render_resources_mut(&mut self) -> &mut RenderResources { - &mut self.render_resources + pub fn get_render_resources_mut(&mut self) -> &mut AssetResources { + &mut self.asset_resources } } diff --git a/examples/scene.rs b/examples/scene.rs index 069a32c8d6..935a308ae7 100644 --- a/examples/scene.rs +++ b/examples/scene.rs @@ -1,11 +1,15 @@ use bevy::prelude::*; fn main() { - App::build().add_default_plugins().setup(setup).run(); + App::build() + .add_default_plugins() + .setup(setup) + .run(); } /// set up a simple scene fn setup(world: &mut World, resources: &mut Resources) { + env_logger::init(); // create a cube and a plane mesh let mut mesh_storage = resources.get_mut::>().unwrap(); let cube_handle = mesh_storage.add(Mesh::load(MeshType::Cube)); @@ -40,6 +44,13 @@ fn setup(world: &mut World, resources: &mut Resources) { translation: Translation::new(0.0, 0.0, 1.0), ..Default::default() }) + // cube + .add_entity(MeshEntity { + mesh: cube_handle, + material: cube_material_handle, + translation: Translation::new(2.0, 0.0, 1.0), + ..Default::default() + }) // light .add_entity(LightEntity { translation: Translation::new(4.0, -4.0, 5.0),