From de2fb1fca2ad32fdafb0c1fec9a2d626b676faad Mon Sep 17 00:00:00 2001 From: Carter Anderson Date: Fri, 10 Apr 2020 01:39:38 -0700 Subject: [PATCH] use RenderContext in ResourceProviders. make RenderContext contain a read-only view of global resources. Merge RenderContext changes back into global resources. --- .../draw_targets/ui_draw_target.rs | 2 +- .../src/render_resource/render_resource.rs | 8 + .../src/render_resource/resource_info.rs | 26 ---- .../src/render_resource/resource_provider.rs | 8 +- .../camera2d_resource_provider.rs | 19 ++- .../camera_resource_provider.rs | 15 +- .../frame_texture_resource_provider.rs | 13 +- .../light_resource_provider.rs | 21 ++- .../mesh_resource_provider.rs | 25 ++- .../uniform_resource_provider.rs | 110 ++++++++----- bevy_render/src/renderer_2/render_context.rs | 15 +- .../src/renderer_2/wgpu_render_context.rs | 129 +++++++++++----- bevy_wgpu/src/wgpu_renderer.rs | 144 ++++++++++-------- bevy_wgpu/src/wgpu_resources.rs | 101 +++++++----- 14 files changed, 376 insertions(+), 260 deletions(-) diff --git a/bevy_render/src/draw_target/draw_targets/ui_draw_target.rs b/bevy_render/src/draw_target/draw_targets/ui_draw_target.rs index aaa09803d5..05067ee70d 100644 --- a/bevy_render/src/draw_target/draw_targets/ui_draw_target.rs +++ b/bevy_render/src/draw_target/draw_targets/ui_draw_target.rs @@ -44,7 +44,7 @@ impl DrawTarget for UiDrawTarget { .. })) = renderer.get_resource_info(ui_instances_buffer) { - Some(array_info.item_count) + Some(array_info.item_capacity) } else { None } diff --git a/bevy_render/src/render_resource/render_resource.rs b/bevy_render/src/render_resource/render_resource.rs index e29eb2910b..d31da88e20 100644 --- a/bevy_render/src/render_resource/render_resource.rs +++ b/bevy_render/src/render_resource/render_resource.rs @@ -24,6 +24,14 @@ pub struct RenderResources { } impl RenderResources { + pub fn consume(&mut self, render_resources: RenderResources) { + // 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); + self.mesh_to_vertices_resource.extend(render_resources.mesh_to_vertices_resource); + self.mesh_to_indices_resource.extend(render_resources.mesh_to_indices_resource); + } + pub fn set_texture_resource(&mut self, texture: Handle, resource: RenderResource) { self.texture_to_resource.insert(texture, resource); } diff --git a/bevy_render/src/render_resource/resource_info.rs b/bevy_render/src/render_resource/resource_info.rs index 34f97e078a..1a86a90ea2 100644 --- a/bevy_render/src/render_resource/resource_info.rs +++ b/bevy_render/src/render_resource/resource_info.rs @@ -1,35 +1,9 @@ -use super::RenderResourceAssignmentsId; use crate::render_resource::BufferUsage; -use std::collections::HashMap; #[derive(Default, Debug)] pub struct BufferArrayInfo { - pub item_count: usize, pub item_size: usize, pub item_capacity: usize, - pub indices: HashMap, - pub current_index: usize, -} - -impl BufferArrayInfo { - pub fn get_index(&self, id: RenderResourceAssignmentsId) -> Option { - self.indices.get(&id).map(|offset| *offset) - } - - pub fn get_or_assign_index(&mut self, id: RenderResourceAssignmentsId) -> usize { - if let Some(offset) = self.indices.get(&id) { - *offset - } else { - if self.current_index == self.item_capacity { - panic!("no empty slots available in array"); - } - - let index = self.current_index; - self.indices.insert(id, index); - self.current_index += 1; - index - } - } } #[derive(Debug)] diff --git a/bevy_render/src/render_resource/resource_provider.rs b/bevy_render/src/render_resource/resource_provider.rs index 8a43f2c45e..5a44a52866 100644 --- a/bevy_render/src/render_resource/resource_provider.rs +++ b/bevy_render/src/render_resource/resource_provider.rs @@ -1,19 +1,19 @@ -use crate::renderer::Renderer; +use crate::{renderer_2::RenderContext}; use legion::prelude::*; pub trait ResourceProvider { fn initialize( &mut self, - _renderer: &mut dyn Renderer, + _renderer: &mut dyn RenderContext, _world: &mut World, _resources: &Resources, ) { } - fn update(&mut self, _renderer: &mut dyn Renderer, _world: &mut World, _resources: &Resources) { + fn update(&mut self, _render_context: &mut dyn RenderContext, _world: &mut World, _resources: &Resources) { } fn finish_update( &mut self, - _renderer: &mut dyn Renderer, + _render_context: &mut dyn RenderContext, _world: &mut World, _resources: &Resources, ) { 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 60f78ffca6..282d07b64c 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 @@ -7,7 +7,7 @@ use crate::{ resource_name, BufferInfo, BufferUsage, RenderResource, RenderResourceAssignments, ResourceProvider, }, - renderer::Renderer, + renderer_2::RenderContext, }; use legion::prelude::*; @@ -32,11 +32,11 @@ impl Camera2dResourceProvider { impl ResourceProvider for Camera2dResourceProvider { fn initialize( &mut self, - renderer: &mut dyn Renderer, + render_context: &mut dyn RenderContext, _world: &mut World, resources: &Resources, ) { - let buffer = renderer.create_buffer(BufferInfo { + let buffer = render_context.create_buffer(BufferInfo { size: std::mem::size_of::<[[f32; 4]; 4]>(), buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM, ..Default::default() @@ -48,7 +48,12 @@ impl ResourceProvider for Camera2dResourceProvider { self.camera_buffer = Some(buffer); } - fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World, resources: &Resources) { + fn update( + &mut self, + render_context: &mut dyn RenderContext, + world: &mut World, + resources: &Resources, + ) { let window_resized_events = resources.get::>().unwrap(); let primary_window_resized_event = window_resized_events .iter(&mut self.window_resized_event_reader) @@ -67,10 +72,10 @@ impl ResourceProvider for Camera2dResourceProvider { let camera_matrix: [[f32; 4]; 4] = camera.view_matrix.to_cols_array_2d(); if let Some(old_tmp_buffer) = self.tmp_buffer { - renderer.remove_buffer(old_tmp_buffer); + render_context.remove_buffer(old_tmp_buffer); } - self.tmp_buffer = Some(renderer.create_buffer_mapped( + self.tmp_buffer = Some(render_context.create_buffer_mapped( BufferInfo { size: matrix_size, buffer_usage: BufferUsage::COPY_SRC, @@ -81,7 +86,7 @@ impl ResourceProvider for Camera2dResourceProvider { }, )); - renderer.copy_buffer_to_buffer( + render_context.copy_buffer_to_buffer( self.tmp_buffer.unwrap(), 0, self.camera_buffer.unwrap(), 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 2a3cf990f2..9e9abfec35 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 @@ -5,8 +5,7 @@ use crate::{ resource_name, BufferInfo, BufferUsage, RenderResource, RenderResourceAssignments, ResourceProvider, }, - renderer::Renderer, - ActiveCamera, Camera, + ActiveCamera, Camera, renderer_2::RenderContext, }; use bevy_app::{EventReader, Events}; @@ -33,11 +32,11 @@ impl CameraResourceProvider { impl ResourceProvider for CameraResourceProvider { fn initialize( &mut self, - renderer: &mut dyn Renderer, + render_context: &mut dyn RenderContext, _world: &mut World, resources: &Resources, ) { - let buffer = renderer.create_buffer(BufferInfo { + let buffer = render_context.create_buffer(BufferInfo { size: std::mem::size_of::<[[f32; 4]; 4]>(), buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM, ..Default::default() @@ -49,7 +48,7 @@ impl ResourceProvider for CameraResourceProvider { self.camera_buffer = Some(buffer); } - fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World, resources: &Resources) { + fn update(&mut self, render_context: &mut dyn RenderContext, world: &mut World, resources: &Resources) { let window_resized_events = resources.get::>().unwrap(); let primary_window_resized_event = window_resized_events .iter(&mut self.window_resized_event_reader) @@ -69,10 +68,10 @@ impl ResourceProvider for CameraResourceProvider { (camera.view_matrix * local_to_world.0).to_cols_array_2d(); if let Some(old_tmp_buffer) = self.tmp_buffer { - renderer.remove_buffer(old_tmp_buffer); + render_context.remove_buffer(old_tmp_buffer); } - self.tmp_buffer = Some(renderer.create_buffer_mapped( + self.tmp_buffer = Some(render_context.create_buffer_mapped( BufferInfo { size: matrix_size, buffer_usage: BufferUsage::COPY_SRC, @@ -83,7 +82,7 @@ impl ResourceProvider for CameraResourceProvider { }, )); - renderer.copy_buffer_to_buffer( + render_context.copy_buffer_to_buffer( self.tmp_buffer.unwrap(), 0, self.camera_buffer.unwrap(), 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 71863b45b5..bc177f1e17 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 @@ -1,7 +1,6 @@ use crate::{ render_resource::{RenderResourceAssignments, ResourceProvider}, - renderer::Renderer, - texture::TextureDescriptor, + texture::TextureDescriptor, renderer_2::RenderContext, }; use bevy_window::Windows; use legion::prelude::*; @@ -23,7 +22,7 @@ impl FrameTextureResourceProvider { } } - pub fn update(&mut self, renderer: &mut dyn Renderer, resources: &Resources) { + pub fn update(&mut self, render_context: &mut dyn RenderContext, resources: &Resources) { let windows = resources.get::().unwrap(); let window = windows.get_primary().unwrap(); @@ -36,17 +35,17 @@ impl FrameTextureResourceProvider { let mut render_resource_assignments = resources.get_mut::().unwrap(); if let Some(old_resource) = render_resource_assignments.get(&self.name) { - renderer.remove_texture(old_resource); + render_context.remove_texture(old_resource); } - let texture_resource = renderer.create_texture(&self.descriptor, None); + let texture_resource = render_context.create_texture(&self.descriptor); render_resource_assignments.set(&self.name, texture_resource); } } } impl ResourceProvider for FrameTextureResourceProvider { - fn update(&mut self, renderer: &mut dyn Renderer, _world: &mut World, resources: &Resources) { - self.update(renderer, resources) + fn update(&mut self, render_context: &mut dyn RenderContext, _world: &mut World, resources: &Resources) { + self.update(render_context, resources) } } 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 0acab6ae88..2d5304db1a 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 @@ -3,8 +3,7 @@ use crate::{ resource_name, BufferInfo, BufferUsage, RenderResource, RenderResourceAssignments, ResourceProvider, }, - renderer::Renderer, - Light, LightRaw, + Light, LightRaw, renderer_2::RenderContext, }; use bevy_transform::prelude::{LocalToWorld, Translation}; use legion::prelude::*; @@ -39,14 +38,14 @@ impl LightResourceProvider { impl ResourceProvider for LightResourceProvider { fn initialize( &mut self, - renderer: &mut dyn Renderer, + render_context: &mut dyn RenderContext, _world: &mut World, resources: &Resources, ) { let light_uniform_size = std::mem::size_of::() + self.max_lights * std::mem::size_of::(); - let buffer = renderer.create_buffer(BufferInfo { + let buffer = render_context.create_buffer(BufferInfo { size: light_uniform_size, buffer_usage: BufferUsage::UNIFORM | BufferUsage::COPY_SRC | BufferUsage::COPY_DST, ..Default::default() @@ -57,7 +56,7 @@ impl ResourceProvider for LightResourceProvider { self.light_buffer = Some(buffer); } - fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World, _resources: &Resources) { + fn update(&mut self, render_context: &mut dyn RenderContext, world: &mut World, _resources: &Resources) { if self.lights_are_dirty { let light_query = <(Read, Read, Read)>::query(); let light_count = light_query.iter(world).count(); @@ -72,14 +71,14 @@ impl ResourceProvider for LightResourceProvider { let light_count_size = std::mem::size_of::(); if let Some(old_tmp_light_buffer) = self.tmp_light_buffer { - renderer.remove_buffer(old_tmp_light_buffer); + render_context.remove_buffer(old_tmp_light_buffer); } if let Some(old_tmp_count_buffer) = self.tmp_count_buffer { - renderer.remove_buffer(old_tmp_count_buffer); + render_context.remove_buffer(old_tmp_count_buffer); } - self.tmp_light_buffer = Some(renderer.create_buffer_mapped( + self.tmp_light_buffer = Some(render_context.create_buffer_mapped( BufferInfo { size: total_size, buffer_usage: BufferUsage::COPY_SRC, @@ -95,7 +94,7 @@ impl ResourceProvider for LightResourceProvider { } }, )); - self.tmp_count_buffer = Some(renderer.create_buffer_mapped( + self.tmp_count_buffer = Some(render_context.create_buffer_mapped( BufferInfo { size: light_count_size, buffer_usage: BufferUsage::COPY_SRC, @@ -106,7 +105,7 @@ impl ResourceProvider for LightResourceProvider { }, )); - renderer.copy_buffer_to_buffer( + render_context.copy_buffer_to_buffer( self.tmp_count_buffer.unwrap(), 0, self.light_buffer.unwrap(), @@ -114,7 +113,7 @@ impl ResourceProvider for LightResourceProvider { light_count_size as u64, ); - renderer.copy_buffer_to_buffer( + render_context.copy_buffer_to_buffer( self.tmp_light_buffer.unwrap(), 0, self.light_buffer.unwrap(), 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 39ddd04036..5ba6525f17 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 @@ -4,9 +4,8 @@ use crate::{ render_resource::{ AssetBatchers, BufferInfo, BufferUsage, RenderResourceAssignments, ResourceProvider, }, - renderer::Renderer, shader::AsUniforms, - Renderable, Vertex, + Renderable, Vertex, renderer_2::RenderContext, }; use bevy_asset::{AssetStorage, Handle}; use legion::{filter::*, prelude::*}; @@ -40,31 +39,29 @@ impl MeshResourceProvider { } fn setup_mesh_resources( - renderer: &mut dyn Renderer, + render_context: &mut dyn RenderContext, mesh_storage: &mut AssetStorage, handle: Handle, render_resource_assignments: &mut RenderResourceAssignments, ) { - let (vertex_buffer, index_buffer) = if let Some(vertex_buffer) = renderer - .get_render_resources() + let (vertex_buffer, index_buffer) = if let Some(vertex_buffer) = render_context .get_mesh_vertices_resource(handle) { ( vertex_buffer, - renderer - .get_render_resources() + render_context .get_mesh_indices_resource(handle), ) } else { let mesh_asset = mesh_storage.get(&handle).unwrap(); - let vertex_buffer = renderer.create_buffer_with_data( + let vertex_buffer = render_context.create_buffer_with_data( BufferInfo { buffer_usage: BufferUsage::VERTEX, ..Default::default() }, mesh_asset.vertices.as_bytes(), ); - let index_buffer = renderer.create_buffer_with_data( + let index_buffer = render_context.create_buffer_with_data( BufferInfo { buffer_usage: BufferUsage::INDEX, ..Default::default() @@ -72,7 +69,7 @@ impl MeshResourceProvider { mesh_asset.indices.as_bytes(), ); - let render_resources = renderer.get_render_resources_mut(); + 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); (vertex_buffer, Some(index_buffer)) @@ -85,7 +82,7 @@ impl MeshResourceProvider { impl ResourceProvider for MeshResourceProvider { fn initialize( &mut self, - _renderer: &mut dyn Renderer, + _render_context: &mut dyn RenderContext, _world: &mut World, resources: &Resources, ) { @@ -93,7 +90,7 @@ impl ResourceProvider for MeshResourceProvider { vertex_buffer_descriptors.set(Vertex::get_vertex_buffer_descriptor().cloned().unwrap()); } - fn update(&mut self, _renderer: &mut dyn Renderer, world: &mut World, resources: &Resources) { + fn update(&mut self, _render_context: &mut dyn RenderContext, world: &mut World, resources: &Resources) { let mut asset_batchers = resources.get_mut::().unwrap(); for (entity, (mesh_handle, _renderable)) in self.mesh_query.iter_entities_mut(world) { asset_batchers.set_entity_handle(entity, *mesh_handle); @@ -102,7 +99,7 @@ impl ResourceProvider for MeshResourceProvider { fn finish_update( &mut self, - renderer: &mut dyn Renderer, + render_context: &mut dyn RenderContext, _world: &mut World, resources: &Resources, ) { @@ -116,7 +113,7 @@ impl ResourceProvider for MeshResourceProvider { let handle = batch.get_handle::().unwrap(); log::trace!("setup mesh for {:?}", batch.render_resource_assignments.id); Self::setup_mesh_resources( - renderer, + render_context, &mut mesh_storage, handle, &mut batch.render_resource_assignments, 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 abcb639b53..5aff3c03dc 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,16 +2,15 @@ use crate::{ pipeline::VertexBufferDescriptors, render_resource::{ AssetBatchers, BufferArrayInfo, BufferInfo, BufferUsage, RenderResource, - RenderResourceAssignments, ResourceInfo, ResourceProvider, + RenderResourceAssignments, ResourceInfo, ResourceProvider, RenderResourceAssignmentsId, }, - renderer::Renderer, shader::{AsUniforms, FieldBindType}, texture::{SamplerDescriptor, Texture, TextureDescriptor}, - Renderable, + Renderable, renderer_2::RenderContext, }; use bevy_asset::{AssetStorage, Handle}; use legion::{filter::*, prelude::*}; -use std::marker::PhantomData; +use std::{collections::HashMap, marker::PhantomData}; pub const BIND_BUFFER_ALIGNMENT: usize = 256; #[derive(Debug)] @@ -22,6 +21,28 @@ struct BufferArrayStatus { staging_buffer_offset: usize, queued_buffer_writes: Vec, buffer: Option, + + current_item_count: usize, + current_item_capacity: usize, + indices: HashMap, + current_index: usize, +} + +impl BufferArrayStatus { + pub fn get_or_assign_index(&mut self, id: RenderResourceAssignmentsId) -> usize { + if let Some(offset) = self.indices.get(&id) { + *offset + } else { + if self.current_index == self.current_item_capacity { + panic!("no empty slots available in array"); + } + + let index = self.current_index; + self.indices.insert(id, index); + self.current_index += 1; + index + } + } } #[derive(Debug)] @@ -173,6 +194,10 @@ where item_size: f(), staging_buffer_offset: 0, buffer: None, + current_index: 0, + current_item_capacity: 0, + current_item_count: 0, + indices: HashMap::new(), }) } } @@ -211,6 +236,10 @@ where item_size: size, staging_buffer_offset: 0, buffer: None, + current_index: 0, + current_item_count: 0, + current_item_capacity: 0, + indices: HashMap::new(), }, )) } @@ -236,7 +265,7 @@ where fn setup_uniform_resources( &mut self, uniforms: &T, - renderer: &mut dyn Renderer, + render_context: &mut dyn RenderContext, resources: &Resources, render_resource_assignments: &mut RenderResourceAssignments, staging_buffer: &mut [u8], @@ -250,13 +279,13 @@ where let (target_buffer, target_offset) = if self.use_dynamic_uniforms { let buffer = uniform_buffer_status.buffer.unwrap(); if let Some(ResourceInfo::Buffer(BufferInfo { - array_info: Some(ref mut array_info), + array_info: Some(ref array_info), is_dynamic: true, .. - })) = renderer.get_resource_info_mut(buffer) + })) = render_context.get_resource_info(buffer) { let index = - array_info.get_or_assign_index(render_resource_assignments.id); + uniform_buffer_status.get_or_assign_index(render_resource_assignments.id); render_resource_assignments.set_indexed( &field_info.uniform_name, buffer, @@ -272,7 +301,7 @@ where { Some(render_resource) => render_resource, None => { - let resource = renderer.create_buffer(BufferInfo { + let resource = render_context.create_buffer(BufferInfo { size, buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM, ..Default::default() @@ -326,14 +355,12 @@ where let texture_handle = uniforms .get_uniform_texture(&field_info.texture_name) .unwrap(); - let (texture_resource, sampler_resource) = match renderer - .get_render_resources() + let (texture_resource, sampler_resource) = match render_context .get_texture_resource(texture_handle) { Some(texture_resource) => ( texture_resource, - renderer - .get_render_resources() + render_context .get_texture_sampler_resource(texture_handle) .unwrap(), ), @@ -343,12 +370,12 @@ where let texture_descriptor: TextureDescriptor = texture.into(); let texture_resource = - renderer.create_texture(&texture_descriptor, Some(&texture.data)); + render_context.create_texture_with_data(&texture_descriptor, &texture.data); let sampler_descriptor: SamplerDescriptor = texture.into(); - let sampler_resource = renderer.create_sampler(&sampler_descriptor); + let sampler_resource = render_context.create_sampler(&sampler_descriptor); - let render_resources = renderer.get_render_resources_mut(); + let render_resources = render_context.local_render_resources_mut(); render_resources.set_texture_resource(texture_handle, texture_resource); render_resources .set_texture_sampler_resource(texture_handle, sampler_resource); @@ -368,7 +395,7 @@ where &mut self, world: &mut World, resources: &Resources, - renderer: &mut dyn Renderer, + render_context: &mut dyn RenderContext, staging_buffer: &mut [u8], ) { let query_finish = self.query_finish.take().unwrap(); @@ -385,7 +412,7 @@ where } else { self.setup_uniform_resources( &uniforms, - renderer, + render_context, resources, &mut renderable.render_resource_assignments, staging_buffer, @@ -400,7 +427,7 @@ where &mut self, world: &mut World, resources: &Resources, - renderer: &mut dyn Renderer, + render_context: &mut dyn RenderContext, staging_buffer: &mut [u8], ) { let assets = resources.get::>(); @@ -416,7 +443,7 @@ where .expect("Handle points to a non-existent resource"); self.setup_uniform_resources( &uniforms, - renderer, + render_context, resources, &mut renderable.render_resource_assignments, staging_buffer, @@ -432,7 +459,7 @@ where &mut self, _world: &mut World, resources: &Resources, - renderer: &mut dyn Renderer, + render_context: &mut dyn RenderContext, staging_buffer: &mut [u8], ) { // update batch resources. this needs to run in "finish_update" because batches aren't finalized across @@ -451,7 +478,7 @@ where if let Some(uniforms) = asset_storage.get(&handle) { self.setup_uniform_resources( uniforms, - renderer, + render_context, resources, &mut batch.render_resource_assignments, staging_buffer, @@ -463,11 +490,11 @@ where } } - fn setup_buffer_arrays(&mut self, renderer: &mut dyn Renderer) { + fn setup_buffer_arrays(&mut self, render_context: &mut dyn RenderContext) { for buffer_array_status in self.uniform_buffer_status.iter_mut() { if let Some((_name, buffer_array_status)) = buffer_array_status { if self.use_dynamic_uniforms { - Self::setup_buffer_array(buffer_array_status, renderer, true); + Self::setup_buffer_array(buffer_array_status, render_context, true); } buffer_array_status.queued_buffer_writes = @@ -476,20 +503,20 @@ where } if let Some(ref mut buffer_array_status) = self.instance_buffer_status { - Self::setup_buffer_array(buffer_array_status, renderer, false); + Self::setup_buffer_array(buffer_array_status, render_context, false); } } fn setup_buffer_array( buffer_array_status: &mut BufferArrayStatus, - renderer: &mut dyn Renderer, + render_context: &mut dyn RenderContext, align: bool, ) { let new_capacity = if let Some(buffer) = buffer_array_status.buffer { if let Some(ResourceInfo::Buffer(BufferInfo { array_info: Some(array_info), .. - })) = renderer.get_resource_info_mut(buffer) + })) = render_context.get_resource_info(buffer) { if array_info.item_capacity < buffer_array_status.new_item_count { // over capacity. lets resize @@ -517,10 +544,9 @@ where let total_size = item_size * new_capacity; - let buffer = renderer.create_buffer(BufferInfo { + let buffer = render_context.create_buffer(BufferInfo { array_info: Some(BufferArrayInfo { item_capacity: new_capacity, - item_count: buffer_array_status.new_item_count, item_size, ..Default::default() }), @@ -529,6 +555,8 @@ where is_dynamic: true, }); + buffer_array_status.current_item_capacity = new_capacity; + log::trace!( "creating buffer for uniform {}. size: {} item_capacity: {} item_size: {}", std::any::type_name::(), @@ -567,7 +595,7 @@ where fn copy_staging_buffer_to_final_buffers( &mut self, - renderer: &mut dyn Renderer, + render_context: &mut dyn RenderContext, staging_buffer: RenderResource, ) { for uniform_buffer_status in self.uniform_buffer_status.iter_mut() { @@ -578,7 +606,7 @@ where .drain(..) .enumerate() { - renderer.copy_buffer_to_buffer( + render_context.copy_buffer_to_buffer( staging_buffer, (start + (i * buffer_array_status.item_size)) as u64, queued_buffer_write.buffer, @@ -597,16 +625,16 @@ where { fn initialize( &mut self, - renderer: &mut dyn Renderer, + render_context: &mut dyn RenderContext, world: &mut World, resources: &Resources, ) { let mut vertex_buffer_descriptors = resources.get_mut::().unwrap(); self.initialize_vertex_buffer_descriptor(&mut vertex_buffer_descriptors); - self.update(renderer, world, resources); + self.update(render_context, world, resources); } - fn update(&mut self, _renderer: &mut dyn Renderer, 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); @@ -614,21 +642,21 @@ where fn finish_update( &mut self, - renderer: &mut dyn Renderer, + render_context: &mut dyn RenderContext, world: &mut World, resources: &Resources, ) { // TODO: when setting batch shader_defs, add INSTANCING - self.setup_buffer_arrays(renderer); + self.setup_buffer_arrays(render_context); let staging_buffer_size = self.update_staging_buffer_offsets(); if staging_buffer_size == 0 { let mut staging_buffer: [u8; 0] = []; - self.setup_uniforms_resources(world, resources, renderer, &mut staging_buffer); - self.setup_handles_resources(world, resources, renderer, &mut staging_buffer); + 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); } else { - let staging_buffer = renderer.create_buffer_mapped( + let staging_buffer = render_context.create_buffer_mapped( BufferInfo { buffer_usage: BufferUsage::COPY_SRC, size: staging_buffer_size, @@ -641,8 +669,8 @@ where }, ); - self.copy_staging_buffer_to_final_buffers(renderer, staging_buffer); - renderer.remove_buffer(staging_buffer); + self.copy_staging_buffer_to_final_buffers(render_context, staging_buffer); + render_context.remove_buffer(staging_buffer); } } } diff --git a/bevy_render/src/renderer_2/render_context.rs b/bevy_render/src/renderer_2/render_context.rs index 0cb3e34044..cffd003add 100644 --- a/bevy_render/src/renderer_2/render_context.rs +++ b/bevy_render/src/renderer_2/render_context.rs @@ -2,8 +2,9 @@ use crate::{ render_resource::{ BufferInfo, RenderResource, RenderResources, ResourceInfo, }, - texture::{SamplerDescriptor, TextureDescriptor}, + texture::{SamplerDescriptor, TextureDescriptor, Texture}, mesh::Mesh, }; +use bevy_asset::Handle; pub trait RenderContext { fn create_sampler(&mut self, sampler_descriptor: &SamplerDescriptor) -> RenderResource; @@ -22,9 +23,13 @@ pub trait RenderContext { 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_resource_info_mut(&mut self, resource: RenderResource) -> Option<&mut ResourceInfo>; - fn render_resources(&self) -> &RenderResources; - fn render_resources_mut(&mut self) -> &mut RenderResources; + 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, @@ -40,7 +45,7 @@ pub trait RenderContext { fn create_texture_with_data( &mut self, texture_descriptor: &TextureDescriptor, - bytes: Option<&[u8]>, + bytes: &[u8], ) -> RenderResource; fn copy_buffer_to_buffer( &mut self, diff --git a/bevy_wgpu/src/renderer_2/wgpu_render_context.rs b/bevy_wgpu/src/renderer_2/wgpu_render_context.rs index b70058c87e..fbcbce78b2 100644 --- a/bevy_wgpu/src/renderer_2/wgpu_render_context.rs +++ b/bevy_wgpu/src/renderer_2/wgpu_render_context.rs @@ -3,9 +3,10 @@ use crate::WgpuResources; use bevy_render::{ render_resource::{BufferInfo, RenderResource, RenderResources, ResourceInfo}, renderer_2::RenderContext, - texture::{SamplerDescriptor, TextureDescriptor}, + texture::{SamplerDescriptor, TextureDescriptor, Texture}, mesh::Mesh, }; use std::sync::Arc; +use bevy_asset::Handle; #[derive(Default)] struct LazyCommandEncoder { @@ -30,37 +31,50 @@ impl LazyCommandEncoder { } } -pub struct WgpuRenderContext { +pub struct WgpuRenderContext<'a> { pub device: Arc, + local_wgpu_resources: WgpuResources, command_encoder: LazyCommandEncoder, - wgpu_resources: WgpuResources, + global_wgpu_resources: &'a WgpuResources, + removed_resources: Vec, } -impl WgpuRenderContext { - pub fn new(device: Arc) -> Self { +impl<'a> WgpuRenderContext<'a> { + pub fn new(device: Arc, global_wgpu_resources: &'a WgpuResources) -> Self { WgpuRenderContext { device, + global_wgpu_resources: global_wgpu_resources, command_encoder: LazyCommandEncoder::default(), - wgpu_resources: WgpuResources::default(), + local_wgpu_resources: WgpuResources::default(), + removed_resources: Vec::new(), } } - pub fn finish(&mut self) -> Option { - self.command_encoder.take().map(|encoder| encoder.finish()) + pub fn finish(mut self) -> (Option, WgpuResources) { + (self.command_encoder.take().map(|encoder| encoder.finish()), self.local_wgpu_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) } } -impl RenderContext for WgpuRenderContext { +impl<'a> RenderContext for WgpuRenderContext<'a> { fn create_sampler(&mut self, sampler_descriptor: &SamplerDescriptor) -> RenderResource { - self.wgpu_resources + self.local_wgpu_resources .create_sampler(&self.device, sampler_descriptor) } fn create_texture(&mut self, texture_descriptor: &TextureDescriptor) -> RenderResource { - self.wgpu_resources + self.local_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) + self.local_wgpu_resources.create_buffer(&self.device, buffer_info) } // TODO: clean this up @@ -74,14 +88,15 @@ impl RenderContext for WgpuRenderContext { self, setup_data, ); - self.wgpu_resources.assign_buffer(buffer, buffer_info) + self.local_wgpu_resources.assign_buffer(buffer, buffer_info) } + fn create_texture_with_data( &mut self, texture_descriptor: &TextureDescriptor, - bytes: Option<&[u8]>, + bytes: &[u8], ) -> RenderResource { - self.wgpu_resources.create_texture_with_data( + self.local_wgpu_resources.create_texture_with_data( &self.device, self.command_encoder.get_or_create(&self.device), texture_descriptor, @@ -89,25 +104,75 @@ impl RenderContext for WgpuRenderContext { ) } fn remove_buffer(&mut self, resource: RenderResource) { - self.wgpu_resources.remove_buffer(resource); + self.local_wgpu_resources.remove_buffer(resource); + self.removed_resources.push(resource); } fn remove_texture(&mut self, resource: RenderResource) { - self.wgpu_resources.remove_texture(resource); + self.local_wgpu_resources.remove_texture(resource); + self.removed_resources.push(resource); } fn remove_sampler(&mut self, resource: RenderResource) { - self.wgpu_resources.remove_sampler(resource); + 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> { - self.wgpu_resources.resource_info.get(&resource) + 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_resource_info_mut(&mut self, resource: RenderResource) -> Option<&mut ResourceInfo> { - self.wgpu_resources.resource_info.get_mut(&resource) + + + fn get_local_resource_info(&self, resource: RenderResource) -> Option<&ResourceInfo> { + self.local_wgpu_resources.resource_info.get(&resource) } - fn render_resources(&self) -> &RenderResources { - &self.wgpu_resources.render_resources + + fn local_render_resources(&self) -> &RenderResources { + &self.local_wgpu_resources.render_resources } - fn render_resources_mut(&mut self) -> &mut RenderResources { - &mut self.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, @@ -117,17 +182,13 @@ impl RenderContext for WgpuRenderContext { destination_offset: u64, size: u64, ) { - self.wgpu_resources.copy_buffer_to_buffer( - self.command_encoder.get_or_create(&self.device), - source_buffer, - source_offset, - destination_buffer, - destination_offset, - size, - ); + 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); } fn create_buffer_with_data(&mut self, buffer_info: BufferInfo, data: &[u8]) -> RenderResource { - self.wgpu_resources + self.local_wgpu_resources .create_buffer_with_data(&self.device, buffer_info, data) } } diff --git a/bevy_wgpu/src/wgpu_renderer.rs b/bevy_wgpu/src/wgpu_renderer.rs index 4c8a14e6cd..12b5088999 100644 --- a/bevy_wgpu/src/wgpu_renderer.rs +++ b/bevy_wgpu/src/wgpu_renderer.rs @@ -13,14 +13,14 @@ use bevy_render::{ pipeline::{update_shader_assignments, PipelineCompiler, PipelineDescriptor}, render_graph::RenderGraph, render_resource::{ - resource_name, BufferInfo, BufferUsage, RenderResource, RenderResourceAssignments, + resource_name, BufferInfo, RenderResource, RenderResourceAssignments, RenderResources, ResourceInfo, }, renderer::Renderer, shader::Shader, texture::{SamplerDescriptor, TextureDescriptor}, }; -use bevy_window::{Window, WindowCreated, WindowResized, Windows}; +use bevy_window::{WindowCreated, WindowResized, Windows}; use legion::prelude::*; use std::{ collections::{HashMap, HashSet}, @@ -75,15 +75,6 @@ impl WgpuRenderer { } } - fn initialize(&mut self, world: &mut World, resources: &mut Resources) { - if self.intialized { - return; - } - - self.initialize_resource_providers(world, resources); - self.intialized = true; - } - pub fn create_render_pass<'a, 'b>( wgpu_resources: &'a WgpuResources, pass_descriptor: &PassDescriptor, @@ -220,30 +211,29 @@ impl WgpuRenderer { } } - pub fn initialize_resource_providers(&mut self, world: &mut World, resources: &mut Resources) { - self.encoder = Some( - self.device - .create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None }), - ); - + pub fn initialize_resource_providers( + world: &mut World, + resources: &mut Resources, + render_context: &mut WgpuRenderContext, + ) { let mut render_graph = resources.get_mut::().unwrap(); for resource_provider in render_graph.resource_providers.iter_mut() { - resource_provider.initialize(self, world, resources); + resource_provider.initialize(render_context, world, resources); } - - // consume current encoder - let command_buffer = self.encoder.take().unwrap().finish(); - self.queue.submit(&[command_buffer]); } - pub fn update_resource_providers(&mut self, world: &mut World, resources: &mut Resources) { + pub fn update_resource_providers( + world: &mut World, + resources: &mut Resources, + render_context: &mut WgpuRenderContext, + ) { let mut render_graph = resources.get_mut::().unwrap(); for resource_provider in render_graph.resource_providers.iter_mut() { - resource_provider.update(self, world, resources); + resource_provider.update(render_context, world, resources); } for resource_provider in render_graph.resource_providers.iter_mut() { - resource_provider.finish_update(self, world, resources); + resource_provider.finish_update(render_context, world, resources); } } @@ -257,14 +247,19 @@ impl WgpuRenderer { } } - pub fn handle_window_resized_events(&mut self, resources: &mut Resources) { + pub fn handle_window_resized_events( + resources: &mut Resources, + device: &wgpu::Device, + wgpu_resources: &mut WgpuResources, + window_resized_event_reader: &mut EventReader, + ) { let windows = resources.get::().unwrap(); let window_resized_events = resources.get::>().unwrap(); let mut handled_windows = HashSet::new(); // iterate in reverse order so we can handle the latest window resize event first for each window. // we skip earlier events for the same window because it results in redundant work for window_resized_event in window_resized_events - .iter(&mut self.window_resized_event_reader) + .iter(window_resized_event_reader) .rev() { if handled_windows.contains(&window_resized_event.id) { @@ -275,18 +270,23 @@ impl WgpuRenderer { .get(window_resized_event.id) .expect("Received window resized event for non-existent window"); - self.setup_swap_chain(window); + // TODO: consider making this a WgpuRenderContext method + wgpu_resources + .create_window_swap_chain(device, window); handled_windows.insert(window_resized_event.id); } } - pub fn handle_window_created_events(&mut self, resources: &mut Resources) { + pub fn handle_window_created_events( + resources: &mut Resources, + device: &wgpu::Device, + wgpu_resources: &mut WgpuResources, + window_created_event_reader: &mut EventReader, + ) { let windows = resources.get::().unwrap(); let window_created_events = resources.get::>().unwrap(); - for window_created_event in - window_created_events.iter(&mut self.window_created_event_reader) - { + for window_created_event in window_created_events.iter(window_created_event_reader) { let window = windows .get(window_created_event.id) .expect("Received window created event for non-existent window"); @@ -295,30 +295,12 @@ impl WgpuRenderer { let winit_windows = resources.get::().unwrap(); let primary_winit_window = winit_windows.get_window(window.id).unwrap(); let surface = wgpu::Surface::create(primary_winit_window.deref()); - self.wgpu_resources - .window_surfaces - .insert(window.id, surface); - self.setup_swap_chain(window); + wgpu_resources.set_window_surface(window.id, surface); + wgpu_resources.create_window_swap_chain(device, window); } } } - fn setup_swap_chain(&mut self, window: &Window) { - let surface = self - .wgpu_resources - .window_surfaces - .get(&window.id) - .expect("Received window resized event for window without a wgpu surface"); - - let swap_chain_descriptor: wgpu::SwapChainDescriptor = window.wgpu_into(); - let swap_chain = self - .device - .create_swap_chain(surface, &swap_chain_descriptor); - self.wgpu_resources - .window_swap_chains - .insert(window.id, swap_chain); - } - fn get_swap_chain_outputs( &mut self, resources: &Resources, @@ -349,16 +331,28 @@ impl WgpuRenderer { impl Renderer for WgpuRenderer { fn update(&mut self, world: &mut World, resources: &mut Resources) { - self.initialize(world, resources); - self.handle_window_created_events(resources); - self.handle_window_resized_events(resources); + Self::handle_window_created_events( + resources, + &self.device, + &mut self.wgpu_resources, + &mut self.window_created_event_reader, + ); + Self::handle_window_resized_events( + resources, + &self.device, + &mut self.wgpu_resources, + &mut self.window_resized_event_reader, + ); + let mut render_context = WgpuRenderContext::new(self.device.clone(), &self.wgpu_resources); + if !self.intialized { + Self::initialize_resource_providers(world, resources, &mut render_context); + self.intialized = true; + } + + // TODO: this self.encoder handoff is a bit gross, but its here to give resource providers access to buffer copies without // exposing the wgpu renderer internals to ResourceProvider traits. if this can be made cleaner that would be pretty cool. - self.encoder = Some( - self.device - .create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None }), - ); // use bevy_render::renderer_2::RenderContext; // let thread_count = 5; @@ -397,10 +391,21 @@ impl Renderer for WgpuRenderer { // self.queue.submit(&command_buffers); - self.update_resource_providers(world, resources); + Self::update_resource_providers(world, resources, &mut render_context); + + let (buffer, wgpu_resources) = render_context.finish(); + self.wgpu_resources + .consume(wgpu_resources); + if let Some(buffer) = buffer { + self.queue.submit(&[buffer]); + } + + self.encoder = Some( + self.device + .create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None }), + ); update_shader_assignments(world, resources, self); self.create_queued_textures(resources); - let mut encoder = self.encoder.take().unwrap(); // setup draw targets @@ -524,12 +529,17 @@ impl Renderer for WgpuRenderer { texture_descriptor: &TextureDescriptor, bytes: Option<&[u8]>, ) -> RenderResource { - self.wgpu_resources.create_texture_with_data( - &self.device, - self.encoder.as_mut().unwrap(), - texture_descriptor, - bytes, - ) + if let Some(bytes) = bytes { + self.wgpu_resources.create_texture_with_data( + &self.device, + self.encoder.as_mut().unwrap(), + texture_descriptor, + bytes, + ) + } else { + self.wgpu_resources + .create_texture(&self.device, texture_descriptor) + } } fn remove_texture(&mut self, resource: RenderResource) { diff --git a/bevy_wgpu/src/wgpu_resources.rs b/bevy_wgpu/src/wgpu_resources.rs index f1f0558c42..8236460769 100644 --- a/bevy_wgpu/src/wgpu_resources.rs +++ b/bevy_wgpu/src/wgpu_resources.rs @@ -8,10 +8,11 @@ use bevy_render::{ RenderResources, ResourceInfo, }, renderer::Renderer, + renderer_2::RenderContext, shader::Shader, - texture::{SamplerDescriptor, TextureDescriptor}, renderer_2::RenderContext, + texture::{SamplerDescriptor, TextureDescriptor}, }; -use bevy_window::WindowId; +use bevy_window::{Window, WindowId}; use std::collections::HashMap; #[derive(Default)] @@ -21,6 +22,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 window_surfaces: HashMap, pub window_swap_chains: HashMap, @@ -34,6 +36,41 @@ 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.window_surfaces.extend(wgpu_resources.window_surfaces); + self.window_swap_chains + .extend(wgpu_resources.window_swap_chains); + self.buffers.extend(wgpu_resources.buffers); + self.textures.extend(wgpu_resources.textures); + self.samplers.extend(wgpu_resources.samplers); + self.resource_info.extend(wgpu_resources.resource_info); + self.shader_modules.extend(wgpu_resources.shader_modules); + self.bind_groups.extend(wgpu_resources.bind_groups); + self.bind_group_layouts + .extend(wgpu_resources.bind_group_layouts); + } + + pub fn set_window_surface(&mut self, window_id: WindowId, surface: wgpu::Surface) { + self.window_surfaces.insert(window_id, surface); + } + + pub fn get_window_surface(&mut self, window_id: WindowId) -> Option<&wgpu::Surface> { + self.window_surfaces.get(&window_id) + } + + pub fn create_window_swap_chain(&mut self, device: &wgpu::Device, window: &Window) { + let swap_chain_descriptor: wgpu::SwapChainDescriptor = window.wgpu_into(); + let surface = self + .window_surfaces + .get(&window.id) + .expect("No surface found for window"); + let swap_chain = device.create_swap_chain(surface, &swap_chain_descriptor); + self.window_swap_chains.insert(window.id, swap_chain); + } + pub fn add_resource_info(&mut self, resource: RenderResource, resource_info: ResourceInfo) { self.resource_info.insert(resource, resource_info); } @@ -198,13 +235,11 @@ impl WgpuResources { setup_data: &mut dyn FnMut(&mut [u8], &mut dyn Renderer), ) -> wgpu::Buffer { let device = renderer.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, - } - ); + 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, renderer); mapped.finish() } @@ -216,13 +251,11 @@ impl WgpuResources { setup_data: &mut dyn FnMut(&mut [u8], &mut dyn RenderContext), ) -> wgpu::Buffer { let device = render_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(), - label: None, - } - ); + 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); mapped.finish() } @@ -285,29 +318,27 @@ impl WgpuResources { device: &wgpu::Device, encoder: &mut wgpu::CommandEncoder, texture_descriptor: &TextureDescriptor, - bytes: Option<&[u8]>, + bytes: &[u8], ) -> RenderResource { let descriptor: wgpu::TextureDescriptor = (*texture_descriptor).wgpu_into(); let texture = device.create_texture(&descriptor); let texture_view = texture.create_default_view(); - if let Some(bytes) = bytes { - let temp_buf = device.create_buffer_with_data(bytes, wgpu::BufferUsage::COPY_SRC); - encoder.copy_buffer_to_texture( - wgpu::BufferCopyView { - buffer: &temp_buf, - offset: 0, - bytes_per_row: 4 * descriptor.size.width, - rows_per_image: 0, // NOTE: Example sets this to 0, but should it be height? - }, - wgpu::TextureCopyView { - texture: &texture, - mip_level: 0, - array_layer: 0, - origin: wgpu::Origin3d { x: 0, y: 0, z: 0 }, - }, - descriptor.size, - ); - } + let temp_buf = device.create_buffer_with_data(bytes, wgpu::BufferUsage::COPY_SRC); + encoder.copy_buffer_to_texture( + wgpu::BufferCopyView { + buffer: &temp_buf, + offset: 0, + bytes_per_row: 4 * descriptor.size.width, + rows_per_image: 0, // NOTE: Example sets this to 0, but should it be height? + }, + wgpu::TextureCopyView { + texture: &texture, + mip_level: 0, + array_layer: 0, + origin: wgpu::Origin3d { x: 0, y: 0, z: 0 }, + }, + descriptor.size, + ); let resource = RenderResource::new(); self.add_resource_info(resource, ResourceInfo::Texture);