mirror of
https://github.com/bevyengine/bevy
synced 2024-11-10 07:04:33 +00:00
RenderGraph2: Finish porting, refactor, cleanup
This commit is contained in:
parent
06b6ade902
commit
791c475354
79 changed files with 965 additions and 2473 deletions
|
@ -6,13 +6,14 @@ edition = "2018"
|
|||
|
||||
[features]
|
||||
default = ["headless", "wgpu", "winit"]
|
||||
headless = ["asset", "core", "derive", "diagnostic", "gltf", "input", "render", "serialization", "transform", "ui", "window"]
|
||||
headless = ["asset", "core", "derive", "diagnostic", "gltf", "input", "pbr", "render", "serialization", "transform", "ui", "window"]
|
||||
asset = ["bevy_asset"]
|
||||
core = ["bevy_core"]
|
||||
derive = ["bevy_derive"]
|
||||
diagnostic = ["bevy_diagnostic"]
|
||||
gltf = ["bevy_gltf"]
|
||||
input = ["bevy_input"]
|
||||
pbr = ["bevy_pbr"]
|
||||
render = ["bevy_render"]
|
||||
serialization = ["bevy_serialization"]
|
||||
transform = ["bevy_transform"]
|
||||
|
@ -30,6 +31,7 @@ bevy_derive = { path = "bevy_derive", optional = true }
|
|||
bevy_diagnostic = { path = "bevy_diagnostic", optional = true }
|
||||
bevy_gltf = { path = "bevy_gltf", optional = true }
|
||||
bevy_input = { path = "bevy_input", optional = true }
|
||||
bevy_pbr = { path = "bevy_pbr", optional = true }
|
||||
bevy_render = { path = "bevy_render", optional = true }
|
||||
bevy_serialization = { path = "bevy_serialization", optional = true }
|
||||
bevy_transform = { path = "bevy_transform", optional = true }
|
||||
|
@ -51,6 +53,7 @@ members = [
|
|||
"bevy_diagnostic",
|
||||
"bevy_gltf",
|
||||
"bevy_input",
|
||||
"bevy_pbr",
|
||||
"bevy_render",
|
||||
"bevy_serialization",
|
||||
"bevy_transform",
|
||||
|
|
18
bevy_pbr/Cargo.toml
Normal file
18
bevy_pbr/Cargo.toml
Normal file
|
@ -0,0 +1,18 @@
|
|||
[package]
|
||||
name = "bevy_pbr"
|
||||
version = "0.1.0"
|
||||
authors = ["Carter Anderson <mcanders1@gmail.com>"]
|
||||
edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
bevy_app = { path = "../bevy_app", version = "0.1.0" }
|
||||
bevy_asset = { path = "../bevy_asset", version = "0.1.0" }
|
||||
bevy_core = { path = "../bevy_core", version = "0.1.0" }
|
||||
bevy_derive = { path = "../bevy_derive", version = "0.1.0" }
|
||||
bevy_render = { path = "../bevy_render", version = "0.1.0" }
|
||||
bevy_transform = { path = "../bevy_transform" }
|
||||
bevy_window = { path = "../bevy_window", version = "0.1.0" }
|
||||
legion = { path = "../bevy_legion"}
|
||||
|
||||
zerocopy = "0.3"
|
||||
glam = "0.8.6"
|
28
bevy_pbr/src/entity.rs
Normal file
28
bevy_pbr/src/entity.rs
Normal file
|
@ -0,0 +1,28 @@
|
|||
use crate::{light::Light, material::StandardMaterial};
|
||||
use bevy_asset::Handle;
|
||||
use bevy_render::{mesh::Mesh, Renderable};
|
||||
use bevy_transform::prelude::{LocalToWorld, Rotation, Scale, Translation};
|
||||
use bevy_derive::EntityArchetype;
|
||||
|
||||
#[derive(EntityArchetype, Default)]
|
||||
#[module(meta = false)]
|
||||
pub struct MeshEntity {
|
||||
// #[tag]
|
||||
pub mesh: Handle<Mesh>,
|
||||
// #[tag]
|
||||
pub material: Handle<StandardMaterial>,
|
||||
pub renderable: Renderable,
|
||||
pub local_to_world: LocalToWorld,
|
||||
pub translation: Translation,
|
||||
pub rotation: Rotation,
|
||||
pub scale: Scale,
|
||||
}
|
||||
|
||||
#[derive(EntityArchetype, Default)]
|
||||
#[module(meta = false)]
|
||||
pub struct LightEntity {
|
||||
pub light: Light,
|
||||
pub local_to_world: LocalToWorld,
|
||||
pub translation: Translation,
|
||||
pub rotation: Rotation,
|
||||
}
|
105
bevy_pbr/src/forward_pbr_render_graph.rs
Normal file
105
bevy_pbr/src/forward_pbr_render_graph.rs
Normal file
|
@ -0,0 +1,105 @@
|
|||
use crate::{
|
||||
material::StandardMaterial, nodes::LightsNode, passes::build_main_pass,
|
||||
pipelines::build_forward_pipeline,
|
||||
};
|
||||
use bevy_app::GetEventReader;
|
||||
use bevy_asset::AssetStorage;
|
||||
use bevy_render::{
|
||||
draw_target::AssignedMeshesDrawTarget,
|
||||
pipeline::PipelineDescriptor,
|
||||
render_graph::{
|
||||
nodes::{
|
||||
AssetUniformNode, CameraNode, PassNode, UniformNode, WindowSwapChainNode,
|
||||
WindowTextureNode,
|
||||
},
|
||||
RenderGraph,
|
||||
},
|
||||
shader::Shader,
|
||||
texture::{Extent3d, TextureDescriptor, TextureDimension, TextureFormat, TextureUsage},
|
||||
};
|
||||
use bevy_transform::prelude::LocalToWorld;
|
||||
use bevy_window::{WindowCreated, WindowReference, WindowResized};
|
||||
use legion::prelude::Resources;
|
||||
|
||||
pub trait ForwardPbrRenderGraphBuilder {
|
||||
fn add_pbr_graph(&mut self, resources: &Resources) -> &mut Self;
|
||||
}
|
||||
|
||||
impl ForwardPbrRenderGraphBuilder for RenderGraph {
|
||||
fn add_pbr_graph(&mut self, resources: &Resources) -> &mut Self {
|
||||
self.add_system_node_named("camera", CameraNode::default(), resources);
|
||||
self.add_system_node_named(
|
||||
"local_to_world",
|
||||
UniformNode::<LocalToWorld>::new(true),
|
||||
resources,
|
||||
);
|
||||
self.add_system_node_named(
|
||||
"standard_material",
|
||||
AssetUniformNode::<StandardMaterial>::new(true),
|
||||
resources,
|
||||
);
|
||||
self.add_system_node_named("lights", LightsNode::new(10), resources);
|
||||
self.add_node_named(
|
||||
"swapchain",
|
||||
WindowSwapChainNode::new(
|
||||
WindowReference::Primary,
|
||||
resources.get_event_reader::<WindowCreated>(),
|
||||
resources.get_event_reader::<WindowResized>(),
|
||||
),
|
||||
);
|
||||
self.add_node_named(
|
||||
"main_pass_depth_texture",
|
||||
WindowTextureNode::new(
|
||||
WindowReference::Primary,
|
||||
TextureDescriptor {
|
||||
size: Extent3d {
|
||||
depth: 1,
|
||||
width: 1,
|
||||
height: 1,
|
||||
},
|
||||
array_layer_count: 1,
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: TextureDimension::D2,
|
||||
format: TextureFormat::Depth32Float, // PERF: vulkan docs recommend using 24 bit depth for better performance
|
||||
usage: TextureUsage::OUTPUT_ATTACHMENT,
|
||||
},
|
||||
resources.get_event_reader::<WindowCreated>(),
|
||||
resources.get_event_reader::<WindowResized>(),
|
||||
),
|
||||
);
|
||||
let mut shaders = resources.get_mut::<AssetStorage<Shader>>().unwrap();
|
||||
let mut pipelines = resources
|
||||
.get_mut::<AssetStorage<PipelineDescriptor>>()
|
||||
.unwrap();
|
||||
let mut main_pass = PassNode::new(build_main_pass());
|
||||
main_pass.add_pipeline(
|
||||
pipelines.add_default(build_forward_pipeline(&mut shaders)),
|
||||
vec![Box::new(AssignedMeshesDrawTarget)],
|
||||
);
|
||||
self.add_node_named("main_pass", main_pass);
|
||||
|
||||
// TODO: replace these with "autowire" groups
|
||||
self.add_node_edge("camera", "main_pass").unwrap();
|
||||
self.add_node_edge("standard_material", "main_pass")
|
||||
.unwrap();
|
||||
self.add_node_edge("local_to_world", "main_pass").unwrap();
|
||||
self.add_node_edge("lights", "main_pass").unwrap();
|
||||
self.add_slot_edge(
|
||||
"swapchain",
|
||||
WindowSwapChainNode::OUT_TEXTURE,
|
||||
"main_pass",
|
||||
"color",
|
||||
)
|
||||
.unwrap();
|
||||
self.add_slot_edge(
|
||||
"main_pass_depth_texture",
|
||||
WindowTextureNode::OUT_TEXTURE,
|
||||
"main_pass",
|
||||
"depth",
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
self
|
||||
}
|
||||
}
|
36
bevy_pbr/src/lib.rs
Normal file
36
bevy_pbr/src/lib.rs
Normal file
|
@ -0,0 +1,36 @@
|
|||
pub mod entity;
|
||||
pub mod light;
|
||||
pub mod material;
|
||||
pub mod nodes;
|
||||
pub mod passes;
|
||||
pub mod pipelines;
|
||||
|
||||
mod forward_pbr_render_graph;
|
||||
pub use forward_pbr_render_graph::*;
|
||||
|
||||
use bevy_app::{AppBuilder, AppPlugin, stage};
|
||||
use bevy_asset::AssetStorage;
|
||||
use material::StandardMaterial;
|
||||
use bevy_render::{render_graph::RenderGraph, shader};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct PbrPlugin;
|
||||
|
||||
// NOTE: this isn't PBR yet. consider this name "aspirational" :)
|
||||
impl AppPlugin for PbrPlugin {
|
||||
fn build(&self, app: &mut AppBuilder) {
|
||||
// asset_batchers.batch_types2::<Mesh, StandardMaterial>();
|
||||
app.add_resource(AssetStorage::<StandardMaterial>::new())
|
||||
.add_system_to_stage(
|
||||
stage::POST_UPDATE,
|
||||
shader::asset_handle_shader_def_system::<StandardMaterial>(),
|
||||
)
|
||||
.add_system_to_stage(
|
||||
stage::POST_UPDATE,
|
||||
shader::asset_handle_batcher_system::<StandardMaterial>(),
|
||||
);
|
||||
let resources = app.resources();
|
||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||
render_graph.add_pbr_graph(resources);
|
||||
}
|
||||
}
|
|
@ -1,8 +1,8 @@
|
|||
use super::{Color, PerspectiveCamera};
|
||||
use bevy_transform::components::Translation;
|
||||
use glam::Mat4;
|
||||
use std::ops::Range;
|
||||
use zerocopy::{AsBytes, FromBytes};
|
||||
use bevy_render::{PerspectiveCamera, Color};
|
||||
|
||||
pub struct Light {
|
||||
pub color: Color,
|
|
@ -1,12 +1,10 @@
|
|||
use crate::{texture::Texture, Color};
|
||||
use bevy_render::{texture::Texture, Color};
|
||||
use bevy_asset::Handle;
|
||||
use bevy_derive::Uniforms;
|
||||
|
||||
use bevy_asset;
|
||||
use bevy_core;
|
||||
|
||||
#[derive(Uniforms)]
|
||||
#[module(meta = false, bevy_render = "crate")]
|
||||
#[module(meta = false)]
|
||||
pub struct StandardMaterial {
|
||||
#[uniform(instance)]
|
||||
pub albedo: Color,
|
|
@ -1,13 +1,13 @@
|
|||
use crate::{
|
||||
render_graph_2::{CommandQueue, Node, ResourceSlots, SystemNode},
|
||||
use bevy_render::{
|
||||
render_graph::{CommandQueue, Node, ResourceSlots, SystemNode},
|
||||
render_resource::{resource_name, BufferInfo, BufferUsage, RenderResourceAssignments},
|
||||
renderer_2::{GlobalRenderResourceContext, RenderContext},
|
||||
Light, LightRaw,
|
||||
renderer::{GlobalRenderResourceContext, RenderContext},
|
||||
};
|
||||
|
||||
use bevy_transform::prelude::*;
|
||||
use legion::prelude::*;
|
||||
use zerocopy::AsBytes;
|
||||
use crate::light::{LightRaw, Light};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct LightsNode {
|
||||
|
@ -44,7 +44,7 @@ pub struct LightCount {
|
|||
}
|
||||
|
||||
impl SystemNode for LightsNode {
|
||||
fn get_system(&self, resources: &mut Resources) -> Box<dyn Schedulable> {
|
||||
fn get_system(&self, _resources: &Resources) -> Box<dyn Schedulable> {
|
||||
let mut light_buffer = None;
|
||||
let mut lights_are_dirty = true;
|
||||
// TODO: merge these
|
3
bevy_pbr/src/nodes/mod.rs
Normal file
3
bevy_pbr/src/nodes/mod.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
mod lights_node;
|
||||
|
||||
pub use lights_node::*;
|
28
bevy_pbr/src/passes/main.rs
Normal file
28
bevy_pbr/src/passes/main.rs
Normal file
|
@ -0,0 +1,28 @@
|
|||
use bevy_render::pass::{
|
||||
LoadOp, PassDescriptor, RenderPassColorAttachmentDescriptor,
|
||||
RenderPassDepthStencilAttachmentDescriptor, StoreOp, TextureAttachment,
|
||||
};
|
||||
|
||||
use bevy_render::Color;
|
||||
|
||||
pub fn build_main_pass() -> PassDescriptor {
|
||||
PassDescriptor {
|
||||
color_attachments: vec![RenderPassColorAttachmentDescriptor {
|
||||
attachment: TextureAttachment::Input("color".to_string()),
|
||||
resolve_target: None,
|
||||
load_op: LoadOp::Clear,
|
||||
store_op: StoreOp::Store,
|
||||
clear_color: Color::rgb(0.1, 0.1, 0.1),
|
||||
}],
|
||||
depth_stencil_attachment: Some(RenderPassDepthStencilAttachmentDescriptor {
|
||||
attachment: TextureAttachment::Input("depth".to_string()),
|
||||
depth_load_op: LoadOp::Clear,
|
||||
depth_store_op: StoreOp::Store,
|
||||
stencil_load_op: LoadOp::Clear,
|
||||
stencil_store_op: StoreOp::Store,
|
||||
clear_depth: 1.0,
|
||||
clear_stencil: 0,
|
||||
}),
|
||||
sample_count: 1,
|
||||
}
|
||||
}
|
3
bevy_pbr/src/passes/mod.rs
Normal file
3
bevy_pbr/src/passes/mod.rs
Normal file
|
@ -0,0 +1,3 @@
|
|||
mod main;
|
||||
|
||||
pub use main::*;
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{
|
||||
use bevy_render::{
|
||||
pipeline::{
|
||||
state_descriptors::{
|
||||
BlendDescriptor, BlendFactor, BlendOperation, ColorStateDescriptor, ColorWrite,
|
||||
|
@ -46,7 +46,7 @@ pub fn build_forward_pipeline(shaders: &mut AssetStorage<Shader>) -> PipelineDes
|
|||
write_mask: ColorWrite::ALL,
|
||||
}
|
||||
],
|
||||
..PipelineDescriptor::new_new(ShaderStages {
|
||||
..PipelineDescriptor::new(ShaderStages {
|
||||
vertex: shaders.add(Shader::from_glsl(
|
||||
ShaderStage::Vertex,
|
||||
include_str!("forward.vert"),
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{pass::RenderPass, pipeline::PipelineDescriptor, renderer_2::RenderContext};
|
||||
use crate::{pass::RenderPass, pipeline::PipelineDescriptor, renderer::RenderContext};
|
||||
use bevy_asset::Handle;
|
||||
use legion::prelude::{Resources, World};
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ use crate::{
|
|||
pass::RenderPass,
|
||||
pipeline::PipelineDescriptor,
|
||||
render_resource::{resource_name, AssetBatchers, RenderResourceAssignments},
|
||||
renderer_2::RenderContext,
|
||||
renderer::RenderContext,
|
||||
Renderable,
|
||||
};
|
||||
use bevy_asset::Handle;
|
||||
|
|
|
@ -9,7 +9,7 @@ use crate::{
|
|||
render_resource::{
|
||||
resource_name, EntityRenderResourceAssignments, RenderResourceAssignments, ResourceInfo,
|
||||
},
|
||||
renderer_2::RenderContext,
|
||||
renderer::RenderContext,
|
||||
Renderable,
|
||||
};
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ use crate::{
|
|||
resource_name, BufferInfo, BufferUsage, RenderResource, RenderResourceAssignments,
|
||||
ResourceInfo,
|
||||
},
|
||||
renderer_2::RenderContext,
|
||||
renderer::RenderContext,
|
||||
};
|
||||
use bevy_asset::Handle;
|
||||
use legion::prelude::*;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
mod draw_target;
|
||||
pub mod draw_targets;
|
||||
mod draw_targets;
|
||||
|
||||
pub use draw_target::*;
|
||||
pub use draw_targets::*;
|
||||
|
|
|
@ -1,25 +1,11 @@
|
|||
use crate::{
|
||||
mesh::Mesh, shader::uniforms::StandardMaterial, ActiveCamera, ActiveCamera2d, Camera,
|
||||
CameraType, Light, Renderable,
|
||||
mesh::Mesh, ActiveCamera, ActiveCamera2d, Camera,
|
||||
CameraType, Renderable,
|
||||
};
|
||||
use bevy_asset::Handle;
|
||||
use bevy_derive::EntityArchetype;
|
||||
use bevy_transform::components::{LocalToWorld, Rotation, Scale, Translation};
|
||||
|
||||
#[derive(EntityArchetype, Default)]
|
||||
#[module(meta = false)]
|
||||
pub struct MeshEntity {
|
||||
// #[tag]
|
||||
pub mesh: Handle<Mesh>,
|
||||
// #[tag]
|
||||
pub material: Handle<StandardMaterial>,
|
||||
pub renderable: Renderable,
|
||||
pub local_to_world: LocalToWorld,
|
||||
pub translation: Translation,
|
||||
pub rotation: Rotation,
|
||||
pub scale: Scale,
|
||||
}
|
||||
|
||||
#[derive(EntityArchetype, Default)]
|
||||
#[module(meta = false)]
|
||||
pub struct MeshMaterialEntity<T: Default + Send + Sync + 'static> {
|
||||
|
@ -32,15 +18,6 @@ pub struct MeshMaterialEntity<T: Default + Send + Sync + 'static> {
|
|||
pub scale: Scale,
|
||||
}
|
||||
|
||||
#[derive(EntityArchetype, Default)]
|
||||
#[module(meta = false)]
|
||||
pub struct LightEntity {
|
||||
pub light: Light,
|
||||
pub local_to_world: LocalToWorld,
|
||||
pub translation: Translation,
|
||||
pub rotation: Rotation,
|
||||
}
|
||||
|
||||
#[derive(EntityArchetype, Default)]
|
||||
#[module(meta = false)]
|
||||
pub struct CameraEntity {
|
||||
|
|
|
@ -3,17 +3,14 @@ mod camera;
|
|||
pub mod entity;
|
||||
pub mod mesh;
|
||||
pub mod render_graph;
|
||||
pub mod render_graph_2;
|
||||
pub mod renderer_2;
|
||||
pub mod renderer;
|
||||
pub mod shader;
|
||||
pub mod vertex;
|
||||
|
||||
mod color;
|
||||
mod light;
|
||||
|
||||
pub use camera::*;
|
||||
pub use color::*;
|
||||
pub use light::*;
|
||||
pub use renderable::*;
|
||||
|
||||
pub use vertex::Vertex;
|
||||
|
@ -28,39 +25,22 @@ pub mod texture;
|
|||
pub use once_cell;
|
||||
|
||||
use self::{
|
||||
draw_target::draw_targets::AssignedMeshesDrawTarget,
|
||||
mesh::Mesh,
|
||||
pass::{
|
||||
LoadOp, RenderPassColorAttachmentDescriptor, RenderPassDepthStencilAttachmentDescriptor,
|
||||
StoreOp, TextureAttachment,
|
||||
},
|
||||
pipeline::{
|
||||
PipelineAssignments, PipelineCompiler, PipelineDescriptor, VertexBufferDescriptors,
|
||||
},
|
||||
render_graph::RenderGraph,
|
||||
render_resource::{
|
||||
entity_render_resource_assignments_system, resource_providers::UniformResourceProvider,
|
||||
AssetBatchers, EntityRenderResourceAssignments, RenderResourceAssignments,
|
||||
entity_render_resource_assignments_system, AssetBatchers, EntityRenderResourceAssignments,
|
||||
RenderResourceAssignments,
|
||||
},
|
||||
shader::{uniforms::StandardMaterial, Shader},
|
||||
shader::Shader,
|
||||
texture::Texture,
|
||||
};
|
||||
|
||||
use bevy_app::{stage, AppBuilder, AppPlugin, GetEventReader};
|
||||
use bevy_app::{stage, AppBuilder, AppPlugin};
|
||||
use bevy_asset::AssetStorage;
|
||||
use bevy_transform::prelude::LocalToWorld;
|
||||
use bevy_window::{WindowCreated, WindowReference, WindowResized};
|
||||
use pass::PassDescriptor;
|
||||
use pipeline::pipelines::build_forward_pipeline;
|
||||
use render_graph_2::{
|
||||
nodes::{
|
||||
Camera2dNode, CameraNode, LightsNode, PassNode, UniformNode, WindowSwapChainNode,
|
||||
WindowTextureNode,
|
||||
},
|
||||
RenderGraph2,
|
||||
};
|
||||
use render_resource::resource_providers::mesh_resource_provider_system;
|
||||
use texture::{Extent3d, TextureDescriptor, TextureDimension, TextureFormat, TextureUsage};
|
||||
use mesh::mesh_resource_provider_system;
|
||||
use render_graph::RenderGraph;
|
||||
|
||||
pub static RENDER_RESOURCE_STAGE: &str = "render_resource";
|
||||
pub static RENDER_STAGE: &str = "render";
|
||||
|
@ -69,24 +49,10 @@ pub static RENDER_STAGE: &str = "render";
|
|||
pub struct RenderPlugin;
|
||||
|
||||
impl RenderPlugin {
|
||||
pub fn setup_render_graph_defaults(app: &mut AppBuilder) {
|
||||
let resources = app.resources();
|
||||
let mut pipelines = app
|
||||
.resources()
|
||||
.get_mut::<AssetStorage<PipelineDescriptor>>()
|
||||
.unwrap();
|
||||
let mut shaders = resources.get_mut::<AssetStorage<Shader>>().unwrap();
|
||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||
render_graph
|
||||
.build(&mut pipelines, &mut shaders)
|
||||
.add_resource_provider(UniformResourceProvider::<LocalToWorld>::new(true));
|
||||
}
|
||||
}
|
||||
|
||||
impl AppPlugin for RenderPlugin {
|
||||
fn build(&self, app: &mut AppBuilder) {
|
||||
let mut asset_batchers = AssetBatchers::default();
|
||||
asset_batchers.batch_types2::<Mesh, StandardMaterial>();
|
||||
app.add_stage_after(stage::POST_UPDATE, RENDER_RESOURCE_STAGE)
|
||||
.add_stage_after(RENDER_RESOURCE_STAGE, RENDER_STAGE)
|
||||
// resources
|
||||
|
@ -94,125 +60,19 @@ impl AppPlugin for RenderPlugin {
|
|||
.add_resource(AssetStorage::<Mesh>::new())
|
||||
.add_resource(AssetStorage::<Texture>::new())
|
||||
.add_resource(AssetStorage::<Shader>::new())
|
||||
.add_resource(AssetStorage::<StandardMaterial>::new())
|
||||
.add_resource(AssetStorage::<PipelineDescriptor>::new())
|
||||
.add_resource(PipelineAssignments::new())
|
||||
.add_resource(PipelineCompiler::new())
|
||||
.add_resource(RenderResourceAssignments::default())
|
||||
.add_resource(VertexBufferDescriptors::default())
|
||||
.add_resource(EntityRenderResourceAssignments::default())
|
||||
.add_resource(asset_batchers)
|
||||
.add_resource(AssetBatchers::default())
|
||||
// core systems
|
||||
.add_system(entity_render_resource_assignments_system())
|
||||
.add_system_to_stage_init(stage::POST_UPDATE, camera::camera_update_system)
|
||||
.add_system_to_stage(stage::POST_UPDATE, mesh::mesh_specializer_system())
|
||||
.add_system_to_stage(stage::POST_UPDATE, mesh::mesh_batcher_system())
|
||||
.add_system_to_stage(
|
||||
stage::POST_UPDATE,
|
||||
shader::asset_handle_shader_def_system::<StandardMaterial>(),
|
||||
)
|
||||
.add_system_to_stage(
|
||||
stage::POST_UPDATE,
|
||||
shader::asset_handle_batcher_system::<StandardMaterial>(),
|
||||
)
|
||||
// render resource provider systems
|
||||
.add_system_to_stage_init(RENDER_RESOURCE_STAGE, mesh_resource_provider_system);
|
||||
RenderPlugin::setup_render_graph_defaults(app);
|
||||
let mut render_graph = RenderGraph2::default();
|
||||
// begin render graph 2
|
||||
{
|
||||
let resources = app.resources_mut();
|
||||
render_graph.add_system_node_named("camera", CameraNode::default(), resources);
|
||||
render_graph.add_system_node_named("camera2d", Camera2dNode::default(), resources);
|
||||
render_graph.add_system_node_named(
|
||||
"standard_material",
|
||||
UniformNode::<StandardMaterial>::new(true),
|
||||
resources,
|
||||
);
|
||||
render_graph.add_system_node_named("lights", LightsNode::new(10), resources);
|
||||
render_graph.add_node_named(
|
||||
"swapchain",
|
||||
WindowSwapChainNode::new(
|
||||
WindowReference::Primary,
|
||||
resources.get_event_reader::<WindowCreated>(),
|
||||
resources.get_event_reader::<WindowResized>(),
|
||||
),
|
||||
);
|
||||
render_graph.add_node_named(
|
||||
"main_pass_depth_texture",
|
||||
WindowTextureNode::new(
|
||||
WindowReference::Primary,
|
||||
TextureDescriptor {
|
||||
size: Extent3d {
|
||||
depth: 1,
|
||||
width: 1,
|
||||
height: 1,
|
||||
},
|
||||
array_layer_count: 1,
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: TextureDimension::D2,
|
||||
format: TextureFormat::Depth32Float, // PERF: vulkan recommends using 24 bit depth for better performance
|
||||
usage: TextureUsage::OUTPUT_ATTACHMENT,
|
||||
},
|
||||
resources.get_event_reader::<WindowCreated>(),
|
||||
resources.get_event_reader::<WindowResized>(),
|
||||
),
|
||||
);
|
||||
let mut shaders = resources.get_mut::<AssetStorage<Shader>>().unwrap();
|
||||
let mut pipelines = resources
|
||||
.get_mut::<AssetStorage<PipelineDescriptor>>()
|
||||
.unwrap();
|
||||
let mut main_pass = PassNode::new(PassDescriptor {
|
||||
color_attachments: vec![RenderPassColorAttachmentDescriptor {
|
||||
attachment: TextureAttachment::Input("color".to_string()),
|
||||
resolve_target: None,
|
||||
load_op: LoadOp::Clear,
|
||||
store_op: StoreOp::Store,
|
||||
clear_color: Color::rgb(0.1, 0.1, 0.1),
|
||||
}],
|
||||
depth_stencil_attachment: Some(RenderPassDepthStencilAttachmentDescriptor {
|
||||
attachment: TextureAttachment::Input("depth".to_string()),
|
||||
depth_load_op: LoadOp::Clear,
|
||||
depth_store_op: StoreOp::Store,
|
||||
stencil_load_op: LoadOp::Clear,
|
||||
stencil_store_op: StoreOp::Store,
|
||||
clear_depth: 1.0,
|
||||
clear_stencil: 0,
|
||||
}),
|
||||
sample_count: 1,
|
||||
});
|
||||
main_pass.add_pipeline(
|
||||
pipelines.add_default(build_forward_pipeline(&mut shaders)),
|
||||
vec![Box::new(AssignedMeshesDrawTarget)],
|
||||
);
|
||||
render_graph.add_node_named("main_pass", main_pass);
|
||||
|
||||
// TODO: replace these with "autowire" groups
|
||||
render_graph.add_node_edge("camera", "main_pass").unwrap();
|
||||
render_graph.add_node_edge("camera2d", "main_pass").unwrap();
|
||||
render_graph
|
||||
.add_node_edge("standard_material", "main_pass")
|
||||
.unwrap();
|
||||
render_graph.add_node_edge("lights", "main_pass").unwrap();
|
||||
render_graph
|
||||
.add_slot_edge(
|
||||
"swapchain",
|
||||
WindowSwapChainNode::OUT_TEXTURE,
|
||||
"main_pass",
|
||||
"color",
|
||||
)
|
||||
.unwrap();
|
||||
render_graph
|
||||
.add_slot_edge(
|
||||
"main_pass_depth_texture",
|
||||
WindowTextureNode::OUT_TEXTURE,
|
||||
"main_pass",
|
||||
"depth",
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
app.add_resource(render_graph);
|
||||
// end render graph 2
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
use crate::{
|
||||
pipeline::{
|
||||
state_descriptors::{IndexFormat, PrimitiveTopology},
|
||||
VertexBufferDescriptor, VertexFormat,
|
||||
VertexBufferDescriptor, VertexFormat, VertexBufferDescriptors,
|
||||
},
|
||||
render_resource::AssetBatchers,
|
||||
Renderable,
|
||||
render_resource::{RenderResourceAssignments, AssetBatchers, BufferInfo, BufferUsage},
|
||||
Renderable, renderer::{GlobalRenderResourceContext, RenderResourceContext}, Vertex,
|
||||
shader::AsUniforms,
|
||||
};
|
||||
use bevy_asset::{AssetStorage, Handle};
|
||||
use glam::*;
|
||||
|
@ -335,6 +336,93 @@ pub fn mesh_specializer_system() -> Box<dyn Schedulable> {
|
|||
})
|
||||
}
|
||||
|
||||
fn setup_mesh_resource(
|
||||
render_resources: &dyn RenderResourceContext,
|
||||
render_resource_assignments: &mut RenderResourceAssignments,
|
||||
vertex_buffer_descriptor: &VertexBufferDescriptor,
|
||||
handle: Handle<Mesh>,
|
||||
meshes: &AssetStorage<Mesh>,
|
||||
) {
|
||||
log::trace!("setup mesh for {:?}", render_resource_assignments.id);
|
||||
let index_format = IndexFormat::Uint16;
|
||||
let (vertex_buffer, index_buffer) = if let Some(vertex_buffer) =
|
||||
render_resources.get_asset_resource(handle, VERTEX_BUFFER_ASSET_INDEX)
|
||||
{
|
||||
(
|
||||
vertex_buffer,
|
||||
render_resources.get_asset_resource(handle, INDEX_BUFFER_ASSET_INDEX),
|
||||
)
|
||||
} else {
|
||||
let mesh_asset = meshes.get(&handle).unwrap();
|
||||
let vertex_bytes = mesh_asset
|
||||
.get_vertex_buffer_bytes(&vertex_buffer_descriptor)
|
||||
.unwrap();
|
||||
// TODO: use a staging buffer here
|
||||
let vertex_buffer = render_resources.create_buffer_with_data(
|
||||
BufferInfo {
|
||||
buffer_usage: BufferUsage::VERTEX,
|
||||
..Default::default()
|
||||
},
|
||||
&vertex_bytes,
|
||||
);
|
||||
let index_bytes = mesh_asset.get_index_buffer_bytes(index_format).unwrap();
|
||||
let index_buffer = render_resources.create_buffer_with_data(
|
||||
BufferInfo {
|
||||
buffer_usage: BufferUsage::INDEX,
|
||||
..Default::default()
|
||||
},
|
||||
&index_bytes,
|
||||
);
|
||||
|
||||
render_resources.set_asset_resource(handle, vertex_buffer, VERTEX_BUFFER_ASSET_INDEX);
|
||||
render_resources.set_asset_resource(handle, index_buffer, INDEX_BUFFER_ASSET_INDEX);
|
||||
(vertex_buffer, Some(index_buffer))
|
||||
};
|
||||
|
||||
render_resource_assignments.set_vertex_buffer("Vertex", vertex_buffer, index_buffer);
|
||||
}
|
||||
|
||||
pub fn mesh_resource_provider_system(resources: &mut Resources) -> Box<dyn Schedulable> {
|
||||
let mut vertex_buffer_descriptors = resources.get_mut::<VertexBufferDescriptors>().unwrap();
|
||||
// TODO: allow pipelines to specialize on vertex_buffer_descriptor and index_format
|
||||
let vertex_buffer_descriptor = Vertex::get_vertex_buffer_descriptor().unwrap();
|
||||
vertex_buffer_descriptors.set(vertex_buffer_descriptor.clone());
|
||||
SystemBuilder::new("mesh_resource_provider")
|
||||
.read_resource::<GlobalRenderResourceContext>()
|
||||
.read_resource::<AssetStorage<Mesh>>()
|
||||
.write_resource::<AssetBatchers>()
|
||||
.with_query(<(Read<Handle<Mesh>>, Write<Renderable>)>::query())
|
||||
.build(
|
||||
move |_, world, (render_resource_context, meshes, asset_batchers), query| {
|
||||
let render_resources = &*render_resource_context.context;
|
||||
if let Some(batches) = asset_batchers.get_handle_batches_mut::<Mesh>() {
|
||||
for batch in batches {
|
||||
let handle = batch.get_handle::<Mesh>().unwrap();
|
||||
setup_mesh_resource(
|
||||
render_resources,
|
||||
&mut batch.render_resource_assignments,
|
||||
&vertex_buffer_descriptor,
|
||||
handle,
|
||||
&meshes,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: remove this once batches are pipeline specific and deprecate assigned_meshes draw target
|
||||
for (handle, mut renderable) in query.iter_mut(world) {
|
||||
setup_mesh_resource(
|
||||
render_resources,
|
||||
&mut renderable.render_resource_assignments,
|
||||
&vertex_buffer_descriptor,
|
||||
*handle,
|
||||
&meshes,
|
||||
);
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::{Vertex, pipeline::state_descriptors::PrimitiveTopology, shader::AsUniforms};
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
mod ops;
|
||||
mod pass;
|
||||
pub mod passes;
|
||||
mod render_pass;
|
||||
|
||||
pub use ops::*;
|
||||
|
|
|
@ -1,57 +0,0 @@
|
|||
use crate::{
|
||||
pass::{
|
||||
LoadOp, PassDescriptor, RenderPassColorAttachmentDescriptor,
|
||||
RenderPassDepthStencilAttachmentDescriptor, StoreOp, TextureAttachment
|
||||
},
|
||||
render_graph::RenderGraphBuilder,
|
||||
render_resource::{resource_name, resource_providers::FrameTextureResourceProvider},
|
||||
texture::{Extent3d, TextureDescriptor, TextureDimension, TextureFormat, TextureUsage},
|
||||
Color,
|
||||
};
|
||||
|
||||
pub trait ForwardPassBuilder {
|
||||
fn add_forward_pass(&mut self) -> &mut Self;
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'c> ForwardPassBuilder for RenderGraphBuilder<'a, 'b, 'c> {
|
||||
fn add_forward_pass(&mut self) -> &mut Self {
|
||||
self.add_resource_provider(FrameTextureResourceProvider::new(
|
||||
resource_name::texture::DEPTH,
|
||||
TextureDescriptor {
|
||||
size: Extent3d {
|
||||
depth: 1,
|
||||
width: 1,
|
||||
height: 1,
|
||||
},
|
||||
array_layer_count: 1,
|
||||
mip_level_count: 1,
|
||||
sample_count: 1,
|
||||
dimension: TextureDimension::D2,
|
||||
format: TextureFormat::Depth32Float, // PERF: vulkan recommends using 24 bit depth for better performance
|
||||
usage: TextureUsage::OUTPUT_ATTACHMENT,
|
||||
},
|
||||
))
|
||||
.add_pass(
|
||||
resource_name::pass::MAIN,
|
||||
PassDescriptor {
|
||||
color_attachments: vec![RenderPassColorAttachmentDescriptor {
|
||||
attachment: TextureAttachment::Name(resource_name::texture::SWAP_CHAIN.to_string()),
|
||||
resolve_target: None,
|
||||
load_op: LoadOp::Clear,
|
||||
store_op: StoreOp::Store,
|
||||
clear_color: Color::rgb(0.1, 0.1, 0.1),
|
||||
}],
|
||||
depth_stencil_attachment: Some(RenderPassDepthStencilAttachmentDescriptor {
|
||||
attachment: TextureAttachment::Name(resource_name::texture::DEPTH.to_string()),
|
||||
depth_load_op: LoadOp::Clear,
|
||||
depth_store_op: StoreOp::Store,
|
||||
stencil_load_op: LoadOp::Clear,
|
||||
stencil_store_op: StoreOp::Store,
|
||||
clear_depth: 1.0,
|
||||
clear_stencil: 0,
|
||||
}),
|
||||
sample_count: 1,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
pipeline::PipelineDescriptor,
|
||||
render_resource::{RenderResource, RenderResourceAssignments},
|
||||
renderer_2::RenderContext,
|
||||
renderer::RenderContext,
|
||||
};
|
||||
use bevy_asset::Handle;
|
||||
use std::ops::Range;
|
||||
|
|
|
@ -3,7 +3,6 @@ mod binding;
|
|||
mod pipeline;
|
||||
mod pipeline_compiler;
|
||||
mod pipeline_layout;
|
||||
pub mod pipelines;
|
||||
pub mod state_descriptors;
|
||||
mod vertex_buffer_descriptor;
|
||||
mod vertex_format;
|
||||
|
|
|
@ -1,18 +1,12 @@
|
|||
use super::{
|
||||
state_descriptors::{
|
||||
BlendDescriptor, ColorStateDescriptor, ColorWrite, CompareFunction, CullMode,
|
||||
DepthStencilStateDescriptor, FrontFace, IndexFormat, PrimitiveTopology,
|
||||
RasterizationStateDescriptor, StencilStateFaceDescriptor,
|
||||
BlendDescriptor, BlendFactor, BlendOperation, ColorStateDescriptor, ColorWrite,
|
||||
CompareFunction, CullMode, DepthStencilStateDescriptor, FrontFace, IndexFormat,
|
||||
PrimitiveTopology, RasterizationStateDescriptor, StencilStateFaceDescriptor,
|
||||
},
|
||||
BindGroupDescriptor, PipelineLayout, VertexBufferDescriptor,
|
||||
PipelineLayout,
|
||||
};
|
||||
use crate::{
|
||||
render_resource::resource_name,
|
||||
shader::{Shader, ShaderStages},
|
||||
texture::TextureFormat,
|
||||
};
|
||||
|
||||
use bevy_asset::{AssetStorage, Handle};
|
||||
use crate::{shader::ShaderStages, texture::TextureFormat};
|
||||
|
||||
// TODO: consider removing this in favor of Option<Layout>
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -30,7 +24,6 @@ pub enum DescriptorType<T> {
|
|||
#[derive(Clone, Debug)]
|
||||
pub struct PipelineDescriptor {
|
||||
pub name: Option<String>,
|
||||
pub draw_targets: Vec<String>,
|
||||
pub layout: PipelineLayoutType,
|
||||
pub shader_stages: ShaderStages,
|
||||
pub rasterization_state: Option<RasterizationStateDescriptor>,
|
||||
|
@ -62,13 +55,12 @@ pub struct PipelineDescriptor {
|
|||
}
|
||||
|
||||
impl PipelineDescriptor {
|
||||
pub fn new_new(shader_stages: ShaderStages) -> Self {
|
||||
pub fn new(shader_stages: ShaderStages) -> Self {
|
||||
PipelineDescriptor {
|
||||
name: None,
|
||||
layout: PipelineLayoutType::Reflected(None),
|
||||
color_states: Vec::new(),
|
||||
depth_stencil_state: None,
|
||||
draw_targets: Vec::new(),
|
||||
shader_stages,
|
||||
rasterization_state: None,
|
||||
primitive_topology: PrimitiveTopology::TriangleList,
|
||||
|
@ -79,14 +71,15 @@ impl PipelineDescriptor {
|
|||
}
|
||||
}
|
||||
|
||||
fn new(name: Option<&str>, vertex_shader: Handle<Shader>) -> Self {
|
||||
pub fn default_config(shader_stages: ShaderStages) -> Self {
|
||||
PipelineDescriptor {
|
||||
name: name.map(|name| name.to_string()),
|
||||
name: None,
|
||||
primitive_topology: PrimitiveTopology::TriangleList,
|
||||
layout: PipelineLayoutType::Reflected(None),
|
||||
color_states: Vec::new(),
|
||||
depth_stencil_state: None,
|
||||
draw_targets: Vec::new(),
|
||||
shader_stages: ShaderStages::new(vertex_shader),
|
||||
index_format: IndexFormat::Uint16,
|
||||
sample_count: 1,
|
||||
sample_mask: !0,
|
||||
alpha_to_coverage_enabled: false,
|
||||
rasterization_state: Some(RasterizationStateDescriptor {
|
||||
front_face: FrontFace::Ccw,
|
||||
cull_mode: CullMode::Back,
|
||||
|
@ -94,11 +87,30 @@ impl PipelineDescriptor {
|
|||
depth_bias_slope_scale: 0.0,
|
||||
depth_bias_clamp: 0.0,
|
||||
}),
|
||||
primitive_topology: PrimitiveTopology::TriangleList,
|
||||
index_format: IndexFormat::Uint16,
|
||||
sample_count: 1,
|
||||
sample_mask: !0,
|
||||
alpha_to_coverage_enabled: false,
|
||||
depth_stencil_state: Some(DepthStencilStateDescriptor {
|
||||
format: TextureFormat::Depth32Float,
|
||||
depth_write_enabled: true,
|
||||
depth_compare: CompareFunction::Less,
|
||||
stencil_front: StencilStateFaceDescriptor::IGNORE,
|
||||
stencil_back: StencilStateFaceDescriptor::IGNORE,
|
||||
stencil_read_mask: 0,
|
||||
stencil_write_mask: 0,
|
||||
}),
|
||||
color_states: vec![ColorStateDescriptor {
|
||||
format: TextureFormat::Bgra8UnormSrgb,
|
||||
color_blend: BlendDescriptor {
|
||||
src_factor: BlendFactor::SrcAlpha,
|
||||
dst_factor: BlendFactor::OneMinusSrcAlpha,
|
||||
operation: BlendOperation::Add,
|
||||
},
|
||||
alpha_blend: BlendDescriptor {
|
||||
src_factor: BlendFactor::One,
|
||||
dst_factor: BlendFactor::One,
|
||||
operation: BlendOperation::Add,
|
||||
},
|
||||
write_mask: ColorWrite::ALL,
|
||||
}],
|
||||
shader_stages,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,159 +128,3 @@ impl PipelineDescriptor {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PipelineDescriptor {
|
||||
pub fn build<'a>(
|
||||
name: &'a str,
|
||||
shader_storage: &'a mut AssetStorage<Shader>,
|
||||
) -> PipelineBuilder<'a> {
|
||||
PipelineBuilder::new(name, shader_storage)
|
||||
}
|
||||
}
|
||||
|
||||
pub struct PipelineBuilder<'a> {
|
||||
pipeline: Option<PipelineDescriptor>,
|
||||
shader_storage: &'a mut AssetStorage<Shader>,
|
||||
name: &'a str,
|
||||
}
|
||||
|
||||
impl<'a> PipelineBuilder<'a> {
|
||||
pub fn new(name: &'a str, shader_storage: &'a mut AssetStorage<Shader>) -> Self {
|
||||
PipelineBuilder {
|
||||
pipeline: None,
|
||||
shader_storage,
|
||||
name,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn finish(&mut self) -> PipelineDescriptor {
|
||||
self.pipeline.take().unwrap()
|
||||
}
|
||||
|
||||
pub fn with_vertex_shader(&mut self, vertex_shader: Shader) -> &mut Self {
|
||||
let vertex_shader_handle = self.shader_storage.add(vertex_shader);
|
||||
self.pipeline = Some(PipelineDescriptor::new(
|
||||
Some(&self.name),
|
||||
vertex_shader_handle,
|
||||
));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_fragment_shader(&mut self, fragment_shader: Shader) -> &mut Self {
|
||||
let fragment_shader_handle = self.shader_storage.add(fragment_shader);
|
||||
self.pipeline.as_mut().unwrap().shader_stages.fragment = Some(fragment_shader_handle);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_color_state(&mut self, color_state_descriptor: ColorStateDescriptor) -> &mut Self {
|
||||
self.pipeline
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.color_states
|
||||
.push(color_state_descriptor);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_depth_stencil_state(
|
||||
&mut self,
|
||||
depth_stencil_state: DepthStencilStateDescriptor,
|
||||
) -> &mut Self {
|
||||
if let Some(_) = self.pipeline.as_ref().unwrap().depth_stencil_state {
|
||||
panic!("Depth stencil state has already been set");
|
||||
}
|
||||
self.pipeline.as_mut().unwrap().depth_stencil_state = Some(depth_stencil_state);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_bind_group(&mut self, bind_group: BindGroupDescriptor) -> &mut Self {
|
||||
let pipeline = self.pipeline.as_mut().unwrap();
|
||||
if let PipelineLayoutType::Reflected(_) = pipeline.layout {
|
||||
pipeline.layout = PipelineLayoutType::Manual(PipelineLayout::default());
|
||||
}
|
||||
|
||||
if let PipelineLayoutType::Manual(ref mut layout) = pipeline.layout {
|
||||
layout.bind_groups.push(bind_group);
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_vertex_buffer_descriptor(
|
||||
&mut self,
|
||||
vertex_buffer_descriptor: VertexBufferDescriptor,
|
||||
) -> &mut Self {
|
||||
let pipeline = self.pipeline.as_mut().unwrap();
|
||||
if let PipelineLayoutType::Reflected(_) = pipeline.layout {
|
||||
pipeline.layout = PipelineLayoutType::Manual(PipelineLayout::default());
|
||||
}
|
||||
|
||||
if let PipelineLayoutType::Manual(ref mut layout) = pipeline.layout {
|
||||
layout
|
||||
.vertex_buffer_descriptors
|
||||
.push(vertex_buffer_descriptor);
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_index_format(&mut self, index_format: IndexFormat) -> &mut Self {
|
||||
self.pipeline.as_mut().unwrap().index_format = index_format;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_draw_target(&mut self, name: &str) -> &mut Self {
|
||||
self.pipeline
|
||||
.as_mut()
|
||||
.unwrap()
|
||||
.draw_targets
|
||||
.push(name.to_string());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_rasterization_state(
|
||||
&mut self,
|
||||
rasterization_state: RasterizationStateDescriptor,
|
||||
) -> &mut Self {
|
||||
self.pipeline.as_mut().unwrap().rasterization_state = Some(rasterization_state);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_primitive_topology(&mut self, primitive_topology: PrimitiveTopology) -> &mut Self {
|
||||
self.pipeline.as_mut().unwrap().primitive_topology = primitive_topology;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_sample_count(&mut self, sample_count: u32) -> &mut Self {
|
||||
self.pipeline.as_mut().unwrap().sample_count = sample_count;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_alpha_to_coverage_enabled(&mut self, alpha_to_coverage_enabled: bool) -> &mut Self {
|
||||
self.pipeline.as_mut().unwrap().alpha_to_coverage_enabled = alpha_to_coverage_enabled;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_sample_mask(&mut self, sample_mask: u32) -> &mut Self {
|
||||
self.pipeline.as_mut().unwrap().sample_mask = sample_mask;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_default_config(&mut self) -> &mut Self {
|
||||
self.with_depth_stencil_state(DepthStencilStateDescriptor {
|
||||
format: TextureFormat::Depth32Float,
|
||||
depth_write_enabled: true,
|
||||
depth_compare: CompareFunction::Less,
|
||||
stencil_front: StencilStateFaceDescriptor::IGNORE,
|
||||
stencil_back: StencilStateFaceDescriptor::IGNORE,
|
||||
stencil_read_mask: 0,
|
||||
stencil_write_mask: 0,
|
||||
})
|
||||
.add_color_state(ColorStateDescriptor {
|
||||
format: TextureFormat::Bgra8UnormSrgb,
|
||||
color_blend: BlendDescriptor::REPLACE,
|
||||
alpha_blend: BlendDescriptor::REPLACE,
|
||||
write_mask: ColorWrite::ALL,
|
||||
})
|
||||
.add_draw_target(resource_name::draw_target::ASSIGNED_MESHES)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::{
|
|||
render_resource::{
|
||||
BufferInfo, RenderResourceAssignments, RenderResourceAssignmentsId, ResourceInfo,
|
||||
},
|
||||
renderer_2::{RenderResourceContext, GlobalRenderResourceContext},
|
||||
renderer::{RenderResourceContext, GlobalRenderResourceContext},
|
||||
shader::{Shader, ShaderSource},
|
||||
Renderable,
|
||||
};
|
||||
|
|
|
@ -1,19 +0,0 @@
|
|||
#version 450
|
||||
|
||||
layout(location = 0) in vec3 v_Position;
|
||||
layout(location = 1) in vec3 v_Normal;
|
||||
layout(location = 2) in vec2 v_Uv;
|
||||
|
||||
layout(location = 0) out vec4 o_Target;
|
||||
|
||||
layout(set = 0, binding = 0) uniform Camera {
|
||||
mat4 ViewProj;
|
||||
};
|
||||
|
||||
layout(set = 1, binding = 1) uniform StandardMaterial_albedo {
|
||||
vec4 Albedo;
|
||||
};
|
||||
|
||||
void main() {
|
||||
o_Target = Albedo;
|
||||
}
|
|
@ -1,27 +0,0 @@
|
|||
#version 450
|
||||
|
||||
layout(location = 0) in vec3 Vertex_Position;
|
||||
layout(location = 1) in vec3 Vertex_Normal;
|
||||
layout(location = 2) in vec2 Vertex_Uv;
|
||||
|
||||
layout(location = 0) out vec3 v_Position;
|
||||
layout(location = 1) out vec3 v_Normal;
|
||||
layout(location = 2) out vec2 v_Uv;
|
||||
|
||||
layout(set = 0, binding = 0) uniform Camera {
|
||||
mat4 ViewProj;
|
||||
};
|
||||
|
||||
layout(set = 1, binding = 0) uniform Object {
|
||||
mat4 Model;
|
||||
};
|
||||
|
||||
layout(set = 1, binding = 1) uniform StandardMaterial_albedo {
|
||||
vec4 Albedo;
|
||||
};
|
||||
|
||||
void main() {
|
||||
v_Normal = mat3(Model) * Vertex_Normal;
|
||||
v_Position = (Model * vec4(Vertex_Position, 1.0)).xyz;
|
||||
gl_Position = ViewProj * v_Position;
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
use crate::{
|
||||
pipeline::state_descriptors::{
|
||||
BlendDescriptor, ColorStateDescriptor, ColorWrite, CompareFunction, CullMode,
|
||||
DepthStencilStateDescriptor, FrontFace, RasterizationStateDescriptor,
|
||||
StencilStateFaceDescriptor,
|
||||
},
|
||||
render_graph::RenderGraphBuilder,
|
||||
render_resource::resource_name,
|
||||
shader::{Shader, ShaderStage},
|
||||
texture::TextureFormat,
|
||||
};
|
||||
|
||||
pub trait ForwardFlatPipelineBuilder {
|
||||
fn add_forward_flat_pipeline(&mut self) -> &mut Self;
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'c> ForwardFlatPipelineBuilder for RenderGraphBuilder<'a, 'b, 'c> {
|
||||
fn add_forward_flat_pipeline(&mut self) -> &mut Self {
|
||||
self.add_pipeline(resource_name::pipeline::FORWARD_FLAT, |builder| {
|
||||
builder
|
||||
.with_vertex_shader(Shader::from_glsl(
|
||||
ShaderStage::Vertex,
|
||||
include_str!("forward_flat.vert"),
|
||||
))
|
||||
.with_fragment_shader(Shader::from_glsl(
|
||||
ShaderStage::Fragment,
|
||||
include_str!("forward_flat.frag"),
|
||||
))
|
||||
.with_rasterization_state(RasterizationStateDescriptor {
|
||||
front_face: FrontFace::Ccw,
|
||||
cull_mode: CullMode::Back,
|
||||
depth_bias: 0,
|
||||
depth_bias_slope_scale: 0.0,
|
||||
depth_bias_clamp: 0.0,
|
||||
})
|
||||
.with_depth_stencil_state(DepthStencilStateDescriptor {
|
||||
format: TextureFormat::Depth32Float,
|
||||
depth_write_enabled: true,
|
||||
depth_compare: CompareFunction::Less,
|
||||
stencil_front: StencilStateFaceDescriptor::IGNORE,
|
||||
stencil_back: StencilStateFaceDescriptor::IGNORE,
|
||||
stencil_read_mask: 0,
|
||||
stencil_write_mask: 0,
|
||||
})
|
||||
.add_color_state(ColorStateDescriptor {
|
||||
format: TextureFormat::Bgra8UnormSrgb,
|
||||
color_blend: BlendDescriptor::REPLACE,
|
||||
alpha_blend: BlendDescriptor::REPLACE,
|
||||
write_mask: ColorWrite::ALL,
|
||||
})
|
||||
.add_draw_target(resource_name::draw_target::MESHES);
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
mod forward;
|
||||
mod forward_flat;
|
||||
mod ui;
|
||||
|
||||
pub use forward::*;
|
||||
pub use forward_flat::*;
|
||||
pub use ui::*;
|
|
@ -1,61 +0,0 @@
|
|||
use crate::{
|
||||
pipeline::state_descriptors::{
|
||||
BlendDescriptor, BlendFactor, BlendOperation, ColorStateDescriptor, ColorWrite,
|
||||
CompareFunction, CullMode, DepthStencilStateDescriptor, FrontFace,
|
||||
RasterizationStateDescriptor, StencilStateFaceDescriptor,
|
||||
},
|
||||
render_graph::RenderGraphBuilder,
|
||||
render_resource::resource_name,
|
||||
shader::{Shader, ShaderStage},
|
||||
texture::TextureFormat,
|
||||
};
|
||||
pub trait UiPipelineBuilder {
|
||||
fn add_ui_pipeline(&mut self) -> &mut Self;
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'c> UiPipelineBuilder for RenderGraphBuilder<'a, 'b, 'c> {
|
||||
fn add_ui_pipeline(&mut self) -> &mut Self {
|
||||
self.add_pipeline(resource_name::pipeline::UI, |builder| {
|
||||
builder
|
||||
.with_vertex_shader(Shader::from_glsl(
|
||||
ShaderStage::Vertex,
|
||||
include_str!("ui.vert"),
|
||||
))
|
||||
.with_fragment_shader(Shader::from_glsl(
|
||||
ShaderStage::Fragment,
|
||||
include_str!("ui.frag"),
|
||||
))
|
||||
.with_rasterization_state(RasterizationStateDescriptor {
|
||||
front_face: FrontFace::Ccw,
|
||||
cull_mode: CullMode::None,
|
||||
depth_bias: 0,
|
||||
depth_bias_slope_scale: 0.0,
|
||||
depth_bias_clamp: 0.0,
|
||||
})
|
||||
.with_depth_stencil_state(DepthStencilStateDescriptor {
|
||||
format: TextureFormat::Depth32Float,
|
||||
depth_write_enabled: false,
|
||||
depth_compare: CompareFunction::Always,
|
||||
stencil_front: StencilStateFaceDescriptor::IGNORE,
|
||||
stencil_back: StencilStateFaceDescriptor::IGNORE,
|
||||
stencil_read_mask: 0,
|
||||
stencil_write_mask: 0,
|
||||
})
|
||||
.add_color_state(ColorStateDescriptor {
|
||||
format: TextureFormat::Bgra8UnormSrgb,
|
||||
color_blend: BlendDescriptor {
|
||||
src_factor: BlendFactor::SrcAlpha,
|
||||
dst_factor: BlendFactor::OneMinusSrcAlpha,
|
||||
operation: BlendOperation::Add,
|
||||
},
|
||||
alpha_blend: BlendDescriptor {
|
||||
src_factor: BlendFactor::One,
|
||||
dst_factor: BlendFactor::One,
|
||||
operation: BlendOperation::Add,
|
||||
},
|
||||
write_mask: ColorWrite::ALL,
|
||||
})
|
||||
.add_draw_target(resource_name::draw_target::UI);
|
||||
})
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{render_resource::RenderResource, renderer_2::RenderContext, texture::Extent3d};
|
||||
use crate::{render_resource::RenderResource, renderer::RenderContext, texture::Extent3d};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
pub enum Command {
|
|
@ -3,14 +3,14 @@ use legion::prelude::{Executor, Resources, Schedulable};
|
|||
use std::{borrow::Cow, collections::HashMap, fmt::Debug};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct RenderGraph2 {
|
||||
pub struct RenderGraph {
|
||||
nodes: HashMap<NodeId, NodeState>,
|
||||
node_names: HashMap<Cow<'static, str>, NodeId>,
|
||||
new_node_systems: Vec<Box<dyn Schedulable>>,
|
||||
node_system_executor: Option<Executor>,
|
||||
}
|
||||
|
||||
impl RenderGraph2 {
|
||||
impl RenderGraph {
|
||||
pub fn add_node<T>(&mut self, node: T) -> NodeId
|
||||
where
|
||||
T: Node,
|
||||
|
@ -41,7 +41,7 @@ impl RenderGraph2 {
|
|||
self.add_node(node)
|
||||
}
|
||||
|
||||
pub fn add_system_node_named<T>(&mut self, name: impl Into<Cow<'static, str>>, node: T, resources: &mut Resources) -> NodeId
|
||||
pub fn add_system_node_named<T>(&mut self, name: impl Into<Cow<'static, str>>, node: T, resources: &Resources) -> NodeId
|
||||
where
|
||||
T: SystemNode + 'static,
|
||||
{
|
||||
|
@ -293,7 +293,7 @@ impl RenderGraph2 {
|
|||
}
|
||||
}
|
||||
|
||||
impl Debug for RenderGraph2 {
|
||||
impl Debug for RenderGraph {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
for node in self.iter_nodes() {
|
||||
writeln!(f, "{:?}", node.id)?;
|
||||
|
@ -307,11 +307,11 @@ impl Debug for RenderGraph2 {
|
|||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::RenderGraph2;
|
||||
use super::RenderGraph;
|
||||
use crate::{
|
||||
render_graph_2::{Edge, Node, NodeId, RenderGraphError, ResourceSlotInfo, ResourceSlots},
|
||||
render_graph::{Edge, Node, NodeId, RenderGraphError, ResourceSlotInfo, ResourceSlots},
|
||||
render_resource::ResourceInfo,
|
||||
renderer_2::RenderContext,
|
||||
renderer::RenderContext,
|
||||
};
|
||||
use legion::prelude::{Resources, World};
|
||||
use std::{collections::HashSet, iter::FromIterator};
|
||||
|
@ -362,7 +362,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
pub fn test_graph_edges() {
|
||||
let mut graph = RenderGraph2::default();
|
||||
let mut graph = RenderGraph::default();
|
||||
let a_id = graph.add_node_named("A", TestNode::new(0, 1));
|
||||
let b_id = graph.add_node_named("B", TestNode::new(0, 1));
|
||||
let c_id = graph.add_node_named("C", TestNode::new(1, 1));
|
||||
|
@ -372,7 +372,7 @@ mod tests {
|
|||
graph.add_node_edge("B", "C").unwrap();
|
||||
graph.add_slot_edge("C", 0, "D", 0).unwrap();
|
||||
|
||||
fn input_nodes(name: &'static str, graph: &RenderGraph2) -> HashSet<NodeId> {
|
||||
fn input_nodes(name: &'static str, graph: &RenderGraph) -> HashSet<NodeId> {
|
||||
graph
|
||||
.iter_node_inputs(name)
|
||||
.unwrap()
|
||||
|
@ -380,7 +380,7 @@ mod tests {
|
|||
.collect::<HashSet<NodeId>>()
|
||||
}
|
||||
|
||||
fn output_nodes(name: &'static str, graph: &RenderGraph2) -> HashSet<NodeId> {
|
||||
fn output_nodes(name: &'static str, graph: &RenderGraph) -> HashSet<NodeId> {
|
||||
graph
|
||||
.iter_node_outputs(name)
|
||||
.unwrap()
|
||||
|
@ -434,7 +434,7 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
let mut graph = RenderGraph2::default();
|
||||
let mut graph = RenderGraph::default();
|
||||
|
||||
graph.add_node_named("A", MyNode { value: 42 });
|
||||
|
||||
|
@ -451,7 +451,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
pub fn test_slot_already_occupied() {
|
||||
let mut graph = RenderGraph2::default();
|
||||
let mut graph = RenderGraph::default();
|
||||
|
||||
graph.add_node_named("A", TestNode::new(0, 1));
|
||||
graph.add_node_named("B", TestNode::new(0, 1));
|
||||
|
@ -471,7 +471,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
pub fn test_edge_already_exists() {
|
||||
let mut graph = RenderGraph2::default();
|
||||
let mut graph = RenderGraph::default();
|
||||
|
||||
graph.add_node_named("A", TestNode::new(0, 1));
|
||||
graph.add_node_named("B", TestNode::new(1, 0));
|
|
@ -1,5 +1,40 @@
|
|||
mod render_graph;
|
||||
mod render_graph_builder;
|
||||
pub mod nodes;
|
||||
mod command;
|
||||
mod graph;
|
||||
mod node;
|
||||
mod edge;
|
||||
mod node_slot;
|
||||
mod schedule;
|
||||
pub use command::*;
|
||||
pub use graph::*;
|
||||
pub use node::*;
|
||||
pub use edge::*;
|
||||
pub use node_slot::*;
|
||||
pub use schedule::*;
|
||||
|
||||
pub use render_graph::*;
|
||||
pub use render_graph_builder::*;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug, Eq, PartialEq)]
|
||||
pub enum RenderGraphError {
|
||||
#[error("Node does not exist")]
|
||||
InvalidNode(NodeLabel),
|
||||
#[error("Node slot does not exist")]
|
||||
InvalidNodeSlot(SlotLabel),
|
||||
#[error("Node does not match the given type")]
|
||||
WrongNodeType,
|
||||
#[error("Attempted to connect a node output slot to an incompatible input node slot")]
|
||||
MismatchedNodeSlots {
|
||||
output_node: NodeId,
|
||||
output_slot: usize,
|
||||
input_node: NodeId,
|
||||
input_slot: usize,
|
||||
},
|
||||
#[error("Attempted to add an edge that already exists")]
|
||||
EdgeAlreadyExists(Edge),
|
||||
#[error("Node has an unconnected input slot.")]
|
||||
UnconnectedNodeInputSlot { node: NodeId, input_slot: usize },
|
||||
#[error("Node has an unconnected output slot.")]
|
||||
UnconnectedNodeOutputSlot { node: NodeId, output_slot: usize },
|
||||
#[error("Node input slot already occupied")]
|
||||
NodeInputSlotAlreadyOccupied { node: NodeId, input_slot: usize, occupied_by_node: NodeId },
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
use super::{Edge, RenderGraphError, ResourceSlotInfo, ResourceSlots};
|
||||
use crate::renderer_2::RenderContext;
|
||||
use crate::renderer::RenderContext;
|
||||
use downcast_rs::{impl_downcast, Downcast};
|
||||
use legion::prelude::{Resources, Schedulable, World};
|
||||
use std::{borrow::Cow, fmt::Debug};
|
||||
|
@ -36,7 +36,7 @@ pub trait Node: Downcast + Send + Sync + 'static {
|
|||
impl_downcast!(Node);
|
||||
|
||||
pub trait SystemNode: Node {
|
||||
fn get_system(&self, resources: &mut Resources) -> Box<dyn Schedulable>;
|
||||
fn get_system(&self, resources: &Resources) -> Box<dyn Schedulable>;
|
||||
}
|
||||
|
||||
pub struct Edges {
|
|
@ -4,12 +4,10 @@ mod window_texture_node;
|
|||
mod window_swapchain_node;
|
||||
mod pass_node;
|
||||
mod uniform_node;
|
||||
mod lights_node;
|
||||
|
||||
pub use camera_node::*;
|
||||
pub use camera2d_node::*;
|
||||
pub use window_texture_node::*;
|
||||
pub use window_swapchain_node::*;
|
||||
pub use pass_node::*;
|
||||
pub use uniform_node::*;
|
||||
pub use lights_node::*;
|
||||
pub use uniform_node::*;
|
|
@ -3,9 +3,9 @@ use bevy_window::WindowResized;
|
|||
|
||||
use crate::{
|
||||
camera::{ActiveCamera2d, Camera},
|
||||
render_graph_2::{CommandQueue, Node, SystemNode, ResourceSlots},
|
||||
render_graph::{CommandQueue, Node, SystemNode, ResourceSlots},
|
||||
render_resource::{resource_name, BufferInfo, BufferUsage, RenderResourceAssignments},
|
||||
renderer_2::{GlobalRenderResourceContext, RenderContext},
|
||||
renderer::{GlobalRenderResourceContext, RenderContext},
|
||||
};
|
||||
|
||||
use bevy_transform::components::LocalToWorld;
|
||||
|
@ -31,7 +31,7 @@ impl Node for Camera2dNode {
|
|||
}
|
||||
|
||||
impl SystemNode for Camera2dNode {
|
||||
fn get_system(&self, resources: &mut Resources) -> Box<dyn Schedulable> {
|
||||
fn get_system(&self, resources: &Resources) -> Box<dyn Schedulable> {
|
||||
let mut camera_buffer = None;
|
||||
let mut tmp_buffer = None;
|
||||
let mut window_resized_event_reader = resources.get_event_reader::<WindowResized>();
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
render_graph_2::{CommandQueue, Node, SystemNode, ResourceSlots},
|
||||
render_graph::{CommandQueue, Node, SystemNode, ResourceSlots},
|
||||
render_resource::{resource_name, BufferInfo, BufferUsage, RenderResourceAssignments},
|
||||
renderer_2::{GlobalRenderResourceContext, RenderContext},
|
||||
renderer::{GlobalRenderResourceContext, RenderContext},
|
||||
ActiveCamera, Camera,
|
||||
};
|
||||
|
||||
|
@ -30,7 +30,7 @@ impl Node for CameraNode {
|
|||
}
|
||||
|
||||
impl SystemNode for CameraNode {
|
||||
fn get_system(&self, resources: &mut Resources) -> Box<dyn Schedulable> {
|
||||
fn get_system(&self, resources: &Resources) -> Box<dyn Schedulable> {
|
||||
let mut camera_buffer = None;
|
||||
let mut tmp_buffer = None;
|
||||
let mut window_resized_event_reader = resources.get_event_reader::<WindowResized>();
|
|
@ -2,9 +2,9 @@ use crate::{
|
|||
draw_target::DrawTarget,
|
||||
pass::{PassDescriptor, TextureAttachment},
|
||||
pipeline::{PipelineCompiler, PipelineDescriptor},
|
||||
render_graph_2::{Node, ResourceSlotInfo, ResourceSlots},
|
||||
render_graph::{Node, ResourceSlotInfo, ResourceSlots},
|
||||
render_resource::{RenderResourceAssignments, ResourceInfo},
|
||||
renderer_2::RenderContext,
|
||||
renderer::RenderContext,
|
||||
shader::Shader,
|
||||
};
|
||||
use bevy_asset::{AssetStorage, Handle};
|
|
@ -1,11 +1,11 @@
|
|||
use crate::{
|
||||
pipeline::VertexBufferDescriptors,
|
||||
render_graph_2::{CommandQueue, Node, ResourceSlots, SystemNode},
|
||||
render_graph::{CommandQueue, Node, ResourceSlots, SystemNode},
|
||||
render_resource::{
|
||||
BufferArrayInfo, BufferInfo, BufferUsage, RenderResource, RenderResourceAssignments,
|
||||
RenderResourceAssignmentsId, ResourceInfo,
|
||||
},
|
||||
renderer_2::{GlobalRenderResourceContext, RenderContext, RenderResourceContext},
|
||||
renderer::{GlobalRenderResourceContext, RenderContext, RenderResourceContext},
|
||||
shader::{AsUniforms, FieldBindType},
|
||||
texture, Renderable,
|
||||
};
|
||||
|
@ -332,6 +332,55 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: use something like this to remove redundancy between AssetUniformNode and UniformNode
|
||||
// fn update_uniforms<T>(
|
||||
// render_resource_context: &dyn RenderResourceContext,
|
||||
// staging_buffer_resource: &mut Option<RenderResource>,
|
||||
// uniform_buffer_arrays: &mut UniformBufferArrays<T>,
|
||||
// command_queue: &mut CommandQueue,
|
||||
// dynamic_uniforms: bool,
|
||||
// increment_uniform_counts: impl Fn(),
|
||||
// update_textures: impl Fn(),
|
||||
// update_uniform_buffers: impl Fn(&mut [u8]),
|
||||
// ) where
|
||||
// T: AsUniforms,
|
||||
// {
|
||||
// if let Some(staging_buffer_resource) = staging_buffer_resource {
|
||||
// render_resource_context.remove_buffer(*staging_buffer_resource);
|
||||
// }
|
||||
// *staging_buffer_resource = None;
|
||||
|
||||
// uniform_buffer_arrays.reset_new_item_counts();
|
||||
|
||||
// increment_uniform_counts();
|
||||
|
||||
// uniform_buffer_arrays.setup_buffer_arrays(render_resource_context, dynamic_uniforms);
|
||||
// let staging_buffer_size = uniform_buffer_arrays.update_staging_buffer_offsets();
|
||||
|
||||
// update_textures();
|
||||
|
||||
// if staging_buffer_size == 0 {
|
||||
// let mut staging_buffer: [u8; 0] = [];
|
||||
// update_uniform_buffers(&mut staging_buffer);
|
||||
// } else {
|
||||
// let staging_buffer = render_resource_context.create_buffer_mapped(
|
||||
// BufferInfo {
|
||||
// buffer_usage: BufferUsage::COPY_SRC,
|
||||
// size: staging_buffer_size,
|
||||
// ..Default::default()
|
||||
// },
|
||||
// &mut |staging_buffer, _render_resources| {
|
||||
// update_uniform_buffers(staging_buffer);
|
||||
// },
|
||||
// );
|
||||
|
||||
// uniform_buffer_arrays
|
||||
// .copy_staging_buffer_to_final_buffers(command_queue, staging_buffer);
|
||||
|
||||
// *staging_buffer_resource = Some(staging_buffer);
|
||||
// }
|
||||
// }
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct UniformNode<T>
|
||||
where
|
||||
|
@ -353,90 +402,6 @@ where
|
|||
_marker: PhantomData::default(),
|
||||
}
|
||||
}
|
||||
|
||||
fn initialize_vertex_buffer_descriptor(
|
||||
vertex_buffer_descriptors: &mut VertexBufferDescriptors,
|
||||
) {
|
||||
let vertex_buffer_descriptor = T::get_vertex_buffer_descriptor();
|
||||
if let Some(vertex_buffer_descriptor) = vertex_buffer_descriptor {
|
||||
if let None = vertex_buffer_descriptors.get(&vertex_buffer_descriptor.name) {
|
||||
vertex_buffer_descriptors.set(vertex_buffer_descriptor.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn setup_uniform_texture_resources(
|
||||
uniforms: &T,
|
||||
command_queue: &mut CommandQueue,
|
||||
texture_storage: &AssetStorage<Texture>,
|
||||
render_resource_context: &dyn RenderResourceContext,
|
||||
render_resource_assignments: &mut RenderResourceAssignments,
|
||||
) {
|
||||
for field_info in T::get_field_infos().iter() {
|
||||
let bind_type = uniforms.get_field_bind_type(&field_info.name);
|
||||
match bind_type {
|
||||
Some(FieldBindType::Texture) => {
|
||||
let texture_handle = uniforms
|
||||
.get_uniform_texture(&field_info.texture_name)
|
||||
.unwrap();
|
||||
let (texture_resource, sampler_resource) = match render_resource_context
|
||||
.get_asset_resource(texture_handle, texture::TEXTURE_ASSET_INDEX)
|
||||
{
|
||||
Some(texture_resource) => (
|
||||
texture_resource,
|
||||
render_resource_context
|
||||
.get_asset_resource(texture_handle, texture::SAMPLER_ASSET_INDEX)
|
||||
.unwrap(),
|
||||
),
|
||||
None => {
|
||||
let texture = texture_storage.get(&texture_handle).unwrap();
|
||||
|
||||
let texture_descriptor: TextureDescriptor = texture.into();
|
||||
let texture_resource =
|
||||
render_resource_context.create_texture(&texture_descriptor);
|
||||
// TODO: queue texture copy
|
||||
// .create_texture_with_data(&texture_descriptor, &texture.data);
|
||||
let texture_buffer = render_resource_context.create_buffer_with_data(BufferInfo {
|
||||
buffer_usage: BufferUsage::COPY_SRC,
|
||||
..Default::default()
|
||||
}, &texture.data);
|
||||
command_queue.copy_buffer_to_texture(
|
||||
texture_buffer,
|
||||
0,
|
||||
(4 * texture.width) as u32,
|
||||
texture_resource,
|
||||
[0, 0, 0],
|
||||
0,
|
||||
0,
|
||||
texture_descriptor.size.clone(),
|
||||
);
|
||||
command_queue.free_buffer(texture_buffer);
|
||||
|
||||
let sampler_descriptor: SamplerDescriptor = texture.into();
|
||||
let sampler_resource =
|
||||
render_resource_context.create_sampler(&sampler_descriptor);
|
||||
|
||||
render_resource_context.set_asset_resource(
|
||||
texture_handle,
|
||||
texture_resource,
|
||||
0,
|
||||
);
|
||||
render_resource_context.set_asset_resource(
|
||||
texture_handle,
|
||||
sampler_resource,
|
||||
1,
|
||||
);
|
||||
(texture_resource, sampler_resource)
|
||||
}
|
||||
};
|
||||
|
||||
render_resource_assignments.set(field_info.texture_name, texture_resource);
|
||||
render_resource_assignments.set(field_info.sampler_name, sampler_resource);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Node for UniformNode<T>
|
||||
|
@ -459,33 +424,25 @@ impl<T> SystemNode for UniformNode<T>
|
|||
where
|
||||
T: AsUniforms,
|
||||
{
|
||||
fn get_system(&self, resources: &mut Resources) -> Box<dyn Schedulable> {
|
||||
fn get_system(&self, resources: &Resources) -> Box<dyn Schedulable> {
|
||||
let mut command_queue = self.command_queue.clone();
|
||||
let mut uniform_buffer_arrays = UniformBufferArrays::<T>::new();
|
||||
let mut vertex_buffer_descriptors = resources.get_mut::<VertexBufferDescriptors>().unwrap();
|
||||
let dynamic_uniforms = self.dynamic_uniforms;
|
||||
let mut staging_buffer_resource = None;
|
||||
UniformNode::<T>::initialize_vertex_buffer_descriptor(&mut vertex_buffer_descriptors);
|
||||
initialize_vertex_buffer_descriptor::<T>(&mut vertex_buffer_descriptors);
|
||||
// TODO: maybe run "update" here
|
||||
SystemBuilder::new("uniform_resource_provider")
|
||||
.read_resource::<AssetStorage<T>>()
|
||||
.read_resource::<AssetStorage<Texture>>()
|
||||
.read_resource::<GlobalRenderResourceContext>()
|
||||
// TODO: this write on RenderResourceAssignments will prevent this system from running in parallel with other systems that do the same
|
||||
.with_query(<(Read<T>, Read<Renderable>)>::query())
|
||||
.with_query(<(Read<Handle<T>>, Read<Renderable>)>::query())
|
||||
.with_query(<(Read<T>, Write<Renderable>)>::query())
|
||||
.with_query(<(Read<Handle<T>>, Write<Renderable>)>::query())
|
||||
.build(
|
||||
move |_,
|
||||
world,
|
||||
(assets, textures, global_render_resource_context),
|
||||
(
|
||||
read_resource_query,
|
||||
read_handle_query,
|
||||
write_resource_query,
|
||||
write_handle_query,
|
||||
)| {
|
||||
(textures, global_render_resource_context),
|
||||
(read_uniform_query, write_uniform_query)| {
|
||||
let render_resource_context = &*global_render_resource_context.context;
|
||||
if let Some(staging_buffer_resource) = staging_buffer_resource {
|
||||
render_resource_context.remove_buffer(staging_buffer_resource);
|
||||
|
@ -494,7 +451,7 @@ where
|
|||
|
||||
uniform_buffer_arrays.reset_new_item_counts();
|
||||
// update uniforms info
|
||||
for (uniforms, renderable) in read_resource_query.iter(world) {
|
||||
for (uniforms, renderable) in read_uniform_query.iter(world) {
|
||||
if !renderable.is_visible {
|
||||
return;
|
||||
}
|
||||
|
@ -506,6 +463,160 @@ where
|
|||
}
|
||||
}
|
||||
|
||||
uniform_buffer_arrays
|
||||
.setup_buffer_arrays(render_resource_context, dynamic_uniforms);
|
||||
let staging_buffer_size = uniform_buffer_arrays.update_staging_buffer_offsets();
|
||||
|
||||
for (uniforms, mut renderable) in write_uniform_query.iter_mut(world) {
|
||||
if !renderable.is_visible {
|
||||
return;
|
||||
}
|
||||
|
||||
if renderable.is_instanced {
|
||||
panic!("instancing not currently supported");
|
||||
} else {
|
||||
setup_uniform_texture_resources::<T>(
|
||||
&uniforms,
|
||||
&mut command_queue,
|
||||
textures,
|
||||
render_resource_context,
|
||||
&mut renderable.render_resource_assignments,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if staging_buffer_size == 0 {
|
||||
let mut staging_buffer: [u8; 0] = [];
|
||||
for (uniforms, mut renderable) in write_uniform_query.iter_mut(world) {
|
||||
if !renderable.is_visible {
|
||||
return;
|
||||
}
|
||||
|
||||
if renderable.is_instanced {
|
||||
panic!("instancing not currently supported");
|
||||
} else {
|
||||
uniform_buffer_arrays.setup_uniform_buffer_resources(
|
||||
&uniforms,
|
||||
dynamic_uniforms,
|
||||
render_resource_context,
|
||||
&mut renderable.render_resource_assignments,
|
||||
&mut staging_buffer,
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
let staging_buffer = render_resource_context.create_buffer_mapped(
|
||||
BufferInfo {
|
||||
buffer_usage: BufferUsage::COPY_SRC,
|
||||
size: staging_buffer_size,
|
||||
..Default::default()
|
||||
},
|
||||
&mut |mut staging_buffer, _render_resources| {
|
||||
for (uniforms, mut renderable) in
|
||||
write_uniform_query.iter_mut(world)
|
||||
{
|
||||
if !renderable.is_visible {
|
||||
return;
|
||||
}
|
||||
|
||||
if renderable.is_instanced {
|
||||
panic!("instancing not currently supported");
|
||||
} else {
|
||||
uniform_buffer_arrays.setup_uniform_buffer_resources(
|
||||
&uniforms,
|
||||
dynamic_uniforms,
|
||||
render_resource_context,
|
||||
&mut renderable.render_resource_assignments,
|
||||
&mut staging_buffer,
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
uniform_buffer_arrays.copy_staging_buffer_to_final_buffers(
|
||||
&mut command_queue,
|
||||
staging_buffer,
|
||||
);
|
||||
|
||||
staging_buffer_resource = Some(staging_buffer);
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct AssetUniformNode<T>
|
||||
where
|
||||
T: AsUniforms,
|
||||
{
|
||||
command_queue: CommandQueue,
|
||||
dynamic_uniforms: bool,
|
||||
_marker: PhantomData<T>,
|
||||
}
|
||||
|
||||
impl<T> AssetUniformNode<T>
|
||||
where
|
||||
T: AsUniforms,
|
||||
{
|
||||
pub fn new(dynamic_uniforms: bool) -> Self {
|
||||
AssetUniformNode {
|
||||
command_queue: CommandQueue::default(),
|
||||
dynamic_uniforms,
|
||||
_marker: PhantomData::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> Node for AssetUniformNode<T>
|
||||
where
|
||||
T: AsUniforms,
|
||||
{
|
||||
fn update(
|
||||
&mut self,
|
||||
_world: &World,
|
||||
_resources: &Resources,
|
||||
render_context: &mut dyn RenderContext,
|
||||
_input: &ResourceSlots,
|
||||
_output: &mut ResourceSlots,
|
||||
) {
|
||||
self.command_queue.execute(render_context);
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> SystemNode for AssetUniformNode<T>
|
||||
where
|
||||
T: AsUniforms,
|
||||
{
|
||||
fn get_system(&self, resources: &Resources) -> Box<dyn Schedulable> {
|
||||
let mut command_queue = self.command_queue.clone();
|
||||
let mut uniform_buffer_arrays = UniformBufferArrays::<T>::new();
|
||||
let mut vertex_buffer_descriptors = resources.get_mut::<VertexBufferDescriptors>().unwrap();
|
||||
let dynamic_uniforms = self.dynamic_uniforms;
|
||||
let mut staging_buffer_resource = None;
|
||||
initialize_vertex_buffer_descriptor::<T>(&mut vertex_buffer_descriptors);
|
||||
// TODO: maybe run "update" here
|
||||
SystemBuilder::new("uniform_resource_provider")
|
||||
.read_resource::<AssetStorage<T>>()
|
||||
.read_resource::<AssetStorage<Texture>>()
|
||||
.read_resource::<GlobalRenderResourceContext>()
|
||||
// TODO: this write on RenderResourceAssignments will prevent this system from running in parallel with other systems that do the same
|
||||
.with_query(<(Read<Handle<T>>, Read<Renderable>)>::query())
|
||||
.with_query(<(Read<Handle<T>>, Write<Renderable>)>::query())
|
||||
.build(
|
||||
move |_,
|
||||
world,
|
||||
(assets, textures, global_render_resource_context),
|
||||
(read_handle_query, write_handle_query)| {
|
||||
let render_resource_context = &*global_render_resource_context.context;
|
||||
if let Some(staging_buffer_resource) = staging_buffer_resource {
|
||||
render_resource_context.remove_buffer(staging_buffer_resource);
|
||||
}
|
||||
staging_buffer_resource = None;
|
||||
|
||||
uniform_buffer_arrays.reset_new_item_counts();
|
||||
|
||||
// update uniform handles info
|
||||
for (handle, renderable) in read_handle_query.iter(world) {
|
||||
if !renderable.is_visible {
|
||||
|
@ -527,24 +638,6 @@ where
|
|||
.setup_buffer_arrays(render_resource_context, dynamic_uniforms);
|
||||
let staging_buffer_size = uniform_buffer_arrays.update_staging_buffer_offsets();
|
||||
|
||||
for (uniforms, mut renderable) in write_resource_query.iter_mut(world) {
|
||||
if !renderable.is_visible {
|
||||
return;
|
||||
}
|
||||
|
||||
if renderable.is_instanced {
|
||||
panic!("instancing not currently supported");
|
||||
} else {
|
||||
Self::setup_uniform_texture_resources(
|
||||
&uniforms,
|
||||
&mut command_queue,
|
||||
textures,
|
||||
render_resource_context,
|
||||
&mut renderable.render_resource_assignments,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
for (handle, mut renderable) in write_handle_query.iter_mut(world) {
|
||||
if !renderable.is_visible {
|
||||
return;
|
||||
|
@ -556,7 +649,7 @@ where
|
|||
let uniforms = assets
|
||||
.get(&handle)
|
||||
.expect("Handle points to a non-existent resource");
|
||||
Self::setup_uniform_texture_resources(
|
||||
setup_uniform_texture_resources::<T>(
|
||||
&uniforms,
|
||||
&mut command_queue,
|
||||
textures,
|
||||
|
@ -567,23 +660,6 @@ where
|
|||
}
|
||||
if staging_buffer_size == 0 {
|
||||
let mut staging_buffer: [u8; 0] = [];
|
||||
for (uniforms, mut renderable) in write_resource_query.iter_mut(world) {
|
||||
if !renderable.is_visible {
|
||||
return;
|
||||
}
|
||||
|
||||
if renderable.is_instanced {
|
||||
panic!("instancing not currently supported");
|
||||
} else {
|
||||
uniform_buffer_arrays.setup_uniform_buffer_resources(
|
||||
&uniforms,
|
||||
dynamic_uniforms,
|
||||
render_resource_context,
|
||||
&mut renderable.render_resource_assignments,
|
||||
&mut staging_buffer,
|
||||
);
|
||||
}
|
||||
}
|
||||
for (handle, mut renderable) in write_handle_query.iter_mut(world) {
|
||||
if !renderable.is_visible {
|
||||
return;
|
||||
|
@ -612,25 +688,6 @@ where
|
|||
..Default::default()
|
||||
},
|
||||
&mut |mut staging_buffer, _render_resources| {
|
||||
for (uniforms, mut renderable) in
|
||||
write_resource_query.iter_mut(world)
|
||||
{
|
||||
if !renderable.is_visible {
|
||||
return;
|
||||
}
|
||||
|
||||
if renderable.is_instanced {
|
||||
panic!("instancing not currently supported");
|
||||
} else {
|
||||
uniform_buffer_arrays.setup_uniform_buffer_resources(
|
||||
&uniforms,
|
||||
dynamic_uniforms,
|
||||
render_resource_context,
|
||||
&mut renderable.render_resource_assignments,
|
||||
&mut staging_buffer,
|
||||
);
|
||||
}
|
||||
}
|
||||
for (handle, mut renderable) in write_handle_query.iter_mut(world) {
|
||||
if !renderable.is_visible {
|
||||
return;
|
||||
|
@ -665,3 +722,93 @@ where
|
|||
)
|
||||
}
|
||||
}
|
||||
|
||||
fn initialize_vertex_buffer_descriptor<T>(vertex_buffer_descriptors: &mut VertexBufferDescriptors)
|
||||
where
|
||||
T: AsUniforms,
|
||||
{
|
||||
let vertex_buffer_descriptor = T::get_vertex_buffer_descriptor();
|
||||
if let Some(vertex_buffer_descriptor) = vertex_buffer_descriptor {
|
||||
if let None = vertex_buffer_descriptors.get(&vertex_buffer_descriptor.name) {
|
||||
vertex_buffer_descriptors.set(vertex_buffer_descriptor.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn setup_uniform_texture_resources<T>(
|
||||
uniforms: &T,
|
||||
command_queue: &mut CommandQueue,
|
||||
texture_storage: &AssetStorage<Texture>,
|
||||
render_resource_context: &dyn RenderResourceContext,
|
||||
render_resource_assignments: &mut RenderResourceAssignments,
|
||||
) where
|
||||
T: AsUniforms,
|
||||
{
|
||||
for field_info in T::get_field_infos().iter() {
|
||||
let bind_type = uniforms.get_field_bind_type(&field_info.name);
|
||||
match bind_type {
|
||||
Some(FieldBindType::Texture) => {
|
||||
let texture_handle = uniforms
|
||||
.get_uniform_texture(&field_info.texture_name)
|
||||
.unwrap();
|
||||
let (texture_resource, sampler_resource) = match render_resource_context
|
||||
.get_asset_resource(texture_handle, texture::TEXTURE_ASSET_INDEX)
|
||||
{
|
||||
Some(texture_resource) => (
|
||||
texture_resource,
|
||||
render_resource_context
|
||||
.get_asset_resource(texture_handle, texture::SAMPLER_ASSET_INDEX)
|
||||
.unwrap(),
|
||||
),
|
||||
None => {
|
||||
let texture = texture_storage.get(&texture_handle).unwrap();
|
||||
|
||||
let texture_descriptor: TextureDescriptor = texture.into();
|
||||
let texture_resource =
|
||||
render_resource_context.create_texture(&texture_descriptor);
|
||||
// TODO: queue texture copy
|
||||
// .create_texture_with_data(&texture_descriptor, &texture.data);
|
||||
let texture_buffer = render_resource_context.create_buffer_with_data(
|
||||
BufferInfo {
|
||||
buffer_usage: BufferUsage::COPY_SRC,
|
||||
..Default::default()
|
||||
},
|
||||
&texture.data,
|
||||
);
|
||||
command_queue.copy_buffer_to_texture(
|
||||
texture_buffer,
|
||||
0,
|
||||
(4 * texture.width) as u32,
|
||||
texture_resource,
|
||||
[0, 0, 0],
|
||||
0,
|
||||
0,
|
||||
texture_descriptor.size.clone(),
|
||||
);
|
||||
command_queue.free_buffer(texture_buffer);
|
||||
|
||||
let sampler_descriptor: SamplerDescriptor = texture.into();
|
||||
let sampler_resource =
|
||||
render_resource_context.create_sampler(&sampler_descriptor);
|
||||
|
||||
render_resource_context.set_asset_resource(
|
||||
texture_handle,
|
||||
texture_resource,
|
||||
0,
|
||||
);
|
||||
render_resource_context.set_asset_resource(
|
||||
texture_handle,
|
||||
sampler_resource,
|
||||
1,
|
||||
);
|
||||
(texture_resource, sampler_resource)
|
||||
}
|
||||
};
|
||||
|
||||
render_resource_assignments.set(field_info.texture_name, texture_resource);
|
||||
render_resource_assignments.set(field_info.sampler_name, sampler_resource);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
render_graph_2::{Node, ResourceSlots, ResourceSlotInfo},
|
||||
render_graph::{Node, ResourceSlots, ResourceSlotInfo},
|
||||
render_resource::ResourceInfo,
|
||||
renderer_2::RenderContext,
|
||||
renderer::RenderContext,
|
||||
};
|
||||
use bevy_app::{EventReader, Events};
|
||||
use bevy_window::{WindowCreated, WindowResized, Windows, WindowReference};
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
render_graph_2::{Node, ResourceSlotInfo, ResourceSlots},
|
||||
render_graph::{Node, ResourceSlotInfo, ResourceSlots},
|
||||
render_resource::ResourceInfo,
|
||||
renderer_2::RenderContext,
|
||||
renderer::RenderContext,
|
||||
texture::TextureDescriptor,
|
||||
};
|
||||
use bevy_app::{EventReader, Events};
|
|
@ -1,98 +0,0 @@
|
|||
use super::RenderGraphBuilder;
|
||||
use crate::{
|
||||
draw_target::DrawTarget,
|
||||
pass::PassDescriptor,
|
||||
pipeline::{PipelineCompiler, PipelineDescriptor},
|
||||
render_resource::ResourceProvider,
|
||||
renderer_2::RenderContext,
|
||||
shader::Shader,
|
||||
texture::TextureDescriptor,
|
||||
};
|
||||
use bevy_asset::{AssetStorage, Handle};
|
||||
use legion::prelude::*;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct RenderGraph {
|
||||
pub pipeline_descriptors: HashSet<Handle<PipelineDescriptor>>,
|
||||
pub pass_descriptors: HashMap<String, PassDescriptor>,
|
||||
pub pass_pipelines: HashMap<String, Vec<Handle<PipelineDescriptor>>>,
|
||||
pub resource_providers: Vec<Box<dyn ResourceProvider + Send + Sync>>,
|
||||
pub queued_textures: Vec<(String, TextureDescriptor)>,
|
||||
pub draw_targets: HashMap<String, Box<dyn DrawTarget + Send + Sync>>,
|
||||
}
|
||||
|
||||
impl RenderGraph {
|
||||
pub fn build<'a, 'b, 'c>(
|
||||
&'c mut self,
|
||||
pipelines: &'a mut AssetStorage<PipelineDescriptor>,
|
||||
shaders: &'b mut AssetStorage<Shader>,
|
||||
) -> RenderGraphBuilder<'a, 'b, 'c> {
|
||||
RenderGraphBuilder {
|
||||
pipelines,
|
||||
shaders,
|
||||
current_pass: None,
|
||||
render_graph: self,
|
||||
}
|
||||
}
|
||||
|
||||
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 fn setup_pipeline_draw_targets(
|
||||
&mut self,
|
||||
world: &mut World,
|
||||
resources: &Resources,
|
||||
render_context: &mut dyn RenderContext,
|
||||
) {
|
||||
let shader_storage = resources.get::<AssetStorage<Shader>>().unwrap();
|
||||
let pipeline_compiler = resources.get::<PipelineCompiler>().unwrap();
|
||||
|
||||
for (pass_name, _pass_descriptor) in self.pass_descriptors.iter() {
|
||||
if let Some(pass_pipelines) = self.pass_pipelines.get(pass_name) {
|
||||
for pass_pipeline in pass_pipelines.iter() {
|
||||
if let Some(compiled_pipelines_iter) =
|
||||
pipeline_compiler.iter_compiled_pipelines(*pass_pipeline)
|
||||
{
|
||||
for compiled_pipeline_handle in compiled_pipelines_iter {
|
||||
let mut pipeline_storage = resources
|
||||
.get_mut::<AssetStorage<PipelineDescriptor>>()
|
||||
.unwrap();
|
||||
let compiled_pipeline_descriptor =
|
||||
pipeline_storage.get_mut(compiled_pipeline_handle).unwrap();
|
||||
|
||||
// create wgpu pipeline if it doesn't exist
|
||||
render_context.create_render_pipeline(
|
||||
*compiled_pipeline_handle,
|
||||
compiled_pipeline_descriptor,
|
||||
&shader_storage,
|
||||
);
|
||||
|
||||
// setup pipeline draw targets
|
||||
for draw_target_name in compiled_pipeline_descriptor.draw_targets.iter()
|
||||
{
|
||||
let draw_target =
|
||||
self.draw_targets.get_mut(draw_target_name).unwrap();
|
||||
draw_target.setup(
|
||||
world,
|
||||
resources,
|
||||
render_context,
|
||||
*compiled_pipeline_handle,
|
||||
compiled_pipeline_descriptor,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,125 +0,0 @@
|
|||
use super::RenderGraph;
|
||||
use crate::{
|
||||
draw_target::DrawTarget,
|
||||
pass::PassDescriptor,
|
||||
pipeline::{PipelineBuilder, PipelineDescriptor},
|
||||
render_resource::ResourceProvider,
|
||||
shader::Shader,
|
||||
texture::TextureDescriptor,
|
||||
};
|
||||
|
||||
use bevy_asset::AssetStorage;
|
||||
|
||||
pub struct RenderGraphBuilder<'a, 'b, 'c> {
|
||||
pub pipelines: &'a mut AssetStorage<PipelineDescriptor>,
|
||||
pub shaders: &'b mut AssetStorage<Shader>,
|
||||
pub render_graph: &'c mut RenderGraph,
|
||||
pub current_pass: Option<String>,
|
||||
}
|
||||
|
||||
impl<'a, 'b, 'c> RenderGraphBuilder<'a, 'b, 'c> {
|
||||
pub fn add_pass(&mut self, name: &str, pass: PassDescriptor) -> &mut 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, name: &str, build: impl Fn(&mut PipelineBuilder)) -> &mut Self {
|
||||
if let Some(ref pass) = self.current_pass {
|
||||
let mut builder = PipelineBuilder::new(name, &mut self.shaders);
|
||||
build(&mut builder);
|
||||
let pipeline = builder.finish();
|
||||
let pipeline_descriptor_handle = self.pipelines.add(pipeline);
|
||||
self.pipelines.set_name(name, pipeline_descriptor_handle);
|
||||
self.render_graph
|
||||
.add_pipeline(&pass, pipeline_descriptor_handle);
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_default_pipeline(
|
||||
&mut self,
|
||||
name: &str,
|
||||
build: impl Fn(&mut PipelineBuilder),
|
||||
) -> &mut Self {
|
||||
if let Some(ref pass) = self.current_pass {
|
||||
let mut builder = PipelineBuilder::new(name, &mut self.shaders);
|
||||
build(&mut builder);
|
||||
let pipeline = builder.finish();
|
||||
let pipeline_descriptor_handle = self.pipelines.add_default(pipeline);
|
||||
self.pipelines.set_name(name, pipeline_descriptor_handle);
|
||||
self.render_graph
|
||||
.add_pipeline(&pass, pipeline_descriptor_handle);
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_pipeline_to_pass(
|
||||
&mut self,
|
||||
pass: &str,
|
||||
name: &str,
|
||||
build: impl Fn(&mut PipelineBuilder),
|
||||
) -> &mut Self {
|
||||
{
|
||||
let mut builder = PipelineBuilder::new(name, &mut self.shaders);
|
||||
build(&mut builder);
|
||||
let pipeline = builder.finish();
|
||||
let pipeline_descriptor_handle = self.pipelines.add(pipeline);
|
||||
self.pipelines.set_name(name, pipeline_descriptor_handle);
|
||||
self.render_graph
|
||||
.add_pipeline(pass, pipeline_descriptor_handle);
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_default_pipeline_to_pass(
|
||||
&mut self,
|
||||
pass: &str,
|
||||
name: &str,
|
||||
build: impl Fn(&mut PipelineBuilder),
|
||||
) -> &mut Self {
|
||||
{
|
||||
let mut builder = PipelineBuilder::new(name, &mut self.shaders);
|
||||
build(&mut builder);
|
||||
let pipeline = builder.finish();
|
||||
let pipeline_descriptor_handle = self.pipelines.add_default(pipeline);
|
||||
self.pipelines.set_name(name, pipeline_descriptor_handle);
|
||||
self.render_graph
|
||||
.add_pipeline(pass, pipeline_descriptor_handle);
|
||||
}
|
||||
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_resource_provider<T>(&mut self, resource_provider: T) -> &mut Self
|
||||
where
|
||||
T: ResourceProvider + Send + Sync + 'static,
|
||||
{
|
||||
self.render_graph
|
||||
.resource_providers
|
||||
.push(Box::new(resource_provider));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_texture(&mut self, name: &str, texture_descriptor: TextureDescriptor) -> &mut Self {
|
||||
self.render_graph
|
||||
.queued_textures
|
||||
.push((name.to_string(), texture_descriptor));
|
||||
self
|
||||
}
|
||||
|
||||
pub fn add_draw_target<T>(&mut self, draw_target: T) -> &mut Self
|
||||
where
|
||||
T: DrawTarget + Send + Sync + 'static,
|
||||
{
|
||||
self.render_graph
|
||||
.draw_targets
|
||||
.insert(draw_target.get_name(), Box::new(draw_target));
|
||||
self
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
use super::{NodeId, NodeState, RenderGraph2, RenderGraphError};
|
||||
use super::{NodeId, NodeState, RenderGraph, RenderGraphError};
|
||||
use std::collections::HashMap;
|
||||
use thiserror::Error;
|
||||
|
||||
|
@ -65,7 +65,7 @@ impl Stages {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn borrow<'a>(&self, render_graph: &'a mut RenderGraph2) -> Vec<StageBorrow<'a>> {
|
||||
pub fn borrow<'a>(&self, render_graph: &'a mut RenderGraph) -> Vec<StageBorrow<'a>> {
|
||||
// unfortunately borrowing render graph nodes in a specific order takes a little bit of gymnastics
|
||||
let mut stage_borrows = Vec::with_capacity(self.stages.len());
|
||||
|
||||
|
@ -102,7 +102,7 @@ impl Stages {
|
|||
|
||||
/// Produces a collection of `Stages`, which are sets of OrderedJobs that must be run before moving on to the next stage
|
||||
pub trait RenderGraphStager {
|
||||
fn get_stages(&mut self, render_graph: &RenderGraph2) -> Result<Stages, RenderGraphError>;
|
||||
fn get_stages(&mut self, render_graph: &RenderGraph) -> Result<Stages, RenderGraphError>;
|
||||
}
|
||||
|
||||
// TODO: remove this
|
||||
|
@ -111,7 +111,7 @@ pub trait RenderGraphStager {
|
|||
pub struct LinearStager;
|
||||
|
||||
impl RenderGraphStager for LinearStager {
|
||||
fn get_stages(&mut self, render_graph: &RenderGraph2) -> Result<Stages, RenderGraphError> {
|
||||
fn get_stages(&mut self, render_graph: &RenderGraph) -> Result<Stages, RenderGraphError> {
|
||||
let mut stage = Stage::default();
|
||||
let mut job = OrderedJob::default();
|
||||
for node in render_graph.iter_nodes() {
|
||||
|
@ -155,7 +155,7 @@ impl DependentNodeStager {
|
|||
}
|
||||
|
||||
impl RenderGraphStager for DependentNodeStager {
|
||||
fn get_stages<'a>(&mut self, render_graph: &RenderGraph2) -> Result<Stages, RenderGraphError> {
|
||||
fn get_stages<'a>(&mut self, render_graph: &RenderGraph) -> Result<Stages, RenderGraphError> {
|
||||
// get all nodes without input. this intentionally includes nodes with no outputs
|
||||
let output_only_nodes = render_graph
|
||||
.iter_nodes()
|
||||
|
@ -178,7 +178,7 @@ impl RenderGraphStager for DependentNodeStager {
|
|||
}
|
||||
|
||||
fn stage_node(
|
||||
graph: &RenderGraph2,
|
||||
graph: &RenderGraph,
|
||||
stages: &mut Vec<Stage>,
|
||||
node_stages_and_jobs: &mut HashMap<NodeId, (usize, usize)>,
|
||||
node: &NodeState,
|
||||
|
@ -263,9 +263,9 @@ fn stage_node(
|
|||
mod tests {
|
||||
use super::{DependentNodeStager, OrderedJob, RenderGraphStager, Stage};
|
||||
use crate::{
|
||||
render_graph_2::{Node, NodeId, RenderGraph2, ResourceSlotInfo, ResourceSlots},
|
||||
render_graph::{Node, NodeId, RenderGraph, ResourceSlotInfo, ResourceSlots},
|
||||
render_resource::ResourceInfo,
|
||||
renderer_2::RenderContext,
|
||||
renderer::RenderContext,
|
||||
};
|
||||
use legion::prelude::{Resources, World};
|
||||
|
||||
|
@ -314,7 +314,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_render_graph_dependency_stager_loose() {
|
||||
let mut graph = RenderGraph2::default();
|
||||
let mut graph = RenderGraph::default();
|
||||
|
||||
// Setup graph to look like this:
|
||||
//
|
||||
|
@ -436,7 +436,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_render_graph_dependency_stager_tight() {
|
||||
let mut graph = RenderGraph2::default();
|
||||
let mut graph = RenderGraph::default();
|
||||
|
||||
// Setup graph to look like this:
|
||||
//
|
|
@ -1,40 +0,0 @@
|
|||
pub mod nodes;
|
||||
mod command;
|
||||
mod graph;
|
||||
mod node;
|
||||
mod edge;
|
||||
mod node_slot;
|
||||
mod schedule;
|
||||
pub use command::*;
|
||||
pub use graph::*;
|
||||
pub use node::*;
|
||||
pub use edge::*;
|
||||
pub use node_slot::*;
|
||||
pub use schedule::*;
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug, Eq, PartialEq)]
|
||||
pub enum RenderGraphError {
|
||||
#[error("Node does not exist")]
|
||||
InvalidNode(NodeLabel),
|
||||
#[error("Node slot does not exist")]
|
||||
InvalidNodeSlot(SlotLabel),
|
||||
#[error("Node does not match the given type")]
|
||||
WrongNodeType,
|
||||
#[error("Attempted to connect a node output slot to an incompatible input node slot")]
|
||||
MismatchedNodeSlots {
|
||||
output_node: NodeId,
|
||||
output_slot: usize,
|
||||
input_node: NodeId,
|
||||
input_slot: usize,
|
||||
},
|
||||
#[error("Attempted to add an edge that already exists")]
|
||||
EdgeAlreadyExists(Edge),
|
||||
#[error("Node has an unconnected input slot.")]
|
||||
UnconnectedNodeInputSlot { node: NodeId, input_slot: usize },
|
||||
#[error("Node has an unconnected output slot.")]
|
||||
UnconnectedNodeOutputSlot { node: NodeId, output_slot: usize },
|
||||
#[error("Node input slot already occupied")]
|
||||
NodeInputSlotAlreadyOccupied { node: NodeId, input_slot: usize, occupied_by_node: NodeId },
|
||||
}
|
|
@ -5,8 +5,6 @@ mod render_resource;
|
|||
mod render_resource_assignments;
|
||||
mod resource_info;
|
||||
pub mod resource_name;
|
||||
mod resource_provider;
|
||||
pub mod resource_providers;
|
||||
|
||||
pub use batching::*;
|
||||
pub use buffer::*;
|
||||
|
@ -14,4 +12,3 @@ pub use entity_render_resource_assignments::*;
|
|||
pub use render_resource::*;
|
||||
pub use render_resource_assignments::*;
|
||||
pub use resource_info::*;
|
||||
pub use resource_provider::*;
|
||||
|
|
|
@ -1,38 +0,0 @@
|
|||
use crate::renderer_2::RenderContext;
|
||||
use legion::prelude::*;
|
||||
|
||||
pub trait ResourceProvider {
|
||||
fn initialize(
|
||||
&mut self,
|
||||
_renderer: &mut dyn RenderContext,
|
||||
_world: &mut World,
|
||||
_resources: &Resources,
|
||||
) {
|
||||
}
|
||||
|
||||
fn update(
|
||||
&mut self,
|
||||
_render_context: &mut dyn RenderContext,
|
||||
_world: &World,
|
||||
_resources: &Resources,
|
||||
) {
|
||||
}
|
||||
|
||||
// TODO: remove this
|
||||
fn finish_update(
|
||||
&mut self,
|
||||
_render_context: &mut dyn RenderContext,
|
||||
_world: &mut World,
|
||||
_resources: &Resources,
|
||||
) {
|
||||
}
|
||||
|
||||
/// Runs after resources have been created on the gpu. In general systems here write gpu-related resources back to entities in this step
|
||||
fn post_update(
|
||||
&mut self,
|
||||
_render_context: &dyn RenderContext,
|
||||
_world: &mut World,
|
||||
_resources: &Resources,
|
||||
) {
|
||||
}
|
||||
}
|
|
@ -1,55 +0,0 @@
|
|||
use crate::{
|
||||
render_resource::{RenderResourceAssignments, ResourceProvider},
|
||||
renderer_2::RenderContext,
|
||||
texture::TextureDescriptor,
|
||||
};
|
||||
|
||||
use bevy_window::Windows;
|
||||
use legion::prelude::*;
|
||||
|
||||
pub struct FrameTextureResourceProvider {
|
||||
pub name: String,
|
||||
pub descriptor: TextureDescriptor,
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
}
|
||||
|
||||
impl FrameTextureResourceProvider {
|
||||
pub fn new(name: &str, descriptor: TextureDescriptor) -> Self {
|
||||
FrameTextureResourceProvider {
|
||||
name: name.to_string(),
|
||||
descriptor,
|
||||
width: 0,
|
||||
height: 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ResourceProvider for FrameTextureResourceProvider {
|
||||
fn update(
|
||||
&mut self,
|
||||
render_context: &mut dyn RenderContext,
|
||||
_world: &World,
|
||||
resources: &Resources,
|
||||
) {
|
||||
let windows = resources.get::<Windows>().unwrap();
|
||||
let window = windows.get_primary().unwrap();
|
||||
|
||||
if self.descriptor.size.width != window.width
|
||||
|| self.descriptor.size.height != window.height
|
||||
{
|
||||
self.descriptor.size.width = window.width;
|
||||
self.descriptor.size.height = window.height;
|
||||
|
||||
let mut render_resource_assignments =
|
||||
resources.get_mut::<RenderResourceAssignments>().unwrap();
|
||||
let render_resources = render_context.resources_mut();
|
||||
if let Some(old_resource) = render_resource_assignments.get(&self.name) {
|
||||
render_resources.remove_texture(old_resource);
|
||||
}
|
||||
|
||||
let texture_resource = render_resources.create_texture(&self.descriptor);
|
||||
render_resource_assignments.set(&self.name, texture_resource);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,132 +0,0 @@
|
|||
use crate::{
|
||||
render_resource::{
|
||||
resource_name, BufferInfo, BufferUsage, RenderResource, RenderResourceAssignments,
|
||||
ResourceProvider,
|
||||
},
|
||||
renderer_2::RenderContext,
|
||||
Light, LightRaw,
|
||||
};
|
||||
use bevy_transform::prelude::{LocalToWorld, Translation};
|
||||
use legion::prelude::*;
|
||||
use zerocopy::AsBytes;
|
||||
|
||||
pub struct LightResourceProvider {
|
||||
pub lights_are_dirty: bool,
|
||||
pub max_lights: usize,
|
||||
pub light_buffer: Option<RenderResource>,
|
||||
pub tmp_light_buffer: Option<RenderResource>,
|
||||
pub tmp_count_buffer: Option<RenderResource>,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[derive(Clone, Copy, AsBytes)]
|
||||
pub struct LightCount {
|
||||
pub num_lights: [u32; 4],
|
||||
}
|
||||
|
||||
impl LightResourceProvider {
|
||||
pub fn new(max_lights: usize) -> Self {
|
||||
LightResourceProvider {
|
||||
lights_are_dirty: true,
|
||||
max_lights,
|
||||
light_buffer: None,
|
||||
tmp_light_buffer: None,
|
||||
tmp_count_buffer: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ResourceProvider for LightResourceProvider {
|
||||
fn initialize(
|
||||
&mut self,
|
||||
render_context: &mut dyn RenderContext,
|
||||
_world: &mut World,
|
||||
resources: &Resources,
|
||||
) {
|
||||
let light_uniform_size =
|
||||
std::mem::size_of::<LightCount>() + self.max_lights * std::mem::size_of::<LightRaw>();
|
||||
|
||||
let buffer = render_context.resources_mut().create_buffer(BufferInfo {
|
||||
size: light_uniform_size,
|
||||
buffer_usage: BufferUsage::UNIFORM | BufferUsage::COPY_SRC | BufferUsage::COPY_DST,
|
||||
..Default::default()
|
||||
});
|
||||
let mut render_resource_assignments =
|
||||
resources.get_mut::<RenderResourceAssignments>().unwrap();
|
||||
render_resource_assignments.set(resource_name::uniform::LIGHTS, buffer);
|
||||
self.light_buffer = Some(buffer);
|
||||
}
|
||||
|
||||
fn update(
|
||||
&mut self,
|
||||
render_context: &mut dyn RenderContext,
|
||||
world: &World,
|
||||
_resources: &Resources,
|
||||
) {
|
||||
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 = std::mem::size_of::<LightRaw>();
|
||||
let total_size = size * light_count;
|
||||
let light_count_size = std::mem::size_of::<LightCount>();
|
||||
let render_resources = render_context.resources_mut();
|
||||
|
||||
if let Some(old_tmp_light_buffer) = self.tmp_light_buffer {
|
||||
render_resources.remove_buffer(old_tmp_light_buffer);
|
||||
}
|
||||
|
||||
if let Some(old_tmp_count_buffer) = self.tmp_count_buffer {
|
||||
render_resources.remove_buffer(old_tmp_count_buffer);
|
||||
}
|
||||
|
||||
self.tmp_light_buffer = Some(render_resources.create_buffer_mapped(
|
||||
BufferInfo {
|
||||
size: total_size,
|
||||
buffer_usage: BufferUsage::COPY_SRC,
|
||||
..Default::default()
|
||||
},
|
||||
&mut |data, _renderer| {
|
||||
for ((light, local_to_world, translation), slot) in
|
||||
light_query.iter(world).zip(data.chunks_exact_mut(size))
|
||||
{
|
||||
slot.copy_from_slice(
|
||||
LightRaw::from(&light, &local_to_world.0, &translation).as_bytes(),
|
||||
);
|
||||
}
|
||||
},
|
||||
));
|
||||
self.tmp_count_buffer = Some(render_resources.create_buffer_mapped(
|
||||
BufferInfo {
|
||||
size: light_count_size,
|
||||
buffer_usage: BufferUsage::COPY_SRC,
|
||||
..Default::default()
|
||||
},
|
||||
&mut |data, _renderer| {
|
||||
data.copy_from_slice([light_count as u32, 0, 0, 0].as_bytes());
|
||||
},
|
||||
));
|
||||
|
||||
render_context.copy_buffer_to_buffer(
|
||||
self.tmp_count_buffer.unwrap(),
|
||||
0,
|
||||
self.light_buffer.unwrap(),
|
||||
0,
|
||||
light_count_size as u64,
|
||||
);
|
||||
|
||||
render_context.copy_buffer_to_buffer(
|
||||
self.tmp_light_buffer.unwrap(),
|
||||
0,
|
||||
self.light_buffer.unwrap(),
|
||||
light_count_size as u64,
|
||||
total_size as u64,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,96 +0,0 @@
|
|||
use crate::{
|
||||
mesh::{self, Mesh},
|
||||
pipeline::{state_descriptors::IndexFormat, VertexBufferDescriptor, VertexBufferDescriptors},
|
||||
render_resource::{AssetBatchers, BufferInfo, BufferUsage, RenderResourceAssignments},
|
||||
renderer_2::{GlobalRenderResourceContext, RenderResourceContext},
|
||||
shader::AsUniforms,
|
||||
Renderable, Vertex,
|
||||
};
|
||||
use bevy_asset::{AssetStorage, Handle};
|
||||
use legion::prelude::*;
|
||||
|
||||
fn setup_mesh_resource(
|
||||
render_resources: &dyn RenderResourceContext,
|
||||
render_resource_assignments: &mut RenderResourceAssignments,
|
||||
vertex_buffer_descriptor: &VertexBufferDescriptor,
|
||||
handle: Handle<Mesh>,
|
||||
meshes: &AssetStorage<Mesh>,
|
||||
) {
|
||||
log::trace!("setup mesh for {:?}", render_resource_assignments.id);
|
||||
let index_format = IndexFormat::Uint16;
|
||||
let (vertex_buffer, index_buffer) = if let Some(vertex_buffer) =
|
||||
render_resources.get_asset_resource(handle, mesh::VERTEX_BUFFER_ASSET_INDEX)
|
||||
{
|
||||
(
|
||||
vertex_buffer,
|
||||
render_resources.get_asset_resource(handle, mesh::INDEX_BUFFER_ASSET_INDEX),
|
||||
)
|
||||
} else {
|
||||
let mesh_asset = meshes.get(&handle).unwrap();
|
||||
let vertex_bytes = mesh_asset
|
||||
.get_vertex_buffer_bytes(&vertex_buffer_descriptor)
|
||||
.unwrap();
|
||||
// TODO: use a staging buffer here
|
||||
let vertex_buffer = render_resources.create_buffer_with_data(
|
||||
BufferInfo {
|
||||
buffer_usage: BufferUsage::VERTEX,
|
||||
..Default::default()
|
||||
},
|
||||
&vertex_bytes,
|
||||
);
|
||||
let index_bytes = mesh_asset.get_index_buffer_bytes(index_format).unwrap();
|
||||
let index_buffer = render_resources.create_buffer_with_data(
|
||||
BufferInfo {
|
||||
buffer_usage: BufferUsage::INDEX,
|
||||
..Default::default()
|
||||
},
|
||||
&index_bytes,
|
||||
);
|
||||
|
||||
render_resources.set_asset_resource(handle, vertex_buffer, mesh::VERTEX_BUFFER_ASSET_INDEX);
|
||||
render_resources.set_asset_resource(handle, index_buffer, mesh::INDEX_BUFFER_ASSET_INDEX);
|
||||
(vertex_buffer, Some(index_buffer))
|
||||
};
|
||||
|
||||
render_resource_assignments.set_vertex_buffer("Vertex", vertex_buffer, index_buffer);
|
||||
}
|
||||
|
||||
pub fn mesh_resource_provider_system(resources: &mut Resources) -> Box<dyn Schedulable> {
|
||||
let mut vertex_buffer_descriptors = resources.get_mut::<VertexBufferDescriptors>().unwrap();
|
||||
// TODO: allow pipelines to specialize on vertex_buffer_descriptor and index_format
|
||||
let vertex_buffer_descriptor = Vertex::get_vertex_buffer_descriptor().unwrap();
|
||||
vertex_buffer_descriptors.set(vertex_buffer_descriptor.clone());
|
||||
SystemBuilder::new("mesh_resource_provider")
|
||||
.read_resource::<GlobalRenderResourceContext>()
|
||||
.read_resource::<AssetStorage<Mesh>>()
|
||||
.write_resource::<AssetBatchers>()
|
||||
.with_query(<(Read<Handle<Mesh>>, Write<Renderable>)>::query())
|
||||
.build(
|
||||
move |_, world, (render_resource_context, meshes, asset_batchers), query| {
|
||||
let render_resources = &*render_resource_context.context;
|
||||
if let Some(batches) = asset_batchers.get_handle_batches_mut::<Mesh>() {
|
||||
for batch in batches {
|
||||
let handle = batch.get_handle::<Mesh>().unwrap();
|
||||
setup_mesh_resource(
|
||||
render_resources,
|
||||
&mut batch.render_resource_assignments,
|
||||
&vertex_buffer_descriptor,
|
||||
handle,
|
||||
&meshes,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: remove this once batches are pipeline specific and deprecate assigned_meshes draw target
|
||||
for (handle, mut renderable) in query.iter_mut(world) {
|
||||
setup_mesh_resource(
|
||||
render_resources,
|
||||
&mut renderable.render_resource_assignments,
|
||||
&vertex_buffer_descriptor,
|
||||
*handle,
|
||||
&meshes,
|
||||
);
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
|
@ -1,9 +0,0 @@
|
|||
mod frame_texture_resource_provider;
|
||||
mod light_resource_provider;
|
||||
mod mesh_resource_provider;
|
||||
mod uniform_resource_provider;
|
||||
|
||||
pub use frame_texture_resource_provider::*;
|
||||
pub use light_resource_provider::*;
|
||||
pub use mesh_resource_provider::*;
|
||||
pub use uniform_resource_provider::*;
|
|
@ -1,799 +0,0 @@
|
|||
use crate::{
|
||||
pipeline::VertexBufferDescriptors,
|
||||
render_resource::{
|
||||
AssetBatchers, BufferArrayInfo, BufferInfo, BufferUsage, RenderResource,
|
||||
RenderResourceAssignments, RenderResourceAssignmentsId, ResourceInfo, ResourceProvider,
|
||||
},
|
||||
renderer_2::{RenderContext, RenderResourceContext},
|
||||
shader::{AsUniforms, FieldBindType},
|
||||
texture::{self, SamplerDescriptor, Texture, TextureDescriptor},
|
||||
Renderable,
|
||||
};
|
||||
use bevy_asset::{AssetStorage, Handle};
|
||||
use legion::{filter::*, prelude::*};
|
||||
use std::{collections::HashMap, marker::PhantomData};
|
||||
pub const BIND_BUFFER_ALIGNMENT: usize = 256;
|
||||
|
||||
#[derive(Debug)]
|
||||
struct BufferArrayStatus {
|
||||
new_item_count: usize,
|
||||
item_size: usize,
|
||||
aligned_size: usize,
|
||||
staging_buffer_offset: usize,
|
||||
queued_buffer_writes: Vec<QueuedBufferWrite>,
|
||||
buffer: Option<RenderResource>,
|
||||
|
||||
current_item_count: usize,
|
||||
current_item_capacity: usize,
|
||||
indices: HashMap<RenderResourceAssignmentsId, usize>,
|
||||
current_index: usize,
|
||||
}
|
||||
|
||||
impl BufferArrayStatus {
|
||||
pub fn get_or_assign_index(&mut self, id: RenderResourceAssignmentsId) -> usize {
|
||||
if let Some(offset) = self.indices.get(&id) {
|
||||
*offset
|
||||
} else {
|
||||
if self.current_index == self.current_item_capacity {
|
||||
panic!("no empty slots available in array");
|
||||
}
|
||||
|
||||
let index = self.current_index;
|
||||
self.indices.insert(id, index);
|
||||
self.current_index += 1;
|
||||
index
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct QueuedBufferWrite {
|
||||
buffer: RenderResource,
|
||||
offset: usize,
|
||||
}
|
||||
|
||||
// TODO: make these queries only update changed T components
|
||||
type UniformQueryRead<T> = Query<
|
||||
(Read<T>, Read<Renderable>),
|
||||
EntityFilterTuple<
|
||||
And<(ComponentFilter<T>, ComponentFilter<Renderable>)>,
|
||||
And<(Passthrough, Passthrough)>,
|
||||
And<(Passthrough, Passthrough)>,
|
||||
>,
|
||||
>;
|
||||
|
||||
type UniformQuery<T> = Query<
|
||||
(Read<T>, Write<Renderable>),
|
||||
EntityFilterTuple<
|
||||
And<(ComponentFilter<T>, ComponentFilter<Renderable>)>,
|
||||
And<(Passthrough, Passthrough)>,
|
||||
And<(Passthrough, Passthrough)>,
|
||||
>,
|
||||
>;
|
||||
|
||||
type UniformHandleQueryRead<T> = Query<
|
||||
(Read<Handle<T>>, Read<Renderable>),
|
||||
EntityFilterTuple<
|
||||
And<(ComponentFilter<Handle<T>>, ComponentFilter<Renderable>)>,
|
||||
And<(Passthrough, Passthrough)>,
|
||||
And<(Passthrough, Passthrough)>,
|
||||
>,
|
||||
>;
|
||||
|
||||
type UniformHandleQuery<T> = Query<
|
||||
(Read<Handle<T>>, Write<Renderable>),
|
||||
EntityFilterTuple<
|
||||
And<(ComponentFilter<Handle<T>>, ComponentFilter<Renderable>)>,
|
||||
And<(Passthrough, Passthrough)>,
|
||||
And<(Passthrough, Passthrough)>,
|
||||
>,
|
||||
>;
|
||||
|
||||
// TODO: rename to RenderResourceProvider
|
||||
pub struct UniformResourceProvider<T>
|
||||
where
|
||||
T: AsUniforms + Send + Sync + 'static,
|
||||
{
|
||||
_marker: PhantomData<T>,
|
||||
use_dynamic_uniforms: bool,
|
||||
is_instanceable: bool,
|
||||
// PERF: somehow remove this HashSet
|
||||
uniform_buffer_status: Vec<Option<(String, BufferArrayStatus)>>,
|
||||
instance_buffer_status: Option<BufferArrayStatus>,
|
||||
query: Option<UniformQueryRead<T>>,
|
||||
query_finish: Option<UniformQuery<T>>,
|
||||
handle_query: Option<UniformHandleQueryRead<T>>,
|
||||
handle_query_finish: Option<UniformHandleQuery<T>>,
|
||||
}
|
||||
|
||||
impl<T> UniformResourceProvider<T>
|
||||
where
|
||||
T: AsUniforms + Send + Sync + 'static,
|
||||
{
|
||||
pub fn new(use_dynamic_uniforms: bool) -> Self {
|
||||
let mut dynamic_uniform_buffer_status = Vec::new();
|
||||
let field_infos = T::get_field_infos();
|
||||
dynamic_uniform_buffer_status.resize_with(field_infos.len(), || None);
|
||||
let is_instanceable = field_infos.iter().find(|f| f.is_instanceable).is_some();
|
||||
UniformResourceProvider {
|
||||
uniform_buffer_status: dynamic_uniform_buffer_status,
|
||||
use_dynamic_uniforms,
|
||||
instance_buffer_status: None,
|
||||
is_instanceable,
|
||||
query: Some(<(Read<T>, Read<Renderable>)>::query()),
|
||||
query_finish: Some(<(Read<T>, Write<Renderable>)>::query()),
|
||||
handle_query: Some(<(Read<Handle<T>>, Read<Renderable>)>::query()),
|
||||
handle_query_finish: Some(<(Read<Handle<T>>, Write<Renderable>)>::query()),
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
|
||||
fn reset_buffer_array_status_counts(&mut self) {
|
||||
for buffer_status in self.uniform_buffer_status.iter_mut() {
|
||||
if let Some((_name, buffer_status)) = buffer_status {
|
||||
buffer_status.new_item_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ref mut buffer_status) = self.instance_buffer_status {
|
||||
buffer_status.new_item_count = 0;
|
||||
}
|
||||
}
|
||||
|
||||
fn update_uniforms_info(&mut self, world: &World) {
|
||||
let query = self.query.take().unwrap();
|
||||
for (uniforms, renderable) in query.iter(world) {
|
||||
if !renderable.is_visible {
|
||||
return;
|
||||
}
|
||||
|
||||
if renderable.is_instanced {
|
||||
if self.is_instanceable {
|
||||
self.increment_instance_count(|| Self::get_instance_size(&uniforms));
|
||||
} else {
|
||||
panic!(
|
||||
"Cannot instance uniforms of type {}",
|
||||
std::any::type_name::<T>()
|
||||
);
|
||||
}
|
||||
} else {
|
||||
self.increment_uniform_counts(&uniforms);
|
||||
}
|
||||
}
|
||||
|
||||
self.query = Some(query);
|
||||
}
|
||||
|
||||
fn update_uniform_handles_info(&mut self, world: &World, resources: &Resources) {
|
||||
let handle_query = self.handle_query.take().unwrap();
|
||||
let assets = resources.get::<AssetStorage<T>>();
|
||||
if let Some(assets) = assets {
|
||||
for (handle, renderable) in handle_query.iter(world) {
|
||||
if !renderable.is_visible {
|
||||
return;
|
||||
}
|
||||
|
||||
if renderable.is_instanced {
|
||||
if self.is_instanceable {
|
||||
self.increment_instance_count(|| {
|
||||
let uniforms = assets.get(&handle).unwrap();
|
||||
Self::get_instance_size(uniforms)
|
||||
});
|
||||
} else {
|
||||
panic!(
|
||||
"Cannot instance uniforms of type Handle<{}>",
|
||||
std::any::type_name::<T>()
|
||||
);
|
||||
}
|
||||
} else {
|
||||
let uniforms = assets
|
||||
.get(&handle)
|
||||
.expect("Handle points to a non-existent resource");
|
||||
// TODO: only increment count if we haven't seen this uniform handle before
|
||||
self.increment_uniform_counts(&uniforms);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.handle_query = Some(handle_query);
|
||||
}
|
||||
|
||||
fn increment_instance_count(&mut self, f: impl Fn() -> usize) {
|
||||
if let Some(ref mut buffer_array_status) = self.instance_buffer_status {
|
||||
buffer_array_status.new_item_count += 1;
|
||||
} else {
|
||||
self.instance_buffer_status = Some(BufferArrayStatus {
|
||||
new_item_count: 1,
|
||||
queued_buffer_writes: Vec::new(),
|
||||
aligned_size: 0,
|
||||
item_size: f(),
|
||||
staging_buffer_offset: 0,
|
||||
buffer: None,
|
||||
current_index: 0,
|
||||
current_item_capacity: 0,
|
||||
current_item_count: 0,
|
||||
indices: HashMap::new(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn get_instance_size(uniforms: &T) -> usize {
|
||||
let mut instance_buffer_size = 0;
|
||||
for field_info in T::get_field_infos().iter() {
|
||||
if field_info.is_instanceable {
|
||||
if let Some(FieldBindType::Uniform { size }) =
|
||||
uniforms.get_field_bind_type(field_info.name)
|
||||
{
|
||||
instance_buffer_size += size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
instance_buffer_size
|
||||
}
|
||||
|
||||
fn increment_uniform_counts(&mut self, uniforms: &T) {
|
||||
for (i, field_info) in T::get_field_infos().iter().enumerate() {
|
||||
if let Some(FieldBindType::Uniform { size }) =
|
||||
uniforms.get_field_bind_type(&field_info.name)
|
||||
{
|
||||
if let Some((ref _name, ref mut buffer_array_status)) =
|
||||
self.uniform_buffer_status[i]
|
||||
{
|
||||
buffer_array_status.new_item_count += 1;
|
||||
} else {
|
||||
self.uniform_buffer_status[i] = Some((
|
||||
field_info.uniform_name.to_string(),
|
||||
BufferArrayStatus {
|
||||
new_item_count: 1,
|
||||
queued_buffer_writes: Vec::new(),
|
||||
aligned_size: Self::get_aligned_dynamic_uniform_size(size),
|
||||
item_size: size,
|
||||
staging_buffer_offset: 0,
|
||||
buffer: None,
|
||||
current_index: 0,
|
||||
current_item_count: 0,
|
||||
current_item_capacity: 0,
|
||||
indices: HashMap::new(),
|
||||
},
|
||||
))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn get_aligned_dynamic_uniform_size(data_size: usize) -> usize {
|
||||
BIND_BUFFER_ALIGNMENT * ((data_size as f32 / BIND_BUFFER_ALIGNMENT as f32).ceil() as usize)
|
||||
}
|
||||
|
||||
fn setup_uniform_buffer_resources(
|
||||
&mut self,
|
||||
uniforms: &T,
|
||||
render_resources: &dyn RenderResourceContext,
|
||||
render_resource_assignments: &mut RenderResourceAssignments,
|
||||
staging_buffer: &mut [u8],
|
||||
) {
|
||||
for (i, field_info) in T::get_field_infos().iter().enumerate() {
|
||||
let bind_type = uniforms.get_field_bind_type(&field_info.name);
|
||||
match bind_type {
|
||||
Some(FieldBindType::Uniform { size }) => {
|
||||
let (_name, uniform_buffer_status) =
|
||||
self.uniform_buffer_status[i].as_mut().unwrap();
|
||||
let (target_buffer, target_offset) = if self.use_dynamic_uniforms {
|
||||
let buffer = uniform_buffer_status.buffer.unwrap();
|
||||
let mut offset = 0;
|
||||
render_resources.get_resource_info(buffer, &mut |resource_info| {
|
||||
if let Some(ResourceInfo::Buffer(BufferInfo {
|
||||
array_info: Some(ref array_info),
|
||||
is_dynamic: true,
|
||||
..
|
||||
})) = resource_info
|
||||
{
|
||||
let index = uniform_buffer_status
|
||||
.get_or_assign_index(render_resource_assignments.id);
|
||||
render_resource_assignments.set_indexed(
|
||||
&field_info.uniform_name,
|
||||
buffer,
|
||||
(index * array_info.item_size) as u32,
|
||||
);
|
||||
offset = index * uniform_buffer_status.aligned_size;
|
||||
} else {
|
||||
panic!("Expected a dynamic uniform buffer");
|
||||
}
|
||||
});
|
||||
(buffer, offset)
|
||||
} else {
|
||||
let resource = match render_resource_assignments
|
||||
.get(field_info.uniform_name)
|
||||
{
|
||||
Some(render_resource) => render_resource,
|
||||
None => {
|
||||
let resource = render_resources.create_buffer(BufferInfo {
|
||||
size,
|
||||
buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM,
|
||||
..Default::default()
|
||||
});
|
||||
render_resource_assignments.set(&field_info.uniform_name, resource);
|
||||
resource
|
||||
}
|
||||
};
|
||||
|
||||
(resource, 0)
|
||||
};
|
||||
|
||||
let staging_buffer_start = uniform_buffer_status.staging_buffer_offset
|
||||
+ (uniform_buffer_status.queued_buffer_writes.len()
|
||||
* uniform_buffer_status.item_size);
|
||||
if let Some(uniform_bytes) =
|
||||
uniforms.get_uniform_bytes_ref(&field_info.uniform_name)
|
||||
{
|
||||
if size != uniform_bytes.len() {
|
||||
panic!("The number of bytes produced for {} do not match the expected count. Actual: {}. Expected: {}.", field_info.uniform_name, uniform_bytes.len(), size);
|
||||
}
|
||||
|
||||
staging_buffer
|
||||
[staging_buffer_start..(staging_buffer_start + uniform_bytes.len())]
|
||||
.copy_from_slice(uniform_bytes);
|
||||
} else if let Some(uniform_bytes) =
|
||||
uniforms.get_uniform_bytes(field_info.uniform_name)
|
||||
{
|
||||
if size != uniform_bytes.len() {
|
||||
panic!("The number of bytes produced for {} do not match the expected count. Actual: {}. Expected: {}.", field_info.uniform_name, uniform_bytes.len(), size);
|
||||
}
|
||||
|
||||
staging_buffer
|
||||
[staging_buffer_start..(staging_buffer_start + uniform_bytes.len())]
|
||||
.copy_from_slice(&uniform_bytes);
|
||||
} else {
|
||||
panic!(
|
||||
"failed to get data from uniform: {}",
|
||||
field_info.uniform_name
|
||||
);
|
||||
};
|
||||
|
||||
uniform_buffer_status
|
||||
.queued_buffer_writes
|
||||
.push(QueuedBufferWrite {
|
||||
buffer: target_buffer,
|
||||
offset: target_offset,
|
||||
});
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn setup_uniform_texture_resources(
|
||||
&mut self,
|
||||
uniforms: &T,
|
||||
render_context: &mut dyn RenderContext,
|
||||
resources: &Resources,
|
||||
render_resource_assignments: &mut RenderResourceAssignments,
|
||||
) {
|
||||
for field_info in T::get_field_infos().iter() {
|
||||
let bind_type = uniforms.get_field_bind_type(&field_info.name);
|
||||
match bind_type {
|
||||
Some(FieldBindType::Texture) => {
|
||||
let texture_handle = uniforms
|
||||
.get_uniform_texture(&field_info.texture_name)
|
||||
.unwrap();
|
||||
let (texture_resource, sampler_resource) = match render_context
|
||||
.resources()
|
||||
.get_asset_resource(texture_handle, texture::TEXTURE_ASSET_INDEX)
|
||||
{
|
||||
Some(texture_resource) => (
|
||||
texture_resource,
|
||||
render_context
|
||||
.resources()
|
||||
.get_asset_resource(texture_handle, texture::SAMPLER_ASSET_INDEX)
|
||||
.unwrap(),
|
||||
),
|
||||
None => {
|
||||
let storage = resources.get::<AssetStorage<Texture>>().unwrap();
|
||||
let texture = storage.get(&texture_handle).unwrap();
|
||||
|
||||
let texture_descriptor: TextureDescriptor = texture.into();
|
||||
let texture_resource = render_context
|
||||
.create_texture_with_data(&texture_descriptor, &texture.data);
|
||||
|
||||
let render_resources = render_context.resources_mut();
|
||||
let sampler_descriptor: SamplerDescriptor = texture.into();
|
||||
let sampler_resource =
|
||||
render_resources.create_sampler(&sampler_descriptor);
|
||||
|
||||
render_resources.set_asset_resource(
|
||||
texture_handle,
|
||||
texture_resource,
|
||||
0,
|
||||
);
|
||||
render_resources.set_asset_resource(
|
||||
texture_handle,
|
||||
sampler_resource,
|
||||
1,
|
||||
);
|
||||
(texture_resource, sampler_resource)
|
||||
}
|
||||
};
|
||||
|
||||
render_resource_assignments.set(field_info.texture_name, texture_resource);
|
||||
render_resource_assignments.set(field_info.sampler_name, sampler_resource);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: the current WgpuRenderContext mapped-memory interface forced these to be separate, but thats inefficient / redundant
|
||||
// try to merge setup_uniforms_buffer_resources and setup_uniforms_texture_resources if possible
|
||||
fn setup_uniforms_buffer_resources(
|
||||
&mut self,
|
||||
world: &mut World,
|
||||
render_resources: &dyn RenderResourceContext,
|
||||
staging_buffer: &mut [u8],
|
||||
) {
|
||||
let query_finish = self.query_finish.take().unwrap();
|
||||
for (uniforms, mut renderable) in query_finish.iter_mut(world) {
|
||||
if !renderable.is_visible {
|
||||
return;
|
||||
}
|
||||
|
||||
if renderable.is_instanced {
|
||||
panic!(
|
||||
"Cannot instance uniforms of type {0}. Only Handle<{0}> can be instanced.",
|
||||
std::any::type_name::<T>()
|
||||
);
|
||||
} else {
|
||||
self.setup_uniform_buffer_resources(
|
||||
&uniforms,
|
||||
render_resources,
|
||||
&mut renderable.render_resource_assignments,
|
||||
staging_buffer,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
self.query_finish = Some(query_finish);
|
||||
}
|
||||
|
||||
fn setup_uniforms_texture_resources(
|
||||
&mut self,
|
||||
world: &mut World,
|
||||
resources: &Resources,
|
||||
render_context: &mut dyn RenderContext,
|
||||
) {
|
||||
let query_finish = self.query_finish.take().unwrap();
|
||||
for (uniforms, mut renderable) in query_finish.iter_mut(world) {
|
||||
if !renderable.is_visible {
|
||||
return;
|
||||
}
|
||||
|
||||
if renderable.is_instanced {
|
||||
panic!(
|
||||
"Cannot instance uniforms of type {0}. Only Handle<{0}> can be instanced.",
|
||||
std::any::type_name::<T>()
|
||||
);
|
||||
} else {
|
||||
self.setup_uniform_texture_resources(
|
||||
&uniforms,
|
||||
render_context,
|
||||
resources,
|
||||
&mut renderable.render_resource_assignments,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
self.query_finish = Some(query_finish);
|
||||
}
|
||||
|
||||
fn setup_handles_buffer_resources(
|
||||
&mut self,
|
||||
world: &mut World,
|
||||
resources: &Resources,
|
||||
render_resources: &dyn RenderResourceContext,
|
||||
staging_buffer: &mut [u8],
|
||||
) {
|
||||
let assets = resources.get::<AssetStorage<T>>();
|
||||
if let Some(assets) = assets {
|
||||
let handle_query_finish = self.handle_query_finish.take().unwrap();
|
||||
for (handle, mut renderable) in handle_query_finish.iter_mut(world) {
|
||||
if !renderable.is_visible || renderable.is_instanced {
|
||||
return;
|
||||
}
|
||||
|
||||
let uniforms = assets
|
||||
.get(&handle)
|
||||
.expect("Handle points to a non-existent resource");
|
||||
// TODO: only setup buffer if we haven't seen this handle before
|
||||
self.setup_uniform_buffer_resources(
|
||||
&uniforms,
|
||||
render_resources,
|
||||
&mut renderable.render_resource_assignments,
|
||||
staging_buffer,
|
||||
);
|
||||
}
|
||||
|
||||
self.handle_query_finish = Some(handle_query_finish);
|
||||
}
|
||||
}
|
||||
|
||||
fn setup_handles_texture_resources(
|
||||
&mut self,
|
||||
world: &mut World,
|
||||
resources: &Resources,
|
||||
render_context: &mut dyn RenderContext,
|
||||
) {
|
||||
let assets = resources.get::<AssetStorage<T>>();
|
||||
if let Some(assets) = assets {
|
||||
let handle_query_finish = self.handle_query_finish.take().unwrap();
|
||||
for (handle, mut renderable) in handle_query_finish.iter_mut(world) {
|
||||
if !renderable.is_visible || renderable.is_instanced {
|
||||
return;
|
||||
}
|
||||
|
||||
let uniforms = assets
|
||||
.get(&handle)
|
||||
.expect("Handle points to a non-existent resource");
|
||||
self.setup_uniform_texture_resources(
|
||||
&uniforms,
|
||||
render_context,
|
||||
resources,
|
||||
&mut renderable.render_resource_assignments,
|
||||
)
|
||||
}
|
||||
|
||||
self.handle_query_finish = Some(handle_query_finish);
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
fn setup_batched_resources(
|
||||
&mut self,
|
||||
_world: &mut World,
|
||||
resources: &Resources,
|
||||
render_context: &mut dyn RenderContext,
|
||||
staging_buffer: &mut [u8],
|
||||
) {
|
||||
// update batch resources. this needs to run in "finish_update" because batches aren't finalized across
|
||||
// all members of the batch until "UniformResourceProvider.update" has run for all members of the batch
|
||||
if let Some(asset_storage) = resources.get::<AssetStorage<T>>() {
|
||||
let mut asset_batchers = resources.get_mut::<AssetBatchers>().unwrap();
|
||||
let handle_type = std::any::TypeId::of::<T>();
|
||||
for batch in asset_batchers.get_handle_batches_mut::<T>().unwrap() {
|
||||
let handle: Handle<T> = batch
|
||||
.handles
|
||||
.iter()
|
||||
.find(|h| h.type_id == handle_type)
|
||||
.map(|h| (*h).into())
|
||||
.unwrap();
|
||||
|
||||
if let Some(uniforms) = asset_storage.get(&handle) {
|
||||
self.setup_uniform_buffer_resources(
|
||||
&uniforms,
|
||||
render_context.resources_mut(),
|
||||
&mut batch.render_resource_assignments,
|
||||
staging_buffer,
|
||||
);
|
||||
self.setup_uniform_texture_resources(
|
||||
&uniforms,
|
||||
render_context,
|
||||
resources,
|
||||
&mut batch.render_resource_assignments,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn setup_buffer_arrays(&mut self, render_context: &mut dyn RenderContext) {
|
||||
for buffer_array_status in self.uniform_buffer_status.iter_mut() {
|
||||
if let Some((_name, buffer_array_status)) = buffer_array_status {
|
||||
if self.use_dynamic_uniforms {
|
||||
Self::setup_buffer_array(buffer_array_status, render_context, true);
|
||||
}
|
||||
|
||||
buffer_array_status.queued_buffer_writes =
|
||||
Vec::with_capacity(buffer_array_status.new_item_count);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ref mut buffer_array_status) = self.instance_buffer_status {
|
||||
Self::setup_buffer_array(buffer_array_status, render_context, false);
|
||||
}
|
||||
}
|
||||
|
||||
fn setup_buffer_array(
|
||||
buffer_array_status: &mut BufferArrayStatus,
|
||||
render_context: &mut dyn RenderContext,
|
||||
align: bool,
|
||||
) {
|
||||
let new_capacity = if let Some(buffer) = buffer_array_status.buffer {
|
||||
let mut new_capacity = None;
|
||||
render_context
|
||||
.resources()
|
||||
.get_resource_info(buffer, &mut |resource_info| {
|
||||
new_capacity = if let Some(ResourceInfo::Buffer(BufferInfo {
|
||||
array_info: Some(array_info),
|
||||
..
|
||||
})) = resource_info
|
||||
{
|
||||
if array_info.item_capacity < buffer_array_status.new_item_count {
|
||||
// over capacity. lets resize
|
||||
Some(
|
||||
buffer_array_status.new_item_count
|
||||
+ buffer_array_status.new_item_count / 2,
|
||||
)
|
||||
} else {
|
||||
// under capacity. no change needed
|
||||
None
|
||||
}
|
||||
} else {
|
||||
// incorrect resource type. overwrite with new buffer
|
||||
Some(buffer_array_status.new_item_count)
|
||||
};
|
||||
});
|
||||
new_capacity
|
||||
} else {
|
||||
// buffer does not exist. create it now.
|
||||
Some(buffer_array_status.new_item_count)
|
||||
};
|
||||
|
||||
if let Some(new_capacity) = new_capacity {
|
||||
let mut item_size = buffer_array_status.item_size;
|
||||
if align {
|
||||
item_size = Self::get_aligned_dynamic_uniform_size(item_size);
|
||||
}
|
||||
|
||||
let total_size = item_size * new_capacity;
|
||||
|
||||
let buffer = render_context.resources_mut().create_buffer(BufferInfo {
|
||||
array_info: Some(BufferArrayInfo {
|
||||
item_capacity: new_capacity,
|
||||
item_size,
|
||||
..Default::default()
|
||||
}),
|
||||
size: total_size,
|
||||
buffer_usage: BufferUsage::COPY_DST | BufferUsage::UNIFORM,
|
||||
is_dynamic: true,
|
||||
});
|
||||
|
||||
buffer_array_status.current_item_capacity = new_capacity;
|
||||
|
||||
log::trace!(
|
||||
"creating buffer for uniform {}. size: {} item_capacity: {} item_size: {}",
|
||||
std::any::type_name::<T>(),
|
||||
total_size,
|
||||
new_capacity,
|
||||
item_size
|
||||
);
|
||||
|
||||
buffer_array_status.buffer = Some(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
fn initialize_vertex_buffer_descriptor(
|
||||
&self,
|
||||
vertex_buffer_descriptors: &mut VertexBufferDescriptors,
|
||||
) {
|
||||
let vertex_buffer_descriptor = T::get_vertex_buffer_descriptor();
|
||||
if let Some(vertex_buffer_descriptor) = vertex_buffer_descriptor {
|
||||
if let None = vertex_buffer_descriptors.get(&vertex_buffer_descriptor.name) {
|
||||
vertex_buffer_descriptors.set(vertex_buffer_descriptor.clone());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn update_staging_buffer_offsets(&mut self) -> usize {
|
||||
let mut size = 0;
|
||||
for dynamic_buffer_array_status in self.uniform_buffer_status.iter_mut() {
|
||||
if let Some((_name, ref mut buffer_array_status)) = dynamic_buffer_array_status {
|
||||
buffer_array_status.staging_buffer_offset = size;
|
||||
size += buffer_array_status.item_size * buffer_array_status.new_item_count;
|
||||
}
|
||||
}
|
||||
|
||||
size
|
||||
}
|
||||
|
||||
fn copy_staging_buffer_to_final_buffers(
|
||||
&mut self,
|
||||
render_context: &mut dyn RenderContext,
|
||||
staging_buffer: RenderResource,
|
||||
) {
|
||||
for uniform_buffer_status in self.uniform_buffer_status.iter_mut() {
|
||||
if let Some((_name, buffer_array_status)) = uniform_buffer_status {
|
||||
let start = buffer_array_status.staging_buffer_offset;
|
||||
for (i, queued_buffer_write) in buffer_array_status
|
||||
.queued_buffer_writes
|
||||
.drain(..)
|
||||
.enumerate()
|
||||
{
|
||||
render_context.copy_buffer_to_buffer(
|
||||
staging_buffer,
|
||||
(start + (i * buffer_array_status.item_size)) as u64,
|
||||
queued_buffer_write.buffer,
|
||||
queued_buffer_write.offset as u64,
|
||||
buffer_array_status.item_size as u64,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<T> ResourceProvider for UniformResourceProvider<T>
|
||||
where
|
||||
T: AsUniforms + Send + Sync + 'static,
|
||||
{
|
||||
fn initialize(
|
||||
&mut self,
|
||||
render_context: &mut dyn RenderContext,
|
||||
world: &mut World,
|
||||
resources: &Resources,
|
||||
) {
|
||||
let mut vertex_buffer_descriptors = resources.get_mut::<VertexBufferDescriptors>().unwrap();
|
||||
self.initialize_vertex_buffer_descriptor(&mut vertex_buffer_descriptors);
|
||||
self.update(render_context, world, resources);
|
||||
}
|
||||
|
||||
fn update(
|
||||
&mut self,
|
||||
_render_context: &mut dyn RenderContext,
|
||||
world: &World,
|
||||
resources: &Resources,
|
||||
) {
|
||||
self.reset_buffer_array_status_counts();
|
||||
self.update_uniforms_info(world);
|
||||
self.update_uniform_handles_info(world, resources);
|
||||
}
|
||||
|
||||
fn finish_update(
|
||||
&mut self,
|
||||
render_context: &mut dyn RenderContext,
|
||||
world: &mut World,
|
||||
resources: &Resources,
|
||||
) {
|
||||
// TODO: when setting batch shader_defs, add INSTANCING
|
||||
self.setup_buffer_arrays(render_context);
|
||||
|
||||
let staging_buffer_size = self.update_staging_buffer_offsets();
|
||||
self.setup_uniforms_texture_resources(world, resources, render_context);
|
||||
self.setup_handles_texture_resources(world, resources, render_context);
|
||||
// self.setup_batched_texture_resources(world, resources, renderer, staging_buffer);
|
||||
if staging_buffer_size == 0 {
|
||||
let mut staging_buffer: [u8; 0] = [];
|
||||
self.setup_uniforms_buffer_resources(
|
||||
world,
|
||||
render_context.resources_mut(),
|
||||
&mut staging_buffer,
|
||||
);
|
||||
self.setup_handles_buffer_resources(
|
||||
world,
|
||||
resources,
|
||||
render_context.resources_mut(),
|
||||
&mut staging_buffer,
|
||||
);
|
||||
// self.setup_batched_buffer_resources(world, resources, renderer, &mut staging_buffer);
|
||||
} else {
|
||||
let staging_buffer = render_context.resources_mut().create_buffer_mapped(
|
||||
BufferInfo {
|
||||
buffer_usage: BufferUsage::COPY_SRC,
|
||||
size: staging_buffer_size,
|
||||
..Default::default()
|
||||
},
|
||||
&mut |staging_buffer, render_resources| {
|
||||
self.setup_uniforms_buffer_resources(world, render_resources, staging_buffer);
|
||||
self.setup_handles_buffer_resources(
|
||||
world,
|
||||
resources,
|
||||
render_resources,
|
||||
staging_buffer,
|
||||
);
|
||||
// self.setup_batched_buffer_resources(world, resources, renderer, staging_buffer);
|
||||
},
|
||||
);
|
||||
|
||||
self.copy_staging_buffer_to_final_buffers(render_context, staging_buffer);
|
||||
render_context.resources_mut().remove_buffer(staging_buffer);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,3 @@
|
|||
mod local_to_world;
|
||||
mod standard_material;
|
||||
|
||||
pub use local_to_world::*;
|
||||
pub use standard_material::*;
|
||||
|
|
61
bevy_ui/src/render/mod.rs
Normal file
61
bevy_ui/src/render/mod.rs
Normal file
|
@ -0,0 +1,61 @@
|
|||
// use crate::{
|
||||
// pipeline::state_descriptors::{
|
||||
// BlendDescriptor, BlendFactor, BlendOperation, ColorStateDescriptor, ColorWrite,
|
||||
// CompareFunction, CullMode, DepthStencilStateDescriptor, FrontFace,
|
||||
// RasterizationStateDescriptor, StencilStateFaceDescriptor,
|
||||
// },
|
||||
// render_graph::RenderGraphBuilder,
|
||||
// render_resource::resource_name,
|
||||
// shader::{Shader, ShaderStage},
|
||||
// texture::TextureFormat,
|
||||
// };
|
||||
// pub trait UiPipelineBuilder {
|
||||
// fn add_ui_pipeline(&mut self) -> &mut Self;
|
||||
// }
|
||||
|
||||
// impl<'a, 'b, 'c> UiPipelineBuilder for RenderGraphBuilder<'a, 'b, 'c> {
|
||||
// fn add_ui_pipeline(&mut self) -> &mut Self {
|
||||
// self.add_pipeline(resource_name::pipeline::UI, |builder| {
|
||||
// builder
|
||||
// .with_vertex_shader(Shader::from_glsl(
|
||||
// ShaderStage::Vertex,
|
||||
// include_str!("ui.vert"),
|
||||
// ))
|
||||
// .with_fragment_shader(Shader::from_glsl(
|
||||
// ShaderStage::Fragment,
|
||||
// include_str!("ui.frag"),
|
||||
// ))
|
||||
// .with_rasterization_state(RasterizationStateDescriptor {
|
||||
// front_face: FrontFace::Ccw,
|
||||
// cull_mode: CullMode::None,
|
||||
// depth_bias: 0,
|
||||
// depth_bias_slope_scale: 0.0,
|
||||
// depth_bias_clamp: 0.0,
|
||||
// })
|
||||
// .with_depth_stencil_state(DepthStencilStateDescriptor {
|
||||
// format: TextureFormat::Depth32Float,
|
||||
// depth_write_enabled: false,
|
||||
// depth_compare: CompareFunction::Always,
|
||||
// stencil_front: StencilStateFaceDescriptor::IGNORE,
|
||||
// stencil_back: StencilStateFaceDescriptor::IGNORE,
|
||||
// stencil_read_mask: 0,
|
||||
// stencil_write_mask: 0,
|
||||
// })
|
||||
// .add_color_state(ColorStateDescriptor {
|
||||
// format: TextureFormat::Bgra8UnormSrgb,
|
||||
// color_blend: BlendDescriptor {
|
||||
// src_factor: BlendFactor::SrcAlpha,
|
||||
// dst_factor: BlendFactor::OneMinusSrcAlpha,
|
||||
// operation: BlendOperation::Add,
|
||||
// },
|
||||
// alpha_blend: BlendDescriptor {
|
||||
// src_factor: BlendFactor::One,
|
||||
// dst_factor: BlendFactor::One,
|
||||
// operation: BlendOperation::Add,
|
||||
// },
|
||||
// write_mask: ColorWrite::ALL,
|
||||
// })
|
||||
// .add_draw_target(resource_name::draw_target::UI);
|
||||
// })
|
||||
// }
|
||||
// }
|
|
@ -1,4 +1,4 @@
|
|||
pub mod renderer_2;
|
||||
pub mod renderer;
|
||||
mod wgpu_render_pass;
|
||||
mod wgpu_renderer;
|
||||
mod wgpu_resources;
|
||||
|
@ -9,10 +9,10 @@ pub use wgpu_renderer::*;
|
|||
pub use wgpu_resources::*;
|
||||
|
||||
use bevy_app::{AppBuilder, AppPlugin, Events};
|
||||
use bevy_render::{renderer_2::GlobalRenderResourceContext, RENDER_STAGE};
|
||||
use bevy_render::{renderer::GlobalRenderResourceContext, RENDER_STAGE};
|
||||
use bevy_window::{WindowCreated, WindowResized};
|
||||
use legion::prelude::*;
|
||||
use renderer_2::WgpuRenderResourceContext;
|
||||
use renderer::WgpuRenderResourceContext;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct WgpuPlugin;
|
||||
|
|
|
@ -13,7 +13,7 @@ use bevy_render::{
|
|||
render_resource::{
|
||||
RenderResource, RenderResourceAssignments, RenderResourceSetId, ResourceInfo,
|
||||
},
|
||||
renderer_2::{RenderContext, RenderResourceContext},
|
||||
renderer::{RenderContext, RenderResourceContext},
|
||||
shader::Shader,
|
||||
texture::{Extent3d, TextureDescriptor},
|
||||
};
|
|
@ -1,7 +1,7 @@
|
|||
use super::{WgpuRenderContext, WgpuRenderResourceContext};
|
||||
use bevy_render::{
|
||||
render_graph_2::{Edge, NodeId, ResourceSlots, StageBorrow},
|
||||
renderer_2::GlobalRenderResourceContext,
|
||||
render_graph::{Edge, NodeId, ResourceSlots, StageBorrow},
|
||||
renderer::GlobalRenderResourceContext,
|
||||
};
|
||||
use legion::prelude::{Resources, World};
|
||||
use std::{collections::HashMap, sync::Arc};
|
|
@ -3,7 +3,7 @@ use crate::WgpuResources;
|
|||
use bevy_asset::{AssetStorage, Handle, HandleUntyped};
|
||||
use bevy_render::{
|
||||
render_resource::{BufferInfo, RenderResource, ResourceInfo},
|
||||
renderer_2::RenderResourceContext,
|
||||
renderer::RenderResourceContext,
|
||||
shader::Shader,
|
||||
texture::{SamplerDescriptor, TextureDescriptor},
|
||||
};
|
|
@ -1,4 +1,4 @@
|
|||
use crate::{renderer_2::WgpuRenderContext, WgpuResourceRefs};
|
||||
use crate::{renderer::WgpuRenderContext, WgpuResourceRefs};
|
||||
use bevy_asset::Handle;
|
||||
use bevy_render::{
|
||||
pass::RenderPass,
|
||||
|
@ -6,7 +6,7 @@ use bevy_render::{
|
|||
render_resource::{
|
||||
RenderResource, RenderResourceAssignments, RenderResourceSetId, ResourceInfo,
|
||||
},
|
||||
renderer_2::RenderContext,
|
||||
renderer::RenderContext,
|
||||
};
|
||||
use std::{collections::HashMap, ops::Range};
|
||||
|
||||
|
|
|
@ -1,14 +1,11 @@
|
|||
use crate::renderer_2::{
|
||||
render_resource_sets_system, WgpuRenderContext, WgpuRenderGraphExecutor,
|
||||
WgpuRenderResourceContext,
|
||||
use crate::renderer::{
|
||||
render_resource_sets_system, WgpuRenderGraphExecutor, WgpuRenderResourceContext,
|
||||
};
|
||||
use bevy_app::{EventReader, Events};
|
||||
use bevy_render::{
|
||||
pipeline::update_shader_assignments,
|
||||
render_graph::RenderGraph,
|
||||
render_graph_2::{DependentNodeStager, RenderGraph2, RenderGraphStager},
|
||||
render_resource::RenderResourceAssignments,
|
||||
renderer_2::{GlobalRenderResourceContext, RenderResourceContext},
|
||||
render_graph::{DependentNodeStager, RenderGraph, RenderGraphStager},
|
||||
renderer::GlobalRenderResourceContext,
|
||||
};
|
||||
use bevy_window::{WindowCreated, WindowResized, Windows};
|
||||
use legion::prelude::*;
|
||||
|
@ -54,117 +51,12 @@ impl WgpuRenderer {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn initialize_resource_providers(
|
||||
world: &mut World,
|
||||
resources: &Resources,
|
||||
render_context: &mut WgpuRenderContext,
|
||||
) {
|
||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||
for resource_provider in render_graph.resource_providers.iter_mut() {
|
||||
resource_provider.initialize(render_context, world, resources);
|
||||
}
|
||||
}
|
||||
|
||||
fn parallel_resource_provider_update(
|
||||
world: &World,
|
||||
resources: &Resources,
|
||||
device: Arc<wgpu::Device>,
|
||||
render_resource_context: &WgpuRenderResourceContext,
|
||||
) -> Vec<wgpu::CommandBuffer> {
|
||||
let max_thread_count = 8;
|
||||
let (sender, receiver) = crossbeam_channel::bounded(max_thread_count);
|
||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||
let chunk_size =
|
||||
(render_graph.resource_providers.len() + max_thread_count - 1) / max_thread_count; // divide ints rounding remainder up
|
||||
// println!("chunk {} {}", chunk_size, render_graph.resource_providers.len());
|
||||
let mut actual_thread_count = 0;
|
||||
crossbeam_utils::thread::scope(|s| {
|
||||
for resource_provider_chunk in render_graph.resource_providers.chunks_mut(chunk_size) {
|
||||
let device = device.clone();
|
||||
let sender = sender.clone();
|
||||
let world = &*world;
|
||||
let resources = &*resources;
|
||||
actual_thread_count += 1;
|
||||
let render_resource_context = render_resource_context.clone();
|
||||
s.spawn(move |_| {
|
||||
let mut render_context =
|
||||
WgpuRenderContext::new(device, render_resource_context);
|
||||
for resource_provider in resource_provider_chunk.iter_mut() {
|
||||
resource_provider.update(&mut render_context, world, resources);
|
||||
}
|
||||
sender.send(render_context.finish()).unwrap();
|
||||
});
|
||||
}
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let mut command_buffers = Vec::new();
|
||||
for _i in 0..actual_thread_count {
|
||||
let command_buffer = receiver.recv().unwrap();
|
||||
if let Some(command_buffer) = command_buffer {
|
||||
command_buffers.push(command_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
command_buffers
|
||||
}
|
||||
|
||||
pub fn update_resource_providers(
|
||||
&mut self,
|
||||
world: &mut World,
|
||||
resources: &Resources,
|
||||
render_resource_context: &WgpuRenderResourceContext,
|
||||
) {
|
||||
let mut command_buffers = Self::parallel_resource_provider_update(
|
||||
world,
|
||||
resources,
|
||||
self.device.clone(),
|
||||
render_resource_context,
|
||||
);
|
||||
|
||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||
let mut results = Vec::new();
|
||||
let thread_count = 5;
|
||||
let chunk_size = (render_graph.resource_providers.len() + thread_count - 1) / thread_count; // divide ints rounding remainder up
|
||||
// crossbeam_utils::thread::scope(|s| {
|
||||
for resource_provider_chunk in render_graph.resource_providers.chunks_mut(chunk_size) {
|
||||
let device = self.device.clone();
|
||||
let mut render_context =
|
||||
WgpuRenderContext::new(device, render_resource_context.clone());
|
||||
for resource_provider in resource_provider_chunk.iter_mut() {
|
||||
resource_provider.finish_update(&mut render_context, world, resources);
|
||||
}
|
||||
results.push(render_context.finish());
|
||||
}
|
||||
|
||||
for command_buffer in results {
|
||||
if let Some(command_buffer) = command_buffer {
|
||||
command_buffers.push(command_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
self.queue.submit(&command_buffers);
|
||||
}
|
||||
|
||||
pub fn create_queued_textures(
|
||||
&mut self,
|
||||
resources: &Resources,
|
||||
global_render_resources: &mut WgpuRenderResourceContext,
|
||||
) {
|
||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||
let mut render_resource_assignments =
|
||||
resources.get_mut::<RenderResourceAssignments>().unwrap();
|
||||
for (name, texture_descriptor) in render_graph.queued_textures.drain(..) {
|
||||
let resource = global_render_resources.create_texture(&texture_descriptor);
|
||||
render_resource_assignments.set(&name, resource);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn handle_window_created_events(
|
||||
&mut self,
|
||||
resources: &Resources,
|
||||
global_render_resource_context: &mut WgpuRenderResourceContext,
|
||||
) {
|
||||
pub fn handle_window_created_events(&mut self, resources: &Resources) {
|
||||
let mut global_context = resources.get_mut::<GlobalRenderResourceContext>().unwrap();
|
||||
let render_resource_context = global_context
|
||||
.context
|
||||
.downcast_mut::<WgpuRenderResourceContext>()
|
||||
.unwrap();
|
||||
let windows = resources.get::<Windows>().unwrap();
|
||||
let window_created_events = resources.get::<Events<WindowCreated>>().unwrap();
|
||||
for window_created_event in
|
||||
|
@ -178,7 +70,7 @@ impl WgpuRenderer {
|
|||
let winit_windows = resources.get::<bevy_winit::WinitWindows>().unwrap();
|
||||
let winit_window = winit_windows.get_window(window.id).unwrap();
|
||||
let surface = wgpu::Surface::create(winit_window.deref());
|
||||
global_render_resource_context
|
||||
render_resource_context
|
||||
.wgpu_resources
|
||||
.set_window_surface(window.id, surface);
|
||||
}
|
||||
|
@ -188,7 +80,7 @@ impl WgpuRenderer {
|
|||
pub fn run_graph(&mut self, world: &mut World, resources: &mut Resources) {
|
||||
// run systems
|
||||
let mut system_executor = {
|
||||
let mut render_graph = resources.get_mut::<RenderGraph2>().unwrap();
|
||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||
render_graph.take_executor()
|
||||
};
|
||||
|
||||
|
@ -199,7 +91,7 @@ impl WgpuRenderer {
|
|||
update_shader_assignments(world, resources);
|
||||
render_resource_sets_system().run(world, resources);
|
||||
|
||||
let mut render_graph = resources.get_mut::<RenderGraph2>().unwrap();
|
||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||
if let Some(executor) = system_executor.take() {
|
||||
render_graph.set_executor(executor);
|
||||
}
|
||||
|
@ -208,7 +100,7 @@ impl WgpuRenderer {
|
|||
let mut stager = DependentNodeStager::loose_grouping();
|
||||
let stages = stager.get_stages(&render_graph).unwrap();
|
||||
let mut borrowed = stages.borrow(&mut render_graph);
|
||||
|
||||
|
||||
// execute stages
|
||||
let graph_executor = WgpuRenderGraphExecutor {
|
||||
max_thread_count: 2,
|
||||
|
@ -223,31 +115,7 @@ impl WgpuRenderer {
|
|||
}
|
||||
|
||||
pub fn update(&mut self, world: &mut World, resources: &mut Resources) {
|
||||
{
|
||||
let mut global_context = resources.get_mut::<GlobalRenderResourceContext>().unwrap();
|
||||
let render_resource_context = global_context
|
||||
.context
|
||||
.downcast_mut::<WgpuRenderResourceContext>()
|
||||
.unwrap();
|
||||
|
||||
self.handle_window_created_events(resources, render_resource_context);
|
||||
|
||||
let mut render_context =
|
||||
WgpuRenderContext::new(self.device.clone(), render_resource_context.clone());
|
||||
if !self.intialized {
|
||||
Self::initialize_resource_providers(world, resources, &mut render_context);
|
||||
let buffer = render_context.finish();
|
||||
if let Some(buffer) = buffer {
|
||||
self.queue.submit(&[buffer]);
|
||||
}
|
||||
self.intialized = true;
|
||||
}
|
||||
|
||||
self.update_resource_providers(world, resources, render_resource_context);
|
||||
|
||||
self.create_queued_textures(resources, &mut render_context.render_resources);
|
||||
};
|
||||
|
||||
self.handle_window_created_events(resources);
|
||||
self.run_graph(world, resources);
|
||||
|
||||
let render_resource_context = resources.get::<GlobalRenderResourceContext>().unwrap();
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
use crate::{renderer_2::WgpuRenderResourceContext, wgpu_type_converter::WgpuInto};
|
||||
use crate::{renderer::WgpuRenderResourceContext, wgpu_type_converter::WgpuInto};
|
||||
use bevy_asset::{Handle, HandleUntyped};
|
||||
use bevy_render::{
|
||||
pipeline::{BindGroupDescriptorId, PipelineDescriptor},
|
||||
render_resource::{BufferInfo, RenderResource, RenderResourceSetId, ResourceInfo},
|
||||
renderer_2::RenderResourceContext,
|
||||
renderer::RenderResourceContext,
|
||||
shader::Shader,
|
||||
texture::{Extent3d, SamplerDescriptor, TextureDescriptor},
|
||||
};
|
||||
|
|
|
@ -12,54 +12,58 @@ struct MyMaterial {
|
|||
pub color: Color,
|
||||
}
|
||||
|
||||
fn add_shader_to_render_graph(resources: &mut Resources) {
|
||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||
let mut pipelines = resources
|
||||
.get_mut::<AssetStorage<PipelineDescriptor>>()
|
||||
.unwrap();
|
||||
let mut shaders = resources.get_mut::<AssetStorage<Shader>>().unwrap();
|
||||
|
||||
render_graph
|
||||
.build(&mut pipelines, &mut shaders)
|
||||
.add_resource_provider(UniformResourceProvider::<MyMaterial>::new(true))
|
||||
.add_pipeline_to_pass(resource_name::pass::MAIN, "MyMaterial", |builder| {
|
||||
builder
|
||||
.with_vertex_shader(Shader::from_glsl(
|
||||
ShaderStage::Vertex,
|
||||
r#"
|
||||
#version 450
|
||||
layout(location = 0) in vec3 Vertex_Position;
|
||||
layout(set = 0, binding = 0) uniform Camera {
|
||||
mat4 ViewProj;
|
||||
};
|
||||
layout(set = 1, binding = 0) uniform Object {
|
||||
mat4 Model;
|
||||
};
|
||||
void main() {
|
||||
gl_Position = ViewProj * Model * vec4(Vertex_Position, 1.0);
|
||||
}
|
||||
"#,
|
||||
))
|
||||
.with_fragment_shader(Shader::from_glsl(
|
||||
ShaderStage::Fragment,
|
||||
r#"
|
||||
#version 450
|
||||
layout(location = 0) out vec4 o_Target;
|
||||
layout(set = 1, binding = 1) uniform MyMaterial_color {
|
||||
vec4 color;
|
||||
};
|
||||
void main() {
|
||||
o_Target = color;
|
||||
}
|
||||
"#,
|
||||
))
|
||||
.with_default_config();
|
||||
});
|
||||
}
|
||||
|
||||
fn setup(world: &mut World, resources: &mut Resources) {
|
||||
// add our shader to the render graph
|
||||
add_shader_to_render_graph(resources);
|
||||
// create new shader pipeline and add to main pass in Render Graph
|
||||
let pipeline_handle = {
|
||||
let mut pipelines = resources
|
||||
.get_mut::<AssetStorage<PipelineDescriptor>>()
|
||||
.unwrap();
|
||||
let mut shaders = resources.get_mut::<AssetStorage<Shader>>().unwrap();
|
||||
|
||||
let pipeline_handle = pipelines.add(PipelineDescriptor::default_config(ShaderStages {
|
||||
vertex: shaders.add(Shader::from_glsl(
|
||||
ShaderStage::Vertex,
|
||||
r#"
|
||||
#version 450
|
||||
layout(location = 0) in vec3 Vertex_Position;
|
||||
layout(set = 0, binding = 0) uniform Camera {
|
||||
mat4 ViewProj;
|
||||
};
|
||||
layout(set = 1, binding = 0) uniform Object {
|
||||
mat4 Model;
|
||||
};
|
||||
void main() {
|
||||
gl_Position = ViewProj * Model * vec4(Vertex_Position, 1.0);
|
||||
}
|
||||
"#,
|
||||
)),
|
||||
fragment: Some(shaders.add(Shader::from_glsl(
|
||||
ShaderStage::Fragment,
|
||||
r#"
|
||||
#version 450
|
||||
layout(location = 0) out vec4 o_Target;
|
||||
layout(set = 1, binding = 1) uniform MyMaterial_color {
|
||||
vec4 color;
|
||||
};
|
||||
void main() {
|
||||
o_Target = color;
|
||||
}
|
||||
"#,
|
||||
))),
|
||||
}));
|
||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||
render_graph.add_system_node_named(
|
||||
"my_material",
|
||||
AssetUniformNode::<MyMaterial>::new(true),
|
||||
resources,
|
||||
);
|
||||
let main_pass: &mut PassNode = render_graph.get_node_mut("main_pass").unwrap();
|
||||
main_pass.add_pipeline(
|
||||
pipeline_handle,
|
||||
vec![Box::new(draw_target::AssignedMeshesDrawTarget)],
|
||||
);
|
||||
pipeline_handle
|
||||
};
|
||||
|
||||
// create materials
|
||||
let mut material_storage = AssetStorage::<MyMaterial>::new();
|
||||
|
@ -68,12 +72,6 @@ fn setup(world: &mut World, resources: &mut Resources) {
|
|||
});
|
||||
resources.insert(material_storage);
|
||||
|
||||
// get a handle to our newly created shader pipeline
|
||||
let mut pipeline_storage = resources
|
||||
.get_mut::<AssetStorage<PipelineDescriptor>>()
|
||||
.unwrap();
|
||||
let pipeline_handle = pipeline_storage.get_named("MyMaterial").unwrap();
|
||||
|
||||
let mut mesh_storage = resources.get_mut::<AssetStorage<Mesh>>().unwrap();
|
||||
let cube_handle = mesh_storage.add(Mesh::from(shape::Cube));
|
||||
|
||||
|
|
|
@ -18,58 +18,62 @@ struct MyMaterial {
|
|||
pub always_red: bool,
|
||||
}
|
||||
|
||||
fn add_shader_to_render_graph(resources: &mut Resources) {
|
||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||
let mut pipelines = resources
|
||||
.get_mut::<AssetStorage<PipelineDescriptor>>()
|
||||
.unwrap();
|
||||
let mut shaders = resources.get_mut::<AssetStorage<Shader>>().unwrap();
|
||||
|
||||
render_graph
|
||||
.build(&mut pipelines, &mut shaders)
|
||||
.add_resource_provider(UniformResourceProvider::<MyMaterial>::new(true))
|
||||
.add_pipeline_to_pass(resource_name::pass::MAIN, "MyMaterial", |builder| {
|
||||
builder
|
||||
.with_vertex_shader(Shader::from_glsl(
|
||||
ShaderStage::Vertex,
|
||||
r#"
|
||||
#version 450
|
||||
layout(location = 0) in vec3 Vertex_Position;
|
||||
layout(set = 0, binding = 0) uniform Camera {
|
||||
mat4 ViewProj;
|
||||
};
|
||||
layout(set = 1, binding = 0) uniform Object {
|
||||
mat4 Model;
|
||||
};
|
||||
void main() {
|
||||
gl_Position = ViewProj * Model * vec4(Vertex_Position, 1.0);
|
||||
}
|
||||
"#,
|
||||
))
|
||||
.with_fragment_shader(Shader::from_glsl(
|
||||
ShaderStage::Fragment,
|
||||
r#"
|
||||
#version 450
|
||||
layout(location = 0) out vec4 o_Target;
|
||||
layout(set = 1, binding = 1) uniform MyMaterial_color {
|
||||
vec4 color;
|
||||
};
|
||||
void main() {
|
||||
o_Target = color;
|
||||
|
||||
# ifdef MYMATERIAL_ALWAYS_RED
|
||||
o_Target = vec4(0.8, 0.0, 0.0, 1.0);
|
||||
# endif
|
||||
}
|
||||
"#,
|
||||
))
|
||||
.with_default_config();
|
||||
});
|
||||
}
|
||||
|
||||
fn setup(world: &mut World, resources: &mut Resources) {
|
||||
// add our shader to the render graph
|
||||
add_shader_to_render_graph(resources);
|
||||
// create new shader pipeline and add to main pass in Render Graph
|
||||
let pipeline_handle = {
|
||||
let mut pipelines = resources
|
||||
.get_mut::<AssetStorage<PipelineDescriptor>>()
|
||||
.unwrap();
|
||||
let mut shaders = resources.get_mut::<AssetStorage<Shader>>().unwrap();
|
||||
|
||||
let pipeline_handle = pipelines.add(PipelineDescriptor::default_config(ShaderStages {
|
||||
vertex: shaders.add(Shader::from_glsl(
|
||||
ShaderStage::Vertex,
|
||||
r#"
|
||||
#version 450
|
||||
layout(location = 0) in vec3 Vertex_Position;
|
||||
layout(set = 0, binding = 0) uniform Camera {
|
||||
mat4 ViewProj;
|
||||
};
|
||||
layout(set = 1, binding = 0) uniform Object {
|
||||
mat4 Model;
|
||||
};
|
||||
void main() {
|
||||
gl_Position = ViewProj * Model * vec4(Vertex_Position, 1.0);
|
||||
}
|
||||
"#,
|
||||
)),
|
||||
fragment: Some(shaders.add(Shader::from_glsl(
|
||||
ShaderStage::Fragment,
|
||||
r#"
|
||||
#version 450
|
||||
layout(location = 0) out vec4 o_Target;
|
||||
layout(set = 1, binding = 1) uniform MyMaterial_color {
|
||||
vec4 color;
|
||||
};
|
||||
void main() {
|
||||
o_Target = color;
|
||||
|
||||
# ifdef MYMATERIAL_ALWAYS_RED
|
||||
o_Target = vec4(0.8, 0.0, 0.0, 1.0);
|
||||
# endif
|
||||
}
|
||||
"#,
|
||||
))),
|
||||
}));
|
||||
let mut render_graph = resources.get_mut::<RenderGraph>().unwrap();
|
||||
render_graph.add_system_node_named(
|
||||
"my_material",
|
||||
AssetUniformNode::<MyMaterial>::new(true),
|
||||
resources,
|
||||
);
|
||||
let main_pass: &mut PassNode = render_graph.get_node_mut("main_pass").unwrap();
|
||||
main_pass.add_pipeline(
|
||||
pipeline_handle,
|
||||
vec![Box::new(draw_target::AssignedMeshesDrawTarget)],
|
||||
);
|
||||
pipeline_handle
|
||||
};
|
||||
|
||||
// create materials
|
||||
let mut material_storage = AssetStorage::<MyMaterial>::new();
|
||||
|
@ -82,15 +86,8 @@ fn setup(world: &mut World, resources: &mut Resources) {
|
|||
color: Color::rgb(0.0, 0.0, 0.0),
|
||||
always_red: true,
|
||||
});
|
||||
|
||||
resources.insert(material_storage);
|
||||
|
||||
// get a handle to our newly created shader pipeline
|
||||
let mut pipeline_storage = resources
|
||||
.get_mut::<AssetStorage<PipelineDescriptor>>()
|
||||
.unwrap();
|
||||
let pipeline_handle = pipeline_storage.get_named("MyMaterial").unwrap();
|
||||
|
||||
let mut mesh_storage = resources.get_mut::<AssetStorage<Mesh>>().unwrap();
|
||||
let cube_handle = mesh_storage.add(Mesh::from(shape::Cube));
|
||||
|
||||
|
|
|
@ -18,6 +18,9 @@ impl AddDefaultPlugins for AppBuilder {
|
|||
#[cfg(feature = "render")]
|
||||
self.add_plugin(bevy_render::RenderPlugin::default());
|
||||
|
||||
#[cfg(feature = "pbr")]
|
||||
self.add_plugin(bevy_pbr::PbrPlugin::default());
|
||||
|
||||
#[cfg(feature = "ui")]
|
||||
self.add_plugin(bevy_ui::UiPlugin::default());
|
||||
|
||||
|
|
|
@ -53,6 +53,8 @@ pub use bevy_diagnostic as diagnostic;
|
|||
pub use bevy_gltf as gltf;
|
||||
#[cfg(feature = "input")]
|
||||
pub use bevy_input as input;
|
||||
#[cfg(feature = "pbr")]
|
||||
pub use bevy_pbr as pbr;
|
||||
#[cfg(feature = "render")]
|
||||
pub use bevy_render as render;
|
||||
#[cfg(feature = "serialization")]
|
||||
|
|
|
@ -9,16 +9,19 @@ pub use crate::core::{
|
|||
pub use crate::derive::*;
|
||||
#[cfg(feature = "diagnostic")]
|
||||
pub use crate::diagnostic::DiagnosticsPlugin;
|
||||
#[cfg(feature = "pbr")]
|
||||
pub use crate::pbr::{material::StandardMaterial, light::Light, entity::*};
|
||||
#[cfg(feature = "render")]
|
||||
pub use crate::render::{
|
||||
entity::*,
|
||||
mesh::{Mesh, shape},
|
||||
pipeline::PipelineDescriptor,
|
||||
render_graph::RenderGraph,
|
||||
render_resource::{resource_name, resource_providers::UniformResourceProvider, AssetBatchers},
|
||||
shader::{uniforms::StandardMaterial, Shader, ShaderDefSuffixProvider, ShaderStage},
|
||||
draw_target,
|
||||
render_graph::{RenderGraph, nodes::{UniformNode, AssetUniformNode, PassNode, WindowSwapChainNode, WindowTextureNode, Camera2dNode, CameraNode}},
|
||||
render_resource::{resource_name, AssetBatchers},
|
||||
shader::{Shader, ShaderDefSuffixProvider, ShaderStage, ShaderStages},
|
||||
texture::{Texture, TextureType},
|
||||
ActiveCamera, ActiveCamera2d, Camera, CameraType, Color, ColorSource, Light, Renderable,
|
||||
ActiveCamera, ActiveCamera2d, Camera, CameraType, Color, ColorSource, Renderable,
|
||||
};
|
||||
#[cfg(feature = "transform")]
|
||||
pub use crate::transform::prelude::*;
|
||||
|
|
Loading…
Reference in a new issue