# Render Pipeline ## Frame Graph We use [KHR_dynamic_rendering](https://lesleylai.info/en/vk-khr-dynamic-rendering/) for vulkan. DX12 render passes are basically equivalent to this. Nevertheless, we need to define which render targets we need and when each RT will be written and read from. This is because we 1. Need to allocate render targets and 2. Want to parallelize independent parts of the frame. Two API concepts: 1. **Render Targets**: Contain format info and sizes. For vulkan, these get "compiled" to a VkImage(View) and a Rect for the render area 2. **Passes**: Contain the information necessary for VkRenderingInfoKHR structs and their DX12/Metal/... equivalents. A render target should actually contain N copies of the image, where N is the max. number of frames in flight. (Usually 2 or 3). Multiple render targets with the same format could be aliased, if they are never accessed concurrently, to save VRAM. A **frame-graph** is then: - A set of render targets. Each render target gets an unique name by which it can be referenced. - A ordered list of passes. The passes are - logically - executed in the order given, but may be scheduled concurrently, if this yields the same results. To determine the possibilities of concurrent execution and aliasing, each pass needs to list the render targets it accesses. ## Interfacing with the scene The update thread computes a scene representation that is made available to the render thread. This should contain a list of objects that, potentially (sans culling) need to be rendered. Each object has a material. A material contains a effect, which lists the passes during which the object needs to be rendered and shader pipelines for each of these passes (sets of shaders + fixed state + meta information about uniforms etc.). It could also define the expected vertex layout for rendered meshes. This information enables us to provide each pass of the frame graph with a list of objects that need to be rendered by that pass. It also allows us to skip passes without any input objects, except when the passes are marked as "execute always" (for example a tone-mapping pass). The material also binds effect properties to "real" values. For example an effect could expose a property like "albedo-map" and the material would bind this to a particular resource. ## Interfacing with the resource system Effects can be loaded from resources (we already have a parser for PSOs and a shader compiler). These would now be tied to a particular frame-graph (set of passes). We could also load frame-graph information from resources, but how do we provide the logic for that pass? **Idea:** Have the game "bind" a struct like the following to a pass: ``` /* rt_pass is some kind of identifier/handle for the pass) struct rt_pass_functions_s { void (*pass_prepare)(rt_pass pass); void (*pass_execute)(rt_pass pass, rt_render_object_list objects); void (*pass_finalize)(rt_pass pass); } ``` The runtime (or a separate library?) can provide some default pass-implementations for this.