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
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 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);
}

View file

@ -3,6 +3,7 @@ use std::collections::HashMap;
pub struct RenderGraph {
pub pipeline_descriptors: HashMap<String, PipelineDescriptor>,
// TODO: make this ordered
pub pass_descriptors: HashMap<String, PassDescriptor>,
pub pass_pipelines: HashMap<String, Vec<String>>,
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 {
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<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 id: ResourceId,
pub struct BufferInfo {
pub size: u64,
pub buffer_usage: wgpu::BufferUsage,
// pub layout: Option<

View file

@ -1,3 +1,7 @@
pub mod texture {
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 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<Camera>, Read<LocalToWorld>, Read<ActiveCamera>)>::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,
);
}
}
}

View file

@ -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<u8> {
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<u8> {
// 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<u8> {

View file

@ -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<wgpu::Surface>,
pub swap_chain_descriptor: wgpu::SwapChainDescriptor,
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>,
}
@ -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::<Vec<wgpu::BindGroupLayoutBinding>>();
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<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 {
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(),
},
}
}
}
}
pub struct Buffer<T> {
pub buffer: T,
pub buffer_info: BufferInfo,
}