// Closed-loop simulation of the guest vblank lock with the runtime's own // RefreshFit and VblankLock (video/refresh_fit.cpp, video/vblank_lock.cpp). // From the repo root: // clang++ -std=c++20 -O2 -Iruntime tests/vblank_lock_sim.cpp runtime/video/refresh_fit.cpp \ // runtime/video/vblank_lock.cpp -o build/vblank_lock_sim // build/vblank_lock_sim // // Model (times in ns): // display refreshes every P (true rate), phase random; a present made // before R_k - latch shows at R_k (FIFO, in order); its // completion is seen at R_k + notify (0.2-0.6 ms, sometimes late). // guest each vblank (VblankLock::Next, or free-running 16.667 ms) // releases one game frame, which reaches the presenter x later // (x drawn per scene). The presenter keeps only the newest // pending frame (older ones are dropped), picks it up ~0.5 ms // later, and presents at once when a swapchain image is free // (3 images: one on screen, at most 2 queued), else waits for // the next flip holding it. // variable (the second table) no grid: a present shows as soon as it is // latched, no sooner than 1/144 s after the last refresh, and // the display refreshes on its own after 1/48 s without one. // Counted from the 60th second (the lock has converged by then): dropped // frames, repeats (a refresh with no new frame while frames flow), slips, // the median vblank -> on screen latency, and the guest vblank's rate. // suspended (the last tables) the game is suspended (iOS: Control Center, // the app switcher): no vblank fires and its frames stand still, // the display shows what was queued, and the next vblank comes // exactly the time suspended later, then VblankLock::Resumed // (gpu/command_processor.cpp's Vsync thread). #include