Frame graph architecture

Viewed 145

Since no new shader can be created during runtime, the full set is known ahead at compile-time. Each shader must reference a "pass" in which it will used to render.

To avoid frame-spikes during runtime, I'd like to pre-create all pipeline objects during startup. And to create a pipieline, the number of outputs and the format of each output attachment must be known - either to create a VkRenderPass or to specify the outputs for the dynamic rendering feature.

However, I'd also like to use the frame graph concept (speech by Yuriy O'Donnell) which in turn builds a graph of render passes with input-output specification and dependencies between them. Some passes are conditionally created (e.g. debug passes), some passes might be dropped from the graph (after "compiling" it).

Additionally, I need to support the "write on top" feature, so instead of specifying a new output during the building of the render pass, I can simply say that the output of this pass will use an output from a previous pass - this is useful for adding alpha-blended rendering, for example.

How can I match the two separate section of the code? In other words, how can I define all render passes during initialization but also use a dynamic approach of building the frame graph each frame without repeating myself?

This is what I'd like to avoid (pseudo-code):

struct Pass1Def
{
    output1 = ImageFormat::RGBA8;
    output2 = ImageFormat::RGBA8;
    // ...
    outputs = // outputs in order (corresponds to location in shader)
};

void init()
{
    for_each_shaders shader {
        passDef = findPassDef(shader);
        createPipeline(shader, passDef);
    }
}

void render()
{
    auto previousResource = someCondition ? passA.outputResource1 : passB.outputResource2;

    graph.addPass(..., [&](PassBuilder& builder, Pass1Data& data) {
        // error-prone: order of function calls matter (corresponds to location in shader)
        
        // error-prone: use the same format defined in Pass1Def
        data.outputResource1 = builder.create(... ImageFormat::RGBA8);
        
        // error-prone: the format depends on the outputResource of a previous pass
        //              however the format must be (and was) specified in Pass1Def
        data.outputResource2 = builder.write(previousResource);
    });
}
0 Answers
Related