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

Code before:
    }
}

void FrameInfoManager::beginFrame(FSwapChain* swapChain, DriverApi& driver,
        Config const& config, uint32_t frameId, std::chrono::steady_clock::time_point const vsync) noexcept {
    auto const now = std::chrono::steady_clock::now();

    auto& history = mFrameTimeHistory;
    // don't exceed the capacity, drop the oldest entry
    if (UTILS_LIKELY(history.size() == history.capacity())) {
        if (!mDisableGpuFrameComplete) {
            assert_invariant(history.back().fence);
            driver.destroyFence(std::move(history.back().fence));
        }
        history.pop_back();
    }

    // create a new entry
    FrameInfoImpl& front = history.emplace_front(frameId);

    // store the current time
    front.vsync = vsync;
    front.beginFrame = now;

    // store compositor timings if supported
    CompositorTiming compositorTiming{};
    if (driver.isCompositorTimingSupported() &&
        driver.queryCompositorTiming(swapChain->getHwHandle(), &compositorTiming)) {
        front.presentDeadline = compositorTiming.compositeDeadline;
        front.displayPresentInterval = compositorTiming.compositeInterval;
        front.compositionToPresentLatency = compositorTiming.compositeToPresentLatency;
        front.expectedPresentTime = compositorTiming.expectedPresentTime;
        if (compositorTiming.frameTime != CompositorTiming::INVALID) {
            // of we have a vsync time from the compositor, ignore the one from the user
            front.vsync = FrameInfoImpl::time_point{
                std::chrono::nanoseconds(compositorTiming.frameTime) };
        }
    }

    if (mHasTimerQueries) {
        // references are not invalidated by CircularQueue<>, so we can associate a reference to
        // the slot we created to the timer query used to find the frame time.
        mQueries[mIndex].pInfo = std::addressof(front);
        // issue the timer query
        driver.beginTimerQuery(mQueries[mIndex].handle);
    }

    // issue the custom backend command to get the backend time
    driver.queueCommand([&front](){
        front.backendBeginFrame = std::chrono::steady_clock::now();
    });

Review comment (bug):
shouldn't we actually skip this frame by `return;` or something? otherwise it looks like it'll crash at `history.emplace_front(frameId);` right below.

Code after:
    }
}

void FrameInfoManager::beginFrame(FSwapChain* swapChain, DriverApi& driver,
        Config const& config, uint32_t frameId, std::chrono::steady_clock::time_point const vsync) noexcept {
    auto const now = std::chrono::steady_clock::now();

    auto& history = mFrameTimeHistory;
    // don't exceed the capacity, drop the oldest entry
    if (UTILS_LIKELY(history.size() == history.capacity())) {
        FrameInfoImpl& frameInfo = history.back();
        if (frameInfo.ready.load(std::memory_order_relaxed)) {
            if (!mDisableGpuFrameComplete) {
                assert_invariant(frameInfo.fence);
                driver.destroyFence(std::move(frameInfo.fence));
            }
            history.pop_back();
        } else {
            // This is a big problem, we ran out of space in the circular queue and that entry
            // hasn't been processed yet. Because the code below keeps a reference to the
            // front element of the queue, we can't pop/push. Our only option is to not record
            // a new entry for this frame, which will create a false skipped frame in the
            // data.
            LOG(WARNING) << "FrameInfo's circular queue is full, but the latest item hasn't "
                            " been processed yet. Skipping this frame, id = " << frameId;
        }
    }

    // create a new entry
    FrameInfoImpl& front = history.emplace_front(frameId);

    // store the current time
    front.vsync = vsync;
    front.beginFrame = now;

    // store compositor timings if supported
    CompositorTiming compositorTiming{};
    if (driver.isCompositorTimingSupported() &&
        driver.queryCompositorTiming(swapChain->getHwHandle(), &compositorTiming)) {
        front.presentDeadline = compositorTiming.compositeDeadline;
        front.displayPresentInterval = compositorTiming.compositeInterval;
        front.compositionToPresentLatency = compositorTiming.compositeToPresentLatency;
        front.expectedPresentTime = compositorTiming.expectedPresentTime;
        if (compositorTiming.frameTime != CompositorTiming::INVALID) {
            // of we have a vsync time from the compositor, ignore the one from the user
            front.vsync = FrameInfoImpl::time_point{
                std::chrono::nanoseconds(compositorTiming.frameTime) };
        }
    }

    if (mHasTimerQueries) {