This folder contains various samples that demonstrate how to use the LiteFX engine. The following table lists the samples and describes the key features.
All samples can be controlled using the following keys:
F7: Toggle V-Sync.F8: Toggle full-screen.F9: Switch to Vulkan backend (if supported).F10: Switch to DirectX 12 backend (if supported).Esc: Exit application.
Note that F11 and F12 are reserved keys, for example to be used by debuggers like Visual Studio, RenderDoc and PIX.
| Number | Name | Description |
|---|---|---|
| 01 | Basic Rendering | This sample shows how to setup a basic renderer using the LiteFX engine. It shows how to create multiple rendering backends and how to switch between them. It also creates the supported backends based on their availability in the build configuration. The application creates a single render pass that exposes a single render pipeline. A vertex and index buffer is created, as well as a constant/uniform buffer for the camera. Multiple back-buffers are used to draw frames in flight. |
| 02 | Render Passes | This sample is an extension of the Basic Rendering sample. It shows how to setup multiple render passes and pass results from earlier passes to input attachments of the next pass. In this example, three render passes are created. One draws the geometry as the earlier example. The other one draws a screen-filling quad that samples the color target of the first render pass. The last one draws an additional geometry on top of the first result |
| 03 | Push Constants | This sample demonstrates how to use push constants. Push constants are an efficient way to pass small chunks of data to shaders. Instead of allocating, binding and managing buffers and descriptors, push constants can directly be put on the command buffer. In this example, different versions of the same object are draws and varying positions and with different colors. |
| 04 | Uniform Arrays | This sample uses uniform buffer arrays to simulate multiple light sources. Instead of creating a buffer for each light source individually, data can be batched together into buffer arrays to pass them in to the shader in a single descriptor. |
| 05 | Textures | This sample demonstrates how to load a texture and how to use it in the shader. Also it shows the integrated support for generating mip-maps. |
| 06 | Multisampling | This sample shows how to use multisampling. It is very similar to the basic rendering sample. All that is required to enable multi-sampling for render targets is to set the desired multi-sampling level when creating a render pass. |
| 07 | Multithreading | This sample uses multiple threads to record command buffers for different objects. It shows how to setup a render pipeline that uses different descriptors for each thread. This is important, so that concurrent writes do not overwrite the descriptor set by another thread. It also shows how to create multiple command buffers from a single frame buffer. |
| 08 | Bindless | This sample demonstrates how to use bindless arrays to draw a variable amount of objects. It allocates 100.000 instances (which can be changed to any number) with random properties, such as color, and rotation axis. It then uses instanced rendering to draw them. |
| 09 | Compute | This sample shows how to use compute and graphics pipelines in combination to implement post-processing effects. It also shows how to distribute workloads amongst different dedicated queues. First, it draws a simple geometry similar to the basic rendering example. It then hands the result to a compute shader that converts the image into a grayscale representation. After that, it copies the result into the presentation frame buffer. |
| 10 | MeshShader | This sample demonstrates the usage of amplification/task and mesh shaders. It removes the vertex and index buffers from the sample and instead uses an amplification shader to emit the primitives of a basic shape. The primitives are then evaluated by a mesh shader and finally drawn into a frame buffer. |
| 11 | RayTracing | This sample shows how to build a complex scene and how to use different hardware ray-tracing techniques in it. It loads a skybox texture that gets sampled if a ray misses any geometry or gets reflected into a miss situation. A simple geometry is loaded into different acceleration structure types and shader-local data is used to change geometry properties. During rendering it demonstrates how to render outside of a render-pass and copy the result into the swap chain back buffer manually. |
| 12 | RayQueries | This sample shows how to perform inline ray-tracing without a dedicated ray-tracing pipeline. It defines a simple rasterization pipeline, that draws a single triangle that fills the entire screen. In the fragment shader, a ray query is created and the intersections are traversed manually. Depending on the intersection event, the ray query continues or exits early. |
| 13 | Indirect | This sample demonstrates indirect rendering. It sets up a series of dummy objects, that are frustum culled in a GPU compute pass, which then fills an indirect draw buffer. This buffer is then used to draw only the objects that are inside the frustum. |
| 14 | DynamicDescriptors | This sample demonstrates the use of dynamic descriptor bindings, i.e., bindings whose type is only determined at bind time, rather than pipeline creation time. It is similar to the Bindless sample, but instead of binding an unbounded runtime array, resources are accessed using the ResourceDescriptorHeap syntax introduced by shader model 6.6. When binding the instance data, instead of calling update on the descriptor set, the same binds dynamic descriptors using the bindToHeap method. This method returns the index to the first descriptor bound, which can directly be passed to the resource descriptor heap from the shader. For this, it needs to be passed to the shader first. In the sample this is done by providing it as a base offset for the instance ID, which is queried using the SV_StartInstanceLocation syntax. |
| 15 | ImGui | This sample demonstrates how to integrate DearImGui. This was previously already possible in the Vulkan backend, however, in the DirectX 12 backend it involved some boilerplate code, creating a dummy descriptor set to be able to allocate descriptors. This sample now uses the externally allocated descriptor range feature available on the DirectX12Device. Using this feature, it is possible to allocate descriptors from the global descriptor heaps directly. ImGui provides callbacks for this case, which are then used to manage the descriptor ranges. |
| 16 | Defragmentation | This sample demonstrates how to use resource defragmentation to optimize memory packing for allocated resources. |
| 17 | Resource Aliasing | Functionally equal to the render pass sample, but it uses overlapping render targets in separate frame buffers to demonstrate how to place and synchronize transient resources in overlapping memory regions. |