diff --git a/src/render/render_graph_2/draw_target.rs b/src/render/render_graph_2/draw_target.rs index e9c05f926f..f2d08a7a0b 100644 --- a/src/render/render_graph_2/draw_target.rs +++ b/src/render/render_graph_2/draw_target.rs @@ -7,10 +7,14 @@ use crate::{ }, }; +use zerocopy::AsBytes; + // A set of draw calls. ex: get + draw meshes, get + draw instanced meshes, draw ui meshes, etc pub type DrawTarget = fn(world: &World, render_pass: &mut dyn RenderPass); -pub fn mesh_draw_target(world: &World, _render_pass: &mut dyn RenderPass) { +const MESH_VERTEX_BUFFER_NAME: &str = "TempMeshVertexBuffer"; +const MESH_INDEX_BUFFER_NAME: &str = "TempMeshIndexBuffer"; +pub fn mesh_draw_target(world: &World, render_pass: &mut dyn RenderPass) { let mut mesh_storage = world.resources.get_mut::>().unwrap(); let mut last_mesh_id = None; let mesh_query = @@ -24,18 +28,27 @@ pub fn mesh_draw_target(world: &World, _render_pass: &mut dyn RenderPass) { } if should_load_mesh { - if let Some(_mesh_asset) = mesh_storage.get(mesh.id) { - // render_pass.load_mesh(mesh.id, mesh_asset); - // render_pass.set_index_buffer(mesh_asset.index_buffer.as_ref().unwrap(), 0); - // render_pass.set_vertex_buffers(0, &[(&mesh_asset.vertex_buffer.as_ref().unwrap(), 0)]); + if let Some(mesh_asset) = mesh_storage.get(mesh.id) { + let renderer = render_pass.get_renderer(); + renderer.create_buffer_with_data(MESH_VERTEX_BUFFER_NAME, mesh_asset.vertices.as_bytes(), wgpu::BufferUsage::VERTEX); + renderer.create_buffer_with_data(MESH_INDEX_BUFFER_NAME, mesh_asset.indices.as_bytes(), wgpu::BufferUsage::INDEX); + + // TODO: Verify buffer format matches render pass + render_pass.set_index_buffer(MESH_INDEX_BUFFER_NAME, 0); + render_pass.set_vertex_buffer(0, MESH_VERTEX_BUFFER_NAME, 0); }; } - if let Some(ref _mesh_asset) = mesh_storage.get(mesh.id) { + if let Some(mesh_asset) = mesh_storage.get(mesh.id) { // pass.set_bind_group(1, material.bind_group.as_ref().unwrap(), &[]); - // pass.draw_indexed(0..mesh_asset.indices.len() as u32, 0, 0..1); + render_pass.draw_indexed(0..mesh_asset.indices.len() as u32, 0, 0..1); }; last_mesh_id = Some(current_mesh_id); } + + // cleanup buffers + let renderer = render_pass.get_renderer(); + renderer.remove_buffer(MESH_VERTEX_BUFFER_NAME); + renderer.remove_buffer(MESH_INDEX_BUFFER_NAME); } \ No newline at end of file diff --git a/src/render/render_graph_2/render_graph.rs b/src/render/render_graph_2/render_graph.rs index 0441d9846e..bd72ee0906 100644 --- a/src/render/render_graph_2/render_graph.rs +++ b/src/render/render_graph_2/render_graph.rs @@ -3,6 +3,7 @@ use std::collections::HashMap; pub struct RenderGraph { pub pipeline_descriptors: HashMap, + // TODO: make this ordered pub pass_descriptors: HashMap, pub pass_pipelines: HashMap>, pub resource_providers: Vec>, diff --git a/src/render/render_graph_2/renderer.rs b/src/render/render_graph_2/renderer.rs index 7fd4ab8ae8..ddd8cbb421 100644 --- a/src/render/render_graph_2/renderer.rs +++ b/src/render/render_graph_2/renderer.rs @@ -1,14 +1,20 @@ -use crate::{asset::Mesh, legion::prelude::*, render::render_graph_2::{RenderGraph, Buffer, ResourceId}}; +use crate::{legion::prelude::*, render::render_graph_2::{RenderGraph, BufferInfo, PipelineDescriptor}}; +use std::ops::Range; pub trait Renderer { fn initialize(&mut self, world: &mut World); fn resize(&mut self, world: &mut World, width: u32, height: u32); fn process_render_graph(&mut self, render_graph: &RenderGraph, world: &mut World); // TODO: swap out wgpu::BufferUsage for custom type - fn create_buffer_with_data(&mut self, data: &[u8], buffer_usage: wgpu::BufferUsage) -> Buffer; - fn free_buffer(&mut self, id: ResourceId) -> Buffer; + fn create_buffer_with_data(&mut self, name: &str, data: &[u8], buffer_usage: wgpu::BufferUsage); + fn remove_buffer(&mut self, name: &str); + fn get_buffer_info(&self, name: &str) -> Option<&BufferInfo>; } pub trait RenderPass { - fn set_index_buffer(&mut self, buffer: &wgpu::Buffer, offset: wgpu::BufferAddress); + fn get_renderer(&mut self) -> &mut dyn Renderer; + fn get_pipeline_descriptor(&self) -> &PipelineDescriptor; + fn set_index_buffer(&mut self, name: &str, offset: u64); + fn set_vertex_buffer(&mut self, start_slot: u32, name: &str, offset: u64); + fn draw_indexed(&mut self, indices: Range, base_vertex: i32, instances: Range); } \ No newline at end of file diff --git a/src/render/render_graph_2/resource.rs b/src/render/render_graph_2/resource.rs index 163cc2e144..0ac029f17d 100644 --- a/src/render/render_graph_2/resource.rs +++ b/src/render/render_graph_2/resource.rs @@ -1,7 +1,6 @@ -pub type ResourceId = u64; +// pub type ResourceId = u64; -pub struct Buffer { - pub id: ResourceId, +pub struct BufferInfo { pub size: u64, pub buffer_usage: wgpu::BufferUsage, // pub layout: Option< diff --git a/src/render/render_graph_2/resource_name.rs b/src/render/render_graph_2/resource_name.rs index 73e7fc6e43..a1884a4f13 100644 --- a/src/render/render_graph_2/resource_name.rs +++ b/src/render/render_graph_2/resource_name.rs @@ -1,3 +1,7 @@ pub mod texture { pub const SWAP_CHAIN: &str = "SwapChain"; +} + +pub mod uniform { + pub const CAMERA: &str = "Camera"; } \ No newline at end of file diff --git a/src/render/render_graph_2/resource_provider.rs b/src/render/render_graph_2/resource_provider.rs index c2d9424ec3..09fc8839db 100644 --- a/src/render/render_graph_2/resource_provider.rs +++ b/src/render/render_graph_2/resource_provider.rs @@ -1,7 +1,9 @@ -use crate::render::{render_graph_2::Renderer, ActiveCamera, Camera}; +use crate::render::{ + render_graph_2::{resource_name, Renderer}, + ActiveCamera, Camera, +}; use bevy_transform::prelude::LocalToWorld; use legion::prelude::*; -use std::mem; use zerocopy::AsBytes; pub trait ResourceProvider { @@ -12,7 +14,7 @@ pub trait ResourceProvider { pub struct CameraResourceProvider; impl ResourceProvider for CameraResourceProvider { - fn update(&self, renderer: &mut dyn Renderer, world: &mut World) {} + fn update(&self, _renderer: &mut dyn Renderer, _world: &mut World) {} fn resize(&self, renderer: &mut dyn Renderer, world: &mut World, width: u32, height: u32) { for (mut camera, local_to_world, _) in <(Write, Read, Read)>::query().iter_mut(world) @@ -20,23 +22,12 @@ impl ResourceProvider for CameraResourceProvider { camera.update(width, height); let camera_matrix: [[f32; 4]; 4] = (camera.view_matrix * local_to_world.0).to_cols_array_2d(); - let matrix_size = mem::size_of::<[[f32; 4]; 4]>() as u64; // TODO: use staging buffer? - let buffer = renderer - .create_buffer_with_data(camera_matrix.as_bytes(), wgpu::BufferUsage::UNIFORM); - // let temp_camera_buffer = render_graph - // .device - // .create_buffer_with_data(camera_matrix.as_bytes(), wgpu::BufferUsage::COPY_SRC); - // let forward_uniform_buffer = render_graph - // .get_uniform_buffer(FORWARD_UNIFORM_BUFFER_NAME) - // .unwrap(); - // encoder.copy_buffer_to_buffer( - // &temp_camera_buffer, - // 0, - // &forward_uniform_buffer.buffer, - // 0, - // matrix_size, - // ); + renderer.create_buffer_with_data( + resource_name::uniform::CAMERA, + camera_matrix.as_bytes(), + wgpu::BufferUsage::UNIFORM, + ); } } } diff --git a/src/render/render_graph_2/shader.rs b/src/render/render_graph_2/shader.rs index 38c1e087a1..bc4653f14b 100644 --- a/src/render/render_graph_2/shader.rs +++ b/src/render/render_graph_2/shader.rs @@ -1,12 +1,9 @@ -use crate::prelude::*; use crate::{ - asset::Texture, legion::{ - borrow::{Ref, RefMap}, + borrow::RefMap, prelude::{Entity, World}, }, - render::render_graph_2::{UniformPropertyType, Binding, BindType}, - render::Albedo, + render::render_graph_2::{UniformPropertyType, BindType}, math::Vec4, }; use zerocopy::AsBytes; @@ -38,15 +35,16 @@ pub trait GetBytes { fn get_bytes_ref(&self) -> Option<&[u8]>; } -impl GetBytes for dyn AsBytes { - fn get_bytes(&self) -> Vec { - self.as_bytes().into() - } +// TODO: might need to add zerocopy to this crate to impl AsBytes for external crates +// impl GetBytes for dyn AsBytes { +// fn get_bytes(&self) -> Vec { +// self.as_bytes().into() +// } - fn get_bytes_ref(&self) -> Option<&[u8]> { - Some(self.as_bytes()) - } -} +// fn get_bytes_ref(&self) -> Option<&[u8]> { +// Some(self.as_bytes()) +// } +// } impl GetBytes for Vec4 { fn get_bytes(&self) -> Vec { diff --git a/src/render/render_graph_2/wgpu_renderer.rs b/src/render/render_graph_2/wgpu_renderer.rs index 71d8191aec..794fc5c80d 100644 --- a/src/render/render_graph_2/wgpu_renderer.rs +++ b/src/render/render_graph_2/wgpu_renderer.rs @@ -1,7 +1,7 @@ use crate::{ legion::prelude::*, render::render_graph_2::{ - resource_name, BindType, Buffer, PassDescriptor, PipelineDescriptor, RenderGraph, + resource_name, BindType, BufferInfo, PassDescriptor, PipelineDescriptor, RenderGraph, RenderPass, RenderPassColorAttachmentDescriptor, RenderPassDepthStencilAttachmentDescriptor, Renderer, TextureDimension, }, @@ -14,7 +14,7 @@ pub struct WgpuRenderer { pub surface: Option, pub swap_chain_descriptor: wgpu::SwapChainDescriptor, pub render_pipelines: HashMap, - pub buffers: HashMap, + pub buffers: HashMap>, pub textures: HashMap, } @@ -79,7 +79,7 @@ impl WgpuRenderer { .map(|(i, binding)| wgpu::BindGroupLayoutBinding { binding: i as u32, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, - ty: (&binding.bind_type).into() + ty: (&binding.bind_type).into(), }) .collect::>(); device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { @@ -252,8 +252,10 @@ impl Renderer for WgpuRenderer { let mut render_pass = WgpuRenderPass { render_pass: &mut render_pass, - renderer: &self, + renderer: self, + pipeline_descriptor, }; + for draw_target in pipeline_descriptor.draw_targets.iter() { draw_target(world, &mut render_pass); } @@ -265,46 +267,62 @@ impl Renderer for WgpuRenderer { let command_buffer = encoder.finish(); self.queue.submit(&[command_buffer]); } - fn create_buffer_with_data(&mut self, data: &[u8], buffer_usage: wgpu::BufferUsage) -> Buffer { + + fn create_buffer_with_data( + &mut self, + name: &str, + data: &[u8], + buffer_usage: wgpu::BufferUsage, + ) { let buffer = self.device.create_buffer_with_data(data, buffer_usage); - // TODO: FILL THIS IN - Buffer { - buffer_usage, - size: data.len() as u64, - id: 0, - } - } - fn free_buffer(&mut self, id: super::ResourceId) -> super::Buffer { - unimplemented!() + self.buffers.insert( + name.to_string(), + Buffer { + buffer, + buffer_info: BufferInfo { + buffer_usage, + size: data.len() as u64, + }, + }, + ); } - // fn load_mesh(&mut self, asset_id: usize, mesh: &Mesh) { - // if let None = mesh.vertex_buffer { - // self.buffers.insert( - // format!("meshv{}", asset_id), - // self.device - // .create_buffer_with_data(mesh.vertices.as_bytes(), wgpu::BufferUsage::VERTEX), - // ); - // } + fn get_buffer_info(&self, name: &str) -> Option<&BufferInfo> { + self.buffers.get(name).map(|b| &b.buffer_info) + } - // if let None = mesh.index_buffer { - // self.buffers.insert( - // format!("meshi{}", asset_id), - // self.device - // .create_buffer_with_data(mesh.indices.as_bytes(), wgpu::BufferUsage::INDEX), - // ); - // } - // } + fn remove_buffer(&mut self, name: &str) { + self.buffers.remove(name); + } } -pub struct WgpuRenderPass<'a, 'b, 'c> { +pub struct WgpuRenderPass<'a, 'b, 'c, 'd> { pub render_pass: &'b mut wgpu::RenderPass<'a>, - pub renderer: &'c WgpuRenderer, + pub pipeline_descriptor: &'c PipelineDescriptor, + pub renderer: &'d mut WgpuRenderer, } -impl<'a, 'b, 'c> RenderPass for WgpuRenderPass<'a, 'b, 'c> { - fn set_index_buffer(&mut self, buffer: &wgpu::Buffer, offset: wgpu::BufferAddress) { - self.render_pass.set_index_buffer(buffer, offset); +impl<'a, 'b, 'c, 'd> RenderPass for WgpuRenderPass<'a, 'b, 'c,'d> { + fn get_renderer(&mut self) -> &mut dyn Renderer { + self.renderer + } + + fn get_pipeline_descriptor(&self) -> &PipelineDescriptor { + self.pipeline_descriptor + } + + fn set_vertex_buffer(&mut self, start_slot: u32, name: &str, offset: u64) { + let buffer = self.renderer.buffers.get(name).unwrap(); + self.render_pass.set_vertex_buffers(start_slot, &[(&buffer.buffer, offset)]); + } + + fn set_index_buffer(&mut self, name: &str, offset: u64) { + let buffer = self.renderer.buffers.get(name).unwrap(); + self.render_pass.set_index_buffer(&buffer.buffer, offset); + } + + fn draw_indexed(&mut self, indices: core::ops::Range, base_vertex: i32, instances: core::ops::Range) { + self.render_pass.draw_indexed(indices, base_vertex, instances); } } @@ -324,12 +342,14 @@ impl From for wgpu::TextureViewDimension { impl From<&BindType> for wgpu::BindingType { fn from(bind_type: &BindType) -> Self { match bind_type { - BindType::Uniform { dynamic, properties: _ } => { - wgpu::BindingType::UniformBuffer { dynamic: *dynamic } - } - BindType::Buffer { dynamic, readonly } => { - wgpu::BindingType::StorageBuffer { dynamic: *dynamic, readonly: *readonly } - } + BindType::Uniform { + dynamic, + properties: _, + } => wgpu::BindingType::UniformBuffer { dynamic: *dynamic }, + BindType::Buffer { dynamic, readonly } => wgpu::BindingType::StorageBuffer { + dynamic: *dynamic, + readonly: *readonly, + }, BindType::SampledTexture { dimension, multisampled, @@ -338,10 +358,14 @@ impl From<&BindType> for wgpu::BindingType { multisampled: *multisampled, }, BindType::Sampler => wgpu::BindingType::Sampler, - BindType::StorageTexture { dimension } => { - wgpu::BindingType::StorageTexture { dimension: (*dimension).into() } + BindType::StorageTexture { dimension } => wgpu::BindingType::StorageTexture { + dimension: (*dimension).into(), }, } } +} -} \ No newline at end of file +pub struct Buffer { + pub buffer: T, + pub buffer_info: BufferInfo, +}