-
Notifications
You must be signed in to change notification settings - Fork 14
Aardvark Rendering 5.6 changelog
Aardvark.Rendering 5.6 comes with new features, improvements, and changes that require manual intervention when upgrading existing code. This document outlines the most important changes.
It is now possible to write shaders that make use of 64-bit floating-point data. Up until now, 32-bit and 64-bit floating-point types were treated equally and could be used interchangeably in shaders. FShade compiled those types and values as 32-bit floats, regardless of the original type.
With this Aardvark.Rendering and FShade release, this feature is removed and floating-point types are compiled accurately. This means that existing shaders, which predominantly used 64-bit floats, have to be fixed when upgrading. To this end, use regular expressions with the find-and-replace tool of your IDE or editor:
-
((?:[0-9]*\.[0-9]+)|(?:[0-9]+[eE][-+]?[0-9]+))→$1f -
((?:[vV][2-4])|(?:[mM][2-4][2-4]))d→$1f -
float|double→float32 -
Constant→ConstantF
Make sure to restrict the search to shader-related code only. If you miss a shader, there is a chance that the F# code will not compile due to type changes of built-in uniforms in Aardvark.Rendering. Unfortunately, some broken shaders may compile fine and only fail at runtime. Because of this, the .NET tool fshadeaot has a feature for detecting shaders that still use 64-bit floats:
dotnet tool install -g fshadeaot
fshadeaot -d ./MyApp.dll
This will search the specified assembly and its dependencies recursively for shaders that still need to fixed:
Sky.Shaders.vsSky uses double-based types: Sky.Shaders.VertexSky, Aardvark.Base.V2d, Aardvark.Base.V4d, Aardvark.Base.M44d, Aardvark.Base.V3d, System.Double
The new FShade 5.7 release comes with many more changes and improvements such as support for 8-bit and 16-bit integers and color types. Refer to the release notes for a complete list.
Aardvark.Rendering.ImGui is a wrapper and an Aardvark backend for the excellent Dear ImGui library. It allows users to quickly build GUIs for their applications without having to worry about state synchronization between the application and the user interface.
The integration of ImGui into Aardvark.Rendering means that users may enrich their demo applications showcasing rendering techniques with a proper GUI without having to rely on Aardvark.Media, which is often overkill for simple demo controls. Various examples in Aardvark.Rendering have been improved with simple user interfaces, most notably the reversed depth example.
Adding ImGui to an application is easy:
- Reference
Aardvark.Rendering.ImGuiin your project. - Initialize ImGui for your window:
The window must be created with a GLFW application (
use gui = window.InitializeImGui()
Aardvark.Application.SlimorAardvark.Applcation.Utilities). If you use thewindowbuilder, callwindow.Control.InitializeImGui()instead. - Define your GUI by setting the render function of ImGui:
This function is called every frame to render the GUI. The methods from the
gui.Render <- fun () -> ImGui.ShowDemoWindow()
ImGuiclass contain all the relevant widgets and controls. For convenience, Aardvark.Rendering.ImGui provides variants forcvaland other Aardvark-specific types. As a reference, take a look at the demo window and its source code. - Add the GUI to your scene graph:
Note that
let cmd = RenderCommand.Ordered [scene; gui] window.Scene <- Sg.execute cmd
Aardvark.Rendering.ImGui.InstanceimplementsISgand can be added to the scene graph directly. Make sure that the GUI is rendered after the rest of the scene graph by using render commands.
This release comes with new features and substantial internal changes to the Vulkan backend improving both performance and reliability.
The management of command queues and submission of command buffers has been reworked from scratch. Queue submissions are no longer managed by dedicated worker threads. Instead, thread-exclusive access to an available queue has to be acquired before directly submitting commands to that queue. This minimizes overhead in single threaded scenarios and results in measurable performance improvements in real-world applications.
Our custom memory manager has been replaced by the more sophisticated and well-regarded Vulkan Memory Allocator. In contrast to our previous solution, VMA handles the heterogenous memory types of Vulkan devices effectively and deals with low-memory situations more reliably.
A proper API for device selection has been added. Previously, the selection was controlled by globally registering a function that selects a device from a list of available devices. This release introduces the IDeviceChooser interface that can be passed to the constructors of any application type. By default, the DeviceChooserAuto implementation is used to select the first dedicated device without requiring any user input.
This release brings new features and improvements for raytracing.
The ManagedTracePool now exposes a uniform provider via the Uniforms property, containing the storage buffers of the pool. As a result, users no longer have to manually add these buffers to their own uniform provider. Instead, the provider of the pool can be combined with the provider containing custom uniforms. This is demonstrated in the Raytracing example.
Opacity micromaps are hierarchical data structures that encode opacity information for acceleration structures at a subtriangle level. They can be built from an alpha map and baked into the acceleration structure. During ray traversal, the micromap is queried to determine if the intersection is with opaque or transparent geometry. If the query returns a definitive result, the ray traversal continues accordingly without invoking the any-hit shader. If the query is inconclusive (i.e., the subtriangle covers both transparent and opaque geometry), the any-hit shader is invoked to determine the opacity state by sampling the alpha texture.
Using a micromap may reduce the number of any-hit shader invocations resulting in better performance. Aardvark.OMM is a wrapper around the NVIDIA OMM SDK to bake, save, and load opacity micromaps. The repository comes with an example that demonstrates how to use OMMs with the Aardvark raytracing API.
Note that this feature is not available on all NVIDIA hardware. Use IRuntime.SupportsMicromaps to query for support.
This extension allows raytracing shaders to fetch the position of an intersection directly from the acceleration structure, rather than fetching it from a buffer via indices. Note that this extension may not be available on older hardware. Use IRuntime.SupportsPositionFetch to query the availability of this feature. The Raytracing example demonstrates this feature.
Shader invocation or execution reordering is a feature that aims to improve performance by reducing execution and data divergence. This is achieved by splitting the regular TraceRay() call into two separate steps: Ray traversal and execution of the closest-hit or miss shader.
In between those steps the threads may be reordered according to a sort key:
let ho = HitObject()
ho.TraceRay<V3f>(scene, origin, direction) |> ignore // Perform ray traversal and store results in hit object
Thread.Reorder(ho, key, 1) // Reorder threads based on hit information and user-provided hint
ho.ExecuteShader(payload) // Execute miss or closest-hit shader after reorderingThe sort key can be based on:
- the hit information encoded in the
HitObject. The exact properties from the hit object which are used to reorder the threads are implementation-defined. - a user-provided hint. The second parameter indicates the number of least significant bits of the hint that are taken into account.
- a combination of the hit information and a user-provided hint (as in the example above).
This feature is only available on NVIDIA Ada Lovelace GPUs (RTX 4000 series) or newer. You can query for its support with IRuntime.SupportsInvocationReorder.
This extension identifies potential problems with raytracing applications at driver level that cannot be detected by the validation layers. In order to use it, you have to set an environment variable NV_ALLOW_RAYTRACING_VALIDATION=1 and construct your application with ValidationLayerConfig.RaytracingValidation = true. Note that using this feature may incur a performance overhead.
Some resources (e.g., render tasks, textures, and buffers) now have a Name property that can be used to assign human-readable debug labels. These debug labels are shown in frame captures of programs like NVIDIA Nsight and RenderDoc.
To use this feature, create your application with debug = true or debug = DebugLevel.Normal. For Vulkan you may also want to generate debug information for shaders by passing a DebugConfig with GenerateShaderDebugInfo = true.
In addition to the removal of the double-as-float feature in FShade shaders, this release comes with a number of breaking changes, which are summarized in this section.
TextureParams is now a bit field instead of a record with boolean fields. The utilities of the TextureParams module have been removed and have to be replaced:
-
TextureParams.empty→TextureParams.None -
TextureParams.srgb→TextureParams.PreferSrgb -
TextureParams.compressed→TextureParams.Compress -
TextureParams.mipmapped→TextureParams.WantMipMaps -
TextureParams.mipmappedSrgb→TextureParams.WantMipMaps ||| TextureParams.PreferSrgb -
TextureParams.mipmappedCompressed→TextureParams.WantMipMaps ||| TextureParams.Compress
If you use TextureParams to construct a PixTexture2d orFileTexture with mipmapping, consider using the constructor accepting a boolean parameter wantMipMaps instead. This parameter is optional and true by default. For example:
FileTexture("image.jpg", TextureParams.mipmapped)is equivalent to
FileTexture("image.jpg")Support for indirect buffers has been improved, including the possibility to use a subrange of a buffer as source for an indirect buffer. This results in breaking changes to the API defined in the IndirectBuffer module:
-
ofBuffer (indexed: bool) (stride: int) (count: int) (buffer: IBuffer)now accepts an additional parameteroffset: uint64afterindexed. -
ofArray' (indexed: bool) (calls: DrawCallInfo[])accepts two additional parametersfirst: intandcount: intafterindexed. The same change applies toofList',ofSeq'andofSeqhave been added for convenience.
DrawCalls.Direct has previously stored a list of DrawCallInfo structs. This has been changed to DrawCallInfo[].
The raytracing API also sees various changes that will break existing code:
- Various record types have been reworked as proper classes for better C# interoperability.
-
RaytracingSceneDescriptionhas been renamed toRaytracingScene. - The
AccelerationStructureUsagetype is now a bit field and has been combined with theallowUpdateparameter ofIRuntime.CreateAccelerationStructure(). The newCompactusage indicates that the acceleration structure is to be compacted after building. This reduces memory usage but may incur a runtime overhead for the build. SetDebugConfig.PrintAccelerationStructureCompactionInfototrueto print statistics about the compaction step. This feature is enabled by default forDebugLevel.Normaland above. - Similarly,
GeometryModeis now also a bit field.Opaquehas been renamed toForceOpaque, andTransparenthas been renamed toForceNoOpaque.DisableOpacityMicromapsandForceOpacityMicromapsTwoStateare new values related to opacity micromaps.
The following minor changes may also require your attention:
- [Sg] Simplified
samplerStateapplicator. Now, takes aSamplerStateargument instead ofSamplerState option. - Changed type of
Handleproperty in resource interfaces touint64(https://github.com/aardvark-platform/aardvark.rendering/issues/106) - Removed
RenderTask.cacheandRenderTask.postProcess - Removed
DefaultSemantic.ColorTextureandDefaultSemantic.DepthTexture - Changed return type of
TryGetUniformandTryGetAttributefromOptiontoValueOption - Changed return type of
IGeometryPool.TryGetBufferViewfromOptiontoValueOption - Replaced
CreateTextureAttachment()withGetOutputView()extensions for adaptive textures. These are consistent with the extensions for non-adaptive textures (note parameter order). - [Application.Utilities] Removed
preventDisposalparameter inISimpleRenderWindow.Run(). Disposing the window automatically afterRun()is problematic if GPU resources are created after creating the window. This commit changes theRun()method to never callDispose()automatically. - [BufferView] Reworked
BufferViewconstructors:- Removed
offsetandstrideparameters forISingleValueBufferconstructor. - Added optional
elementTypeparameter forArrayandISingleValueBufferconstructors.
- Removed
- Added optional
discardparameter for buffer upload and copy inIBufferRuntime. The parameter indicates if the implementation may discard the current content of the destination buffer. This may improve performance in scenarios where the buffer is used for rendering operations and updated every frame. On macOS with OpenGL updating a buffer that is currently in use will lead to implicit synchronization and massive stalls. Discarding the current buffer lets OpenGL allocate new storage and perform the copy operation without waiting for the rendering operation. - [ManagedPool] Reworked how attribute data of geometry is represented and handled within the pool. Previously,
PooledGeometryhas been added as an alternative toAdaptiveGeometryto allow for passingSymbolDictfor performance reasons. This is reverted, insteadAdaptiveGeometrycan now hold anyIDictionary.