more renderer work

This commit is contained in:
Carter Anderson 2020-01-23 23:39:56 -08:00
parent 7b89531268
commit bcd7dae0ec
8 changed files with 126 additions and 90 deletions

View File

@ -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 // 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 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::<AssetStorage<Mesh>>().unwrap(); let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
let mut last_mesh_id = None; let mut last_mesh_id = None;
let mesh_query = let mesh_query =
@ -24,18 +28,27 @@ pub fn mesh_draw_target(world: &World, _render_pass: &mut dyn RenderPass) {
} }
if should_load_mesh { if should_load_mesh {
if let Some(_mesh_asset) = mesh_storage.get(mesh.id) { if let Some(mesh_asset) = mesh_storage.get(mesh.id) {
// render_pass.load_mesh(mesh.id, mesh_asset); let renderer = render_pass.get_renderer();
// render_pass.set_index_buffer(mesh_asset.index_buffer.as_ref().unwrap(), 0); renderer.create_buffer_with_data(MESH_VERTEX_BUFFER_NAME, mesh_asset.vertices.as_bytes(), wgpu::BufferUsage::VERTEX);
// render_pass.set_vertex_buffers(0, &[(&mesh_asset.vertex_buffer.as_ref().unwrap(), 0)]); 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.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); 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);
} }

View File

@ -3,6 +3,7 @@ use std::collections::HashMap;
pub struct RenderGraph { pub struct RenderGraph {
pub pipeline_descriptors: HashMap<String, PipelineDescriptor>, pub pipeline_descriptors: HashMap<String, PipelineDescriptor>,
// TODO: make this ordered
pub pass_descriptors: HashMap<String, PassDescriptor>, pub pass_descriptors: HashMap<String, PassDescriptor>,
pub pass_pipelines: HashMap<String, Vec<String>>, pub pass_pipelines: HashMap<String, Vec<String>>,
pub resource_providers: Vec<Box<dyn ResourceProvider>>, pub resource_providers: Vec<Box<dyn ResourceProvider>>,

View File

@ -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 { pub trait Renderer {
fn initialize(&mut self, world: &mut World); fn initialize(&mut self, world: &mut World);
fn resize(&mut self, world: &mut World, width: u32, height: u32); fn resize(&mut self, world: &mut World, width: u32, height: u32);
fn process_render_graph(&mut self, render_graph: &RenderGraph, world: &mut World); fn process_render_graph(&mut self, render_graph: &RenderGraph, world: &mut World);
// TODO: swap out wgpu::BufferUsage for custom type // TODO: swap out wgpu::BufferUsage for custom type
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);
fn free_buffer(&mut self, id: ResourceId) -> Buffer; fn remove_buffer(&mut self, name: &str);
fn get_buffer_info(&self, name: &str) -> Option<&BufferInfo>;
} }
pub trait RenderPass { 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<u32>, base_vertex: i32, instances: Range<u32>);
} }

View File

@ -1,7 +1,6 @@
pub type ResourceId = u64; // pub type ResourceId = u64;
pub struct Buffer { pub struct BufferInfo {
pub id: ResourceId,
pub size: u64, pub size: u64,
pub buffer_usage: wgpu::BufferUsage, pub buffer_usage: wgpu::BufferUsage,
// pub layout: Option< // pub layout: Option<

View File

@ -1,3 +1,7 @@
pub mod texture { pub mod texture {
pub const SWAP_CHAIN: &str = "SwapChain"; pub const SWAP_CHAIN: &str = "SwapChain";
} }
pub mod uniform {
pub const CAMERA: &str = "Camera";
}

View File

@ -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 bevy_transform::prelude::LocalToWorld;
use legion::prelude::*; use legion::prelude::*;
use std::mem;
use zerocopy::AsBytes; use zerocopy::AsBytes;
pub trait ResourceProvider { pub trait ResourceProvider {
@ -12,7 +14,7 @@ pub trait ResourceProvider {
pub struct CameraResourceProvider; pub struct CameraResourceProvider;
impl ResourceProvider for 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) { fn resize(&self, renderer: &mut dyn Renderer, world: &mut World, width: u32, height: u32) {
for (mut camera, local_to_world, _) in for (mut camera, local_to_world, _) in
<(Write<Camera>, Read<LocalToWorld>, Read<ActiveCamera>)>::query().iter_mut(world) <(Write<Camera>, Read<LocalToWorld>, Read<ActiveCamera>)>::query().iter_mut(world)
@ -20,23 +22,12 @@ impl ResourceProvider for CameraResourceProvider {
camera.update(width, height); camera.update(width, height);
let camera_matrix: [[f32; 4]; 4] = let camera_matrix: [[f32; 4]; 4] =
(camera.view_matrix * local_to_world.0).to_cols_array_2d(); (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? // TODO: use staging buffer?
let buffer = renderer renderer.create_buffer_with_data(
.create_buffer_with_data(camera_matrix.as_bytes(), wgpu::BufferUsage::UNIFORM); resource_name::uniform::CAMERA,
// let temp_camera_buffer = render_graph camera_matrix.as_bytes(),
// .device wgpu::BufferUsage::UNIFORM,
// .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,
// );
} }
} }
} }

View File

@ -1,12 +1,9 @@
use crate::prelude::*;
use crate::{ use crate::{
asset::Texture,
legion::{ legion::{
borrow::{Ref, RefMap}, borrow::RefMap,
prelude::{Entity, World}, prelude::{Entity, World},
}, },
render::render_graph_2::{UniformPropertyType, Binding, BindType}, render::render_graph_2::{UniformPropertyType, BindType},
render::Albedo,
math::Vec4, math::Vec4,
}; };
use zerocopy::AsBytes; use zerocopy::AsBytes;
@ -38,15 +35,16 @@ pub trait GetBytes {
fn get_bytes_ref(&self) -> Option<&[u8]>; fn get_bytes_ref(&self) -> Option<&[u8]>;
} }
impl GetBytes for dyn AsBytes { // TODO: might need to add zerocopy to this crate to impl AsBytes for external crates
fn get_bytes(&self) -> Vec<u8> { // impl GetBytes for dyn AsBytes {
self.as_bytes().into() // fn get_bytes(&self) -> Vec<u8> {
} // self.as_bytes().into()
// }
fn get_bytes_ref(&self) -> Option<&[u8]> { // fn get_bytes_ref(&self) -> Option<&[u8]> {
Some(self.as_bytes()) // Some(self.as_bytes())
} // }
} // }
impl GetBytes for Vec4 { impl GetBytes for Vec4 {
fn get_bytes(&self) -> Vec<u8> { fn get_bytes(&self) -> Vec<u8> {

View File

@ -1,7 +1,7 @@
use crate::{ use crate::{
legion::prelude::*, legion::prelude::*,
render::render_graph_2::{ render::render_graph_2::{
resource_name, BindType, Buffer, PassDescriptor, PipelineDescriptor, RenderGraph, resource_name, BindType, BufferInfo, PassDescriptor, PipelineDescriptor, RenderGraph,
RenderPass, RenderPassColorAttachmentDescriptor, RenderPass, RenderPassColorAttachmentDescriptor,
RenderPassDepthStencilAttachmentDescriptor, Renderer, TextureDimension, RenderPassDepthStencilAttachmentDescriptor, Renderer, TextureDimension,
}, },
@ -14,7 +14,7 @@ pub struct WgpuRenderer {
pub surface: Option<wgpu::Surface>, pub surface: Option<wgpu::Surface>,
pub swap_chain_descriptor: wgpu::SwapChainDescriptor, pub swap_chain_descriptor: wgpu::SwapChainDescriptor,
pub render_pipelines: HashMap<String, wgpu::RenderPipeline>, pub render_pipelines: HashMap<String, wgpu::RenderPipeline>,
pub buffers: HashMap<String, wgpu::Buffer>, pub buffers: HashMap<String, Buffer<wgpu::Buffer>>,
pub textures: HashMap<String, wgpu::TextureView>, pub textures: HashMap<String, wgpu::TextureView>,
} }
@ -79,7 +79,7 @@ impl WgpuRenderer {
.map(|(i, binding)| wgpu::BindGroupLayoutBinding { .map(|(i, binding)| wgpu::BindGroupLayoutBinding {
binding: i as u32, binding: i as u32,
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT, visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
ty: (&binding.bind_type).into() ty: (&binding.bind_type).into(),
}) })
.collect::<Vec<wgpu::BindGroupLayoutBinding>>(); .collect::<Vec<wgpu::BindGroupLayoutBinding>>();
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
@ -252,8 +252,10 @@ impl Renderer for WgpuRenderer {
let mut render_pass = WgpuRenderPass { let mut render_pass = WgpuRenderPass {
render_pass: &mut render_pass, render_pass: &mut render_pass,
renderer: &self, renderer: self,
pipeline_descriptor,
}; };
for draw_target in pipeline_descriptor.draw_targets.iter() { for draw_target in pipeline_descriptor.draw_targets.iter() {
draw_target(world, &mut render_pass); draw_target(world, &mut render_pass);
} }
@ -265,46 +267,62 @@ impl Renderer for WgpuRenderer {
let command_buffer = encoder.finish(); let command_buffer = encoder.finish();
self.queue.submit(&[command_buffer]); 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); let buffer = self.device.create_buffer_with_data(data, buffer_usage);
// TODO: FILL THIS IN self.buffers.insert(
name.to_string(),
Buffer { Buffer {
buffer,
buffer_info: BufferInfo {
buffer_usage, buffer_usage,
size: data.len() as u64, size: data.len() as u64,
id: 0, },
} },
} );
fn free_buffer(&mut self, id: super::ResourceId) -> super::Buffer {
unimplemented!()
} }
// fn load_mesh(&mut self, asset_id: usize, mesh: &Mesh) { fn get_buffer_info(&self, name: &str) -> Option<&BufferInfo> {
// if let None = mesh.vertex_buffer { self.buffers.get(name).map(|b| &b.buffer_info)
// self.buffers.insert( }
// format!("meshv{}", asset_id),
// self.device
// .create_buffer_with_data(mesh.vertices.as_bytes(), wgpu::BufferUsage::VERTEX),
// );
// }
// if let None = mesh.index_buffer { fn remove_buffer(&mut self, name: &str) {
// self.buffers.insert( self.buffers.remove(name);
// format!("meshi{}", asset_id), }
// self.device
// .create_buffer_with_data(mesh.indices.as_bytes(), wgpu::BufferUsage::INDEX),
// );
// }
// }
} }
pub struct WgpuRenderPass<'a, 'b, 'c> { pub struct WgpuRenderPass<'a, 'b, 'c, 'd> {
pub render_pass: &'b mut wgpu::RenderPass<'a>, 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> { impl<'a, 'b, 'c, 'd> RenderPass for WgpuRenderPass<'a, 'b, 'c,'d> {
fn set_index_buffer(&mut self, buffer: &wgpu::Buffer, offset: wgpu::BufferAddress) { fn get_renderer(&mut self) -> &mut dyn Renderer {
self.render_pass.set_index_buffer(buffer, offset); 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<u32>, base_vertex: i32, instances: core::ops::Range<u32>) {
self.render_pass.draw_indexed(indices, base_vertex, instances);
} }
} }
@ -324,12 +342,14 @@ impl From<TextureDimension> for wgpu::TextureViewDimension {
impl From<&BindType> for wgpu::BindingType { impl From<&BindType> for wgpu::BindingType {
fn from(bind_type: &BindType) -> Self { fn from(bind_type: &BindType) -> Self {
match bind_type { match bind_type {
BindType::Uniform { dynamic, properties: _ } => { BindType::Uniform {
wgpu::BindingType::UniformBuffer { dynamic: *dynamic } dynamic,
} properties: _,
BindType::Buffer { dynamic, readonly } => { } => wgpu::BindingType::UniformBuffer { dynamic: *dynamic },
wgpu::BindingType::StorageBuffer { dynamic: *dynamic, readonly: *readonly } BindType::Buffer { dynamic, readonly } => wgpu::BindingType::StorageBuffer {
} dynamic: *dynamic,
readonly: *readonly,
},
BindType::SampledTexture { BindType::SampledTexture {
dimension, dimension,
multisampled, multisampled,
@ -338,10 +358,14 @@ impl From<&BindType> for wgpu::BindingType {
multisampled: *multisampled, multisampled: *multisampled,
}, },
BindType::Sampler => wgpu::BindingType::Sampler, BindType::Sampler => wgpu::BindingType::Sampler,
BindType::StorageTexture { dimension } => { BindType::StorageTexture { dimension } => wgpu::BindingType::StorageTexture {
wgpu::BindingType::StorageTexture { dimension: (*dimension).into() } dimension: (*dimension).into(),
}, },
} }
} }
}
pub struct Buffer<T> {
pub buffer: T,
pub buffer_info: BufferInfo,
} }