Use RenderStartup for OIT and make sure systems run conditionally.

This commit is contained in:
andriyDev 2025-07-16 18:17:21 -07:00
parent 877d278785
commit c5ebbfc873

View File

@ -18,7 +18,7 @@ use bevy_render::{
}, },
renderer::{RenderAdapter, RenderDevice}, renderer::{RenderAdapter, RenderDevice},
view::{ExtractedView, ViewTarget, ViewUniform, ViewUniforms}, view::{ExtractedView, ViewTarget, ViewUniform, ViewUniforms},
Render, RenderApp, RenderSystems, Render, RenderApp, RenderStartup, RenderSystems,
}; };
use bevy_utils::default; use bevy_utils::default;
use tracing::warn; use tracing::warn;
@ -34,30 +34,32 @@ pub struct OitResolvePlugin;
impl Plugin for OitResolvePlugin { impl Plugin for OitResolvePlugin {
fn build(&self, app: &mut bevy_app::App) { fn build(&self, app: &mut bevy_app::App) {
embedded_asset!(app, "oit_resolve.wgsl"); embedded_asset!(app, "oit_resolve.wgsl");
}
fn finish(&self, app: &mut bevy_app::App) {
let Some(render_app) = app.get_sub_app_mut(RenderApp) else { let Some(render_app) = app.get_sub_app_mut(RenderApp) else {
return; return;
}; };
if !is_oit_supported(
render_app.world().resource::<RenderAdapter>(),
render_app.world().resource::<RenderDevice>(),
true,
) {
return;
}
render_app render_app
.configure_sets(
RenderStartup,
OitSystems
.after(check_is_oit_supported)
.run_if(resource_exists::<OitSupported>),
)
.configure_sets(Render, OitSystems.run_if(resource_exists::<OitSupported>))
.add_systems(RenderStartup, check_is_oit_supported)
.add_systems(RenderStartup, init_oit_resolve_pipeline.in_set(OitSystems))
.add_systems( .add_systems(
Render, Render,
( (
queue_oit_resolve_pipeline.in_set(RenderSystems::Queue), queue_oit_resolve_pipeline
prepare_oit_resolve_bind_group.in_set(RenderSystems::PrepareBindGroups), .in_set(OitSystems)
.in_set(RenderSystems::Queue),
prepare_oit_resolve_bind_group
.in_set(OitSystems)
.in_set(RenderSystems::PrepareBindGroups),
), ),
) );
.init_resource::<OitResolvePipeline>();
} }
} }
@ -89,6 +91,25 @@ pub fn is_oit_supported(adapter: &RenderAdapter, device: &RenderDevice, warn: bo
true true
} }
/// System set for systems used for OIT.
#[derive(SystemSet, PartialEq, Eq, Hash, Debug, Clone)]
struct OitSystems;
/// A resource to indicate that OIT is supported.
#[derive(Resource)]
struct OitSupported;
/// A system to perform a one-time check for whether OIT is supported and insert a resource if so.
fn check_is_oit_supported(
mut commands: Commands,
render_device: Res<RenderDevice>,
render_adapter: Res<RenderAdapter>,
) {
if is_oit_supported(&render_adapter, &render_device, true) {
commands.insert_resource(OitSupported);
}
}
/// Bind group for the OIT resolve pass. /// Bind group for the OIT resolve pass.
#[derive(Resource, Deref)] #[derive(Resource, Deref)]
pub struct OitResolveBindGroup(pub BindGroup); pub struct OitResolveBindGroup(pub BindGroup);
@ -102,33 +123,29 @@ pub struct OitResolvePipeline {
pub oit_depth_bind_group_layout: BindGroupLayout, pub oit_depth_bind_group_layout: BindGroupLayout,
} }
impl FromWorld for OitResolvePipeline { pub fn init_oit_resolve_pipeline(mut commands: Commands, render_device: Res<RenderDevice>) {
fn from_world(world: &mut World) -> Self { let view_bind_group_layout = render_device.create_bind_group_layout(
let render_device = world.resource::<RenderDevice>(); "oit_resolve_bind_group_layout",
&BindGroupLayoutEntries::sequential(
let view_bind_group_layout = render_device.create_bind_group_layout( ShaderStages::FRAGMENT,
"oit_resolve_bind_group_layout", (
&BindGroupLayoutEntries::sequential( uniform_buffer::<ViewUniform>(true),
ShaderStages::FRAGMENT, // layers
( storage_buffer_sized(false, None),
uniform_buffer::<ViewUniform>(true), // layer ids
// layers storage_buffer_sized(false, None),
storage_buffer_sized(false, None),
// layer ids
storage_buffer_sized(false, None),
),
), ),
); ),
);
let oit_depth_bind_group_layout = render_device.create_bind_group_layout( let oit_depth_bind_group_layout = render_device.create_bind_group_layout(
"oit_depth_bind_group_layout", "oit_depth_bind_group_layout",
&BindGroupLayoutEntries::single(ShaderStages::FRAGMENT, texture_depth_2d()), &BindGroupLayoutEntries::single(ShaderStages::FRAGMENT, texture_depth_2d()),
); );
OitResolvePipeline { commands.insert_resource(OitResolvePipeline {
view_bind_group_layout, view_bind_group_layout,
oit_depth_bind_group_layout, oit_depth_bind_group_layout,
} });
}
} }
#[derive(Component, Deref, Clone, Copy)] #[derive(Component, Deref, Clone, Copy)]