remove old render graph

This commit is contained in:
Carter Anderson 2020-02-17 18:36:31 -08:00
parent acebeb924c
commit 6f376b5f3f
93 changed files with 524 additions and 3421 deletions

View file

@ -1,7 +1,7 @@
use bevy::{
prelude::*,
render::{
render_graph_2::{PipelineDescriptor, StandardMaterial, resource_name, resource_providers::UniformResourceProvider},
render_graph::{PipelineDescriptor, resource_name},
Shader, ShaderStage, Vertex,
},
};

View file

@ -2,7 +2,7 @@ use bevy::prelude::*;
fn main() {
AppBuilder::new()
.add_defaults_legacy()
.add_defaults()
.setup_world(setup)
.run();
}

View file

@ -21,7 +21,6 @@ struct Wander {
fn main() {
AppBuilder::new()
.add_defaults_legacy()
.setup_world(setup)
.add_system(build_wander_system())
.add_system(build_navigate_system())

View file

@ -2,5 +2,5 @@ use bevy::{asset, prelude::*};
fn main() {
asset::load_gltf("examples/assets/Box.gltf").unwrap();
AppBuilder::new().add_defaults_legacy().run();
AppBuilder::new().add_defaults().run();
}

View file

@ -4,7 +4,7 @@ struct Rotator;
fn main() {
AppBuilder::new()
.add_defaults_legacy()
.add_defaults()
.setup_world(setup)
.add_system(build_rotator_system())
.run();

View file

@ -2,7 +2,7 @@ use bevy::prelude::*;
fn main() {
AppBuilder::new()
.add_defaults_legacy()
.add_defaults()
.load_plugin("examples/plugin_loading/example_plugin/target/release/libexample_plugin.so")
.run();
}

View file

@ -3,7 +3,7 @@ use serde::{Deserialize, Serialize};
use type_uuid::TypeUuid;
fn main() {
let app = AppBuilder::new()
.add_defaults_legacy()
.add_defaults()
.setup_world(setup)
.build();

View file

@ -1,10 +1,7 @@
use bevy::prelude::*;
fn main() {
AppBuilder::new()
.add_defaults_legacy()
.setup_world(setup)
.run();
AppBuilder::new().add_defaults().setup_world(setup).run();
}
fn setup(world: &mut World) {
@ -19,18 +16,33 @@ fn setup(world: &mut World) {
world
.build()
// plane
.add_archetype(MeshEntity {
.add_archetype(NewMeshEntity {
mesh: plane_handle.clone(),
material: Material::new(Albedo::Color(math::vec4(0.1, 0.2, 0.1, 1.0))),
local_to_world: LocalToWorld::identity(),
translation: Translation::new(0.0, 0.0, 0.0),
material: StandardMaterial {
albedo: math::vec4(0.1, 0.2, 0.1, 1.0),
everything_is_red: false,
},
..Default::default()
})
// cube
.add_archetype(MeshEntity {
mesh: cube_handle,
material: Material::new(Albedo::Color(math::vec4(0.5, 0.3, 0.3, 1.0))),
local_to_world: LocalToWorld::identity(),
// tan cube
.add_archetype(NewMeshEntity {
mesh: cube_handle.clone(),
material: StandardMaterial {
albedo: math::vec4(0.5, 0.4, 0.3, 1.0),
everything_is_red: false,
},
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 {
@ -38,7 +50,7 @@ fn setup(world: &mut World) {
color: wgpu::Color {
r: 0.8,
g: 0.8,
b: 0.5,
b: 0.8,
a: 1.0,
},
fov: f32::to_radians(60.0),

View file

@ -1,126 +0,0 @@
use bevy::prelude::*;
use rand::{rngs::StdRng, Rng, SeedableRng};
use std::collections::VecDeque;
fn main() {
AppBuilder::new()
.add_defaults_legacy()
.add_system(build_move_system())
.add_system(build_print_status_system())
.setup_world(setup)
.run();
}
fn build_move_system() -> Box<dyn Schedulable> {
SystemBuilder::new("Move")
.read_resource::<Time>()
.with_query(<(Write<Translation>, Write<Material>)>::query())
.build(move |_, world, time, person_query| {
for (mut translation, mut _material) in person_query.iter_mut(world) {
translation.0 += math::vec3(1.0, 0.0, 0.0) * time.delta_seconds;
}
})
}
fn build_print_status_system() -> Box<dyn Schedulable> {
let mut elapsed = 0.0;
let mut frame_time_total = 0.0;
let mut frame_time_count = 0;
let frame_time_max = 10;
let mut frame_time_values = VecDeque::new();
SystemBuilder::new("PrintStatus")
.read_resource::<Time>()
.build(move |_, _world, time, _queries| {
elapsed += time.delta_seconds;
frame_time_values.push_front(time.delta_seconds);
frame_time_total += time.delta_seconds;
frame_time_count += 1;
if frame_time_count > frame_time_max {
frame_time_count = frame_time_max;
frame_time_total -= frame_time_values.pop_back().unwrap();
}
if elapsed > 1.0 {
if frame_time_count > 0 && frame_time_total > 0.0 {
println!(
"fps: {}",
1.0 / (frame_time_total / frame_time_count as f32)
)
}
elapsed = 0.0;
}
})
}
fn setup(world: &mut World) {
let cube = Mesh::load(MeshType::Cube);
let plane = Mesh::load(MeshType::Plane { size: 10.0 });
let (cube_handle, plane_handle) = {
let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
(mesh_storage.add(cube), mesh_storage.add(plane))
};
let mut builder = world
.build()
// plane
.add_archetype(MeshEntity {
mesh: plane_handle.clone(),
material: Material::new(Albedo::Color(math::vec4(0.1, 0.2, 0.1, 1.0))),
local_to_world: LocalToWorld::identity(),
translation: Translation::new(0.0, 0.0, 0.0),
})
// cube
.add_archetype(MeshEntity {
mesh: cube_handle.clone(),
material: Material::new(Albedo::Color(math::vec4(0.5, 0.3, 0.3, 1.0))),
local_to_world: LocalToWorld::identity(),
translation: Translation::new(0.0, 0.0, 1.0),
})
// light
.add_archetype(LightEntity {
light: Light {
color: wgpu::Color {
r: 0.8,
g: 0.8,
b: 0.5,
a: 1.0,
},
fov: f32::to_radians(60.0),
depth: 0.1..50.0,
target_view: None,
},
local_to_world: LocalToWorld::identity(),
translation: Translation::new(4.0, -4.0, 5.0),
rotation: Rotation::from_euler_angles(0.0, 0.0, 0.0),
})
// camera
.add_archetype(CameraEntity {
camera: Camera::new(CameraType::Projection {
fov: std::f32::consts::PI / 4.0,
near: 1.0,
far: 1000.0,
aspect_ratio: 1.0,
}),
active_camera: ActiveCamera,
local_to_world: LocalToWorld(Mat4::look_at_rh(
Vec3::new(3.0, 8.0, 5.0),
Vec3::new(0.0, 0.0, 0.0),
Vec3::new(0.0, 0.0, 1.0),
)),
});
let mut rng = StdRng::from_entropy();
for _ in 0..10000 {
builder = builder.add_archetype(MeshEntity {
mesh: cube_handle.clone(),
material: Material::new(Albedo::Color(math::vec4(0.5, 0.3, 0.3, 1.0))),
local_to_world: LocalToWorld::identity(),
translation: Translation::new(
rng.gen_range(-50.0, 50.0),
rng.gen_range(-50.0, 50.0),
0.0,
),
});
}
builder.build()
}

View file

@ -1,80 +0,0 @@
use bevy::{prelude::*, render::render_graph_2::StandardMaterial};
fn main() {
AppBuilder::new().add_defaults().setup_world(setup).run();
}
fn setup(world: &mut World) {
let cube = Mesh::load(MeshType::Cube);
let plane = Mesh::load(MeshType::Plane { size: 10.0 });
let (cube_handle, plane_handle) = {
let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
(mesh_storage.add(cube), mesh_storage.add(plane))
};
world
.build()
// plane
.add_archetype(NewMeshEntity {
mesh: plane_handle.clone(),
material: StandardMaterial {
albedo: math::vec4(0.1, 0.2, 0.1, 1.0),
everything_is_red: false,
},
..Default::default()
})
// tan cube
.add_archetype(NewMeshEntity {
mesh: cube_handle.clone(),
material: StandardMaterial {
albedo: math::vec4(0.5, 0.4, 0.3, 1.0),
everything_is_red: false,
},
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 {
color: wgpu::Color {
r: 0.8,
g: 0.8,
b: 0.8,
a: 1.0,
},
fov: f32::to_radians(60.0),
depth: 0.1..50.0,
target_view: None,
},
local_to_world: LocalToWorld::identity(),
translation: Translation::new(4.0, -4.0, 5.0),
rotation: Rotation::from_euler_angles(0.0, 0.0, 0.0),
})
// camera
.add_archetype(CameraEntity {
camera: Camera::new(CameraType::Projection {
fov: std::f32::consts::PI / 4.0,
near: 1.0,
far: 1000.0,
aspect_ratio: 1.0,
}),
active_camera: ActiveCamera,
local_to_world: LocalToWorld(Mat4::look_at_rh(
Vec3::new(3.0, 8.0, 5.0),
Vec3::new(0.0, 0.0, 0.0),
Vec3::new(0.0, 0.0, 1.0),
)),
})
.build();
}

View file

@ -1,4 +1,4 @@
use bevy::{prelude::*, render::render_graph_2::StandardMaterial};
use bevy::prelude::*;
use rand::{rngs::StdRng, Rng, SeedableRng};
use std::collections::VecDeque;

View file

@ -1,41 +1,36 @@
use bevy::{asset, prelude::*};
fn main() {
AppBuilder::new()
.add_defaults_legacy()
.setup_world(setup)
.run();
AppBuilder::new().add_defaults().setup_world(setup).run();
}
fn setup(world: &mut World) {
let cube_handle = {
let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
let cube = Mesh::load(MeshType::Cube);
mesh_storage.add(cube)
mesh_storage.add(Mesh::load(MeshType::Cube))
};
let texture_handle = {
let _texture_handle = {
let mut texture_storage = world.resources.get_mut::<AssetStorage<Texture>>().unwrap();
let texture = Texture::load(TextureType::Data(asset::create_texels(256)));
texture_storage.add(texture)
};
// cube
world.insert(
(),
vec![(
cube_handle,
Material::new(Albedo::Texture(texture_handle)),
LocalToWorld::identity(),
Translation::new(0.0, 0.0, 1.0),
)],
);
// light
world.insert(
(),
vec![(
Light {
world
.build()
// cube
.add_archetype(NewMeshEntity {
mesh: cube_handle.clone(),
material: StandardMaterial {
albedo: math::vec4(0.5, 0.3, 0.3, 1.0),
everything_is_red: false,
},
translation: Translation::new(0.0, 0.0, 1.0),
..Default::default()
})
// light
.add_archetype(LightEntity {
light: Light {
color: wgpu::Color {
r: 0.8,
g: 0.8,
@ -46,28 +41,24 @@ fn setup(world: &mut World) {
depth: 0.1..50.0,
target_view: None,
},
LocalToWorld::identity(),
Translation::new(4.0, -4.0, 5.0),
Rotation::from_euler_angles(0.0, 0.0, 0.0),
)],
);
// camera
world.insert(
(),
vec![(
Camera::new(CameraType::Projection {
local_to_world: LocalToWorld::identity(),
translation: Translation::new(4.0, -4.0, 5.0),
rotation: Rotation::from_euler_angles(0.0, 0.0, 0.0),
})
// camera
.add_archetype(CameraEntity {
camera: Camera::new(CameraType::Projection {
fov: std::f32::consts::PI / 4.0,
near: 1.0,
far: 1000.0,
aspect_ratio: 1.0,
}),
ActiveCamera,
LocalToWorld(Mat4::look_at_rh(
active_camera: ActiveCamera,
local_to_world: LocalToWorld(Mat4::look_at_rh(
Vec3::new(3.0, 8.0, 5.0),
Vec3::new(0.0, 0.0, 0.0),
Vec3::new(0.0, 0.0, 1.0),
)),
)],
);
})
.build();
}

View file

@ -1,64 +0,0 @@
use bevy::{asset, prelude::*, render::render_graph_2::StandardMaterial};
fn main() {
AppBuilder::new().add_defaults().setup_world(setup).run();
}
fn setup(world: &mut World) {
let cube_handle = {
let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
mesh_storage.add(Mesh::load(MeshType::Cube))
};
let _texture_handle = {
let mut texture_storage = world.resources.get_mut::<AssetStorage<Texture>>().unwrap();
let texture = Texture::load(TextureType::Data(asset::create_texels(256)));
texture_storage.add(texture)
};
world
.build()
// cube
.add_archetype(NewMeshEntity {
mesh: cube_handle.clone(),
material: StandardMaterial {
albedo: math::vec4(0.5, 0.3, 0.3, 1.0),
everything_is_red: false,
},
translation: Translation::new(0.0, 0.0, 1.0),
..Default::default()
})
// light
.add_archetype(LightEntity {
light: Light {
color: wgpu::Color {
r: 0.8,
g: 0.8,
b: 0.5,
a: 1.0,
},
fov: f32::to_radians(60.0),
depth: 0.1..50.0,
target_view: None,
},
local_to_world: LocalToWorld::identity(),
translation: Translation::new(4.0, -4.0, 5.0),
rotation: Rotation::from_euler_angles(0.0, 0.0, 0.0),
})
// camera
.add_archetype(CameraEntity {
camera: Camera::new(CameraType::Projection {
fov: std::f32::consts::PI / 4.0,
near: 1.0,
far: 1000.0,
aspect_ratio: 1.0,
}),
active_camera: ActiveCamera,
local_to_world: LocalToWorld(Mat4::look_at_rh(
Vec3::new(3.0, 8.0, 5.0),
Vec3::new(0.0, 0.0, 0.0),
Vec3::new(0.0, 0.0, 1.0),
)),
})
.build();
}

View file

@ -1,10 +1,7 @@
use bevy::prelude::*;
fn main() {
AppBuilder::new()
.add_defaults_legacy()
.setup_world(setup)
.run();
AppBuilder::new().add_defaults().setup_world(setup).run();
}
fn setup(world: &mut World) {
@ -14,21 +11,21 @@ fn setup(world: &mut World) {
mesh_storage.add(cube)
};
// cube
world.insert(
(),
vec![(
cube_handle,
LocalToWorld::identity(),
Material::new(Albedo::Color(math::vec4(0.5, 0.3, 0.3, 1.0))),
)],
);
// light
world.insert(
(),
vec![(
Light {
world
.build()
// cube
.add_archetype(NewMeshEntity {
mesh: cube_handle.clone(),
material: StandardMaterial {
albedo: math::vec4(0.5, 0.3, 0.3, 1.0),
everything_is_red: false,
},
translation: Translation::new(0.0, 0.0, 1.0),
..Default::default()
})
// light
.add_archetype(LightEntity {
light: Light {
color: wgpu::Color {
r: 0.8,
g: 0.8,
@ -39,39 +36,28 @@ fn setup(world: &mut World) {
depth: 0.1..50.0,
target_view: None,
},
LocalToWorld::identity(),
Translation::new(4.0, -4.0, 5.0),
Rotation::from_euler_angles(0.0, 0.0, 0.0),
)],
);
// 3d camera
world.insert(
(),
vec![
// camera
(
Camera::new(CameraType::Projection {
fov: std::f32::consts::PI / 4.0,
near: 1.0,
far: 1000.0,
aspect_ratio: 1.0,
}),
ActiveCamera,
LocalToWorld(Mat4::look_at_rh(
Vec3::new(3.0, -5.0, 3.0),
Vec3::new(0.0, 0.0, 0.0),
Vec3::new(0.0, 0.0, 1.0),
)),
),
],
);
// 2d camera
world.insert(
(),
vec![(
Camera::new(CameraType::Orthographic {
local_to_world: LocalToWorld::identity(),
translation: Translation::new(4.0, -4.0, 5.0),
rotation: Rotation::from_euler_angles(0.0, 0.0, 0.0),
})
// 3d camera
.add_archetype(CameraEntity {
camera: Camera::new(CameraType::Projection {
fov: std::f32::consts::PI / 4.0,
near: 1.0,
far: 1000.0,
aspect_ratio: 1.0,
}),
active_camera: ActiveCamera,
local_to_world: LocalToWorld(Mat4::look_at_rh(
Vec3::new(3.0, 8.0, 5.0),
Vec3::new(0.0, 0.0, 0.0),
Vec3::new(0.0, 0.0, 1.0),
)),
})
// 2d camera
.add_archetype(Camera2dEntity {
camera: Camera::new(CameraType::Orthographic {
left: 0.0,
right: 0.0,
bottom: 0.0,
@ -79,9 +65,9 @@ fn setup(world: &mut World) {
near: 0.0,
far: 1.0,
}),
ActiveCamera2d,
)],
);
active_camera_2d: ActiveCamera2d,
})
.build();
// bottom left anchor with vertical fill
world.insert(

View file

@ -1,172 +0,0 @@
use bevy::{prelude::*, render::render_graph_2::StandardMaterial};
fn main() {
AppBuilder::new().add_defaults().setup_world(setup).run();
}
fn setup(world: &mut World) {
let cube = Mesh::load(MeshType::Cube);
let cube_handle = {
let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
mesh_storage.add(cube)
};
world
.build()
// cube
.add_archetype(NewMeshEntity {
mesh: cube_handle.clone(),
material: StandardMaterial {
albedo: math::vec4(0.5, 0.3, 0.3, 1.0),
everything_is_red: false,
},
translation: Translation::new(0.0, 0.0, 1.0),
..Default::default()
})
// light
.add_archetype(LightEntity {
light: Light {
color: wgpu::Color {
r: 0.8,
g: 0.8,
b: 0.5,
a: 1.0,
},
fov: f32::to_radians(60.0),
depth: 0.1..50.0,
target_view: None,
},
local_to_world: LocalToWorld::identity(),
translation: Translation::new(4.0, -4.0, 5.0),
rotation: Rotation::from_euler_angles(0.0, 0.0, 0.0),
})
// 3d camera
.add_archetype(CameraEntity {
camera: Camera::new(CameraType::Projection {
fov: std::f32::consts::PI / 4.0,
near: 1.0,
far: 1000.0,
aspect_ratio: 1.0,
}),
active_camera: ActiveCamera,
local_to_world: LocalToWorld(Mat4::look_at_rh(
Vec3::new(3.0, 8.0, 5.0),
Vec3::new(0.0, 0.0, 0.0),
Vec3::new(0.0, 0.0, 1.0),
)),
})
// 2d camera
.add_archetype(Camera2dEntity {
camera: Camera::new(CameraType::Orthographic {
left: 0.0,
right: 0.0,
bottom: 0.0,
top: 0.0,
near: 0.0,
far: 1.0,
}),
active_camera_2d: ActiveCamera2d,
})
.build();
// bottom left anchor with vertical fill
world.insert(
(),
vec![(Node::new(
math::vec2(0.0, 0.0),
Anchors::new(0.0, 0.0, 0.0, 1.0),
Margins::new(10.0, 200.0, 10.0, 10.0),
math::vec4(0.1, 0.1, 0.1, 1.0),
),)],
);
// top right anchor with vertical fill
world.insert(
(),
vec![(Node::new(
math::vec2(0.0, 0.0),
Anchors::new(1.0, 1.0, 0.0, 1.0),
Margins::new(10.0, 100.0, 50.0, 100.0),
math::vec4(0.1, 0.1, 0.1, 1.0),
),)],
);
// render order test: reddest in the back, whitest in the front
world.insert(
(),
vec![(Node::new(
math::vec2(75.0, 75.0),
Anchors::new(0.5, 0.5, 0.5, 0.5),
Margins::new(0.0, 100.0, 0.0, 100.0),
math::vec4(1.0, 0.1, 0.1, 1.0),
),)],
);
world.insert(
(),
vec![(Node::new(
math::vec2(50.0, 50.0),
Anchors::new(0.5, 0.5, 0.5, 0.5),
Margins::new(0.0, 100.0, 0.0, 100.0),
math::vec4(1.0, 0.3, 0.3, 1.0),
),)],
);
world.insert(
(),
vec![(Node::new(
math::vec2(100.0, 100.0),
Anchors::new(0.5, 0.5, 0.5, 0.5),
Margins::new(0.0, 100.0, 0.0, 100.0),
math::vec4(1.0, 0.5, 0.5, 1.0),
),)],
);
world.insert(
(),
vec![(Node::new(
math::vec2(150.0, 150.0),
Anchors::new(0.5, 0.5, 0.5, 0.5),
Margins::new(0.0, 100.0, 0.0, 100.0),
math::vec4(1.0, 0.7, 0.7, 1.0),
),)],
);
// parenting
let parent = *world
.insert(
(),
vec![(Node::new(
math::vec2(300.0, 300.0),
Anchors::new(0.0, 0.0, 0.0, 0.0),
Margins::new(0.0, 200.0, 0.0, 200.0),
math::vec4(0.1, 0.1, 1.0, 1.0),
),)],
)
.first()
.unwrap();
world.insert(
(),
vec![(
Node::new(
math::vec2(0.0, 0.0),
Anchors::new(0.0, 1.0, 0.0, 1.0),
Margins::new(20.0, 20.0, 20.0, 20.0),
math::vec4(0.6, 0.6, 1.0, 1.0),
),
Parent(parent),
)],
);
// alpha test
world.insert(
(),
vec![(Node::new(
math::vec2(200.0, 200.0),
Anchors::new(0.5, 0.5, 0.5, 0.5),
Margins::new(0.0, 100.0, 0.0, 100.0),
math::vec4(1.0, 0.9, 0.9, 0.4),
),)],
);
}

View file

@ -9,14 +9,12 @@ use legion::prelude::*;
use crate::{
app::AppBuilder,
core::Time,
render,
render::render_graph_2::{RenderGraph, Renderer},
render::render_graph::{RenderGraph, Renderer},
};
pub struct App {
pub universe: Universe,
pub world: World,
pub legacy_render_graph: Option<render::RenderGraph>,
pub renderer: Option<Box<dyn Renderer>>,
pub render_graph: RenderGraph,
pub schedule: Schedule,
@ -27,7 +25,6 @@ impl App {
universe: Universe,
world: World,
schedule: Schedule,
legacy_render_graph: Option<render::RenderGraph>,
renderer: Option<Box<dyn Renderer>>,
render_graph: RenderGraph,
) -> App {
@ -35,7 +32,6 @@ impl App {
universe,
world,
schedule,
legacy_render_graph,
renderer,
render_graph,
}
@ -51,11 +47,6 @@ impl App {
}
self.schedule.execute(&mut self.world);
// TODO: remove me
if let Some(ref mut render_graph) = self.legacy_render_graph {
render_graph.render(&mut self.world);
}
if let Some(ref mut renderer) = self.renderer {
renderer.process_render_graph(&mut self.render_graph, &mut self.world);
}
@ -79,9 +70,6 @@ impl App {
self.world.resources.insert(window);
log::info!("Initializing the example...");
if let Some(ref mut render_graph) = self.legacy_render_graph {
render_graph.initialize(&mut self.world);
}
if let Some(ref mut renderer) = self.renderer {
renderer.initialize(&mut self.world, &mut self.render_graph);
@ -99,10 +87,6 @@ impl App {
event: WindowEvent::Resized(size),
..
} => {
if let Some(ref mut render_graph) = self.legacy_render_graph {
render_graph.resize(size.width, size.height, &mut self.world);
}
if let Some(ref mut renderer) = self.renderer {
renderer.resize(
&mut self.world,

View file

@ -5,10 +5,10 @@ use crate::{
legion::prelude::{Runnable, Schedulable, Schedule, Universe, World},
plugin::load_plugin,
render::{
passes::*,
render_graph_2::{
passes::*, pipelines::*, renderers::wgpu_renderer::WgpuRenderer, resource_providers::*,
ShaderPipelineAssignments, StandardMaterial, RenderGraphBuilder
render_graph::{
draw_targets::*, passes::*, pipelines::*, renderers::wgpu_renderer::WgpuRenderer,
resource_name, resource_providers::*, CompiledShaderMap, PipelineDescriptor,
RenderGraphBuilder, Renderer, ShaderPipelineAssignments, StandardMaterial,
},
*,
},
@ -16,15 +16,13 @@ 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, assigned_meshes_draw_target}};
use std::collections::HashMap;
pub struct AppBuilder {
pub world: World,
pub universe: Universe,
pub legacy_render_graph: Option<RenderGraph>,
pub renderer: Option<Box<dyn render_graph_2::Renderer>>,
pub render_graph_builder: render_graph_2::RenderGraphBuilder,
pub renderer: Option<Box<dyn Renderer>>,
pub render_graph_builder: RenderGraphBuilder,
pub system_stages: HashMap<String, Vec<Box<dyn Schedulable>>>,
pub runnable_stages: HashMap<String, Vec<Box<dyn Runnable>>>,
pub stage_order: Vec<String>,
@ -37,8 +35,7 @@ impl AppBuilder {
AppBuilder {
universe,
world,
render_graph_builder: render_graph_2::RenderGraphBuilder::new(),
legacy_render_graph: None,
render_graph_builder: RenderGraphBuilder::new(),
renderer: None,
system_stages: HashMap::new(),
runnable_stages: HashMap::new(),
@ -70,7 +67,6 @@ impl AppBuilder {
self.universe,
self.world,
schedule_builder.build(),
self.legacy_render_graph,
self.renderer,
self.render_graph_builder.build(),
)
@ -120,46 +116,6 @@ impl AppBuilder {
self
}
pub fn with_legacy_render_graph(mut self) -> Self {
self.legacy_render_graph = Some(RenderGraph::new());
self
}
pub fn add_default_passes(mut self) -> Self {
let msaa_samples = 4;
{
let render_graph = &mut self.legacy_render_graph.as_mut().unwrap();
render_graph
.add_render_resource_manager(Box::new(render_resources::MaterialResourceManager));
render_graph.add_render_resource_manager(Box::new(
render_resources::LightResourceManager::new(10),
));
render_graph
.add_render_resource_manager(Box::new(render_resources::GlobalResourceManager));
render_graph
.add_render_resource_manager(Box::new(render_resources::Global2dResourceManager));
let depth_format = wgpu::TextureFormat::Depth32Float;
render_graph.set_pass(
"forward",
Box::new(ForwardPass::new(depth_format, msaa_samples)),
);
render_graph.set_pipeline(
"forward",
"forward",
Box::new(ForwardPipeline::new(msaa_samples)),
);
render_graph.set_pipeline(
"forward",
"forward_instanced",
Box::new(ForwardInstancedPipeline::new(depth_format, msaa_samples)),
);
render_graph.set_pipeline("forward", "ui", Box::new(UiPipeline::new(msaa_samples)));
}
self
}
pub fn add_default_resources(mut self) -> Self {
let resources = &mut self.world.resources;
resources.insert(Time::new());
@ -185,7 +141,10 @@ impl AppBuilder {
self.setup_render_graph(|builder, pipeline_storage, shader_storage| {
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::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))
@ -199,7 +158,14 @@ impl AppBuilder {
})
}
pub fn setup_render_graph(mut self, setup: impl Fn(RenderGraphBuilder, &mut AssetStorage<PipelineDescriptor>, &mut AssetStorage<Shader>) -> RenderGraphBuilder) -> Self {
pub fn setup_render_graph(
mut self,
setup: impl Fn(
RenderGraphBuilder,
&mut AssetStorage<PipelineDescriptor>,
&mut AssetStorage<Shader>,
) -> RenderGraphBuilder,
) -> Self {
{
let mut pipeline_storage = self
.world
@ -211,7 +177,11 @@ impl AppBuilder {
.resources
.get_mut::<AssetStorage<Shader>>()
.unwrap();
self.render_graph_builder = setup(self.render_graph_builder, &mut pipeline_storage, &mut shader_storage);
self.render_graph_builder = setup(
self.render_graph_builder,
&mut pipeline_storage,
&mut shader_storage,
);
}
self
@ -222,13 +192,6 @@ impl AppBuilder {
self
}
pub fn add_defaults_legacy(self) -> Self {
self.with_legacy_render_graph()
.add_default_resources()
.add_default_passes()
.add_default_systems()
}
pub fn add_defaults(self) -> Self {
self.add_default_resources()
.add_default_systems()

View file

@ -1,6 +1,6 @@
use crate::{
prelude::*,
render::render_graph_2::{Renderable, ShaderUniforms, StandardMaterial},
render::render_graph::{Renderable, ShaderUniforms, StandardMaterial},
};
use bevy_derive::EntityArchetype;

View file

@ -6,6 +6,7 @@ pub use crate::{
ecs::{default_archetypes::*, EntityArchetype, WorldBuilder, WorldBuilderSource},
render::{
ActiveCamera, ActiveCamera2d, Albedo, Camera, CameraType, Instanced, Light, Material,
render_graph::StandardMaterial,
},
ui::{Anchors, Margins, Node},
};

View file

@ -1,20 +1,16 @@
pub mod camera;
pub mod instancing;
pub mod passes;
pub mod render_graph_2;
pub mod render_resources;
pub mod render_graph;
pub mod shader;
pub mod shader_reflect;
mod light;
mod material;
mod render_graph;
mod vertex;
pub use camera::*;
pub use light::*;
pub use material::*;
pub use render_graph::*;
pub use shader::*;
use std::mem;

View file

@ -1,44 +0,0 @@
#version 450
const int MAX_LIGHTS = 10;
layout(location = 0) in vec3 v_Normal;
layout(location = 1) in vec4 v_Position;
layout(location = 0) out vec4 o_Target;
struct Light {
mat4 proj;
vec4 pos;
vec4 color;
};
layout(set = 0, binding = 0) uniform Globals {
mat4 ViewProj;
uvec4 NumLights;
};
layout(set = 0, binding = 1) uniform Lights {
Light SceneLights[MAX_LIGHTS];
};
layout(set = 1, binding = 0) uniform Entity {
mat4 World;
vec4 Color;
};
void main() {
vec3 normal = normalize(v_Normal);
vec3 ambient = vec3(0.05, 0.05, 0.05);
// accumulate color
vec3 color = ambient;
for (int i=0; i<int(NumLights.x) && i<MAX_LIGHTS; ++i) {
Light light = SceneLights[i];
// compute Lambertian diffuse term
vec3 light_dir = normalize(light.pos.xyz - v_Position.xyz);
float diffuse = max(0.0, dot(normal, light_dir));
// add light contribution
color += diffuse * light.color.xyz;
}
// multiply the light by material color
o_Target = vec4(color, 1.0) * Color;
}

View file

@ -1,23 +0,0 @@
#version 450
layout(location = 0) in vec4 a_Pos;
layout(location = 1) in vec4 a_Normal;
layout(location = 2) in vec4 a_Uv;
layout(location = 0) out vec3 v_Normal;
layout(location = 1) out vec4 v_Position;
layout(set = 0, binding = 0) uniform Globals {
mat4 ViewProj;
uvec4 NumLights;
};
layout(set = 1, binding = 0) uniform Entity {
mat4 World;
vec4 Color;
};
void main() {
v_Normal = mat3(World) * vec3(a_Normal.xyz);
v_Position = World * vec4(a_Pos);
gl_Position = ViewProj * v_Position;
}

View file

@ -1,169 +0,0 @@
use crate::render::*;
use legion::prelude::*;
use wgpu::{Device, SwapChainDescriptor};
use zerocopy::{AsBytes, FromBytes};
#[repr(C)]
#[derive(Clone, Copy, AsBytes, FromBytes)]
pub struct ForwardUniforms {
pub proj: [[f32; 4]; 4],
pub num_lights: [u32; 4],
}
pub struct ForwardPass {
pub depth_format: wgpu::TextureFormat,
pub msaa_samples: usize,
}
impl ForwardPass {
pub fn new(depth_format: wgpu::TextureFormat, msaa_samples: usize) -> Self {
ForwardPass {
depth_format,
msaa_samples,
}
}
fn get_depth_texture(
&self,
device: &Device,
swap_chain_descriptor: &SwapChainDescriptor,
) -> wgpu::TextureView {
let texture = device.create_texture(&wgpu::TextureDescriptor {
size: wgpu::Extent3d {
width: swap_chain_descriptor.width,
height: swap_chain_descriptor.height,
depth: 1,
},
array_layer_count: 1,
mip_level_count: 1,
sample_count: self.msaa_samples as u32,
dimension: wgpu::TextureDimension::D2,
format: self.depth_format,
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
});
texture.create_default_view()
}
fn get_multisampled_framebuffer(
&self,
device: &Device,
swap_chain_descriptor: &SwapChainDescriptor,
sample_count: usize,
) -> wgpu::TextureView {
let multisampled_texture_extent = wgpu::Extent3d {
width: swap_chain_descriptor.width,
height: swap_chain_descriptor.height,
depth: 1,
};
let multisampled_frame_descriptor = &wgpu::TextureDescriptor {
size: multisampled_texture_extent,
array_layer_count: 1,
mip_level_count: 1,
sample_count: sample_count as u32,
dimension: wgpu::TextureDimension::D2,
format: swap_chain_descriptor.format,
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
};
device
.create_texture(multisampled_frame_descriptor)
.create_default_view()
}
}
const DEPTH_TEXTURE_NAME: &str = "forward_depth";
const MULTISAMPLED_FRAMEBUFFER_TEXTURE_NAME: &str = "forward_multisampled_framebuffer";
impl Pass for ForwardPass {
fn initialize(&self, render_graph: &mut RenderGraphData) {
let depth_texture =
self.get_depth_texture(&render_graph.device, &render_graph.swap_chain_descriptor);
render_graph.set_texture(DEPTH_TEXTURE_NAME, depth_texture);
if self.msaa_samples > 1 {
let multisampled_framebuffer = self.get_multisampled_framebuffer(
&render_graph.device,
&render_graph.swap_chain_descriptor,
self.msaa_samples,
);
render_graph.set_texture(
MULTISAMPLED_FRAMEBUFFER_TEXTURE_NAME,
multisampled_framebuffer,
);
}
}
fn begin<'a>(
&mut self,
render_graph: &mut RenderGraphData,
_: &mut World,
encoder: &'a mut wgpu::CommandEncoder,
frame: &'a wgpu::SwapChainOutput,
) -> Option<wgpu::RenderPass<'a>> {
let depth_texture = render_graph.get_texture(DEPTH_TEXTURE_NAME);
let color_attachment = if self.msaa_samples == 1 {
wgpu::RenderPassColorAttachmentDescriptor {
attachment: &frame.view,
resolve_target: None,
load_op: wgpu::LoadOp::Clear,
store_op: wgpu::StoreOp::Store,
clear_color: wgpu::Color {
r: 0.3,
g: 0.4,
b: 0.5,
a: 1.0,
},
}
} else {
let multisampled_framebuffer = render_graph
.get_texture(MULTISAMPLED_FRAMEBUFFER_TEXTURE_NAME)
.unwrap();
wgpu::RenderPassColorAttachmentDescriptor {
attachment: multisampled_framebuffer,
resolve_target: Some(&frame.view),
load_op: wgpu::LoadOp::Clear,
store_op: wgpu::StoreOp::Store,
clear_color: wgpu::Color {
r: 0.3,
g: 0.4,
b: 0.5,
a: 1.0,
},
}
};
Some(encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
color_attachments: &[color_attachment],
depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachmentDescriptor {
attachment: depth_texture.unwrap(),
depth_load_op: wgpu::LoadOp::Clear,
depth_store_op: wgpu::StoreOp::Store,
stencil_load_op: wgpu::LoadOp::Clear,
stencil_store_op: wgpu::StoreOp::Store,
clear_depth: 1.0,
clear_stencil: 0,
}),
}))
}
fn resize(&self, render_graph: &mut RenderGraphData) {
let depth_texture =
self.get_depth_texture(&render_graph.device, &render_graph.swap_chain_descriptor);
render_graph.set_texture(DEPTH_TEXTURE_NAME, depth_texture);
if self.msaa_samples > 1 {
let multisampled_framebuffer = self.get_multisampled_framebuffer(
&render_graph.device,
&render_graph.swap_chain_descriptor,
self.msaa_samples,
);
render_graph.set_texture(
MULTISAMPLED_FRAMEBUFFER_TEXTURE_NAME,
multisampled_framebuffer,
);
}
}
fn should_repeat(&self) -> bool {
false
}
}

View file

@ -1,181 +0,0 @@
use crate::{asset::*, render::*};
use legion::prelude::*;
use wgpu::SwapChainOutput;
pub struct ForwardPipeline {
pub pipeline: Option<wgpu::RenderPipeline>,
pub depth_format: wgpu::TextureFormat,
pub bind_group: Option<wgpu::BindGroup>,
pub msaa_samples: usize,
}
impl ForwardPipeline {
pub fn new(msaa_samples: usize) -> Self {
ForwardPipeline {
pipeline: None,
bind_group: None,
msaa_samples,
depth_format: wgpu::TextureFormat::Depth32Float,
}
}
}
impl Pipeline for ForwardPipeline {
fn initialize(&mut self, render_graph: &mut RenderGraphData, _: &mut World) {
let vs_bytes = shader::glsl_to_spirv(
include_str!("forward.vert"),
shader::ShaderStage::Vertex,
None,
);
let fs_bytes = shader::glsl_to_spirv(
include_str!("forward.frag"),
shader::ShaderStage::Fragment,
None,
);
let bind_group_layout =
render_graph
.device
.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
bindings: &[
wgpu::BindGroupLayoutBinding {
binding: 0, // global
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
},
wgpu::BindGroupLayoutBinding {
binding: 1, // lights
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
},
],
});
self.bind_group = Some({
let forward_uniform_buffer = render_graph
.get_uniform_buffer(render_resources::FORWARD_UNIFORM_BUFFER_NAME)
.unwrap();
let light_uniform_buffer = render_graph
.get_uniform_buffer(render_resources::LIGHT_UNIFORM_BUFFER_NAME)
.unwrap();
// Create bind group
render_graph
.device
.create_bind_group(&wgpu::BindGroupDescriptor {
layout: &bind_group_layout,
bindings: &[
wgpu::Binding {
binding: 0,
resource: forward_uniform_buffer.get_binding_resource(),
},
wgpu::Binding {
binding: 1,
resource: light_uniform_buffer.get_binding_resource(),
},
],
})
});
let material_bind_group_layout = render_graph
.get_bind_group_layout(render_resources::MATERIAL_BIND_GROUP_LAYOUT_NAME)
.unwrap();
let pipeline_layout =
render_graph
.device
.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
bind_group_layouts: &[&bind_group_layout, material_bind_group_layout],
});
let vertex_buffer_descriptor = get_vertex_buffer_descriptor();
let vs_module = render_graph.device.create_shader_module(&vs_bytes);
let fs_module = render_graph.device.create_shader_module(&fs_bytes);
self.pipeline = Some(render_graph.device.create_render_pipeline(
&wgpu::RenderPipelineDescriptor {
layout: &pipeline_layout,
vertex_stage: wgpu::ProgrammableStageDescriptor {
module: &vs_module,
entry_point: "main",
},
fragment_stage: Some(wgpu::ProgrammableStageDescriptor {
module: &fs_module,
entry_point: "main",
}),
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
front_face: wgpu::FrontFace::Ccw,
cull_mode: wgpu::CullMode::Back,
depth_bias: 0,
depth_bias_slope_scale: 0.0,
depth_bias_clamp: 0.0,
}),
primitive_topology: wgpu::PrimitiveTopology::TriangleList,
color_states: &[wgpu::ColorStateDescriptor {
format: render_graph.swap_chain_descriptor.format,
color_blend: wgpu::BlendDescriptor::REPLACE,
alpha_blend: wgpu::BlendDescriptor::REPLACE,
write_mask: wgpu::ColorWrite::ALL,
}],
depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor {
format: self.depth_format,
depth_write_enabled: true,
depth_compare: wgpu::CompareFunction::Less,
stencil_front: wgpu::StencilStateFaceDescriptor::IGNORE,
stencil_back: wgpu::StencilStateFaceDescriptor::IGNORE,
stencil_read_mask: 0,
stencil_write_mask: 0,
}),
index_format: wgpu::IndexFormat::Uint16,
vertex_buffers: &[vertex_buffer_descriptor],
sample_count: self.msaa_samples as u32,
sample_mask: !0,
alpha_to_coverage_enabled: false,
},
));
}
fn render(
&mut self,
render_graph: &RenderGraphData,
pass: &mut wgpu::RenderPass,
_: &SwapChainOutput,
world: &mut World,
) {
pass.set_bind_group(0, self.bind_group.as_ref().unwrap(), &[]);
let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
let mut last_mesh_id = None;
let mesh_query =
<(Read<Material>, Read<Handle<Mesh>>)>::query().filter(!component::<Instanced>());
for (material, mesh) in mesh_query.iter(world) {
let current_mesh_id = mesh.id;
let mut should_load_mesh = last_mesh_id == None;
if let Some(last) = last_mesh_id {
should_load_mesh = last != current_mesh_id;
}
if should_load_mesh {
if let Some(mesh_asset) = mesh_storage.get_id_mut(mesh.id) {
mesh_asset.setup_buffers(&render_graph.device);
pass.set_index_buffer(mesh_asset.index_buffer.as_ref().unwrap(), 0);
pass.set_vertex_buffers(0, &[(&mesh_asset.vertex_buffer.as_ref().unwrap(), 0)]);
};
}
if let Some(ref mesh_asset) = mesh_storage.get_id(mesh.id) {
pass.set_bind_group(1, material.bind_group.as_ref().unwrap(), &[]);
pass.draw_indexed(0..mesh_asset.indices.len() as u32, 0, 0..1);
};
last_mesh_id = Some(current_mesh_id);
}
}
fn resize(&mut self, _: &RenderGraphData) {}
fn get_pipeline(&self) -> &wgpu::RenderPipeline {
self.pipeline.as_ref().unwrap()
}
}

View file

@ -1,5 +0,0 @@
mod forward_pass;
mod forward_pipeline;
pub use forward_pass::*;
pub use forward_pipeline::*;

View file

@ -1,40 +0,0 @@
#version 450
const int MAX_LIGHTS = 10;
layout(location = 0) in vec3 v_Normal;
layout(location = 1) in vec4 v_Position;
layout(location = 2) in vec4 v_Color;
layout(location = 0) out vec4 o_Target;
struct Light {
mat4 proj;
vec4 pos;
vec4 color;
};
layout(set = 0, binding = 0) uniform Globals {
mat4 u_ViewProj;
uvec4 u_NumLights;
};
layout(set = 0, binding = 1) uniform Lights {
Light u_Lights[MAX_LIGHTS];
};
void main() {
vec3 normal = normalize(v_Normal);
vec3 ambient = vec3(0.05, 0.05, 0.05);
// accumulate color
vec3 color = ambient;
for (int i=0; i<int(u_NumLights.x) && i<MAX_LIGHTS; ++i) {
Light light = u_Lights[i];
// compute Lambertian diffuse term
vec3 light_dir = normalize(light.pos.xyz - v_Position.xyz);
float diffuse = max(0.0, dot(normal, light_dir));
// add light contribution
color += diffuse * light.color.xyz;
}
// multiply the light by material color
o_Target = vec4(color, 1.0) * v_Color;
}

View file

@ -1,27 +0,0 @@
#version 450
// vertex attributes
layout(location = 0) in vec4 a_Pos;
layout(location = 1) in vec4 a_Normal;
layout(location = 2) in vec2 a_Uv;
// Instanced attributes
layout (location = 3) in vec3 a_instancePos;
layout (location = 4) in vec4 a_instanceColor;
layout(location = 0) out vec3 v_Normal;
layout(location = 1) out vec4 v_Position;
layout(location = 2) out vec4 v_Color;
layout(set = 0, binding = 0) uniform Globals {
mat4 u_ViewProj;
uvec4 u_NumLights;
};
void main() {
v_Normal = vec3(a_Normal.xyz);
v_Position = vec4(a_Pos) + vec4(a_instancePos, 1.0);
v_Color = a_instanceColor;
gl_Position = u_ViewProj * v_Position;
}

View file

@ -1,307 +0,0 @@
use crate::{
asset::*,
prelude::LocalToWorld,
render::{instancing::InstanceBufferInfo, *},
};
use legion::prelude::*;
use std::{collections::HashMap, mem};
use wgpu::{Device, SwapChainOutput};
use zerocopy::AsBytes;
pub struct ForwardInstancedPipeline {
pub pipeline: Option<wgpu::RenderPipeline>,
pub depth_format: wgpu::TextureFormat,
pub local_bind_group: Option<wgpu::BindGroup>,
pub instance_buffer_infos: Option<Vec<InstanceBufferInfo>>,
pub msaa_samples: usize,
}
impl ForwardInstancedPipeline {
pub fn new(depth_format: wgpu::TextureFormat, msaa_samples: usize) -> Self {
ForwardInstancedPipeline {
pipeline: None,
depth_format,
msaa_samples,
local_bind_group: None,
instance_buffer_infos: None,
}
}
fn create_instance_buffer_infos(device: &Device, world: &World) -> Vec<InstanceBufferInfo> {
let entities = <(
Read<Material>,
Read<LocalToWorld>,
Read<Handle<Mesh>>,
Read<Instanced>,
)>::query();
if entities.iter(world).count() == 0 {
return Vec::new();
}
let uniform_size = mem::size_of::<SimpleMaterialUniforms>();
let mut mesh_groups: HashMap<
usize,
Vec<(
legion::borrow::Ref<Material>,
legion::borrow::Ref<LocalToWorld>,
)>,
> = HashMap::new();
for (material, transform, mesh, _) in entities.iter(world) {
match mesh_groups.get_mut(&mesh.id) {
Some(entities) => {
entities.push((material, transform));
}
None => {
let mut entities = Vec::new();
let id = mesh.id;
entities.push((material, transform));
mesh_groups.insert(id, entities);
}
}
}
let mut instance_buffer_infos = Vec::new();
for (mesh_id, mut same_mesh_entities) in mesh_groups {
let temp_buf_data = device.create_buffer_mapped(
same_mesh_entities.len() * uniform_size,
wgpu::BufferUsage::COPY_SRC | wgpu::BufferUsage::VERTEX,
);
let entity_count = same_mesh_entities.len();
for ((material, transform), slot) in same_mesh_entities
.drain(..)
.zip(temp_buf_data.data.chunks_exact_mut(uniform_size))
{
let (_, _, translation) = transform.0.to_scale_rotation_translation();
slot.copy_from_slice(
SimpleMaterialUniforms {
position: translation.into(),
color: material.get_color().into(),
}
.as_bytes(),
);
}
instance_buffer_infos.push(InstanceBufferInfo {
mesh_id,
buffer: temp_buf_data.finish(),
instance_count: entity_count,
});
}
instance_buffer_infos
}
#[allow(dead_code)]
fn create_instance_buffer_infos_direct(
device: &Device,
world: &World,
) -> Vec<InstanceBufferInfo> {
let entities = <(
Read<Material>,
Read<LocalToWorld>,
Read<Handle<Mesh>>,
Read<Instanced>,
)>::query();
let entities_count = entities.iter(world).count();
let mut last_mesh_id = None;
let mut data = Vec::with_capacity(entities_count);
for (material, transform, mesh, _) in entities.iter(world) {
last_mesh_id = Some(mesh.id);
let (_, _, translation) = transform.0.to_scale_rotation_translation();
data.push(SimpleMaterialUniforms {
position: translation.into(),
color: material.get_color().into(),
});
}
let buffer = device.create_buffer_with_data(
data.as_bytes(),
wgpu::BufferUsage::COPY_SRC | wgpu::BufferUsage::VERTEX,
);
let mut instance_buffer_infos = Vec::new();
instance_buffer_infos.push(InstanceBufferInfo {
mesh_id: last_mesh_id.unwrap(),
buffer,
instance_count: entities_count,
});
instance_buffer_infos
}
}
impl Pipeline for ForwardInstancedPipeline {
fn initialize(&mut self, render_graph: &mut RenderGraphData, world: &mut World) {
let vs_bytes = shader::glsl_to_spirv(
include_str!("forward_instanced.vert"),
shader::ShaderStage::Vertex,
None,
);
let fs_bytes = shader::glsl_to_spirv(
include_str!("forward_instanced.frag"),
shader::ShaderStage::Fragment,
None,
);
let bind_group_layout =
render_graph
.device
.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
bindings: &[
wgpu::BindGroupLayoutBinding {
binding: 0, // global
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
},
wgpu::BindGroupLayoutBinding {
binding: 1, // lights
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
},
],
});
// TODO: this is the same as normal forward pipeline. we can probably reuse
self.local_bind_group = Some({
let forward_uniform_buffer = render_graph
.get_uniform_buffer(render_resources::FORWARD_UNIFORM_BUFFER_NAME)
.unwrap();
let light_uniform_buffer = render_graph
.get_uniform_buffer(render_resources::LIGHT_UNIFORM_BUFFER_NAME)
.unwrap();
// Create bind group
render_graph
.device
.create_bind_group(&wgpu::BindGroupDescriptor {
layout: &bind_group_layout,
bindings: &[
wgpu::Binding {
binding: 0,
resource: forward_uniform_buffer.get_binding_resource(),
},
wgpu::Binding {
binding: 1,
resource: light_uniform_buffer.get_binding_resource(),
},
],
})
});
let simple_material_uniforms_size = mem::size_of::<SimpleMaterialUniforms>();
let instance_buffer_descriptor = wgpu::VertexBufferDescriptor {
stride: simple_material_uniforms_size as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Instance,
attributes: &[
wgpu::VertexAttributeDescriptor {
format: wgpu::VertexFormat::Float3,
offset: 0,
shader_location: 3,
},
wgpu::VertexAttributeDescriptor {
format: wgpu::VertexFormat::Float4,
offset: 3 * 4,
shader_location: 4,
},
],
};
let vertex_buffer_descriptor = get_vertex_buffer_descriptor();
let pipeline_layout =
render_graph
.device
.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
bind_group_layouts: &[&bind_group_layout],
});
let vs_module = render_graph.device.create_shader_module(&vs_bytes);
let fs_module = render_graph.device.create_shader_module(&fs_bytes);
self.pipeline = Some(render_graph.device.create_render_pipeline(
&wgpu::RenderPipelineDescriptor {
layout: &pipeline_layout,
vertex_stage: wgpu::ProgrammableStageDescriptor {
module: &vs_module,
entry_point: "main",
},
fragment_stage: Some(wgpu::ProgrammableStageDescriptor {
module: &fs_module,
entry_point: "main",
}),
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
front_face: wgpu::FrontFace::Ccw,
cull_mode: wgpu::CullMode::Back,
depth_bias: 0,
depth_bias_slope_scale: 0.0,
depth_bias_clamp: 0.0,
}),
primitive_topology: wgpu::PrimitiveTopology::TriangleList,
color_states: &[wgpu::ColorStateDescriptor {
format: render_graph.swap_chain_descriptor.format,
color_blend: wgpu::BlendDescriptor::REPLACE,
alpha_blend: wgpu::BlendDescriptor::REPLACE,
write_mask: wgpu::ColorWrite::ALL,
}],
depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor {
format: self.depth_format,
depth_write_enabled: true,
depth_compare: wgpu::CompareFunction::Less,
stencil_front: wgpu::StencilStateFaceDescriptor::IGNORE,
stencil_back: wgpu::StencilStateFaceDescriptor::IGNORE,
stencil_read_mask: 0,
stencil_write_mask: 0,
}),
index_format: wgpu::IndexFormat::Uint16,
vertex_buffers: &[vertex_buffer_descriptor, instance_buffer_descriptor],
sample_count: self.msaa_samples as u32,
sample_mask: !0,
alpha_to_coverage_enabled: false,
},
));
self.instance_buffer_infos = Some(Self::create_instance_buffer_infos(
&render_graph.device,
world,
));
}
fn render(
&mut self,
render_graph: &RenderGraphData,
pass: &mut wgpu::RenderPass,
_: &SwapChainOutput,
world: &mut World,
) {
self.instance_buffer_infos = Some(Self::create_instance_buffer_infos(
&render_graph.device,
world,
));
pass.set_bind_group(0, self.local_bind_group.as_ref().unwrap(), &[]);
let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
for instance_buffer_info in self.instance_buffer_infos.as_ref().unwrap().iter() {
if let Some(mesh_asset) = mesh_storage.get_id_mut(instance_buffer_info.mesh_id) {
mesh_asset.setup_buffers(&render_graph.device);
pass.set_index_buffer(mesh_asset.index_buffer.as_ref().unwrap(), 0);
pass.set_vertex_buffers(0, &[(&mesh_asset.vertex_buffer.as_ref().unwrap(), 0)]);
pass.set_vertex_buffers(1, &[(&instance_buffer_info.buffer, 0)]);
pass.draw_indexed(
0..mesh_asset.indices.len() as u32,
0,
0..instance_buffer_info.instance_count as u32,
);
};
}
}
fn resize(&mut self, _: &RenderGraphData) {}
fn get_pipeline(&self) -> &wgpu::RenderPipeline {
self.pipeline.as_ref().unwrap()
}
}

View file

@ -1,62 +0,0 @@
#version 450
const int MAX_LIGHTS = 10;
layout(location = 0) in vec3 v_Normal;
layout(location = 1) in vec4 v_Position;
layout(location = 0) out vec4 o_Target;
struct Light {
mat4 proj;
vec4 pos;
vec4 color;
};
layout(set = 0, binding = 0) uniform Globals {
mat4 u_ViewProj;
uvec4 u_NumLights;
};
layout(set = 0, binding = 1) uniform Lights {
Light u_Lights[MAX_LIGHTS];
};
layout(set = 0, binding = 2) uniform texture2DArray t_Shadow;
layout(set = 0, binding = 3) uniform samplerShadow s_Shadow;
layout(set = 1, binding = 0) uniform Entity {
mat4 u_World;
vec4 u_Color;
};
float fetch_shadow(int light_id, vec4 homogeneous_coords) {
if (homogeneous_coords.w <= 0.0) {
return 1.0;
}
// compute texture coordinates for shadow lookup
vec4 light_local = vec4(
(homogeneous_coords.xy/homogeneous_coords.w + 1.0) / 2.0,
light_id,
homogeneous_coords.z / homogeneous_coords.w
);
// do the lookup, using HW PCF and comparison
return texture(sampler2DArrayShadow(t_Shadow, s_Shadow), light_local);
}
void main() {
vec3 normal = normalize(v_Normal);
vec3 ambient = vec3(0.05, 0.05, 0.05);
// accumulate color
vec3 color = ambient;
for (int i=0; i<int(u_NumLights.x) && i<MAX_LIGHTS; ++i) {
Light light = u_Lights[i];
// project into the light space
float shadow = fetch_shadow(i, light.proj * v_Position);
// compute Lambertian diffuse term
vec3 light_dir = normalize(light.pos.xyz - v_Position.xyz);
float diffuse = max(0.0, dot(normal, light_dir));
// add light contribution
color += shadow * diffuse * light.color.xyz;
}
// multiply the light by material color
o_Target = vec4(color, 1.0) * u_Color;
}

View file

@ -1,23 +0,0 @@
#version 450
layout(location = 0) in vec4 a_Pos;
layout(location = 1) in vec4 a_Normal;
layout(location = 2) in vec2 a_Uv;
layout(location = 0) out vec3 v_Normal;
layout(location = 1) out vec4 v_Position;
layout(set = 0, binding = 0) uniform Globals {
mat4 u_ViewProj;
uvec4 u_NumLights;
};
layout(set = 1, binding = 0) uniform Entity {
mat4 u_World;
vec4 u_Color;
};
void main() {
v_Normal = mat3(u_World) * vec3(a_Normal.xyz);
v_Position = u_World * vec4(a_Pos);
gl_Position = u_ViewProj * v_Position;
}

View file

@ -1,194 +0,0 @@
use crate::{
asset::*,
render::{passes::shadow, *},
};
use legion::prelude::*;
use wgpu::SwapChainOutput;
pub struct ForwardShadowPassNew {
pub pipeline: Option<wgpu::RenderPipeline>,
pub bind_group: Option<wgpu::BindGroup>,
pub depth_format: wgpu::TextureFormat,
}
impl ForwardShadowPassNew {
pub fn new() -> Self {
ForwardShadowPassNew {
pipeline: None,
bind_group: None,
depth_format: wgpu::TextureFormat::Depth32Float,
}
}
}
impl Pipeline for ForwardShadowPassNew {
fn initialize(&mut self, render_graph: &mut RenderGraphData, _world: &mut World) {
let vs_bytes = shader::glsl_to_spirv(
include_str!("forward_shadow.vert"),
shader::ShaderStage::Vertex,
None,
);
let fs_bytes = shader::glsl_to_spirv(
include_str!("forward_shadow.frag"),
shader::ShaderStage::Fragment,
None,
);
let bind_group_layout =
render_graph
.device
.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
bindings: &[
wgpu::BindGroupLayoutBinding {
binding: 0, // global
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
},
wgpu::BindGroupLayoutBinding {
binding: 1, // lights
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
},
wgpu::BindGroupLayoutBinding {
binding: 2,
visibility: wgpu::ShaderStage::FRAGMENT,
ty: wgpu::BindingType::SampledTexture {
multisampled: false,
dimension: wgpu::TextureViewDimension::D2Array,
},
},
wgpu::BindGroupLayoutBinding {
binding: 3,
visibility: wgpu::ShaderStage::FRAGMENT,
ty: wgpu::BindingType::Sampler,
},
],
});
self.bind_group = Some({
let forward_uniform_buffer = render_graph
.get_uniform_buffer(render_resources::FORWARD_UNIFORM_BUFFER_NAME)
.unwrap();
let light_uniform_buffer = render_graph
.get_uniform_buffer(render_resources::LIGHT_UNIFORM_BUFFER_NAME)
.unwrap();
let shadow_sampler = render_graph
.get_sampler(shadow::SHADOW_SAMPLER_NAME)
.unwrap();
let shadow_texture = render_graph
.get_texture(shadow::SHADOW_TEXTURE_NAME)
.unwrap();
// Create bind group
render_graph
.device
.create_bind_group(&wgpu::BindGroupDescriptor {
layout: &bind_group_layout,
bindings: &[
wgpu::Binding {
binding: 0,
resource: forward_uniform_buffer.get_binding_resource(),
},
wgpu::Binding {
binding: 1,
resource: light_uniform_buffer.get_binding_resource(),
},
wgpu::Binding {
binding: 2,
resource: wgpu::BindingResource::TextureView(shadow_texture),
},
wgpu::Binding {
binding: 3,
resource: wgpu::BindingResource::Sampler(shadow_sampler),
},
],
})
});
let material_bind_group_layout = render_graph
.get_bind_group_layout(render_resources::MATERIAL_BIND_GROUP_LAYOUT_NAME)
.unwrap();
let pipeline_layout =
render_graph
.device
.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
bind_group_layouts: &[&bind_group_layout, material_bind_group_layout],
});
let vs_module = render_graph.device.create_shader_module(&vs_bytes);
let fs_module = render_graph.device.create_shader_module(&fs_bytes);
let vertex_buffer_descriptor = get_vertex_buffer_descriptor();
self.pipeline = Some(render_graph.device.create_render_pipeline(
&wgpu::RenderPipelineDescriptor {
layout: &pipeline_layout,
vertex_stage: wgpu::ProgrammableStageDescriptor {
module: &vs_module,
entry_point: "main",
},
fragment_stage: Some(wgpu::ProgrammableStageDescriptor {
module: &fs_module,
entry_point: "main",
}),
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
front_face: wgpu::FrontFace::Ccw,
cull_mode: wgpu::CullMode::Back,
depth_bias: 0,
depth_bias_slope_scale: 0.0,
depth_bias_clamp: 0.0,
}),
primitive_topology: wgpu::PrimitiveTopology::TriangleList,
color_states: &[wgpu::ColorStateDescriptor {
format: render_graph.swap_chain_descriptor.format,
color_blend: wgpu::BlendDescriptor::REPLACE,
alpha_blend: wgpu::BlendDescriptor::REPLACE,
write_mask: wgpu::ColorWrite::ALL,
}],
depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor {
format: self.depth_format,
depth_write_enabled: true,
depth_compare: wgpu::CompareFunction::Less,
stencil_front: wgpu::StencilStateFaceDescriptor::IGNORE,
stencil_back: wgpu::StencilStateFaceDescriptor::IGNORE,
stencil_read_mask: 0,
stencil_write_mask: 0,
}),
index_format: wgpu::IndexFormat::Uint16,
vertex_buffers: &[vertex_buffer_descriptor],
sample_count: 1,
sample_mask: !0,
alpha_to_coverage_enabled: false,
},
));
}
fn render(
&mut self,
render_graph: &RenderGraphData,
pass: &mut wgpu::RenderPass,
_swap_chain_output: &SwapChainOutput,
world: &mut World,
) {
let mesh_query = <(Read<Material>, Read<Handle<Mesh>>)>::query();
pass.set_bind_group(0, self.bind_group.as_ref().unwrap(), &[]);
let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
for (material, mesh) in mesh_query.iter(world) {
if let Some(mesh_asset) = mesh_storage.get_id_mut(mesh.id) {
mesh_asset.setup_buffers(&render_graph.device);
pass.set_bind_group(1, material.bind_group.as_ref().unwrap(), &[]);
pass.set_index_buffer(mesh_asset.index_buffer.as_ref().unwrap(), 0);
pass.set_vertex_buffers(0, &[(&mesh_asset.vertex_buffer.as_ref().unwrap(), 0)]);
pass.draw_indexed(0..mesh_asset.indices.len() as u32, 0, 0..1);
};
}
}
fn resize(&mut self, _render_graph: &RenderGraphData) {}
fn get_pipeline(&self) -> &wgpu::RenderPipeline {
self.pipeline.as_ref().unwrap()
}
}

View file

@ -1,11 +0,0 @@
mod forward;
mod forward_instanced;
mod forward_shadow;
mod shadow;
mod ui;
pub use forward::{ForwardPass, ForwardPipeline, ForwardUniforms};
pub use forward_instanced::ForwardInstancedPipeline;
pub use forward_shadow::ForwardShadowPassNew;
pub use shadow::ShadowPass;
pub use ui::UiPipeline;

View file

@ -1,5 +0,0 @@
mod shadow_pass;
mod shadow_pipeline;
pub use shadow_pass::*;
pub use shadow_pipeline::*;

View file

@ -1,4 +0,0 @@
#version 450
void main() {
}

View file

@ -1,16 +0,0 @@
#version 450
layout(location = 0) in vec4 a_Pos;
layout(set = 0, binding = 0) uniform Globals {
mat4 u_ViewProj;
};
layout(set = 1, binding = 0) uniform Entity {
mat4 u_World;
vec4 u_Color;
};
void main() {
gl_Position = u_ViewProj * u_World * vec4(a_Pos);
}

View file

@ -1,126 +0,0 @@
use crate::{
prelude::{LocalToWorld, Translation},
render::{passes::shadow, *},
};
use legion::prelude::*;
use std::mem;
pub struct ShadowPass {
pub shadow_size: wgpu::Extent3d,
light_index: isize,
shadow_texture: Option<wgpu::Texture>,
shadow_format: wgpu::TextureFormat,
pub max_lights: usize,
}
pub const SHADOW_TEXTURE_NAME: &str = "shadow_texture";
impl ShadowPass {
pub fn new(
shadow_size: wgpu::Extent3d,
shadow_format: wgpu::TextureFormat,
max_lights: usize,
) -> Self {
ShadowPass {
light_index: -1,
shadow_texture: None,
shadow_size,
shadow_format,
max_lights,
}
}
}
impl Pass for ShadowPass {
fn initialize(&self, render_graph: &mut RenderGraphData) {
let shadow_texture = render_graph
.device
.create_texture(&wgpu::TextureDescriptor {
size: self.shadow_size,
array_layer_count: self.max_lights as u32,
mip_level_count: 1,
sample_count: 1,
dimension: wgpu::TextureDimension::D2,
format: self.shadow_format,
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT | wgpu::TextureUsage::SAMPLED,
});
let shadow_view = shadow_texture.create_default_view();
render_graph.set_texture(SHADOW_TEXTURE_NAME, shadow_view);
}
fn begin<'a>(
&mut self,
render_graph: &mut RenderGraphData,
world: &mut World,
encoder: &'a mut wgpu::CommandEncoder,
_frame: &'a wgpu::SwapChainOutput,
) -> Option<wgpu::RenderPass<'a>> {
if self.light_index == -1 {
self.light_index = 0;
}
let light_query = <(Write<Light>, Read<LocalToWorld>, Read<Translation>)>::query();
let light_count = light_query.iter_mut(world).count();
for (i, (mut light, _, _)) in light_query.iter_mut(world).enumerate() {
if i != self.light_index as usize {
continue;
}
if let None = light.target_view {
light.target_view = Some(self.shadow_texture.as_ref().unwrap().create_view(
&wgpu::TextureViewDescriptor {
format: self.shadow_format,
dimension: wgpu::TextureViewDimension::D2,
aspect: wgpu::TextureAspect::All,
base_mip_level: 0,
level_count: 1,
base_array_layer: i as u32,
array_layer_count: 1,
},
));
}
// The light uniform buffer already has the projection,
// let's just copy it over to the shadow uniform buffer.
let light_uniform_buffer = render_graph
.get_uniform_buffer(render_resources::LIGHT_UNIFORM_BUFFER_NAME)
.unwrap();
let shadow_pipeline_uniform_buffer = render_graph
.get_uniform_buffer(shadow::SHADOW_PIPELINE_UNIFORMS)
.unwrap();
encoder.copy_buffer_to_buffer(
&light_uniform_buffer.buffer,
(i * mem::size_of::<LightRaw>()) as wgpu::BufferAddress,
&shadow_pipeline_uniform_buffer.buffer,
0,
64,
);
self.light_index += 1;
if self.light_index as usize == light_count {
self.light_index = -1;
}
return Some(encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
color_attachments: &[],
depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachmentDescriptor {
attachment: light.target_view.as_ref().unwrap(),
depth_load_op: wgpu::LoadOp::Clear,
depth_store_op: wgpu::StoreOp::Store,
stencil_load_op: wgpu::LoadOp::Clear,
stencil_store_op: wgpu::StoreOp::Store,
clear_depth: 1.0,
clear_stencil: 0,
}),
}));
}
None
}
fn resize(&self, _render_graph: &mut RenderGraphData) {}
fn should_repeat(&self) -> bool {
return self.light_index != -1;
}
}

View file

@ -1,185 +0,0 @@
use crate::{asset::*, render::*};
use legion::prelude::*;
use std::mem;
use wgpu::SwapChainOutput;
pub const SHADOW_PIPELINE_UNIFORMS: &str = "shadow_pipeline";
pub const SHADOW_SAMPLER_NAME: &str = "shadow_sampler";
#[repr(C)]
pub struct ShadowUniforms {
pub proj: [[f32; 4]; 4],
}
pub struct ShadowPipeline {
pub pipeline: Option<wgpu::RenderPipeline>,
pub bind_group: Option<wgpu::BindGroup>,
pub shadow_format: wgpu::TextureFormat,
}
impl ShadowPipeline {
#[allow(dead_code)]
pub fn new(shadow_format: wgpu::TextureFormat) -> Self {
ShadowPipeline {
bind_group: None,
pipeline: None,
shadow_format,
}
}
}
impl Pipeline for ShadowPipeline {
fn initialize(&mut self, render_graph: &mut RenderGraphData, _: &mut World) {
let bind_group_layout =
render_graph
.device
.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
bindings: &[wgpu::BindGroupLayoutBinding {
binding: 0, // global
visibility: wgpu::ShaderStage::VERTEX,
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
}],
});
let material_bind_group_layout = render_graph
.get_bind_group_layout(render_resources::MATERIAL_BIND_GROUP_LAYOUT_NAME)
.unwrap();
let pipeline_layout =
render_graph
.device
.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
bind_group_layouts: &[&bind_group_layout, material_bind_group_layout],
});
let uniform_size = mem::size_of::<ShadowUniforms>() as wgpu::BufferAddress;
let uniform_buf = render_graph.device.create_buffer(&wgpu::BufferDescriptor {
size: uniform_size,
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
});
// Create bind group
self.bind_group = Some(
render_graph
.device
.create_bind_group(&wgpu::BindGroupDescriptor {
layout: &bind_group_layout,
bindings: &[wgpu::Binding {
binding: 0,
resource: wgpu::BindingResource::Buffer {
buffer: &uniform_buf,
range: 0..uniform_size,
},
}],
}),
);
render_graph.set_uniform_buffer(
SHADOW_PIPELINE_UNIFORMS,
UniformBuffer {
buffer: uniform_buf,
size: uniform_size,
},
);
// Create other resources
let shadow_sampler = render_graph
.device
.create_sampler(&wgpu::SamplerDescriptor {
address_mode_u: wgpu::AddressMode::ClampToEdge,
address_mode_v: wgpu::AddressMode::ClampToEdge,
address_mode_w: wgpu::AddressMode::ClampToEdge,
mag_filter: wgpu::FilterMode::Linear,
min_filter: wgpu::FilterMode::Linear,
mipmap_filter: wgpu::FilterMode::Nearest,
lod_min_clamp: -100.0,
lod_max_clamp: 100.0,
compare_function: wgpu::CompareFunction::LessEqual,
});
render_graph.set_sampler(SHADOW_SAMPLER_NAME, shadow_sampler);
let vertex_buffer_descriptor = get_vertex_buffer_descriptor();
// Create the render pipeline
let vs_bytes = shader::glsl_to_spirv(
include_str!("shadow.vert"),
shader::ShaderStage::Vertex,
None,
);
let fs_bytes = shader::glsl_to_spirv(
include_str!("shadow.frag"),
shader::ShaderStage::Fragment,
None,
);
let vs_module = render_graph.device.create_shader_module(&vs_bytes);
let fs_module = render_graph.device.create_shader_module(&fs_bytes);
self.pipeline = Some(render_graph.device.create_render_pipeline(
&wgpu::RenderPipelineDescriptor {
layout: &pipeline_layout,
vertex_stage: wgpu::ProgrammableStageDescriptor {
module: &vs_module,
entry_point: "main",
},
fragment_stage: Some(wgpu::ProgrammableStageDescriptor {
module: &fs_module,
entry_point: "main",
}),
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
front_face: wgpu::FrontFace::Ccw,
cull_mode: wgpu::CullMode::Back,
depth_bias: 2, // corresponds to bilinear filtering
depth_bias_slope_scale: 2.0,
depth_bias_clamp: 0.0,
}),
primitive_topology: wgpu::PrimitiveTopology::TriangleList,
color_states: &[],
depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor {
format: self.shadow_format,
depth_write_enabled: true,
depth_compare: wgpu::CompareFunction::LessEqual,
stencil_front: wgpu::StencilStateFaceDescriptor::IGNORE,
stencil_back: wgpu::StencilStateFaceDescriptor::IGNORE,
stencil_read_mask: 0,
stencil_write_mask: 0,
}),
index_format: wgpu::IndexFormat::Uint16,
vertex_buffers: &[vertex_buffer_descriptor],
sample_count: 1,
sample_mask: !0,
alpha_to_coverage_enabled: false,
},
));
}
fn render(
&mut self,
render_graph: &RenderGraphData,
pass: &mut wgpu::RenderPass,
_: &SwapChainOutput,
world: &mut World,
) {
let mesh_query =
<(Read<Material>, Read<Handle<Mesh>>)>::query().filter(!component::<Instanced>());
pass.set_bind_group(0, self.bind_group.as_ref().unwrap(), &[]);
let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
for (material, mesh) in mesh_query.iter(world) {
if let Some(mesh_asset) = mesh_storage.get_id_mut(mesh.id) {
mesh_asset.setup_buffers(&render_graph.device);
pass.set_bind_group(1, material.bind_group.as_ref().unwrap(), &[]);
pass.set_index_buffer(&mesh_asset.index_buffer.as_ref().unwrap(), 0);
pass.set_vertex_buffers(0, &[(&mesh_asset.vertex_buffer.as_ref().unwrap(), 0)]);
pass.draw_indexed(0..mesh_asset.indices.len() as u32, 0, 0..1);
};
}
}
fn resize(&mut self, _: &RenderGraphData) {}
fn get_pipeline(&self) -> &wgpu::RenderPipeline {
self.pipeline.as_ref().unwrap()
}
}

View file

@ -1,264 +0,0 @@
use crate::{
asset::*,
ecs, math,
prelude::Parent,
render::{instancing::InstanceBufferInfo, *},
ui::Node,
};
use legion::prelude::*;
use wgpu::SwapChainOutput;
use zerocopy::{AsBytes, FromBytes};
#[repr(C)]
#[derive(Clone, Copy, AsBytes, FromBytes)]
pub struct RectData {
pub position: [f32; 2],
pub size: [f32; 2],
pub color: [f32; 4],
pub z_index: f32,
}
pub struct UiPipeline {
pub pipeline: Option<wgpu::RenderPipeline>,
pub depth_format: wgpu::TextureFormat,
pub quad: Option<Handle<Mesh>>,
pub bind_group: Option<wgpu::BindGroup>,
pub msaa_samples: usize,
}
impl UiPipeline {
pub fn new(msaa_samples: usize) -> Self {
UiPipeline {
pipeline: None,
bind_group: None,
msaa_samples,
quad: None,
depth_format: wgpu::TextureFormat::Depth32Float,
}
}
pub fn create_rect_buffers(
&self,
device: &wgpu::Device,
world: &mut World,
) -> Vec<InstanceBufferInfo> {
let node_query = <Read<Node>>::query().filter(!component::<Parent>());
if node_query.iter(world).count() == 0 {
return Vec::new();
}
let mut data = Vec::new();
// TODO: this probably isn't the best way to handle z-ordering
let mut z = 0.9999;
{
let mut add_data: Box<dyn FnMut(&World, Entity, ()) -> Option<()>> =
Box::new(|world, entity, _| {
let node = world.get_component::<Node>(entity).unwrap();
data.push(RectData {
position: node.global_position.into(),
size: node.size.into(),
color: node.color.into(),
z_index: z,
});
z -= 0.0001;
Some(())
});
for entity in node_query
.iter_entities(world)
.map(|(entity, _)| entity)
.collect::<Vec<Entity>>()
{
ecs::run_on_hierarchy(world, entity, (), &mut add_data);
}
}
let buffer = device.create_buffer_with_data(
data.as_bytes(),
wgpu::BufferUsage::COPY_SRC | wgpu::BufferUsage::VERTEX,
);
let mesh_id = self.quad.as_ref().unwrap().id;
let mut instance_buffer_infos = Vec::new();
instance_buffer_infos.push(InstanceBufferInfo {
mesh_id,
buffer,
instance_count: data.len(),
});
instance_buffer_infos
}
}
impl Pipeline for UiPipeline {
fn initialize(&mut self, render_graph: &mut RenderGraphData, world: &mut World) {
let vs_bytes =
shader::glsl_to_spirv(include_str!("ui.vert"), shader::ShaderStage::Vertex, None);
let fs_bytes =
shader::glsl_to_spirv(include_str!("ui.frag"), shader::ShaderStage::Fragment, None);
let bind_group_layout =
render_graph
.device
.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
bindings: &[wgpu::BindGroupLayoutBinding {
binding: 0, // global_2d
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
}],
});
self.bind_group = Some({
let global_2d_uniform_buffer = render_graph
.get_uniform_buffer(render_resources::GLOBAL_2D_UNIFORM_BUFFER_NAME)
.unwrap();
// Create bind group
render_graph
.device
.create_bind_group(&wgpu::BindGroupDescriptor {
layout: &bind_group_layout,
bindings: &[wgpu::Binding {
binding: 0,
resource: global_2d_uniform_buffer.get_binding_resource(),
}],
})
});
{
let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
let quad = Mesh::load(MeshType::Quad {
north_west: math::vec2(-0.5, 0.5),
north_east: math::vec2(0.5, 0.5),
south_west: math::vec2(-0.5, -0.5),
south_east: math::vec2(0.5, -0.5),
});
self.quad = Some(mesh_storage.add(quad));
}
let pipeline_layout =
render_graph
.device
.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
bind_group_layouts: &[&bind_group_layout],
});
let vertex_buffer_descriptor = get_vertex_buffer_descriptor();
let rect_data_size = mem::size_of::<RectData>();
let instance_buffer_descriptor = wgpu::VertexBufferDescriptor {
stride: rect_data_size as wgpu::BufferAddress,
step_mode: wgpu::InputStepMode::Instance,
attributes: &[
wgpu::VertexAttributeDescriptor {
format: wgpu::VertexFormat::Float2,
offset: 0,
shader_location: 3,
},
wgpu::VertexAttributeDescriptor {
format: wgpu::VertexFormat::Float2,
offset: 2 * 4,
shader_location: 4,
},
wgpu::VertexAttributeDescriptor {
format: wgpu::VertexFormat::Float4,
offset: 4 * 4,
shader_location: 5,
},
wgpu::VertexAttributeDescriptor {
format: wgpu::VertexFormat::Float,
offset: 8 * 4,
shader_location: 6,
},
],
};
let vs_module = render_graph.device.create_shader_module(&vs_bytes);
let fs_module = render_graph.device.create_shader_module(&fs_bytes);
let pipedesc = wgpu::RenderPipelineDescriptor {
layout: &pipeline_layout,
vertex_stage: wgpu::ProgrammableStageDescriptor {
module: &vs_module,
entry_point: "main",
},
fragment_stage: Some(wgpu::ProgrammableStageDescriptor {
module: &fs_module,
entry_point: "main",
}),
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
front_face: wgpu::FrontFace::Ccw,
cull_mode: wgpu::CullMode::None,
depth_bias: 0,
depth_bias_slope_scale: 0.0,
depth_bias_clamp: 0.0,
}),
primitive_topology: wgpu::PrimitiveTopology::TriangleList,
color_states: &[wgpu::ColorStateDescriptor {
format: wgpu::TextureFormat::Bgra8UnormSrgb,
color_blend: wgpu::BlendDescriptor {
src_factor: wgpu::BlendFactor::SrcAlpha,
dst_factor: wgpu::BlendFactor::OneMinusSrcAlpha,
operation: wgpu::BlendOperation::Add,
},
alpha_blend: wgpu::BlendDescriptor {
src_factor: wgpu::BlendFactor::One,
dst_factor: wgpu::BlendFactor::One,
operation: wgpu::BlendOperation::Add,
},
write_mask: wgpu::ColorWrite::ALL,
}],
depth_stencil_state: Some(wgpu::DepthStencilStateDescriptor {
format: self.depth_format,
depth_write_enabled: false,
depth_compare: wgpu::CompareFunction::Always,
stencil_front: wgpu::StencilStateFaceDescriptor::IGNORE,
stencil_back: wgpu::StencilStateFaceDescriptor::IGNORE,
stencil_read_mask: 0,
stencil_write_mask: 0,
}),
index_format: wgpu::IndexFormat::Uint16,
vertex_buffers: &[vertex_buffer_descriptor, instance_buffer_descriptor],
sample_count: self.msaa_samples as u32,
sample_mask: !0,
alpha_to_coverage_enabled: false,
};
self.pipeline = Some(render_graph.device.create_render_pipeline(&pipedesc));
}
fn render(
&mut self,
render_graph: &RenderGraphData,
pass: &mut wgpu::RenderPass,
_: &SwapChainOutput,
world: &mut World,
) {
let instance_buffer_infos = Some(self.create_rect_buffers(&render_graph.device, world));
pass.set_bind_group(0, self.bind_group.as_ref().unwrap(), &[]);
let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
for instance_buffer_info in instance_buffer_infos.as_ref().unwrap().iter() {
if let Some(mesh_asset) = mesh_storage.get_id_mut(instance_buffer_info.mesh_id) {
mesh_asset.setup_buffers(&render_graph.device);
pass.set_index_buffer(mesh_asset.index_buffer.as_ref().unwrap(), 0);
pass.set_vertex_buffers(0, &[(&mesh_asset.vertex_buffer.as_ref().unwrap(), 0)]);
pass.set_vertex_buffers(1, &[(&instance_buffer_info.buffer, 0)]);
pass.draw_indexed(
0..mesh_asset.indices.len() as u32,
0,
0..instance_buffer_info.instance_count as u32,
);
};
}
}
fn resize(&mut self, _: &RenderGraphData) {}
fn get_pipeline(&self) -> &wgpu::RenderPipeline {
self.pipeline.as_ref().unwrap()
}
}

View file

@ -1,25 +0,0 @@
#version 450
// vertex attributes
layout(location = 0) in vec4 a_Pos;
layout(location = 1) in vec4 a_Normal;
layout(location = 2) in vec2 a_Uv;
// instanced attributes (RectData)
layout (location = 3) in vec2 a_RectPosition;
layout (location = 4) in vec2 a_RectSize;
layout (location = 5) in vec4 a_RectColor;
layout (location = 6) in float a_RectZIndex;
layout(location = 0) out vec4 v_Color;
layout(set = 0, binding = 0) uniform Globals {
mat4 u_ViewProj;
};
void main() {
v_Color = a_RectColor;
vec4 position = a_Pos * vec4(a_RectSize, 0.0, 1.0);
position = position + vec4(a_RectPosition + a_RectSize / 2.0, -a_RectZIndex, 0.0);
gl_Position = u_ViewProj * position;
}

View file

@ -1,4 +1,4 @@
use crate::{asset::Handle, render::render_graph_2::{pipeline::PipelineDescriptor, RenderPass}};
use crate::{asset::Handle, render::render_graph::{pipeline::PipelineDescriptor, RenderPass}};
use legion::prelude::World;
// A set of draw calls. ex: get + draw meshes, get + draw instanced meshes, draw ui meshes, etc

View file

@ -2,7 +2,7 @@ use crate::{
asset::{AssetStorage, Handle, Mesh},
legion::prelude::*,
render::{
render_graph_2::{resource_name, RenderPass, Renderable, PipelineDescriptor, ShaderPipelineAssignments},
render_graph::{resource_name, RenderPass, Renderable, PipelineDescriptor, ShaderPipelineAssignments},
},
};

View file

@ -2,7 +2,7 @@ use crate::{
asset::{AssetStorage, Handle, Mesh},
legion::prelude::*,
render::{
render_graph_2::{resource_name, RenderPass, Renderable, ShaderUniforms, PipelineDescriptor},
render_graph::{resource_name, RenderPass, Renderable, ShaderUniforms, PipelineDescriptor},
Instanced,
},
};

View file

@ -1,7 +1,7 @@
use crate::{
asset::{AssetStorage, Mesh, Handle},
legion::prelude::*,
render::render_graph_2::{resource_name, RenderPass, ResourceInfo, PipelineDescriptor},
render::render_graph::{resource_name, RenderPass, ResourceInfo, PipelineDescriptor},
};
use zerocopy::AsBytes;

View file

@ -1,11 +1,29 @@
mod draw_target;
pub mod draw_targets;
mod pass;
pub mod passes;
mod pipeline;
mod pipeline_layout;
pub mod pipelines;
mod render_graph;
mod render_graph_data;
mod render_resource_manager;
mod renderable;
mod renderer;
pub mod renderers;
mod resource;
pub mod resource_name;
pub mod resource_provider;
pub mod resource_providers;
mod uniform;
mod uniforms;
pub use pass::Pass;
pub use pipeline::Pipeline;
pub use draw_target::*;
pub use pass::*;
pub use pipeline::*;
pub use pipeline_layout::*;
pub use render_graph::*;
pub use render_graph_data::*;
pub use render_resource_manager::RenderResourceManager;
pub use renderable::*;
pub use renderer::*;
pub use resource::*;
pub use resource_provider::*;
pub use uniform::*;
pub use uniforms::*;

View file

@ -1,15 +1,33 @@
use crate::render::render_graph::RenderGraphData;
use legion::world::World;
pub struct RenderPassColorAttachmentDescriptor {
/// The actual color attachment.
pub attachment: String,
pub trait Pass {
fn initialize(&self, render_graph: &mut RenderGraphData);
fn begin<'a>(
&mut self,
render_graph: &mut RenderGraphData,
world: &mut World,
encoder: &'a mut wgpu::CommandEncoder,
frame: &'a wgpu::SwapChainOutput,
) -> Option<wgpu::RenderPass<'a>>;
fn should_repeat(&self) -> bool;
fn resize(&self, render_graph: &mut RenderGraphData);
/// The resolve target for this color attachment, if any.
pub resolve_target: Option<String>,
/// The beginning-of-pass load operation for this color attachment.
pub load_op: wgpu::LoadOp,
/// The end-of-pass store operation for this color attachment.
pub store_op: wgpu::StoreOp,
/// The color that will be assigned to every pixel of this attachment when cleared.
pub clear_color: wgpu::Color,
}
pub struct RenderPassDepthStencilAttachmentDescriptor {
pub attachment: String,
pub depth_load_op: wgpu::LoadOp,
pub depth_store_op: wgpu::StoreOp,
pub clear_depth: f32,
pub stencil_load_op: wgpu::LoadOp,
pub stencil_store_op: wgpu::StoreOp,
pub clear_stencil: u32,
}
// A set of pipeline bindings and draw calls with color and depth outputs
pub struct PassDescriptor {
pub color_attachments: Vec<RenderPassColorAttachmentDescriptor>,
pub depth_stencil_attachment: Option<RenderPassDepthStencilAttachmentDescriptor>,
pub sample_count: u32,
}

View file

@ -1,4 +1,4 @@
use crate::render::render_graph_2::{
use crate::render::render_graph::{
resource_name, resource_providers::FrameTextureResourceProvider, PassDescriptor,
RenderGraphBuilder, RenderPassColorAttachmentDescriptor,
RenderPassDepthStencilAttachmentDescriptor, TextureDescriptor, TextureDimension,

View file

@ -1,16 +1,209 @@
use crate::render::RenderGraphData;
use legion::world::World;
use wgpu::SwapChainOutput;
use crate::{asset::{AssetStorage, Handle}, render::{
render_graph::{BindGroup, PipelineLayout},
shader::{Shader, ShaderStages},
}};
pub trait Pipeline {
fn initialize(&mut self, render_graph: &mut RenderGraphData, world: &mut World);
fn render(
&mut self,
render_graph: &RenderGraphData,
pass: &mut wgpu::RenderPass,
frame: &SwapChainOutput,
world: &mut World,
);
fn resize(&mut self, render_graph: &RenderGraphData);
fn get_pipeline(&self) -> &wgpu::RenderPipeline;
#[derive(Clone, Debug)]
pub struct VertexBufferDescriptor {
pub stride: wgpu::BufferAddress,
pub step_mode: wgpu::InputStepMode,
pub attributes: Vec<wgpu::VertexAttributeDescriptor>,
}
impl<'a> Into<wgpu::VertexBufferDescriptor<'a>> for &'a VertexBufferDescriptor {
fn into(self) -> wgpu::VertexBufferDescriptor<'a> {
wgpu::VertexBufferDescriptor {
step_mode: self.step_mode,
stride: self.stride,
attributes: &self.attributes,
}
}
}
#[derive(Clone, Debug)]
pub enum PipelineLayoutType {
Manual(PipelineLayout),
Reflected(Option<PipelineLayout>),
}
#[derive(Clone, Debug)]
pub struct PipelineDescriptor {
pub draw_targets: Vec<String>,
pub layout: PipelineLayoutType,
pub shader_stages: ShaderStages,
pub rasterization_state: Option<wgpu::RasterizationStateDescriptor>,
/// The primitive topology used to interpret vertices.
pub primitive_topology: wgpu::PrimitiveTopology,
/// The effect of draw calls on the color aspect of the output target.
pub color_states: Vec<wgpu::ColorStateDescriptor>,
/// The effect of draw calls on the depth and stencil aspects of the output target, if any.
pub depth_stencil_state: Option<wgpu::DepthStencilStateDescriptor>,
/// The format of any index buffers used with this pipeline.
pub index_format: wgpu::IndexFormat,
/// The format of any vertex buffers used with this pipeline.
pub vertex_buffer_descriptors: Vec<VertexBufferDescriptor>,
/// The number of samples calculated per pixel (for MSAA).
pub sample_count: u32,
/// Bitmask that restricts the samples of a pixel modified by this pipeline.
pub sample_mask: u32,
/// When enabled, produces another sample mask per pixel based on the alpha output value, that
/// is ANDed with the sample_mask and the primitive coverage to restrict the set of samples
/// affected by a primitive.
/// The implicit mask produced for alpha of zero is guaranteed to be zero, and for alpha of one
/// is guaranteed to be all 1-s.
pub alpha_to_coverage_enabled: bool,
}
impl PipelineDescriptor {
fn new(vertex_shader: Handle<Shader>) -> Self {
PipelineDescriptor {
layout: PipelineLayoutType::Reflected(None),
color_states: Vec::new(),
depth_stencil_state: None,
draw_targets: Vec::new(),
shader_stages: ShaderStages::new(vertex_shader),
vertex_buffer_descriptors: Vec::new(),
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
front_face: wgpu::FrontFace::Ccw,
cull_mode: wgpu::CullMode::Back,
depth_bias: 0,
depth_bias_slope_scale: 0.0,
depth_bias_clamp: 0.0,
}),
primitive_topology: wgpu::PrimitiveTopology::TriangleList,
index_format: wgpu::IndexFormat::Uint16,
sample_count: 1,
sample_mask: !0,
alpha_to_coverage_enabled: false,
}
}
pub fn get_layout(&self) -> Option<&PipelineLayout> {
match self.layout {
PipelineLayoutType::Reflected(ref layout) => layout.as_ref(),
PipelineLayoutType::Manual(ref layout) => Some(layout),
}
}
pub fn get_layout_mut(&mut self) -> Option<&mut PipelineLayout> {
match self.layout {
PipelineLayoutType::Reflected(ref mut layout) => layout.as_mut(),
PipelineLayoutType::Manual(ref mut layout) => Some(layout),
}
}
}
impl PipelineDescriptor {
pub fn build(shader_storage: &mut AssetStorage<Shader>, vertex_shader: Shader) -> PipelineBuilder {
PipelineBuilder::new(shader_storage, vertex_shader)
}
}
pub struct PipelineBuilder<'a> {
pipeline: PipelineDescriptor,
shader_storage: &'a mut AssetStorage<Shader>,
}
impl<'a> PipelineBuilder<'a> {
pub fn new(shader_storage: &'a mut AssetStorage<Shader>, vertex_shader: Shader) -> Self {
let vertex_shader_handle = shader_storage.add(vertex_shader);
PipelineBuilder {
pipeline: PipelineDescriptor::new(vertex_shader_handle),
shader_storage,
}
}
pub fn build(self) -> PipelineDescriptor {
self.pipeline
}
pub fn with_fragment_shader(mut self, fragment_shader: Shader) -> Self {
let fragment_shader_handle = self.shader_storage.add(fragment_shader);
self.pipeline.shader_stages.fragment = Some(fragment_shader_handle);
self
}
pub fn add_color_state(mut self, color_state_descriptor: wgpu::ColorStateDescriptor) -> Self {
self.pipeline.color_states.push(color_state_descriptor);
self
}
pub fn with_depth_stencil_state(
mut self,
depth_stencil_state: wgpu::DepthStencilStateDescriptor,
) -> Self {
if let Some(_) = self.pipeline.depth_stencil_state {
panic!("Depth stencil state has already been set");
}
self.pipeline.depth_stencil_state = Some(depth_stencil_state);
self
}
pub fn add_bind_group(mut self, bind_group: BindGroup) -> Self {
if let PipelineLayoutType::Reflected(_) = self.pipeline.layout {
self.pipeline.layout = PipelineLayoutType::Manual(PipelineLayout::new());
}
if let PipelineLayoutType::Manual(ref mut layout) = self.pipeline.layout {
layout.bind_groups.push(bind_group);
}
self
}
pub fn add_vertex_buffer_descriptor(
mut self,
vertex_buffer_descriptor: VertexBufferDescriptor,
) -> Self {
self.pipeline
.vertex_buffer_descriptors
.push(vertex_buffer_descriptor);
self
}
pub fn with_index_format(mut self, index_format: wgpu::IndexFormat) -> Self {
self.pipeline.index_format = index_format;
self
}
pub fn add_draw_target(mut self, name: &str) -> Self {
self.pipeline.draw_targets.push(name.to_string());
self
}
pub fn with_rasterization_state(
mut self,
rasterization_state: wgpu::RasterizationStateDescriptor,
) -> Self {
self.pipeline.rasterization_state = Some(rasterization_state);
self
}
pub fn with_primitive_topology(mut self, primitive_topology: wgpu::PrimitiveTopology) -> Self {
self.pipeline.primitive_topology = primitive_topology;
self
}
pub fn with_sample_count(mut self, sample_count: u32) -> Self {
self.pipeline.sample_count = sample_count;
self
}
pub fn with_alpha_to_coverage_enabled(mut self, alpha_to_coverage_enabled: bool) -> Self {
self.pipeline.alpha_to_coverage_enabled = alpha_to_coverage_enabled;
self
}
pub fn with_sample_mask(mut self, sample_mask: u32) -> Self {
self.pipeline.sample_mask = sample_mask;
self
}
}

View file

@ -1,7 +1,7 @@
use crate::{
asset::AssetStorage,
render::{
render_graph_2::{resource_name, PipelineDescriptor, RenderGraphBuilder},
render_graph::{resource_name, PipelineDescriptor, RenderGraphBuilder},
shader::{Shader, ShaderStage},
Vertex,
},

View file

@ -1,8 +1,8 @@
use crate::{
asset::AssetStorage,
render::{
render_graph_2::{
resource_name, pipeline_layout::*, PipelineDescriptor,
render_graph::{
resource_name, PipelineDescriptor,
RenderGraphBuilder,
},
shader::{Shader, ShaderStage},

View file

@ -1,8 +1,8 @@
use crate::{
asset::AssetStorage,
render::{
render_graph_2::{
pipeline_layout::*, resource_providers::RectData,
render_graph::{
resource_providers::RectData,
PipelineDescriptor, RenderGraphBuilder, VertexBufferDescriptor, resource_name,
},
shader::{Shader, ShaderStage},

View file

@ -1,182 +1,115 @@
use crate::render::{Pass, Pipeline, RenderGraphData, RenderResourceManager};
use legion::world::World;
use std::{collections::HashMap, ops::Deref};
use crate::{
asset::{AssetStorage, Handle},
render::render_graph::{
DrawTarget, PassDescriptor, PipelineDescriptor, ResourceProvider, TextureDescriptor,
},
};
use std::collections::{HashMap, HashSet};
pub struct RenderGraph {
pub data: Option<RenderGraphData>,
passes: HashMap<String, Box<dyn Pass>>,
pipelines: HashMap<String, Box<dyn Pipeline>>,
pass_pipelines: HashMap<String, Vec<String>>,
render_resource_managers: Vec<Box<dyn RenderResourceManager>>,
swap_chain: Option<wgpu::SwapChain>,
pub pipeline_descriptors: HashSet<Handle<PipelineDescriptor>>,
// TODO: make this ordered
pub pass_descriptors: HashMap<String, PassDescriptor>,
pub pass_pipelines: HashMap<String, Vec<Handle<PipelineDescriptor>>>,
pub resource_providers: Vec<Box<dyn ResourceProvider>>,
pub queued_textures: Vec<(String, TextureDescriptor)>,
pub draw_targets: HashMap<String, DrawTarget>,
}
impl Default for RenderGraph {
fn default() -> Self {
RenderGraph {
pipeline_descriptors: HashSet::new(),
pass_descriptors: HashMap::new(),
pass_pipelines: HashMap::new(),
resource_providers: Vec::new(),
queued_textures: Vec::new(),
draw_targets: HashMap::new(),
}
}
}
impl RenderGraph {
pub fn new() -> Self {
RenderGraph {
passes: HashMap::new(),
pipelines: HashMap::new(),
pass_pipelines: HashMap::new(),
render_resource_managers: Vec::new(),
data: None,
swap_chain: None,
}
}
pub fn add_pipeline(&mut self, pass: &str, pipeline: Handle<PipelineDescriptor>) {
self.pipeline_descriptors.insert(pipeline.clone());
pub fn initialize(&mut self, world: &mut World) {
let adapter = wgpu::Adapter::request(
&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::Default,
},
wgpu::BackendBit::PRIMARY,
)
.unwrap();
let (device, queue) = adapter.request_device(&wgpu::DeviceDescriptor {
extensions: wgpu::Extensions {
anisotropic_filtering: false,
},
limits: wgpu::Limits::default(),
});
let (surface, window_size) = {
let window = world.resources.get::<winit::window::Window>().unwrap();
let surface = wgpu::Surface::create(window.deref());
let window_size = window.inner_size();
(surface, window_size)
};
let swap_chain_descriptor = wgpu::SwapChainDescriptor {
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
format: wgpu::TextureFormat::Bgra8UnormSrgb,
width: window_size.width,
height: window_size.height,
present_mode: wgpu::PresentMode::Vsync,
};
self.swap_chain = Some(device.create_swap_chain(&surface, &swap_chain_descriptor));
self.data = Some(RenderGraphData::new(
device,
swap_chain_descriptor,
queue,
surface,
));
let data = self.data.as_mut().unwrap();
for render_resource_manager in self.render_resource_managers.iter_mut() {
render_resource_manager.initialize(data, world);
if let None = self.pass_pipelines.get(pass) {
self.pass_pipelines.insert(pass.to_string(), Vec::new());
}
for pass in self.passes.values_mut() {
pass.initialize(data);
}
for pipeline in self.pipelines.values_mut() {
pipeline.initialize(data, world);
}
self.resize(window_size.width, window_size.height, world);
}
pub fn render(&mut self, world: &mut World) {
if self.passes.len() == 0 {
return;
}
let frame = self
.swap_chain
.as_mut()
.unwrap()
.get_next_texture()
.expect("Timeout when acquiring next swap chain texture");
let data = self.data.as_mut().unwrap();
let mut encoder = data
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
for render_resource_manager in self.render_resource_managers.iter_mut() {
render_resource_manager.update(data, &mut encoder, world);
}
for (pass_name, pass) in self.passes.iter_mut() {
loop {
let render_pass = pass.begin(data, world, &mut encoder, &frame);
if let Some(mut render_pass) = render_pass {
if let Some(pipeline_names) = self.pass_pipelines.get(pass_name) {
for pipeline_name in pipeline_names.iter() {
let pipeline = self.pipelines.get_mut(pipeline_name).unwrap();
render_pass.set_pipeline(pipeline.get_pipeline());
pipeline.render(data, &mut render_pass, &frame, world);
}
}
if !pass.should_repeat() {
break;
}
}
}
}
let command_buffer = encoder.finish();
data.queue.submit(&[command_buffer]);
}
pub fn resize(&mut self, width: u32, height: u32, world: &mut World) {
let data = self.data.as_mut().unwrap();
data.swap_chain_descriptor.width = width;
data.swap_chain_descriptor.height = height;
self.swap_chain = Some(
data.device
.create_swap_chain(&data.surface, &data.swap_chain_descriptor),
);
let mut encoder = data
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
for render_resource_manager in self.render_resource_managers.iter_mut() {
render_resource_manager.resize(data, &mut encoder, world);
}
let command_buffer = encoder.finish();
for pass in self.passes.values_mut() {
pass.resize(data);
}
for pipeline in self.pipelines.values_mut() {
pipeline.resize(data);
}
data.queue.submit(&[command_buffer]);
}
pub fn add_render_resource_manager(
&mut self,
render_resource_manager: Box<dyn RenderResourceManager>,
) {
self.render_resource_managers.push(render_resource_manager);
}
pub fn set_pipeline(
&mut self,
pass_name: &str,
pipeline_name: &str,
pipeline: Box<dyn Pipeline>,
) {
self.pipelines.insert(pipeline_name.to_string(), pipeline);
if let None = self.pass_pipelines.get_mut(pass_name) {
let pipelines = Vec::new();
self.pass_pipelines.insert(pass_name.to_string(), pipelines);
};
let current_pass_pipelines = self.pass_pipelines.get_mut(pass_name).unwrap();
current_pass_pipelines.push(pipeline_name.to_string());
}
pub fn set_pass(&mut self, name: &str, pass: Box<dyn Pass>) {
self.passes.insert(name.to_string(), pass);
let pass_pipelines = self.pass_pipelines.get_mut(pass).unwrap();
pass_pipelines.push(pipeline);
}
}
pub struct RenderGraphBuilder {
render_graph: RenderGraph,
current_pass: Option<String>,
}
impl RenderGraphBuilder {
pub fn new() -> Self {
RenderGraphBuilder {
render_graph: RenderGraph::default(),
current_pass: None,
}
}
pub fn add_pass(mut self, name: &str, pass: PassDescriptor) -> Self {
self.current_pass = Some(name.to_string());
self.render_graph
.pass_descriptors
.insert(name.to_string(), pass);
self
}
pub fn add_pipeline(
mut self,
pipeline_descriptor_storage: &mut AssetStorage<PipelineDescriptor>,
pipeline: PipelineDescriptor,
) -> Self {
if let Some(ref pass) = self.current_pass {
let pipeline_descriptor_handle = pipeline_descriptor_storage.add(pipeline);
self.render_graph
.add_pipeline(&pass, pipeline_descriptor_handle);
}
self
}
pub fn add_pipeline_to_pass(
mut self,
pass: &str,
pipeline_descriptor_storage: &mut AssetStorage<PipelineDescriptor>,
pipeline: PipelineDescriptor,
) -> Self {
let pipeline_descriptor_handle = pipeline_descriptor_storage.add(pipeline);
self.render_graph
.add_pipeline(pass, pipeline_descriptor_handle);
self
}
pub fn add_resource_provider(mut self, resource_provider: Box<dyn ResourceProvider>) -> Self {
self.render_graph.resource_providers.push(resource_provider);
self
}
pub fn add_texture(mut self, name: &str, texture_descriptor: TextureDescriptor) -> Self {
self.render_graph
.queued_textures
.push((name.to_string(), texture_descriptor));
self
}
pub fn add_draw_target(mut self, name: &str, draw_target: DrawTarget) -> Self {
self.render_graph
.draw_targets
.insert(name.to_string(), draw_target);
self
}
pub fn build(self) -> RenderGraph {
self.render_graph
}
}

View file

@ -1,67 +0,0 @@
use crate::render::UniformBuffer;
use std::collections::HashMap;
pub struct RenderGraphData {
pub swap_chain_descriptor: wgpu::SwapChainDescriptor,
pub device: wgpu::Device,
pub queue: wgpu::Queue,
pub surface: wgpu::Surface,
textures: HashMap<String, wgpu::TextureView>,
samplers: HashMap<String, wgpu::Sampler>,
uniform_buffers: HashMap<String, UniformBuffer>,
bind_group_layouts: HashMap<String, wgpu::BindGroupLayout>,
}
impl RenderGraphData {
pub fn new(
device: wgpu::Device,
swap_chain_descriptor: wgpu::SwapChainDescriptor,
queue: wgpu::Queue,
surface: wgpu::Surface,
) -> Self {
RenderGraphData {
textures: HashMap::new(),
samplers: HashMap::new(),
uniform_buffers: HashMap::new(),
bind_group_layouts: HashMap::new(),
device,
swap_chain_descriptor,
queue,
surface,
}
}
pub fn set_uniform_buffer(&mut self, name: &str, uniform_buffer: UniformBuffer) {
self.uniform_buffers
.insert(name.to_string(), uniform_buffer);
}
pub fn get_uniform_buffer(&self, name: &str) -> Option<&UniformBuffer> {
self.uniform_buffers.get(name)
}
pub fn set_bind_group_layout(&mut self, name: &str, bind_group_layout: wgpu::BindGroupLayout) {
self.bind_group_layouts
.insert(name.to_string(), bind_group_layout);
}
pub fn get_bind_group_layout(&self, name: &str) -> Option<&wgpu::BindGroupLayout> {
self.bind_group_layouts.get(name)
}
pub fn set_texture(&mut self, name: &str, texture: wgpu::TextureView) {
self.textures.insert(name.to_string(), texture);
}
pub fn get_texture(&self, name: &str) -> Option<&wgpu::TextureView> {
self.textures.get(name)
}
pub fn set_sampler(&mut self, name: &str, sampler: wgpu::Sampler) {
self.samplers.insert(name.to_string(), sampler);
}
pub fn get_sampler(&self, name: &str) -> Option<&wgpu::Sampler> {
self.samplers.get(name)
}
}

View file

@ -1,18 +0,0 @@
use crate::render::RenderGraphData;
use legion::world::World;
pub trait RenderResourceManager {
fn initialize(&self, render_graph: &mut RenderGraphData, world: &mut World);
fn update<'a>(
&mut self,
render_graph: &mut RenderGraphData,
encoder: &'a mut wgpu::CommandEncoder,
world: &mut World,
);
fn resize<'a>(
&self,
render_graph: &mut RenderGraphData,
encoder: &'a mut wgpu::CommandEncoder,
world: &mut World,
);
}

View file

@ -1,6 +1,6 @@
use crate::{
asset::{AssetStorage, Handle},
render::{render_graph_2::RenderGraph, Shader, ShaderSource},
render::{render_graph::RenderGraph, Shader, ShaderSource},
};
use legion::prelude::*;
use std::collections::{HashMap, HashSet};

View file

@ -1,6 +1,6 @@
use crate::{
legion::prelude::*,
render::render_graph_2::{
render::render_graph::{
resource::DynamicUniformBufferInfo, PipelineDescriptor, RenderGraph, ResourceInfo,
TextureDescriptor,
},

View file

@ -2,7 +2,7 @@ use crate::{
asset::{AssetStorage, Handle},
legion::prelude::*,
render::{
render_graph_2::{
render_graph::{
resource_name, update_shader_assignments, BindGroup, BindType,
DynamicUniformBufferInfo, PassDescriptor, PipelineDescriptor, PipelineLayout,
PipelineLayoutType, RenderGraph, RenderPass, RenderPassColorAttachmentDescriptor,
@ -166,7 +166,7 @@ impl WgpuRenderer {
entry_point: "main",
},
fragment_stage: match fragment_shader {
Some(fragment_shader) => Some(wgpu::ProgrammableStageDescriptor {
Some(_) => Some(wgpu::ProgrammableStageDescriptor {
entry_point: "main",
module: fragment_shader_module.as_ref().unwrap(),
}),

View file

@ -1,4 +1,4 @@
use crate::render::render_graph_2::Renderer;
use crate::render::render_graph::Renderer;
use legion::prelude::*;
pub trait ResourceProvider {

View file

@ -1,5 +1,5 @@
use crate::render::{
render_graph_2::{resource_name, Renderer, ResourceProvider},
render_graph::{resource_name, Renderer, ResourceProvider},
ActiveCamera2d, Camera,
};
use legion::prelude::*;

View file

@ -1,5 +1,5 @@
use crate::render::{
render_graph_2::{resource_name, Renderer, ResourceProvider},
render_graph::{resource_name, Renderer, ResourceProvider},
ActiveCamera, Camera,
};
use bevy_transform::prelude::LocalToWorld;

View file

@ -1,6 +1,6 @@
use crate::{
prelude::World,
render::render_graph_2::{Renderer, ResourceProvider, TextureDescriptor},
render::render_graph::{Renderer, ResourceProvider, TextureDescriptor},
};
pub struct FrameTextureResourceProvider {

View file

@ -1,5 +1,5 @@
use crate::render::{
render_graph_2::{resource_name, Renderer, ResourceProvider},
render_graph::{resource_name, Renderer, ResourceProvider},
Light, LightRaw,
};
use bevy_transform::prelude::{LocalToWorld, Translation};

View file

@ -2,7 +2,7 @@ use crate::{
asset::{Asset, AssetStorage, Handle, Mesh, MeshType},
ecs, math,
prelude::Node,
render::render_graph_2::{resource_name, Renderer, ResourceProvider},
render::render_graph::{resource_name, Renderer, ResourceProvider},
};
use bevy_transform::prelude::Parent;
use legion::prelude::*;

View file

@ -1,6 +1,5 @@
use crate::{
legion::prelude::World,
render::render_graph_2::{
render::render_graph::{
resource::DynamicUniformBufferInfo, AsUniforms, Renderable, Renderer, ResourceProvider,
},
};

View file

@ -4,7 +4,7 @@ use crate::{
prelude::{Entity, World},
},
math::Vec4,
render::render_graph_2::{BindType, UniformPropertyType},
render::render_graph::{BindType, UniformPropertyType},
};
use legion::storage::Component;
use zerocopy::AsBytes;

View file

@ -1,4 +1,4 @@
use crate::render::render_graph_2::{
use crate::render::render_graph::{
uniform::{AsUniforms, UniformInfo},
BindType, UniformPropertyType,
};

View file

@ -1,7 +1,7 @@
use crate::{
math,
math::Vec4,
render::render_graph_2::{
render::render_graph::{
uniform::{AsUniforms, GetBytes, UniformInfo},
BindType, ShaderDefSuffixProvider, UniformPropertyType,
},

View file

@ -1,29 +0,0 @@
mod draw_target;
pub mod draw_targets;
mod pass;
pub mod passes;
mod pipeline;
mod pipeline_layout;
pub mod pipelines;
mod render_graph;
mod renderable;
mod renderer;
pub mod renderers;
mod resource;
pub mod resource_name;
pub mod resource_provider;
pub mod resource_providers;
mod uniform;
mod uniforms;
pub use draw_target::*;
pub use pass::*;
pub use pipeline::*;
pub use pipeline_layout::*;
pub use render_graph::*;
pub use renderable::*;
pub use renderer::*;
pub use resource::*;
pub use resource_provider::*;
pub use uniform::*;
pub use uniforms::*;

View file

@ -1,33 +0,0 @@
pub struct RenderPassColorAttachmentDescriptor {
/// The actual color attachment.
pub attachment: String,
/// The resolve target for this color attachment, if any.
pub resolve_target: Option<String>,
/// The beginning-of-pass load operation for this color attachment.
pub load_op: wgpu::LoadOp,
/// The end-of-pass store operation for this color attachment.
pub store_op: wgpu::StoreOp,
/// The color that will be assigned to every pixel of this attachment when cleared.
pub clear_color: wgpu::Color,
}
pub struct RenderPassDepthStencilAttachmentDescriptor {
pub attachment: String,
pub depth_load_op: wgpu::LoadOp,
pub depth_store_op: wgpu::StoreOp,
pub clear_depth: f32,
pub stencil_load_op: wgpu::LoadOp,
pub stencil_store_op: wgpu::StoreOp,
pub clear_stencil: u32,
}
// A set of pipeline bindings and draw calls with color and depth outputs
pub struct PassDescriptor {
pub color_attachments: Vec<RenderPassColorAttachmentDescriptor>,
pub depth_stencil_attachment: Option<RenderPassDepthStencilAttachmentDescriptor>,
pub sample_count: u32,
}

View file

@ -1,209 +0,0 @@
use crate::{asset::{AssetStorage, Handle}, render::{
render_graph_2::{BindGroup, PipelineLayout},
shader::{Shader, ShaderStages},
}};
#[derive(Clone, Debug)]
pub struct VertexBufferDescriptor {
pub stride: wgpu::BufferAddress,
pub step_mode: wgpu::InputStepMode,
pub attributes: Vec<wgpu::VertexAttributeDescriptor>,
}
impl<'a> Into<wgpu::VertexBufferDescriptor<'a>> for &'a VertexBufferDescriptor {
fn into(self) -> wgpu::VertexBufferDescriptor<'a> {
wgpu::VertexBufferDescriptor {
step_mode: self.step_mode,
stride: self.stride,
attributes: &self.attributes,
}
}
}
#[derive(Clone, Debug)]
pub enum PipelineLayoutType {
Manual(PipelineLayout),
Reflected(Option<PipelineLayout>),
}
#[derive(Clone, Debug)]
pub struct PipelineDescriptor {
pub draw_targets: Vec<String>,
pub layout: PipelineLayoutType,
pub shader_stages: ShaderStages,
pub rasterization_state: Option<wgpu::RasterizationStateDescriptor>,
/// The primitive topology used to interpret vertices.
pub primitive_topology: wgpu::PrimitiveTopology,
/// The effect of draw calls on the color aspect of the output target.
pub color_states: Vec<wgpu::ColorStateDescriptor>,
/// The effect of draw calls on the depth and stencil aspects of the output target, if any.
pub depth_stencil_state: Option<wgpu::DepthStencilStateDescriptor>,
/// The format of any index buffers used with this pipeline.
pub index_format: wgpu::IndexFormat,
/// The format of any vertex buffers used with this pipeline.
pub vertex_buffer_descriptors: Vec<VertexBufferDescriptor>,
/// The number of samples calculated per pixel (for MSAA).
pub sample_count: u32,
/// Bitmask that restricts the samples of a pixel modified by this pipeline.
pub sample_mask: u32,
/// When enabled, produces another sample mask per pixel based on the alpha output value, that
/// is ANDed with the sample_mask and the primitive coverage to restrict the set of samples
/// affected by a primitive.
/// The implicit mask produced for alpha of zero is guaranteed to be zero, and for alpha of one
/// is guaranteed to be all 1-s.
pub alpha_to_coverage_enabled: bool,
}
impl PipelineDescriptor {
fn new(vertex_shader: Handle<Shader>) -> Self {
PipelineDescriptor {
layout: PipelineLayoutType::Reflected(None),
color_states: Vec::new(),
depth_stencil_state: None,
draw_targets: Vec::new(),
shader_stages: ShaderStages::new(vertex_shader),
vertex_buffer_descriptors: Vec::new(),
rasterization_state: Some(wgpu::RasterizationStateDescriptor {
front_face: wgpu::FrontFace::Ccw,
cull_mode: wgpu::CullMode::Back,
depth_bias: 0,
depth_bias_slope_scale: 0.0,
depth_bias_clamp: 0.0,
}),
primitive_topology: wgpu::PrimitiveTopology::TriangleList,
index_format: wgpu::IndexFormat::Uint16,
sample_count: 1,
sample_mask: !0,
alpha_to_coverage_enabled: false,
}
}
pub fn get_layout(&self) -> Option<&PipelineLayout> {
match self.layout {
PipelineLayoutType::Reflected(ref layout) => layout.as_ref(),
PipelineLayoutType::Manual(ref layout) => Some(layout),
}
}
pub fn get_layout_mut(&mut self) -> Option<&mut PipelineLayout> {
match self.layout {
PipelineLayoutType::Reflected(ref mut layout) => layout.as_mut(),
PipelineLayoutType::Manual(ref mut layout) => Some(layout),
}
}
}
impl PipelineDescriptor {
pub fn build(shader_storage: &mut AssetStorage<Shader>, vertex_shader: Shader) -> PipelineBuilder {
PipelineBuilder::new(shader_storage, vertex_shader)
}
}
pub struct PipelineBuilder<'a> {
pipeline: PipelineDescriptor,
shader_storage: &'a mut AssetStorage<Shader>,
}
impl<'a> PipelineBuilder<'a> {
pub fn new(shader_storage: &'a mut AssetStorage<Shader>, vertex_shader: Shader) -> Self {
let vertex_shader_handle = shader_storage.add(vertex_shader);
PipelineBuilder {
pipeline: PipelineDescriptor::new(vertex_shader_handle),
shader_storage,
}
}
pub fn build(self) -> PipelineDescriptor {
self.pipeline
}
pub fn with_fragment_shader(mut self, fragment_shader: Shader) -> Self {
let fragment_shader_handle = self.shader_storage.add(fragment_shader);
self.pipeline.shader_stages.fragment = Some(fragment_shader_handle);
self
}
pub fn add_color_state(mut self, color_state_descriptor: wgpu::ColorStateDescriptor) -> Self {
self.pipeline.color_states.push(color_state_descriptor);
self
}
pub fn with_depth_stencil_state(
mut self,
depth_stencil_state: wgpu::DepthStencilStateDescriptor,
) -> Self {
if let Some(_) = self.pipeline.depth_stencil_state {
panic!("Depth stencil state has already been set");
}
self.pipeline.depth_stencil_state = Some(depth_stencil_state);
self
}
pub fn add_bind_group(mut self, bind_group: BindGroup) -> Self {
if let PipelineLayoutType::Reflected(_) = self.pipeline.layout {
self.pipeline.layout = PipelineLayoutType::Manual(PipelineLayout::new());
}
if let PipelineLayoutType::Manual(ref mut layout) = self.pipeline.layout {
layout.bind_groups.push(bind_group);
}
self
}
pub fn add_vertex_buffer_descriptor(
mut self,
vertex_buffer_descriptor: VertexBufferDescriptor,
) -> Self {
self.pipeline
.vertex_buffer_descriptors
.push(vertex_buffer_descriptor);
self
}
pub fn with_index_format(mut self, index_format: wgpu::IndexFormat) -> Self {
self.pipeline.index_format = index_format;
self
}
pub fn add_draw_target(mut self, name: &str) -> Self {
self.pipeline.draw_targets.push(name.to_string());
self
}
pub fn with_rasterization_state(
mut self,
rasterization_state: wgpu::RasterizationStateDescriptor,
) -> Self {
self.pipeline.rasterization_state = Some(rasterization_state);
self
}
pub fn with_primitive_topology(mut self, primitive_topology: wgpu::PrimitiveTopology) -> Self {
self.pipeline.primitive_topology = primitive_topology;
self
}
pub fn with_sample_count(mut self, sample_count: u32) -> Self {
self.pipeline.sample_count = sample_count;
self
}
pub fn with_alpha_to_coverage_enabled(mut self, alpha_to_coverage_enabled: bool) -> Self {
self.pipeline.alpha_to_coverage_enabled = alpha_to_coverage_enabled;
self
}
pub fn with_sample_mask(mut self, sample_mask: u32) -> Self {
self.pipeline.sample_mask = sample_mask;
self
}
}

View file

@ -1,9 +0,0 @@
#version 450
layout(location = 0) in vec4 v_Color;
layout(location = 0) out vec4 o_Target;
void main() {
o_Target = v_Color;
}

View file

@ -1,115 +0,0 @@
use crate::{
asset::{AssetStorage, Handle},
render::render_graph_2::{
DrawTarget, PassDescriptor, PipelineDescriptor, ResourceProvider, TextureDescriptor,
},
};
use std::collections::{HashMap, HashSet};
pub struct RenderGraph {
pub pipeline_descriptors: HashSet<Handle<PipelineDescriptor>>,
// TODO: make this ordered
pub pass_descriptors: HashMap<String, PassDescriptor>,
pub pass_pipelines: HashMap<String, Vec<Handle<PipelineDescriptor>>>,
pub resource_providers: Vec<Box<dyn ResourceProvider>>,
pub queued_textures: Vec<(String, TextureDescriptor)>,
pub draw_targets: HashMap<String, DrawTarget>,
}
impl Default for RenderGraph {
fn default() -> Self {
RenderGraph {
pipeline_descriptors: HashSet::new(),
pass_descriptors: HashMap::new(),
pass_pipelines: HashMap::new(),
resource_providers: Vec::new(),
queued_textures: Vec::new(),
draw_targets: HashMap::new(),
}
}
}
impl RenderGraph {
pub fn add_pipeline(&mut self, pass: &str, pipeline: Handle<PipelineDescriptor>) {
self.pipeline_descriptors.insert(pipeline.clone());
if let None = self.pass_pipelines.get(pass) {
self.pass_pipelines.insert(pass.to_string(), Vec::new());
}
let pass_pipelines = self.pass_pipelines.get_mut(pass).unwrap();
pass_pipelines.push(pipeline);
}
}
pub struct RenderGraphBuilder {
render_graph: RenderGraph,
current_pass: Option<String>,
}
impl RenderGraphBuilder {
pub fn new() -> Self {
RenderGraphBuilder {
render_graph: RenderGraph::default(),
current_pass: None,
}
}
pub fn add_pass(mut self, name: &str, pass: PassDescriptor) -> Self {
self.current_pass = Some(name.to_string());
self.render_graph
.pass_descriptors
.insert(name.to_string(), pass);
self
}
pub fn add_pipeline(
mut self,
pipeline_descriptor_storage: &mut AssetStorage<PipelineDescriptor>,
pipeline: PipelineDescriptor,
) -> Self {
if let Some(ref pass) = self.current_pass {
let pipeline_descriptor_handle = pipeline_descriptor_storage.add(pipeline);
self.render_graph
.add_pipeline(&pass, pipeline_descriptor_handle);
}
self
}
pub fn add_pipeline_to_pass(
mut self,
pass: &str,
pipeline_descriptor_storage: &mut AssetStorage<PipelineDescriptor>,
pipeline: PipelineDescriptor,
) -> Self {
let pipeline_descriptor_handle = pipeline_descriptor_storage.add(pipeline);
self.render_graph
.add_pipeline(pass, pipeline_descriptor_handle);
self
}
pub fn add_resource_provider(mut self, resource_provider: Box<dyn ResourceProvider>) -> Self {
self.render_graph.resource_providers.push(resource_provider);
self
}
pub fn add_texture(mut self, name: &str, texture_descriptor: TextureDescriptor) -> Self {
self.render_graph
.queued_textures
.push((name.to_string(), texture_descriptor));
self
}
pub fn add_draw_target(mut self, name: &str, draw_target: DrawTarget) -> Self {
self.render_graph
.draw_targets
.insert(name.to_string(), draw_target);
self
}
pub fn build(self) -> RenderGraph {
self.render_graph
}
}

View file

@ -1,72 +0,0 @@
use crate::{math, render::*};
use legion::prelude::*;
use std::mem;
use zerocopy::{AsBytes, FromBytes};
pub const GLOBAL_2D_UNIFORM_BUFFER_NAME: &str = "global_2d";
#[repr(C)]
#[derive(Clone, Copy, AsBytes, FromBytes)]
pub struct Global2dUniforms {
pub projection_matrix: [[f32; 4]; 4],
}
pub struct Global2dResourceManager;
impl RenderResourceManager for Global2dResourceManager {
fn initialize(&self, render_graph: &mut RenderGraphData, _: &mut World) {
let uniform_size = mem::size_of::<Global2dUniforms>() as wgpu::BufferAddress;
let ui_uniforms = Global2dUniforms {
projection_matrix: math::Mat4::identity().to_cols_array_2d(),
};
let buffer = render_graph.device.create_buffer_with_data(
ui_uniforms.as_bytes(),
wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
);
let uniform_buffer = UniformBuffer {
buffer,
size: uniform_size,
};
render_graph.set_uniform_buffer(GLOBAL_2D_UNIFORM_BUFFER_NAME, uniform_buffer);
}
fn update<'a>(
&mut self,
_render_graph: &mut RenderGraphData,
_encoder: &'a mut wgpu::CommandEncoder,
_world: &mut World,
) {
}
fn resize<'a>(
&self,
render_graph: &mut RenderGraphData,
encoder: &'a mut wgpu::CommandEncoder,
world: &mut World,
) {
for (mut camera, _) in <(Write<Camera>, Read<ActiveCamera2d>)>::query().iter_mut(world) {
camera.update(
render_graph.swap_chain_descriptor.width,
render_graph.swap_chain_descriptor.height,
);
let camera_matrix: [[f32; 4]; 4] = camera.view_matrix.to_cols_array_2d();
let matrix_size = mem::size_of::<[[f32; 4]; 4]>() as u64;
let temp_camera_buffer = render_graph
.device
.create_buffer_with_data(camera_matrix.as_bytes(), wgpu::BufferUsage::COPY_SRC);
let global_2d_uniform_buffer = render_graph
.get_uniform_buffer(GLOBAL_2D_UNIFORM_BUFFER_NAME)
.unwrap();
encoder.copy_buffer_to_buffer(
&temp_camera_buffer,
0,
&global_2d_uniform_buffer.buffer,
0,
matrix_size,
);
}
}
}

View file

@ -1,73 +0,0 @@
use crate::{
math,
prelude::LocalToWorld,
render::{passes::ForwardUniforms, *},
};
use legion::prelude::*;
use std::mem;
use zerocopy::AsBytes;
pub const FORWARD_UNIFORM_BUFFER_NAME: &str = "forward";
pub struct GlobalResourceManager;
impl RenderResourceManager for GlobalResourceManager {
fn initialize(&self, render_graph: &mut RenderGraphData, world: &mut World) {
let light_count = <Read<Light>>::query().iter(world).count();
let forward_uniforms = ForwardUniforms {
proj: math::Mat4::identity().to_cols_array_2d(),
num_lights: [light_count as u32, 0, 0, 0],
};
let uniform_size = mem::size_of::<ForwardUniforms>() as wgpu::BufferAddress;
let buffer = render_graph.device.create_buffer_with_data(
forward_uniforms.as_bytes(),
wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
);
let uniform_buffer = UniformBuffer {
buffer,
size: uniform_size,
};
render_graph.set_uniform_buffer(FORWARD_UNIFORM_BUFFER_NAME, uniform_buffer);
}
fn update<'a>(
&mut self,
_render_graph: &mut RenderGraphData,
_encoder: &'a mut wgpu::CommandEncoder,
_world: &mut World,
) {
}
fn resize<'a>(
&self,
render_graph: &mut RenderGraphData,
encoder: &'a mut wgpu::CommandEncoder,
world: &mut World,
) {
for (mut camera, local_to_world, _) in
<(Write<Camera>, Read<LocalToWorld>, Read<ActiveCamera>)>::query().iter_mut(world)
{
camera.update(
render_graph.swap_chain_descriptor.width,
render_graph.swap_chain_descriptor.height,
);
let camera_matrix: [[f32; 4]; 4] =
(camera.view_matrix * local_to_world.0).to_cols_array_2d();
let matrix_size = mem::size_of::<[[f32; 4]; 4]>() as u64;
let temp_camera_buffer = render_graph
.device
.create_buffer_with_data(camera_matrix.as_bytes(), wgpu::BufferUsage::COPY_SRC);
let forward_uniform_buffer = render_graph
.get_uniform_buffer(FORWARD_UNIFORM_BUFFER_NAME)
.unwrap();
encoder.copy_buffer_to_buffer(
&temp_camera_buffer,
0,
&forward_uniform_buffer.buffer,
0,
matrix_size,
);
}
}
}

View file

@ -1,91 +0,0 @@
use crate::{
prelude::{LocalToWorld, Translation},
render::*,
};
use legion::prelude::*;
use std::mem;
use zerocopy::AsBytes;
pub const LIGHT_UNIFORM_BUFFER_NAME: &str = "lights";
pub struct LightResourceManager {
pub lights_are_dirty: bool,
pub max_lights: usize,
}
impl LightResourceManager {
pub fn new(max_lights: usize) -> Self {
LightResourceManager {
lights_are_dirty: true,
max_lights,
}
}
}
impl RenderResourceManager for LightResourceManager {
fn initialize(&self, render_graph: &mut RenderGraphData, _world: &mut World) {
let light_uniform_size =
(self.max_lights * mem::size_of::<LightRaw>()) as wgpu::BufferAddress;
let light_uniform_buffer = UniformBuffer {
buffer: render_graph.device.create_buffer(&wgpu::BufferDescriptor {
size: light_uniform_size,
usage: wgpu::BufferUsage::UNIFORM
| wgpu::BufferUsage::COPY_SRC
| wgpu::BufferUsage::COPY_DST,
}),
size: light_uniform_size,
};
render_graph.set_uniform_buffer(LIGHT_UNIFORM_BUFFER_NAME, light_uniform_buffer);
}
fn update<'a>(
&mut self,
render_graph: &mut RenderGraphData,
encoder: &'a mut wgpu::CommandEncoder,
world: &mut World,
) {
if self.lights_are_dirty {
let light_query = <(Read<Light>, Read<LocalToWorld>, Read<Translation>)>::query();
let light_count = light_query.iter(world).count();
if light_count == 0 {
return;
}
self.lights_are_dirty = false;
let size = mem::size_of::<LightRaw>();
let total_size = size * light_count;
let temp_buf_data = render_graph
.device
.create_buffer_mapped(total_size, wgpu::BufferUsage::COPY_SRC);
for ((light, local_to_world, translation), slot) in light_query
.iter(world)
.zip(temp_buf_data.data.chunks_exact_mut(size))
{
slot.copy_from_slice(
LightRaw::from(&light, &local_to_world.0, &translation).as_bytes(),
);
}
let light_uniform_buffer = render_graph
.get_uniform_buffer(LIGHT_UNIFORM_BUFFER_NAME)
.unwrap();
encoder.copy_buffer_to_buffer(
&temp_buf_data.finish(),
0,
&light_uniform_buffer.buffer,
0,
total_size as wgpu::BufferAddress,
);
}
}
fn resize<'a>(
&self,
_render_graph: &mut RenderGraphData,
_encoder: &'a mut wgpu::CommandEncoder,
_world: &mut World,
) {
}
}

View file

@ -1,112 +0,0 @@
use crate::{prelude::LocalToWorld, render::*};
use legion::prelude::*;
use std::mem;
use zerocopy::AsBytes;
pub const MATERIAL_BIND_GROUP_LAYOUT_NAME: &str = "material";
pub struct MaterialResourceManager;
impl RenderResourceManager for MaterialResourceManager {
fn initialize(&self, render_graph: &mut RenderGraphData, _world: &mut World) {
let material_bind_group_layout =
render_graph
.device
.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
bindings: &[wgpu::BindGroupLayoutBinding {
binding: 0,
visibility: wgpu::ShaderStage::VERTEX | wgpu::ShaderStage::FRAGMENT,
ty: wgpu::BindingType::UniformBuffer { dynamic: false },
}],
});
render_graph
.set_bind_group_layout(MATERIAL_BIND_GROUP_LAYOUT_NAME, material_bind_group_layout);
}
fn update<'a>(
&mut self,
render_graph: &mut RenderGraphData,
encoder: &'a mut wgpu::CommandEncoder,
world: &mut World,
) {
let entities =
<(Write<Material>, Read<LocalToWorld>)>::query().filter(!component::<Instanced>());
let entities_count = entities.iter_mut(world).count();
if entities_count == 0 {
return;
}
let size = mem::size_of::<MaterialUniforms>();
let temp_buf_data = render_graph
.device
.create_buffer_mapped(entities_count * size, wgpu::BufferUsage::COPY_SRC);
for ((material, transform), slot) in entities
.iter_mut(world)
.zip(temp_buf_data.data.chunks_exact_mut(size))
{
slot.copy_from_slice(
MaterialUniforms {
model: transform.0.to_cols_array_2d(),
color: material.get_color().into(),
}
.as_bytes(),
);
}
let material_bind_group_layout = render_graph
.get_bind_group_layout(MATERIAL_BIND_GROUP_LAYOUT_NAME)
.unwrap();
for mut material in <Write<Material>>::query()
.filter(!component::<Instanced>())
.iter_mut(world)
{
if let None = material.bind_group {
let material_uniform_size =
mem::size_of::<MaterialUniforms>() as wgpu::BufferAddress;
let uniform_buf = render_graph.device.create_buffer(&wgpu::BufferDescriptor {
size: material_uniform_size,
usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
});
let bind_group =
render_graph
.device
.create_bind_group(&wgpu::BindGroupDescriptor {
layout: material_bind_group_layout,
bindings: &[wgpu::Binding {
binding: 0,
resource: wgpu::BindingResource::Buffer {
buffer: &uniform_buf,
range: 0..material_uniform_size,
},
}],
});
material.bind_group = Some(bind_group);
material.uniform_buf = Some(uniform_buf);
}
}
let temp_buf = temp_buf_data.finish();
for (i, (material, _)) in entities.iter_mut(world).enumerate() {
encoder.copy_buffer_to_buffer(
&temp_buf,
(i * size) as wgpu::BufferAddress,
material.uniform_buf.as_ref().unwrap(),
0,
size as wgpu::BufferAddress,
);
}
}
fn resize<'a>(
&self,
_render_graph: &mut RenderGraphData,
_encoder: &'a mut wgpu::CommandEncoder,
_world: &mut World,
) {
}
}

View file

@ -1,9 +0,0 @@
mod global_2d_resource_manager;
mod global_resource_manager;
mod light_resource_manager;
mod material_resource_manager;
pub use global_2d_resource_manager::*;
pub use global_resource_manager::*;
pub use light_resource_manager::*;
pub use material_resource_manager::*;

View file

@ -1,4 +1,4 @@
use crate::render::render_graph_2::{
use crate::render::render_graph::{
BindGroup, BindType, Binding, UniformProperty, UniformPropertyType,
};
use spirv_reflect::{

View file

@ -1,4 +1,4 @@
use crate::render::render_graph_2::VertexBufferDescriptor;
use crate::render::render_graph::VertexBufferDescriptor;
use std::convert::From;
use zerocopy::{AsBytes, FromBytes};