diff --git a/crates/bevy_render/src/draw_target/draw_targets/assigned_meshes_draw_target.rs b/crates/bevy_render/src/draw_target/draw_targets/assigned_meshes_draw_target.rs index a704ce7adb..57604be21a 100644 --- a/crates/bevy_render/src/draw_target/draw_targets/assigned_meshes_draw_target.rs +++ b/crates/bevy_render/src/draw_target/draw_targets/assigned_meshes_draw_target.rs @@ -101,7 +101,7 @@ impl DrawTarget for AssignedMeshesDrawTarget { pipeline_assignments.assignments.get(&pipeline_handle); let global_render_resource_assignments = resources.get::().unwrap(); - render_context.setup_bind_groups(pipeline_descriptor, &global_render_resource_assignments); + render_context.resources().setup_bind_groups(pipeline_descriptor, &global_render_resource_assignments); if let Some(assigned_render_resource_assignments) = assigned_render_resource_assignments { for assignment_id in assigned_render_resource_assignments.iter() { let entity = entity_render_resource_assignments @@ -112,7 +112,7 @@ impl DrawTarget for AssignedMeshesDrawTarget { continue; } - render_context.setup_bind_groups( + render_context.resources().setup_bind_groups( pipeline_descriptor, &renderable.render_resource_assignments, ); diff --git a/crates/bevy_render/src/draw_target/draw_targets/mod.rs b/crates/bevy_render/src/draw_target/draw_targets/mod.rs index d29d08b1dd..fd9e76a0ca 100644 --- a/crates/bevy_render/src/draw_target/draw_targets/mod.rs +++ b/crates/bevy_render/src/draw_target/draw_targets/mod.rs @@ -1,7 +1,5 @@ mod assigned_meshes_draw_target; mod meshes_draw_target; -mod ui_draw_target; pub use assigned_meshes_draw_target::*; pub use meshes_draw_target::*; -pub use ui_draw_target::*; diff --git a/crates/bevy_render/src/draw_target/draw_targets/ui_draw_target.rs b/crates/bevy_render/src/draw_target/draw_targets/ui_draw_target.rs deleted file mode 100644 index bf62b53c1b..0000000000 --- a/crates/bevy_render/src/draw_target/draw_targets/ui_draw_target.rs +++ /dev/null @@ -1,126 +0,0 @@ -use crate::{ - draw_target::DrawTarget, - mesh::{shape::Quad, Mesh}, - pass::RenderPass, - pipeline::PipelineDescriptor, - render_resource::{ - resource_name, BufferInfo, BufferUsage, RenderResource, RenderResourceAssignments, - ResourceInfo, - }, - renderer::RenderContext, -}; -use bevy_asset::Handle; -use legion::prelude::*; - -#[derive(Default)] -pub struct UiDrawTarget { - pub mesh_vertex_buffer: Option, - pub mesh_index_buffer: Option, - pub mesh_index_length: usize, - pub mesh: Option>, -} - -impl DrawTarget for UiDrawTarget { - fn draw( - &self, - _world: &World, - resources: &Resources, - render_pass: &mut dyn RenderPass, - _pipeline_handle: Handle, - pipeline_descriptor: &PipelineDescriptor, - ) { - let render_resource_assignments = resources.get::().unwrap(); - let ui_instances_buffer = { - match render_resource_assignments.get(resource_name::buffer::UI_INSTANCES) { - Some(buffer) => buffer, - None => return, - } - }; - - let index_count = { - let mut index_count = None; - let render_context = render_pass.get_render_context(); - render_context.resources().get_resource_info( - ui_instances_buffer, - &mut |resource_info| { - if let Some(ResourceInfo::Buffer(BufferInfo { - array_info: Some(array_info), - .. - })) = resource_info - { - index_count = Some(array_info.item_capacity); - } - }, - ); - index_count - }; - - let global_render_resource_assignments = - resources.get::().unwrap(); - render_pass.set_render_resources(pipeline_descriptor, &global_render_resource_assignments); - render_pass.set_index_buffer(self.mesh_index_buffer.unwrap(), 0); - render_pass.set_vertex_buffer(0, self.mesh_vertex_buffer.unwrap(), 0); - render_pass.set_vertex_buffer(1, ui_instances_buffer, 0); - render_pass.draw_indexed( - 0..self.mesh_index_length as u32, - 0, - 0..(index_count.unwrap() as u32), - ); - } - - fn setup( - &mut self, - _world: &World, - resources: &Resources, - render_context: &mut dyn RenderContext, - _pipeline_handle: Handle, - pipeline_descriptor: &PipelineDescriptor, - ) { - // don't create meshes if they have already been created - if let Some(_) = self.mesh_vertex_buffer { - return; - } - - let quad = Mesh::from(Quad { - size: glam::vec2(1.0, 1.0), - }); - let vertex_buffer_bytes = quad - .get_vertex_buffer_bytes( - pipeline_descriptor - .get_layout() - .unwrap() - .vertex_buffer_descriptors - .first() - .as_ref() - .unwrap(), - ) - .unwrap(); - self.mesh_vertex_buffer = Some(render_context.resources_mut().create_buffer_with_data( - BufferInfo { - buffer_usage: BufferUsage::VERTEX, - ..Default::default() - }, - &vertex_buffer_bytes, - )); - - let index_buffer_bytes = quad - .get_index_buffer_bytes(pipeline_descriptor.index_format) - .unwrap(); - self.mesh_index_buffer = Some(render_context.resources_mut().create_buffer_with_data( - BufferInfo { - buffer_usage: BufferUsage::INDEX, - ..Default::default() - }, - &index_buffer_bytes, - )); - - self.mesh_index_length = quad.indices.as_ref().unwrap().len(); - - let global_render_resource_assignments = - resources.get::().unwrap(); - render_context.setup_bind_groups(pipeline_descriptor, &global_render_resource_assignments); - } - fn get_name(&self) -> String { - resource_name::draw_target::UI.to_string() - } -} diff --git a/crates/bevy_render/src/render_graph/nodes/pass_node.rs b/crates/bevy_render/src/render_graph/nodes/pass_node.rs index 6e02e8262f..f9786b4fb0 100644 --- a/crates/bevy_render/src/render_graph/nodes/pass_node.rs +++ b/crates/bevy_render/src/render_graph/nodes/pass_node.rs @@ -114,7 +114,7 @@ impl Node for PassNode { } } - render_context.create_render_pipeline( + render_context.resources().create_render_pipeline( *compiled_pipeline_handle, &compiled_pipeline_descriptor, &shader_storage, diff --git a/crates/bevy_render/src/renderer/headless_render_resource_context.rs b/crates/bevy_render/src/renderer/headless_render_resource_context.rs index 0b9210f90f..c4f01ee6de 100644 --- a/crates/bevy_render/src/renderer/headless_render_resource_context.rs +++ b/crates/bevy_render/src/renderer/headless_render_resource_context.rs @@ -1,6 +1,9 @@ use super::RenderResourceContext; use crate::{ - render_resource::{BufferInfo, RenderResource, ResourceInfo}, + pipeline::{BindGroupDescriptor, PipelineDescriptor}, + render_resource::{ + BufferInfo, RenderResource, RenderResourceAssignments, RenderResourceSetId, ResourceInfo, + }, shader::Shader, texture::{SamplerDescriptor, TextureDescriptor}, }; @@ -63,7 +66,7 @@ impl RenderResourceContext for HeadlessRenderResourceContext { resource } fn create_shader_module( - &mut self, + &self, _shader_handle: Handle, _shader_storage: &AssetStorage, ) { @@ -106,4 +109,24 @@ impl RenderResourceContext for HeadlessRenderResourceContext { .get(&(handle, index)) .cloned() } + fn create_render_pipeline( + &self, + _pipeline_handle: Handle, + _pipeline_descriptor: &PipelineDescriptor, + _shader_storage: &AssetStorage, + ) { + } + fn create_bind_group( + &self, + bind_group_descriptor: &BindGroupDescriptor, + render_resource_assignments: &RenderResourceAssignments, + ) -> Option { + if let Some((render_resource_set_id, _indices)) = + render_resource_assignments.get_render_resource_set_id(bind_group_descriptor.id) + { + Some(*render_resource_set_id) + } else { + None + } + } } diff --git a/crates/bevy_render/src/renderer/render_context.rs b/crates/bevy_render/src/renderer/render_context.rs index a7ef2e7150..dda48c8ff4 100644 --- a/crates/bevy_render/src/renderer/render_context.rs +++ b/crates/bevy_render/src/renderer/render_context.rs @@ -1,12 +1,9 @@ use super::RenderResourceContext; use crate::{ pass::{PassDescriptor, RenderPass}, - pipeline::{BindGroupDescriptor, PipelineDescriptor}, - render_resource::{RenderResource, RenderResourceAssignments, RenderResourceSetId}, - shader::Shader, + render_resource::{RenderResource, RenderResourceAssignments}, texture::{Extent3d, TextureDescriptor}, }; -use bevy_asset::{AssetStorage, Handle}; pub trait RenderContext { fn resources(&self) -> &dyn RenderResourceContext; @@ -36,27 +33,6 @@ pub trait RenderContext { destination_array_layer: u32, size: Extent3d, ); - fn create_bind_group( - &mut self, - bind_group_descriptor: &BindGroupDescriptor, - render_resource_assignments: &RenderResourceAssignments, - ) -> Option; - fn create_render_pipeline( - &mut self, - pipeline_handle: Handle, - pipeline_descriptor: &PipelineDescriptor, - shader_storage: &AssetStorage, - ); - fn setup_bind_groups( - &mut self, - pipeline_descriptor: &PipelineDescriptor, - render_resource_assignments: &RenderResourceAssignments, - ) { - let pipeline_layout = pipeline_descriptor.get_layout().unwrap(); - for bind_group in pipeline_layout.bind_groups.iter() { - self.create_bind_group(bind_group, render_resource_assignments); - } - } fn begin_pass( &mut self, pass_descriptor: &PassDescriptor, diff --git a/crates/bevy_render/src/renderer/render_resource_context.rs b/crates/bevy_render/src/renderer/render_resource_context.rs index 2e9ed441c7..2a7a9ed96a 100644 --- a/crates/bevy_render/src/renderer/render_resource_context.rs +++ b/crates/bevy_render/src/renderer/render_resource_context.rs @@ -1,7 +1,7 @@ use crate::{ - render_resource::{BufferInfo, RenderResource, ResourceInfo}, + render_resource::{BufferInfo, RenderResource, ResourceInfo, RenderResourceAssignments, RenderResourceSetId}, shader::Shader, - texture::{SamplerDescriptor, TextureDescriptor}, + texture::{SamplerDescriptor, TextureDescriptor}, pipeline::{BindGroupDescriptor, PipelineDescriptor}, }; use bevy_asset::{AssetStorage, Handle, HandleUntyped}; use bevy_window::{Window, WindowId}; @@ -38,7 +38,7 @@ pub trait RenderResourceContext: Downcast + Send + Sync + 'static { ) -> RenderResource; fn create_buffer_with_data(&self, buffer_info: BufferInfo, data: &[u8]) -> RenderResource; fn create_shader_module( - &mut self, + &self, shader_handle: Handle, shader_storage: &AssetStorage, ); @@ -61,6 +61,27 @@ pub trait RenderResourceContext: Downcast + Send + Sync + 'static { handle: HandleUntyped, index: usize, ) -> Option; + fn create_render_pipeline( + &self, + pipeline_handle: Handle, + pipeline_descriptor: &PipelineDescriptor, + shader_storage: &AssetStorage, + ); + fn create_bind_group( + &self, + bind_group_descriptor: &BindGroupDescriptor, + render_resource_assignments: &RenderResourceAssignments, + ) -> Option; + fn setup_bind_groups( + &self, + pipeline_descriptor: &PipelineDescriptor, + render_resource_assignments: &RenderResourceAssignments, + ) { + let pipeline_layout = pipeline_descriptor.get_layout().unwrap(); + for bind_group in pipeline_layout.bind_groups.iter() { + self.create_bind_group(bind_group, render_resource_assignments); + } + } } impl dyn RenderResourceContext { diff --git a/crates/bevy_wgpu/src/diagnostic/wgpu_resource_diagnostics_plugin.rs b/crates/bevy_wgpu/src/diagnostic/wgpu_resource_diagnostics_plugin.rs index 218ca26de5..f4e6774cd3 100644 --- a/crates/bevy_wgpu/src/diagnostic/wgpu_resource_diagnostics_plugin.rs +++ b/crates/bevy_wgpu/src/diagnostic/wgpu_resource_diagnostics_plugin.rs @@ -128,7 +128,7 @@ impl WgpuResourceDiagnosticsPlugin { diagnostics.add_measurement( Self::WINDOW_SURFACES, render_resource_context - .wgpu_resources + .resources .window_surfaces .read() .unwrap() @@ -138,7 +138,7 @@ impl WgpuResourceDiagnosticsPlugin { diagnostics.add_measurement( Self::SWAP_CHAINS, render_resource_context - .wgpu_resources + .resources .window_swap_chains .read() .unwrap() @@ -148,7 +148,7 @@ impl WgpuResourceDiagnosticsPlugin { diagnostics.add_measurement( Self::SWAP_CHAIN_OUTPUTS, render_resource_context - .wgpu_resources + .resources .swap_chain_outputs .read() .unwrap() @@ -158,7 +158,7 @@ impl WgpuResourceDiagnosticsPlugin { diagnostics.add_measurement( Self::BUFFERS, render_resource_context - .wgpu_resources + .resources .buffers .read() .unwrap() @@ -168,7 +168,7 @@ impl WgpuResourceDiagnosticsPlugin { diagnostics.add_measurement( Self::TEXTURES, render_resource_context - .wgpu_resources + .resources .textures .read() .unwrap() @@ -178,7 +178,7 @@ impl WgpuResourceDiagnosticsPlugin { diagnostics.add_measurement( Self::TEXTURE_VIEWS, render_resource_context - .wgpu_resources + .resources .texture_views .read() .unwrap() @@ -188,7 +188,7 @@ impl WgpuResourceDiagnosticsPlugin { diagnostics.add_measurement( Self::SAMPLERS, render_resource_context - .wgpu_resources + .resources .samplers .read() .unwrap() @@ -198,7 +198,7 @@ impl WgpuResourceDiagnosticsPlugin { diagnostics.add_measurement( Self::BIND_GROUPS, render_resource_context - .wgpu_resources + .resources .bind_groups .read() .unwrap() @@ -208,7 +208,7 @@ impl WgpuResourceDiagnosticsPlugin { diagnostics.add_measurement( Self::BIND_GROUP_LAYOUTS, render_resource_context - .wgpu_resources + .resources .bind_group_layouts .read() .unwrap() @@ -218,7 +218,7 @@ impl WgpuResourceDiagnosticsPlugin { diagnostics.add_measurement( Self::SHADER_MODULES, render_resource_context - .wgpu_resources + .resources .shader_modules .read() .unwrap() @@ -228,7 +228,7 @@ impl WgpuResourceDiagnosticsPlugin { diagnostics.add_measurement( Self::RENDER_PIPELINES, render_resource_context - .wgpu_resources + .resources .render_pipelines .read() .unwrap() diff --git a/crates/bevy_wgpu/src/renderer/wgpu_render_context.rs b/crates/bevy_wgpu/src/renderer/wgpu_render_context.rs index e4c0c2fad8..6e9d7e3a38 100644 --- a/crates/bevy_wgpu/src/renderer/wgpu_render_context.rs +++ b/crates/bevy_wgpu/src/renderer/wgpu_render_context.rs @@ -1,20 +1,13 @@ use super::WgpuRenderResourceContext; -use crate::{ - wgpu_type_converter::{OwnedWgpuVertexBufferDescriptor, WgpuInto}, - WgpuRenderPass, WgpuResourceRefs, -}; -use bevy_asset::{AssetStorage, Handle}; +use crate::{wgpu_type_converter::WgpuInto, WgpuRenderPass, WgpuResourceRefs}; + use bevy_render::{ pass::{ PassDescriptor, RenderPass, RenderPassColorAttachmentDescriptor, RenderPassDepthStencilAttachmentDescriptor, TextureAttachment, }, - pipeline::{BindGroupDescriptor, BindType, PipelineDescriptor}, - render_resource::{ - RenderResource, RenderResourceAssignments, RenderResourceSetId, ResourceInfo, - }, + render_resource::{RenderResource, RenderResourceAssignments}, renderer::{RenderContext, RenderResourceContext}, - shader::Shader, texture::{Extent3d, TextureDescriptor}, }; use bevy_window::WindowId; @@ -86,14 +79,11 @@ impl RenderContext for WgpuRenderContext { texture_descriptor: &TextureDescriptor, bytes: &[u8], ) -> RenderResource { - self.render_resources - .wgpu_resources - .create_texture_with_data( - &self.device, - self.command_encoder.get_or_create(&self.device), - texture_descriptor, - bytes, - ) + self.render_resources.create_texture_with_data( + self.command_encoder.get_or_create(&self.device), + texture_descriptor, + bytes, + ) } fn copy_buffer_to_buffer( &mut self, @@ -103,9 +93,8 @@ impl RenderContext for WgpuRenderContext { destination_offset: u64, size: u64, ) { - let command_encoder = self.command_encoder.get_or_create(&self.device); - self.render_resources.wgpu_resources.copy_buffer_to_buffer( - command_encoder, + self.render_resources.copy_buffer_to_buffer( + self.command_encoder.get_or_create(&self.device), source_buffer, source_offset, destination_buffer, @@ -113,305 +102,38 @@ impl RenderContext for WgpuRenderContext { size, ); } + + fn copy_buffer_to_texture( + &mut self, + source_buffer: RenderResource, + source_offset: u64, + source_bytes_per_row: u32, + destination_texture: RenderResource, + destination_origin: [u32; 3], + destination_mip_level: u32, + destination_array_layer: u32, + size: Extent3d, + ) { + self.render_resources.copy_buffer_to_texture( + self.command_encoder.get_or_create(&self.device), + source_buffer, + source_offset, + source_bytes_per_row, + destination_texture, + destination_origin, + destination_mip_level, + destination_array_layer, + size, + ) + } + fn resources(&self) -> &dyn RenderResourceContext { &self.render_resources } fn resources_mut(&mut self) -> &mut dyn RenderResourceContext { &mut self.render_resources } - fn create_bind_group( - &mut self, - bind_group_descriptor: &BindGroupDescriptor, - render_resource_assignments: &RenderResourceAssignments, - ) -> Option { - if let Some((render_resource_set_id, _indices)) = - render_resource_assignments.get_render_resource_set_id(bind_group_descriptor.id) - { - if !self - .render_resources - .wgpu_resources - .has_bind_group(bind_group_descriptor.id, *render_resource_set_id) - { - log::trace!( - "start creating bind group for RenderResourceSet {:?}", - render_resource_set_id - ); - let wgpu_bind_group = { - let textures = self - .render_resources - .wgpu_resources - .texture_views - .read() - .unwrap(); - let samplers = self - .render_resources - .wgpu_resources - .samplers - .read() - .unwrap(); - let buffers = self.render_resources.wgpu_resources.buffers.read().unwrap(); - let bindings = bind_group_descriptor - .bindings - .iter() - .map(|binding| { - if let Some(resource) = render_resource_assignments.get(&binding.name) { - let mut wgpu_resource = None; - self.resources().get_resource_info( - resource, - &mut |resource_info| { - log::trace!( - "found binding {} ({}) resource: {:?} {:?}", - binding.index, - binding.name, - resource, - resource_info - ); - wgpu_resource = match &binding.bind_type { - BindType::SampledTexture { .. } => { - if let Some(ResourceInfo::Texture) = resource_info { - let texture = textures.get(&resource).unwrap(); - Some(wgpu::BindingResource::TextureView( - texture, - )) - } else { - panic!("expected a Texture resource"); - } - } - BindType::Sampler { .. } => { - if let Some(ResourceInfo::Sampler) = resource_info { - let sampler = samplers.get(&resource).unwrap(); - Some(wgpu::BindingResource::Sampler(sampler)) - } else { - panic!("expected a Sampler resource"); - } - } - BindType::Uniform { .. } => { - if let Some(ResourceInfo::Buffer(buffer_info)) = - resource_info - { - let buffer = buffers.get(&resource).unwrap(); - Some(wgpu::BindingResource::Buffer { - buffer, - range: 0..buffer_info.size as u64, - }) - } else { - panic!("expected a Buffer resource"); - } - } - _ => panic!("unsupported bind type"), - } - }, - ); - wgpu::Binding { - binding: binding.index, - resource: wgpu_resource.expect("No resource binding found"), - } - } else { - panic!( - "No resource assigned to uniform \"{}\" for RenderResourceAssignments {:?}", - binding.name, - render_resource_assignments.id - ); - } - }) - .collect::>(); - let bind_group_layouts = self - .render_resources - .wgpu_resources - .bind_group_layouts - .read() - .unwrap(); - let bind_group_layout = - bind_group_layouts.get(&bind_group_descriptor.id).unwrap(); - let wgpu_bind_group_descriptor = wgpu::BindGroupDescriptor { - label: None, - layout: bind_group_layout, - bindings: bindings.as_slice(), - }; - self.render_resources.wgpu_resources.create_bind_group( - &self.device, - *render_resource_set_id, - &wgpu_bind_group_descriptor, - ) - }; - self.render_resources.wgpu_resources.set_bind_group( - bind_group_descriptor.id, - *render_resource_set_id, - wgpu_bind_group, - ); - return Some(*render_resource_set_id); - } - } - None - } - fn create_render_pipeline( - &mut self, - pipeline_handle: Handle, - pipeline_descriptor: &PipelineDescriptor, - shader_storage: &AssetStorage, - ) { - if let Some(_) = self - .render_resources - .wgpu_resources - .render_pipelines - .read() - .unwrap() - .get(&pipeline_handle) - { - return; - } - - let layout = pipeline_descriptor.get_layout().unwrap(); - for bind_group in layout.bind_groups.iter() { - if self - .render_resources - .wgpu_resources - .bind_group_layouts - .read() - .unwrap() - .get(&bind_group.id) - .is_none() - { - let bind_group_layout_binding = bind_group - .bindings - .iter() - .map(|binding| wgpu::BindGroupLayoutEntry { - binding: binding.index, - visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: (&binding.bind_type).wgpu_into(), - }) - .collect::>(); - self.render_resources - .wgpu_resources - .create_bind_group_layout( - &self.device, - bind_group.id, - &wgpu::BindGroupLayoutDescriptor { - bindings: bind_group_layout_binding.as_slice(), - label: None, - }, - ); - } - } - - let pipeline_layout = { - let bind_group_layouts = self - .render_resources - .wgpu_resources - .bind_group_layouts - .read() - .unwrap(); - // setup and collect bind group layouts - let bind_group_layouts = layout - .bind_groups - .iter() - .map(|bind_group| bind_group_layouts.get(&bind_group.id).unwrap()) - .collect::>(); - self.device - .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - bind_group_layouts: bind_group_layouts.as_slice(), - }) - }; - - let owned_vertex_buffer_descriptors = layout - .vertex_buffer_descriptors - .iter() - .map(|v| v.wgpu_into()) - .collect::>(); - - let color_states = pipeline_descriptor - .color_states - .iter() - .map(|c| c.wgpu_into()) - .collect::>(); - - if self - .render_resources - .wgpu_resources - .shader_modules - .read() - .unwrap() - .get(&pipeline_descriptor.shader_stages.vertex) - .is_none() - { - self.render_resources - .create_shader_module(pipeline_descriptor.shader_stages.vertex, shader_storage); - } - - if let Some(fragment_handle) = pipeline_descriptor.shader_stages.fragment { - if self - .render_resources - .wgpu_resources - .shader_modules - .read() - .unwrap() - .get(&fragment_handle) - .is_none() - { - self.render_resources - .create_shader_module(fragment_handle, shader_storage); - } - }; - let wgpu_pipeline = { - let shader_modules = self - .render_resources - .wgpu_resources - .shader_modules - .read() - .unwrap(); - let vertex_shader_module = shader_modules - .get(&pipeline_descriptor.shader_stages.vertex) - .unwrap(); - - let fragment_shader_module = match pipeline_descriptor.shader_stages.fragment { - Some(fragment_handle) => Some(shader_modules.get(&fragment_handle).unwrap()), - None => None, - }; - - let render_pipeline_descriptor = wgpu::RenderPipelineDescriptor { - layout: &pipeline_layout, - vertex_stage: wgpu::ProgrammableStageDescriptor { - module: &vertex_shader_module, - entry_point: "main", - }, - fragment_stage: match pipeline_descriptor.shader_stages.fragment { - Some(_) => Some(wgpu::ProgrammableStageDescriptor { - entry_point: "main", - module: fragment_shader_module.as_ref().unwrap(), - }), - None => None, - }, - rasterization_state: pipeline_descriptor - .rasterization_state - .as_ref() - .map(|r| r.wgpu_into()), - primitive_topology: pipeline_descriptor.primitive_topology.wgpu_into(), - color_states: &color_states, - depth_stencil_state: pipeline_descriptor - .depth_stencil_state - .as_ref() - .map(|d| d.wgpu_into()), - vertex_state: wgpu::VertexStateDescriptor { - index_format: pipeline_descriptor.index_format.wgpu_into(), - vertex_buffers: &owned_vertex_buffer_descriptors - .iter() - .map(|v| v.into()) - .collect::>(), - }, - sample_count: pipeline_descriptor.sample_count, - sample_mask: pipeline_descriptor.sample_mask, - alpha_to_coverage_enabled: pipeline_descriptor.alpha_to_coverage_enabled, - }; - - self.render_resources - .wgpu_resources - .create_render_pipeline(&self.device, &render_pipeline_descriptor) - }; - self.render_resources - .wgpu_resources - .set_render_pipeline(pipeline_handle, wgpu_pipeline); - } fn begin_pass( &mut self, pass_descriptor: &PassDescriptor, @@ -421,7 +143,7 @@ impl RenderContext for WgpuRenderContext { if !self.command_encoder.is_some() { self.command_encoder.create(&self.device); } - let resource_lock = self.render_resources.wgpu_resources.read(); + let resource_lock = self.render_resources.resources.read(); let refs = resource_lock.refs(); let mut encoder = self.command_encoder.take().unwrap(); { @@ -443,29 +165,6 @@ impl RenderContext for WgpuRenderContext { self.command_encoder.set(encoder); } - fn copy_buffer_to_texture( - &mut self, - source_buffer: RenderResource, - source_offset: u64, - source_bytes_per_row: u32, - destination_texture: RenderResource, - destination_origin: [u32; 3], - destination_mip_level: u32, - destination_array_layer: u32, - size: Extent3d, - ) { - self.render_resources.wgpu_resources.copy_buffer_to_texture( - self.command_encoder.get_or_create(&self.device), - source_buffer, - source_offset, - source_bytes_per_row, - destination_texture, - destination_origin, - destination_mip_level, - destination_array_layer, - size, - ) - } } pub fn create_render_pass<'a, 'b>( diff --git a/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs b/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs index 0dcb7ad698..e14cda6648 100644 --- a/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs +++ b/crates/bevy_wgpu/src/renderer/wgpu_render_resource_context.rs @@ -1,70 +1,282 @@ -use crate::WgpuResources; +use crate::{ + wgpu_type_converter::{OwnedWgpuVertexBufferDescriptor, WgpuInto}, + WgpuBindGroupInfo, WgpuResources, +}; use bevy_asset::{AssetStorage, Handle, HandleUntyped}; use bevy_render::{ - render_resource::{BufferInfo, RenderResource, ResourceInfo}, + pipeline::{BindGroupDescriptor, BindType, PipelineDescriptor}, + render_resource::{ + BufferInfo, RenderResource, RenderResourceAssignments, RenderResourceSetId, ResourceInfo, + }, renderer::RenderResourceContext, shader::Shader, - texture::{SamplerDescriptor, TextureDescriptor}, + texture::{Extent3d, SamplerDescriptor, TextureDescriptor}, }; -use bevy_window::Window; +use bevy_window::{Window, WindowId}; use std::sync::Arc; #[derive(Clone)] pub struct WgpuRenderResourceContext { pub device: Arc, - pub wgpu_resources: WgpuResources, + pub resources: WgpuResources, } impl WgpuRenderResourceContext { pub fn new(device: Arc) -> Self { WgpuRenderResourceContext { device, - wgpu_resources: WgpuResources::default(), + resources: WgpuResources::default(), } } + + pub fn set_window_surface(&self, window_id: WindowId, surface: wgpu::Surface) { + let mut window_surfaces = self.resources.window_surfaces.write().unwrap(); + window_surfaces.insert(window_id, surface); + } + + pub fn create_texture_with_data( + &mut self, + command_encoder: &mut wgpu::CommandEncoder, + texture_descriptor: &TextureDescriptor, + bytes: &[u8], + ) -> RenderResource { + let mut resource_info = self.resources.resource_info.write().unwrap(); + let mut texture_views = self.resources.texture_views.write().unwrap(); + let mut textures = self.resources.textures.write().unwrap(); + + let descriptor: wgpu::TextureDescriptor = (*texture_descriptor).wgpu_into(); + let texture = self.device.create_texture(&descriptor); + let texture_view = texture.create_default_view(); + let temp_buf = self + .device + .create_buffer_with_data(bytes, wgpu::BufferUsage::COPY_SRC); + command_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(); + resource_info.insert(resource, ResourceInfo::Texture); + texture_views.insert(resource, texture_view); + textures.insert(resource, texture); + + resource + } + + pub fn copy_buffer_to_buffer( + &self, + command_encoder: &mut wgpu::CommandEncoder, + source_buffer: RenderResource, + source_offset: u64, + destination_buffer: RenderResource, + destination_offset: u64, + size: u64, + ) { + let buffers = self.resources.buffers.read().unwrap(); + + let source = buffers.get(&source_buffer).unwrap(); + let destination = buffers.get(&destination_buffer).unwrap(); + command_encoder.copy_buffer_to_buffer( + source, + source_offset, + destination, + destination_offset, + size, + ); + } + + pub fn copy_buffer_to_texture( + &self, + command_encoder: &mut wgpu::CommandEncoder, + source_buffer: RenderResource, + source_offset: u64, + source_bytes_per_row: u32, + destination_texture: RenderResource, + destination_origin: [u32; 3], // TODO: replace with math type + destination_mip_level: u32, + destination_array_layer: u32, + size: Extent3d, + ) { + let buffers = self.resources.buffers.read().unwrap(); + let textures = self.resources.textures.read().unwrap(); + + let source = buffers.get(&source_buffer).unwrap(); + let destination = textures.get(&destination_texture).unwrap(); + command_encoder.copy_buffer_to_texture( + wgpu::BufferCopyView { + buffer: source, + offset: source_offset, + bytes_per_row: source_bytes_per_row, + rows_per_image: 0, // NOTE: Example sets this to 0, but should it be height? + }, + wgpu::TextureCopyView { + texture: destination, + mip_level: destination_mip_level, + array_layer: destination_array_layer, + origin: wgpu::Origin3d { + x: destination_origin[0], + y: destination_origin[1], + z: destination_origin[2], + }, + }, + size.wgpu_into(), + ); + } + + pub fn create_bind_group_layout(&self, descriptor: &BindGroupDescriptor) { + if self + .resources + .bind_group_layouts + .read() + .unwrap() + .get(&descriptor.id) + .is_some() + { + return; + } + + let mut bind_group_layouts = self.resources.bind_group_layouts.write().unwrap(); + // TODO: consider re-checking existence here + let bind_group_layout_binding = descriptor + .bindings + .iter() + .map(|binding| wgpu::BindGroupLayoutEntry { + binding: binding.index, + visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, + ty: (&binding.bind_type).wgpu_into(), + }) + .collect::>(); + let wgpu_descriptor = wgpu::BindGroupLayoutDescriptor { + bindings: bind_group_layout_binding.as_slice(), + label: None, + }; + let bind_group_layout = self.device.create_bind_group_layout(&wgpu_descriptor); + bind_group_layouts.insert(descriptor.id, bind_group_layout); + } } impl RenderResourceContext for WgpuRenderResourceContext { fn create_sampler(&self, sampler_descriptor: &SamplerDescriptor) -> RenderResource { - self.wgpu_resources - .create_sampler(&self.device, sampler_descriptor) - } - fn create_texture(&self, texture_descriptor: &TextureDescriptor) -> RenderResource { - self.wgpu_resources - .create_texture(&self.device, texture_descriptor) - } - fn create_buffer(&self, buffer_info: BufferInfo) -> RenderResource { - self.wgpu_resources.create_buffer(&self.device, buffer_info) + let mut samplers = self.resources.samplers.write().unwrap(); + let mut resource_info = self.resources.resource_info.write().unwrap(); + + let descriptor: wgpu::SamplerDescriptor = (*sampler_descriptor).wgpu_into(); + let sampler = self.device.create_sampler(&descriptor); + + let resource = RenderResource::new(); + samplers.insert(resource, sampler); + resource_info.insert(resource, ResourceInfo::Sampler); + resource + } + + fn create_texture(&self, texture_descriptor: &TextureDescriptor) -> RenderResource { + let mut textures = self.resources.textures.write().unwrap(); + let mut texture_views = self.resources.texture_views.write().unwrap(); + let mut resource_info = self.resources.resource_info.write().unwrap(); + + let descriptor: wgpu::TextureDescriptor = (*texture_descriptor).wgpu_into(); + let texture = self.device.create_texture(&descriptor); + let texture_view = texture.create_default_view(); + + let resource = RenderResource::new(); + resource_info.insert(resource, ResourceInfo::Texture); + texture_views.insert(resource, texture_view); + textures.insert(resource, texture); + resource + } + + fn create_buffer(&self, buffer_info: BufferInfo) -> RenderResource { + // TODO: consider moving this below "create" for efficiency + let mut resource_info = self.resources.resource_info.write().unwrap(); + let mut buffers = self.resources.buffers.write().unwrap(); + + let buffer = self.device.create_buffer(&wgpu::BufferDescriptor { + label: None, + size: buffer_info.size as u64, + usage: buffer_info.buffer_usage.wgpu_into(), + }); + + let resource = RenderResource::new(); + resource_info.insert(resource, ResourceInfo::Buffer(buffer_info)); + buffers.insert(resource, buffer); + resource } - // TODO: clean this up fn create_buffer_mapped( &self, buffer_info: BufferInfo, setup_data: &mut dyn FnMut(&mut [u8], &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) + // TODO: consider moving this below "create" for efficiency + + let mut mapped = self.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(), self); + let buffer = mapped.finish(); + + let resource = RenderResource::new(); + let mut resource_info = self.resources.resource_info.write().unwrap(); + let mut buffers = self.resources.buffers.write().unwrap(); + resource_info.insert(resource, ResourceInfo::Buffer(buffer_info)); + buffers.insert(resource, buffer); + resource } - fn create_buffer_with_data(&self, buffer_info: BufferInfo, data: &[u8]) -> RenderResource { - self.wgpu_resources - .create_buffer_with_data(&self.device, buffer_info, data) + fn create_buffer_with_data(&self, mut buffer_info: BufferInfo, data: &[u8]) -> RenderResource { + // TODO: consider moving this below "create" for efficiency + let mut resource_info = self.resources.resource_info.write().unwrap(); + let mut buffers = self.resources.buffers.write().unwrap(); + + buffer_info.size = data.len(); + let buffer = self + .device + .create_buffer_with_data(data, buffer_info.buffer_usage.wgpu_into()); + + let resource = RenderResource::new(); + resource_info.insert(resource, ResourceInfo::Buffer(buffer_info)); + buffers.insert(resource, buffer); + resource } fn remove_buffer(&self, resource: RenderResource) { - self.wgpu_resources.remove_buffer(resource); + let mut buffers = self.resources.buffers.write().unwrap(); + let mut resource_info = self.resources.resource_info.write().unwrap(); + + buffers.remove(&resource); + resource_info.remove(&resource); } + fn remove_texture(&self, resource: RenderResource) { - self.wgpu_resources.remove_texture(resource); + let mut textures = self.resources.textures.write().unwrap(); + let mut texture_views = self.resources.texture_views.write().unwrap(); + let mut resource_info = self.resources.resource_info.write().unwrap(); + + textures.remove(&resource); + texture_views.remove(&resource); + resource_info.remove(&resource); } + fn remove_sampler(&self, resource: RenderResource) { - self.wgpu_resources.remove_sampler(resource); + let mut samplers = self.resources.samplers.write().unwrap(); + let mut resource_info = self.resources.resource_info.write().unwrap(); + + samplers.remove(&resource); + resource_info.remove(&resource); } fn get_resource_info( @@ -72,16 +284,18 @@ impl RenderResourceContext for WgpuRenderResourceContext { resource: RenderResource, handle_info: &mut dyn FnMut(Option<&ResourceInfo>), ) { - self.wgpu_resources.get_resource_info(resource, handle_info); + let resource_info = self.resources.resource_info.read().unwrap(); + let info = resource_info.get(&resource); + handle_info(info); } fn create_shader_module( - &mut self, + &self, shader_handle: Handle, shader_storage: &AssetStorage, ) { if self - .wgpu_resources + .resources .shader_modules .read() .unwrap() @@ -91,39 +305,281 @@ impl RenderResourceContext for WgpuRenderResourceContext { return; } + let mut shader_modules = self.resources.shader_modules.write().unwrap(); + // TODO: consider re-checking existence here + let shader = shader_storage.get(&shader_handle).unwrap(); - self.wgpu_resources - .create_shader_module(&self.device, shader_handle, shader); + let shader_module = self.device.create_shader_module(&shader.get_spirv(None)); + shader_modules.insert(shader_handle, shader_module); } + fn create_swap_chain(&self, window: &Window) { - self.wgpu_resources - .create_window_swap_chain(&self.device, window) + let surfaces = self.resources.window_surfaces.read().unwrap(); + let mut window_swap_chains = self.resources.window_swap_chains.write().unwrap(); + + let swap_chain_descriptor: wgpu::SwapChainDescriptor = window.wgpu_into(); + let surface = surfaces + .get(&window.id) + .expect("No surface found for window"); + let swap_chain = self + .device + .create_swap_chain(surface, &swap_chain_descriptor); + + window_swap_chains.insert(window.id, swap_chain); } + fn next_swap_chain_texture(&self, window_id: bevy_window::WindowId) -> RenderResource { - self.wgpu_resources.next_swap_chain_texture(window_id) + let mut window_swap_chains = self.resources.window_swap_chains.write().unwrap(); + let mut swap_chain_outputs = self.resources.swap_chain_outputs.write().unwrap(); + + let window_swap_chain = window_swap_chains.get_mut(&window_id).unwrap(); + let next_texture = window_swap_chain.get_next_texture().unwrap(); + + // TODO: Add ResourceInfo + let render_resource = RenderResource::new(); + swap_chain_outputs.insert(render_resource, next_texture); + render_resource } + fn drop_swap_chain_texture(&self, render_resource: RenderResource) { - self.wgpu_resources - .remove_swap_chain_texture(render_resource); + let mut swap_chain_outputs = self.resources.swap_chain_outputs.write().unwrap(); + swap_chain_outputs.remove(&render_resource); } + fn drop_all_swap_chain_textures(&self) { - self.wgpu_resources.remove_all_swap_chain_textures(); + let mut swap_chain_outputs = self.resources.swap_chain_outputs.write().unwrap(); + swap_chain_outputs.clear(); } + fn set_asset_resource_untyped( &self, handle: HandleUntyped, render_resource: RenderResource, index: usize, ) { - self.wgpu_resources - .set_asset_resource_untyped(handle, render_resource, index); + let mut asset_resources = self.resources.asset_resources.write().unwrap(); + asset_resources.insert((handle, index), render_resource); } + fn get_asset_resource_untyped( &self, handle: HandleUntyped, index: usize, ) -> Option { - self.wgpu_resources - .get_asset_resource_untyped(handle, index) + let asset_resources = self.resources.asset_resources.read().unwrap(); + asset_resources.get(&(handle, index)).cloned() + } + + fn create_render_pipeline( + &self, + pipeline_handle: Handle, + pipeline_descriptor: &PipelineDescriptor, + shaders: &AssetStorage, + ) { + if self + .resources + .render_pipelines + .read() + .unwrap() + .get(&pipeline_handle) + .is_some() + { + return; + } + + let layout = pipeline_descriptor.get_layout().unwrap(); + for bind_group_descriptor in layout.bind_groups.iter() { + self.create_bind_group_layout(&bind_group_descriptor); + } + + let bind_group_layouts = self.resources.bind_group_layouts.read().unwrap(); + // setup and collect bind group layouts + let bind_group_layouts = layout + .bind_groups + .iter() + .map(|bind_group| 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 owned_vertex_buffer_descriptors = layout + .vertex_buffer_descriptors + .iter() + .map(|v| v.wgpu_into()) + .collect::>(); + + let color_states = pipeline_descriptor + .color_states + .iter() + .map(|c| c.wgpu_into()) + .collect::>(); + + self.create_shader_module(pipeline_descriptor.shader_stages.vertex, shaders); + + if let Some(fragment_handle) = pipeline_descriptor.shader_stages.fragment { + self.create_shader_module(fragment_handle, shaders); + } + + let shader_modules = self.resources.shader_modules.read().unwrap(); + let vertex_shader_module = shader_modules + .get(&pipeline_descriptor.shader_stages.vertex) + .unwrap(); + + let fragment_shader_module = match pipeline_descriptor.shader_stages.fragment { + Some(fragment_handle) => Some(shader_modules.get(&fragment_handle).unwrap()), + None => None, + }; + + let render_pipeline_descriptor = wgpu::RenderPipelineDescriptor { + layout: &pipeline_layout, + vertex_stage: wgpu::ProgrammableStageDescriptor { + module: &vertex_shader_module, + entry_point: "main", + }, + fragment_stage: match pipeline_descriptor.shader_stages.fragment { + Some(_) => Some(wgpu::ProgrammableStageDescriptor { + entry_point: "main", + module: fragment_shader_module.as_ref().unwrap(), + }), + None => None, + }, + rasterization_state: pipeline_descriptor + .rasterization_state + .as_ref() + .map(|r| r.wgpu_into()), + primitive_topology: pipeline_descriptor.primitive_topology.wgpu_into(), + color_states: &color_states, + depth_stencil_state: pipeline_descriptor + .depth_stencil_state + .as_ref() + .map(|d| d.wgpu_into()), + vertex_state: wgpu::VertexStateDescriptor { + index_format: pipeline_descriptor.index_format.wgpu_into(), + vertex_buffers: &owned_vertex_buffer_descriptors + .iter() + .map(|v| v.into()) + .collect::>(), + }, + sample_count: pipeline_descriptor.sample_count, + sample_mask: pipeline_descriptor.sample_mask, + alpha_to_coverage_enabled: pipeline_descriptor.alpha_to_coverage_enabled, + }; + + let render_pipeline = self + .device + .create_render_pipeline(&render_pipeline_descriptor); + let mut render_pipelines = self.resources.render_pipelines.write().unwrap(); + render_pipelines.insert(pipeline_handle, render_pipeline); + } + + fn create_bind_group( + &self, + bind_group_descriptor: &BindGroupDescriptor, + render_resource_assignments: &RenderResourceAssignments, + ) -> Option { + if let Some((render_resource_set_id, _indices)) = + render_resource_assignments.get_render_resource_set_id(bind_group_descriptor.id) + { + if !self + .resources + .has_bind_group(bind_group_descriptor.id, *render_resource_set_id) + { + log::trace!( + "start creating bind group for RenderResourceSet {:?}", + render_resource_set_id + ); + let texture_views = self.resources.texture_views.read().unwrap(); + let samplers = self.resources.samplers.read().unwrap(); + let buffers = self.resources.buffers.read().unwrap(); + let resource_info = self.resources.resource_info.read().unwrap(); + let bind_group_layouts = self.resources.bind_group_layouts.read().unwrap(); + let mut bind_groups = self.resources.bind_groups.write().unwrap(); + + let bindings = bind_group_descriptor + .bindings + .iter() + .map(|binding| { + if let Some(resource) = render_resource_assignments.get(&binding.name) { + let info = resource_info + .get(&resource) + .expect("referenced resource does not exist"); + log::trace!( + "found binding {} ({}) resource: {:?} {:?}", + binding.index, + binding.name, + resource, + resource_info + ); + let wgpu_resource = match &binding.bind_type { + BindType::SampledTexture { .. } => { + if let ResourceInfo::Texture = info { + let texture = texture_views.get(&resource).unwrap(); + wgpu::BindingResource::TextureView(texture) + } else { + panic!("expected a Texture resource"); + } + } + BindType::Sampler { .. } => { + if let ResourceInfo::Sampler = info { + let sampler = samplers.get(&resource).unwrap(); + wgpu::BindingResource::Sampler(sampler) + } else { + panic!("expected a Sampler resource"); + } + } + BindType::Uniform { .. } => { + if let ResourceInfo::Buffer(buffer_info) = info { + let buffer = buffers.get(&resource).unwrap(); + wgpu::BindingResource::Buffer { + buffer, + range: 0..buffer_info.size as u64, + } + } else { + panic!("expected a Buffer resource"); + } + } + _ => panic!("unsupported bind type"), + }; + wgpu::Binding { + binding: binding.index, + resource: wgpu_resource, + } + } else { + panic!( + "No resource assigned to uniform \"{}\" for RenderResourceAssignments {:?}", + binding.name, + render_resource_assignments.id + ); + } + }) + .collect::>(); + + let bind_group_layout = bind_group_layouts.get(&bind_group_descriptor.id).unwrap(); + let wgpu_bind_group_descriptor = wgpu::BindGroupDescriptor { + label: None, + layout: bind_group_layout, + bindings: bindings.as_slice(), + }; + let wgpu_bind_group = self.device.create_bind_group(&wgpu_bind_group_descriptor); + + let bind_group_info = bind_groups + .entry(bind_group_descriptor.id) + .or_insert_with(|| WgpuBindGroupInfo::default()); + bind_group_info + .bind_groups + .insert(*render_resource_set_id, wgpu_bind_group); + log::trace!( + "created bind group for RenderResourceSet {:?}", + render_resource_set_id + ); + return Some(*render_resource_set_id); + } + } + + None } } diff --git a/crates/bevy_wgpu/src/wgpu_renderer.rs b/crates/bevy_wgpu/src/wgpu_renderer.rs index aa220c7252..f327fba112 100644 --- a/crates/bevy_wgpu/src/wgpu_renderer.rs +++ b/crates/bevy_wgpu/src/wgpu_renderer.rs @@ -79,9 +79,7 @@ impl WgpuRenderer { let winit_windows = resources.get::().unwrap(); let winit_window = winit_windows.get_window(window.id).unwrap(); let surface = unsafe { self.instance.create_surface(winit_window.deref()) }; - render_resource_context - .wgpu_resources - .set_window_surface(window.id, surface); + render_resource_context.set_window_surface(window.id, surface); } } } diff --git a/crates/bevy_wgpu/src/wgpu_resources.rs b/crates/bevy_wgpu/src/wgpu_resources.rs index a6b6efb635..36823494af 100644 --- a/crates/bevy_wgpu/src/wgpu_resources.rs +++ b/crates/bevy_wgpu/src/wgpu_resources.rs @@ -1,13 +1,10 @@ -use crate::{renderer::WgpuRenderResourceContext, wgpu_type_converter::WgpuInto}; use bevy_asset::{Handle, HandleUntyped}; use bevy_render::{ pipeline::{BindGroupDescriptorId, PipelineDescriptor}, - render_resource::{BufferInfo, RenderResource, RenderResourceSetId, ResourceInfo}, - renderer::RenderResourceContext, + render_resource::{RenderResource, RenderResourceSetId, ResourceInfo}, shader::Shader, - texture::{Extent3d, SamplerDescriptor, TextureDescriptor}, }; -use bevy_window::{Window, WindowId}; +use bevy_window::WindowId; use std::{ collections::HashMap, sync::{Arc, RwLock, RwLockReadGuard}, @@ -98,57 +95,6 @@ impl WgpuResources { } } - pub fn set_window_surface(&self, window_id: WindowId, surface: wgpu::Surface) { - self.window_surfaces - .write() - .unwrap() - .insert(window_id, surface); - } - - pub fn next_swap_chain_texture(&self, window_id: WindowId) -> RenderResource { - let mut swap_chain_outputs = self.window_swap_chains.write().unwrap(); - let swap_chain_output = swap_chain_outputs.get_mut(&window_id).unwrap(); - let next_texture = swap_chain_output.get_next_texture().unwrap(); - let render_resource = RenderResource::new(); - // TODO: Add ResourceInfo - self.swap_chain_outputs - .write() - .unwrap() - .insert(render_resource, next_texture); - render_resource - } - - pub fn remove_swap_chain_texture(&self, render_resource: RenderResource) { - self.swap_chain_outputs - .write() - .unwrap() - .remove(&render_resource); - } - - pub fn remove_all_swap_chain_textures(&self) { - self.swap_chain_outputs.write().unwrap().clear(); - } - - pub fn create_window_swap_chain(&self, device: &wgpu::Device, window: &Window) { - let swap_chain_descriptor: wgpu::SwapChainDescriptor = window.wgpu_into(); - let surfaces = self.window_surfaces.read().unwrap(); - let surface = 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 - .write() - .unwrap() - .insert(window.id, swap_chain); - } - - pub fn add_resource_info(&self, resource: RenderResource, resource_info: ResourceInfo) { - self.resource_info - .write() - .unwrap() - .insert(resource, resource_info); - } - pub fn has_bind_group( &self, bind_group_descriptor_id: BindGroupDescriptorId, @@ -168,324 +114,4 @@ impl WgpuResources { false } } - - pub fn create_bind_group( - &self, - device: &wgpu::Device, - render_resource_set_id: RenderResourceSetId, - bind_group_descriptor: &wgpu::BindGroupDescriptor, - ) -> wgpu::BindGroup { - log::trace!( - "created bind group for RenderResourceSet {:?}", - render_resource_set_id - ); - device.create_bind_group(bind_group_descriptor) - } - - pub fn set_bind_group( - &self, - bind_group_descriptor_id: BindGroupDescriptorId, - render_resource_set_id: RenderResourceSetId, - bind_group: wgpu::BindGroup, - ) { - let mut bind_groups = self.bind_groups.write().unwrap(); - let bind_group_info = bind_groups - .entry(bind_group_descriptor_id) - .or_insert_with(|| WgpuBindGroupInfo::default()); - bind_group_info - .bind_groups - .insert(render_resource_set_id, bind_group); - } - - pub fn create_buffer(&self, device: &wgpu::Device, buffer_info: BufferInfo) -> RenderResource { - let buffer = device.create_buffer(&wgpu::BufferDescriptor { - label: None, - size: buffer_info.size as u64, - usage: buffer_info.buffer_usage.wgpu_into(), - }); - - let resource = RenderResource::new(); - self.add_resource_info(resource, ResourceInfo::Buffer(buffer_info)); - - self.buffers.write().unwrap().insert(resource, buffer); - resource - } - - pub fn create_buffer_with_data( - &self, - device: &wgpu::Device, - mut buffer_info: BufferInfo, - data: &[u8], - ) -> RenderResource { - buffer_info.size = data.len(); - let buffer = device.create_buffer_with_data(data, buffer_info.buffer_usage.wgpu_into()); - self.assign_buffer(buffer, buffer_info) - } - - // TODO: taking a closure isn't fantastic. is there any way to make this better without exposing the lock in the interface? - pub fn get_resource_info( - &self, - resource: RenderResource, - handle_info: &mut dyn FnMut(Option<&ResourceInfo>), - ) { - let resource_info = self.resource_info.read().unwrap(); - let info = resource_info.get(&resource); - handle_info(info); - } - - pub fn remove_buffer(&self, resource: RenderResource) { - self.buffers.write().unwrap().remove(&resource); - self.resource_info.write().unwrap().remove(&resource); - } - - pub fn assign_buffer(&self, buffer: wgpu::Buffer, buffer_info: BufferInfo) -> RenderResource { - let resource = RenderResource::new(); - self.add_resource_info(resource, ResourceInfo::Buffer(buffer_info)); - self.buffers.write().unwrap().insert(resource, buffer); - resource - } - - // TODO: clean this up - pub fn begin_create_buffer_mapped_render_context( - buffer_info: &BufferInfo, - render_resources: &WgpuRenderResourceContext, - setup_data: &mut dyn FnMut(&mut [u8], &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() - } - - pub fn copy_buffer_to_buffer( - &self, - encoder: &mut wgpu::CommandEncoder, - source_buffer: RenderResource, - source_offset: u64, - destination_buffer: RenderResource, - destination_offset: u64, - size: u64, - ) { - let buffers = self.buffers.read().unwrap(); - let source = buffers.get(&source_buffer).unwrap(); - let destination = buffers.get(&destination_buffer).unwrap(); - encoder.copy_buffer_to_buffer(source, source_offset, destination, destination_offset, size); - } - - pub fn copy_buffer_to_texture( - &self, - encoder: &mut wgpu::CommandEncoder, - source_buffer: RenderResource, - source_offset: u64, - source_bytes_per_row: u32, - destination_texture: RenderResource, - destination_origin: [u32; 3], // TODO: replace with math type - destination_mip_level: u32, - destination_array_layer: u32, - size: Extent3d, - ) { - let buffers = self.buffers.read().unwrap(); - let textures = self.textures.read().unwrap(); - let source = buffers.get(&source_buffer).unwrap(); - let destination = textures.get(&destination_texture).unwrap(); - encoder.copy_buffer_to_texture( - wgpu::BufferCopyView { - buffer: source, - offset: source_offset, - bytes_per_row: source_bytes_per_row, - rows_per_image: 0, // NOTE: Example sets this to 0, but should it be height? - }, - wgpu::TextureCopyView { - texture: destination, - mip_level: destination_mip_level, - array_layer: destination_array_layer, - origin: wgpu::Origin3d { - x: destination_origin[0], - y: destination_origin[1], - z: destination_origin[2], - }, - }, - size.wgpu_into(), - ); - } - - pub fn create_shader_module( - &self, - device: &wgpu::Device, - shader_handle: Handle, - shader: &Shader, - ) { - let shader_module = device.create_shader_module(&shader.get_spirv(None)); - self.shader_modules - .write() - .unwrap() - .insert(shader_handle, shader_module); - } - - pub fn create_sampler( - &self, - device: &wgpu::Device, - sampler_descriptor: &SamplerDescriptor, - ) -> RenderResource { - let descriptor: wgpu::SamplerDescriptor = (*sampler_descriptor).wgpu_into(); - let sampler = device.create_sampler(&descriptor); - let resource = RenderResource::new(); - self.samplers.write().unwrap().insert(resource, sampler); - self.add_resource_info(resource, ResourceInfo::Sampler); - resource - } - - pub fn create_texture( - &self, - device: &wgpu::Device, - texture_descriptor: &TextureDescriptor, - ) -> RenderResource { - let descriptor: wgpu::TextureDescriptor = (*texture_descriptor).wgpu_into(); - let texture = device.create_texture(&descriptor); - let texture_view = texture.create_default_view(); - let resource = RenderResource::new(); - self.add_resource_info(resource, ResourceInfo::Texture); - self.texture_views - .write() - .unwrap() - .insert(resource, texture_view); - self.textures.write().unwrap().insert(resource, texture); - resource - } - - pub fn create_texture_with_data( - &self, - device: &wgpu::Device, - encoder: &mut wgpu::CommandEncoder, - texture_descriptor: &TextureDescriptor, - bytes: &[u8], - ) -> RenderResource { - let descriptor: wgpu::TextureDescriptor = (*texture_descriptor).wgpu_into(); - let texture = device.create_texture(&descriptor); - let texture_view = texture.create_default_view(); - 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); - self.texture_views - .write() - .unwrap() - .insert(resource, texture_view); - resource - } - - pub fn remove_texture(&self, resource: RenderResource) { - self.texture_views.write().unwrap().remove(&resource); - self.textures.write().unwrap().remove(&resource); - self.resource_info.write().unwrap().remove(&resource); - } - - pub fn remove_sampler(&self, resource: RenderResource) { - self.samplers.write().unwrap().remove(&resource); - self.resource_info.write().unwrap().remove(&resource); - } - - pub fn set_asset_resource( - &mut self, - handle: Handle, - render_resource: RenderResource, - index: usize, - ) where - T: 'static, - { - self.asset_resources - .write() - .unwrap() - .insert((handle.into(), index), render_resource); - } - - pub fn get_asset_resource( - &mut self, - handle: Handle, - index: usize, - ) -> Option - where - T: 'static, - { - self.asset_resources - .write() - .unwrap() - .get(&(handle.into(), index)) - .cloned() - } - - pub fn set_asset_resource_untyped( - &self, - handle: HandleUntyped, - render_resource: RenderResource, - index: usize, - ) { - self.asset_resources - .write() - .unwrap() - .insert((handle, index), render_resource); - } - - pub fn get_asset_resource_untyped( - &self, - handle: HandleUntyped, - index: usize, - ) -> Option { - self.asset_resources - .write() - .unwrap() - .get(&(handle, index)) - .cloned() - } - - pub fn create_bind_group_layout( - &self, - device: &wgpu::Device, - bind_group_id: BindGroupDescriptorId, - descriptor: &wgpu::BindGroupLayoutDescriptor, - ) { - let wgpu_bind_group_layout = device.create_bind_group_layout(descriptor); - self.bind_group_layouts - .write() - .unwrap() - .insert(bind_group_id, wgpu_bind_group_layout); - } - - pub fn create_render_pipeline( - &self, - device: &wgpu::Device, - descriptor: &wgpu::RenderPipelineDescriptor, - ) -> wgpu::RenderPipeline { - device.create_render_pipeline(&descriptor) - } - - pub fn set_render_pipeline( - &self, - pipeline_handle: Handle, - render_pipeline: wgpu::RenderPipeline, - ) { - self.render_pipelines - .write() - .unwrap() - .insert(pipeline_handle, render_pipeline); - } }