- Slang and GLSL shader development platform.
- Shader debbugging utilities.
- Automatic shader reloading.
- Automatic GPU synchronization.
- HDR windows management.
- Multi-threaded background tasks.
- ImGui integration to easily tune parameters.
- Rendering utilities support (Scene, Cameras, Light, Mesh, Materials, ...).
To download the engine:
git clone https://github.com/SuperRonan/VkEngine.git --recurse-submodulesUse this command to pull the submodules if you forgot to do so with the first command:
$ git submodule update --init --recursiveVkEngine also requires the VulkanSDK to be installed. A recent version containing the Slang libraries is required. You can then use CMake to build the engine.
Supported platforms:
- Windows: Supported
- Linux: Not Supported (coming soon)
- MacOs: Not Supported
- Interactive rendering engine.
- Basic scene edition with ImGui (place objects, change some properties, ...)
- Light transport algorithms (Path Tracer, Light tracer, Bidirectional Path Tracer).
- Spectral rendering options.
- More rendering experimentations to come...

Interactive 3D BSDF visualizer.
- Compute statistics (correlation, variance, integral, ...) of different spherical functions.
- Customize the viewed BSDFs by directly changing the shader source code.

It is often tidious to debug shaders. The engine implements shader debugging utilities to ease this process, without using external tools.
debugging.mp4
It is possible to print values (builtin types, vectors, matrices, arrays of builtin, string litterals (in GLSL, wip for Slang) or any type conforming to IPrintable) for quick inspection.
We can place the printing cursor in screen space, or in 3D space to show when the thread emitting the information is.
It is also possible to print lines between two points (to show a traced path for example).
-h, --help shows help message and exits
-v, --version prints version information and exits
--name Name of the Application
--validation Enable Vulkan Validation Layers [nargs=0..1] [default: 0]
--name_vk_objects Name Vulkan Objects [nargs=0..1] [default: 1]
--cmd_labels Set Labels in the CommandBuffer [nargs=0..1] [default: 1]
--helper_threads Set the number of helper threads, 'all' to use all available threads, 'none' to run single thread, -n to use all threads minus n [nargs=0..1] [default: "all"]
--gpu Select the index of the gpu to use [nargs=0..1] [default: -1]
--image_layout Select which image layout to use, possible values are: 'specific', 'general', 'auto' or a bit mask per usage (0 for specfic, 1 for general) [nargs=0..1] [default: "specific"]
--verbosity Set the console verbosity level (int) [nargs=0..1] [default: 2]
--dump_shader_source Enable shaders source dump in the gen folder [nargs=0..1] [default: 0]
--dump_preprocessed_shader Enable preprocessed shaders source dump in the gen folder [nargs=0..1] [default: 0]
--dump_spv Enable shaders SPIR-V binary dump in the gen folder [nargs=0..1] [default: 0]
--dump_slang_to_glsl Compile Slang Shaders to GLSL and dump in the gen folder [nargs=0..1] [default: 0]
--shaderc_optimization_level Set ShaderC optimization level [nargs=0..1] [default: 2]
--slang_optimization_level Set Slang optimization level [nargs=0..1] [default: 3]
--resolution Set the resolution of the main window [nargs: 2]
--imgui_docking Force the ImGui Docking feature (0 or 1)
--imgui_multi_viewport Force the ImGui Multi Viewport feature (0 or 1)
-
Fill UBO transfer command
-
SDL backend?
- SDL Window
- SDL Input listeners
- SDL Audio
-
CPU Parallel task executions
- Task executor
- Shader compilation
- Pipeline creation
-
Common Shaders Definitions
-
Common shaders bindings
-
Automatic shader definitions (to progressively complete)
-
Shader pragma once
-
Dynamic Shaders Definitions (keep a table)
-
UpdateContext
-
VkShaderObjectEXT?
-
Complete Graphics command
- Bresenham line rasterization
- Mesh Shaders command
- MSAA
- FragmentCommand
-
RenderPass-less rendering?
-
Mesh
- Mesh interface
- Rigid Mesh
- Animated Mesh with skeleton
- Terrain
- ???
- .obj loader
- Simple mesh generation
- Platonic solids
- Box
- Sphere
- Icosphere
- Mesh renderer, Mesh representation
- Mesh attribs from reflection
- Mesh compression?
- Meshlets?
- Separate positions from other vertex data?
- Mesh interface
-
Scene
-
VkRayTracingKHR
- TLAS
- SBT
-
Modules
-
Multi layer swapchain (for VR)
-
Debug buffers
- GLSL strings
-
Input manager
-
Improve CMake
- AddProject function
- Separate list for .exe
- Option to build .exe
- FastDebug build (Same as Debug, with IDL=0)
- Correctly import Vulkan
-
Better ResourceStateTracker
- Remake the interface
- Actually store the resource state in the resource rather than in a separate map?
- Correctly track potentially overlapping subresources
- for Buffers
- for Images
-
Fix synchronization validation errors
-
Re use descriptor sets
- set = 0: common set (debug, ...), managed by the executor
- set = 1: scene set
- set = 2: module set
- set = 3: shader set
- set = 4: push_descriptor set (shader invocation specific data)
-
CmdBuffer bindings (pipeline + desc sets)
- Bind pipeline -> reset desc bindings?
-
DescSetLayout cache managed by the application
-
Accumulate all descriptor updates in the UpdateContext
-
Multi window mode (independent of ImGui)
-
Buffer / Image on recreate instance command policy (copy content)
-
MultiExecutor
-
Cmake: Make and Optimized mode (debug info for my code, other libs ands stl linked in release with IDL = 0)
-
Window:
- Correct HDR support (also ImGui)
- Fullscreen
- Resized by the application
-
UpdateResources takes a priority as parameter, so for instance shaders that will not be used can still be updated, but with a lower priority
- For now, AsynchTasks are executed asynch, but are joined synch, which allows them to have side effect (store their result in the object emmiting the task). It should be forbiden, as it might create bugs, especially with an asynch joining of tasks.
-
InstanceHolders (aka Descriptors) have an option to not hold and instance (mostly to free memory for Images and Buffers)
-
Add a mode to use the GENERAL image layout instead of the specialized layout and measure the performance of doing so
-
Refactor ResourceBinding and remove Resource
-
Remove ext features from the device requested feature chain when the extension is not used (it now generates a validation error)
-
Separate DescriptorSet and DescriptorPool
- Use one pool for many descriptor sets (for model resources)
-
Add helper types StringVector, AnyVector, ...
-
Refactor UploadQueue, AsynchUpload, ... to avoid using individual small allocations
-
Make a common interface render pass
-
Find a better project name
-
Rework on thatlib
- Basic Renderer
- Seam Carving
- Mutiple rigid body simulation
- Fluid simulation?
- Reversed perspective redering
- Wave Function Collapse
- PT, LT, BDPT, VCM?
- SIBR
- HashCache based field storage + neural recontstruction?
- ReStiR
- Radiance guiding
October 2023: There should be two types of resources, synch ones and asynch ones.
- Synch resources (curent implementation) are intended to be "script resources", in a limited number, updated by the main thread, always loaded and ready to use
- Asynch resources are intended to be meshes, textures, etc, in a large number, managed (loaded, updated) by asynch threads and can be not avaible yet, partially available, or complitely available April 2024: The distinction has kind of been implemented now. Problem: automatic synchronization of all the scene resources is expesive. But all these resources are synched the "same" way, the synchronization work can be done once and shared to all these resources. Maybe create a distinction between two synch regimes: Auto and Manual.
Objectives:
- Synchronize multiple times the same resources for the same or different usages (refactor of SynchHelper)
- Simple Resource usage list with one usage per resources (works for now)
- Have more dynamic descriptor sets (adding or removing descriptors "on the fly")
- Resource management: have resources be managed by their owner ifp, else by the script manager, instead of only by the executor
- Execute host tasks in parallel (such as shader compilation, resources loading)
- Load scene (mesh, textures) asynch
- Asynch Textures
- Asynch Mesh
- Asynch Mesh group
- Refactor the Executor (and linearExecutor): issue an ExecThread to record commands in
- Add a transfer queue to the LinearExecutor to load assets
- Refactor command execition:
- Command execution issue an execution object declaring the resources on which it will interact and how, synchronization of said resources will be done externaly by the executor. This allows for ASAP synch, rather than the current mandatory ALAP
- Auto Build an execution graph from these execution objects (nodes) and their resources (edges)
- Explicitely instancify Resources
- ExecutionNodes are Command's instances, as such, they should only reference resources instances.
- Have a separate render thread
In its current implementation, DynamicValue is not thread safe and may lead to crashes! DynValueInstance::value() is marked as const, which would be thread safe, but is it not because of the mutable cached value. The problem is currently 99% under control (it has probably never occured while using the engine, but only as a thought experiment and in a stress test designed for it) So its resolution is necessary, but not urgent. I see 3 possible solutions:
- Add a (shared_)mutex to DynValueInstance to lock the evaluation (common solution to keep mutable in a multi threaded context). This might not be enough since we would need to keep the lock when viewing the cached value with a reference. Maybe create a wrapped type like SharedLockedView?
- Remove the mutable cached value from DynValueInstance (maybe move it to DynValue)
- Rethink the whole DynValue architechture
- Evalute DV's with an EvaluationContext, which would contain a index of the cycle
- Each DV would keep a cached value, assiciated with a cycle index, and shared_mutex
- Uppon evaluation, DV's would be recursivly evaluated with a ctx, only evaluating when the ctx cycle index is greater than the cached value's one. The mutex would be locked during the evaluation
- So each DV would idealy be evaluated only once
- Maybe keep not just one cached value, bu a small buffer of n values to keep a history, a be able to access previous values (allowing to evaluate the next frame DV's while reading their value for the previous frame)