Overview
NVIDIA Flow is a realtime sparse voxel fluid simulation. It includes a combustion model for the creation of fire and smoke effects. The simulation runs on GPU and is implemented in HLSL.
Flow by default dynamically allocates 32x16x16 voxel blocks based on emitters and feedback from the simulation. There is no bounding box limiting allocation, so the domain is only limited by 32-bit precision and the configurable maximum blocks in the pool.
Flow Context
Flow provides shader bytecode targeted for Vulkan and DX12 (DX11 might work, but is not tested). The NvFlowContext interface provides a very high level abstraction to allow the Flow simulation to request GPU resources. This high level interface provides the needed flexibility to work in many different implementations based on Vulkan/DX12. Implementations can even choose behave completely asynchronous. The provided NvFlowContextOpt is an example of this. A default Vulkan implementation is provided, and includes support for interop using shared buffers and semaphores.
Latency is described using getCurrentFrame() and getLastFrameCompleted(). This allows for arbitrarily high latency, with the caveat higher latency can lead to more resource allocation calls.
Flow Reflection
Flow includes builtin reflection for all simulation parameters. This reduces maintenance on integrations, and allows new parameters to be exposed while maintaining binary compatibility. Parameters are stored in C style POD structs, and reflection information is provided for each struct with the suffix convention {struct_name}_NvFlowReflectDatatype. Default values are also provided, with {struct_name}_default naming convention.
In addition to the low level NvFlowReflect system, NvFlowDatabase is provided as an optional/reference utility for the traversal of the reflection data. NvFlowDatabase also includes versioning, designed to allow Flow parameters to be updated one thread asynchronous to another thread reading an older snapshot. This is useful for systems that have a dedicated rendering thread. Versioning uses the same mechanism as NvFlowContext, tracking a latest version and a min active version to avoid freeing data that might still be needed.
The NvFlowGridParams provides a registry of the supported Flow types. It also serves as a thread safe pipe for sending Flow parameters from one thread to another. It includes management of the version numbers used by NvFlowDatabase.
Flow Operators
NvFlowOp provides a standard interface for different components of the Flow simulation. Combined with the reflection system, it enables Flow operator to be dynamically exposed to a node graph. At the same time, it also provides a straightforward C interface, allowing for compile time graphs to be created.
Flow Sparse
NvFlowSparse serves as the foundation for management of Flow blocks. It accepts an unsorted list of integer block locations and allocates blocks while also enforcing a maximum number of locations. It builds the structured needed to then accelerate access to the active blocks. It also includes support for building NanoVDB structures for fast export.
Flow Grid
Flow Grid serves as the default container connecting NvFlowOp and NvFlowSparse together to form a complete simulation, with optional rendering. It is generally called by the rendering thread, since calls in this interface produces many NvFlowContext calls. Also included is the NvFlowGridOp layer, this embeds NvFlowContextOp in order to reduce total VRAM usage by analyzing the graph in NvFlowGrid.