It heavily inspired by guide on https://www.howtovulkan.com
Vulkan is a headache, but it can be eased with extensions:
- Dynamic rendering (no more VkRenderPass and VkFramebuffer). It makes vulkan rendering much simpler at cost of tiled gpu's which mostly for mobile etc. So tiled gpu's fuck you. But with VK_KHR_dynamic_rendering_local_read can also work without overhead for tiled gpu if it will needed.
- Descriptor indexing (aka bindless descriptors)
- Synchronization2
- Buffer device address
- Unified image layouts (allows always use VK_IMAGE_LAYOUT_GENERAL)
- [Maybe] Push descriptors
The rendering engine should use a render graph generated at compile time via nim macros. This way, there should be no performance overhead compared to manual control of render pass inputs and outputs. At the same time it significantly reduces the complexity of working with the renderer.
render pass API pseudo code:
pass "scene":
produce "sceneColor"
clear [1.0, 0.0, 0.0, 1.0]
record cmd:
# do some drawing
pass "final":
consume "sceneColor"
output Swapchain
shader[fragment] fancyPostProcessEffectSpirv
Textures: simply use bindless texture array. Yes, texture atlases are no longer necessary nowadays since bindless descriptor sets exist. Each texture is a VkImage, and image views are stored in a bindless descriptor set. The original purpose of texture atlases was to reduce draw call counts. Bindless descriptors can achieve this in a single draw call via instanced rendering with vertex or storage buffer. Moreover, it slightly simplifies the shaders. In fact, this enables drawing in a single draw call and allows for easy addition of new textures in real-time without significant overhead, which is quite useful for modding or procedural texture generation. Interestingly, this also simplifies the creation of textures with different sizes.
Memory management is a huge pain, so it's necessary to either create bindings for a library like Vulkan Memory Allocator or build a custom simple GPU allocator (the implementation at https://github.com/Traverse-Research/gpu-allocator is worth looking into).
It heavily inspired by guide on https://www.howtovulkan.com
Vulkan is a headache, but it can be eased with extensions:
The rendering engine should use a render graph generated at compile time via nim macros. This way, there should be no performance overhead compared to manual control of render pass inputs and outputs. At the same time it significantly reduces the complexity of working with the renderer.
render pass API pseudo code:
Textures: simply use bindless texture array. Yes, texture atlases are no longer necessary nowadays since bindless descriptor sets exist. Each texture is a VkImage, and image views are stored in a bindless descriptor set. The original purpose of texture atlases was to reduce draw call counts. Bindless descriptors can achieve this in a single draw call via instanced rendering with vertex or storage buffer. Moreover, it slightly simplifies the shaders. In fact, this enables drawing in a single draw call and allows for easy addition of new textures in real-time without significant overhead, which is quite useful for modding or procedural texture generation. Interestingly, this also simplifies the creation of textures with different sizes.
Memory management is a huge pain, so it's necessary to either create bindings for a library like Vulkan Memory Allocator or build a custom simple GPU allocator (the implementation at https://github.com/Traverse-Research/gpu-allocator is worth looking into).