mirror of
https://github.com/bevyengine/bevy
synced 2024-11-24 21:53:07 +00:00
upgrade wgpu. work around new wgpu lifetimes (this was painful)
This commit is contained in:
parent
8beed27c0e
commit
85c880e754
13 changed files with 220 additions and 190 deletions
|
@ -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"
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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,
|
||||||
|
) {
|
||||||
|
}
|
||||||
|
}
|
|
@ -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::*;
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue