Repository: google/filament
File: filament/src/details/Renderer.cpp (C++)

Code before:
        mBeginFrameInternal();
        mBeginFrameInternal = {};
    }

    FEngine& engine = mEngine;
    FEngine::DriverApi& driver = engine.getDriverApi();

    if constexpr (UTILS_HAS_THREADING) {
        // on debug builds this helps to catch cases where we're writing to
        // the buffer form another thread, which is currently not allowed.
        driver.debugThreading();
    }

    FILAMENT_CHECK_PRECONDITION(mSwapChain && engine.isValid(mSwapChain))
            << "SwapChain must remain valid until endFrame is called.";

    // mSwapChain cannot be null by construction
    mSwapChain->commit(driver);
    mSwapChain = nullptr;

    mFrameInfoManager.endFrame(driver);
    mFrameSkipper.submitFrame(driver);

    if (engine.isUboBatchingEnabled()) {
        std::optional<UboManager>& uboManager = engine.getUboManager();
        assert_invariant(uboManager.has_value());
        uboManager->endFrame(driver, engine.getMaterialInstanceResourceList());
    }

    driver.endFrame(mFrameId);

    // gives the backend a chance to execute periodic tasks
    driver.tick();

    // stop the frame capture, if one was requested
    if (UTILS_UNLIKELY(engine.debug.renderer.doFrameCapture)) {
        driver.stopCapture();
        engine.debug.renderer.doFrameCapture = false;
    }

    // do this before engine.flush()
    mResourceAllocator->gc();

    // Run the component managers' GC in parallel
    // WARNING: while doing this we can't access any component manager
    auto& js = engine.getJobSystem();

    auto *job = js.runAndRetain(jobs::createJob(js, nullptr, &FEngine::gc, &engine)); // gc all managers

    engine.flush();     // flush command stream


Review comment (performance):
no need to return the optional *and* check `isUboBatchingEnabled()`. I would keep the `isUboBatchingEnabled()` check and just write `engine.getUboManager()->endFrame()`

Code after:
        mBeginFrameInternal();
        mBeginFrameInternal = {};
    }

    FEngine& engine = mEngine;
    FEngine::DriverApi& driver = engine.getDriverApi();

    if constexpr (UTILS_HAS_THREADING) {
        // on debug builds this helps to catch cases where we're writing to
        // the buffer form another thread, which is currently not allowed.
        driver.debugThreading();
    }

    FILAMENT_CHECK_PRECONDITION(mSwapChain && engine.isValid(mSwapChain))
            << "SwapChain must remain valid until endFrame is called.";

    // mSwapChain cannot be null by construction
    mSwapChain->commit(driver);
    mSwapChain = nullptr;

    mFrameInfoManager.endFrame(driver);
    mFrameSkipper.submitFrame(driver);

    engine.submitFrame();

    driver.endFrame(mFrameId);

    // gives the backend a chance to execute periodic tasks
    driver.tick();

    // stop the frame capture, if one was requested
    if (UTILS_UNLIKELY(engine.debug.renderer.doFrameCapture)) {
        driver.stopCapture();
        engine.debug.renderer.doFrameCapture = false;
    }

    // do this before engine.flush()
    mResourceAllocator->gc();

    // Run the component managers' GC in parallel
    // WARNING: while doing this we can't access any component manager
    auto& js = engine.getJobSystem();

    auto *job = js.runAndRetain(jobs::createJob(js, nullptr, &FEngine::gc, &engine)); // gc all managers

    engine.flush();     // flush command stream

    // make sure we're done with the gcs
    js.waitAndRelease(job);
}