more graph work
This commit is contained in:
parent
54005fcdd0
commit
79bb83732f
@ -1,24 +1,23 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
app::App,
|
app::{App, system_stage},
|
||||||
asset::*,
|
asset::*,
|
||||||
core::Time,
|
core::Time,
|
||||||
legion::prelude::{Runnable, Schedulable, Schedule, Universe, World},
|
legion::prelude::{Runnable, Schedulable, Schedule, Universe, World},
|
||||||
render::{passes::*, *},
|
|
||||||
render::render_graph_2,
|
render::render_graph_2,
|
||||||
|
render::render_graph_2::{pipelines::*, wgpu_renderer::WgpuRenderer},
|
||||||
|
render::{passes::*, *},
|
||||||
ui,
|
ui,
|
||||||
};
|
};
|
||||||
|
|
||||||
use bevy_transform::transform_system_bundle;
|
use bevy_transform::transform_system_bundle;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
pub const UPDATE: &str = "update";
|
|
||||||
|
|
||||||
pub struct AppBuilder {
|
pub struct AppBuilder {
|
||||||
pub world: World,
|
pub world: World,
|
||||||
pub universe: Universe,
|
pub universe: Universe,
|
||||||
pub legacy_render_graph: Option<RenderGraph>,
|
pub legacy_render_graph: Option<RenderGraph>,
|
||||||
pub renderer: Option<Box<dyn render_graph_2::Renderer>>,
|
pub renderer: Option<Box<dyn render_graph_2::Renderer>>,
|
||||||
pub render_graph: render_graph_2::RenderGraph,
|
pub render_graph_builder: render_graph_2::RenderGraphBuilder,
|
||||||
pub system_stages: HashMap<String, Vec<Box<dyn Schedulable>>>,
|
pub system_stages: HashMap<String, Vec<Box<dyn Schedulable>>>,
|
||||||
pub runnable_stages: HashMap<String, Vec<Box<dyn Runnable>>>,
|
pub runnable_stages: HashMap<String, Vec<Box<dyn Runnable>>>,
|
||||||
pub stage_order: Vec<String>,
|
pub stage_order: Vec<String>,
|
||||||
@ -31,7 +30,7 @@ impl AppBuilder {
|
|||||||
AppBuilder {
|
AppBuilder {
|
||||||
universe,
|
universe,
|
||||||
world,
|
world,
|
||||||
render_graph: render_graph_2::RenderGraph::default(),
|
render_graph_builder: render_graph_2::RenderGraphBuilder::new(),
|
||||||
legacy_render_graph: None,
|
legacy_render_graph: None,
|
||||||
renderer: None,
|
renderer: None,
|
||||||
system_stages: HashMap::new(),
|
system_stages: HashMap::new(),
|
||||||
@ -66,7 +65,7 @@ impl AppBuilder {
|
|||||||
schedule_builder.build(),
|
schedule_builder.build(),
|
||||||
self.legacy_render_graph,
|
self.legacy_render_graph,
|
||||||
self.renderer,
|
self.renderer,
|
||||||
self.render_graph,
|
self.render_graph_builder.build(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,7 +84,7 @@ impl AppBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_system(self, system: Box<dyn Schedulable>) -> Self {
|
pub fn add_system(self, system: Box<dyn Schedulable>) -> Self {
|
||||||
self.add_system_to_stage(UPDATE, system)
|
self.add_system_to_stage(system_stage::UPDATE, system)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_system_to_stage(mut self, stage_name: &str, system: Box<dyn Schedulable>) -> Self {
|
pub fn add_system_to_stage(mut self, stage_name: &str, system: Box<dyn Schedulable>) -> Self {
|
||||||
@ -171,23 +170,31 @@ impl AppBuilder {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn add_render_graph_defaults(mut self) -> Self {
|
||||||
|
self.render_graph_builder = self
|
||||||
|
.render_graph_builder
|
||||||
|
.add_forward_pass()
|
||||||
|
.add_forward_pipeline();
|
||||||
|
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_wgpu_renderer(mut self) -> Self {
|
pub fn add_wgpu_renderer(mut self) -> Self {
|
||||||
self.renderer = Some(Box::new(render_graph_2::WgpuRenderer::new()));
|
self.renderer = Some(Box::new(WgpuRenderer::new()));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_defaults_legacy(self) -> Self {
|
pub fn add_defaults_legacy(self) -> Self {
|
||||||
self
|
self.with_legacy_render_graph()
|
||||||
.with_legacy_render_graph()
|
|
||||||
.add_default_resources()
|
.add_default_resources()
|
||||||
.add_default_passes()
|
.add_default_passes()
|
||||||
.add_default_systems()
|
.add_default_systems()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn add_defaults(self) -> Self {
|
pub fn add_defaults(self) -> Self {
|
||||||
self
|
self.add_default_resources()
|
||||||
.add_default_resources()
|
|
||||||
.add_default_systems()
|
.add_default_systems()
|
||||||
|
.add_render_graph_defaults()
|
||||||
.add_wgpu_renderer()
|
.add_wgpu_renderer()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,5 +1,6 @@
|
|||||||
mod app;
|
mod app;
|
||||||
mod app_builder;
|
mod app_builder;
|
||||||
|
pub mod system_stage;
|
||||||
|
|
||||||
pub use app::App;
|
pub use app::App;
|
||||||
pub use app_builder::AppBuilder;
|
pub use app_builder::AppBuilder;
|
||||||
|
|||||||
1
src/app/system_stage.rs
Normal file
1
src/app/system_stage.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub const UPDATE: &str = "update";
|
||||||
41
src/render/render_graph_2/draw_target.rs
Normal file
41
src/render/render_graph_2/draw_target.rs
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
use crate::{
|
||||||
|
asset::{AssetStorage, Handle, Mesh},
|
||||||
|
legion::prelude::*,
|
||||||
|
render::{
|
||||||
|
render_graph_2::{ShaderMaterials, RenderPass},
|
||||||
|
Instanced,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
// A set of draw calls. ex: get + draw meshes, get + draw instanced meshes, draw ui meshes, etc
|
||||||
|
pub type DrawTarget = fn(world: &World, render_pass: &mut dyn RenderPass);
|
||||||
|
|
||||||
|
pub fn mesh_draw_target(world: &World, render_pass: &mut dyn RenderPass) {
|
||||||
|
let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
|
||||||
|
let mut last_mesh_id = None;
|
||||||
|
let mesh_query =
|
||||||
|
<(Read<ShaderMaterials>, 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(mesh.id) {
|
||||||
|
// render_pass.load_mesh(mesh.id, mesh_asset);
|
||||||
|
// render_pass.set_index_buffer(mesh_asset.index_buffer.as_ref().unwrap(), 0);
|
||||||
|
// render_pass.set_vertex_buffers(0, &[(&mesh_asset.vertex_buffer.as_ref().unwrap(), 0)]);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(ref mesh_asset) = mesh_storage.get(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);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,52 +0,0 @@
|
|||||||
use crate::render::{render_graph_2::*, shader::{Shader, ShaderStage}, Vertex};
|
|
||||||
|
|
||||||
fn build_example_graph() -> RenderGraph {
|
|
||||||
// TODO: read this from swap chain
|
|
||||||
let swap_chain_color_format = wgpu::TextureFormat::Bgra8UnormSrgb;
|
|
||||||
RenderGraph::build()
|
|
||||||
.add_pass(
|
|
||||||
"main",
|
|
||||||
PassDescriptor {
|
|
||||||
color_attachments: Vec::new(),
|
|
||||||
depth_stencil_attachment: None,
|
|
||||||
sample_count: 1,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.add_pipeline(
|
|
||||||
"forward",
|
|
||||||
PipelineDescriptor::build(Shader::from_glsl(
|
|
||||||
include_str!("../passes/forward/forward.vert"),
|
|
||||||
ShaderStage::Vertex,
|
|
||||||
))
|
|
||||||
.with_fragment_shader(Shader::from_glsl(
|
|
||||||
include_str!("../passes/forward/forward.vert"),
|
|
||||||
ShaderStage::Fragment,
|
|
||||||
))
|
|
||||||
.with_rasterization_state(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,
|
|
||||||
})
|
|
||||||
.with_depth_stencil_state(wgpu::DepthStencilStateDescriptor {
|
|
||||||
format: wgpu::TextureFormat::Depth32Float,
|
|
||||||
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,
|
|
||||||
})
|
|
||||||
.with_color_state(wgpu::ColorStateDescriptor {
|
|
||||||
format: swap_chain_color_format,
|
|
||||||
color_blend: wgpu::BlendDescriptor::REPLACE,
|
|
||||||
alpha_blend: wgpu::BlendDescriptor::REPLACE,
|
|
||||||
write_mask: wgpu::ColorWrite::ALL,
|
|
||||||
})
|
|
||||||
.with_vertex_buffer_descriptor(Vertex::get_vertex_buffer_descriptor())
|
|
||||||
.with_draw_target(mesh_draw_target)
|
|
||||||
.build()
|
|
||||||
)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
@ -1,15 +1,19 @@
|
|||||||
|
pub mod pipelines;
|
||||||
|
pub mod resource;
|
||||||
|
pub mod wgpu_renderer;
|
||||||
mod pipeline;
|
mod pipeline;
|
||||||
mod pass;
|
mod pass;
|
||||||
mod renderer;
|
mod renderer;
|
||||||
mod shader;
|
mod shader;
|
||||||
mod render_graph;
|
mod render_graph;
|
||||||
mod example;
|
mod draw_target;
|
||||||
|
|
||||||
pub use pipeline::*;
|
pub use pipeline::*;
|
||||||
pub use pass::*;
|
pub use pass::*;
|
||||||
pub use renderer::*;
|
pub use renderer::*;
|
||||||
pub use shader::*;
|
pub use shader::*;
|
||||||
pub use render_graph::*;
|
pub use render_graph::*;
|
||||||
|
pub use draw_target::*;
|
||||||
|
|
||||||
// a named graphics resource provided by a resource provider
|
// a named graphics resource provided by a resource provider
|
||||||
pub struct Resource {
|
pub struct Resource {
|
||||||
|
|||||||
44
src/render/render_graph_2/pipelines/forward/forward.frag
Normal file
44
src/render/render_graph_2/pipelines/forward/forward.frag
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#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 = 1, binding = 0) uniform Entity {
|
||||||
|
mat4 u_World;
|
||||||
|
vec4 u_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(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) * u_Color;
|
||||||
|
}
|
||||||
23
src/render/render_graph_2/pipelines/forward/forward.vert
Normal file
23
src/render/render_graph_2/pipelines/forward/forward.vert
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#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 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;
|
||||||
|
}
|
||||||
92
src/render/render_graph_2/pipelines/forward/mod.rs
Normal file
92
src/render/render_graph_2/pipelines/forward/mod.rs
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
use crate::render::{
|
||||||
|
Vertex,
|
||||||
|
{
|
||||||
|
render_graph_2::{
|
||||||
|
mesh_draw_target, PassDescriptor, PipelineDescriptor, RenderGraphBuilder,
|
||||||
|
RenderPassColorAttachmentDescriptor, RenderPassDepthStencilAttachmentDescriptor,
|
||||||
|
resource,
|
||||||
|
},
|
||||||
|
shader::{Shader, ShaderStage},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
pub trait ForwardPipelineBuilder {
|
||||||
|
fn add_forward_pipeline(self) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ForwardPipelineBuilder for RenderGraphBuilder {
|
||||||
|
fn add_forward_pipeline(self) -> Self {
|
||||||
|
self.add_pipeline(
|
||||||
|
"forward",
|
||||||
|
PipelineDescriptor::build(Shader::from_glsl(
|
||||||
|
include_str!("forward.vert"),
|
||||||
|
ShaderStage::Vertex,
|
||||||
|
))
|
||||||
|
.with_fragment_shader(Shader::from_glsl(
|
||||||
|
include_str!("forward.frag"),
|
||||||
|
ShaderStage::Fragment,
|
||||||
|
))
|
||||||
|
.with_rasterization_state(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,
|
||||||
|
})
|
||||||
|
.with_depth_stencil_state(wgpu::DepthStencilStateDescriptor {
|
||||||
|
format: wgpu::TextureFormat::Depth32Float,
|
||||||
|
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,
|
||||||
|
})
|
||||||
|
.with_color_state(wgpu::ColorStateDescriptor {
|
||||||
|
format: wgpu::TextureFormat::Bgra8UnormSrgb,
|
||||||
|
color_blend: wgpu::BlendDescriptor::REPLACE,
|
||||||
|
alpha_blend: wgpu::BlendDescriptor::REPLACE,
|
||||||
|
write_mask: wgpu::ColorWrite::ALL,
|
||||||
|
})
|
||||||
|
.with_vertex_buffer_descriptor(Vertex::get_vertex_buffer_descriptor())
|
||||||
|
.with_draw_target(mesh_draw_target)
|
||||||
|
.build(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub trait ForwardPassBuilder {
|
||||||
|
fn add_forward_pass(self) -> Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ForwardPassBuilder for RenderGraphBuilder {
|
||||||
|
fn add_forward_pass(self) -> Self {
|
||||||
|
self.add_pass(
|
||||||
|
"main",
|
||||||
|
PassDescriptor {
|
||||||
|
color_attachments: vec![RenderPassColorAttachmentDescriptor {
|
||||||
|
attachment: resource::texture::SWAP_CHAIN.to_string(),
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
}],
|
||||||
|
depth_stencil_attachment: None,
|
||||||
|
// depth_stencil_attachment: Some(RenderPassDepthStencilAttachmentDescriptor {
|
||||||
|
// attachment: "forward_depth".to_string(),
|
||||||
|
// 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,
|
||||||
|
// }),
|
||||||
|
sample_count: 1,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
3
src/render/render_graph_2/pipelines/mod.rs
Normal file
3
src/render/render_graph_2/pipelines/mod.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
mod forward;
|
||||||
|
|
||||||
|
pub use forward::*;
|
||||||
@ -17,21 +17,19 @@ impl Default for RenderGraph {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderGraph {
|
|
||||||
pub fn build() -> RenderGraphBuilder {
|
|
||||||
RenderGraphBuilder {
|
|
||||||
render_graph: RenderGraph::default(),
|
|
||||||
current_pass: None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct RenderGraphBuilder {
|
pub struct RenderGraphBuilder {
|
||||||
render_graph: RenderGraph,
|
render_graph: RenderGraph,
|
||||||
current_pass: Option<String>,
|
current_pass: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RenderGraphBuilder {
|
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 {
|
pub fn add_pass(mut self, name: &str, pass: PassDescriptor) -> Self {
|
||||||
self.current_pass = Some(name.to_string());
|
self.current_pass = Some(name.to_string());
|
||||||
self.render_graph
|
self.render_graph
|
||||||
|
|||||||
@ -1,50 +1,4 @@
|
|||||||
use crate::{
|
use crate::{asset::Mesh, legion::prelude::*, render::render_graph_2::RenderGraph};
|
||||||
asset::{AssetStorage, Handle, Mesh},
|
|
||||||
legion::prelude::*,
|
|
||||||
render::{
|
|
||||||
render_graph_2::{PassDescriptor, PipelineDescriptor, RenderGraph, ShaderMaterials},
|
|
||||||
Instanced,
|
|
||||||
},
|
|
||||||
};
|
|
||||||
use std::{collections::HashMap, ops::Deref};
|
|
||||||
use zerocopy::AsBytes;
|
|
||||||
|
|
||||||
// A set of draw calls. ex: get + draw meshes, get + draw instanced meshes, draw ui meshes, etc
|
|
||||||
// Mesh target
|
|
||||||
// trait DrawTarget {
|
|
||||||
// fn draw(device: &wgpu::Device);
|
|
||||||
// }
|
|
||||||
pub type DrawTarget = fn(world: &World, render_pass: &mut dyn RenderPass);
|
|
||||||
|
|
||||||
pub fn mesh_draw_target(world: &World, render_pass: &mut dyn RenderPass) {
|
|
||||||
let mut mesh_storage = world.resources.get_mut::<AssetStorage<Mesh>>().unwrap();
|
|
||||||
let mut last_mesh_id = None;
|
|
||||||
let mesh_query =
|
|
||||||
<(Read<ShaderMaterials>, 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(mesh.id) {
|
|
||||||
// render_pass.load_mesh(mesh.id, mesh_asset);
|
|
||||||
// render_pass.set_index_buffer(mesh_asset.index_buffer.as_ref().unwrap(), 0);
|
|
||||||
// render_pass.set_vertex_buffers(0, &[(&mesh_asset.vertex_buffer.as_ref().unwrap(), 0)]);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(ref mesh_asset) = mesh_storage.get(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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait Renderer {
|
pub trait Renderer {
|
||||||
fn initialize(&mut self, world: &mut World);
|
fn initialize(&mut self, world: &mut World);
|
||||||
@ -53,208 +7,6 @@ pub trait Renderer {
|
|||||||
fn load_mesh(&mut self, asset_id: usize, mesh: &Mesh);
|
fn load_mesh(&mut self, asset_id: usize, mesh: &Mesh);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WgpuRenderer {
|
|
||||||
pub device: wgpu::Device,
|
|
||||||
pub surface: Option<wgpu::Surface>,
|
|
||||||
pub swap_chain_descriptor: wgpu::SwapChainDescriptor,
|
|
||||||
pub render_pipelines: HashMap<String, wgpu::RenderPipeline>,
|
|
||||||
pub buffers: HashMap<String, wgpu::Buffer>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WgpuRenderer {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
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 swap_chain_descriptor = wgpu::SwapChainDescriptor {
|
|
||||||
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
|
|
||||||
format: wgpu::TextureFormat::Bgra8UnormSrgb,
|
|
||||||
width: 0,
|
|
||||||
height: 0,
|
|
||||||
present_mode: wgpu::PresentMode::Vsync,
|
|
||||||
};
|
|
||||||
|
|
||||||
WgpuRenderer {
|
|
||||||
device,
|
|
||||||
surface: None,
|
|
||||||
swap_chain_descriptor,
|
|
||||||
render_pipelines: HashMap::new(),
|
|
||||||
buffers: HashMap::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn create_render_pipeline(
|
|
||||||
pipeline_descriptor: &PipelineDescriptor,
|
|
||||||
device: &wgpu::Device,
|
|
||||||
) -> wgpu::RenderPipeline {
|
|
||||||
let vertex_shader_module = pipeline_descriptor
|
|
||||||
.shader_stages
|
|
||||||
.vertex
|
|
||||||
.create_shader_module(device);
|
|
||||||
let fragment_shader_module = match pipeline_descriptor.shader_stages.fragment {
|
|
||||||
Some(ref fragment_shader) => Some(fragment_shader.create_shader_module(device)),
|
|
||||||
None => None,
|
|
||||||
};
|
|
||||||
|
|
||||||
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
|
||||||
bind_group_layouts: &[],
|
|
||||||
});
|
|
||||||
let render_pipeline_descriptor = wgpu::RenderPipelineDescriptor {
|
|
||||||
layout: &pipeline_layout,
|
|
||||||
vertex_stage: wgpu::ProgrammableStageDescriptor {
|
|
||||||
module: &vertex_shader_module,
|
|
||||||
entry_point: &pipeline_descriptor.shader_stages.vertex.entry_point,
|
|
||||||
},
|
|
||||||
fragment_stage: match pipeline_descriptor.shader_stages.fragment {
|
|
||||||
Some(ref fragment_shader) => Some(wgpu::ProgrammableStageDescriptor {
|
|
||||||
entry_point: &fragment_shader.entry_point,
|
|
||||||
module: fragment_shader_module.as_ref().unwrap(),
|
|
||||||
}),
|
|
||||||
None => None,
|
|
||||||
},
|
|
||||||
rasterization_state: pipeline_descriptor.rasterization_state.clone(),
|
|
||||||
primitive_topology: pipeline_descriptor.primitive_topology,
|
|
||||||
color_states: &pipeline_descriptor.color_states,
|
|
||||||
depth_stencil_state: pipeline_descriptor.depth_stencil_state.clone(),
|
|
||||||
index_format: pipeline_descriptor.index_format,
|
|
||||||
vertex_buffers: &pipeline_descriptor
|
|
||||||
.vertex_buffer_descriptors
|
|
||||||
.iter()
|
|
||||||
.map(|v| v.into())
|
|
||||||
.collect::<Vec<wgpu::VertexBufferDescriptor>>(),
|
|
||||||
sample_count: pipeline_descriptor.sample_count,
|
|
||||||
sample_mask: pipeline_descriptor.sample_mask,
|
|
||||||
alpha_to_coverage_enabled: pipeline_descriptor.alpha_to_coverage_enabled,
|
|
||||||
};
|
|
||||||
|
|
||||||
device.create_render_pipeline(&render_pipeline_descriptor)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn create_render_pass<'a>(
|
|
||||||
pass_descriptor: &PassDescriptor,
|
|
||||||
encoder: &'a mut wgpu::CommandEncoder,
|
|
||||||
frame: &'a wgpu::SwapChainOutput,
|
|
||||||
) -> wgpu::RenderPass<'a> {
|
|
||||||
// TODO: fill this in
|
|
||||||
encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
|
||||||
color_attachments: &[],
|
|
||||||
depth_stencil_attachment: None,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Renderer for WgpuRenderer {
|
|
||||||
fn initialize(&mut self, world: &mut World) {
|
|
||||||
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)
|
|
||||||
};
|
|
||||||
|
|
||||||
self.surface = Some(surface);
|
|
||||||
self.resize(world, window_size.width, window_size.height);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resize(&mut self, world: &mut World, width: u32, height: u32) {
|
|
||||||
let swap_chain = self
|
|
||||||
.device
|
|
||||||
.create_swap_chain(self.surface.as_ref().unwrap(), &self.swap_chain_descriptor);
|
|
||||||
self.swap_chain_descriptor.width = width;
|
|
||||||
self.swap_chain_descriptor.height = height;
|
|
||||||
|
|
||||||
// WgpuRenderer can't own swap_chain without creating lifetime ergonomics issues
|
|
||||||
world.resources.insert(swap_chain);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn process_render_graph(&mut self, render_graph: &RenderGraph, world: &mut World) {
|
|
||||||
let mut swap_chain = world.resources.get_mut::<wgpu::SwapChain>().unwrap();
|
|
||||||
let frame = swap_chain
|
|
||||||
.get_next_texture()
|
|
||||||
.expect("Timeout when acquiring next swap chain texture");
|
|
||||||
|
|
||||||
let mut encoder = self
|
|
||||||
.device
|
|
||||||
.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
|
|
||||||
|
|
||||||
for (pass_name, pass_descriptor) in render_graph.pass_descriptors.iter() {
|
|
||||||
let mut render_pass =
|
|
||||||
WgpuRenderer::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)
|
|
||||||
{
|
|
||||||
if let None = self.render_pipelines.get(pass_pipeline) {
|
|
||||||
let render_pipeline = WgpuRenderer::create_render_pipeline(
|
|
||||||
pipeline_descriptor,
|
|
||||||
&self.device,
|
|
||||||
);
|
|
||||||
self.render_pipelines
|
|
||||||
.insert(pass_pipeline.to_string(), render_pipeline);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut render_pass = WgpuRenderPass {
|
|
||||||
render_pass: &mut render_pass,
|
|
||||||
renderer: &self,
|
|
||||||
};
|
|
||||||
for draw_target in pipeline_descriptor.draw_targets.iter() {
|
|
||||||
draw_target(world, &mut render_pass);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn load_mesh(&mut self, asset_id: usize, mesh: &Mesh) {
|
|
||||||
if let None = mesh.vertex_buffer {
|
|
||||||
self.buffers.insert(
|
|
||||||
format!("meshv{}", asset_id),
|
|
||||||
self.device
|
|
||||||
.create_buffer_with_data(mesh.vertices.as_bytes(), wgpu::BufferUsage::VERTEX),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if let None = mesh.index_buffer {
|
|
||||||
self.buffers.insert(
|
|
||||||
format!("meshi{}", asset_id),
|
|
||||||
self.device
|
|
||||||
.create_buffer_with_data(mesh.indices.as_bytes(), wgpu::BufferUsage::INDEX),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub trait RenderPass {
|
pub trait RenderPass {
|
||||||
fn set_index_buffer(&mut self, buffer: &wgpu::Buffer, offset: wgpu::BufferAddress);
|
fn set_index_buffer(&mut self, buffer: &wgpu::Buffer, offset: wgpu::BufferAddress);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct WgpuRenderPass<'a, 'b, 'c> {
|
|
||||||
pub render_pass: &'b mut wgpu::RenderPass<'a>,
|
|
||||||
pub renderer: &'c WgpuRenderer,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a, 'b, 'c> RenderPass for WgpuRenderPass<'a, 'b, 'c> {
|
|
||||||
fn set_index_buffer(&mut self, buffer: &wgpu::Buffer, offset: wgpu::BufferAddress) {
|
|
||||||
self.render_pass.set_index_buffer(buffer, offset);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// pub trait RenderResources {
|
|
||||||
// fn get_buffer(name: &str) -> Option<Buffer>;
|
|
||||||
// fn get_texture(name: &str) -> Option<Texture>;
|
|
||||||
// fn get_sampler(name: &str) -> Option<Sampler>;
|
|
||||||
// }
|
|
||||||
1
src/render/render_graph_2/resource/mod.rs
Normal file
1
src/render/render_graph_2/resource/mod.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub mod texture;
|
||||||
1
src/render/render_graph_2/resource/texture.rs
Normal file
1
src/render/render_graph_2/resource/texture.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
pub const SWAP_CHAIN: &str = "swap_chain";
|
||||||
274
src/render/render_graph_2/wgpu_renderer.rs
Normal file
274
src/render/render_graph_2/wgpu_renderer.rs
Normal file
@ -0,0 +1,274 @@
|
|||||||
|
use crate::{
|
||||||
|
asset::Mesh,
|
||||||
|
legion::prelude::*,
|
||||||
|
render::render_graph_2::{
|
||||||
|
resource, PassDescriptor, PipelineDescriptor, RenderGraph, RenderPass,
|
||||||
|
RenderPassColorAttachmentDescriptor, RenderPassDepthStencilAttachmentDescriptor, Renderer,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
use std::{collections::HashMap, ops::Deref};
|
||||||
|
use zerocopy::AsBytes;
|
||||||
|
|
||||||
|
pub struct WgpuRenderer {
|
||||||
|
pub device: wgpu::Device,
|
||||||
|
pub queue: wgpu::Queue,
|
||||||
|
pub surface: Option<wgpu::Surface>,
|
||||||
|
pub swap_chain_descriptor: wgpu::SwapChainDescriptor,
|
||||||
|
pub render_pipelines: HashMap<String, wgpu::RenderPipeline>,
|
||||||
|
pub buffers: HashMap<String, wgpu::Buffer>,
|
||||||
|
pub textures: HashMap<String, wgpu::TextureView>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WgpuRenderer {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
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 swap_chain_descriptor = wgpu::SwapChainDescriptor {
|
||||||
|
usage: wgpu::TextureUsage::OUTPUT_ATTACHMENT,
|
||||||
|
format: wgpu::TextureFormat::Bgra8UnormSrgb,
|
||||||
|
width: 0,
|
||||||
|
height: 0,
|
||||||
|
present_mode: wgpu::PresentMode::Vsync,
|
||||||
|
};
|
||||||
|
|
||||||
|
WgpuRenderer {
|
||||||
|
device,
|
||||||
|
queue,
|
||||||
|
surface: None,
|
||||||
|
swap_chain_descriptor,
|
||||||
|
render_pipelines: HashMap::new(),
|
||||||
|
buffers: HashMap::new(),
|
||||||
|
textures: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_render_pipeline(
|
||||||
|
pipeline_descriptor: &PipelineDescriptor,
|
||||||
|
device: &wgpu::Device,
|
||||||
|
) -> wgpu::RenderPipeline {
|
||||||
|
let vertex_shader_module = pipeline_descriptor
|
||||||
|
.shader_stages
|
||||||
|
.vertex
|
||||||
|
.create_shader_module(device);
|
||||||
|
let fragment_shader_module = match pipeline_descriptor.shader_stages.fragment {
|
||||||
|
Some(ref fragment_shader) => Some(fragment_shader.create_shader_module(device)),
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
|
||||||
|
bind_group_layouts: &[],
|
||||||
|
});
|
||||||
|
let render_pipeline_descriptor = wgpu::RenderPipelineDescriptor {
|
||||||
|
layout: &pipeline_layout,
|
||||||
|
vertex_stage: wgpu::ProgrammableStageDescriptor {
|
||||||
|
module: &vertex_shader_module,
|
||||||
|
entry_point: &pipeline_descriptor.shader_stages.vertex.entry_point,
|
||||||
|
},
|
||||||
|
fragment_stage: match pipeline_descriptor.shader_stages.fragment {
|
||||||
|
Some(ref fragment_shader) => Some(wgpu::ProgrammableStageDescriptor {
|
||||||
|
entry_point: &fragment_shader.entry_point,
|
||||||
|
module: fragment_shader_module.as_ref().unwrap(),
|
||||||
|
}),
|
||||||
|
None => None,
|
||||||
|
},
|
||||||
|
rasterization_state: pipeline_descriptor.rasterization_state.clone(),
|
||||||
|
primitive_topology: pipeline_descriptor.primitive_topology,
|
||||||
|
color_states: &pipeline_descriptor.color_states,
|
||||||
|
depth_stencil_state: pipeline_descriptor.depth_stencil_state.clone(),
|
||||||
|
index_format: pipeline_descriptor.index_format,
|
||||||
|
vertex_buffers: &pipeline_descriptor
|
||||||
|
.vertex_buffer_descriptors
|
||||||
|
.iter()
|
||||||
|
.map(|v| v.into())
|
||||||
|
.collect::<Vec<wgpu::VertexBufferDescriptor>>(),
|
||||||
|
sample_count: pipeline_descriptor.sample_count,
|
||||||
|
sample_mask: pipeline_descriptor.sample_mask,
|
||||||
|
alpha_to_coverage_enabled: pipeline_descriptor.alpha_to_coverage_enabled,
|
||||||
|
};
|
||||||
|
|
||||||
|
device.create_render_pipeline(&render_pipeline_descriptor)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_render_pass<'a>(
|
||||||
|
&self,
|
||||||
|
pass_descriptor: &PassDescriptor,
|
||||||
|
encoder: &'a mut wgpu::CommandEncoder,
|
||||||
|
frame: &'a wgpu::SwapChainOutput,
|
||||||
|
) -> wgpu::RenderPass<'a> {
|
||||||
|
// TODO: fill this in
|
||||||
|
encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
|
||||||
|
color_attachments: &pass_descriptor
|
||||||
|
.color_attachments
|
||||||
|
.iter()
|
||||||
|
.map(|c| self.create_wgpu_color_attachment_descriptor(c, frame))
|
||||||
|
.collect::<Vec<wgpu::RenderPassColorAttachmentDescriptor>>(),
|
||||||
|
depth_stencil_attachment: pass_descriptor
|
||||||
|
.depth_stencil_attachment
|
||||||
|
.as_ref()
|
||||||
|
.map(|d| self.create_wgpu_depth_stencil_attachment_descriptor(d, frame)),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_wgpu_color_attachment_descriptor<'a>(
|
||||||
|
&'a self,
|
||||||
|
color_attachment_descriptor: &RenderPassColorAttachmentDescriptor,
|
||||||
|
frame: &'a wgpu::SwapChainOutput,
|
||||||
|
) -> wgpu::RenderPassColorAttachmentDescriptor<'a> {
|
||||||
|
let attachment = match color_attachment_descriptor.attachment.as_str() {
|
||||||
|
resource::texture::SWAP_CHAIN => &frame.view,
|
||||||
|
_ => self
|
||||||
|
.textures
|
||||||
|
.get(&color_attachment_descriptor.attachment)
|
||||||
|
.unwrap(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let resolve_target = match color_attachment_descriptor.resolve_target {
|
||||||
|
Some(ref target) => match target.as_str() {
|
||||||
|
resource::texture::SWAP_CHAIN => Some(&frame.view),
|
||||||
|
_ => Some(&frame.view),
|
||||||
|
},
|
||||||
|
None => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
wgpu::RenderPassColorAttachmentDescriptor {
|
||||||
|
store_op: color_attachment_descriptor.store_op,
|
||||||
|
load_op: color_attachment_descriptor.load_op,
|
||||||
|
clear_color: color_attachment_descriptor.clear_color,
|
||||||
|
attachment,
|
||||||
|
resolve_target,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn create_wgpu_depth_stencil_attachment_descriptor<'a>(
|
||||||
|
&'a self,
|
||||||
|
depth_stencil_attachment_descriptor: &RenderPassDepthStencilAttachmentDescriptor,
|
||||||
|
frame: &'a wgpu::SwapChainOutput,
|
||||||
|
) -> wgpu::RenderPassDepthStencilAttachmentDescriptor<&'a wgpu::TextureView> {
|
||||||
|
let attachment = match depth_stencil_attachment_descriptor.attachment.as_str() {
|
||||||
|
resource::texture::SWAP_CHAIN => &frame.view,
|
||||||
|
_ => self
|
||||||
|
.textures
|
||||||
|
.get(&depth_stencil_attachment_descriptor.attachment)
|
||||||
|
.unwrap(),
|
||||||
|
};
|
||||||
|
|
||||||
|
wgpu::RenderPassDepthStencilAttachmentDescriptor {
|
||||||
|
attachment,
|
||||||
|
clear_depth: depth_stencil_attachment_descriptor.clear_depth,
|
||||||
|
clear_stencil: depth_stencil_attachment_descriptor.clear_stencil,
|
||||||
|
depth_load_op: depth_stencil_attachment_descriptor.depth_load_op,
|
||||||
|
depth_store_op: depth_stencil_attachment_descriptor.depth_store_op,
|
||||||
|
stencil_load_op: depth_stencil_attachment_descriptor.stencil_load_op,
|
||||||
|
stencil_store_op: depth_stencil_attachment_descriptor.stencil_store_op,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Renderer for WgpuRenderer {
|
||||||
|
fn initialize(&mut self, world: &mut World) {
|
||||||
|
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)
|
||||||
|
};
|
||||||
|
|
||||||
|
self.surface = Some(surface);
|
||||||
|
self.resize(world, window_size.width, window_size.height);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn resize(&mut self, world: &mut World, width: u32, height: u32) {
|
||||||
|
let swap_chain = self
|
||||||
|
.device
|
||||||
|
.create_swap_chain(self.surface.as_ref().unwrap(), &self.swap_chain_descriptor);
|
||||||
|
self.swap_chain_descriptor.width = width;
|
||||||
|
self.swap_chain_descriptor.height = height;
|
||||||
|
|
||||||
|
// WgpuRenderer can't own swap_chain without creating lifetime ergonomics issues
|
||||||
|
world.resources.insert(swap_chain);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_render_graph(&mut self, render_graph: &RenderGraph, world: &mut World) {
|
||||||
|
let mut swap_chain = world.resources.get_mut::<wgpu::SwapChain>().unwrap();
|
||||||
|
let frame = swap_chain
|
||||||
|
.get_next_texture()
|
||||||
|
.expect("Timeout when acquiring next swap chain texture");
|
||||||
|
|
||||||
|
let mut encoder = self
|
||||||
|
.device
|
||||||
|
.create_command_encoder(&wgpu::CommandEncoderDescriptor { todo: 0 });
|
||||||
|
|
||||||
|
for (pass_name, pass_descriptor) in render_graph.pass_descriptors.iter() {
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
if let None = self.render_pipelines.get(pass_pipeline) {
|
||||||
|
let render_pipeline = WgpuRenderer::create_render_pipeline(
|
||||||
|
pipeline_descriptor,
|
||||||
|
&self.device,
|
||||||
|
);
|
||||||
|
self.render_pipelines
|
||||||
|
.insert(pass_pipeline.to_string(), render_pipeline);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut render_pass = WgpuRenderPass {
|
||||||
|
render_pass: &mut render_pass,
|
||||||
|
renderer: &self,
|
||||||
|
};
|
||||||
|
for draw_target in pipeline_descriptor.draw_targets.iter() {
|
||||||
|
draw_target(world, &mut render_pass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let command_buffer = encoder.finish();
|
||||||
|
self.queue.submit(&[command_buffer]);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load_mesh(&mut self, asset_id: usize, mesh: &Mesh) {
|
||||||
|
if let None = mesh.vertex_buffer {
|
||||||
|
self.buffers.insert(
|
||||||
|
format!("meshv{}", asset_id),
|
||||||
|
self.device
|
||||||
|
.create_buffer_with_data(mesh.vertices.as_bytes(), wgpu::BufferUsage::VERTEX),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let None = mesh.index_buffer {
|
||||||
|
self.buffers.insert(
|
||||||
|
format!("meshi{}", asset_id),
|
||||||
|
self.device
|
||||||
|
.create_buffer_with_data(mesh.indices.as_bytes(), wgpu::BufferUsage::INDEX),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct WgpuRenderPass<'a, 'b, 'c> {
|
||||||
|
pub render_pass: &'b mut wgpu::RenderPass<'a>,
|
||||||
|
pub renderer: &'c WgpuRenderer,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a, 'b, 'c> RenderPass for WgpuRenderPass<'a, 'b, 'c> {
|
||||||
|
fn set_index_buffer(&mut self, buffer: &wgpu::Buffer, offset: wgpu::BufferAddress) {
|
||||||
|
self.render_pass.set_index_buffer(buffer, offset);
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user