Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bevyengine
GitHub Repository: bevyengine/bevy
Path: blob/main/crates/bevy_anti_alias/src/dlss/mod.rs
9412 views
1
//! NVIDIA Deep Learning Super Sampling (DLSS).
2
//!
3
//! DLSS uses machine learning models to upscale and anti-alias images.
4
//!
5
//! Requires a NVIDIA RTX GPU, and the Windows/Linux Vulkan rendering backend. Does not work on other platforms.
6
//!
7
//! See https://github.com/bevyengine/dlss_wgpu for licensing requirements and setup instructions.
8
//!
9
//! # Usage
10
//! 1. Enable Bevy's `dlss` feature
11
//! 2. During app setup, insert the `DlssProjectId` resource before `DefaultPlugins`
12
//! 3. Check for the presence of `Option<Res<DlssSuperResolutionSupported>>` at runtime to see if DLSS is supported on the current machine
13
//! 4. Add the `Dlss` component to your camera entity, optionally setting a specific `DlssPerfQualityMode` (defaults to `Auto`)
14
//! 5. Optionally add sharpening via `ContrastAdaptiveSharpening`
15
//! 6. Custom rendering code, including third party crates, should account for the optional `MainPassResolutionOverride` to work with DLSS (see the `custom_render_phase` example)
16
17
mod extract;
18
mod node;
19
mod prepare;
20
21
pub use dlss_wgpu::DlssPerfQualityMode;
22
23
use bevy_app::{App, Plugin};
24
use bevy_camera::Hdr;
25
use bevy_core_pipeline::{
26
prepass::{DepthPrepass, MotionVectorPrepass},
27
schedule::{Core3d, Core3dSystems},
28
};
29
use bevy_ecs::prelude::*;
30
use bevy_math::{UVec2, Vec2};
31
use bevy_post_process::bloom::bloom;
32
use bevy_reflect::{reflect_remote, Reflect};
33
use bevy_render::{
34
camera::{MipBias, TemporalJitter},
35
renderer::{
36
raw_vulkan_init::{AdditionalVulkanFeatures, RawVulkanInitSettings},
37
RenderDevice, RenderQueue,
38
},
39
texture::CachedTexture,
40
view::prepare_view_targets,
41
ExtractSchedule, Render, RenderApp, RenderSystems,
42
};
43
use dlss_wgpu::{
44
ray_reconstruction::{
45
DlssRayReconstruction, DlssRayReconstructionDepthMode, DlssRayReconstructionRoughnessMode,
46
},
47
super_resolution::DlssSuperResolution,
48
FeatureSupport,
49
};
50
use std::{
51
marker::PhantomData,
52
ops::Deref,
53
sync::{Arc, Mutex},
54
};
55
use tracing::info;
56
use uuid::Uuid;
57
58
/// Initializes DLSS support in the renderer. This must be registered before [`RenderPlugin`](bevy_render::RenderPlugin) because
59
/// it configures render init code.
60
#[derive(Default)]
61
pub struct DlssInitPlugin;
62
63
impl Plugin for DlssInitPlugin {
64
#[allow(unsafe_code)]
65
fn build(&self, app: &mut App) {
66
let dlss_project_id = app.world().get_resource::<DlssProjectId>()
67
.expect("The `dlss` feature is enabled, but DlssProjectId was not added to the App before DlssInitPlugin.").0;
68
let mut raw_vulkan_settings = app
69
.world_mut()
70
.get_resource_or_init::<RawVulkanInitSettings>();
71
72
// SAFETY: this does not remove any instance features and only enables features that are supported
73
unsafe {
74
raw_vulkan_settings.add_create_instance_callback(
75
move |mut args, additional_vulkan_features| {
76
let mut feature_support = FeatureSupport::default();
77
match dlss_wgpu::register_instance_extensions(
78
dlss_project_id,
79
&mut args,
80
&mut feature_support,
81
) {
82
Ok(_) => {
83
if feature_support.super_resolution_supported {
84
additional_vulkan_features.insert::<DlssSuperResolutionSupported>();
85
}
86
if feature_support.ray_reconstruction_supported {
87
additional_vulkan_features
88
.insert::<DlssRayReconstructionSupported>();
89
}
90
}
91
Err(_) => {}
92
}
93
},
94
);
95
}
96
97
// SAFETY: this does not remove any device features and only enables features that are supported
98
unsafe {
99
raw_vulkan_settings.add_create_device_callback(
100
move |mut args, adapter, additional_vulkan_features| {
101
let mut feature_support = FeatureSupport::default();
102
match dlss_wgpu::register_device_extensions(
103
dlss_project_id,
104
&mut args,
105
adapter,
106
&mut feature_support,
107
) {
108
Ok(_) => {
109
if feature_support.super_resolution_supported {
110
additional_vulkan_features.insert::<DlssSuperResolutionSupported>();
111
} else {
112
additional_vulkan_features.remove::<DlssSuperResolutionSupported>();
113
}
114
if feature_support.ray_reconstruction_supported {
115
additional_vulkan_features
116
.insert::<DlssRayReconstructionSupported>();
117
} else {
118
additional_vulkan_features
119
.remove::<DlssRayReconstructionSupported>();
120
}
121
}
122
Err(_) => {}
123
}
124
},
125
)
126
};
127
}
128
}
129
130
/// Enables DLSS support. This requires [`DlssInitPlugin`] to function, which must be manually registered in the correct order
131
/// prior to registering this plugin.
132
#[derive(Default)]
133
pub struct DlssPlugin;
134
135
impl Plugin for DlssPlugin {
136
fn build(&self, app: &mut App) {
137
app.register_type::<Dlss<DlssSuperResolutionFeature>>()
138
.register_type::<Dlss<DlssRayReconstructionFeature>>();
139
}
140
141
fn finish(&self, app: &mut App) {
142
let (super_resolution_supported, ray_reconstruction_supported) = {
143
let features = app
144
.sub_app_mut(RenderApp)
145
.world()
146
.resource::<AdditionalVulkanFeatures>();
147
(
148
features.has::<DlssSuperResolutionSupported>(),
149
features.has::<DlssRayReconstructionSupported>(),
150
)
151
};
152
if !super_resolution_supported {
153
return;
154
}
155
156
let wgpu_device = {
157
let render_world = app.sub_app(RenderApp).world();
158
let render_device = render_world.resource::<RenderDevice>().wgpu_device();
159
render_device.clone()
160
};
161
let project_id = app.world().get_resource::<DlssProjectId>()
162
.expect("The `dlss` feature is enabled, but DlssProjectId was not added to the App before DlssPlugin.");
163
let dlss_sdk = dlss_wgpu::DlssSdk::new(project_id.0, wgpu_device);
164
if dlss_sdk.is_err() {
165
info!("DLSS is not supported on this system");
166
return;
167
}
168
169
app.insert_resource(DlssSuperResolutionSupported);
170
if ray_reconstruction_supported {
171
app.insert_resource(DlssRayReconstructionSupported);
172
}
173
174
app.sub_app_mut(RenderApp)
175
.insert_resource(DlssSdk(dlss_sdk.unwrap()))
176
.add_systems(
177
ExtractSchedule,
178
(
179
extract::extract_dlss::<DlssSuperResolutionFeature>,
180
extract::extract_dlss::<DlssRayReconstructionFeature>,
181
),
182
)
183
.add_systems(
184
Render,
185
(
186
prepare::prepare_dlss::<DlssSuperResolutionFeature>,
187
prepare::prepare_dlss::<DlssRayReconstructionFeature>,
188
)
189
.in_set(RenderSystems::ManageViews)
190
.before(prepare_view_targets),
191
);
192
193
app.sub_app_mut(RenderApp).add_systems(
194
Core3d,
195
(node::dlss_super_resolution, node::dlss_ray_reconstruction)
196
.chain()
197
.before(bloom)
198
.in_set(Core3dSystems::PostProcess),
199
);
200
}
201
}
202
203
/// Camera component to enable DLSS.
204
#[derive(Component, Reflect, Clone)]
205
#[reflect(Component)]
206
#[require(TemporalJitter, MipBias, DepthPrepass, MotionVectorPrepass, Hdr)]
207
pub struct Dlss<F: DlssFeature = DlssSuperResolutionFeature> {
208
/// How much upscaling should be applied.
209
#[reflect(remote = DlssPerfQualityModeRemoteReflect)]
210
pub perf_quality_mode: DlssPerfQualityMode,
211
/// Set to true to delete the saved temporal history (past frames).
212
///
213
/// Useful for preventing ghosting when the history is no longer
214
/// representative of the current frame, such as in sudden camera cuts.
215
///
216
/// After setting this to true, it will automatically be toggled
217
/// back to false at the end of the frame.
218
pub reset: bool,
219
#[reflect(ignore)]
220
pub _phantom_data: PhantomData<F>,
221
}
222
223
impl Default for Dlss<DlssSuperResolutionFeature> {
224
fn default() -> Self {
225
Self {
226
perf_quality_mode: Default::default(),
227
reset: Default::default(),
228
_phantom_data: Default::default(),
229
}
230
}
231
}
232
233
pub trait DlssFeature: Reflect + Clone + Default {
234
type Context: Send;
235
236
fn upscaled_resolution(context: &Self::Context) -> UVec2;
237
238
fn render_resolution(context: &Self::Context) -> UVec2;
239
240
fn suggested_jitter(
241
context: &Self::Context,
242
frame_number: u32,
243
render_resolution: UVec2,
244
) -> Vec2;
245
246
fn suggested_mip_bias(context: &Self::Context, render_resolution: UVec2) -> f32;
247
248
fn new_context(
249
upscaled_resolution: UVec2,
250
perf_quality_mode: DlssPerfQualityMode,
251
feature_flags: dlss_wgpu::DlssFeatureFlags,
252
sdk: Arc<Mutex<dlss_wgpu::DlssSdk>>,
253
device: &RenderDevice,
254
queue: &RenderQueue,
255
) -> Result<Self::Context, dlss_wgpu::DlssError>;
256
}
257
258
/// DLSS Super Resolution.
259
///
260
/// Only available when the [`DlssSuperResolutionSupported`] resource exists.
261
#[derive(Reflect, Clone, Default)]
262
pub struct DlssSuperResolutionFeature;
263
264
impl DlssFeature for DlssSuperResolutionFeature {
265
type Context = DlssSuperResolution;
266
267
fn upscaled_resolution(context: &Self::Context) -> UVec2 {
268
context.upscaled_resolution().into()
269
}
270
271
fn render_resolution(context: &Self::Context) -> UVec2 {
272
context.render_resolution().into()
273
}
274
275
fn suggested_jitter(
276
context: &Self::Context,
277
frame_number: u32,
278
render_resolution: UVec2,
279
) -> Vec2 {
280
context
281
.suggested_jitter(frame_number, render_resolution.to_array())
282
.into()
283
}
284
285
fn suggested_mip_bias(context: &Self::Context, render_resolution: UVec2) -> f32 {
286
context.suggested_mip_bias(render_resolution.to_array())
287
}
288
289
fn new_context(
290
upscaled_resolution: UVec2,
291
perf_quality_mode: DlssPerfQualityMode,
292
feature_flags: dlss_wgpu::DlssFeatureFlags,
293
sdk: Arc<Mutex<dlss_wgpu::DlssSdk>>,
294
device: &RenderDevice,
295
queue: &RenderQueue,
296
) -> Result<Self::Context, dlss_wgpu::DlssError> {
297
DlssSuperResolution::new(
298
upscaled_resolution.to_array(),
299
perf_quality_mode,
300
feature_flags,
301
sdk,
302
device.wgpu_device(),
303
queue.deref(),
304
)
305
}
306
}
307
308
/// DLSS Ray Reconstruction.
309
///
310
/// Only available when the [`DlssRayReconstructionSupported`] resource exists.
311
#[derive(Reflect, Clone, Default)]
312
pub struct DlssRayReconstructionFeature;
313
314
impl DlssFeature for DlssRayReconstructionFeature {
315
type Context = DlssRayReconstruction;
316
317
fn upscaled_resolution(context: &Self::Context) -> UVec2 {
318
context.upscaled_resolution().into()
319
}
320
321
fn render_resolution(context: &Self::Context) -> UVec2 {
322
context.render_resolution().into()
323
}
324
325
fn suggested_jitter(
326
context: &Self::Context,
327
frame_number: u32,
328
render_resolution: UVec2,
329
) -> Vec2 {
330
context
331
.suggested_jitter(frame_number, render_resolution.to_array())
332
.into()
333
}
334
335
fn suggested_mip_bias(context: &Self::Context, render_resolution: UVec2) -> f32 {
336
context.suggested_mip_bias(render_resolution.to_array())
337
}
338
339
fn new_context(
340
upscaled_resolution: UVec2,
341
perf_quality_mode: DlssPerfQualityMode,
342
feature_flags: dlss_wgpu::DlssFeatureFlags,
343
sdk: Arc<Mutex<dlss_wgpu::DlssSdk>>,
344
device: &RenderDevice,
345
queue: &RenderQueue,
346
) -> Result<Self::Context, dlss_wgpu::DlssError> {
347
DlssRayReconstruction::new(
348
upscaled_resolution.to_array(),
349
perf_quality_mode,
350
feature_flags,
351
DlssRayReconstructionRoughnessMode::Packed,
352
DlssRayReconstructionDepthMode::Hardware,
353
sdk,
354
device.wgpu_device(),
355
queue.deref(),
356
)
357
}
358
}
359
360
/// Additional textures needed as inputs for [`DlssRayReconstructionFeature`].
361
#[derive(Component)]
362
pub struct ViewDlssRayReconstructionTextures {
363
pub diffuse_albedo: CachedTexture,
364
pub specular_albedo: CachedTexture,
365
pub normal_roughness: CachedTexture,
366
pub specular_motion_vectors: CachedTexture,
367
}
368
369
#[reflect_remote(DlssPerfQualityMode)]
370
#[derive(Default)]
371
enum DlssPerfQualityModeRemoteReflect {
372
#[default]
373
Auto,
374
Dlaa,
375
Quality,
376
Balanced,
377
Performance,
378
UltraPerformance,
379
}
380
381
#[derive(Resource)]
382
struct DlssSdk(Arc<Mutex<dlss_wgpu::DlssSdk>>);
383
384
/// Application-specific ID for DLSS.
385
///
386
/// See the DLSS programming guide for more info.
387
#[derive(Resource, Clone)]
388
pub struct DlssProjectId(pub Uuid);
389
390
/// When DLSS Super Resolution is supported by the current system, this resource will exist in the main world.
391
/// Otherwise this resource will be absent.
392
#[derive(Resource, Clone, Copy)]
393
pub struct DlssSuperResolutionSupported;
394
395
/// When DLSS Ray Reconstruction is supported by the current system, this resource will exist in the main world.
396
/// Otherwise this resource will be absent.
397
#[derive(Resource, Clone, Copy)]
398
pub struct DlssRayReconstructionSupported;
399
400