Hello everyone.
I am currently looking at remaking our rendering back-end from the ground up. The goal is to multi-thread rendering and to move to 2nd generation APIs. So i have been looking at those APIs (mostly Vulkan and somewhat DX12 so far which are quite similar) and i think i have a decent understanding of how they work.
Just to give the big picture, the front-end of the rendering system is responsible for implementing the rendering logic of different parts of the scene like terrain (LoD, view-frustum culling) etc and produces rendering commands for the back-end in the form of state objects and resources to bind. These objects are created using builder objects and can be built of multiple threads since they don't contain any GPU objects. When submitted to the back-end, the rendering thread just sets the states and performs the draw calls.
This design is very friendly to 2nd generation at a first glance. I did take a look at DOOM3-BFG Vulkan renderer and what they do is to use an array of "frame" objects (one for each image of the swapchain). Each has a command buffer and when drawing commands are submitted, they wait on the fence of the current frame (which most of the time will be finished) and record the command buffers on the presentation thread and they just ping-pong the two command buffers from frame to frame. It's easy but it doesn't leverage the API capabilities.
My idea is to use a similar frame mechanism for the back-end while building command buffers on other threads. The builder objects could be used by the front-end (taking care to make the render pass concept first class citizens in the builder API). The builder could just be making Vulkan objects directly and just produce opaque objects that the rendering thread would just have to submit.
At this point of my reflection the main issue i'm facing is the management of the command buffers life cycle since they are allocated from command buffer pools. The rendering thread could reset the command buffer (by resetting the pool) and the handing it back to a queue when the front-end could get them but it would require that the pool be submitted with the command buffer and it would also require more synchronisation.