mirror of
https://github.com/bevyengine/bevy
synced 2025-02-16 14:08:32 +00:00
add assigned meshes render target
dynamic compiling w/ entity-specifc macros works!
This commit is contained in:
parent
56e5414b63
commit
c208945833
13 changed files with 121 additions and 28 deletions
|
@ -24,7 +24,7 @@ fn setup(world: &mut World) {
|
|||
},
|
||||
..Default::default()
|
||||
})
|
||||
// cube
|
||||
// tan cube
|
||||
.add_archetype(NewMeshEntity {
|
||||
mesh: cube_handle.clone(),
|
||||
material: StandardMaterial {
|
||||
|
@ -34,6 +34,16 @@ fn setup(world: &mut World) {
|
|||
translation: Translation::new(0.0, 0.0, 1.0),
|
||||
..Default::default()
|
||||
})
|
||||
// red cube
|
||||
.add_archetype(NewMeshEntity {
|
||||
mesh: cube_handle.clone(),
|
||||
material: StandardMaterial {
|
||||
albedo: math::vec4(0.5, 0.4, 0.3, 1.0),
|
||||
everything_is_red: true,
|
||||
},
|
||||
translation: Translation::new(3.0, 0.0, 1.0),
|
||||
..Default::default()
|
||||
})
|
||||
// light
|
||||
.add_archetype(LightEntity {
|
||||
light: Light {
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
use core::marker::PhantomData;
|
||||
use bevy::{prelude::*, render::render_graph_2::{Renderable, StandardMaterial}};
|
||||
use bevy::{prelude::*, render::render_graph_2::StandardMaterial};
|
||||
use rand::{rngs::StdRng, Rng, SeedableRng};
|
||||
use std::collections::VecDeque;
|
||||
|
||||
|
@ -83,23 +82,17 @@ fn setup(world: &mut World) {
|
|||
.add_archetype(NewMeshEntity {
|
||||
mesh: cube_handle.clone(),
|
||||
material: StandardMaterial {
|
||||
albedo: math::vec4(1.0, 0.0, 0.0, 1.0),
|
||||
everything_is_red: true,
|
||||
albedo: math::vec4(1.0, 1.0, 1.0, 1.0),
|
||||
everything_is_red: false,
|
||||
},
|
||||
translation: Translation::new(0.0, 0.0, 1.0),
|
||||
renderable: Renderable {
|
||||
pipelines: vec![
|
||||
Handle::new(0), // Forward Pipeline Handle
|
||||
],
|
||||
..Default::default()
|
||||
},
|
||||
..Default::default()
|
||||
})
|
||||
.add_archetype(NewMeshEntity {
|
||||
mesh: cube_handle.clone(),
|
||||
material: StandardMaterial {
|
||||
albedo: math::vec4(0.0, 1.0, 0.0, 1.0),
|
||||
everything_is_red: false,
|
||||
everything_is_red: true,
|
||||
},
|
||||
translation: Translation::new(-2.0, 0.0, 1.0),
|
||||
..Default::default()
|
||||
|
|
|
@ -16,7 +16,7 @@ use crate::{
|
|||
};
|
||||
|
||||
use bevy_transform::{prelude::LocalToWorld, transform_system_bundle};
|
||||
use render_graph_2::{CompiledShaderMap, PipelineDescriptor, resource_name, draw_targets::{ui_draw_target, meshes_draw_target}};
|
||||
use render_graph_2::{CompiledShaderMap, PipelineDescriptor, resource_name, draw_targets::{ui_draw_target, meshes_draw_target, assigned_meshes_draw_target}};
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub struct AppBuilder {
|
||||
|
@ -196,6 +196,7 @@ impl AppBuilder {
|
|||
self.render_graph_builder = self
|
||||
.render_graph_builder
|
||||
.add_draw_target(resource_name::draw_target::MESHES, meshes_draw_target)
|
||||
.add_draw_target(resource_name::draw_target::ASSIGNED_MESHES, assigned_meshes_draw_target)
|
||||
.add_draw_target(resource_name::draw_target::UI, ui_draw_target)
|
||||
.add_resource_provider(Box::new(CameraResourceProvider))
|
||||
.add_resource_provider(Box::new(Camera2dResourceProvider))
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
use crate::render::render_graph_2::RenderPass;
|
||||
use crate::{asset::Handle, render::render_graph_2::{pipeline::PipelineDescriptor, RenderPass}};
|
||||
use legion::prelude::World;
|
||||
|
||||
// A set of draw calls. ex: get + draw meshes, get + draw instanced meshes, draw ui meshes, etc
|
||||
|
||||
// TODO: consider swapping out dyn RenderPass for explicit WgpuRenderPass type to avoid dynamic dispatch
|
||||
pub type DrawTarget = fn(world: &World, render_pass: &mut dyn RenderPass);
|
||||
pub type DrawTarget = fn(
|
||||
world: &World,
|
||||
render_pass: &mut dyn RenderPass,
|
||||
pipeline_handle: Handle<PipelineDescriptor>,
|
||||
);
|
||||
|
|
|
@ -0,0 +1,79 @@
|
|||
use crate::{
|
||||
asset::{AssetStorage, Handle, Mesh},
|
||||
legion::prelude::*,
|
||||
render::{
|
||||
render_graph_2::{resource_name, RenderPass, Renderable, PipelineDescriptor, ShaderPipelineAssignments},
|
||||
},
|
||||
};
|
||||
|
||||
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_index_length = 0;
|
||||
|
||||
let assigned_entities = shader_pipeline_assignments
|
||||
.assignments
|
||||
.get(&pipeline_handle);
|
||||
|
||||
if let Some(assigned_entities) = assigned_entities {
|
||||
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();
|
||||
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();
|
||||
renderer.create_buffer_with_data(
|
||||
resource_name::buffer::TEMP_MESH_VERTEX_BUFFER_NAME,
|
||||
mesh_asset.vertices.as_bytes(),
|
||||
wgpu::BufferUsage::VERTEX,
|
||||
);
|
||||
renderer.create_buffer_with_data(
|
||||
resource_name::buffer::TEMP_MESH_INDEX_BUFFER_NAME,
|
||||
mesh_asset.indices.as_bytes(),
|
||||
wgpu::BufferUsage::INDEX,
|
||||
);
|
||||
|
||||
// TODO: Verify buffer format matches render pass
|
||||
render_pass
|
||||
.set_index_buffer(resource_name::buffer::TEMP_MESH_INDEX_BUFFER_NAME, 0);
|
||||
render_pass.set_vertex_buffer(
|
||||
0,
|
||||
resource_name::buffer::TEMP_MESH_VERTEX_BUFFER_NAME,
|
||||
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
|
||||
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();
|
||||
renderer.remove_buffer(resource_name::buffer::TEMP_MESH_VERTEX_BUFFER_NAME);
|
||||
renderer.remove_buffer(resource_name::buffer::TEMP_MESH_INDEX_BUFFER_NAME);
|
||||
}
|
||||
}
|
|
@ -2,14 +2,14 @@ use crate::{
|
|||
asset::{AssetStorage, Handle, Mesh},
|
||||
legion::prelude::*,
|
||||
render::{
|
||||
render_graph_2::{resource_name, RenderPass, Renderable, ShaderUniforms},
|
||||
render_graph_2::{resource_name, RenderPass, Renderable, ShaderUniforms, PipelineDescriptor},
|
||||
Instanced,
|
||||
},
|
||||
};
|
||||
|
||||
use zerocopy::AsBytes;
|
||||
|
||||
pub fn meshes_draw_target(world: &World, render_pass: &mut dyn RenderPass) {
|
||||
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_index_length = 0;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
mod meshes_draw_target;
|
||||
mod assigned_meshes_draw_target;
|
||||
mod ui_draw_target;
|
||||
|
||||
pub use meshes_draw_target::*;
|
||||
pub use assigned_meshes_draw_target::*;
|
||||
pub use ui_draw_target::*;
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
use crate::{
|
||||
asset::{AssetStorage, Mesh},
|
||||
asset::{AssetStorage, Mesh, Handle},
|
||||
legion::prelude::*,
|
||||
render::render_graph_2::{resource_name, RenderPass, ResourceInfo},
|
||||
render::render_graph_2::{resource_name, RenderPass, ResourceInfo, PipelineDescriptor},
|
||||
};
|
||||
|
||||
use zerocopy::AsBytes;
|
||||
|
||||
pub fn ui_draw_target(world: &World, render_pass: &mut dyn RenderPass) {
|
||||
pub fn ui_draw_target(world: &World, render_pass: &mut dyn RenderPass, _pipeline_handle: Handle<PipelineDescriptor>) {
|
||||
let mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
|
||||
// NOTE: this is ugly and borrowing is stupid
|
||||
let result = {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::{asset::{AssetStorage, Handle}, render::{
|
||||
render_graph_2::{BindGroup, DrawTarget, PipelineLayout},
|
||||
render_graph_2::{BindGroup, PipelineLayout},
|
||||
shader::{Shader, ShaderStages},
|
||||
}};
|
||||
|
||||
|
|
|
@ -101,7 +101,7 @@ impl ForwardPipelineBuilder for RenderGraphBuilder {
|
|||
write_mask: wgpu::ColorWrite::ALL,
|
||||
})
|
||||
.add_vertex_buffer_descriptor(Vertex::get_vertex_buffer_descriptor())
|
||||
.add_draw_target(resource_name::draw_target::MESHES)
|
||||
.add_draw_target(resource_name::draw_target::ASSIGNED_MESHES)
|
||||
.build(),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::{
|
||||
asset::{AssetStorage, Handle},
|
||||
render::{render_graph_2::RenderGraph, Shader, ShaderStages, ShaderSource},
|
||||
render::{render_graph_2::RenderGraph, Shader, ShaderSource},
|
||||
};
|
||||
use legion::prelude::*;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
@ -16,7 +16,9 @@ impl Default for Renderable {
|
|||
fn default() -> Self {
|
||||
Renderable {
|
||||
is_visible: true,
|
||||
pipelines: Vec::new(),
|
||||
pipelines: vec![
|
||||
Handle::new(0), // TODO: this could be better
|
||||
],
|
||||
shader_defs: HashSet::new(),
|
||||
}
|
||||
}
|
||||
|
@ -98,7 +100,6 @@ pub fn update_shader_assignments(world: &mut World, render_graph: &mut RenderGra
|
|||
let final_handle = if let Some((_shader_defs, macroed_pipeline_handle)) = compiled_shader_map.pipeline_to_macro_pipelines.get_mut(pipeline_handle).unwrap().iter().find(|(shader_defs, _macroed_pipeline_handle)| *shader_defs == renderable.shader_defs) {
|
||||
macroed_pipeline_handle.clone()
|
||||
} else {
|
||||
println!("Create pipeline {:?} {:?}", pipeline_handle, renderable.shader_defs);
|
||||
let pipeline_descriptor = pipeline_descriptor_storage.get(pipeline_handle).unwrap();
|
||||
let macroed_pipeline_handle = {
|
||||
let mut macroed_vertex_handle = try_compiling_shader_with_macros(&mut compiled_shader_map, &mut shader_storage, &renderable, &pipeline_descriptor.shader_stages.vertex);
|
||||
|
@ -114,7 +115,10 @@ pub fn update_shader_assignments(world: &mut World, render_graph: &mut RenderGra
|
|||
macroed_pipeline.shader_stages.fragment = fragment;
|
||||
}
|
||||
|
||||
pipeline_descriptor_storage.add(macroed_pipeline)
|
||||
let macroed_pipeline_handle = pipeline_descriptor_storage.add(macroed_pipeline);
|
||||
// TODO: get correct pass name
|
||||
render_graph.add_pipeline("main", macroed_pipeline_handle.clone());
|
||||
macroed_pipeline_handle
|
||||
} else {
|
||||
pipeline_handle.clone()
|
||||
}
|
||||
|
@ -125,7 +129,6 @@ pub fn update_shader_assignments(world: &mut World, render_graph: &mut RenderGra
|
|||
macroed_pipeline_handle
|
||||
};
|
||||
|
||||
// TODO: collecting assigments in a map means they won't be removed when the macro changes
|
||||
// TODO: this will break down if pipeline layout changes. fix this with "autolayout"
|
||||
if let None = shader_pipeline_assignments.assignments.get(&final_handle) {
|
||||
shader_pipeline_assignments.assignments.insert(final_handle.clone(), Vec::new());
|
||||
|
|
|
@ -448,7 +448,7 @@ impl Renderer for WgpuRenderer {
|
|||
|
||||
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);
|
||||
draw_target(world, &mut render_pass, pass_pipeline.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,5 +17,6 @@ pub mod buffer {
|
|||
|
||||
pub mod draw_target {
|
||||
pub const MESHES: &str = "Meshes";
|
||||
pub const ASSIGNED_MESHES: &str = "AssignedMeshes";
|
||||
pub const UI: &str = "Ui";
|
||||
}
|
Loading…
Add table
Reference in a new issue