import * as THREE from 'three/webgpu'; import type { TSLFloatNode, TSLUniformNode, TSLVec2Node, TSLVec4Node } from '../types/tsl.js'; /** Renderer surface required by AFVideo's decoded-view GPU array ring. */ export interface AFVideoGPUCacheRenderer { initRenderTarget(target: THREE.RenderTarget): void; copyTextureToTexture(source: THREE.Texture, destination: THREE.Texture, sourceRegion?: THREE.Box2 | THREE.Box3 | null, destinationPosition?: THREE.Vector2 | THREE.Vector3 | null, sourceLevel?: number, destinationLevel?: number): void; getRenderTarget(): THREE.RenderTarget | null; getActiveCubeFace(): number; getActiveMipmapLevel(): number; setRenderTarget(target: THREE.RenderTarget | null, activeCubeFace?: number, activeMipmapLevel?: number): void; render(scene: THREE.Object3D, camera: THREE.Camera): void; } /** Internal configuration transferred from BakedMotion to one AFVideo track. */ export interface AFVideoGPUCacheOptions { readonly renderer: AFVideoGPUCacheRenderer; readonly layers: number; } /** Immutable point-in-time cache counters. */ export interface AFVideoGPUCacheFacts { readonly enabled: boolean; readonly capacity: number; readonly resident: number; readonly hits: number; readonly misses: number; readonly primaryUploads: number; readonly alphaUploads: number; } /** Immutable upload/copy attribution for one AFVideo decoder channel. */ export interface AFVideoUploadChannelFacts { readonly gpuLumaUploads: number; readonly cpuCopyToCalls: number; readonly cpuCopyToTotalMs: number; readonly cpuCopyToMaxMs: number; } /** Immutable point-in-time upload/copy attribution for one AFVideo track. */ export interface AFVideoUploadFacts { readonly color: AFVideoUploadChannelFacts; readonly alpha: AFVideoUploadChannelFacts; } export type AFVideoGPUCacheChannel = 'primary' | 'alpha'; /** * Luma-byte reconstruction used when rasterizing a decoded VideoFrame into R8 cache layers. * `extremum` suits grayscale imagery with saturated borders (UTSBV depth/matte); `bt709` is the * exact matrix inverse for neutral-chroma data tracks (splat attribute planes). */ export type AFVideoLumaRecovery = 'extremum' | 'bt709'; /** * Which decode a backend already applied to a sampled video texel, and therefore which inverse * restores the authored code value. WebGPU samples through an sRGB texture view honouring the * frame's BT.709 transfer; the WebGL backend forces a linear internal format for video textures * and injects three's sRGB decode in the shader instead. */ export type AFVideoMatteDecode = 'bt709' | 'srgb'; /** * Whether a borrowed renderer exposes the synchronous state-preserving passes required by the * GPU array ring. Kept structural so BakedMotion's smaller public renderer surface remains valid. */ export declare function isAFVideoGPUCacheRenderer(value: unknown): value is AFVideoGPUCacheRenderer; /** * Per-track decoded-view LRU. Color is copied directly into RGBA array layers; semantic data and * embedded alpha take one tiny raster pass into R8 array layers, avoiding VideoFrame.copyTo(). */ export declare class AFVideoGPUCache { readonly renderer: AFVideoGPUCacheRenderer; readonly requestedCapacity: number; readonly dataChannel: boolean; readonly primaryTarget: THREE.RenderTarget; readonly alphaTarget: THREE.RenderTarget; readonly primaryUpload: THREE.VideoFrameTexture; readonly lumaUpload: THREE.VideoFrameTexture; readonly lumaTexelInset: TSLUniformNode<'vec2', THREE.Vector2>; readonly lumaPass: THREE.QuadMesh; readonly repackScale: TSLUniformNode<'vec2', THREE.Vector2>; readonly repackMatteOffset: TSLUniformNode<'vec2', THREE.Vector2>; readonly primaryLayers: TSLUniformNode<'int', number>[]; readonly alphaLayers: TSLUniformNode<'int', number>[]; readonly hasAlphaNode: TSLUniformNode<'int', number>; capacity: number; hasAlpha: boolean; initialized: boolean; hits: number; misses: number; private uploads; private primaryUploads; private alphaUploads; private primaryLumaUploads; private alphaLumaUploads; private clock; private frames; private lastUsed; private primaryReady; private alphaReady; private frameLayers; private readonly copyRegion; constructor({ renderer, layers, dataChannel, colorSpace, flipY, slots, lumaRecovery, }: AFVideoGPUCacheOptions & { dataChannel: boolean; colorSpace: THREE.ColorSpace; flipY: boolean; slots: number; lumaRecovery?: AFVideoLumaRecovery; }); initialize(width: number, height: number, totalFrames: number, hasAlpha: boolean): void; samplePrimary(slot: number, coordinate: TSLVec2Node): TSLVec4Node; /** * Sample the decoded embedded matte without also touching the primary color texture. * * This is intentionally separate from {@link sampleAlpha}: callers that already know the * track has an embedded matte can avoid compiling the opaque-primary fallback into hot * vertex shaders. * * @internal */ sampleMatte(slot: number, coordinate: TSLVec2Node): TSLFloatNode; sampleAlpha(slot: number, coordinate: TSLVec2Node): TSLFloatNode; lookup(frame: number, activeReady: boolean): boolean; resident(frame: number): boolean; channelReady(frame: number, channel: AFVideoGPUCacheChannel): boolean; layerFor(frame: number): number; /** * Whether one decoded channel can be uploaded without replacing a pinned presentation layer. * * This intentionally considers partially populated views as occupied. `facts.resident` counts * only views whose required channels are complete, so it cannot safely answer admission while * color and embedded-alpha outputs arrive independently. */ canUpload(frame: number, pinned: ReadonlySet): boolean; assignSlot(slot: number, frame: number, channel: AFVideoGPUCacheChannel): boolean; uploadPrimary(frame: VideoFrame, id: number, pinned: ReadonlySet): number; uploadAlpha(frame: VideoFrame, id: number, pinned: ReadonlySet): number; get uploadFacts(): Readonly; get uploadCount(): number; get facts(): Readonly; residentFrames(): readonly number[]; dispose(): void; private touch; private ensureLayer; private renderLuma; private renderQuad; }