Use RenderStartup
for SolariPlugins
.
This commit is contained in:
parent
1525dff7ad
commit
fcdc0822df
@ -20,8 +20,16 @@ pub mod prelude {
|
||||
|
||||
use crate::realtime::SolariLightingPlugin;
|
||||
use crate::scene::RaytracingScenePlugin;
|
||||
use bevy_app::{PluginGroup, PluginGroupBuilder};
|
||||
use bevy_render::settings::WgpuFeatures;
|
||||
use bevy_app::{App, Plugin, PluginGroup, PluginGroupBuilder};
|
||||
use bevy_ecs::{
|
||||
resource::Resource,
|
||||
schedule::{common_conditions::resource_exists, IntoScheduleConfigs, SystemSet},
|
||||
system::{Commands, Res},
|
||||
};
|
||||
use bevy_render::{
|
||||
renderer::RenderDevice, settings::WgpuFeatures, ExtractSchedule, Render, RenderStartup,
|
||||
};
|
||||
use tracing::warn;
|
||||
|
||||
/// An experimental set of plugins for raytraced lighting.
|
||||
///
|
||||
@ -36,6 +44,7 @@ pub struct SolariPlugins;
|
||||
impl PluginGroup for SolariPlugins {
|
||||
fn build(self) -> PluginGroupBuilder {
|
||||
PluginGroupBuilder::start::<Self>()
|
||||
.add(SolariCorePlugin)
|
||||
.add(RaytracingScenePlugin)
|
||||
.add(SolariLightingPlugin)
|
||||
}
|
||||
@ -52,3 +61,50 @@ impl SolariPlugins {
|
||||
| WgpuFeatures::PARTIALLY_BOUND_BINDING_ARRAY
|
||||
}
|
||||
}
|
||||
|
||||
struct SolariCorePlugin;
|
||||
|
||||
impl Plugin for SolariCorePlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.add_systems(RenderStartup, check_solari_has_required_features)
|
||||
// Note: conditions only run once per schedule run. So even though these conditions
|
||||
// could apply to many systems, they will only be checked once for the entire group.
|
||||
.configure_sets(
|
||||
RenderStartup,
|
||||
SolariSystems
|
||||
.after(check_solari_has_required_features)
|
||||
.run_if(resource_exists::<HasSolariRequiredFeatures>),
|
||||
)
|
||||
.configure_sets(
|
||||
ExtractSchedule,
|
||||
SolariSystems.run_if(resource_exists::<HasSolariRequiredFeatures>),
|
||||
)
|
||||
.configure_sets(
|
||||
Render,
|
||||
SolariSystems.run_if(resource_exists::<HasSolariRequiredFeatures>),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(SystemSet, PartialEq, Eq, Debug, Clone, Hash)]
|
||||
pub struct SolariSystems;
|
||||
|
||||
/// A resource to track whether the renderer has the required features for Solari systems.
|
||||
#[derive(Resource)]
|
||||
struct HasSolariRequiredFeatures;
|
||||
|
||||
/// Check for the Solari required features once in startup, and insert a resource if the features
|
||||
/// are enabled.
|
||||
///
|
||||
/// Now systems can do a cheap check for if the resource exists.
|
||||
fn check_solari_has_required_features(mut commands: Commands, render_device: Res<RenderDevice>) {
|
||||
let features = render_device.features();
|
||||
if !features.contains(SolariPlugins::required_wgpu_features()) {
|
||||
warn!(
|
||||
"SolariSystems disabled. GPU lacks support for required features: {:?}.",
|
||||
SolariPlugins::required_wgpu_features().difference(features)
|
||||
);
|
||||
return;
|
||||
}
|
||||
commands.insert_resource(HasSolariRequiredFeatures);
|
||||
}
|
||||
|
@ -2,22 +2,22 @@ mod extract;
|
||||
mod node;
|
||||
mod prepare;
|
||||
|
||||
use crate::SolariPlugins;
|
||||
use crate::{scene::init_raytracing_scene_bindings, SolariSystems};
|
||||
use bevy_app::{App, Plugin};
|
||||
use bevy_asset::embedded_asset;
|
||||
use bevy_core_pipeline::core_3d::graph::{Core3d, Node3d};
|
||||
use bevy_ecs::{component::Component, reflect::ReflectComponent, schedule::IntoScheduleConfigs};
|
||||
use bevy_ecs::{
|
||||
component::Component, reflect::ReflectComponent, schedule::IntoScheduleConfigs, world::World,
|
||||
};
|
||||
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
|
||||
use bevy_render::{
|
||||
render_graph::{RenderGraphExt, ViewNodeRunner},
|
||||
renderer::RenderDevice,
|
||||
view::Hdr,
|
||||
ExtractSchedule, Render, RenderApp, RenderSystems,
|
||||
ExtractSchedule, Render, RenderApp, RenderStartup, RenderSystems,
|
||||
};
|
||||
use extract::extract_pathtracer;
|
||||
use node::PathtracerNode;
|
||||
use prepare::prepare_pathtracer_accumulation_texture;
|
||||
use tracing::warn;
|
||||
|
||||
/// Non-realtime pathtracing.
|
||||
///
|
||||
@ -30,32 +30,25 @@ impl Plugin for PathtracingPlugin {
|
||||
embedded_asset!(app, "pathtracer.wgsl");
|
||||
|
||||
app.register_type::<Pathtracer>();
|
||||
}
|
||||
|
||||
fn finish(&self, app: &mut App) {
|
||||
let render_app = app.sub_app_mut(RenderApp);
|
||||
|
||||
let render_device = render_app.world().resource::<RenderDevice>();
|
||||
let features = render_device.features();
|
||||
if !features.contains(SolariPlugins::required_wgpu_features()) {
|
||||
warn!(
|
||||
"PathtracingPlugin not loaded. GPU lacks support for required features: {:?}.",
|
||||
SolariPlugins::required_wgpu_features().difference(features)
|
||||
);
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
render_app
|
||||
.add_systems(ExtractSchedule, extract_pathtracer)
|
||||
.add_systems(
|
||||
RenderStartup,
|
||||
add_solari_pathtracing_render_graph_nodes
|
||||
.after(init_raytracing_scene_bindings)
|
||||
.in_set(SolariSystems),
|
||||
)
|
||||
.add_systems(ExtractSchedule, extract_pathtracer.in_set(SolariSystems))
|
||||
.add_systems(
|
||||
Render,
|
||||
prepare_pathtracer_accumulation_texture.in_set(RenderSystems::PrepareResources),
|
||||
)
|
||||
.add_render_graph_node::<ViewNodeRunner<PathtracerNode>>(
|
||||
Core3d,
|
||||
node::graph::PathtracerNode,
|
||||
)
|
||||
.add_render_graph_edges(Core3d, (Node3d::EndMainPass, node::graph::PathtracerNode));
|
||||
prepare_pathtracer_accumulation_texture
|
||||
.in_set(RenderSystems::PrepareResources)
|
||||
.in_set(SolariSystems),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -65,3 +58,15 @@ impl Plugin for PathtracingPlugin {
|
||||
pub struct Pathtracer {
|
||||
pub reset: bool,
|
||||
}
|
||||
|
||||
// We only want to add these render graph nodes and edges if Solari required features are present.
|
||||
// Making this a system that runs at RenderStartup allows a run condition to check for required
|
||||
// features first.
|
||||
fn add_solari_pathtracing_render_graph_nodes(world: &mut World) {
|
||||
world
|
||||
.add_render_graph_node::<ViewNodeRunner<PathtracerNode>>(
|
||||
Core3d,
|
||||
node::graph::PathtracerNode,
|
||||
)
|
||||
.add_render_graph_edges(Core3d, (Node3d::EndMainPass, node::graph::PathtracerNode));
|
||||
}
|
||||
|
@ -2,26 +2,26 @@ mod extract;
|
||||
mod node;
|
||||
mod prepare;
|
||||
|
||||
use crate::SolariPlugins;
|
||||
use crate::{scene::init_raytracing_scene_bindings, SolariSystems};
|
||||
use bevy_app::{App, Plugin};
|
||||
use bevy_asset::embedded_asset;
|
||||
use bevy_core_pipeline::{
|
||||
core_3d::graph::{Core3d, Node3d},
|
||||
prepass::{DeferredPrepass, DepthPrepass, MotionVectorPrepass},
|
||||
};
|
||||
use bevy_ecs::{component::Component, reflect::ReflectComponent, schedule::IntoScheduleConfigs};
|
||||
use bevy_ecs::{
|
||||
component::Component, reflect::ReflectComponent, schedule::IntoScheduleConfigs, world::World,
|
||||
};
|
||||
use bevy_pbr::DefaultOpaqueRendererMethod;
|
||||
use bevy_reflect::{std_traits::ReflectDefault, Reflect};
|
||||
use bevy_render::{
|
||||
render_graph::{RenderGraphExt, ViewNodeRunner},
|
||||
renderer::RenderDevice,
|
||||
view::Hdr,
|
||||
ExtractSchedule, Render, RenderApp, RenderSystems,
|
||||
ExtractSchedule, Render, RenderApp, RenderStartup, RenderSystems,
|
||||
};
|
||||
use extract::extract_solari_lighting;
|
||||
use node::SolariLightingNode;
|
||||
use prepare::prepare_solari_lighting_resources;
|
||||
use tracing::warn;
|
||||
|
||||
pub struct SolariLightingPlugin;
|
||||
|
||||
@ -31,33 +31,27 @@ impl Plugin for SolariLightingPlugin {
|
||||
|
||||
app.register_type::<SolariLighting>()
|
||||
.insert_resource(DefaultOpaqueRendererMethod::deferred());
|
||||
}
|
||||
|
||||
fn finish(&self, app: &mut App) {
|
||||
let render_app = app.sub_app_mut(RenderApp);
|
||||
|
||||
let render_device = render_app.world().resource::<RenderDevice>();
|
||||
let features = render_device.features();
|
||||
if !features.contains(SolariPlugins::required_wgpu_features()) {
|
||||
warn!(
|
||||
"SolariLightingPlugin not loaded. GPU lacks support for required features: {:?}.",
|
||||
SolariPlugins::required_wgpu_features().difference(features)
|
||||
);
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
render_app
|
||||
.add_systems(ExtractSchedule, extract_solari_lighting)
|
||||
.add_systems(
|
||||
RenderStartup,
|
||||
add_solari_lighting_render_graph_nodes
|
||||
.after(init_raytracing_scene_bindings)
|
||||
.in_set(SolariSystems),
|
||||
)
|
||||
.add_systems(
|
||||
ExtractSchedule,
|
||||
extract_solari_lighting.in_set(SolariSystems),
|
||||
)
|
||||
.add_systems(
|
||||
Render,
|
||||
prepare_solari_lighting_resources.in_set(RenderSystems::PrepareResources),
|
||||
)
|
||||
.add_render_graph_node::<ViewNodeRunner<SolariLightingNode>>(
|
||||
Core3d,
|
||||
node::graph::SolariLightingNode,
|
||||
)
|
||||
.add_render_graph_edges(
|
||||
Core3d,
|
||||
(Node3d::EndMainPass, node::graph::SolariLightingNode),
|
||||
prepare_solari_lighting_resources
|
||||
.in_set(RenderSystems::PrepareResources)
|
||||
.in_set(SolariSystems),
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -87,3 +81,18 @@ impl Default for SolariLighting {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We only want to add these render graph nodes and edges if Solari required features are present.
|
||||
// Making this a system that runs at RenderStartup allows a run condition to check for required
|
||||
// features first.
|
||||
fn add_solari_lighting_render_graph_nodes(world: &mut World) {
|
||||
world
|
||||
.add_render_graph_node::<ViewNodeRunner<SolariLightingNode>>(
|
||||
Core3d,
|
||||
node::graph::SolariLightingNode,
|
||||
)
|
||||
.add_render_graph_edges(
|
||||
Core3d,
|
||||
(Node3d::EndMainPass, node::graph::SolariLightingNode),
|
||||
);
|
||||
}
|
||||
|
@ -4,8 +4,7 @@ use bevy_color::{ColorToComponents, LinearRgba};
|
||||
use bevy_ecs::{
|
||||
entity::{Entity, EntityHashMap},
|
||||
resource::Resource,
|
||||
system::{Query, Res, ResMut},
|
||||
world::{FromWorld, World},
|
||||
system::{Commands, Query, Res, ResMut},
|
||||
};
|
||||
use bevy_math::{ops::cos, Mat4, Vec3};
|
||||
use bevy_pbr::{ExtractedDirectionalLight, MeshMaterial3d, StandardMaterial};
|
||||
@ -265,36 +264,35 @@ pub fn prepare_raytracing_scene_bindings(
|
||||
));
|
||||
}
|
||||
|
||||
impl FromWorld for RaytracingSceneBindings {
|
||||
fn from_world(world: &mut World) -> Self {
|
||||
let render_device = world.resource::<RenderDevice>();
|
||||
|
||||
Self {
|
||||
bind_group: None,
|
||||
bind_group_layout: render_device.create_bind_group_layout(
|
||||
"raytracing_scene_bind_group_layout",
|
||||
&BindGroupLayoutEntries::sequential(
|
||||
ShaderStages::COMPUTE,
|
||||
(
|
||||
storage_buffer_read_only_sized(false, None).count(MAX_MESH_SLAB_COUNT),
|
||||
storage_buffer_read_only_sized(false, None).count(MAX_MESH_SLAB_COUNT),
|
||||
texture_2d(TextureSampleType::Float { filterable: true })
|
||||
.count(MAX_TEXTURE_COUNT),
|
||||
sampler(SamplerBindingType::Filtering).count(MAX_TEXTURE_COUNT),
|
||||
storage_buffer_read_only_sized(false, None),
|
||||
acceleration_structure(),
|
||||
storage_buffer_read_only_sized(false, None),
|
||||
storage_buffer_read_only_sized(false, None),
|
||||
storage_buffer_read_only_sized(false, None),
|
||||
storage_buffer_read_only_sized(false, None),
|
||||
storage_buffer_read_only_sized(false, None),
|
||||
storage_buffer_read_only_sized(false, None),
|
||||
),
|
||||
pub(crate) fn init_raytracing_scene_bindings(
|
||||
mut commands: Commands,
|
||||
render_device: Res<RenderDevice>,
|
||||
) {
|
||||
commands.insert_resource(RaytracingSceneBindings {
|
||||
bind_group: None,
|
||||
bind_group_layout: render_device.create_bind_group_layout(
|
||||
"raytracing_scene_bind_group_layout",
|
||||
&BindGroupLayoutEntries::sequential(
|
||||
ShaderStages::COMPUTE,
|
||||
(
|
||||
storage_buffer_read_only_sized(false, None).count(MAX_MESH_SLAB_COUNT),
|
||||
storage_buffer_read_only_sized(false, None).count(MAX_MESH_SLAB_COUNT),
|
||||
texture_2d(TextureSampleType::Float { filterable: true })
|
||||
.count(MAX_TEXTURE_COUNT),
|
||||
sampler(SamplerBindingType::Filtering).count(MAX_TEXTURE_COUNT),
|
||||
storage_buffer_read_only_sized(false, None),
|
||||
acceleration_structure(),
|
||||
storage_buffer_read_only_sized(false, None),
|
||||
storage_buffer_read_only_sized(false, None),
|
||||
storage_buffer_read_only_sized(false, None),
|
||||
storage_buffer_read_only_sized(false, None),
|
||||
storage_buffer_read_only_sized(false, None),
|
||||
storage_buffer_read_only_sized(false, None),
|
||||
),
|
||||
),
|
||||
previous_frame_light_entities: Vec::new(),
|
||||
}
|
||||
}
|
||||
),
|
||||
previous_frame_light_entities: Vec::new(),
|
||||
});
|
||||
}
|
||||
|
||||
struct CachedBindingArray<T, I: Eq + Hash> {
|
||||
|
@ -6,9 +6,11 @@ mod types;
|
||||
pub use binder::RaytracingSceneBindings;
|
||||
pub use types::RaytracingMesh3d;
|
||||
|
||||
use crate::SolariPlugins;
|
||||
pub(crate) use binder::init_raytracing_scene_bindings;
|
||||
|
||||
use crate::SolariSystems;
|
||||
use bevy_app::{App, Plugin};
|
||||
use bevy_ecs::schedule::IntoScheduleConfigs;
|
||||
use bevy_ecs::{schedule::IntoScheduleConfigs, system::ResMut};
|
||||
use bevy_render::{
|
||||
extract_resource::ExtractResourcePlugin,
|
||||
load_shader_library,
|
||||
@ -18,13 +20,11 @@ use bevy_render::{
|
||||
},
|
||||
render_asset::prepare_assets,
|
||||
render_resource::BufferUsages,
|
||||
renderer::RenderDevice,
|
||||
ExtractSchedule, Render, RenderApp, RenderSystems,
|
||||
ExtractSchedule, Render, RenderApp, RenderStartup, RenderSystems,
|
||||
};
|
||||
use binder::prepare_raytracing_scene_bindings;
|
||||
use blas::{prepare_raytracing_blas, BlasManager};
|
||||
use extract::{extract_raytracing_scene, StandardMaterialAssets};
|
||||
use tracing::warn;
|
||||
|
||||
/// Creates acceleration structures and binding arrays of resources for raytracing.
|
||||
pub struct RaytracingScenePlugin;
|
||||
@ -34,35 +34,28 @@ impl Plugin for RaytracingScenePlugin {
|
||||
load_shader_library!(app, "raytracing_scene_bindings.wgsl");
|
||||
load_shader_library!(app, "sampling.wgsl");
|
||||
|
||||
app.register_type::<RaytracingMesh3d>();
|
||||
}
|
||||
app.register_type::<RaytracingMesh3d>()
|
||||
.add_plugins(ExtractResourcePlugin::<StandardMaterialAssets>::default());
|
||||
|
||||
fn finish(&self, app: &mut App) {
|
||||
let render_app = app.sub_app_mut(RenderApp);
|
||||
let render_device = render_app.world().resource::<RenderDevice>();
|
||||
let features = render_device.features();
|
||||
if !features.contains(SolariPlugins::required_wgpu_features()) {
|
||||
warn!(
|
||||
"RaytracingScenePlugin not loaded. GPU lacks support for required features: {:?}.",
|
||||
SolariPlugins::required_wgpu_features().difference(features)
|
||||
);
|
||||
let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
|
||||
return;
|
||||
}
|
||||
|
||||
app.add_plugins(ExtractResourcePlugin::<StandardMaterialAssets>::default());
|
||||
|
||||
let render_app = app.sub_app_mut(RenderApp);
|
||||
|
||||
render_app
|
||||
.world_mut()
|
||||
.resource_mut::<MeshAllocator>()
|
||||
.extra_buffer_usages |= BufferUsages::BLAS_INPUT | BufferUsages::STORAGE;
|
||||
};
|
||||
|
||||
render_app
|
||||
.init_resource::<BlasManager>()
|
||||
.init_resource::<StandardMaterialAssets>()
|
||||
.init_resource::<RaytracingSceneBindings>()
|
||||
.add_systems(ExtractSchedule, extract_raytracing_scene)
|
||||
.add_systems(
|
||||
RenderStartup,
|
||||
(
|
||||
add_raytracing_extra_mesh_buffer_usages,
|
||||
init_raytracing_scene_bindings,
|
||||
)
|
||||
.in_set(SolariSystems),
|
||||
)
|
||||
.add_systems(
|
||||
ExtractSchedule,
|
||||
extract_raytracing_scene.in_set(SolariSystems),
|
||||
)
|
||||
.add_systems(
|
||||
Render,
|
||||
(
|
||||
@ -71,7 +64,12 @@ impl Plugin for RaytracingScenePlugin {
|
||||
.before(prepare_assets::<RenderMesh>)
|
||||
.after(allocate_and_free_meshes),
|
||||
prepare_raytracing_scene_bindings.in_set(RenderSystems::PrepareBindGroups),
|
||||
),
|
||||
)
|
||||
.in_set(SolariSystems),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn add_raytracing_extra_mesh_buffer_usages(mut mesh_allocator: ResMut<MeshAllocator>) {
|
||||
mesh_allocator.extra_buffer_usages |= BufferUsages::BLAS_INPUT | BufferUsages::STORAGE;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user