NVIDIA GameWorks Graphics App Framework and Libraries
The Graphics sample applications all leverage a cross-platform application framework and helper libraries in order to streamline and unify the sample code, and offer ease-of-use to developers.
This document covers the following:
Application Framework Overview
The framework consists of a few libraries that each implement a particular reusable feature area:
- NvAppBase
Provides the raw application structure, with needed methods, callbacks, and event loop to execute on various platforms. It also includes abstractions for timing, mouse/touch input, keyboard input, gamepad control, and logging.
- NvAssetLoader
Provides basic file reading functionality. On Android, also supports reading files from the AssetManager.
- NvGamepad
Provides abstraction of gamepad input across platforms -- specifically, it implements support for Windows XInput and Android gamepad devices at this time.
- NvGLUtils
Provides a number of helper classes for managing GL-related data -- including a GLSL program loader, and an image class focused on textures for the API.
- NvImage
Cross-platform and API-agnostic image code, including an image loader focused on DDS files/data.
- NvModel
Provides a number of helper classes for loading and managing geometric model files -- including loading simple OBJ files, rendering, transforming and optimizing the content.
- NvUI
Provides a user interface framework for many standard 2D widgets, as well as the specific "TweakBar" UI used in the sample applications.
- NvVKUtil
Provides a number of helper classes for managing Vulkan-related data -- including a SPIR-V program loader, and an image class focused on textures for the API.
The following sections introduce the classes that are provided in each library.
NvAppBase
The NVAppBase library exports a set of classes that make it easy to create simple Vulkan, OpenGL and OpenGL ES applications that run on Windows, Android and Linux from a single source base. The basic functionalities of application lifecycle, input handling and mapping, window handling, file loading OpenGL context creation and interactive mainloop are all in place, leaving the application author to focus on the content of the application itself.
class NvAppBase
NvAppBase serves as a base class for applications and a base implementation of core application functionality. It includes callback functions for all forms of user input, rendering, initialization and shutdown. It provides access to platform functionalities like the OpenGL context, the game controllers (if any) and status information.
Most applications will not subclass NvAppBase directly, as far more functionality is available via the subclass NvSampleApp.
NvAppBase exposes the key startup function that all applications must define and implement: NvAppFactory. This function is declared and called in the NvAppBase library, but must be defined by the application. Each application creates an instance of itself in this function and returns it to the caller. This is how the application framework bootstraps itself.
class NvSampleApp
NvSampleApp inherits from NvAppBase and adds a host of functionalities that are used by all of the sample applications in the samples pack. These include built-in:
- NvInputTransformer object and update calls to the object so that the application can implement a user-controlled object or camera by simply setting the desired interaction mode and querying the latest transform matrices.
- NvTweakBar UI for easy creation of basic "parameter tuning" dialogs.
- Framerate counter for displaying the mean frame rate in the UI.
- Test mode to allow for unattended application testing and reporting.
Two subclasses of NvSampleApp, NvSampleAppVK and NvSampleAppGL add API-specific graphics context functions. These give dire3ct access to useful API objects (devices, queues, etc). Since most samples are either GL or VK and not both, this further subclassing enforces no new limitations.
All of the sample applications are subclasses of either NvSampleAppGL or NvSampleAppVK as appropriate, adding as needed to the initialization, rendering, update and input-handling functions. However, the availability of the built-in UI and input mapping objects means that extremely few (if any) samples need to explicitly override the input handling.
class NvPlatformContext
NvPlatformContext exports important platform functionalities to be used by both the framework and the app itself, including:
- Flags indicating whether the application should exit, whether it is the currently-focused application, whether the app has lost its GL context, etc.
- The ability to request that the app exit.
- The gamepad object (if gamepads are supported on the platform).
- The command-line arguments or properties used to launch the application.
class NvAppContext
NvAppContext provides cross-platform and cross-API access to the generic graphics-related functionalities and queries. These include:
- Binding and unbinding the context to/from the current thread.
- Swapping (presenting).
- Querying the width and height of the main window surface.
- Querying platform capabilities.
class NvStopWatch
NvStopWatch provides cross-platform timer functionalities for timing application operations and doing animations based on wall-clock time.
class NvFramerateCounter
NvFramerateCounter provides and easy encapsulation for measuring and computing the mean frame rate of an application over an adjustable window of frames and time. The application need do no more than signal the end of each frame.
class NvInputTransformer
NvInputTransformer automatically maps touch, mouse and gamepad input events into OpenGL-ready transform matrices. It can generate different interaction paradigms, such as "camera orbits object (virtual trackball)", "First-person shooter" and "2D pan-and-zoom". The functions in NvInputTransformer that accept input events filter them and will return whether the event should be "eaten" by the interaction method, or whether the events were ignored and should be passed on for further processing. Methods also allow the application to define starting location and orientation, as well as initial rotational and linear velocities.
NvAssetLoader
NvAssetLoader provides functions that allow applications to load asset files into memory on all supported platforms. On Windows and Linux, assets are read from directories on the local filesystem, while on Android, the assets are ready from the application's APK pack.
NvGamepad
NvGamepad is a cross-platform gamepad class that makes it easy for applications to query the status of connected gamepads. This support includes digital buttons as well as analog axes. A logical clock is implemented per gamepad to allow applications to quickly determine if any gamepad axes or buttons have changed since the last query. NvGamepad is abstract and serves as the client-side interface for using gamepads.
NvGamepadAndroid and NvGamepadXInput are concrete implementations of NvGamepad for Android and XINPUT-supporting (Win32) platforms. Applications using a cross-platform app framework will likely never deal with these subclasses directly. They will be given pointers to them, cast to the base NvGamepad class. The only interfaces these subclasses add are platform-specific methods of passing input events so that the current gamepad status is kept up-to-date.
NvGLUtils
The NvGLUtils package is a collection of classes designed to simplify common rendering-related operations without attempting to "abstract away" OpenGL.
namespace NvImageGL
NvImageGL Functions for loading NvImage objects into GL textures.
class NvModelGL
NvModelGL loads OBJ data from asset files or from memory blocks. It formats them for rendering via OpenGL and provides functions to render the objects using the application's own shaders.
class NvShapesGL
NvShapesGL includes simple functions to draw basic primitives like rectangles, points and lines using the applications own shaders.
class NvGLSLProgram
NvGLSLProgram supports loading and binding of GLSL shader programs as well as common uniform and attribute operations. GLSL shaders can be loaded from asset files or strings; there are convenience functions for the common vertex-plus-fragment shader case, but all forms of shaders can be loaded, including extensions such as Compute Shadrs. While not the top performance, for simple samples, uniforms and attributes can be set by string name as well as by index.
class NvSimpleFBO
NvSimpleFBO wraps framebuffer object creation with some simple APIs and makes it easy to create and bind FBOs. Both color and depth texture buffers are supported.
NvImage
NvImage includes lightweight geometry loaders and optimizers designed to load OBJ files for rendering under OpenGL.
NvModel
NvModel includes lightweight geometry loaders and optimizers designed to load OBJ files for rendering under OpenGL.
NvUI
NvUI is a cross-platform, GL/GLES-based user interface widget framework. It includes support for typical elements like icons/graphics, frames, text, buttons, progress bars and sliders, and popup menus, handling user interaction with widgets and rendering of their visuals. The primary use of NvUI in the sample applications is the construction and handling of the NvTweakBar interface.
NvVKUtil
The NvVKUtil package is a collection of classes designed to simplify common rendering-related operations without attempting to "abstract away" Vulkan.
class NvModelVK
NvModelVK loads OBJ data from asset files or from memory blocks. It formats them for rendering via Vulkan and provides functions to render the objects using the application's own shaders.
NvSampleApp-based Application Flow
At a high level, NvSampleApp-based samples are initialized and run in the following manner:
- The platform's "main" function (built into the NvAppBase library) is started
- The main function calls NvAppFactory to create an instance of NvAppBase. This call is actually defined in the derived application itself and returns a pointer to an object that is an instance of the application class itself (e.g. MyApp), cast to the base class NvAppBase.
- The main function sets up the OpenGL system or wrapper and creates the application window on windowed platforms.
- The main function calls the application object's mainLoop, function. This is normally the implementation in NvSampleApp. This function will loop and not return to main until the application exits.
- The NvSampleApp::mainLoop function loops:
- mainLoop tests if the platform context indicates that it is still running. If not, the mainLoop returns
- mainLoop polls for events from the platform context
- The platform context queries the platform-specific input system (this code is in the NvAppBase library). Any input events are passed to the NvAppBase instance's input functions.
- NvSampleApp's implementation of the NvAppBase input functions:
- Passes the input the NvTweakUI
- If not handled, then the input is passed to the specific app's "handle*Input" and "handleGamepad*" functions
- If not handled, the the input is passed to the NvInputTransformer
- mainLoop calls the app's update function.
- If the rendering context is not yet set up, the mainLoop attempts to set it up via the platform API context
- If the setup succeeds, mainLoop calls the app's initRendering function
- mainLoop then creates the NvTweakUI
- mainLoop calls the app's initUI
- If the rendering context is set up, the mainLoop calls the app's render function.
- mainLoop calls the renderUI function
- Main shuts down all instances and exits
Third-Party Libraries Overview
The framework currently uses some third-party libraries to layer particular functionality: