C: DLSS Frame Generation Example#
DLSS Frame Generation makes motion smoother in an interactive viewer by adding color frames between simulated camera frames. You can display these extra frames without increasing the camera simulation rate. It works in Real-Time Path Tracing.
This example shows how to enable the feature, read the returned frames, and save them as PNGs. It moves an NVIDIA logo across a grid so you can see the intermediate positions. To display the frames in a window, use the Vulkan interop example, which also shows how to pace presentation and drop interpolated frames that are no longer needed.
The animation shows all four frames returned by one step on a Blackwell GPU: three interpolated frames followed by the simulated frame.
Hardware Requirements#
Frame generation requires an Ada (RTX 40-series) or newer GPU. The RenderProduct must run on a GPU with an active display attached and use a supported NVIDIA driver and operating system; a GPU used only for display-less rendering does not generate interpolated frames. On unsupported hardware, the example still runs and reports one simulated frame per step. Refer to Hardware & Driver Requirements for driver requirements.
Ada supports one interpolated frame per simulated frame. Blackwell supports up to three. Requests above the hardware maximum are reduced rather than rejected. Refer to DLSS Frame Generation for all requirements.
Build and Run#
Configuring the packaged example requires network access so CMake can download the pinned ovrtx and ovstage archives. The scene ships with the example, so runtime network access is not required.
Prerequisites
sudo apt-get install build-essential cmake
Runtime requires a supported NVIDIA driver and unsandboxed execution.
Building
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build
Running
./build/frame-generation --frames 3
Prerequisites
Visual Studio 2022 17.8 or newer with C++ tools
A supported NVIDIA driver
Unsandboxed runtime execution
Building
cmake -B build
cmake --build build --config Release
Running
.\build\Release\frame-generation.exe --frames 3
Interpreting Results#
The example saves every requested step to the current working directory. The default two steps let you inspect startup and the next capture. A startup or reset step may contain only the simulated frame while interpolation history is established.
On Blackwell, --frames 3 can produce step1_interp0.png, step1_interp1.png, step1_interp2.png, and step1_simulated.png for the second step. Ada supports one interpolated frame, so the same request can produce two files. Requests above the hardware maximum are reduced rather than rejected.
The printed output_frame_count tells you what was returned. For the bundled camera, a count greater than one means frame generation is active. A successful run with one frame per step still rendered and saved the simulated images. If later steps have no interpolated frames, check the feature requirements.
Using Frame Generation in Your Application#
Configure your RenderProduct for Real-Time Path Tracing with a single color output, then enable frame generation. This USD example requests three interpolated frames; the camera at /World/Camera must already exist:
#usda 1.0
def Scope "Render" {
def RenderProduct "Camera" {
int2 resolution = (640, 480)
rel camera = </World/Camera>
rel orderedVars = [<LdrColor>]
token omni:rtx:rendermode = "RealTimePathTracing"
bool omni:rtx:dlss:frameGeneration = 1
int omni:rtx:dlss:frameGenerationInterpolatedFrameCount = 3
def RenderVar "LdrColor" {
string sourceName = "LdrColor"
}
}
}
You can also write these attributes at runtime. This example uses author_frame_generation() in main.cpp to apply the command-line options through ovstage before stepping.
Step the renderer as usual, then select the RenderProduct from the result. For the unscheduled camera used here, every step completes one capture: its interpolated frames come first and its simulated frame comes last. The following code derives their indices from the returned count:
// All returned frames must belong to one completed capture, as in this example.
// Scheduled cameras can return multiple simulated captures, so their total frame
// count cannot classify interpolation. For one capture, frames [0, N) are
// interpolated in presentation order and the last frame is simulated; N is zero
// when frame generation is off or declined.
//
// Never hardcode N. Derive it from output_frame_count on every step -- the count
// can change at runtime when the renderer starts or stops honouring the request.
/// Frame indices for a result containing exactly one completed camera capture.
struct FrameLayout {
size_t interpolated_count; // N
size_t simulated_frame_index; // always output_frame_count - 1
bool frame_generation_active;
};
/// Classify a nonempty, single-capture result; multi-capture steps are unsupported.
FrameLayout classify_output_frames(ovrtx_render_product_output_t const& output) {
FrameLayout layout{};
layout.simulated_frame_index = output.output_frame_count - 1;
layout.interpolated_count = output.output_frame_count - 1;
layout.frame_generation_active = output.output_frame_count > 1;
return layout;
}
Select a frame before looking up its color RenderVar, then map, consume, and unmap the output. Each frame uses the same RenderVar path. The example saves all frames; a viewer should select the frame due for presentation and drop overdue interpolated frames.
Custom --usd scenes must retain the expected /Render/Camera, /Render/LdrColor, and /World/Logo prims and complete exactly one capture per step. A scheduled camera can return several simulated captures in one step, so this example’s count-based classification does not apply to that case.
Options#
Option |
Meaning |
|---|---|
|
Requests a non-negative interpolated frame count. |
|
Sets a positive number of steps to render and save. The default is 2. |
|
Sets how far the logo moves along X per step. The default is 5 world units. |
|
Disables frame generation for comparison with the same scene. |
|
Selects the USD layer to render. The default is the bundled |
Licensing#
This example uses stb_image_write.h from the minimal example, (c) Sean Barrett, released under Public Domain.