upgrade wgpu. work around new wgpu lifetimes (this was painful)

This commit is contained in:
Carter Anderson 2020-03-05 00:44:53 -08:00
parent 8beed27c0e
commit 85c880e754
13 changed files with 220 additions and 190 deletions

View file

@ -7,7 +7,7 @@ edition = "2018"
[dependencies] [dependencies]
# Modified to use std::any::type_name instead of std::any::TypeId # Modified to use std::any::type_name instead of std::any::TypeId
legion = { path = "bevy_legion", features = ["serde-1"] } legion = { path = "bevy_legion", features = ["serde-1"] }
wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "4a0da16fe6764c4e1dc918a31cbd7467d404df51"} wgpu = { git = "https://github.com/gfx-rs/wgpu-rs.git", rev = "2374b8ec9ddbc058dd0237856fc30d33e6ff8f93"}
glam = "0.8.4" glam = "0.8.4"
winit = "0.21.0" winit = "0.21.0"
zerocopy = "0.2" zerocopy = "0.2"

View file

@ -150,6 +150,7 @@ impl AppBuilder {
.add_resource_provider(Box::new(Camera2dResourceProvider::default())) .add_resource_provider(Box::new(Camera2dResourceProvider::default()))
.add_resource_provider(Box::new(LightResourceProvider::new(10))) .add_resource_provider(Box::new(LightResourceProvider::new(10)))
.add_resource_provider(Box::new(UiResourceProvider::new())) .add_resource_provider(Box::new(UiResourceProvider::new()))
.add_resource_provider(Box::new(MeshResourceProvider::new()))
.add_resource_provider(Box::new(UniformResourceProvider::<StandardMaterial>::new())) .add_resource_provider(Box::new(UniformResourceProvider::<StandardMaterial>::new()))
.add_resource_provider(Box::new(UniformResourceProvider::<LocalToWorld>::new())) .add_resource_provider(Box::new(UniformResourceProvider::<LocalToWorld>::new()))
.add_forward_pass() .add_forward_pass()

View file

@ -1,25 +1,20 @@
use crate::{ use crate::{
asset::{AssetStorage, Handle, Mesh}, asset::{Handle, Mesh},
legion::prelude::*, legion::prelude::*,
render::render_graph::{PipelineDescriptor, RenderPass, Renderable, ShaderPipelineAssignments}, render::render_graph::{PipelineDescriptor, RenderPass, Renderable, ShaderPipelineAssignments, ResourceInfo},
}; };
use zerocopy::AsBytes;
pub fn assigned_meshes_draw_target( pub fn assigned_meshes_draw_target(
world: &World, world: &World,
render_pass: &mut dyn RenderPass, render_pass: &mut dyn RenderPass,
pipeline_handle: Handle<PipelineDescriptor>, pipeline_handle: Handle<PipelineDescriptor>,
) { ) {
let mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
let shader_pipeline_assignments = world let shader_pipeline_assignments = world
.resources .resources
.get_mut::<ShaderPipelineAssignments>() .get_mut::<ShaderPipelineAssignments>()
.unwrap(); .unwrap();
let mut current_mesh_id = None; let mut current_mesh_handle = None;
let mut current_mesh_vertex_buffer = None; let mut current_mesh_index_len = 0;
let mut current_mesh_index_buffer = None;
let mut current_mesh_index_length = 0;
let assigned_entities = shader_pipeline_assignments let assigned_entities = shader_pipeline_assignments
.assignments .assignments
@ -29,56 +24,30 @@ pub fn assigned_meshes_draw_target(
for entity in assigned_entities.iter() { for entity in assigned_entities.iter() {
// TODO: hopefully legion has better random access apis that are more like queries? // TODO: hopefully legion has better random access apis that are more like queries?
let renderable = world.get_component::<Renderable>(*entity).unwrap(); let renderable = world.get_component::<Renderable>(*entity).unwrap();
let mesh = world.get_component::<Handle<Mesh>>(*entity).unwrap(); let mesh = *world.get_component::<Handle<Mesh>>(*entity).unwrap();
if !renderable.is_visible { if !renderable.is_visible {
continue; continue;
} }
let mut should_load_mesh = current_mesh_id == None; let renderer = render_pass.get_renderer();
if let Some(current) = current_mesh_id { let render_resources = renderer.get_render_resources();
should_load_mesh = current != mesh.id; if current_mesh_handle != Some(mesh) {
} if let Some(vertex_buffer_resource) = render_resources.get_mesh_vertices_resource(mesh) {
let index_buffer_resource = render_resources.get_mesh_indices_resource(mesh).unwrap();
if should_load_mesh { match renderer.get_resource_info(index_buffer_resource).unwrap() {
if let Some(mesh_asset) = mesh_storage.get_id(mesh.id) { ResourceInfo::Buffer { size, ..} => current_mesh_index_len = (size / 2) as u32,
let renderer = render_pass.get_renderer(); _ => panic!("expected a buffer type"),
if let Some(buffer) = current_mesh_vertex_buffer {
renderer.remove_buffer(buffer);
} }
render_pass.set_index_buffer(index_buffer_resource, 0);
if let Some(buffer) = current_mesh_index_buffer { render_pass.set_vertex_buffer(0, vertex_buffer_resource, 0);
renderer.remove_buffer(buffer); }
} // TODO: Verify buffer format matches render pass
current_mesh_vertex_buffer = Some(renderer.create_buffer_with_data( current_mesh_handle = Some(mesh);
mesh_asset.vertices.as_bytes(),
wgpu::BufferUsage::VERTEX,
));
current_mesh_index_buffer = Some(renderer.create_buffer_with_data(
mesh_asset.indices.as_bytes(),
wgpu::BufferUsage::INDEX,
));
// TODO: Verify buffer format matches render pass
render_pass.set_index_buffer(current_mesh_index_buffer.unwrap(), 0);
render_pass.set_vertex_buffer(0, current_mesh_vertex_buffer.unwrap(), 0);
current_mesh_id = Some(mesh.id);
current_mesh_index_length = mesh_asset.indices.len() as u32;
};
} }
// TODO: validate bind group properties against shader uniform properties at least once // TODO: validate bind group properties against shader uniform properties at least once
render_pass.setup_bind_groups(Some(&entity)); render_pass.setup_bind_groups(Some(&entity));
render_pass.draw_indexed(0..current_mesh_index_length, 0, 0..1); render_pass.draw_indexed(0..current_mesh_index_len, 0, 0..1);
}
// cleanup buffers
let renderer = render_pass.get_renderer();
if let Some(buffer) = current_mesh_vertex_buffer {
renderer.remove_buffer(buffer);
}
if let Some(buffer) = current_mesh_index_buffer {
renderer.remove_buffer(buffer);
} }
} }
} }

View file

@ -1,24 +1,19 @@
use crate::{ use crate::{
asset::{AssetStorage, Handle, Mesh}, asset::{Handle, Mesh},
legion::prelude::*, legion::prelude::*,
render::{ render::{
render_graph::{PipelineDescriptor, RenderPass, Renderable}, render_graph::{PipelineDescriptor, RenderPass, Renderable, ResourceInfo},
Instanced, Instanced,
}, },
}; };
use zerocopy::AsBytes;
pub fn meshes_draw_target( pub fn meshes_draw_target(
world: &World, world: &World,
render_pass: &mut dyn RenderPass, render_pass: &mut dyn RenderPass,
_pipeline_handle: Handle<PipelineDescriptor>, _pipeline_handle: Handle<PipelineDescriptor>,
) { ) {
let mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap(); let mut current_mesh_handle = None;
let mut current_mesh_id = None; let mut current_mesh_index_len = 0;
let mut current_mesh_vertex_buffer = None;
let mut current_mesh_index_buffer = None;
let mut current_mesh_index_length = 0;
let mesh_query = let mesh_query =
<(Read<Handle<Mesh>>, Read<Renderable>)>::query().filter(!component::<Instanced>()); <(Read<Handle<Mesh>>, Read<Renderable>)>::query().filter(!component::<Instanced>());
@ -27,51 +22,26 @@ pub fn meshes_draw_target(
continue; continue;
} }
let mut should_load_mesh = current_mesh_id == None; let renderer = render_pass.get_renderer();
if let Some(current) = current_mesh_id { let render_resources = renderer.get_render_resources();
should_load_mesh = current != mesh.id; if current_mesh_handle != Some(*mesh) {
} if let Some(vertex_buffer_resource) = render_resources.get_mesh_vertices_resource(*mesh)
{
if should_load_mesh { let index_buffer_resource =
if let Some(mesh_asset) = mesh_storage.get_id(mesh.id) { render_resources.get_mesh_indices_resource(*mesh).unwrap();
let renderer = render_pass.get_renderer(); match renderer.get_resource_info(index_buffer_resource).unwrap() {
if let Some(buffer) = current_mesh_vertex_buffer { ResourceInfo::Buffer { size, .. } => current_mesh_index_len = (size / 2) as u32,
renderer.remove_buffer(buffer); _ => panic!("expected a buffer type"),
} }
render_pass.set_index_buffer(index_buffer_resource, 0);
if let Some(buffer) = current_mesh_index_buffer { render_pass.set_vertex_buffer(0, vertex_buffer_resource, 0);
renderer.remove_buffer(buffer); }
} // TODO: Verify buffer format matches render pass
current_mesh_vertex_buffer = Some(renderer.create_buffer_with_data( current_mesh_handle = Some(*mesh);
mesh_asset.vertices.as_bytes(),
wgpu::BufferUsage::VERTEX,
));
current_mesh_index_buffer = Some(renderer.create_buffer_with_data(
mesh_asset.indices.as_bytes(),
wgpu::BufferUsage::INDEX,
));
// TODO: Verify buffer format matches render pass
render_pass.set_index_buffer(current_mesh_index_buffer.unwrap(), 0);
render_pass.set_vertex_buffer(0, current_mesh_vertex_buffer.unwrap(), 0);
current_mesh_id = Some(mesh.id);
current_mesh_index_length = mesh_asset.indices.len() as u32;
};
} }
// TODO: validate bind group properties against shader uniform properties at least once // TODO: validate bind group properties against shader uniform properties at least once
render_pass.setup_bind_groups(Some(&entity)); render_pass.setup_bind_groups(Some(&entity));
render_pass.draw_indexed(0..current_mesh_index_length, 0, 0..1); render_pass.draw_indexed(0..current_mesh_index_len, 0, 0..1);
}
// cleanup buffers
let renderer = render_pass.get_renderer();
if let Some(buffer) = current_mesh_vertex_buffer {
renderer.remove_buffer(buffer);
}
if let Some(buffer) = current_mesh_index_buffer {
renderer.remove_buffer(buffer);
} }
} }

View file

@ -11,66 +11,67 @@ pub fn ui_draw_target(
render_pass: &mut dyn RenderPass, render_pass: &mut dyn RenderPass,
_pipeline_handle: Handle<PipelineDescriptor>, _pipeline_handle: Handle<PipelineDescriptor>,
) { ) {
let mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap(); // TODO: re-add support for this
let mut current_mesh_vertex_buffer = None; // let mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
let mut current_mesh_index_buffer = None; // let mut current_mesh_vertex_buffer = None;
let ui_instances_buffer = { // let mut current_mesh_index_buffer = None;
let renderer = render_pass.get_renderer(); // let ui_instances_buffer = {
match renderer.get_render_resources().get_named_resource(resource_name::buffer::UI_INSTANCES) { // let renderer = render_pass.get_renderer();
Some(buffer) => buffer, // match renderer.get_render_resources().get_named_resource(resource_name::buffer::UI_INSTANCES) {
None => return, // Some(buffer) => buffer,
} // None => return,
}; // }
// NOTE: this is ugly and borrowing is stupid // };
let result = { // // NOTE: this is ugly and borrowing is stupid
let renderer = render_pass.get_renderer(); // let result = {
let result = if let Some(ResourceInfo::InstanceBuffer { count, mesh_id, .. }) = // let renderer = render_pass.get_renderer();
renderer.get_resource_info(ui_instances_buffer) // let result = if let Some(ResourceInfo::InstanceBuffer { count, mesh_id, .. }) =
{ // renderer.get_resource_info(ui_instances_buffer)
Some((*count, *mesh_id)) // {
} else { // Some((*count, *mesh_id))
None // } else {
}; // None
// };
if let Some((instance_count, mesh_id)) = result { // if let Some((instance_count, mesh_id)) = result {
if let Some(mesh_asset) = mesh_storage.get_id(mesh_id) { // if let Some(mesh_asset) = mesh_storage.get_id(mesh_id) {
if let Some(buffer) = current_mesh_vertex_buffer { // if let Some(buffer) = current_mesh_vertex_buffer {
renderer.remove_buffer(buffer); // renderer.remove_buffer(buffer);
} // }
if let Some(buffer) = current_mesh_index_buffer { // if let Some(buffer) = current_mesh_index_buffer {
renderer.remove_buffer(buffer); // renderer.remove_buffer(buffer);
} // }
current_mesh_vertex_buffer = Some(renderer.create_buffer_with_data( // current_mesh_vertex_buffer = Some(renderer.create_buffer_with_data(
mesh_asset.vertices.as_bytes(), // mesh_asset.vertices.as_bytes(),
wgpu::BufferUsage::VERTEX, // wgpu::BufferUsage::VERTEX,
)); // ));
current_mesh_index_buffer = Some(renderer.create_buffer_with_data( // current_mesh_index_buffer = Some(renderer.create_buffer_with_data(
mesh_asset.indices.as_bytes(), // mesh_asset.indices.as_bytes(),
wgpu::BufferUsage::INDEX, // wgpu::BufferUsage::INDEX,
)); // ));
Some((instance_count, mesh_asset.indices.len())) // Some((instance_count, mesh_asset.indices.len()))
} else { // } else {
None // None
} // }
} else { // } else {
None // None
} // }
}; // };
if let Some((instance_count, indices_length)) = result { // if let Some((instance_count, indices_length)) = result {
render_pass.setup_bind_groups(None); // render_pass.setup_bind_groups(None);
render_pass.set_index_buffer(current_mesh_index_buffer.unwrap(), 0); // render_pass.set_index_buffer(current_mesh_index_buffer.unwrap(), 0);
render_pass.set_vertex_buffer(0, current_mesh_vertex_buffer.unwrap(), 0); // render_pass.set_vertex_buffer(0, current_mesh_vertex_buffer.unwrap(), 0);
render_pass.set_vertex_buffer(1, ui_instances_buffer, 0); // render_pass.set_vertex_buffer(1, ui_instances_buffer, 0);
render_pass.draw_indexed(0..indices_length as u32, 0, 0..(instance_count as u32)); // render_pass.draw_indexed(0..indices_length as u32, 0, 0..(instance_count as u32));
} // }
let renderer = render_pass.get_renderer(); // let renderer = render_pass.get_renderer();
if let Some(buffer) = current_mesh_vertex_buffer { // if let Some(buffer) = current_mesh_vertex_buffer {
renderer.remove_buffer(buffer); // renderer.remove_buffer(buffer);
} // }
if let Some(buffer) = current_mesh_index_buffer { // if let Some(buffer) = current_mesh_index_buffer {
renderer.remove_buffer(buffer); // renderer.remove_buffer(buffer);
} // }
} }

View file

@ -1,4 +1,4 @@
use crate::asset::{Handle, Texture}; use crate::asset::{Handle, Texture, Mesh};
use std::collections::HashMap; use std::collections::HashMap;
#[derive(Copy, Clone, Hash, Debug, Eq, PartialEq)] #[derive(Copy, Clone, Hash, Debug, Eq, PartialEq)]
@ -11,6 +11,8 @@ pub struct RenderResources {
pub name_to_resource: HashMap<String, RenderResource>, pub name_to_resource: HashMap<String, RenderResource>,
pub texture_to_resource: HashMap<Handle<Texture>, RenderResource>, pub texture_to_resource: HashMap<Handle<Texture>, RenderResource>,
pub texture_to_sampler_resource: HashMap<Handle<Texture>, RenderResource>, pub texture_to_sampler_resource: HashMap<Handle<Texture>, RenderResource>,
pub mesh_to_vertices_resource: HashMap<Handle<Mesh>, RenderResource>,
pub mesh_to_indices_resource: HashMap<Handle<Mesh>, RenderResource>,
pub resource_index: u64, pub resource_index: u64,
} }
@ -31,6 +33,22 @@ impl RenderResources {
self.texture_to_resource.get(&texture).cloned() self.texture_to_resource.get(&texture).cloned()
} }
pub fn set_mesh_vertices_resource(&mut self, mesh: Handle<Mesh>, resource: RenderResource) {
self.mesh_to_vertices_resource.insert(mesh, resource);
}
pub fn get_mesh_vertices_resource(&self, mesh: Handle<Mesh>) -> Option<RenderResource> {
self.mesh_to_vertices_resource.get(&mesh).cloned()
}
pub fn set_mesh_indices_resource(&mut self, mesh: Handle<Mesh>, resource: RenderResource) {
self.mesh_to_indices_resource.insert(mesh, resource);
}
pub fn get_mesh_indices_resource(&self, mesh: Handle<Mesh>) -> Option<RenderResource> {
self.mesh_to_indices_resource.get(&mesh).cloned()
}
pub fn set_texture_sampler_resource(&mut self, texture: Handle<Texture>, resource: RenderResource) { pub fn set_texture_sampler_resource(&mut self, texture: Handle<Texture>, resource: RenderResource) {
self.texture_to_sampler_resource.insert(texture, resource); self.texture_to_sampler_resource.insert(texture, resource);
} }

View file

@ -86,7 +86,7 @@ pub trait Renderer {
pub trait RenderPass { pub trait RenderPass {
// TODO: consider using static dispatch for the renderer: Renderer<WgpuBackend>. compare compile times // TODO: consider using static dispatch for the renderer: Renderer<WgpuBackend>. compare compile times
fn get_renderer(&mut self) -> &mut dyn Renderer; fn get_renderer(&mut self) -> &dyn Renderer;
fn get_pipeline_descriptor(&self) -> &PipelineDescriptor; fn get_pipeline_descriptor(&self) -> &PipelineDescriptor;
fn set_index_buffer(&mut self, resource: RenderResource, offset: u64); fn set_index_buffer(&mut self, resource: RenderResource, offset: u64);
fn set_vertex_buffer(&mut self, start_slot: u32, resource: RenderResource, offset: u64); fn set_vertex_buffer(&mut self, start_slot: u32, resource: RenderResource, offset: u64);

View file

@ -18,7 +18,6 @@ pub struct WgpuResources {
pub buffers: HashMap<RenderResource, wgpu::Buffer>, pub buffers: HashMap<RenderResource, wgpu::Buffer>,
pub textures: HashMap<RenderResource, wgpu::TextureView>, pub textures: HashMap<RenderResource, wgpu::TextureView>,
pub samplers: HashMap<RenderResource, wgpu::Sampler>, pub samplers: HashMap<RenderResource, wgpu::Sampler>,
pub render_pipelines: HashMap<Handle<PipelineDescriptor>, wgpu::RenderPipeline>,
pub resource_info: HashMap<RenderResource, ResourceInfo>, pub resource_info: HashMap<RenderResource, ResourceInfo>,
pub bind_groups: HashMap<u64, BindGroupInfo>, pub bind_groups: HashMap<u64, BindGroupInfo>,
pub bind_group_layouts: HashMap<u64, wgpu::BindGroupLayout>, pub bind_group_layouts: HashMap<u64, wgpu::BindGroupLayout>,
@ -32,7 +31,6 @@ pub struct WgpuResources {
impl WgpuResources { impl WgpuResources {
pub fn new() -> Self { pub fn new() -> Self {
WgpuResources { WgpuResources {
render_pipelines: HashMap::new(),
buffers: HashMap::new(), buffers: HashMap::new(),
textures: HashMap::new(), textures: HashMap::new(),
samplers: HashMap::new(), samplers: HashMap::new(),
@ -455,6 +453,7 @@ pub struct WgpuRenderer {
pub surface: Option<wgpu::Surface>, pub surface: Option<wgpu::Surface>,
pub encoder: Option<wgpu::CommandEncoder>, pub encoder: Option<wgpu::CommandEncoder>,
pub swap_chain_descriptor: wgpu::SwapChainDescriptor, pub swap_chain_descriptor: wgpu::SwapChainDescriptor,
pub render_pipelines: HashMap<Handle<PipelineDescriptor>, wgpu::RenderPipeline>,
pub wgpu_resources: WgpuResources, pub wgpu_resources: WgpuResources,
} }
@ -490,6 +489,7 @@ impl WgpuRenderer {
encoder: None, encoder: None,
swap_chain_descriptor, swap_chain_descriptor,
wgpu_resources: WgpuResources::new(), wgpu_resources: WgpuResources::new(),
render_pipelines: HashMap::new(),
} }
} }
@ -620,7 +620,7 @@ impl WgpuRenderer {
} }
pub fn create_render_pass<'a>( pub fn create_render_pass<'a>(
wgpu_resources: &WgpuResources, wgpu_resources: &'a WgpuResources,
pass_descriptor: &PassDescriptor, pass_descriptor: &PassDescriptor,
encoder: &'a mut wgpu::CommandEncoder, encoder: &'a mut wgpu::CommandEncoder,
frame: &'a wgpu::SwapChainOutput, frame: &'a wgpu::SwapChainOutput,
@ -686,7 +686,7 @@ impl WgpuRenderer {
wgpu_resources: &'a WgpuResources, wgpu_resources: &'a WgpuResources,
depth_stencil_attachment_descriptor: &RenderPassDepthStencilAttachmentDescriptor, depth_stencil_attachment_descriptor: &RenderPassDepthStencilAttachmentDescriptor,
frame: &'a wgpu::SwapChainOutput, frame: &'a wgpu::SwapChainOutput,
) -> wgpu::RenderPassDepthStencilAttachmentDescriptor<&'a wgpu::TextureView> { ) -> wgpu::RenderPassDepthStencilAttachmentDescriptor<'a> {
let attachment = match depth_stencil_attachment_descriptor.attachment.as_str() { let attachment = match depth_stencil_attachment_descriptor.attachment.as_str() {
resource_name::texture::SWAP_CHAIN => &frame.view, resource_name::texture::SWAP_CHAIN => &frame.view,
_ => { _ => {
@ -828,7 +828,6 @@ impl Renderer for WgpuRenderer {
.unwrap(); .unwrap();
// create pipelines // create pipelines
if !self if !self
.wgpu_resources
.render_pipelines .render_pipelines
.contains_key(pipeline_descriptor_handle) .contains_key(pipeline_descriptor_handle)
{ {
@ -849,7 +848,7 @@ impl Renderer for WgpuRenderer {
vertex_shader, vertex_shader,
fragment_shader, fragment_shader,
); );
self.wgpu_resources.render_pipelines self.render_pipelines
.insert(*pipeline_descriptor_handle, render_pipeline); .insert(*pipeline_descriptor_handle, render_pipeline);
} }
@ -862,22 +861,23 @@ impl Renderer for WgpuRenderer {
for (pass_name, pass_descriptor) in render_graph.pass_descriptors.iter() { for (pass_name, pass_descriptor) in render_graph.pass_descriptors.iter() {
// run passes // run passes
let mut render_pass = Self::create_render_pass(&mut self.wgpu_resources, pass_descriptor, &mut encoder, &frame); let mut render_pass = Self::create_render_pass(&self.wgpu_resources, pass_descriptor, &mut encoder, &frame);
if let Some(pass_pipelines) = render_graph.pass_pipelines.get(pass_name) { if let Some(pass_pipelines) = render_graph.pass_pipelines.get(pass_name) {
for pass_pipeline in pass_pipelines.iter() { for pass_pipeline in pass_pipelines.iter() {
let pipeline_descriptor = pipeline_storage.get(pass_pipeline).unwrap(); let pipeline_descriptor = pipeline_storage.get(pass_pipeline).unwrap();
let render_pipeline = self.wgpu_resources.render_pipelines.get(pass_pipeline).unwrap(); let render_pipeline = self.render_pipelines.get(pass_pipeline).unwrap();
render_pass.set_pipeline(render_pipeline); render_pass.set_pipeline(render_pipeline);
let mut render_pass = WgpuRenderPass { let mut wgpu_render_pass = WgpuRenderPass {
render_pass: &mut render_pass, render_pass: &mut render_pass,
renderer: self,
pipeline_descriptor, pipeline_descriptor,
wgpu_resources: &self.wgpu_resources,
renderer: &self
}; };
for draw_target_name in pipeline_descriptor.draw_targets.iter() { for draw_target_name in pipeline_descriptor.draw_targets.iter() {
let draw_target = render_graph.draw_targets.get(draw_target_name).unwrap(); let draw_target = render_graph.draw_targets.get(draw_target_name).unwrap();
draw_target(world, &mut render_pass, pass_pipeline.clone()); draw_target(world, &mut wgpu_render_pass, *pass_pipeline);
} }
} }
} }
@ -1018,11 +1018,12 @@ impl Renderer for WgpuRenderer {
pub struct WgpuRenderPass<'a, 'b, 'c, 'd> { pub struct WgpuRenderPass<'a, 'b, 'c, 'd> {
pub render_pass: &'b mut wgpu::RenderPass<'a>, pub render_pass: &'b mut wgpu::RenderPass<'a>,
pub pipeline_descriptor: &'c PipelineDescriptor, pub pipeline_descriptor: &'c PipelineDescriptor,
pub renderer: &'d mut WgpuRenderer, pub wgpu_resources: &'a WgpuResources,
pub renderer: &'d WgpuRenderer,
} }
impl<'a, 'b, 'c, 'd> RenderPass for WgpuRenderPass<'a, 'b, 'c, 'd> { impl<'a, 'b, 'c, 'd> RenderPass for WgpuRenderPass<'a, 'b, 'c, 'd> {
fn get_renderer(&mut self) -> &mut dyn Renderer { fn get_renderer(&mut self) -> &dyn Renderer {
self.renderer self.renderer
} }
@ -1031,13 +1032,13 @@ impl<'a, 'b, 'c, 'd> RenderPass for WgpuRenderPass<'a, 'b, 'c, 'd> {
} }
fn set_vertex_buffer(&mut self, start_slot: u32, resource: RenderResource, offset: u64) { fn set_vertex_buffer(&mut self, start_slot: u32, resource: RenderResource, offset: u64) {
let buffer = self.renderer.wgpu_resources.buffers.get(&resource).unwrap(); let buffer = self.wgpu_resources.buffers.get(&resource).unwrap();
self.render_pass self.render_pass
.set_vertex_buffers(start_slot, &[(&buffer, offset)]); .set_vertex_buffers(start_slot, &[(&buffer, offset)]);
} }
fn set_index_buffer(&mut self, resource: RenderResource, offset: u64) { fn set_index_buffer(&mut self, resource: RenderResource, offset: u64) {
let buffer = self.renderer.wgpu_resources.buffers.get(&resource).unwrap(); let buffer = self.wgpu_resources.buffers.get(&resource).unwrap();
self.render_pass.set_index_buffer(&buffer, offset); self.render_pass.set_index_buffer(&buffer, offset);
} }
@ -1055,17 +1056,18 @@ impl<'a, 'b, 'c, 'd> RenderPass for WgpuRenderPass<'a, 'b, 'c, 'd> {
let pipeline_layout = self.pipeline_descriptor.get_layout().unwrap(); let pipeline_layout = self.pipeline_descriptor.get_layout().unwrap();
for bind_group in pipeline_layout.bind_groups.iter() { for bind_group in pipeline_layout.bind_groups.iter() {
let bind_group_id = bind_group.get_hash().unwrap(); let bind_group_id = bind_group.get_hash().unwrap();
let bind_group_info = match self.renderer.wgpu_resources.bind_groups.get(&bind_group_id) { let bind_group_info = match self.wgpu_resources.bind_groups.get(&bind_group_id) {
// if there is a "global" bind group, use that // if there is a "global" bind group, use that
Some(bind_group_info) => bind_group_info, Some(bind_group_info) => bind_group_info,
// otherwise try to get an entity-specific bind group // otherwise try to get an entity-specific bind group
None => { None => {
if let Some(entity) = entity { if let Some(entity) = entity {
if let None = self.renderer.wgpu_resources.get_entity_bind_group(*entity, bind_group_id) { if let None = self.wgpu_resources.get_entity_bind_group(*entity, bind_group_id) {
self.renderer.wgpu_resources.create_entity_bind_group(&self.renderer.device, bind_group, *entity); // TODO: Uncomment this
// self.wgpu_resources.create_entity_bind_group(&self.renderer.device, bind_group, *entity);
} }
self.renderer.wgpu_resources self.wgpu_resources
.get_entity_bind_group(*entity, bind_group_id) .get_entity_bind_group(*entity, bind_group_id)
.unwrap() .unwrap()
} else { } else {
@ -1082,14 +1084,13 @@ impl<'a, 'b, 'c, 'd> RenderPass for WgpuRenderPass<'a, 'b, 'c, 'd> {
} }
if let Some(resource) = self if let Some(resource) = self
.renderer
.wgpu_resources .wgpu_resources
.render_resources .render_resources
.get_named_resource(&binding.name) .get_named_resource(&binding.name)
{ {
// PERF: This hashmap get is pretty expensive (10 fps for 10000 entities) // PERF: This hashmap get is pretty expensive (10 fps for 10000 entities)
if let Some(dynamic_uniform_buffer_info) = if let Some(dynamic_uniform_buffer_info) =
self.renderer.wgpu_resources.dynamic_uniform_buffer_info.get(&resource) self.wgpu_resources.dynamic_uniform_buffer_info.get(&resource)
{ {
let index = dynamic_uniform_buffer_info let index = dynamic_uniform_buffer_info
.offsets .offsets

View file

@ -1,8 +1,4 @@
pub enum ResourceInfo { pub enum ResourceInfo {
BufferMapped {
size: u64,
buffer_usage: wgpu::BufferUsage,
},
Buffer { Buffer {
size: u64, size: u64,
buffer_usage: wgpu::BufferUsage, buffer_usage: wgpu::BufferUsage,

View file

@ -0,0 +1,72 @@
use crate::{
asset::{AssetStorage, Handle, Mesh},
prelude::Renderable,
render::render_graph::{Renderer, ResourceProvider},
};
use legion::{filter::*, prelude::*};
use zerocopy::AsBytes;
pub struct MeshResourceProvider {
pub mesh_query: Query<
(Read<Handle<Mesh>>, Read<Renderable>),
EntityFilterTuple<
And<(
ComponentFilter<Handle<Mesh>>,
ComponentFilter<Renderable>,
ComponentFilter<Handle<Mesh>>,
)>,
And<(Passthrough, Passthrough)>,
And<(
Passthrough,
Passthrough,
ComponentChangedFilter<Handle<Mesh>>,
)>,
>,
>,
}
impl MeshResourceProvider {
pub fn new() -> Self {
MeshResourceProvider {
mesh_query: <(Read<Handle<Mesh>>, Read<Renderable>)>::query()
.filter(changed::<Handle<Mesh>>()),
}
}
}
impl ResourceProvider for MeshResourceProvider {
fn initialize(&mut self, _renderer: &mut dyn Renderer, _world: &mut World) {}
fn update(&mut self, renderer: &mut dyn Renderer, world: &mut World) {
let mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
for (mesh_handle, _renderable) in self.mesh_query.iter(world) {
if let None = renderer
.get_render_resources()
.get_mesh_vertices_resource(*mesh_handle)
{
let mesh_asset = mesh_storage.get(&mesh_handle).unwrap();
let vertex_buffer = renderer.create_buffer_with_data(
mesh_asset.vertices.as_bytes(),
wgpu::BufferUsage::VERTEX,
);
let index_buffer = renderer.create_buffer_with_data(
mesh_asset.indices.as_bytes(),
wgpu::BufferUsage::INDEX,
);
let render_resources = renderer.get_render_resources_mut();
render_resources.set_mesh_vertices_resource(*mesh_handle, vertex_buffer);
render_resources.set_mesh_indices_resource(*mesh_handle, index_buffer);
}
}
}
fn resize(
&mut self,
_renderer: &mut dyn Renderer,
_world: &mut World,
_width: u32,
_height: u32,
) {
}
}

View file

@ -4,6 +4,7 @@ mod frame_texture_resource_provider;
mod light_resource_provider; mod light_resource_provider;
mod ui_resource_provider; mod ui_resource_provider;
mod uniform_resource_provider; mod uniform_resource_provider;
mod mesh_resource_provider;
pub use camera2d_resource_provider::*; pub use camera2d_resource_provider::*;
pub use camera_resource_provider::*; pub use camera_resource_provider::*;
@ -11,3 +12,4 @@ pub use frame_texture_resource_provider::*;
pub use light_resource_provider::*; pub use light_resource_provider::*;
pub use ui_resource_provider::*; pub use ui_resource_provider::*;
pub use uniform_resource_provider::*; pub use uniform_resource_provider::*;
pub use mesh_resource_provider::*;

View file

@ -63,7 +63,7 @@ where
.insert(uniform_info.name.to_string(), (None, 0, HashSet::new())); .insert(uniform_info.name.to_string(), (None, 0, HashSet::new()));
} }
let (resource, counts, entities) = self.uniform_buffer_info_resources.get_mut(uniform_info.name).unwrap(); let (_resource, counts, entities) = self.uniform_buffer_info_resources.get_mut(uniform_info.name).unwrap();
entities.insert(entity); entities.insert(entity);
*counts += 1; *counts += 1;
} }
@ -112,7 +112,7 @@ where
} }
// allocate uniform buffers // allocate uniform buffers
for (name, (resource, count, entities)) in self.uniform_buffer_info_resources.iter_mut() { for (name, (resource, count, _entities)) in self.uniform_buffer_info_resources.iter_mut() {
let count = *count as u64; let count = *count as u64;
if let Some(resource) = resource { if let Some(resource) = resource {
let mut info = renderer let mut info = renderer
@ -158,7 +158,7 @@ where
// TODO: check if index has changed. if it has, then entity should be updated // TODO: check if index has changed. if it has, then entity should be updated
// TODO: only mem-map entities if their data has changed // TODO: only mem-map entities if their data has changed
// PERF: These hashmap inserts are pretty expensive (10 fps for 10000 entities) // PERF: These hashmap inserts are pretty expensive (10 fps for 10000 entities)
info.offsets.insert(entity, offset as u64); info.offsets.insert(entity, offset as u32);
// TODO: try getting ref first // TODO: try getting ref first
offset += alignment; offset += alignment;
} }

View file

@ -171,7 +171,7 @@ pub struct UniformInfo<'a> {
} }
pub struct DynamicUniformBufferInfo { pub struct DynamicUniformBufferInfo {
pub offsets: HashMap<Entity, u64>, pub offsets: HashMap<Entity, u32>,
pub capacity: u64, pub capacity: u64,
pub count: u64, pub count: u64,
} }