entity uniforms kind of work in the new render graph
but only the last entity because they all use the same buffer
This commit is contained in:
parent
5ca84dbde0
commit
d76b2b032e
14
.vscode/launch.json
vendored
14
.vscode/launch.json
vendored
@ -26,15 +26,15 @@
|
|||||||
{
|
{
|
||||||
"type": "lldb",
|
"type": "lldb",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"name": "Debug example 'simple'",
|
"name": "Build and launch example",
|
||||||
"cargo": {
|
"cargo": {
|
||||||
"args": [
|
"args": [
|
||||||
"build",
|
"build",
|
||||||
"--example=simple",
|
"--example=simple_new_graph",
|
||||||
"--package=bevy"
|
"--package=bevy"
|
||||||
],
|
],
|
||||||
"filter": {
|
"filter": {
|
||||||
"name": "simple",
|
"name": "simple_new_graph",
|
||||||
"kind": "example"
|
"kind": "example"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -44,13 +44,13 @@
|
|||||||
{
|
{
|
||||||
"type": "lldb",
|
"type": "lldb",
|
||||||
"request": "launch",
|
"request": "launch",
|
||||||
"name": "Debug unit tests in example 'simple'",
|
"name": "Launch example",
|
||||||
"cargo": {
|
"cargo": {
|
||||||
"args": [
|
"args": [
|
||||||
"test",
|
"run",
|
||||||
"--no-run",
|
|
||||||
"--example=simple",
|
"--example=simple",
|
||||||
"--package=bevy"
|
"--package=bevy",
|
||||||
|
"--release"
|
||||||
],
|
],
|
||||||
"filter": {
|
"filter": {
|
||||||
"name": "simple",
|
"name": "simple",
|
||||||
|
@ -120,21 +120,21 @@ fn create_entities_builder_add_component(world: &mut World, plane_handle: Handle
|
|||||||
fn create_entities_builder_archetype(world: &mut World, plane_handle: Handle<Mesh>, cube_handle: Handle<Mesh>) {
|
fn create_entities_builder_archetype(world: &mut World, plane_handle: Handle<Mesh>, cube_handle: Handle<Mesh>) {
|
||||||
world.build()
|
world.build()
|
||||||
// plane
|
// plane
|
||||||
.build_archetype(MeshEntity {
|
.add_archetype(MeshEntity {
|
||||||
mesh: plane_handle.clone(),
|
mesh: plane_handle.clone(),
|
||||||
material: Material::new(Albedo::Color(math::vec4(0.1, 0.2, 0.1, 1.0))),
|
material: Material::new(Albedo::Color(math::vec4(0.1, 0.2, 0.1, 1.0))),
|
||||||
local_to_world: LocalToWorld::identity(),
|
local_to_world: LocalToWorld::identity(),
|
||||||
translation: Translation::new(0.0, 0.0, 0.0),
|
translation: Translation::new(0.0, 0.0, 0.0),
|
||||||
})
|
})
|
||||||
// cube
|
// cube
|
||||||
.build_archetype(MeshEntity {
|
.add_archetype(MeshEntity {
|
||||||
mesh: cube_handle,
|
mesh: cube_handle,
|
||||||
material: Material::new(Albedo::Color(math::vec4(0.5, 0.3, 0.3, 1.0))),
|
material: Material::new(Albedo::Color(math::vec4(0.5, 0.3, 0.3, 1.0))),
|
||||||
local_to_world: LocalToWorld::identity(),
|
local_to_world: LocalToWorld::identity(),
|
||||||
translation: Translation::new(0.0, 0.0, 1.0),
|
translation: Translation::new(0.0, 0.0, 1.0),
|
||||||
})
|
})
|
||||||
// light
|
// light
|
||||||
.build_archetype(LightEntity {
|
.add_archetype(LightEntity {
|
||||||
light: Light {
|
light: Light {
|
||||||
color: wgpu::Color {
|
color: wgpu::Color {
|
||||||
r: 0.8,
|
r: 0.8,
|
||||||
@ -151,7 +151,7 @@ fn create_entities_builder_archetype(world: &mut World, plane_handle: Handle<Mes
|
|||||||
rotation: Rotation::from_euler_angles(0.0, 0.0, 0.0),
|
rotation: Rotation::from_euler_angles(0.0, 0.0, 0.0),
|
||||||
})
|
})
|
||||||
// camera
|
// camera
|
||||||
.build_archetype(CameraEntity {
|
.add_archetype(CameraEntity {
|
||||||
camera: Camera::new(CameraType::Projection {
|
camera: Camera::new(CameraType::Projection {
|
||||||
fov: std::f32::consts::PI / 4.0,
|
fov: std::f32::consts::PI / 4.0,
|
||||||
near: 1.0,
|
near: 1.0,
|
||||||
|
@ -26,21 +26,21 @@ pub fn setup(world: &mut World) {
|
|||||||
|
|
||||||
world.build()
|
world.build()
|
||||||
// plane
|
// plane
|
||||||
.build_archetype(MeshEntity {
|
.add_archetype(MeshEntity {
|
||||||
mesh: plane_handle.clone(),
|
mesh: plane_handle.clone(),
|
||||||
material: Material::new(Albedo::Color(math::vec4(0.1, 0.2, 0.1, 1.0))),
|
material: Material::new(Albedo::Color(math::vec4(0.1, 0.2, 0.1, 1.0))),
|
||||||
local_to_world: LocalToWorld::identity(),
|
local_to_world: LocalToWorld::identity(),
|
||||||
translation: Translation::new(0.0, 0.0, 0.0),
|
translation: Translation::new(0.0, 0.0, 0.0),
|
||||||
})
|
})
|
||||||
// cube
|
// cube
|
||||||
.build_archetype(MeshEntity {
|
.add_archetype(MeshEntity {
|
||||||
mesh: cube_handle,
|
mesh: cube_handle,
|
||||||
material: Material::new(Albedo::Color(math::vec4(0.5, 0.3, 0.3, 1.0))),
|
material: Material::new(Albedo::Color(math::vec4(0.5, 0.3, 0.3, 1.0))),
|
||||||
local_to_world: LocalToWorld::identity(),
|
local_to_world: LocalToWorld::identity(),
|
||||||
translation: Translation::new(0.0, 0.0, 1.0),
|
translation: Translation::new(0.0, 0.0, 1.0),
|
||||||
})
|
})
|
||||||
// light
|
// light
|
||||||
// .build_archetype(LightEntity {
|
// .add_archetype(LightEntity {
|
||||||
// light: Light {
|
// light: Light {
|
||||||
// color: wgpu::Color {
|
// color: wgpu::Color {
|
||||||
// r: 0.8,
|
// r: 0.8,
|
||||||
@ -57,7 +57,7 @@ pub fn setup(world: &mut World) {
|
|||||||
// rotation: Rotation::from_euler_angles(0.0, 0.0, 0.0),
|
// rotation: Rotation::from_euler_angles(0.0, 0.0, 0.0),
|
||||||
// })
|
// })
|
||||||
// camera
|
// camera
|
||||||
.build_archetype(CameraEntity {
|
.add_archetype(CameraEntity {
|
||||||
camera: Camera::new(CameraType::Projection {
|
camera: Camera::new(CameraType::Projection {
|
||||||
fov: std::f32::consts::PI / 4.0,
|
fov: std::f32::consts::PI / 4.0,
|
||||||
near: 1.0,
|
near: 1.0,
|
||||||
|
@ -15,21 +15,21 @@ fn setup(world: &mut World) {
|
|||||||
|
|
||||||
world.build()
|
world.build()
|
||||||
// plane
|
// plane
|
||||||
.build_archetype(MeshEntity {
|
.add_archetype(MeshEntity {
|
||||||
mesh: plane_handle.clone(),
|
mesh: plane_handle.clone(),
|
||||||
material: Material::new(Albedo::Color(math::vec4(0.1, 0.2, 0.1, 1.0))),
|
material: Material::new(Albedo::Color(math::vec4(0.1, 0.2, 0.1, 1.0))),
|
||||||
local_to_world: LocalToWorld::identity(),
|
local_to_world: LocalToWorld::identity(),
|
||||||
translation: Translation::new(0.0, 0.0, 0.0),
|
translation: Translation::new(0.0, 0.0, 0.0),
|
||||||
})
|
})
|
||||||
// cube
|
// cube
|
||||||
.build_archetype(MeshEntity {
|
.add_archetype(MeshEntity {
|
||||||
mesh: cube_handle,
|
mesh: cube_handle,
|
||||||
material: Material::new(Albedo::Color(math::vec4(0.5, 0.3, 0.3, 1.0))),
|
material: Material::new(Albedo::Color(math::vec4(0.5, 0.3, 0.3, 1.0))),
|
||||||
local_to_world: LocalToWorld::identity(),
|
local_to_world: LocalToWorld::identity(),
|
||||||
translation: Translation::new(0.0, 0.0, 1.0),
|
translation: Translation::new(0.0, 0.0, 1.0),
|
||||||
})
|
})
|
||||||
// light
|
// light
|
||||||
.build_archetype(LightEntity {
|
.add_archetype(LightEntity {
|
||||||
light: Light {
|
light: Light {
|
||||||
color: wgpu::Color {
|
color: wgpu::Color {
|
||||||
r: 0.8,
|
r: 0.8,
|
||||||
@ -46,7 +46,7 @@ fn setup(world: &mut World) {
|
|||||||
rotation: Rotation::from_euler_angles(0.0, 0.0, 0.0),
|
rotation: Rotation::from_euler_angles(0.0, 0.0, 0.0),
|
||||||
})
|
})
|
||||||
// camera
|
// camera
|
||||||
.build_archetype(CameraEntity {
|
.add_archetype(CameraEntity {
|
||||||
camera: Camera::new(CameraType::Projection {
|
camera: Camera::new(CameraType::Projection {
|
||||||
fov: std::f32::consts::PI / 4.0,
|
fov: std::f32::consts::PI / 4.0,
|
||||||
near: 1.0,
|
near: 1.0,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
use bevy::prelude::*;
|
use bevy::prelude::*;
|
||||||
use bevy::render::render_graph_2::{StandardMaterial, ShaderUniforms};
|
use bevy::render::render_graph_2::{StandardMaterial, ShaderUniforms, uniform_selector};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
AppBuilder::new().add_defaults().setup_world(setup).run();
|
AppBuilder::new().add_defaults().setup_world(setup).run();
|
||||||
@ -16,28 +16,43 @@ fn setup(world: &mut World) {
|
|||||||
|
|
||||||
world.build()
|
world.build()
|
||||||
// plane
|
// plane
|
||||||
// .build_archetype(MeshEntity {
|
// .add_archetype(MeshEntity {
|
||||||
// mesh: plane_handle.clone(),
|
// mesh: plane_handle.clone(),
|
||||||
// material: Material::new(Albedo::Color(math::vec4(0.1, 0.2, 0.1, 1.0))),
|
// material: Material::new(Albedo::Color(math::vec4(0.1, 0.2, 0.1, 1.0))),
|
||||||
// local_to_world: LocalToWorld::identity(),
|
// local_to_world: LocalToWorld::identity(),
|
||||||
// translation: Translation::new(0.0, 0.0, 0.0),
|
// translation: Translation::new(0.0, 0.0, 0.0),
|
||||||
// })
|
// })
|
||||||
// cube
|
// cube
|
||||||
.build_archetype(NewMeshEntity {
|
.add_archetype(NewMeshEntity {
|
||||||
mesh: cube_handle,
|
mesh: cube_handle.clone(),
|
||||||
material: StandardMaterial {
|
material: StandardMaterial {
|
||||||
albedo: math::vec4(1.0, 0.0, 0.0, 1.0),
|
albedo: math::vec4(1.0, 0.0, 0.0, 1.0),
|
||||||
},
|
},
|
||||||
shader_uniforms: ShaderUniforms {
|
shader_uniforms: ShaderUniforms {
|
||||||
uniform_selectors: Vec::new(
|
uniform_selectors: vec![
|
||||||
|
uniform_selector::<StandardMaterial>,
|
||||||
)
|
uniform_selector::<LocalToWorld>,
|
||||||
|
]
|
||||||
},
|
},
|
||||||
local_to_world: LocalToWorld::identity(),
|
local_to_world: LocalToWorld::identity(),
|
||||||
translation: Translation::new(0.0, 0.0, 1.0),
|
translation: Translation::new(0.0, 0.0, 1.0),
|
||||||
})
|
})
|
||||||
|
// .add_archetype(NewMeshEntity {
|
||||||
|
// mesh: cube_handle.clone(),
|
||||||
|
// material: StandardMaterial {
|
||||||
|
// albedo: math::vec4(0.0, 1.0, 0.0, 1.0),
|
||||||
|
// },
|
||||||
|
// shader_uniforms: ShaderUniforms {
|
||||||
|
// uniform_selectors: vec![
|
||||||
|
// uniform_selector::<StandardMaterial>,
|
||||||
|
// uniform_selector::<LocalToWorld>,
|
||||||
|
// ]
|
||||||
|
// },
|
||||||
|
// local_to_world: LocalToWorld::identity(),
|
||||||
|
// translation: Translation::new(-2.0, 0.0, 1.0),
|
||||||
|
// })
|
||||||
// light
|
// light
|
||||||
// .build_archetype(LightEntity {
|
// .add_archetype(LightEntity {
|
||||||
// light: Light {
|
// light: Light {
|
||||||
// color: wgpu::Color {
|
// color: wgpu::Color {
|
||||||
// r: 0.8,
|
// r: 0.8,
|
||||||
@ -54,7 +69,7 @@ fn setup(world: &mut World) {
|
|||||||
// rotation: Rotation::from_euler_angles(0.0, 0.0, 0.0),
|
// rotation: Rotation::from_euler_angles(0.0, 0.0, 0.0),
|
||||||
// })
|
// })
|
||||||
// camera
|
// camera
|
||||||
.build_archetype(CameraEntity {
|
.add_archetype(CameraEntity {
|
||||||
camera: Camera::new(CameraType::Projection {
|
camera: Camera::new(CameraType::Projection {
|
||||||
fov: std::f32::consts::PI / 4.0,
|
fov: std::f32::consts::PI / 4.0,
|
||||||
near: 1.0,
|
near: 1.0,
|
||||||
|
@ -52,7 +52,7 @@ impl App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ref mut renderer) = self.renderer {
|
if let Some(ref mut renderer) = self.renderer {
|
||||||
renderer.process_render_graph(&self.render_graph, &mut self.world);
|
renderer.process_render_graph(&mut self.render_graph, &mut self.world);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(mut time) = self.world.resources.get_mut::<Time>() {
|
if let Some(mut time) = self.world.resources.get_mut::<Time>() {
|
||||||
@ -79,7 +79,7 @@ impl App {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if let Some(ref mut renderer) = self.renderer {
|
if let Some(ref mut renderer) = self.renderer {
|
||||||
renderer.initialize(&mut self.world);
|
renderer.initialize(&mut self.world, &mut self.render_graph);
|
||||||
}
|
}
|
||||||
|
|
||||||
log::info!("Entering render loop...");
|
log::info!("Entering render loop...");
|
||||||
@ -101,7 +101,7 @@ impl App {
|
|||||||
|
|
||||||
if let Some(ref mut renderer) = self.renderer {
|
if let Some(ref mut renderer) = self.renderer {
|
||||||
renderer
|
renderer
|
||||||
.resize(&mut self.world, size.width, size.height);
|
.resize(&mut self.world, &mut self.render_graph, size.width, size.height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
event::Event::WindowEvent { event, .. } => match event {
|
event::Event::WindowEvent { event, .. } => match event {
|
||||||
|
@ -4,7 +4,7 @@ use crate::{
|
|||||||
core::Time,
|
core::Time,
|
||||||
legion::prelude::{Runnable, Schedulable, Schedule, Universe, World},
|
legion::prelude::{Runnable, Schedulable, Schedule, Universe, World},
|
||||||
render::render_graph_2,
|
render::render_graph_2,
|
||||||
render::render_graph_2::{pipelines::*, wgpu_renderer::WgpuRenderer},
|
render::render_graph_2::{pipelines::*, wgpu_renderer::WgpuRenderer, resource_provider::CameraResourceProvider},
|
||||||
render::{passes::*, *},
|
render::{passes::*, *},
|
||||||
plugin::load_plugin,
|
plugin::load_plugin,
|
||||||
ui,
|
ui,
|
||||||
@ -174,6 +174,7 @@ impl AppBuilder {
|
|||||||
pub fn add_render_graph_defaults(mut self) -> Self {
|
pub fn add_render_graph_defaults(mut self) -> Self {
|
||||||
self.render_graph_builder = self
|
self.render_graph_builder = self
|
||||||
.render_graph_builder
|
.render_graph_builder
|
||||||
|
.add_resource_provider(Box::new(CameraResourceProvider))
|
||||||
.add_forward_pass()
|
.add_forward_pass()
|
||||||
.add_forward_pipeline();
|
.add_forward_pipeline();
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ impl<'a> EntityBuilder<'a> {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_archetype(mut self, entity_archetype: impl EntityArchetype) -> Self {
|
pub fn add_archetype(mut self, entity_archetype: impl EntityArchetype) -> Self {
|
||||||
self.current_entity = Some(entity_archetype.insert(self.world));
|
self.current_entity = Some(entity_archetype.insert(self.world));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ pub fn mesh_draw_target(world: &World, render_pass: &mut dyn RenderPass) {
|
|||||||
let mut last_mesh_id = None;
|
let mut last_mesh_id = None;
|
||||||
let mesh_query =
|
let mesh_query =
|
||||||
<(Read<ShaderUniforms>, Read<Handle<Mesh>>)>::query().filter(!component::<Instanced>());
|
<(Read<ShaderUniforms>, Read<Handle<Mesh>>)>::query().filter(!component::<Instanced>());
|
||||||
for (_material, mesh) in mesh_query.iter(world) {
|
for (_shader_uniforms, mesh) in mesh_query.iter(world) {
|
||||||
let current_mesh_id = mesh.id;
|
let current_mesh_id = mesh.id;
|
||||||
|
|
||||||
let mut should_load_mesh = last_mesh_id == None;
|
let mut should_load_mesh = last_mesh_id == None;
|
||||||
@ -39,7 +39,9 @@ pub fn mesh_draw_target(world: &World, render_pass: &mut dyn RenderPass) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: re-getting the mesh isn't necessary. just store the index count
|
||||||
if let Some(mesh_asset) = mesh_storage.get(mesh.id) {
|
if let Some(mesh_asset) = mesh_storage.get(mesh.id) {
|
||||||
|
// TODO: validate bind group properties against shader uniform properties at least once
|
||||||
render_pass.setup_bind_groups();
|
render_pass.setup_bind_groups();
|
||||||
render_pass.draw_indexed(0..mesh_asset.indices.len() as u32, 0, 0..1);
|
render_pass.draw_indexed(0..mesh_asset.indices.len() as u32, 0, 0..1);
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
pub mod pipelines;
|
pub mod pipelines;
|
||||||
pub mod resource_name;
|
pub mod resource_name;
|
||||||
pub mod wgpu_renderer;
|
pub mod wgpu_renderer;
|
||||||
mod resource_provider;
|
pub mod resource_provider;
|
||||||
mod resource;
|
mod resource;
|
||||||
mod pipeline;
|
mod pipeline;
|
||||||
mod pipeline_layout;
|
mod pipeline_layout;
|
||||||
|
@ -42,6 +42,17 @@ pub enum BindType {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl BindType {
|
||||||
|
pub fn get_uniform_size(&self) -> Option<u64> {
|
||||||
|
match self {
|
||||||
|
BindType::Uniform { properties, .. } => {
|
||||||
|
Some(properties.iter().fold(0, |total, property| total + property.property_type.get_size()))
|
||||||
|
},
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Hash)]
|
#[derive(Hash)]
|
||||||
pub struct UniformProperty {
|
pub struct UniformProperty {
|
||||||
pub name: String,
|
pub name: String,
|
||||||
@ -57,8 +68,21 @@ pub enum UniformPropertyType {
|
|||||||
Vec3,
|
Vec3,
|
||||||
Vec4,
|
Vec4,
|
||||||
Mat4,
|
Mat4,
|
||||||
Struct(Vec<UniformPropertyType>),
|
// Struct(Vec<UniformPropertyType>),
|
||||||
Array(Box<UniformPropertyType>, usize),
|
// Array(Box<UniformPropertyType>, usize),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl UniformPropertyType {
|
||||||
|
fn get_size(&self) -> u64 {
|
||||||
|
match self {
|
||||||
|
UniformPropertyType::Int => 4,
|
||||||
|
UniformPropertyType::Float => 4,
|
||||||
|
UniformPropertyType::UVec4 => 4 * 4,
|
||||||
|
UniformPropertyType::Vec3 => 4 * 3,
|
||||||
|
UniformPropertyType::Vec4 => 4 * 4,
|
||||||
|
UniformPropertyType::Mat4 => 4 * 4 * 4,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Hash)]
|
#[derive(Copy, Clone, Hash)]
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
#version 450
|
#version 450
|
||||||
|
|
||||||
layout(location = 0) in vec3 v_Normal;
|
layout(location = 0) in vec4 v_Position;
|
||||||
layout(location = 1) in vec4 v_Position;
|
layout(location = 1) in vec3 v_Normal;
|
||||||
|
layout(location = 2) in vec2 v_Uv;
|
||||||
|
|
||||||
layout(location = 0) out vec4 o_Target;
|
layout(location = 0) out vec4 o_Target;
|
||||||
|
|
||||||
@ -15,5 +16,6 @@ layout(set = 1, binding = 1) uniform StandardMaterial {
|
|||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
// multiply the light by material color
|
// multiply the light by material color
|
||||||
|
o_Target = vec4(1.0, 0.0, 0.0, 1.0);
|
||||||
o_Target = Albedo;
|
o_Target = Albedo;
|
||||||
}
|
}
|
||||||
|
@ -2,10 +2,11 @@
|
|||||||
|
|
||||||
layout(location = 0) in vec4 a_Pos;
|
layout(location = 0) in vec4 a_Pos;
|
||||||
layout(location = 1) in vec4 a_Normal;
|
layout(location = 1) in vec4 a_Normal;
|
||||||
layout(location = 2) in vec4 a_Uv;
|
layout(location = 2) in vec2 a_Uv;
|
||||||
|
|
||||||
layout(location = 0) out vec3 v_Normal;
|
layout(location = 0) out vec4 v_Position;
|
||||||
layout(location = 1) out vec4 v_Position;
|
layout(location = 1) out vec3 v_Normal;
|
||||||
|
layout(location = 2) out vec2 v_Uv;
|
||||||
|
|
||||||
layout(set = 0, binding = 0) uniform Camera {
|
layout(set = 0, binding = 0) uniform Camera {
|
||||||
mat4 ViewProj;
|
mat4 ViewProj;
|
||||||
@ -22,5 +23,7 @@ layout(set = 1, binding = 1) uniform StandardMaterial {
|
|||||||
void main() {
|
void main() {
|
||||||
v_Normal = mat3(Model) * vec3(a_Normal.xyz);
|
v_Normal = mat3(Model) * vec3(a_Normal.xyz);
|
||||||
v_Position = Model * vec4(a_Pos);
|
v_Position = Model * vec4(a_Pos);
|
||||||
|
// v_Normal = vec3(a_Normal.xyz);
|
||||||
|
// v_Position = vec4(a_Pos);
|
||||||
gl_Position = ViewProj * v_Position;
|
gl_Position = ViewProj * v_Position;
|
||||||
}
|
}
|
||||||
|
@ -75,15 +75,15 @@ impl ForwardPipelineBuilder for RenderGraphBuilder {
|
|||||||
depth_bias_slope_scale: 0.0,
|
depth_bias_slope_scale: 0.0,
|
||||||
depth_bias_clamp: 0.0,
|
depth_bias_clamp: 0.0,
|
||||||
})
|
})
|
||||||
.with_depth_stencil_state(wgpu::DepthStencilStateDescriptor {
|
// .with_depth_stencil_state(wgpu::DepthStencilStateDescriptor {
|
||||||
format: wgpu::TextureFormat::Depth32Float,
|
// format: wgpu::TextureFormat::Depth32Float,
|
||||||
depth_write_enabled: true,
|
// depth_write_enabled: true,
|
||||||
depth_compare: wgpu::CompareFunction::Less,
|
// depth_compare: wgpu::CompareFunction::Less,
|
||||||
stencil_front: wgpu::StencilStateFaceDescriptor::IGNORE,
|
// stencil_front: wgpu::StencilStateFaceDescriptor::IGNORE,
|
||||||
stencil_back: wgpu::StencilStateFaceDescriptor::IGNORE,
|
// stencil_back: wgpu::StencilStateFaceDescriptor::IGNORE,
|
||||||
stencil_read_mask: 0,
|
// stencil_read_mask: 0,
|
||||||
stencil_write_mask: 0,
|
// stencil_write_mask: 0,
|
||||||
})
|
// })
|
||||||
.add_color_state(wgpu::ColorStateDescriptor {
|
.add_color_state(wgpu::ColorStateDescriptor {
|
||||||
format: wgpu::TextureFormat::Bgra8UnormSrgb,
|
format: wgpu::TextureFormat::Bgra8UnormSrgb,
|
||||||
color_blend: wgpu::BlendDescriptor::REPLACE,
|
color_blend: wgpu::BlendDescriptor::REPLACE,
|
||||||
|
@ -1,18 +1,19 @@
|
|||||||
use crate::{legion::prelude::*, render::render_graph_2::{RenderGraph, ResourceInfo, PipelineDescriptor, BindGroup}};
|
use crate::{legion::prelude::*, render::render_graph_2::{RenderGraph, ResourceInfo, PipelineDescriptor}};
|
||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
|
||||||
pub trait Renderer {
|
pub trait Renderer {
|
||||||
fn initialize(&mut self, world: &mut World);
|
fn initialize(&mut self, world: &mut World, render_graph: &mut RenderGraph);
|
||||||
fn resize(&mut self, world: &mut World, width: u32, height: u32);
|
fn resize(&mut self, world: &mut World, render_graph: &mut RenderGraph, width: u32, height: u32);
|
||||||
fn process_render_graph(&mut self, render_graph: &RenderGraph, world: &mut World);
|
fn process_render_graph(&mut self, render_graph: &mut RenderGraph, world: &mut World);
|
||||||
// TODO: swap out wgpu::BufferUsage for custom type
|
// TODO: swap out wgpu::BufferUsage for non-wgpu type
|
||||||
fn create_buffer_with_data(&mut self, name: &str, data: &[u8], buffer_usage: wgpu::BufferUsage);
|
fn create_buffer_with_data(&mut self, name: &str, data: &[u8], buffer_usage: wgpu::BufferUsage);
|
||||||
fn setup_bind_group(&mut self, bind_group: &BindGroup) -> u64;
|
fn create_buffer(&mut self, name: &str, size: u64, buffer_usage: wgpu::BufferUsage);
|
||||||
fn remove_buffer(&mut self, name: &str);
|
fn remove_buffer(&mut self, name: &str);
|
||||||
fn get_resource_info(&self, name: &str) -> Option<&ResourceInfo>;
|
fn get_resource_info(&self, name: &str) -> Option<&ResourceInfo>;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait RenderPass {
|
pub trait RenderPass {
|
||||||
|
// TODO: consider using static dispatch for the renderer: Renderer<WgpuBackend>. compare compile times
|
||||||
fn get_renderer(&mut self) -> &mut dyn Renderer;
|
fn get_renderer(&mut self) -> &mut dyn Renderer;
|
||||||
fn get_pipeline_descriptor(&self) -> &PipelineDescriptor;
|
fn get_pipeline_descriptor(&self) -> &PipelineDescriptor;
|
||||||
fn set_index_buffer(&mut self, name: &str, offset: u64);
|
fn set_index_buffer(&mut self, name: &str, offset: u64);
|
||||||
|
@ -1,4 +1,8 @@
|
|||||||
pub enum ResourceInfo {
|
pub enum ResourceInfo {
|
||||||
|
BufferMapped {
|
||||||
|
size: u64,
|
||||||
|
buffer_usage: wgpu::BufferUsage,
|
||||||
|
},
|
||||||
Buffer {
|
Buffer {
|
||||||
size: u64,
|
size: u64,
|
||||||
buffer_usage: wgpu::BufferUsage,
|
buffer_usage: wgpu::BufferUsage,
|
||||||
|
@ -37,7 +37,7 @@ pub trait GetBytes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: might need to add zerocopy to this crate to impl AsBytes for external crates
|
// TODO: might need to add zerocopy to this crate to impl AsBytes for external crates
|
||||||
// impl GetBytes for dyn AsBytes {
|
// impl<T> GetBytes for T where T : AsBytes {
|
||||||
// fn get_bytes(&self) -> Vec<u8> {
|
// fn get_bytes(&self) -> Vec<u8> {
|
||||||
// self.as_bytes().into()
|
// self.as_bytes().into()
|
||||||
// }
|
// }
|
||||||
@ -61,7 +61,7 @@ impl GetBytes for Vec4 {
|
|||||||
pub trait AsUniforms {
|
pub trait AsUniforms {
|
||||||
fn get_uniform_info(&self) -> &[UniformInfo];
|
fn get_uniform_info(&self) -> &[UniformInfo];
|
||||||
fn get_uniform_layouts(&self) -> &[&[UniformPropertyType]];
|
fn get_uniform_layouts(&self) -> &[&[UniformPropertyType]];
|
||||||
fn get_uniform_value(&self, index: usize) -> Vec<u8>;
|
fn get_uniform_bytes(&self, name: &str) -> Option<Vec<u8>>;
|
||||||
// TODO: support zero-copy uniforms
|
// TODO: support zero-copy uniforms
|
||||||
// fn get_uniform_value_ref(&self, index: usize) -> &[u8];
|
// fn get_uniform_value_ref(&self, index: usize) -> &[u8];
|
||||||
}
|
}
|
||||||
@ -71,27 +71,12 @@ pub trait AsUniforms {
|
|||||||
// pub
|
// pub
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
|
||||||
// create this from a derive macro
|
|
||||||
const STANDARD_MATERIAL_UNIFORM_INFO: &[UniformInfo] = &[
|
|
||||||
UniformInfo {
|
|
||||||
name: "StandardMaterial",
|
|
||||||
bind_type: BindType::Uniform {
|
|
||||||
dynamic: false,
|
|
||||||
properties: Vec::new()
|
|
||||||
},
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
// these are separate from BindType::Uniform{properties} because they need to be const
|
|
||||||
const STANDARD_MATERIAL_UNIFORM_LAYOUTS: &[&[UniformPropertyType]] = &[&[]];
|
|
||||||
|
|
||||||
pub struct UniformInfo<'a> {
|
pub struct UniformInfo<'a> {
|
||||||
pub name: &'a str,
|
pub name: &'a str,
|
||||||
pub bind_type: BindType,
|
pub bind_type: BindType,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn standard_material_selector<T>(entity: Entity, world: &World) -> Option<RefMap<&dyn AsUniforms>> where T: AsUniforms + Component {
|
pub fn uniform_selector<T>(entity: Entity, world: &World) -> Option<RefMap<&dyn AsUniforms>> where T: AsUniforms + Component {
|
||||||
world.get_component::<T>(entity).map(
|
world.get_component::<T>(entity).map(
|
||||||
|c| {
|
|c| {
|
||||||
c.map_into(|s| {
|
c.map_into(|s| {
|
||||||
@ -100,6 +85,21 @@ pub fn standard_material_selector<T>(entity: Entity, world: &World) -> Option<Re
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create this from a derive macro
|
||||||
|
const STANDARD_MATERIAL_UNIFORM_INFO: &[UniformInfo] = &[
|
||||||
|
UniformInfo {
|
||||||
|
name: "StandardMaterial",
|
||||||
|
bind_type: BindType::Uniform {
|
||||||
|
dynamic: false,
|
||||||
|
// TODO: fill this in with properties
|
||||||
|
properties: Vec::new()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// these are separate from BindType::Uniform{properties} because they need to be const
|
||||||
|
const STANDARD_MATERIAL_UNIFORM_LAYOUTS: &[&[UniformPropertyType]] = &[&[]];
|
||||||
|
|
||||||
// const ST
|
// const ST
|
||||||
impl AsUniforms for StandardMaterial {
|
impl AsUniforms for StandardMaterial {
|
||||||
fn get_uniform_info(&self) -> &[UniformInfo] {
|
fn get_uniform_info(&self) -> &[UniformInfo] {
|
||||||
@ -110,10 +110,66 @@ impl AsUniforms for StandardMaterial {
|
|||||||
STANDARD_MATERIAL_UNIFORM_LAYOUTS
|
STANDARD_MATERIAL_UNIFORM_LAYOUTS
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_uniform_value(&self, index: usize) -> Vec<u8> {
|
fn get_uniform_bytes(&self, name: &str) -> Option<Vec<u8>> {
|
||||||
match index {
|
match name {
|
||||||
0 => self.albedo.get_bytes(),
|
"StandardMaterial" => Some(self.albedo.get_bytes()),
|
||||||
_ => panic!("index out of bounds"),
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// fn iter_properties(&self) -> std::slice::Iter<&'static str> {
|
||||||
|
// STANDARD_MATERIAL_PROPERTIES.iter()
|
||||||
|
// }
|
||||||
|
// fn get_property(&self, name: &str) -> Option<ShaderValue> {
|
||||||
|
// match name {
|
||||||
|
// "albedo" => Some(match self.albedo {
|
||||||
|
// Albedo::Color(color) => ShaderValue::Vec4(color),
|
||||||
|
// Albedo::Texture(ref texture) => ShaderValue::Texture(texture)
|
||||||
|
// }),
|
||||||
|
// _ => None,
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// fn get_selector(&self) -> ShaderMaterialSelector {
|
||||||
|
// |entity, world| {
|
||||||
|
// world.get_component::<Self>(entity).map(
|
||||||
|
// |c: Ref<StandardMaterial>| {
|
||||||
|
// c.map_into(|s| {
|
||||||
|
// s as &dyn ShaderMaterial
|
||||||
|
// })
|
||||||
|
// }
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
// create this from a derive macro
|
||||||
|
const LOCAL_TO_WORLD_UNIFORM_INFO: &[UniformInfo] = &[
|
||||||
|
UniformInfo {
|
||||||
|
name: "Object",
|
||||||
|
bind_type: BindType::Uniform {
|
||||||
|
dynamic: false,
|
||||||
|
// TODO: fill this in with properties
|
||||||
|
properties: Vec::new()
|
||||||
|
},
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
// these are separate from BindType::Uniform{properties} because they need to be const
|
||||||
|
const LOCAL_TO_WORLD_UNIFORM_LAYOUTS: &[&[UniformPropertyType]] = &[&[]];
|
||||||
|
|
||||||
|
// const ST
|
||||||
|
impl AsUniforms for bevy_transform::prelude::LocalToWorld {
|
||||||
|
fn get_uniform_info(&self) -> &[UniformInfo] {
|
||||||
|
LOCAL_TO_WORLD_UNIFORM_INFO
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_uniform_layouts(&self) -> &[&[UniformPropertyType]] {
|
||||||
|
LOCAL_TO_WORLD_UNIFORM_LAYOUTS
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_uniform_bytes(&self, name: &str) -> Option<Vec<u8>> {
|
||||||
|
match name {
|
||||||
|
"Object" => Some(self.0.to_cols_array_2d().as_bytes().into()),
|
||||||
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// fn iter_properties(&self) -> std::slice::Iter<&'static str> {
|
// fn iter_properties(&self) -> std::slice::Iter<&'static str> {
|
||||||
|
@ -3,7 +3,8 @@ use crate::{
|
|||||||
render::render_graph_2::{
|
render::render_graph_2::{
|
||||||
resource_name, BindGroup, BindType, PassDescriptor, PipelineDescriptor, RenderGraph,
|
resource_name, BindGroup, BindType, PassDescriptor, PipelineDescriptor, RenderGraph,
|
||||||
RenderPass, RenderPassColorAttachmentDescriptor,
|
RenderPass, RenderPassColorAttachmentDescriptor,
|
||||||
RenderPassDepthStencilAttachmentDescriptor, Renderer, ResourceInfo, TextureDimension,
|
RenderPassDepthStencilAttachmentDescriptor, Renderer, ResourceInfo, ShaderUniforms,
|
||||||
|
TextureDimension,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
use std::{
|
use std::{
|
||||||
@ -21,7 +22,7 @@ pub struct WgpuRenderer {
|
|||||||
pub buffers: HashMap<String, wgpu::Buffer>,
|
pub buffers: HashMap<String, wgpu::Buffer>,
|
||||||
pub textures: HashMap<String, wgpu::TextureView>,
|
pub textures: HashMap<String, wgpu::TextureView>,
|
||||||
pub resource_info: HashMap<String, ResourceInfo>,
|
pub resource_info: HashMap<String, ResourceInfo>,
|
||||||
pub bind_groups: HashMap<u64, wgpu::BindGroup>,
|
pub bind_groups: HashMap<u64, BindGroupInfo>,
|
||||||
pub bind_group_layouts: HashMap<u64, wgpu::BindGroupLayout>,
|
pub bind_group_layouts: HashMap<u64, wgpu::BindGroupLayout>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,9 +118,8 @@ impl WgpuRenderer {
|
|||||||
})
|
})
|
||||||
.collect::<Vec<&wgpu::BindGroupLayout>>();
|
.collect::<Vec<&wgpu::BindGroupLayout>>();
|
||||||
|
|
||||||
|
|
||||||
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||||
bind_group_layouts: bind_group_layouts.as_slice()
|
bind_group_layouts: bind_group_layouts.as_slice(),
|
||||||
});
|
});
|
||||||
|
|
||||||
let render_pipeline_descriptor = wgpu::RenderPipelineDescriptor {
|
let render_pipeline_descriptor = wgpu::RenderPipelineDescriptor {
|
||||||
@ -229,10 +229,131 @@ impl WgpuRenderer {
|
|||||||
fn add_resource_info(&mut self, name: &str, resource_info: ResourceInfo) {
|
fn add_resource_info(&mut self, name: &str, resource_info: ResourceInfo) {
|
||||||
self.resource_info.insert(name.to_string(), resource_info);
|
self.resource_info.insert(name.to_string(), resource_info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: consider moving this to a resource provider
|
||||||
|
fn setup_bind_group(&mut self, bind_group: &BindGroup) -> u64 {
|
||||||
|
// TODO: cache hash result in bind_group?
|
||||||
|
let mut hasher = DefaultHasher::new();
|
||||||
|
bind_group.hash(&mut hasher);
|
||||||
|
let bind_group_id = hasher.finish();
|
||||||
|
|
||||||
|
if let None = self.bind_groups.get(&bind_group_id) {
|
||||||
|
let mut unset_uniforms = Vec::new();
|
||||||
|
// if a uniform resource buffer doesn't exist, create a new empty one
|
||||||
|
for binding in bind_group.bindings.iter() {
|
||||||
|
if let None = self.resource_info.get(&binding.name) {
|
||||||
|
unset_uniforms.push(binding.name.to_string());
|
||||||
|
if let BindType::Uniform { .. } = &binding.bind_type {
|
||||||
|
let size = binding.bind_type.get_uniform_size().unwrap();
|
||||||
|
self.create_buffer(
|
||||||
|
&binding.name,
|
||||||
|
size,
|
||||||
|
wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create wgpu Bindings
|
||||||
|
let bindings = bind_group
|
||||||
|
.bindings
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(i, b)| {
|
||||||
|
let resource_info = self.resource_info.get(&b.name).unwrap();
|
||||||
|
wgpu::Binding {
|
||||||
|
binding: i as u32,
|
||||||
|
resource: match &b.bind_type {
|
||||||
|
BindType::Uniform {
|
||||||
|
dynamic,
|
||||||
|
properties,
|
||||||
|
} => {
|
||||||
|
if let ResourceInfo::Buffer { size, buffer_usage } = resource_info {
|
||||||
|
let buffer = self.buffers.get(&b.name).unwrap();
|
||||||
|
wgpu::BindingResource::Buffer {
|
||||||
|
buffer: buffer,
|
||||||
|
range: 0..*size,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic!("expected a Buffer resource");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => panic!("unsupported bind type"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<wgpu::Binding>>();
|
||||||
|
|
||||||
|
let bind_group_layout = self.bind_group_layouts.get(&bind_group_id).unwrap();
|
||||||
|
let bind_group_descriptor = wgpu::BindGroupDescriptor {
|
||||||
|
layout: bind_group_layout,
|
||||||
|
bindings: bindings.as_slice(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let bind_group = self.device.create_bind_group(&bind_group_descriptor);
|
||||||
|
self.bind_groups.insert(
|
||||||
|
bind_group_id,
|
||||||
|
BindGroupInfo {
|
||||||
|
bind_group,
|
||||||
|
unset_uniforms,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
bind_group_id
|
||||||
|
}
|
||||||
|
|
||||||
|
fn setup_entity_shader_uniforms(
|
||||||
|
&mut self,
|
||||||
|
bind_group: &BindGroup,
|
||||||
|
world: &World,
|
||||||
|
entity: Entity,
|
||||||
|
shader_uniforms: &ShaderUniforms,
|
||||||
|
encoder: &mut wgpu::CommandEncoder,
|
||||||
|
) {
|
||||||
|
// TODO: cache hash result in bind_group?
|
||||||
|
let mut hasher = DefaultHasher::new();
|
||||||
|
bind_group.hash(&mut hasher);
|
||||||
|
let bind_group_id = hasher.finish();
|
||||||
|
let bind_group_info = self.bind_groups.get(&bind_group_id).unwrap();
|
||||||
|
for unset_uniform in bind_group_info.unset_uniforms.iter() {
|
||||||
|
let mut found_uniform = false;
|
||||||
|
for uniform_selector in shader_uniforms.uniform_selectors.iter().rev() {
|
||||||
|
let uniforms = uniform_selector(entity, world).unwrap_or_else(|| {
|
||||||
|
panic!(
|
||||||
|
"ShaderUniform selector points to a missing component. Uniform: {}",
|
||||||
|
unset_uniform
|
||||||
|
)
|
||||||
|
});
|
||||||
|
if let Some(bytes) = uniforms.get_uniform_bytes(unset_uniform) {
|
||||||
|
// TODO: validate bind_group layout vs shader uniform
|
||||||
|
let temp_buffer = self
|
||||||
|
.device
|
||||||
|
.create_buffer_with_data(bytes.as_slice(), wgpu::BufferUsage::COPY_SRC);
|
||||||
|
let uniform_buffer = self.buffers.get(unset_uniform).unwrap();
|
||||||
|
|
||||||
|
encoder.copy_buffer_to_buffer(
|
||||||
|
&temp_buffer,
|
||||||
|
0,
|
||||||
|
uniform_buffer,
|
||||||
|
0,
|
||||||
|
bytes.len() as u64,
|
||||||
|
);
|
||||||
|
|
||||||
|
found_uniform = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !found_uniform {
|
||||||
|
panic!("ShaderUniform did not find a source for Uniform: {}. Consider adding a uniform selector to this entity's ShaderUniforms component.", unset_uniform);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Renderer for WgpuRenderer {
|
impl Renderer for WgpuRenderer {
|
||||||
fn initialize(&mut self, world: &mut World) {
|
fn initialize(&mut self, world: &mut World, render_graph: &mut RenderGraph) {
|
||||||
let (surface, window_size) = {
|
let (surface, window_size) = {
|
||||||
let window = world.resources.get::<winit::window::Window>().unwrap();
|
let window = world.resources.get::<winit::window::Window>().unwrap();
|
||||||
let surface = wgpu::Surface::create(window.deref());
|
let surface = wgpu::Surface::create(window.deref());
|
||||||
@ -241,10 +362,19 @@ impl Renderer for WgpuRenderer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
self.surface = Some(surface);
|
self.surface = Some(surface);
|
||||||
self.resize(world, window_size.width, window_size.height);
|
self.resize(world, render_graph, window_size.width, window_size.height);
|
||||||
|
for resource_provider in render_graph.resource_providers.iter_mut() {
|
||||||
|
resource_provider.initialize(self, world);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resize(&mut self, world: &mut World, width: u32, height: u32) {
|
fn resize(
|
||||||
|
&mut self,
|
||||||
|
world: &mut World,
|
||||||
|
render_graph: &mut RenderGraph,
|
||||||
|
width: u32,
|
||||||
|
height: u32,
|
||||||
|
) {
|
||||||
self.swap_chain_descriptor.width = width;
|
self.swap_chain_descriptor.width = width;
|
||||||
self.swap_chain_descriptor.height = height;
|
self.swap_chain_descriptor.height = height;
|
||||||
let swap_chain = self
|
let swap_chain = self
|
||||||
@ -253,9 +383,16 @@ impl Renderer for WgpuRenderer {
|
|||||||
|
|
||||||
// WgpuRenderer can't own swap_chain without creating lifetime ergonomics issues, so lets just store it in World.
|
// WgpuRenderer can't own swap_chain without creating lifetime ergonomics issues, so lets just store it in World.
|
||||||
world.resources.insert(swap_chain);
|
world.resources.insert(swap_chain);
|
||||||
|
for resource_provider in render_graph.resource_providers.iter_mut() {
|
||||||
|
resource_provider.resize(self, world, width, height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_render_graph(&mut self, render_graph: &mut RenderGraph, world: &mut World) {
|
||||||
|
for resource_provider in render_graph.resource_providers.iter_mut() {
|
||||||
|
resource_provider.update(self, world);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_render_graph(&mut self, render_graph: &RenderGraph, world: &mut World) {
|
|
||||||
let mut swap_chain = world.resources.get_mut::<wgpu::SwapChain>().unwrap();
|
let mut swap_chain = world.resources.get_mut::<wgpu::SwapChain>().unwrap();
|
||||||
let frame = swap_chain
|
let frame = swap_chain
|
||||||
.get_next_texture()
|
.get_next_texture()
|
||||||
@ -265,23 +402,48 @@ impl Renderer for WgpuRenderer {
|
|||||||
.device
|
.device
|
||||||
.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
|
.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
|
||||||
|
|
||||||
for (pass_name, pass_descriptor) in render_graph.pass_descriptors.iter() {
|
// setup, pipelines, bind groups, and resources
|
||||||
let mut render_pass = self.create_render_pass(pass_descriptor, &mut encoder, &frame);
|
for (pipeline_name, pipeline_descriptor) in render_graph.pipeline_descriptors.iter() {
|
||||||
if let Some(pass_pipelines) = render_graph.pass_pipelines.get(pass_name) {
|
// create pipelines
|
||||||
for pass_pipeline in pass_pipelines.iter() {
|
if let None = self.render_pipelines.get(pipeline_name) {
|
||||||
if let Some(pipeline_descriptor) =
|
|
||||||
render_graph.pipeline_descriptors.get(pass_pipeline)
|
|
||||||
{
|
|
||||||
if let None = self.render_pipelines.get(pass_pipeline) {
|
|
||||||
let render_pipeline = WgpuRenderer::create_render_pipeline(
|
let render_pipeline = WgpuRenderer::create_render_pipeline(
|
||||||
pipeline_descriptor,
|
pipeline_descriptor,
|
||||||
&mut self.bind_group_layouts,
|
&mut self.bind_group_layouts,
|
||||||
&self.device,
|
&self.device,
|
||||||
);
|
);
|
||||||
self.render_pipelines
|
self.render_pipelines
|
||||||
.insert(pass_pipeline.to_string(), render_pipeline);
|
.insert(pipeline_name.to_string(), render_pipeline);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// create bind groups
|
||||||
|
for bind_group in pipeline_descriptor.pipeline_layout.bind_groups.iter() {
|
||||||
|
self.setup_bind_group(bind_group);
|
||||||
|
// TODO: Move this out of the for loop
|
||||||
|
// copy entity ShaderUniforms to buffers
|
||||||
|
let shader_uniform_query = <Read<ShaderUniforms>>::query();
|
||||||
|
for (entity, shader_uniforms) in shader_uniform_query.iter_entities(world) {
|
||||||
|
self.setup_entity_shader_uniforms(
|
||||||
|
bind_group,
|
||||||
|
world,
|
||||||
|
entity,
|
||||||
|
&&*shader_uniforms,
|
||||||
|
&mut encoder,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (pass_name, pass_descriptor) in render_graph.pass_descriptors.iter() {
|
||||||
|
// run passes
|
||||||
|
let mut render_pass = self.create_render_pass(pass_descriptor, &mut encoder, &frame);
|
||||||
|
if let Some(pass_pipelines) = render_graph.pass_pipelines.get(pass_name) {
|
||||||
|
for pass_pipeline in pass_pipelines.iter() {
|
||||||
|
if let Some(pipeline_descriptor) =
|
||||||
|
render_graph.pipeline_descriptors.get(pass_pipeline)
|
||||||
|
{
|
||||||
|
let render_pipeline = self.render_pipelines.get(pass_pipeline).unwrap();
|
||||||
|
render_pass.set_pipeline(render_pipeline);
|
||||||
|
|
||||||
let mut render_pass = WgpuRenderPass {
|
let mut render_pass = WgpuRenderPass {
|
||||||
render_pass: &mut render_pass,
|
render_pass: &mut render_pass,
|
||||||
renderer: self,
|
renderer: self,
|
||||||
@ -318,6 +480,23 @@ impl Renderer for WgpuRenderer {
|
|||||||
self.buffers.insert(name.to_string(), buffer);
|
self.buffers.insert(name.to_string(), buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn create_buffer(&mut self, name: &str, size: u64, buffer_usage: wgpu::BufferUsage) {
|
||||||
|
let buffer = self.device.create_buffer(&wgpu::BufferDescriptor {
|
||||||
|
size: size,
|
||||||
|
usage: buffer_usage,
|
||||||
|
});
|
||||||
|
|
||||||
|
self.add_resource_info(
|
||||||
|
name,
|
||||||
|
ResourceInfo::Buffer {
|
||||||
|
buffer_usage,
|
||||||
|
size: size,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
self.buffers.insert(name.to_string(), buffer);
|
||||||
|
}
|
||||||
|
|
||||||
fn get_resource_info(&self, name: &str) -> Option<&ResourceInfo> {
|
fn get_resource_info(&self, name: &str) -> Option<&ResourceInfo> {
|
||||||
self.resource_info.get(name)
|
self.resource_info.get(name)
|
||||||
}
|
}
|
||||||
@ -325,56 +504,6 @@ impl Renderer for WgpuRenderer {
|
|||||||
fn remove_buffer(&mut self, name: &str) {
|
fn remove_buffer(&mut self, name: &str) {
|
||||||
self.buffers.remove(name);
|
self.buffers.remove(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn setup_bind_group(&mut self, bind_group: &BindGroup) -> u64 {
|
|
||||||
// TODO: cache hash result in bind_group?
|
|
||||||
let mut hasher = DefaultHasher::new();
|
|
||||||
bind_group.hash(&mut hasher);
|
|
||||||
let bind_group_id = hasher.finish();
|
|
||||||
|
|
||||||
|
|
||||||
// TODO: setup bind group layout
|
|
||||||
if let None = self.bind_groups.get(&bind_group_id) {
|
|
||||||
let bindings = bind_group
|
|
||||||
.bindings
|
|
||||||
.iter()
|
|
||||||
.enumerate()
|
|
||||||
.map(|(i, b)| wgpu::Binding {
|
|
||||||
binding: i as u32,
|
|
||||||
resource: match &b.bind_type {
|
|
||||||
BindType::Uniform {
|
|
||||||
dynamic,
|
|
||||||
properties,
|
|
||||||
} => {
|
|
||||||
let resource_info = self.resource_info.get(&b.name).unwrap();
|
|
||||||
if let ResourceInfo::Buffer { size, buffer_usage } = resource_info {
|
|
||||||
let buffer = self.buffers.get(&b.name).unwrap();
|
|
||||||
wgpu::BindingResource::Buffer {
|
|
||||||
buffer: buffer,
|
|
||||||
range: 0..*size,
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
panic!("expected a Buffer resource");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => panic!("unsupported bind type"),
|
|
||||||
},
|
|
||||||
})
|
|
||||||
.collect::<Vec<wgpu::Binding>>();
|
|
||||||
|
|
||||||
let bind_group_layout = self.bind_group_layouts.get(&bind_group_id).unwrap();
|
|
||||||
let bind_group_descriptor = wgpu::BindGroupDescriptor {
|
|
||||||
layout: bind_group_layout,
|
|
||||||
bindings: bindings.as_slice(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let bind_group = self.device.create_bind_group(&bind_group_descriptor);
|
|
||||||
// let bind
|
|
||||||
self.bind_groups.insert(bind_group_id, bind_group);
|
|
||||||
}
|
|
||||||
|
|
||||||
bind_group_id
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WgpuRenderPass<'a, 'b, 'c, 'd> {
|
pub struct WgpuRenderPass<'a, 'b, 'c, 'd> {
|
||||||
@ -422,12 +551,13 @@ impl<'a, 'b, 'c, 'd> RenderPass for WgpuRenderPass<'a, 'b, 'c, 'd> {
|
|||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
{
|
{
|
||||||
let id = self.renderer.setup_bind_group(bind_group);
|
// TODO: cache hash result in bind_group?
|
||||||
self.render_pass.set_bind_group(
|
let mut hasher = DefaultHasher::new();
|
||||||
i as u32,
|
bind_group.hash(&mut hasher);
|
||||||
self.renderer.bind_groups.get(&id).unwrap(),
|
let bind_group_id = hasher.finish();
|
||||||
&[],
|
let bind_group_info = self.renderer.bind_groups.get(&bind_group_id).unwrap();
|
||||||
);
|
self.render_pass
|
||||||
|
.set_bind_group(i as u32, &bind_group_info.bind_group, &[]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -470,3 +600,8 @@ impl From<&BindType> for wgpu::BindingType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct BindGroupInfo {
|
||||||
|
pub bind_group: wgpu::BindGroup,
|
||||||
|
pub unset_uniforms: Vec<String>,
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user