Initial DLSS implementation
This commit is contained in:
parent
e9daac4f11
commit
c75b2b4f26
@ -463,6 +463,9 @@ tonemapping_luts = ["bevy_internal/tonemapping_luts", "ktx2", "bevy_image/zstd"]
|
||||
# Include SMAA Look Up Tables KTX2 Files
|
||||
smaa_luts = ["bevy_internal/smaa_luts"]
|
||||
|
||||
# NVIDIA Deep Learning Super Sampling
|
||||
dlss = ["bevy_internal/dlss"]
|
||||
|
||||
# Enable AccessKit on Unix backends (currently only works with experimental screen readers and forks.)
|
||||
accesskit_unix = ["bevy_internal/accesskit_unix"]
|
||||
|
||||
|
||||
@ -13,6 +13,7 @@ trace = []
|
||||
webgl = []
|
||||
webgpu = []
|
||||
smaa_luts = ["bevy_render/ktx2", "bevy_image/ktx2", "bevy_image/zstd"]
|
||||
dlss = ["dep:dlss_wgpu"]
|
||||
|
||||
[dependencies]
|
||||
# bevy
|
||||
@ -30,6 +31,7 @@ bevy_diagnostic = { path = "../bevy_diagnostic", version = "0.17.0-dev" }
|
||||
|
||||
# other
|
||||
tracing = { version = "0.1", default-features = false, features = ["std"] }
|
||||
dlss_wgpu = { path = "../../../dlss_wgpu", optional = true }
|
||||
|
||||
[lints]
|
||||
workspace = true
|
||||
|
||||
29
crates/bevy_anti_aliasing/src/dlss/extract.rs
Normal file
29
crates/bevy_anti_aliasing/src/dlss/extract.rs
Normal file
@ -0,0 +1,29 @@
|
||||
use super::{prepare::ViewDlssContext, Dlss};
|
||||
use bevy_ecs::{
|
||||
query::With,
|
||||
system::{Commands, ResMut},
|
||||
};
|
||||
use bevy_render::{
|
||||
camera::{Camera, MainPassResolutionOverride, Projection},
|
||||
sync_world::RenderEntity,
|
||||
view::Hdr,
|
||||
MainWorld,
|
||||
};
|
||||
|
||||
pub fn extract_dlss(mut commands: Commands, mut main_world: ResMut<MainWorld>) {
|
||||
let mut cameras_3d = main_world
|
||||
.query_filtered::<(RenderEntity, &Camera, &Projection, Option<&mut Dlss>), With<Hdr>>();
|
||||
|
||||
for (entity, camera, camera_projection, mut dlss) in cameras_3d.iter_mut(&mut main_world) {
|
||||
let has_perspective_projection = matches!(camera_projection, Projection::Perspective(_));
|
||||
let mut entity_commands = commands
|
||||
.get_entity(entity)
|
||||
.expect("Camera entity wasn't synced.");
|
||||
if dlss.is_some() && camera.is_active && has_perspective_projection {
|
||||
entity_commands.insert(dlss.as_deref().unwrap().clone());
|
||||
dlss.as_mut().unwrap().reset = false;
|
||||
} else {
|
||||
entity_commands.remove::<(Dlss, ViewDlssContext, MainPassResolutionOverride)>();
|
||||
}
|
||||
}
|
||||
}
|
||||
105
crates/bevy_anti_aliasing/src/dlss/mod.rs
Normal file
105
crates/bevy_anti_aliasing/src/dlss/mod.rs
Normal file
@ -0,0 +1,105 @@
|
||||
mod extract;
|
||||
mod node;
|
||||
mod prepare;
|
||||
|
||||
use bevy_app::{App, Plugin};
|
||||
use bevy_core_pipeline::{
|
||||
core_3d::graph::{Core3d, Node3d},
|
||||
prepass::{DepthPrepass, MotionVectorPrepass},
|
||||
};
|
||||
use bevy_ecs::{
|
||||
component::Component, prelude::ReflectComponent, resource::Resource,
|
||||
schedule::IntoScheduleConfigs,
|
||||
};
|
||||
use bevy_reflect::{prelude::ReflectDefault, reflect_remote, Reflect};
|
||||
use bevy_render::{
|
||||
camera::{MipBias, TemporalJitter},
|
||||
render_graph::{RenderGraphApp, ViewNodeRunner},
|
||||
renderer::RenderDevice,
|
||||
view::{prepare_view_targets, prepare_view_uniforms, Hdr},
|
||||
ExtractSchedule, Render, RenderApp, RenderSystems,
|
||||
};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use tracing::info;
|
||||
|
||||
pub use bevy_render::{DlssProjectId, DlssSupported};
|
||||
pub use dlss_wgpu::DlssPerfQualityMode;
|
||||
|
||||
pub struct DlssPlugin;
|
||||
|
||||
impl Plugin for DlssPlugin {
|
||||
fn build(&self, app: &mut App) {
|
||||
app.register_type::<Dlss>();
|
||||
}
|
||||
|
||||
fn finish(&self, app: &mut App) {
|
||||
if app.world().get_resource::<DlssSupported>().is_none() {
|
||||
info!("DLSS is not supported on this system");
|
||||
return;
|
||||
}
|
||||
|
||||
let dlss_project_id = app.world().resource::<DlssProjectId>().0;
|
||||
|
||||
let render_app = app.get_sub_app_mut(RenderApp).unwrap();
|
||||
let render_device = render_app.world().resource::<RenderDevice>().clone();
|
||||
|
||||
let dlss_sdk =
|
||||
dlss_wgpu::DlssSdk::new(dlss_project_id, render_device.wgpu_device().clone());
|
||||
if dlss_sdk.is_err() {
|
||||
app.world_mut().remove_resource::<DlssSupported>();
|
||||
info!("DLSS is not supported on this system");
|
||||
return;
|
||||
}
|
||||
|
||||
render_app
|
||||
.insert_resource(DlssSdk(dlss_sdk.unwrap()))
|
||||
.add_systems(ExtractSchedule, extract::extract_dlss)
|
||||
.add_systems(
|
||||
Render,
|
||||
prepare::configure_dlss_view_targets
|
||||
.in_set(RenderSystems::ManageViews)
|
||||
.before(prepare_view_targets),
|
||||
)
|
||||
.add_systems(
|
||||
Render,
|
||||
prepare::prepare_dlss
|
||||
.in_set(RenderSystems::PrepareResources)
|
||||
.before(prepare_view_uniforms),
|
||||
)
|
||||
.add_render_graph_node::<ViewNodeRunner<node::DlssNode>>(Core3d, Node3d::Dlss)
|
||||
.add_render_graph_edges(
|
||||
Core3d,
|
||||
(
|
||||
Node3d::EndMainPass,
|
||||
Node3d::MotionBlur, // Running before DLSS reduces edge artifacts and noise
|
||||
Node3d::Dlss,
|
||||
Node3d::Bloom,
|
||||
Node3d::Tonemapping,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Component, Reflect, Clone, Default)]
|
||||
#[reflect(Component, Default)]
|
||||
#[require(TemporalJitter, MipBias, DepthPrepass, MotionVectorPrepass, Hdr)]
|
||||
pub struct Dlss {
|
||||
#[reflect(remote = DlssPerfQualityModeRemoteReflect)]
|
||||
pub perf_quality_mode: DlssPerfQualityMode,
|
||||
pub reset: bool,
|
||||
}
|
||||
|
||||
#[reflect_remote(DlssPerfQualityMode)]
|
||||
#[derive(Default)]
|
||||
enum DlssPerfQualityModeRemoteReflect {
|
||||
#[default]
|
||||
Auto,
|
||||
Dlaa,
|
||||
Quality,
|
||||
Balanced,
|
||||
Performance,
|
||||
UltraPerformance,
|
||||
}
|
||||
|
||||
#[derive(Resource)]
|
||||
struct DlssSdk(Arc<Mutex<dlss_wgpu::DlssSdk>>);
|
||||
85
crates/bevy_anti_aliasing/src/dlss/node.rs
Normal file
85
crates/bevy_anti_aliasing/src/dlss/node.rs
Normal file
@ -0,0 +1,85 @@
|
||||
use super::{prepare::ViewDlssContext, Dlss};
|
||||
use bevy_core_pipeline::prepass::ViewPrepassTextures;
|
||||
use bevy_ecs::{query::QueryItem, world::World};
|
||||
use bevy_render::{
|
||||
camera::{MainPassResolutionOverride, TemporalJitter},
|
||||
render_graph::{NodeRunError, RenderGraphContext, ViewNode},
|
||||
renderer::{RenderAdapter, RenderContext},
|
||||
view::ViewTarget,
|
||||
};
|
||||
use dlss_wgpu::{DlssExposure, DlssRenderParameters, DlssTexture};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct DlssNode;
|
||||
|
||||
impl ViewNode for DlssNode {
|
||||
type ViewQuery = (
|
||||
&'static Dlss,
|
||||
&'static ViewDlssContext,
|
||||
&'static MainPassResolutionOverride,
|
||||
&'static TemporalJitter,
|
||||
&'static ViewTarget,
|
||||
&'static ViewPrepassTextures,
|
||||
);
|
||||
|
||||
fn run(
|
||||
&self,
|
||||
_graph: &mut RenderGraphContext,
|
||||
render_context: &mut RenderContext,
|
||||
(
|
||||
dlss,
|
||||
dlss_context,
|
||||
viewport_override,
|
||||
temporal_jitter,
|
||||
view_target,
|
||||
prepass_textures,
|
||||
): QueryItem<Self::ViewQuery>,
|
||||
world: &World,
|
||||
) -> Result<(), NodeRunError> {
|
||||
let adapter = world.resource::<RenderAdapter>();
|
||||
let (Some(prepass_motion_vectors_texture), Some(prepass_depth_texture)) =
|
||||
(&prepass_textures.motion_vectors, &prepass_textures.depth)
|
||||
else {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
let view_target = view_target.post_process_write();
|
||||
|
||||
let render_resolution = viewport_override.0;
|
||||
let render_parameters = DlssRenderParameters {
|
||||
color: DlssTexture {
|
||||
texture: &view_target.source_texture,
|
||||
view: &view_target.source,
|
||||
},
|
||||
depth: DlssTexture {
|
||||
texture: &prepass_depth_texture.texture.texture,
|
||||
view: &prepass_depth_texture.texture.default_view,
|
||||
},
|
||||
motion_vectors: DlssTexture {
|
||||
texture: &prepass_motion_vectors_texture.texture.texture,
|
||||
view: &prepass_motion_vectors_texture.texture.default_view,
|
||||
},
|
||||
exposure: DlssExposure::Automatic, // TODO
|
||||
bias: None, // TODO
|
||||
dlss_output: DlssTexture {
|
||||
texture: &view_target.destination_texture,
|
||||
view: &view_target.destination,
|
||||
},
|
||||
reset: dlss.reset,
|
||||
jitter_offset: -temporal_jitter.offset,
|
||||
partial_texture_size: Some(render_resolution),
|
||||
motion_vector_scale: Some(-render_resolution.as_vec2()),
|
||||
};
|
||||
|
||||
let command_encoder = render_context.command_encoder();
|
||||
let mut dlss_context = dlss_context.context.lock().unwrap();
|
||||
|
||||
command_encoder.push_debug_group("dlss");
|
||||
dlss_context
|
||||
.render(render_parameters, command_encoder, &adapter)
|
||||
.expect("Failed to render DLSS");
|
||||
command_encoder.pop_debug_group();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
111
crates/bevy_anti_aliasing/src/dlss/prepare.rs
Normal file
111
crates/bevy_anti_aliasing/src/dlss/prepare.rs
Normal file
@ -0,0 +1,111 @@
|
||||
use super::{Dlss, DlssSdk};
|
||||
use bevy_core_pipeline::{
|
||||
core_3d::Camera3d,
|
||||
prepass::{DepthPrepass, MotionVectorPrepass},
|
||||
};
|
||||
use bevy_diagnostic::FrameCount;
|
||||
use bevy_ecs::{
|
||||
component::Component,
|
||||
entity::Entity,
|
||||
query::With,
|
||||
system::{Commands, Query, Res},
|
||||
};
|
||||
use bevy_math::Vec4Swizzles;
|
||||
use bevy_render::{
|
||||
camera::{CameraMainTextureUsages, MainPassResolutionOverride, MipBias, TemporalJitter},
|
||||
render_resource::TextureUsages,
|
||||
renderer::{RenderDevice, RenderQueue},
|
||||
view::ExtractedView,
|
||||
};
|
||||
use dlss_wgpu::{DlssContext, DlssFeatureFlags, DlssPerfQualityMode};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
pub fn prepare_dlss(
|
||||
mut query: Query<
|
||||
(
|
||||
Entity,
|
||||
&ExtractedView,
|
||||
&Dlss,
|
||||
&mut TemporalJitter,
|
||||
&mut MipBias,
|
||||
Option<&mut ViewDlssContext>,
|
||||
),
|
||||
(
|
||||
With<Camera3d>,
|
||||
With<TemporalJitter>,
|
||||
With<DepthPrepass>,
|
||||
With<MotionVectorPrepass>,
|
||||
),
|
||||
>,
|
||||
dlss_sdk: Res<DlssSdk>,
|
||||
render_device: Res<RenderDevice>,
|
||||
render_queue: Res<RenderQueue>,
|
||||
frame_count: Res<FrameCount>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
for (entity, view, dlss, mut temporal_jitter, mut mip_bias, mut dlss_context) in &mut query {
|
||||
let upscaled_resolution = view.viewport.zw();
|
||||
|
||||
let dlss_feature_flags = DlssFeatureFlags::LowResolutionMotionVectors
|
||||
| DlssFeatureFlags::InvertedDepth
|
||||
| DlssFeatureFlags::HighDynamicRange
|
||||
| DlssFeatureFlags::AutoExposure; // TODO
|
||||
|
||||
match dlss_context.as_deref_mut() {
|
||||
Some(dlss_context)
|
||||
if upscaled_resolution
|
||||
== dlss_context.context.lock().unwrap().upscaled_resolution()
|
||||
&& dlss.perf_quality_mode == dlss_context.perf_quality_mode
|
||||
&& dlss_feature_flags == dlss_context.feature_flags =>
|
||||
{
|
||||
let dlss_context = dlss_context.context.lock().unwrap();
|
||||
temporal_jitter.offset =
|
||||
dlss_context.suggested_jitter(frame_count.0, dlss_context.render_resolution());
|
||||
}
|
||||
_ => {
|
||||
let dlss_context = DlssContext::new(
|
||||
upscaled_resolution,
|
||||
dlss.perf_quality_mode,
|
||||
dlss_feature_flags,
|
||||
Arc::clone(&dlss_sdk.0),
|
||||
render_device.wgpu_device(),
|
||||
&render_queue,
|
||||
)
|
||||
.expect("Failed to create DlssContext");
|
||||
|
||||
let render_resolution = dlss_context.render_resolution();
|
||||
temporal_jitter.offset =
|
||||
dlss_context.suggested_jitter(frame_count.0, render_resolution);
|
||||
mip_bias.0 = dlss_context.suggested_mip_bias(render_resolution);
|
||||
|
||||
commands.entity(entity).insert((
|
||||
ViewDlssContext {
|
||||
context: Mutex::new(dlss_context),
|
||||
perf_quality_mode: dlss.perf_quality_mode,
|
||||
feature_flags: dlss_feature_flags,
|
||||
},
|
||||
MainPassResolutionOverride(render_resolution),
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Component)]
|
||||
pub struct ViewDlssContext {
|
||||
pub context: Mutex<DlssContext>,
|
||||
pub perf_quality_mode: DlssPerfQualityMode,
|
||||
pub feature_flags: DlssFeatureFlags,
|
||||
}
|
||||
|
||||
pub fn configure_dlss_view_targets(
|
||||
mut view_targets: Query<(&mut Camera3d, &mut CameraMainTextureUsages), With<Dlss>>,
|
||||
) {
|
||||
for (mut camera_3d, mut camera_main_texture_usages) in view_targets.iter_mut() {
|
||||
camera_main_texture_usages.0 |= TextureUsages::STORAGE_BINDING;
|
||||
|
||||
let mut depth_texture_usages = TextureUsages::from(camera_3d.depth_texture_usages);
|
||||
depth_texture_usages |= TextureUsages::TEXTURE_BINDING;
|
||||
camera_3d.depth_texture_usages = depth_texture_usages.into();
|
||||
}
|
||||
}
|
||||
@ -13,6 +13,8 @@ use smaa::SmaaPlugin;
|
||||
use taa::TemporalAntiAliasPlugin;
|
||||
|
||||
pub mod contrast_adaptive_sharpening;
|
||||
#[cfg(feature = "dlss")]
|
||||
pub mod dlss;
|
||||
pub mod fxaa;
|
||||
pub mod smaa;
|
||||
pub mod taa;
|
||||
@ -21,6 +23,13 @@ pub mod taa;
|
||||
pub struct AntiAliasingPlugin;
|
||||
impl Plugin for AntiAliasingPlugin {
|
||||
fn build(&self, app: &mut bevy_app::App) {
|
||||
app.add_plugins((FxaaPlugin, SmaaPlugin, TemporalAntiAliasPlugin, CasPlugin));
|
||||
app.add_plugins((
|
||||
FxaaPlugin,
|
||||
SmaaPlugin,
|
||||
TemporalAntiAliasPlugin,
|
||||
CasPlugin,
|
||||
#[cfg(feature = "dlss")]
|
||||
dlss::DlssPlugin,
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,6 +31,7 @@ pub mod graph {
|
||||
Wireframe,
|
||||
LateDownsampleDepth,
|
||||
Taa,
|
||||
Dlss,
|
||||
MotionBlur,
|
||||
Bloom,
|
||||
AutoExposure,
|
||||
|
||||
@ -73,6 +73,9 @@ tonemapping_luts = ["bevy_core_pipeline/tonemapping_luts"]
|
||||
# Include SMAA LUT KTX2 Files
|
||||
smaa_luts = ["bevy_anti_aliasing/smaa_luts"]
|
||||
|
||||
# NVIDIA Deep Learning Super Sampling
|
||||
dlss = ["bevy_anti_aliasing/dlss", "bevy_render/dlss"]
|
||||
|
||||
# Audio format support (vorbis is enabled by default)
|
||||
flac = ["bevy_audio/flac"]
|
||||
mp3 = ["bevy_audio/mp3"]
|
||||
|
||||
@ -51,6 +51,7 @@ webgpu = ["wgpu/webgpu"]
|
||||
detailed_trace = []
|
||||
## Adds serialization support through `serde`.
|
||||
serialize = ["bevy_mesh/serialize"]
|
||||
dlss = ["dep:dlss_wgpu"]
|
||||
|
||||
[dependencies]
|
||||
# bevy
|
||||
@ -100,6 +101,7 @@ wgpu = { version = "25", default-features = false, features = [
|
||||
"fragile-send-sync-non-atomic-wasm",
|
||||
] }
|
||||
naga = { version = "25", features = ["wgsl-in"] }
|
||||
dlss_wgpu = { path = "../../../dlss_wgpu", optional = true }
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
bytemuck = { version = "1.5", features = ["derive", "must_cast"] }
|
||||
downcast-rs = { version = "2", default-features = false, features = ["std"] }
|
||||
|
||||
@ -104,7 +104,7 @@ use crate::{
|
||||
mesh::{MeshPlugin, MorphPlugin, RenderMesh},
|
||||
render_asset::prepare_assets,
|
||||
render_resource::{PipelineCache, Shader, ShaderLoader},
|
||||
renderer::{render_system, RenderInstance},
|
||||
renderer::render_system,
|
||||
settings::RenderCreation,
|
||||
storage::StoragePlugin,
|
||||
view::{ViewPlugin, WindowRenderPlugin},
|
||||
@ -113,11 +113,9 @@ use alloc::sync::Arc;
|
||||
use bevy_app::{App, AppLabel, Plugin, SubApp};
|
||||
use bevy_asset::{AssetApp, AssetServer};
|
||||
use bevy_ecs::{prelude::*, schedule::ScheduleLabel};
|
||||
use bevy_utils::WgpuWrapper;
|
||||
use bitflags::bitflags;
|
||||
use core::ops::{Deref, DerefMut};
|
||||
use std::sync::Mutex;
|
||||
use tracing::debug;
|
||||
|
||||
/// Inline shader as an `embedded_asset` and load it permanently.
|
||||
///
|
||||
@ -346,6 +344,14 @@ impl Plugin for RenderPlugin {
|
||||
.ok()
|
||||
.cloned();
|
||||
let settings = render_creation.clone();
|
||||
|
||||
#[cfg(feature = "dlss")]
|
||||
let dlss_project_id = app
|
||||
.world()
|
||||
.get_resource::<DlssProjectId>()
|
||||
.expect("The `dlss` feature is enabled, but DlssProjectId was not added to the App before DefaultPlugins.")
|
||||
.0;
|
||||
|
||||
let async_renderer = async move {
|
||||
let instance = wgpu::Instance::new(&wgpu::InstanceDescriptor {
|
||||
backends,
|
||||
@ -385,24 +391,16 @@ impl Plugin for RenderPlugin {
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let (device, queue, adapter_info, render_adapter) =
|
||||
renderer::initialize_renderer(
|
||||
&instance,
|
||||
&settings,
|
||||
&request_adapter_options,
|
||||
)
|
||||
.await;
|
||||
debug!("Configured wgpu adapter Limits: {:#?}", device.limits());
|
||||
debug!("Configured wgpu adapter Features: {:#?}", device.features());
|
||||
let mut future_render_resources_inner =
|
||||
future_render_resources_wrapper.lock().unwrap();
|
||||
*future_render_resources_inner = Some(RenderResources(
|
||||
device,
|
||||
queue,
|
||||
adapter_info,
|
||||
render_adapter,
|
||||
RenderInstance(Arc::new(WgpuWrapper::new(instance))),
|
||||
));
|
||||
let render_resources = renderer::initialize_renderer(
|
||||
instance,
|
||||
&settings,
|
||||
&request_adapter_options,
|
||||
#[cfg(feature = "dlss")]
|
||||
dlss_project_id,
|
||||
)
|
||||
.await;
|
||||
|
||||
*future_render_resources_wrapper.lock().unwrap() = Some(render_resources);
|
||||
};
|
||||
// In wasm, spawn a task and detach it for execution
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
@ -475,6 +473,16 @@ impl Plugin for RenderPlugin {
|
||||
if let Some(future_render_resources) =
|
||||
app.world_mut().remove_resource::<FutureRenderResources>()
|
||||
{
|
||||
#[cfg(feature = "dlss")]
|
||||
let RenderResources(
|
||||
device,
|
||||
queue,
|
||||
adapter_info,
|
||||
render_adapter,
|
||||
instance,
|
||||
dlss_available,
|
||||
) = future_render_resources.0.lock().unwrap().take().unwrap();
|
||||
#[cfg(not(feature = "dlss"))]
|
||||
let RenderResources(device, queue, adapter_info, render_adapter, instance) =
|
||||
future_render_resources.0.lock().unwrap().take().unwrap();
|
||||
|
||||
@ -488,6 +496,11 @@ impl Plugin for RenderPlugin {
|
||||
.insert_resource(render_adapter.clone())
|
||||
.insert_resource(compressed_image_format_support);
|
||||
|
||||
#[cfg(feature = "dlss")]
|
||||
if let Some(dlss_available) = dlss_available {
|
||||
app.insert_resource(dlss_available);
|
||||
}
|
||||
|
||||
let render_app = app.sub_app_mut(RenderApp);
|
||||
|
||||
render_app
|
||||
@ -632,3 +645,11 @@ pub fn get_mali_driver_version(adapter: &RenderAdapter) -> Option<u32> {
|
||||
|
||||
None
|
||||
}
|
||||
|
||||
#[cfg(feature = "dlss")]
|
||||
#[derive(Resource)]
|
||||
pub struct DlssProjectId(pub bevy_asset::uuid::Uuid);
|
||||
|
||||
#[cfg(feature = "dlss")]
|
||||
#[derive(Resource, Clone, Copy)]
|
||||
pub struct DlssSupported;
|
||||
|
||||
@ -7,14 +7,14 @@ use bevy_tasks::ComputeTaskPool;
|
||||
use bevy_utils::WgpuWrapper;
|
||||
pub use graph_runner::*;
|
||||
pub use render_device::*;
|
||||
use tracing::{error, info, info_span, warn};
|
||||
use tracing::{debug, error, info, info_span, warn};
|
||||
|
||||
use crate::{
|
||||
diagnostic::{internal::DiagnosticsRecorder, RecordDiagnostics},
|
||||
render_graph::RenderGraph,
|
||||
render_phase::TrackedRenderPass,
|
||||
render_resource::RenderPassDescriptor,
|
||||
settings::{WgpuSettings, WgpuSettingsPriority},
|
||||
settings::{RenderResources, WgpuSettings, WgpuSettingsPriority},
|
||||
view::{ExtractedWindows, ViewTarget},
|
||||
};
|
||||
use alloc::sync::Arc;
|
||||
@ -148,10 +148,11 @@ const GPU_NOT_FOUND_ERROR_MESSAGE: &str = if cfg!(target_os = "linux") {
|
||||
/// Initializes the renderer by retrieving and preparing the GPU instance, device and queue
|
||||
/// for the specified backend.
|
||||
pub async fn initialize_renderer(
|
||||
instance: &Instance,
|
||||
instance: Instance,
|
||||
options: &WgpuSettings,
|
||||
request_adapter_options: &RequestAdapterOptions<'_, '_>,
|
||||
) -> (RenderDevice, RenderQueue, RenderAdapterInfo, RenderAdapter) {
|
||||
#[cfg(feature = "dlss")] dlss_project_id: bevy_asset::uuid::Uuid,
|
||||
) -> RenderResources {
|
||||
let adapter = instance
|
||||
.request_adapter(request_adapter_options)
|
||||
.await
|
||||
@ -309,24 +310,47 @@ pub async fn initialize_renderer(
|
||||
};
|
||||
}
|
||||
|
||||
let (device, queue) = adapter
|
||||
.request_device(&wgpu::DeviceDescriptor {
|
||||
label: options.device_label.as_ref().map(AsRef::as_ref),
|
||||
required_features: features,
|
||||
required_limits: limits,
|
||||
memory_hints: options.memory_hints.clone(),
|
||||
// See https://github.com/gfx-rs/wgpu/issues/5974
|
||||
trace: Trace::Off,
|
||||
})
|
||||
.await
|
||||
.unwrap();
|
||||
let queue = Arc::new(WgpuWrapper::new(queue));
|
||||
let adapter = Arc::new(WgpuWrapper::new(adapter));
|
||||
(
|
||||
let device_descriptor = wgpu::DeviceDescriptor {
|
||||
label: options.device_label.as_ref().map(AsRef::as_ref),
|
||||
required_features: features,
|
||||
required_limits: limits,
|
||||
memory_hints: options.memory_hints.clone(),
|
||||
// See https://github.com/gfx-rs/wgpu/issues/5974
|
||||
trace: Trace::Off,
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "dlss"))]
|
||||
let (device, queue) = adapter.request_device(&device_descriptor).await.unwrap();
|
||||
|
||||
#[cfg(feature = "dlss")]
|
||||
let mut dlss_supported = false;
|
||||
#[cfg(feature = "dlss")]
|
||||
let (device, queue) = {
|
||||
match dlss_wgpu::request_device(dlss_project_id, &adapter, &device_descriptor) {
|
||||
Ok(x) => {
|
||||
dlss_supported = true;
|
||||
x
|
||||
}
|
||||
// Fallback to standard device request
|
||||
Err(_) => adapter.request_device(&device_descriptor).await.unwrap(),
|
||||
}
|
||||
};
|
||||
|
||||
debug!("Configured wgpu adapter Limits: {:#?}", device.limits());
|
||||
debug!("Configured wgpu adapter Features: {:#?}", device.features());
|
||||
|
||||
RenderResources(
|
||||
RenderDevice::from(device),
|
||||
RenderQueue(queue),
|
||||
RenderQueue(Arc::new(WgpuWrapper::new(queue))),
|
||||
RenderAdapterInfo(WgpuWrapper::new(adapter_info)),
|
||||
RenderAdapter(adapter),
|
||||
RenderAdapter(Arc::new(WgpuWrapper::new(adapter))),
|
||||
RenderInstance(Arc::new(WgpuWrapper::new(instance))),
|
||||
#[cfg(feature = "dlss")]
|
||||
if dlss_supported {
|
||||
Some(crate::DlssSupported)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -142,11 +142,12 @@ impl Default for WgpuSettings {
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct RenderResources(
|
||||
pub RenderDevice,
|
||||
pub RenderQueue,
|
||||
pub RenderAdapterInfo,
|
||||
pub RenderAdapter,
|
||||
pub RenderInstance,
|
||||
pub(crate) RenderDevice,
|
||||
pub(crate) RenderQueue,
|
||||
pub(crate) RenderAdapterInfo,
|
||||
pub(crate) RenderAdapter,
|
||||
pub(crate) RenderInstance,
|
||||
#[cfg(feature = "dlss")] pub(crate) Option<crate::DlssSupported>,
|
||||
);
|
||||
|
||||
/// An enum describing how the renderer will initialize resources. This is used when creating the [`RenderPlugin`](crate::RenderPlugin).
|
||||
@ -170,7 +171,16 @@ impl RenderCreation {
|
||||
adapter: RenderAdapter,
|
||||
instance: RenderInstance,
|
||||
) -> Self {
|
||||
RenderResources(device, queue, adapter_info, adapter, instance).into()
|
||||
RenderResources(
|
||||
device,
|
||||
queue,
|
||||
adapter_info,
|
||||
adapter,
|
||||
instance,
|
||||
#[cfg(feature = "dlss")]
|
||||
None,
|
||||
)
|
||||
.into()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -8,7 +8,8 @@ pub use window::*;
|
||||
use crate::{
|
||||
camera::{
|
||||
CameraMainTextureUsages, ClearColor, ClearColorConfig, Exposure, ExtractedCamera,
|
||||
ManualTextureViews, MipBias, NormalizedRenderTarget, TemporalJitter,
|
||||
MainPassResolutionOverride, ManualTextureViews, MipBias, NormalizedRenderTarget,
|
||||
TemporalJitter,
|
||||
},
|
||||
experimental::occlusion_culling::OcclusionCulling,
|
||||
extract_component::ExtractComponentPlugin,
|
||||
@ -912,6 +913,7 @@ pub fn prepare_view_uniforms(
|
||||
Option<&Frustum>,
|
||||
Option<&TemporalJitter>,
|
||||
Option<&MipBias>,
|
||||
Option<&MainPassResolutionOverride>,
|
||||
)>,
|
||||
frame_count: Res<FrameCount>,
|
||||
) {
|
||||
@ -924,13 +926,23 @@ pub fn prepare_view_uniforms(
|
||||
else {
|
||||
return;
|
||||
};
|
||||
for (entity, extracted_camera, extracted_view, frustum, temporal_jitter, mip_bias) in &views {
|
||||
for (
|
||||
entity,
|
||||
extracted_camera,
|
||||
extracted_view,
|
||||
frustum,
|
||||
temporal_jitter,
|
||||
mip_bias,
|
||||
viewport_override,
|
||||
) in &views
|
||||
{
|
||||
let viewport = extracted_view.viewport.as_vec4();
|
||||
let unjittered_projection = extracted_view.clip_from_view;
|
||||
let mut clip_from_view = unjittered_projection;
|
||||
|
||||
if let Some(temporal_jitter) = temporal_jitter {
|
||||
temporal_jitter.jitter_projection(&mut clip_from_view, viewport.zw());
|
||||
let jitter_view_size = viewport_override.map_or(viewport.zw(), |v| v.0.as_vec2());
|
||||
temporal_jitter.jitter_projection(&mut clip_from_view, jitter_view_size);
|
||||
}
|
||||
|
||||
let view_from_clip = clip_from_view.inverse();
|
||||
|
||||
@ -79,6 +79,7 @@ The default feature set enables most of the expected features of a game engine,
|
||||
|debug_glam_assert|Enable assertions in debug builds to check the validity of parameters passed to glam|
|
||||
|default_no_std|Recommended defaults for no_std applications|
|
||||
|detailed_trace|Enable detailed trace event logging. These trace events are expensive even when off, thus they require compile time opt-in|
|
||||
|dlss|NVIDIA Deep Learning Super Sampling|
|
||||
|dynamic_linking|Force dynamic linking, which improves iterative compile times|
|
||||
|embedded_watcher|Enables watching in memory asset providers for Bevy Asset hot-reloading|
|
||||
|experimental_bevy_feathers|Feathers widget collection.|
|
||||
|
||||
@ -21,25 +21,58 @@ use bevy::{
|
||||
},
|
||||
};
|
||||
|
||||
#[cfg(feature = "dlss")]
|
||||
use bevy::anti_aliasing::dlss::{Dlss, DlssPerfQualityMode, DlssProjectId, DlssSupported};
|
||||
|
||||
fn main() {
|
||||
App::new()
|
||||
.add_plugins(DefaultPlugins)
|
||||
let mut app = App::new();
|
||||
|
||||
#[cfg(feature = "dlss")]
|
||||
app.insert_resource(DlssProjectId(bevy_asset::uuid::uuid!(
|
||||
"5417916c-0291-4e3f-8f65-326c1858ab96"
|
||||
)));
|
||||
|
||||
app.add_plugins(DefaultPlugins)
|
||||
.add_systems(Startup, setup)
|
||||
.add_systems(Update, (modify_aa, modify_sharpening, update_ui))
|
||||
.run();
|
||||
.add_systems(Update, (modify_aa, modify_sharpening, update_ui));
|
||||
|
||||
app.run();
|
||||
}
|
||||
|
||||
type TaaComponents = (
|
||||
TemporalAntiAliasing,
|
||||
TemporalJitter,
|
||||
MipBias,
|
||||
MipBias,
|
||||
DepthPrepass,
|
||||
MotionVectorPrepass,
|
||||
);
|
||||
|
||||
#[cfg(feature = "dlss")]
|
||||
type DlssComponents = (
|
||||
Dlss,
|
||||
TemporalJitter,
|
||||
MipBias,
|
||||
DepthPrepass,
|
||||
MotionVectorPrepass,
|
||||
);
|
||||
#[cfg(not(feature = "dlss"))]
|
||||
type DlssComponents = ();
|
||||
|
||||
fn modify_aa(
|
||||
keys: Res<ButtonInput<KeyCode>>,
|
||||
camera: Single<
|
||||
#[cfg(feature = "dlss")] camera: Single<
|
||||
(
|
||||
Entity,
|
||||
Option<&mut Fxaa>,
|
||||
Option<&mut Smaa>,
|
||||
Option<&TemporalAntiAliasing>,
|
||||
&mut Msaa,
|
||||
Option<&mut Dlss>,
|
||||
),
|
||||
With<Camera>,
|
||||
>,
|
||||
#[cfg(not(feature = "dlss"))] camera: Single<
|
||||
(
|
||||
Entity,
|
||||
Option<&mut Fxaa>,
|
||||
@ -49,8 +82,12 @@ fn modify_aa(
|
||||
),
|
||||
With<Camera>,
|
||||
>,
|
||||
#[cfg(feature = "dlss")] dlss_supported: Option<Res<DlssSupported>>,
|
||||
mut commands: Commands,
|
||||
) {
|
||||
#[cfg(feature = "dlss")]
|
||||
let (camera_entity, fxaa, smaa, taa, mut msaa, dlss) = camera.into_inner();
|
||||
#[cfg(not(feature = "dlss"))]
|
||||
let (camera_entity, fxaa, smaa, taa, mut msaa) = camera.into_inner();
|
||||
let mut camera = commands.entity(camera_entity);
|
||||
|
||||
@ -60,7 +97,8 @@ fn modify_aa(
|
||||
camera
|
||||
.remove::<Fxaa>()
|
||||
.remove::<Smaa>()
|
||||
.remove::<TaaComponents>();
|
||||
.remove::<TaaComponents>()
|
||||
.remove::<DlssComponents>();
|
||||
}
|
||||
|
||||
// MSAA
|
||||
@ -68,7 +106,8 @@ fn modify_aa(
|
||||
camera
|
||||
.remove::<Fxaa>()
|
||||
.remove::<Smaa>()
|
||||
.remove::<TaaComponents>();
|
||||
.remove::<TaaComponents>()
|
||||
.remove::<DlssComponents>();
|
||||
|
||||
*msaa = Msaa::Sample4;
|
||||
}
|
||||
@ -92,6 +131,7 @@ fn modify_aa(
|
||||
camera
|
||||
.remove::<Smaa>()
|
||||
.remove::<TaaComponents>()
|
||||
.remove::<DlssComponents>()
|
||||
.insert(Fxaa::default());
|
||||
}
|
||||
|
||||
@ -125,6 +165,7 @@ fn modify_aa(
|
||||
camera
|
||||
.remove::<Fxaa>()
|
||||
.remove::<TaaComponents>()
|
||||
.remove::<DlssComponents>()
|
||||
.insert(Smaa::default());
|
||||
}
|
||||
|
||||
@ -150,8 +191,43 @@ fn modify_aa(
|
||||
camera
|
||||
.remove::<Fxaa>()
|
||||
.remove::<Smaa>()
|
||||
.remove::<DlssComponents>()
|
||||
.insert(TemporalAntiAliasing::default());
|
||||
}
|
||||
|
||||
// DLSS
|
||||
#[cfg(feature = "dlss")]
|
||||
if keys.just_pressed(KeyCode::Digit6) && dlss.is_none() && dlss_supported.is_some() {
|
||||
*msaa = Msaa::Off;
|
||||
camera
|
||||
.remove::<Fxaa>()
|
||||
.remove::<Smaa>()
|
||||
.remove::<TaaComponents>()
|
||||
.insert(Dlss::default());
|
||||
}
|
||||
|
||||
// DLSS Settings
|
||||
#[cfg(feature = "dlss")]
|
||||
if let Some(mut dlss) = dlss {
|
||||
if keys.just_pressed(KeyCode::KeyZ) {
|
||||
dlss.perf_quality_mode = DlssPerfQualityMode::Auto;
|
||||
}
|
||||
if keys.just_pressed(KeyCode::KeyX) {
|
||||
dlss.perf_quality_mode = DlssPerfQualityMode::UltraPerformance;
|
||||
}
|
||||
if keys.just_pressed(KeyCode::KeyC) {
|
||||
dlss.perf_quality_mode = DlssPerfQualityMode::Performance;
|
||||
}
|
||||
if keys.just_pressed(KeyCode::KeyV) {
|
||||
dlss.perf_quality_mode = DlssPerfQualityMode::Balanced;
|
||||
}
|
||||
if keys.just_pressed(KeyCode::KeyB) {
|
||||
dlss.perf_quality_mode = DlssPerfQualityMode::Quality;
|
||||
}
|
||||
if keys.just_pressed(KeyCode::KeyN) {
|
||||
dlss.perf_quality_mode = DlssPerfQualityMode::Dlaa;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn modify_sharpening(
|
||||
@ -179,7 +255,18 @@ fn modify_sharpening(
|
||||
}
|
||||
|
||||
fn update_ui(
|
||||
camera: Single<
|
||||
#[cfg(feature = "dlss")] camera: Single<
|
||||
(
|
||||
Option<&Fxaa>,
|
||||
Option<&Smaa>,
|
||||
Option<&TemporalAntiAliasing>,
|
||||
&ContrastAdaptiveSharpening,
|
||||
&Msaa,
|
||||
Option<&Dlss>,
|
||||
),
|
||||
With<Camera>,
|
||||
>,
|
||||
#[cfg(not(feature = "dlss"))] camera: Single<
|
||||
(
|
||||
Option<&Fxaa>,
|
||||
Option<&Smaa>,
|
||||
@ -190,22 +277,35 @@ fn update_ui(
|
||||
With<Camera>,
|
||||
>,
|
||||
mut ui: Single<&mut Text>,
|
||||
#[cfg(feature = "dlss")] dlss_supported: Option<Res<DlssSupported>>,
|
||||
) {
|
||||
#[cfg(feature = "dlss")]
|
||||
let (fxaa, smaa, taa, cas, msaa, dlss) = *camera;
|
||||
#[cfg(not(feature = "dlss"))]
|
||||
let (fxaa, smaa, taa, cas, msaa) = *camera;
|
||||
|
||||
let ui = &mut ui.0;
|
||||
*ui = "Antialias Method\n".to_string();
|
||||
|
||||
#[cfg(feature = "dlss")]
|
||||
let dlss_none = dlss.is_none();
|
||||
#[cfg(not(feature = "dlss"))]
|
||||
let dlss_none = true;
|
||||
|
||||
draw_selectable_menu_item(
|
||||
ui,
|
||||
"No AA",
|
||||
'1',
|
||||
*msaa == Msaa::Off && fxaa.is_none() && taa.is_none() && smaa.is_none(),
|
||||
*msaa == Msaa::Off && fxaa.is_none() && taa.is_none() && smaa.is_none() && dlss_none,
|
||||
);
|
||||
draw_selectable_menu_item(ui, "MSAA", '2', *msaa != Msaa::Off);
|
||||
draw_selectable_menu_item(ui, "FXAA", '3', fxaa.is_some());
|
||||
draw_selectable_menu_item(ui, "SMAA", '4', smaa.is_some());
|
||||
draw_selectable_menu_item(ui, "TAA", '5', taa.is_some());
|
||||
#[cfg(feature = "dlss")]
|
||||
if dlss_supported.is_some() {
|
||||
draw_selectable_menu_item(ui, "DLSS", '6', dlss.is_some());
|
||||
}
|
||||
|
||||
if *msaa != Msaa::Off {
|
||||
ui.push_str("\n----------\n\nSample Count\n");
|
||||
@ -241,6 +341,28 @@ fn update_ui(
|
||||
draw_selectable_menu_item(ui, "Ultra", 'R', smaa.preset == SmaaPreset::Ultra);
|
||||
}
|
||||
|
||||
#[cfg(feature = "dlss")]
|
||||
if let Some(dlss) = dlss {
|
||||
let pqm = dlss.perf_quality_mode;
|
||||
ui.push_str("\n----------\n\nQuality\n");
|
||||
draw_selectable_menu_item(ui, "Auto", 'Z', pqm == DlssPerfQualityMode::Auto);
|
||||
draw_selectable_menu_item(
|
||||
ui,
|
||||
"UltraPerformance",
|
||||
'X',
|
||||
pqm == DlssPerfQualityMode::UltraPerformance,
|
||||
);
|
||||
draw_selectable_menu_item(
|
||||
ui,
|
||||
"Performance",
|
||||
'C',
|
||||
pqm == DlssPerfQualityMode::Performance,
|
||||
);
|
||||
draw_selectable_menu_item(ui, "Balanced", 'V', pqm == DlssPerfQualityMode::Balanced);
|
||||
draw_selectable_menu_item(ui, "Quality", 'B', pqm == DlssPerfQualityMode::Quality);
|
||||
draw_selectable_menu_item(ui, "DLAA", 'N', pqm == DlssPerfQualityMode::Dlaa);
|
||||
}
|
||||
|
||||
ui.push_str("\n----------\n\n");
|
||||
draw_selectable_menu_item(ui, "Sharpening", '0', cas.enabled);
|
||||
|
||||
@ -260,7 +382,7 @@ fn setup(
|
||||
) {
|
||||
// Plane
|
||||
commands.spawn((
|
||||
Mesh3d(meshes.add(Plane3d::default().mesh().size(50.0, 50.0))),
|
||||
Mesh3d(meshes.add(Plane3d::default().mesh().size(20.0, 20.0))),
|
||||
MeshMaterial3d(materials.add(Color::srgb(0.1, 0.2, 0.1))),
|
||||
));
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user