import type { ComputePipeline, GpuContext, GpuTexture, RenderPipeline, ShaderReflection } from "./types.js"; /** How a {@link RingAllocator} is bound: sets its usage and offset alignment. */ export type RingAllocatorKind = "uniform" | "read-only-storage"; /** * Per-frame ring buffer. Each draw's structs are packed into CPU staging at * aligned offsets, bound through bind groups with dynamic offsets, and flushed * with a single writeBuffer before submission. * * One instance per binding kind: uniform and storage have different usage flags * and different minimum offset alignments, and a slice has to satisfy the one * it will be bound as. */ export declare class RingAllocator { #private; buffer: GPUBuffer; /** Incremented when the GPU buffer is replaced; part of bind group cache keys. */ generation: number; constructor(device: GPUDevice, kind?: RingAllocatorKind, initialSize?: number); get staging(): ArrayBuffer; /** Reserve an aligned slice; returns its byte offset. Grows when exhausted. */ allocate(size: number): number; /** Upload the staged range. Called before queue submission. */ flush(): void; /** Start a new frame: reclaim the cursor and destroy retired buffers. */ reset(): void; dispose(): void; } export interface ActivePass { encoder: GPURenderPassEncoder; colorFormats: (GPUTextureFormat | null)[]; depthStencilFormat: GPUTextureFormat | undefined; /** Pipelines in this pass must not write depth. */ depthReadOnly: boolean; sampleCount: number; /** Signature of everything above, part of pipeline variant cache keys. */ key: string; } export interface ActiveComputePass { encoder: GPUComputePassEncoder; } /** * Per-pipeline-object cache: shader reflection and pipeline layout are resolved * once per plain pipeline object (its WGSL sources are assumed immutable), and * GPU pipelines are stored per variant signature — pass formats, vertex layout * and mutable pipeline state. */ export interface CachedPipelines { reflection: ShaderReflection; layout: GPUPipelineLayout; layoutKey: string; variants: Map; } /** * Adds the per-stage sources resolved from the pipeline's shader form, so the * combined `shader` is unfolded once rather than at every variant miss. * `fragmentSource` undefined means a pipeline with no fragment stage. */ export interface CachedRenderPipelines extends CachedPipelines { vertexSource: string; fragmentSource: string | undefined; } export interface FrameState { encoder: GPUCommandEncoder; /** * The literal swapchain texture for this segment, distinct from * FrameSegment.canvasTexture when preserveDrawingBuffer routes rendering * through a backbuffer instead — endFrame() blits into this. */ swapchainTexture: GPUTexture; canvasView: GPUTextureView; /** * Whether the managed canvas depth/stencil has been attached to a pass this * frame — it clears at first use and loads afterwards. */ canvasDepthStencilCleared: boolean; activePass: ActivePass | null; activeComputePass: ActiveComputePass | null; } export interface CommandsState { /** * Lazy — created at the first submit that packs uniforms, so the frame loop * costs nothing for code that never submits a declarative command. */ allocator: RingAllocator | null; /** Runtime-sized `array` storage bindings filled from a JS array. */ storageAllocator: RingAllocator | null; bindGroupLayouts: Map; pipelineLayouts: Map; /** * Cache keys embed the ids of the GpuBuffer/GpuTexture wrappers bound in each * group; a disposed-and-replaced resource would otherwise leave its old bind * group cached forever. `bindGroupsByResource` is the reverse index (resource * id → cache keys), pruned by `bindGroupFinalizer` once a wrapper is * unreachable — GC-triggered rather than tied to `dispose()`, so a * GpuBuffer/GpuTexture's dispose() never needs to know the * declarative-commands cache exists. */ bindGroups: Map; bindGroupsByResource: Map>; bindGroupFinalizer: FinalizationRegistry; renderPipelines: WeakMap; computePipelines: WeakMap>; /** * Pipeline objects whose reflection threw or whose GPU pipeline failed * validation. Their submits are skipped: the error is reported once, and an * invalid pipeline would otherwise invalidate the whole command buffer. */ failedPipelines: WeakSet; /** * Context-managed canvas-sized depth/stencil texture (depthStencilAttachment: * "canvas"). */ canvasDepthStencil: GpuTexture | null; frame: FrameState | null; } export declare function commandsState(ctx: GpuContext): CommandsState; /** * Like {@link commandsState}, but never creates one — for teardown paths that * must not allocate state for a context that never submitted a declarative * command. */ export declare function peekCommandsState(ctx: GpuContext): CommandsState | undefined; /** * Register a bind-group-cacheable resource wrapper (a GpuBuffer/GpuTexture, not * the raw GPUBuffer/GPUTextureView the bind group actually retains — a * FinalizationRegistry watching the retained object would never fire, since the * very cache entry it's meant to prune keeps it alive) so its cache entries are * pruned once the wrapper is unreachable. A no-op past the first call for a * given id. */ export declare function trackBindGroupResource(state: CommandsState, id: number, wrapper: object, cacheKey: string): void; export declare function frameState(ctx: GpuContext): FrameState; //# sourceMappingURL=state.d.ts.map