NVRHI (NVIDIA Rendering Hardware Interface)
repository·main·Indexed 24 days ago
https://github.com/nvidia-rtx/nvrhiA high-level graphics abstraction library providing a unified interface for Direct3D 11, Direct3D 12, and Vulkan 1.3. NVRHI simplifies modern graphics programming by automating resource lifetime management, state tracking, and barrier placement. It supports Graphics, Compute, Ray Tracing, and Meshlet pipelines, and offers optional integration with NVAPI and RTXMU for advanced acceleration structure management.
What's inside NVRHI
- NVRHI (NVIDIA Rendering Hardware Interface) is a library that provides a common abstraction layer over multiple graphics APIs (GAPIs), specifically Direct3D 11, Direct3D 12, and Vulkan 1.3. It is designed to facilitate the portability of rendering code across different APIs while providing high-performance features like automatic resource state tracking, deferred resource destruction, and parallel command list recording. It supports Graphics, Compute, Ray Tracing, and Meshlet pipelines.
Ray Tracing Support Overview
mainNVRHI provides hardware-accelerated ray tracing support for both Vulkan and D3D12. It supports two primary methods:
- Ray Tracing Pipelines: Uses
KHR_ray_tracing_pipeline(Vulkan) or DXR 1.0 (D3D12). - Ray Queries: Uses
KHR_ray_query(Vulkan) or DXR 1.1TraceRayInline(D3D12).
Both methods share the same underlying acceleration structure model (TLAS and BLAS).
- Ray Tracing Pipelines: Uses
Understand the NVRHI programming model
mainNVRHI uses a programming model that blends DX11, DX12, and Vulkan. Key characteristics include:
- Resource Lifetime Management: Unlike modern GAPIs where the application manages everything, NVRHI tracks resources, their usage, and GPU completion. It handles automatic resource state tracking and barrier placement.
- Automatic Data Handling: The library manages GPU data uploads and scratch buffers for ray tracing acceleration structure builds.
- Coarse-grained API: The API is more structured than DX11, utilizing Pipeline State Objects (PSOs), graphics state structures, and binding layouts/sets. This reduces API call overhead through efficient state caching.
- Deferred Destruction: Resources are not destroyed immediately when released by the application. Instead, they are destroyed when their reference count reaches zero and the GPU is no longer using them. You must call
IDevice::runGarbageCollection()at least once per frame to perform actual destruction.
Implement Bindless Rendering with Descriptor Tables
mainFor modern techniques like ray tracing that require dynamic indexing, NVRHI provides bindless support.
Bindless Layouts:
- Implement
IBindingLayout. - Created via
IDevice::createBindlessLayout. - Specify shader visibility, register spaces (DX12), and maximum capacity (Vulkan).
Descriptor Tables:
- The runtime counterpart to bindless layouts; they implement
IBindingSet. - They are untyped arrays of resource bindings with variable size (DX12) that can be modified after creation.
- Use
IDevice::writeDescriptorTableto add a resource, or useResourceType::Noneto erase a binding.
Warning: Descriptor tables do not keep strong references to resources. You must manually manage resource lifetimes and ensure correct synchronization/barriers. It is recommended to use only permanent resources in descriptor tables.
- Implement
Integrate RTXMU with NVRHI
mainNVRHI provides optional integration with the RTXMU library for managing bottom-level ray tracing acceleration structures (BLAS).
Setup Steps:
- Set the CMake variable
NVRHI_WITH_RTXMUtoON. This triggers an automatic download of RTXMU viaFetchContent. - (Optional) Configure
NVRHI_RTXMU_GIT_REPOSITORY,NVRHI_RTXMU_GIT_TAG, orNVRHI_RTXMU_FETCH_DIRto customize the download.
Usage: When enabled, all BLAS'es are managed by RTXMU. If a BLAS is built with the
AllowCompactionflag, it will be automatically compacted when you call theICommandList::compactBottomLevelAccelStructsmethod.- Set the CMake variable
How Binding Layouts and Sets work together
mainNVRHI uses a symmetrical two-part system for resource binding:
Binding Layouts (
IBindingLayout): Declare what resources will be used (type and slot).- Items are
BindingLayoutItemstructures specifyingResourceType(e.g.,Texture_SRV,VolatileConstantBuffer) and the binding slot (e.g.,t#for SRVs). - Layouts define shader visibility, register space (DX12), and array sizes.
- Layouts are used to create pipelines (graphics, compute, etc.).
- Items are
Binding Sets (
IBindingSet): Provide the actual resources for a layout.- Items are
BindingSetItemstructures specifying the resource, slot, and array index. - They handle subresource details (like specific mip levels or slices) automatically.
- Binding sets are used when issuing commands via
ICommandList::setGraphicsStateorsetComputeState.
- Items are
Important Lifecycle Notes:
- Both are immutable once created.
- Binding sets keep strong references to their resources. To improve CPU performance for long-lived sets, set
BindingSetDesc::trackLiveness = false, but you must then manually ensure the GPU is finished with the resources before releasing the set.
Manage resource lifetime with RefCountPtr and handles
mainAll NVRHI resources (pipelines, textures, etc.) derive from
IResource, which follows the COM reference counting model (AddRef/Release).- Automatic Reference Counting: Use the
RefCountPtr<T>template to automate lifetime management. - Resource Handles: NVRHI defines type-specific handles using
RefCountPtr. For example,typedef RefCountPtr<ITexture> TextureHandle. - Function Compatibility: Any function accepting a raw resource pointer can be passed a handle, as it will automatically convert the pointer into a strong reference.
- Fire and Forget: You can create resources or pipelines in a local scope, record commands, and exit the scope; the library will ensure they persist until the GPU work is complete.
- Automatic Reference Counting: Use the
Configure resource state tracking and barriers
mainNVRHI automates resource state transitions and barrier placement. Because command lists can be recorded in parallel and executed out of order, you must provide hints to the command list about resource states.
Three ways to manage states:
- Explicit Transitions: Use
beginTrackingTexture/BufferStateto provide the prior state at the start of a command list, andsetTexture/BufferStateat the end to set the desired exit state. - Initial State Tracking: Create resources with the
keepInitialStatedescriptor set totrue. The command list will assume the resource enters in itsinitialStateand transitions it back to that state upon exiting. - Permanent States: Call
setPermanentTexture/BufferStatefor static resources (like material textures). These resources do not require state tracking and are cheaper on the CPU.
Controlling UAV Barriers:
- NVRHI automatically places UAV barriers between successive uses of a resource in
UnorderedAccessstate. - Disable automatic UAV barriers: Use
setEnableUavBarriersForTexture/Buffer(bool enable)to temporarily stop automatic barriers (useful for overlapping shader accesses). - Manual UAV barriers: Use
nvrhi::utils::texture/bufferUavBarrierto place barriers manually. - Manual Mode: Use
setEnableAutomaticBarriers(false)to disable all automatic barrier placement. In this mode, you must manually manage all transitions usingsetTexture/BufferStateand callcommitBarriers()to push them to the GAPI.
- Explicit Transitions: Use
Work with Framebuffers and FramebufferInfo
mainA
IFramebufferis an immutable collection of up to 8 render targets and a depth target.While framebuffers were previously required to create pipelines, you now only need a
FramebufferInfostructure to create a graphics or meshlet pipeline. This structure defines the render target counts, formats, and multisampling configuration. A pipeline created with a specificFramebufferInfocan be used with anyIFramebufferthat shares the same info. You can retrieve this info from a framebuffer usingIFramebuffer::getFramebufferInfo.Introduction to the NVRHI Tutorial
mainThis tutorial guides developers through integrating NVRHI into an application and using its APIs to render objects using both rasterization and ray tracing pipelines.Initialize an IDevice for your GAPI
mainNVRHI does not create the underlying GAPI device. You must provide the existing device to NVRHI using backend-specific creation functions:
- D3D11:
nvrhi::d3d11::createDevicein<nvrhi/d3d11.h> - D3D12:
nvrhi::d3d12::createDevicein<nvrhi/d3d12.h> - Vulkan:
nvrhi::vulkan::createDevicein<nvrhi/vulkan.h> - Validation:
nvrhi::validation::createDevicein<nvrhi/validation.h>(wraps anotherIDeviceto intercept and validate calls).
Note for DX12 and Vulkan: You must provide up to 3 queues during
IDevicecreation: graphics (required), compute, and copy (optional).- D3D11:
Enable NVRHI Validation Layers
mainYou can wrap your existing
nvrhi::DeviceHandlewith a validation layer to catch errors. This is done usingnvrhi::validation::createValidationLayer.#include <nvrhi/validation.h> if (enableValidation) { nvrhi::DeviceHandle nvrhiValidationLayer = nvrhi::validation::createValidationLayer(nvrhiDevice); nvrhiDevice = nvrhiValidationLayer; // make the rest of the application go through the validation layer }