frame.cpp

cross platform rendering playground

src/editor/frame.cpp

4.2 KB
#ifdef ENABLE_EDITOR
#include "editor.h"

#include <algorithm>

#include "backend/imgui_backend.h"
#include "passes/fg_utils.h"
#include "passes/imgui/imgui.h"
#include "pipelines.h"
#include "renderer.h"
#include "scene/scene.h"

namespace editor {

void eval_render_size(u32 viewport_w, u32 viewport_h, rhi::Swapchain &swapchain, rhi::Extent2D &extent) {
    rhi::Extent2D sc_extent = rhi::swapchain_extent(swapchain);
    u32 w = (viewport_w > 0) ? viewport_w : sc_extent.width;
    u32 h = (viewport_h > 0) ? viewport_h : sc_extent.height;

    extent.width = std::max(w, 1u);
    extent.height = std::max(h, 1u);
}

void handle_frame_begin(
    Editor &e,
    RenderData &rd,
    rhi::Device &device,
    rhi::Swapchain &swapchain,
    FrameGraph &fg,
    ImageHandle swapchain_target,
    rhi::Extent2D &render_size,
    Scene &scene,
    Pipelines &pipelines,
    PassTimings &timings,
    u32 frame_slot
) {
    begin_frame(e, rd);

    if (e.viewport_resized && e.viewport_width > 0 && e.viewport_height > 0) {
        rhi::queue_wait_idle(device);

        eval_render_size(e.viewport_width, e.viewport_height, swapchain, render_size);

        fg.overwrite_imported_image(swapchain_target, rhi::swapchain_image(swapchain, 0));
        fg.compile(device, render_size);

        Camera &cam = scene.cameras[scene.active_camera];
        cam.aspect = static_cast<f32>(render_size.width) / static_cast<f32>(render_size.height);

        e.viewport_resized = false;
    }

    if (reload_requested(e)) {
        pipelines.reload();
    }

    timings.readback(device, frame_slot);
}

void record_present(
    Editor &e,
    Pipelines &pipelines,
    rhi::ShaderCompiler &sc,
    FrameGraph &fg,
    rhi::Swapchain &swapchain,
    const PresentTargets &targets,
    PassTimings &timings
) {
    imgui_pass::record(*fg.device, pipelines, sc, fg, rhi::swapchain_format(swapchain));
    e.imgui_pipeline = &pipelines.get_render("ImGui");

    Editor *ed = &e;
    PassTimings *tm = &timings;
    rhi::Swapchain *sw = &swapchain;
    PresentTargets tg = targets;

    auto &builder = fg.add_pass("Editor Present");
    builder.read(tg.display, rhi::ResourceState::TextureSample);
    builder.read(tg.irradiance, rhi::ResourceState::TextureSample);
    builder.read(tg.distance, rhi::ResourceState::TextureSample);
    builder.read(tg.id_blit, rhi::ResourceState::TextureSample);

    for (u32 i = 0; i < Light::CASCADE_COUNT; ++i) {
        builder.read(tg.cascade[i], rhi::ResourceState::TextureSample);
    }

    builder.write(tg.swapchain, rhi::ResourceState::ColorDraw).execute([ed, tm, sw, tg](PassContext &ctx) {
        ctx.render_data->display = ctx.get_image(tg.display);
        ctx.render_data->irr_atlas = ctx.get_image(tg.irradiance);
        ctx.render_data->dis_atlas = ctx.get_image(tg.distance);
        ctx.render_data->id_blit = ctx.get_image(tg.id_blit);

        for (u32 i = 0; i < Light::CASCADE_COUNT; ++i) {
            ctx.render_data->cascade[i] = ctx.get_image(tg.cascade[i]);
        };

        auto vs = ctx.image_view(tg.swapchain, {.aspect = rhi::ImageAspect::Color, .mip_count = 1});

        rhi::AttachmentDesc color_att{};
        color_att.img = &vs;
        color_att.loadOp = rhi::LoadOp::CLEAR;
        color_att.storeOp = rhi::StoreOp::STORE;
        color_att.clearValue.color.float32[0] = 0.0f;
        color_att.clearValue.color.float32[1] = 0.0f;
        color_att.clearValue.color.float32[2] = 0.0f;
        color_att.clearValue.color.float32[3] = 1.0f;

        u32 pass_count;
        const PassInspectorEntry *passes = tm->entries(pass_count);
        editor::end_frame(*ed, *ctx.scene, *ctx.render_data, passes, pass_count);

        bool draw_ui = false;
        if (ed->imgui_pipeline != nullptr) {
            draw_ui = imgui_backend::prepare(ctx);
        }

        rhi::RenderingInfo ri{};
        ri.colorAttachments[0] = color_att;
        ri.colorAttachmentCount = 1;
        ri.width = (u32)rhi::swapchain_extent(*sw).width;
        ri.height = (u32)rhi::swapchain_extent(*sw).height;

        rhi::begin_rendering(ctx.cmd, ri);
        if (draw_ui) {
            imgui_backend::draw(ctx, *ed->imgui_pipeline, ri.width, ri.height);
        }
        rhi::end_rendering(ctx.cmd);
    });
}

} // namespace editor

#endif // ENABLE_EDITOR