/** * Buffers a frame's draws create, and resources they replace, released once * the frame is submitted. * * A mark mints a buffer per draw and WebGPU frees none of them on its own, so * a hovered chart was creating hundreds a frame and holding every one, which * reached tens of gigabytes. Destroying is safe after submit: an implementation * keeps a buffer alive until the commands referencing it have run. */ declare class FrameBuffers { private current; private previous; hold(resource: T): T; /** * Frees the frame before last. A capture and an image that finishes loading * both submit again around a frame, so a buffer is only let go once a later * frame has been through as well. */ release(): void; } /** The frame's buffers for a device, which die with it. */ export declare function bufferPool(device: GPUDevice): FrameBuffers; /** * Uploads through the queue rather than mappedAtCreation. A mapped range * costs one JS ArrayBuffer per buffer and a frame creates a buffer per mark, * which exhausts that allocation on a memory-constrained runner: every * create then throws "size (32) is too large for the implementation". * * `lasting` keeps the buffer out of the frame pool, for the few that are held * across frames rather than rebuilt. */ export declare function uploadBuffer(device: GPUDevice, label: string, data: Uint16Array | Uint32Array | Float32Array, usage: GPUBufferUsageFlags, lasting?: boolean): GPUBuffer; /** * A mark's buffers and the uniform block they share. getMarkResources sets the * resolution, offset and clip before every draw, since the manager outlives the * frame that made it. */ export declare class BufferManager { private readonly device; private readonly bufferName; private uniformCache; private readonly uniforms; /** The uniforms as the shared buffer cache keys them, until a setter changes one. */ private uniformKey; constructor(device: GPUDevice, bufferName: string); createUniformBuffer(): GPUBuffer; /** * Uniform buffer for the current resolution and offset, reused across draws * that share them. Marks that draw many times per frame would otherwise mint * one per draw. Keyed by the values rather than shared outright, because the * render queue defers every draw to the end of the frame: one buffer rewritten * per group would hand every draw the last group's offset. */ sharedUniformBuffer(): GPUBuffer; createGeometryBuffer(data: Float32Array, lasting?: boolean): GPUBuffer; createInstanceBuffer(data: Float32Array): GPUBuffer; setResolution([width, height]: readonly [width: number, height: number]): void; setOffset(x: number, y: number): void; setDpi(dpi: number): void; /** * The rounded clip every draw from this mark is held to. A scissor rect is * exact for a plain box and already carries every clip in the chain, so the * shader is only told about the box whose corners it has to cut. */ setClipRound(round?: { box: readonly number[]; radii: readonly number[]; }): void; /** * Whether a clip path's coverage mask is bound and should be read. The mask * itself is a texture binding, and this is what tells the shader to look at * it rather than at the placeholder bound when there is no path clip. */ setClipMask(on: boolean): void; private setUniform; } export {};