WIP ‐ Vulkan - bryanedds/Nu GitHub Wiki
The Four Horsemen
Vulkan rendering incorporates four foundational components, here tentatively titled the Four Horsemen:
Memory Management
This horseman has been subdued by the Vulkan Memory Alligator. Device memory allocation can be completely automated and consequently ignored during the initial pass. For the optimization phase, VMA enables controlled device memory management via custom memory pools, so that Nu's VRAM can be cut at its joints.
Command System
All of the actual live rendering work is controlled by commands. The infrastructure for processing these commands is responsible for all of the synchronization, which presents both the major danger of (platform specific) error and the major challenge of optimization. During the initial pass, the commands will presumably execute serially, resulting in negligible complexity. During the optimization phase, they will be parallelized, which may or may not produce enough complexity to warrant abstraction.
Graphics Pipelines
All of the information needed to tell Vulkan what to draw and how to draw it is hardcoded into static data structures called graphics pipelines. This information includes not only the shaders, but entire multi-pass rendering sequences like deferred rendering. The process of porting Nu's existing rendering architecture will consist of translating it into pipelines. There will be at least three pipelines, one each for 2D, 3D and IMGUI.
Presentation System
Once the pipelines' output is merged into the final image, presentation is the process of sending it to the screen. These consecutive images are placed in a queue called the swap chain, where they await delivery to an object called the surface, which represents the screen or window via SDL. How the swap chain is set up determines correct synchronization with Nu's framerate, vsync and latency. It is crucial to get this right, but should be simple enough to get out of the way pretty quickly. There should be at least three swap chain images (i.e. places in queue) to prevent delays in writing to the swap chain (Sellers, p. 144, but cf https://vulkan-tutorial.com/Drawing_a_triangle/Presentation/Swap_chain#page_Creating-the-swap-chain).
Custom Validation
TODO: Learn as we go on this, but let's see what we might be able to anticipate.
.Net Binding
Nu's interface to Vulkan is the Vortice.Vulkan binding. It is adequately low-level while providing appropriate and very helpful optional abstractions, including selective Vulkan function overloads and most importantly string handling. It also provides invisible cross-platform loading. It is of minimal size and complexity and therefore hackable.
Vortice.Vulkan is partly based on vk, which is no longer actively maintained. There is also another, more direct, descendent of vk currently under maintenance: Vulkan.Net. It is a beautiful wrapper, but lacks the helpful abstractions.
Standard
-
Common practice and convention for interacting with Vulkan must be adhered to as much as possible. Any deviation may lead to unpredictable results due to inadequate implementation by vendors.
-
The claims of validation error messages about user code should be taken seriously and literally. They are very good at revealing deceptive false premises.
-
Vortice.Vulkan's one shortcoming is that it inappropriately uses the Vulkan prefix "vk/Vk" in non-Vulkan functions and types, which is misleading. For clarity, these must be marked "// not vulkan function" (or equivalent). Regular use types like VkUtf8String are excepted.
-
If Vortice.Vulkan fails to allow any particular compliance with the spec, this must be noted in a comment. The exception to this is Vortice.Vulkan's internalization of the sType struct member.
Vulkan functions
-
All Vulkan functions must be looked up in the spec upon first use.
-
Vortice.Vulkan often provides a choice between managed pointers (byref) and unmanaged pointers. For the sake of simplicity, the former should be preferred. No comment required.
-
Otherwise, the most conservative overload of Vulkan functions should be the default. i.e. the arguments should normally match the spec.
-
Higher-level overloads of Vulkan functions can be used if there is a compelling reason to do so. Use of higher-level overloads and the reason for said use must be explained in a comment.
Vulkan Structs
-
All Vulkan structs must be looked up in the spec upon first use.
-
When constructing informational Vulkan structs, only the bare minimal relevant members should be filled out, ordered according to the spec.
Vulkan Boolean
- Vortice.Vulkan does not enable spec compliant boolean usage. Normal boolean values should be used to provide required type via implicit conversion.
Pointers
-
Use of pointer handling helpers from Vortice.Vulkan should be avoided.
-
All pointer handling should be done through Native.fs.
-
All arrays and strings must be pinned in memory before unmanaged pointers to them are passed to Vulkan structs or functions.
-
Abstractions must always be used wherever possible for handling unmanaged pointers to strings and arrays.
-
Abstractions for handling unmanaged pointers must be assigned with the "use" keyword.
General Notes
-
For buffers, and presumably for images, the sharingMode should, for performance reasons, default to VK_SHARING_MODE_EXCLUSIVE (Sellers, p. 44).
-
Variables specified in uniform buffers must adhere to memory alignment requirements, see https://vulkan-tutorial.com/Uniform_buffers/Descriptor_pool_and_sets#page_Alignment-requirements.
-
"The specification document still recommends that you enable validation layers at device level as well for compatibility, which is required by some implementations." (https://vulkan-tutorial.com/Drawing_a_triangle/Setup/Validation_layers#page_What-are-validation-layers) Also, be sure to review this chapter, especially https://vulkan-tutorial.com/Drawing_a_triangle/Setup/Validation_layers#page_Message-callback.
-
Some commentary about validation layers (including a blind spot) at https://vulkan-tutorial.com/Texture_mapping/Combined_image_sampler#page_Updating-the-descriptors.
-
"The currently available drivers will only allow you to create a small number of queues for each queue family and you don't really need more than one. That's because you can create all of the command buffers on multiple threads and then submit them all at once on the main thread with a single low-overhead call." (https://vulkan-tutorial.com/Drawing_a_triangle/Setup/Logical_device_and_queues#page_Specifying-the-queues-to-be-created) But does OpenGL rely on multiple queues for optimization?
-
Pipeline Resource Limits (Sellers, p. 195-6) apparently rendered trivial by descriptor indexing: https://www.youtube.com/watch?v=tXipcoeuNh4.
References
-
Sellers, Graham, Vulkan Programming Guide: The Official Guide to Learning Vulkan, Addison-Wesley, 2017.
-
https://zeux.io/2020/02/27/writing-an-efficient-vulkan-renderer/. Must read article on efficient Vulkan programming.
-
https://docs.vulkan.org/guide/latest/index.html. An official source of general info (logistics) about Vulkan.
-
https://github.com/KhronosGroup/Vulkan-Loader/blob/main/docs/LoaderInterfaceArchitecture.md. Key source on the Vulkan Loader; also good source on the Vulkan environment generally. This sort of useful discussion extends into https://github.com/KhronosGroup/Vulkan-Loader/blob/main/docs/LoaderApplicationInterface.md.
-
https://registry.khronos.org/vulkan/specs/1.3-extensions/html/chap46.html. Contains specification on versioning and compatibility.
-
https://vulkan.lunarg.com/doc/sdk/1.3.280.0/windows/getting_started.html. Official documentation on Vulkan SDK; includes an explanation of its versioning.
-
https://wiki.libsdl.org/SDL2/SDL_Vulkan_LoadLibrary. Documentation on loading Vulkan from SDL.
-
https://source.android.com/docs/core/graphics/implement-vulkan#versions. Official source on Android Vulkan support.
-
https://vulkan.gpuinfo.org/displaydevicelimit.php?platform=android&name=maxPerStageDescriptorSampledImages. Data on device texture limits.
-
https://community.khronos.org/t/bindless-textures/103941. Useful discussion about how the concept of 'bindless textures' applies to Vulkan.
-
https://www.reddit.com/r/vulkan/comments/d4jbss/vulkan_and_c_where_is_it/. Somewhat obnoxious discussion of .Net Vulkan bindings.