/**
 * # WebGPU Debug Marker Implementation — Problem Statement
 *
 * ## Background
 *
 * WebGPU exposes `pushDebugGroup` / `popDebugGroup` on two distinct objects:
 *   - The **render encoder** (`GPUCommandEncoder`), which lives for the lifetime of an entire
 *     submission (one call to `flushFramebuffer`).
 *   - The **render pass encoder** (`GPURenderPassEncoder`), which lives only for the duration of
 *     a single render pass.
 *
 * WebGPU requires that every push/pop pair is issued on the **same** object, and that all open
 * groups are closed before the object ends. Violating either rule is a validation error.
 *
 * ## The Core Problem
 *
 * From the Babylon.js side, the user calls `_debugPushGroup` / `_debugPopGroup` at arbitrary
 * points in time — completely independently of whether a render pass is currently active or not.
 * This creates several mismatched-context scenarios that must be handled transparently.
 *
 * ## Scenario 1 — Push on render encoder, pop inside a render pass
 *
 *   1. User calls `_debugPushGroup` while no render pass is active → group is pushed on the
 *      render encoder and recorded in `_debugMarkersEncoderGroups`.
 *   2. A render pass starts (`_currentRenderPass` becomes non-null).
 *   3. User calls `_debugPopGroup` while the render pass is active. The pop must logically target
 *      the render encoder group, but we cannot call `popDebugGroup` on the render encoder while a
 *      render pass is active (the pass is the live object).
 *   4. We detect this mismatch because `_debugMarkersPassGroups` is empty (no group was pushed
 *      during this render pass), so we increment `_debugMarkersPendingEncoderPops` instead of
 *      issuing the pop immediately.
 *   5. When the render pass ends (`_endCurrentRenderPass`), `_debugPendingPop` drains the
 *      `_debugMarkersPendingEncoderPops` counter and issues the deferred pops on the render encoder.
 *
 *   **Edge case — deferred pop followed by a render-pass push:** if the user pushes another group
 *   during the same render pass *after* the deferred pop was recorded, that new group goes into
 *   `_debugMarkersPassGroups`. When the pass ends, `_debugPopBeforeEndOfEncoder` auto-pops the
 *   pass-level group, leaving it floating in `_debugMarkersPassGroups`. `_debugPendingPop` then
 *   pops from `_debugMarkersEncoderGroups` — a separate array that can never contain pass-level
 *   entries — so the floating pass-level group is preserved intact and will be re-pushed on the
 *   next render pass by `_debugPushAfterStartOfEncoder`.
 *
 * ## Scenario 2 — Push inside a render pass, render pass ends before pop
 *
 *   1. User calls `_debugPushGroup` while a render pass is active → group is pushed on the render
 *      pass encoder and recorded in `_debugMarkersPassGroups`.
 *   2. The render pass ends (e.g. a new render target is bound) before the user calls
 *      `_debugPopGroup`. All open render-pass groups must be closed before
 *      `GPURenderPassEncoder.end()` is called.
 *   3. `_debugPopBeforeEndOfEncoder` auto-pops every group in `_debugMarkersPassGroups` from the
 *      render pass encoder. The names remain in `_debugMarkersPassGroups` (the array is not
 *      cleared) so the logical nesting is preserved and the groups are now "floating".
 *   4. After the next render pass is created, `_debugPushAfterStartOfEncoder` re-pushes all
 *      floating pass groups onto it, so that when the user eventually calls `_debugPopGroup`
 *      there is always a matching push on the current live object.
 *
 * ## Scenario 3 — `flushFramebuffer` called mid-frame (multiple times per frame)
 *
 *   `flushFramebuffer` submits all recorded GPU commands and creates a brand-new pair of encoders.
 *   It can be called more than once during a single Babylon.js frame (e.g. for read-back
 *   operations, multi-view rendering, or explicit flushes). Each call:
 *   1. Ends the current render pass if any (`_endCurrentRenderPass`), which triggers the
 *      render-pass auto-pop and pending-pop handling described above.
 *   2. Calls `_debugPopBeforeEndOfEncoder` to close every still-open group on the render encoder
 *      before it is finalised and submitted. Only encoder-level groups (`_debugMarkersEncoderGroups`)
 *      are popped from the encoder; pass-level groups (`_debugMarkersPassGroups`) are already
 *      floating after step 1 and were never pushed on the encoder, so they are left alone.
 *   3. Creates new `_uploadEncoder` / `_renderEncoder` instances.
 *   4. Calls `_debugPushAfterStartOfEncoder` to re-open the encoder-level groups on the new render
 *      encoder, so the user's subsequent pops still find a matching push.
 *   When `flushFramebuffer` is called from `endFrame` (the last flush of the frame), both arrays
 *   are cleared (`_debugMarkersEncoderGroups` and `_debugMarkersPassGroups`) because any groups
 *   still open at end-of-frame are considered abandoned.
 *
 * ## State variables
 *
 *   - `_debugMarkersEncoderGroups` — names of groups currently open on the render encoder (pushed
 *     while no render pass was active). These are re-pushed on the new render encoder after each
 *     mid-frame flush.
 *   - `_debugMarkersPassGroups` — names of groups pushed while a render pass was active. While a
 *     pass is live these are open on that pass encoder. When a pass ends they become "floating" —
 *     auto-popped from the finished pass but not yet on any GPU object — and remain here until the
 *     next render pass starts and `_debugPushAfterStartOfEncoder` re-opens them on it.
 *   - `_debugMarkersPendingEncoderPops` — count of user pops that arrived while a render pass was
 *     active but whose matching push lived on the render encoder. These pops are deferred and
 *     replayed on the render encoder once the render pass ends.
 */
export {};
