{"version":3,"file":"render-step.mjs","sources":["../../../src/frameloop/render-step.ts"],"sourcesContent":["import { statsBuffer } from \"../stats/buffer\"\nimport { StepNames } from \"./order\"\nimport { FrameData, Process, Step } from \"./types\"\n\nexport function createRenderStep(\n    runNextFrame: () => void,\n    stepName?: StepNames\n): Step {\n    /**\n     * We create and reuse two queues, one to queue jobs for the current frame\n     * and one for the next. We reuse to avoid triggering GC after x frames.\n     */\n    let thisFrame = new Set<Process>()\n    let nextFrame = new Set<Process>()\n\n    /**\n     * Track whether we're currently processing jobs in this step. This way\n     * we can decide whether to schedule new jobs for this frame or next.\n     */\n    let isProcessing = false\n\n    let flushNextFrame = false\n\n    /**\n     * A set of processes which were marked keepAlive when scheduled.\n     */\n    const toKeepAlive = new WeakSet<Process>()\n\n    let latestFrameData: FrameData = {\n        delta: 0.0,\n        timestamp: 0.0,\n        isProcessing: false,\n    }\n\n    let numCalls = 0\n\n    function triggerCallback(callback: Process) {\n        if (toKeepAlive.has(callback)) {\n            step.schedule(callback)\n            runNextFrame()\n        }\n\n        numCalls++\n        callback(latestFrameData)\n    }\n\n    const step: Step = {\n        /**\n         * Schedule a process to run on the next frame.\n         */\n        schedule: (callback, keepAlive = false, immediate = false) => {\n            const addToCurrentFrame = immediate && isProcessing\n            const queue = addToCurrentFrame ? thisFrame : nextFrame\n\n            if (keepAlive) toKeepAlive.add(callback)\n\n            if (!queue.has(callback)) queue.add(callback)\n\n            return callback\n        },\n\n        /**\n         * Cancel the provided callback from running on the next frame.\n         */\n        cancel: (callback) => {\n            nextFrame.delete(callback)\n            toKeepAlive.delete(callback)\n        },\n\n        /**\n         * Execute all schedule callbacks.\n         */\n        process: (frameData) => {\n            latestFrameData = frameData\n\n            /**\n             * If we're already processing we've probably been triggered by a flushSync\n             * inside an existing process. Instead of executing, mark flushNextFrame\n             * as true and ensure we flush the following frame at the end of this one.\n             */\n            if (isProcessing) {\n                flushNextFrame = true\n                return\n            }\n\n            isProcessing = true\n\n            // Swap this frame and the next to avoid GC\n            ;[thisFrame, nextFrame] = [nextFrame, thisFrame]\n\n            // Execute this frame\n            thisFrame.forEach(triggerCallback)\n\n            /**\n             * If we're recording stats then\n             */\n            if (stepName && statsBuffer.value) {\n                statsBuffer.value.frameloop[stepName].push(numCalls)\n            }\n            numCalls = 0\n\n            // Clear the frame so no callbacks remain. This is to avoid\n            // memory leaks should this render step not run for a while.\n            thisFrame.clear()\n\n            isProcessing = false\n\n            if (flushNextFrame) {\n                flushNextFrame = false\n                step.process(frameData)\n            }\n        },\n    }\n\n    return step\n}\n"],"names":[],"mappings":";;AAIgB,SAAA,gBAAgB,CAC5B,YAAwB,EACxB,QAAoB,EAAA;AAEpB;;;AAGG;AACH,IAAA,IAAI,SAAS,GAAG,IAAI,GAAG,EAAW,CAAA;AAClC,IAAA,IAAI,SAAS,GAAG,IAAI,GAAG,EAAW,CAAA;AAElC;;;AAGG;IACH,IAAI,YAAY,GAAG,KAAK,CAAA;IAExB,IAAI,cAAc,GAAG,KAAK,CAAA;AAE1B;;AAEG;AACH,IAAA,MAAM,WAAW,GAAG,IAAI,OAAO,EAAW,CAAA;AAE1C,IAAA,IAAI,eAAe,GAAc;AAC7B,QAAA,KAAK,EAAE,GAAG;AACV,QAAA,SAAS,EAAE,GAAG;AACd,QAAA,YAAY,EAAE,KAAK;KACtB,CAAA;IAED,IAAI,QAAQ,GAAG,CAAC,CAAA;IAEhB,SAAS,eAAe,CAAC,QAAiB,EAAA;AACtC,QAAA,IAAI,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;AAC3B,YAAA,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;AACvB,YAAA,YAAY,EAAE,CAAA;SACjB;AAED,QAAA,QAAQ,EAAE,CAAA;QACV,QAAQ,CAAC,eAAe,CAAC,CAAA;KAC5B;AAED,IAAA,MAAM,IAAI,GAAS;AACf;;AAEG;AACH,QAAA,QAAQ,EAAE,CAAC,QAAQ,EAAE,SAAS,GAAG,KAAK,EAAE,SAAS,GAAG,KAAK,KAAI;AACzD,YAAA,MAAM,iBAAiB,GAAG,SAAS,IAAI,YAAY,CAAA;YACnD,MAAM,KAAK,GAAG,iBAAiB,GAAG,SAAS,GAAG,SAAS,CAAA;AAEvD,YAAA,IAAI,SAAS;AAAE,gBAAA,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;AAExC,YAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC;AAAE,gBAAA,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAA;AAE7C,YAAA,OAAO,QAAQ,CAAA;SAClB;AAED;;AAEG;AACH,QAAA,MAAM,EAAE,CAAC,QAAQ,KAAI;AACjB,YAAA,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;AAC1B,YAAA,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;SAC/B;AAED;;AAEG;AACH,QAAA,OAAO,EAAE,CAAC,SAAS,KAAI;YACnB,eAAe,GAAG,SAAS,CAAA;AAE3B;;;;AAIG;YACH,IAAI,YAAY,EAAE;gBACd,cAAc,GAAG,IAAI,CAAA;gBACrB,OAAM;aACT;YAED,YAAY,GAAG,IAAI,CAGlB;YAAA,CAAC,SAAS,EAAE,SAAS,CAAC,GAAG,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;;AAGhD,YAAA,SAAS,CAAC,OAAO,CAAC,eAAe,CAAC,CAAA;AAElC;;AAEG;AACH,YAAA,IAAI,QAAQ,IAAI,WAAW,CAAC,KAAK,EAAE;AAC/B,gBAAA,WAAW,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;aACvD;YACD,QAAQ,GAAG,CAAC,CAAA;;;YAIZ,SAAS,CAAC,KAAK,EAAE,CAAA;YAEjB,YAAY,GAAG,KAAK,CAAA;YAEpB,IAAI,cAAc,EAAE;gBAChB,cAAc,GAAG,KAAK,CAAA;AACtB,gBAAA,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAA;aAC1B;SACJ;KACJ,CAAA;AAED,IAAA,OAAO,IAAI,CAAA;AACf;;;;"}