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]
|
||||
# Modified to use std::any::type_name instead of std::any::TypeId
|
||||
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"
|
||||
winit = "0.21.0"
|
||||
zerocopy = "0.2"
|
||||
|
|
|
@ -150,6 +150,7 @@ impl AppBuilder {
|
|||
.add_resource_provider(Box::new(Camera2dResourceProvider::default()))
|
||||
.add_resource_provider(Box::new(LightResourceProvider::new(10)))
|
||||
.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::<LocalToWorld>::new()))
|
||||
.add_forward_pass()
|
||||
|
|
|
@ -1,25 +1,20 @@
|
|||
use crate::{
|
||||
asset::{AssetStorage, Handle, Mesh},
|
||||
asset::{Handle, Mesh},
|
||||
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(
|
||||
world: &World,
|
||||
render_pass: &mut dyn RenderPass,
|
||||
pipeline_handle: Handle<PipelineDescriptor>,
|
||||
) {
|
||||
let mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
|
||||
let shader_pipeline_assignments = world
|
||||
.resources
|
||||
.get_mut::<ShaderPipelineAssignments>()
|
||||
.unwrap();
|
||||
let mut current_mesh_id = None;
|
||||
let mut current_mesh_vertex_buffer = None;
|
||||
let mut current_mesh_index_buffer = None;
|
||||
let mut current_mesh_index_length = 0;
|
||||
let mut current_mesh_handle = None;
|
||||
let mut current_mesh_index_len = 0;
|
||||
|
||||
let assigned_entities = shader_pipeline_assignments
|
||||
.assignments
|
||||
|
@ -29,56 +24,30 @@ pub fn assigned_meshes_draw_target(
|
|||
for entity in assigned_entities.iter() {
|
||||
// TODO: hopefully legion has better random access apis that are more like queries?
|
||||
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 {
|
||||
continue;
|
||||
}
|
||||
|
||||
let mut should_load_mesh = current_mesh_id == None;
|
||||
if let Some(current) = current_mesh_id {
|
||||
should_load_mesh = current != mesh.id;
|
||||
}
|
||||
|
||||
if should_load_mesh {
|
||||
if let Some(mesh_asset) = mesh_storage.get_id(mesh.id) {
|
||||
let renderer = render_pass.get_renderer();
|
||||
if let Some(buffer) = current_mesh_vertex_buffer {
|
||||
renderer.remove_buffer(buffer);
|
||||
let renderer = render_pass.get_renderer();
|
||||
let render_resources = renderer.get_render_resources();
|
||||
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();
|
||||
match renderer.get_resource_info(index_buffer_resource).unwrap() {
|
||||
ResourceInfo::Buffer { size, ..} => current_mesh_index_len = (size / 2) as u32,
|
||||
_ => panic!("expected a buffer type"),
|
||||
}
|
||||
|
||||
if let Some(buffer) = current_mesh_index_buffer {
|
||||
renderer.remove_buffer(buffer);
|
||||
}
|
||||
current_mesh_vertex_buffer = Some(renderer.create_buffer_with_data(
|
||||
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;
|
||||
};
|
||||
render_pass.set_index_buffer(index_buffer_resource, 0);
|
||||
render_pass.set_vertex_buffer(0, vertex_buffer_resource, 0);
|
||||
}
|
||||
// TODO: Verify buffer format matches render pass
|
||||
current_mesh_handle = Some(mesh);
|
||||
}
|
||||
|
||||
// TODO: validate bind group properties against shader uniform properties at least once
|
||||
render_pass.setup_bind_groups(Some(&entity));
|
||||
render_pass.draw_indexed(0..current_mesh_index_length, 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);
|
||||
render_pass.draw_indexed(0..current_mesh_index_len, 0, 0..1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,24 +1,19 @@
|
|||
use crate::{
|
||||
asset::{AssetStorage, Handle, Mesh},
|
||||
asset::{Handle, Mesh},
|
||||
legion::prelude::*,
|
||||
render::{
|
||||
render_graph::{PipelineDescriptor, RenderPass, Renderable},
|
||||
render_graph::{PipelineDescriptor, RenderPass, Renderable, ResourceInfo},
|
||||
Instanced,
|
||||
},
|
||||
};
|
||||
|
||||
use zerocopy::AsBytes;
|
||||
|
||||
pub fn meshes_draw_target(
|
||||
world: &World,
|
||||
render_pass: &mut dyn RenderPass,
|
||||
_pipeline_handle: Handle<PipelineDescriptor>,
|
||||
) {
|
||||
let mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
|
||||
let mut current_mesh_id = None;
|
||||
let mut current_mesh_vertex_buffer = None;
|
||||
let mut current_mesh_index_buffer = None;
|
||||
let mut current_mesh_index_length = 0;
|
||||
let mut current_mesh_handle = None;
|
||||
let mut current_mesh_index_len = 0;
|
||||
let mesh_query =
|
||||
<(Read<Handle<Mesh>>, Read<Renderable>)>::query().filter(!component::<Instanced>());
|
||||
|
||||
|
@ -27,51 +22,26 @@ pub fn meshes_draw_target(
|
|||
continue;
|
||||
}
|
||||
|
||||
let mut should_load_mesh = current_mesh_id == None;
|
||||
if let Some(current) = current_mesh_id {
|
||||
should_load_mesh = current != mesh.id;
|
||||
}
|
||||
|
||||
if should_load_mesh {
|
||||
if let Some(mesh_asset) = mesh_storage.get_id(mesh.id) {
|
||||
let renderer = render_pass.get_renderer();
|
||||
if let Some(buffer) = current_mesh_vertex_buffer {
|
||||
renderer.remove_buffer(buffer);
|
||||
let renderer = render_pass.get_renderer();
|
||||
let render_resources = renderer.get_render_resources();
|
||||
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();
|
||||
match renderer.get_resource_info(index_buffer_resource).unwrap() {
|
||||
ResourceInfo::Buffer { size, .. } => current_mesh_index_len = (size / 2) as u32,
|
||||
_ => panic!("expected a buffer type"),
|
||||
}
|
||||
|
||||
if let Some(buffer) = current_mesh_index_buffer {
|
||||
renderer.remove_buffer(buffer);
|
||||
}
|
||||
current_mesh_vertex_buffer = Some(renderer.create_buffer_with_data(
|
||||
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;
|
||||
};
|
||||
render_pass.set_index_buffer(index_buffer_resource, 0);
|
||||
render_pass.set_vertex_buffer(0, vertex_buffer_resource, 0);
|
||||
}
|
||||
// TODO: Verify buffer format matches render pass
|
||||
current_mesh_handle = Some(*mesh);
|
||||
}
|
||||
|
||||
// TODO: validate bind group properties against shader uniform properties at least once
|
||||
render_pass.setup_bind_groups(Some(&entity));
|
||||
render_pass.draw_indexed(0..current_mesh_index_length, 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);
|
||||
render_pass.draw_indexed(0..current_mesh_index_len, 0, 0..1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,66 +11,67 @@ pub fn ui_draw_target(
|
|||
render_pass: &mut dyn RenderPass,
|
||||
_pipeline_handle: Handle<PipelineDescriptor>,
|
||||
) {
|
||||
let mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
|
||||
let mut current_mesh_vertex_buffer = None;
|
||||
let mut current_mesh_index_buffer = None;
|
||||
let ui_instances_buffer = {
|
||||
let renderer = render_pass.get_renderer();
|
||||
match renderer.get_render_resources().get_named_resource(resource_name::buffer::UI_INSTANCES) {
|
||||
Some(buffer) => buffer,
|
||||
None => return,
|
||||
}
|
||||
};
|
||||
// NOTE: this is ugly and borrowing is stupid
|
||||
let result = {
|
||||
let renderer = render_pass.get_renderer();
|
||||
let result = if let Some(ResourceInfo::InstanceBuffer { count, mesh_id, .. }) =
|
||||
renderer.get_resource_info(ui_instances_buffer)
|
||||
{
|
||||
Some((*count, *mesh_id))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
// TODO: re-add support for this
|
||||
// let mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
|
||||
// let mut current_mesh_vertex_buffer = None;
|
||||
// let mut current_mesh_index_buffer = None;
|
||||
// let ui_instances_buffer = {
|
||||
// let renderer = render_pass.get_renderer();
|
||||
// match renderer.get_render_resources().get_named_resource(resource_name::buffer::UI_INSTANCES) {
|
||||
// Some(buffer) => buffer,
|
||||
// None => return,
|
||||
// }
|
||||
// };
|
||||
// // NOTE: this is ugly and borrowing is stupid
|
||||
// let result = {
|
||||
// let renderer = render_pass.get_renderer();
|
||||
// let result = if let Some(ResourceInfo::InstanceBuffer { count, mesh_id, .. }) =
|
||||
// renderer.get_resource_info(ui_instances_buffer)
|
||||
// {
|
||||
// Some((*count, *mesh_id))
|
||||
// } else {
|
||||
// None
|
||||
// };
|
||||
|
||||
if let Some((instance_count, mesh_id)) = result {
|
||||
if let Some(mesh_asset) = mesh_storage.get_id(mesh_id) {
|
||||
if let Some(buffer) = current_mesh_vertex_buffer {
|
||||
renderer.remove_buffer(buffer);
|
||||
}
|
||||
// if let Some((instance_count, mesh_id)) = result {
|
||||
// if let Some(mesh_asset) = mesh_storage.get_id(mesh_id) {
|
||||
// if let Some(buffer) = current_mesh_vertex_buffer {
|
||||
// renderer.remove_buffer(buffer);
|
||||
// }
|
||||
|
||||
if let Some(buffer) = current_mesh_index_buffer {
|
||||
renderer.remove_buffer(buffer);
|
||||
}
|
||||
current_mesh_vertex_buffer = Some(renderer.create_buffer_with_data(
|
||||
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,
|
||||
));
|
||||
Some((instance_count, mesh_asset.indices.len()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
if let Some((instance_count, indices_length)) = result {
|
||||
render_pass.setup_bind_groups(None);
|
||||
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(1, ui_instances_buffer, 0);
|
||||
render_pass.draw_indexed(0..indices_length as u32, 0, 0..(instance_count as u32));
|
||||
}
|
||||
// if let Some(buffer) = current_mesh_index_buffer {
|
||||
// renderer.remove_buffer(buffer);
|
||||
// }
|
||||
// current_mesh_vertex_buffer = Some(renderer.create_buffer_with_data(
|
||||
// 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,
|
||||
// ));
|
||||
// Some((instance_count, mesh_asset.indices.len()))
|
||||
// } else {
|
||||
// None
|
||||
// }
|
||||
// } else {
|
||||
// None
|
||||
// }
|
||||
// };
|
||||
// if let Some((instance_count, indices_length)) = result {
|
||||
// render_pass.setup_bind_groups(None);
|
||||
// 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(1, ui_instances_buffer, 0);
|
||||
// render_pass.draw_indexed(0..indices_length as u32, 0, 0..(instance_count as u32));
|
||||
// }
|
||||
|
||||
let renderer = render_pass.get_renderer();
|
||||
if let Some(buffer) = current_mesh_vertex_buffer {
|
||||
renderer.remove_buffer(buffer);
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
// if let Some(buffer) = current_mesh_index_buffer {
|
||||
// renderer.remove_buffer(buffer);
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::asset::{Handle, Texture};
|
||||
use crate::asset::{Handle, Texture, Mesh};
|
||||
use std::collections::HashMap;
|
||||
|
||||
#[derive(Copy, Clone, Hash, Debug, Eq, PartialEq)]
|
||||
|
@ -11,6 +11,8 @@ pub struct RenderResources {
|
|||
pub name_to_resource: HashMap<String, RenderResource>,
|
||||
pub texture_to_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,
|
||||
}
|
||||
|
||||
|
@ -31,6 +33,22 @@ impl RenderResources {
|
|||
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) {
|
||||
self.texture_to_sampler_resource.insert(texture, resource);
|
||||
}
|
||||
|
|
|
@ -86,7 +86,7 @@ pub trait Renderer {
|
|||
|
||||
pub trait RenderPass {
|
||||
// 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 set_index_buffer(&mut self, 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 textures: HashMap<RenderResource, wgpu::TextureView>,
|
||||
pub samplers: HashMap<RenderResource, wgpu::Sampler>,
|
||||
pub render_pipelines: HashMap<Handle<PipelineDescriptor>, wgpu::RenderPipeline>,
|
||||
pub resource_info: HashMap<RenderResource, ResourceInfo>,
|
||||
pub bind_groups: HashMap<u64, BindGroupInfo>,
|
||||
pub bind_group_layouts: HashMap<u64, wgpu::BindGroupLayout>,
|
||||
|
@ -32,7 +31,6 @@ pub struct WgpuResources {
|
|||
impl WgpuResources {
|
||||
pub fn new() -> Self {
|
||||
WgpuResources {
|
||||
render_pipelines: HashMap::new(),
|
||||
buffers: HashMap::new(),
|
||||
textures: HashMap::new(),
|
||||
samplers: HashMap::new(),
|
||||
|
@ -455,6 +453,7 @@ pub struct WgpuRenderer {
|
|||
pub surface: Option<wgpu::Surface>,
|
||||
pub encoder: Option<wgpu::CommandEncoder>,
|
||||
pub swap_chain_descriptor: wgpu::SwapChainDescriptor,
|
||||
pub render_pipelines: HashMap<Handle<PipelineDescriptor>, wgpu::RenderPipeline>,
|
||||
pub wgpu_resources: WgpuResources,
|
||||
}
|
||||
|
||||
|
@ -490,6 +489,7 @@ impl WgpuRenderer {
|
|||
encoder: None,
|
||||
swap_chain_descriptor,
|
||||
wgpu_resources: WgpuResources::new(),
|
||||
render_pipelines: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -620,7 +620,7 @@ impl WgpuRenderer {
|
|||
}
|
||||
|
||||
pub fn create_render_pass<'a>(
|
||||
wgpu_resources: &WgpuResources,
|
||||
wgpu_resources: &'a WgpuResources,
|
||||
pass_descriptor: &PassDescriptor,
|
||||
encoder: &'a mut wgpu::CommandEncoder,
|
||||
frame: &'a wgpu::SwapChainOutput,
|
||||
|
@ -686,7 +686,7 @@ impl WgpuRenderer {
|
|||
wgpu_resources: &'a WgpuResources,
|
||||
depth_stencil_attachment_descriptor: &RenderPassDepthStencilAttachmentDescriptor,
|
||||
frame: &'a wgpu::SwapChainOutput,
|
||||
) -> wgpu::RenderPassDepthStencilAttachmentDescriptor<&'a wgpu::TextureView> {
|
||||
) -> wgpu::RenderPassDepthStencilAttachmentDescriptor<'a> {
|
||||
let attachment = match depth_stencil_attachment_descriptor.attachment.as_str() {
|
||||
resource_name::texture::SWAP_CHAIN => &frame.view,
|
||||
_ => {
|
||||
|
@ -828,7 +828,6 @@ impl Renderer for WgpuRenderer {
|
|||
.unwrap();
|
||||
// create pipelines
|
||||
if !self
|
||||
.wgpu_resources
|
||||
.render_pipelines
|
||||
.contains_key(pipeline_descriptor_handle)
|
||||
{
|
||||
|
@ -849,7 +848,7 @@ impl Renderer for WgpuRenderer {
|
|||
vertex_shader,
|
||||
fragment_shader,
|
||||
);
|
||||
self.wgpu_resources.render_pipelines
|
||||
self.render_pipelines
|
||||
.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() {
|
||||
// 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) {
|
||||
for pass_pipeline in pass_pipelines.iter() {
|
||||
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);
|
||||
|
||||
let mut render_pass = WgpuRenderPass {
|
||||
let mut wgpu_render_pass = WgpuRenderPass {
|
||||
render_pass: &mut render_pass,
|
||||
renderer: self,
|
||||
pipeline_descriptor,
|
||||
wgpu_resources: &self.wgpu_resources,
|
||||
renderer: &self
|
||||
};
|
||||
|
||||
for draw_target_name in pipeline_descriptor.draw_targets.iter() {
|
||||
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 render_pass: &'b mut wgpu::RenderPass<'a>,
|
||||
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> {
|
||||
fn get_renderer(&mut self) -> &mut dyn Renderer {
|
||||
fn get_renderer(&mut self) -> &dyn 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) {
|
||||
let buffer = self.renderer.wgpu_resources.buffers.get(&resource).unwrap();
|
||||
let buffer = self.wgpu_resources.buffers.get(&resource).unwrap();
|
||||
self.render_pass
|
||||
.set_vertex_buffers(start_slot, &[(&buffer, offset)]);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
for bind_group in pipeline_layout.bind_groups.iter() {
|
||||
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
|
||||
Some(bind_group_info) => bind_group_info,
|
||||
// otherwise try to get an entity-specific bind group
|
||||
None => {
|
||||
if let Some(entity) = entity {
|
||||
if let None = self.renderer.wgpu_resources.get_entity_bind_group(*entity, bind_group_id) {
|
||||
self.renderer.wgpu_resources.create_entity_bind_group(&self.renderer.device, bind_group, *entity);
|
||||
if let None = self.wgpu_resources.get_entity_bind_group(*entity, bind_group_id) {
|
||||
// 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)
|
||||
.unwrap()
|
||||
} else {
|
||||
|
@ -1082,14 +1084,13 @@ impl<'a, 'b, 'c, 'd> RenderPass for WgpuRenderPass<'a, 'b, 'c, 'd> {
|
|||
}
|
||||
|
||||
if let Some(resource) = self
|
||||
.renderer
|
||||
.wgpu_resources
|
||||
.render_resources
|
||||
.get_named_resource(&binding.name)
|
||||
{
|
||||
// PERF: This hashmap get is pretty expensive (10 fps for 10000 entities)
|
||||
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
|
||||
.offsets
|
||||
|
|
|
@ -1,8 +1,4 @@
|
|||
pub enum ResourceInfo {
|
||||
BufferMapped {
|
||||
size: u64,
|
||||
buffer_usage: wgpu::BufferUsage,
|
||||
},
|
||||
Buffer {
|
||||
size: u64,
|
||||
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 ui_resource_provider;
|
||||
mod uniform_resource_provider;
|
||||
mod mesh_resource_provider;
|
||||
|
||||
pub use camera2d_resource_provider::*;
|
||||
pub use camera_resource_provider::*;
|
||||
|
@ -11,3 +12,4 @@ pub use frame_texture_resource_provider::*;
|
|||
pub use light_resource_provider::*;
|
||||
pub use ui_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()));
|
||||
}
|
||||
|
||||
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);
|
||||
*counts += 1;
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ where
|
|||
}
|
||||
|
||||
// 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;
|
||||
if let Some(resource) = resource {
|
||||
let mut info = renderer
|
||||
|
@ -158,7 +158,7 @@ where
|
|||
// TODO: check if index has changed. if it has, then entity should be updated
|
||||
// TODO: only mem-map entities if their data has changed
|
||||
// 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
|
||||
offset += alignment;
|
||||
}
|
||||
|
|
|
@ -171,7 +171,7 @@ pub struct UniformInfo<'a> {
|
|||
}
|
||||
|
||||
pub struct DynamicUniformBufferInfo {
|
||||
pub offsets: HashMap<Entity, u64>,
|
||||
pub offsets: HashMap<Entity, u32>,
|
||||
pub capacity: u64,
|
||||
pub count: u64,
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue