@taole/giftstage 0.1.36 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. package/README.md +770 -694
  2. package/dist/core/audio-manager.d.ts +10 -1
  3. package/dist/core/gift-stage.d.ts +63 -1
  4. package/dist/core/index.d.ts +4 -4
  5. package/dist/core/post-animator.d.ts +1 -1
  6. package/dist/core/render-manager.d.ts +55 -6
  7. package/dist/{gift-stage.cjs.js → gift-stage.cjs} +1401 -287
  8. package/dist/gift-stage.es.js +11500 -6094
  9. package/dist/gpu/backend-operation-result.d.ts +6 -0
  10. package/dist/gpu/detect.d.ts +1 -1
  11. package/dist/gpu/index.d.ts +3 -3
  12. package/dist/gpu/webgl1-backend.d.ts +8 -4
  13. package/dist/gpu/webgl2-backend.d.ts +154 -4
  14. package/dist/gpu/webgpu-backend.d.ts +130 -4
  15. package/dist/index.d.ts +36 -27
  16. package/dist/parsers/atlas-builder.d.ts +1 -1
  17. package/dist/parsers/index.d.ts +7 -7
  18. package/dist/parsers/svga-parser-worker-client.d.ts +1 -1
  19. package/dist/parsers/svga-parser.d.ts +1 -1
  20. package/dist/parsers/svga-proto-js.d.ts +1 -1
  21. package/dist/parsers/svga-sprite-table-binary.d.ts +1 -1
  22. package/dist/parsers/svga-sprite-table.d.ts +1 -1
  23. package/dist/parsers/svga-worker-payload-binary.d.ts +3 -3
  24. package/dist/parsers/vap-config-parser.d.ts +1 -1
  25. package/dist/plugin/motion-track.d.ts +19 -0
  26. package/dist/plugin/playback-scope.d.ts +42 -0
  27. package/dist/plugin/types.d.ts +183 -0
  28. package/dist/public.d.ts +2 -0
  29. package/dist/renderers/alpha-video-renderer.d.ts +1 -1
  30. package/dist/renderers/image-renderer.d.ts +1 -1
  31. package/dist/renderers/index.d.ts +4 -4
  32. package/dist/renderers/particle-batch-renderer.d.ts +19 -0
  33. package/dist/renderers/svga-batch-renderer.d.ts +140 -7
  34. package/dist/renderers/vap-renderer.d.ts +1 -1
  35. package/dist/shaders/index.d.ts +20 -0
  36. package/dist/types/index.d.ts +357 -6
  37. package/dist/utils/clip-mesh.d.ts +13 -0
  38. package/dist/utils/gift-object-fit.d.ts +2 -2
  39. package/dist/utils/gift-transform.d.ts +3 -1
  40. package/dist/utils/resource-cache.d.ts +1 -1
  41. package/dist/utils/slot-content.d.ts +1 -1
  42. package/dist/utils/svga-binary-cache.d.ts +2 -2
  43. package/dist/utils/svga-frame-timeline.d.ts +95 -0
  44. package/dist/utils/svga-hybrid-command-table.d.ts +12 -0
  45. package/dist/utils/svga-slot-state-schema.d.ts +28 -0
  46. package/dist/utils/vap-mix-composer.d.ts +1 -1
  47. package/dist/utils/wc-atlas-upload-size.d.ts +1 -1
  48. package/dist/wasm/wasm-bridge.d.ts +1 -1
  49. package/dist/workers/svga-atlas-worker-client.d.ts +1 -1
  50. package/dist/workers/svga-clip-worker-client.d.ts +1 -1
  51. package/package.json +81 -76
@@ -0,0 +1,6 @@
1
+ import type { BackendOperationFailureReason, BackendOperationResult } from '../types/index.js';
2
+ /** Shared success result for allocation-free backend hot paths. */
3
+ export declare const BACKEND_OPERATION_SUBMITTED: BackendOperationResult;
4
+ export declare function rejectBackendOperation(reason: BackendOperationFailureReason, message?: string): BackendOperationResult;
5
+ /** Convert a rejected backend operation into the frame-level exception path. */
6
+ export declare function requireBackendOperation(result: BackendOperationResult, operation: string): void;
@@ -1,2 +1,2 @@
1
- import type { GPUBackend } from '../types';
1
+ import type { GPUBackend } from '../types/index.js';
2
2
  export declare function createBackend(canvas: HTMLCanvasElement, preferWebGPU?: boolean, antialias?: boolean, forceWebGL1?: boolean): Promise<GPUBackend>;
@@ -1,3 +1,3 @@
1
- export { createBackend } from './detect';
2
- export { WebGL2Backend } from './webgl2-backend';
3
- export { WebGPUBackend } from './webgpu-backend';
1
+ export { createBackend } from './detect.js';
2
+ export { WebGL2Backend } from './webgl2-backend.js';
3
+ export { WebGPUBackend } from './webgpu-backend.js';
@@ -1,4 +1,4 @@
1
- import type { GPUBackend, GPUBufferHandle, GPUTextureHandle, TextureOpts, BufferUsage, DrawCommand, GPUBufferSource } from '../types';
1
+ import type { GPUBackend, GPUBufferHandle, GPUTextureHandle, TextureOpts, BufferUsage, DrawCommand, GPUBufferSource, BackendOperationResult } from '../types/index.js';
2
2
  export declare class WebGL1Backend implements GPUBackend {
3
3
  readonly type: "webgl1";
4
4
  readonly canvas: HTMLCanvasElement;
@@ -13,6 +13,7 @@ export declare class WebGL1Backend implements GPUBackend {
13
13
  private cachedTex0Id;
14
14
  private cachedProjectionRef;
15
15
  private cachedProjectionShader;
16
+ private lastDrawSubmitted;
16
17
  private videoUploadCanvas;
17
18
  private videoUploadCtx;
18
19
  private supportsUintIndices;
@@ -38,8 +39,10 @@ export declare class WebGL1Backend implements GPUBackend {
38
39
  private applyDrawUniforms;
39
40
  beginFrame(options?: {
40
41
  stencil?: boolean;
41
- }): void;
42
- endFrame(): void;
42
+ }): BackendOperationResult;
43
+ endFrame(): BackendOperationResult;
44
+ abortFrame(): BackendOperationResult;
45
+ private errorMessage;
43
46
  private getBufferSourceByteLength;
44
47
  private normalizeIndexSource;
45
48
  createBuffer(data: GPUBufferSource, usage: BufferUsage): GPUBufferHandle;
@@ -52,7 +55,8 @@ export declare class WebGL1Backend implements GPUBackend {
52
55
  updateTexture(handle: GPUTextureHandle, source: TexImageSource): void;
53
56
  updateTextureRegion(handle: GPUTextureHandle, source: TexImageSource, x: number, y: number, destWidth?: number, destHeight?: number): void;
54
57
  deleteTexture(handle: GPUTextureHandle): void;
55
- draw(cmd: DrawCommand): void;
58
+ draw(cmd: DrawCommand): BackendOperationResult;
59
+ private drawInternal;
56
60
  clearStencil(): void;
57
61
  setScissor(x: number, y: number, w: number, h: number): void;
58
62
  resetScissor(): void;
@@ -1,6 +1,50 @@
1
- import type { GPUBackend, GPUBufferHandle, GPUTextureHandle, TextureOpts, BufferUsage, DrawCommand, GPUBufferSource } from '../types';
1
+ import type { GPUBackend, GPUBufferHandle, GPUTextureHandle, TextureOpts, BufferUsage, DrawCommand, GPUBufferSource, SVGAFrameTableBinding, SVGAFrameTableCreateOptions, BackendOperationResult } from '../types/index.js';
2
+ /** The table-aware shader is added by the timeline path without widening the
3
+ * public ShaderType union during the backend migration. */
4
+ export declare const WEBGL2_SVGA_FRAME_TABLE_SHADER: "svga-frame-table-instanced-premul";
5
+ export declare const WEBGL2_SVGA_FRAME_TABLE_FLOATS_PER_FRAME = 12;
6
+ /** Static UV/page metadata is two RGBA texels per sprite row. */
7
+ export declare const WEBGL2_SVGA_FRAME_METADATA_FLOATS_PER_SPRITE = 8;
8
+ export type WebGL2FrameTableBinding = Extract<SVGAFrameTableBinding, {
9
+ backend: 'webgl2';
10
+ }> & {
11
+ /** Static UV/page metadata texture paired with the frame table. */
12
+ spriteMetadataTexture?: GPUTextureHandle;
13
+ };
14
+ /**
15
+ * WebGL2 table-aware draw command. The backend accepts these fields through
16
+ * structural typing so the public DrawCommand can be widened independently.
17
+ */
18
+ export interface SVGAFrameTableDrawCommand extends DrawCommand {
19
+ svgaFrameTable?: WebGL2FrameTableBinding | GPUTextureHandle | null;
20
+ svgaFrameTableTexture?: GPUTextureHandle | null;
21
+ svgaSpriteMetadata?: GPUTextureHandle | null;
22
+ svgaSpriteMetadataTexture?: GPUTextureHandle | null;
23
+ svgaSpriteMetadataBase?: number;
24
+ svgaFrameTableMetadataBase?: number;
25
+ svgaFrameTableSlotState?: Float32Array;
26
+ svgaSlotState?: Float32Array;
27
+ svgaFrameIndex?: number;
28
+ svgaSpriteBase?: number;
29
+ svgaFrameTableAtlasPage?: number;
30
+ svgaFrameTableParentAffine?: Float32Array;
31
+ svgaFrameTableParentTranslate?: Float32Array;
32
+ svgaFrameTableOpacity?: number;
33
+ svgaFrameTableClipRect?: Float32Array;
34
+ svgaFrameTableFrameCount?: number;
35
+ svgaFrameTableSpriteCount?: number;
36
+ svgaFrameTableFrameIndex?: number;
37
+ svgaFrameTableSpriteBase?: number;
38
+ frameTableTexture?: GPUTextureHandle | null;
39
+ spriteMetadataTexture?: GPUTextureHandle | null;
40
+ frameTableFrameCount?: number;
41
+ frameTableSpriteCount?: number;
42
+ frameTableFrameIndex?: number;
43
+ frameTableSpriteBase?: number;
44
+ }
2
45
  export declare class WebGL2Backend implements GPUBackend {
3
46
  readonly type: "webgl2";
47
+ readonly supportsAtomicFrameReplay = true;
4
48
  readonly canvas: HTMLCanvasElement;
5
49
  maxTextureSize: number;
6
50
  private antialias;
@@ -8,11 +52,16 @@ export declare class WebGL2Backend implements GPUBackend {
8
52
  private nextId;
9
53
  private buffers;
10
54
  private textures;
55
+ private frameTables;
56
+ /** Metadata textures generated by a frame-table create call (external ones are not owned). */
57
+ private ownedFrameTableMetadataIds;
11
58
  private programs;
12
59
  private vertexArrays;
13
60
  /** Per-frame GL state caches (aligned with WebGPU bind-group / uniform write dedup). */
14
61
  private cachedDrawProgram;
15
62
  private cachedTex0Id;
63
+ private cachedFrameTableId;
64
+ private cachedFrameMetadataId;
16
65
  private cachedProjectionRef;
17
66
  private cachedProjectionShader;
18
67
  /** Canvas bridge retained for iOS/iPadOS WebKit and as a one-way runtime fallback. */
@@ -20,12 +69,24 @@ export declare class WebGL2Backend implements GPUBackend {
20
69
  private videoUploadCtx;
21
70
  private videoElementPreferCanvasBridge;
22
71
  private videoElementDirectUploadValidated;
72
+ /** WebGL2 float vertex-texture capability used by the SVGA frame-table path. */
73
+ maxVertexTextureImageUnits: number;
74
+ /** Set only after the table shader has compiled and vertex texture fetch is available. */
75
+ svgaFrameTableSupported: boolean;
23
76
  /** DYNAMIC_DRAW upload target for `svga-instanced-premul` (`FrameJobData` per instance). */
24
77
  private static readonly INST_SVGA_GL_MAX;
25
78
  private static readonly INST_SVGA_GL_FLOATS;
26
79
  private static readonly INST_SVGA_GL_STRIDE;
27
80
  private static readonly INST_SVGA_GL_BYTES;
28
81
  private instancedSvgaInstanceGLBuffer;
82
+ private svgaSlotStateTexture;
83
+ private svgaSlotStateTextureWidth;
84
+ private svgaSlotStateTextureHeight;
85
+ private svgaSlotStateUploadScratch;
86
+ private svgaSlotStateUploadId;
87
+ private readonly svgaTableInfoScratch;
88
+ private readonly svgaTableSizeScratch;
89
+ private readonly svgaMetadataSizeScratch;
29
90
  /** DYNAMIC_DRAW upload target for instanced clip-mask affine transforms. */
30
91
  private static readonly INST_CLIP_MASK_GL_MAX;
31
92
  private static readonly INST_CLIP_MASK_GL_FLOATS;
@@ -38,9 +99,50 @@ export declare class WebGL2Backend implements GPUBackend {
38
99
  private instancedAlphaInstanceGLBuffer;
39
100
  private static readonly INST_VAP_GL_MAX;
40
101
  private static readonly INST_VAP_GL_BYTES;
102
+ private performanceBufferWrites;
103
+ private performanceBufferWriteBytes;
104
+ private performanceStorageBufferWrites;
105
+ private performanceStorageBufferWriteBytes;
106
+ private performanceSubmittedDrawCalls;
107
+ private performanceRejectedDrawCalls;
108
+ private performanceSVGADynamicUploadWrites;
109
+ private performanceSVGADynamicUploadBytes;
110
+ private runtimeSubmittedDrawCalls;
111
+ private runtimeRejectedDrawCalls;
112
+ private currentDrawResult;
113
+ private currentDrawRecorded;
114
+ private runtimeBackendLosses;
115
+ private runtimeDiagnosticHandler;
116
+ private contextLost;
117
+ private deviceLostHandler;
118
+ private readonly onContextLost;
41
119
  private instancedVapInstanceGLBuffer;
42
120
  constructor(canvas: HTMLCanvasElement, antialias?: boolean);
43
121
  init(): Promise<void>;
122
+ getPerformanceSnapshot(): {
123
+ bufferWrites: number;
124
+ bufferWriteBytes: number;
125
+ storageBufferWrites: number;
126
+ storageBufferWriteBytes: number;
127
+ submittedDrawCalls: number;
128
+ rejectedDrawCalls: number;
129
+ svgaDynamicUploadWrites: number;
130
+ svgaDynamicUploadBytes: number;
131
+ };
132
+ getRuntimeDiagnosticsSnapshot(): {
133
+ submittedDrawCalls: number;
134
+ rejectedDrawCalls: number;
135
+ webgpuUncapturedErrors: number;
136
+ backendLosses: number;
137
+ };
138
+ setRuntimeDiagnosticHandler(handler: ((event: {
139
+ type: 'gpu-uncaptured-error' | 'backend-lost';
140
+ message?: string;
141
+ }) => void) | null): void;
142
+ resetPerformanceSnapshot(): void;
143
+ setDeviceLostHandler(handler: (() => void) | null): void;
144
+ private recordSubmittedDraw;
145
+ private rejectSVGAFastPathDraw;
44
146
  private initPrograms;
45
147
  private makeProgramEntry;
46
148
  /**
@@ -63,19 +165,53 @@ export declare class WebGL2Backend implements GPUBackend {
63
165
  private applyDrawUniforms;
64
166
  beginFrame(options?: {
65
167
  stencil?: boolean;
66
- }): void;
67
- endFrame(): void;
168
+ }): BackendOperationResult;
169
+ endFrame(): BackendOperationResult;
170
+ abortFrame(): BackendOperationResult;
171
+ private errorMessage;
68
172
  private getBufferSourceByteLength;
69
173
  createBuffer(data: GPUBufferSource, usage: BufferUsage): GPUBufferHandle;
70
174
  updateBuffer(handle: GPUBufferHandle, data: GPUBufferSource, offset?: number): void;
71
175
  deleteBuffer(handle: GPUBufferHandle): void;
72
176
  private uploadVideoFrameToTexture;
73
177
  createTexture(source: TexImageSource | ArrayBuffer, opts: TextureOpts): GPUTextureHandle;
178
+ /**
179
+ * Returns whether this context can sample the immutable SVGA table from a
180
+ * vertex shader. Callers should use this before selecting `gpu-direct`;
181
+ * a false result leaves the existing CPU-reference path untouched.
182
+ */
183
+ canCreateSVGAFrameTable(): boolean;
184
+ private assertSVGAFrameTableSupport;
185
+ private createFloatTableTexture;
186
+ /**
187
+ * Packs a linear RGBA texel stream into one 2D texture. Width is kept a
188
+ * multiple of the logical record width (3 frame texels or 2 metadata
189
+ * texels), while height is allowed to grow up to MAX_TEXTURE_SIZE. This
190
+ * avoids rejecting wide assets merely because `texelCount` exceeds the
191
+ * maximum texture height.
192
+ */
193
+ private createLinearFloatTableTexture;
194
+ /**
195
+ * Creates the resource-level static UV/page metadata texture paired with a
196
+ * frame table. Input rows may contain either four floats (UV only) or eight
197
+ * floats (UV + atlas page/flags). The compact four-float form uses page and
198
+ * flags zero in its second texel; row order remains the sprite index.
199
+ */
200
+ createSVGAFrameTableMetadata(metadata: Float32Array, spriteCount: number, strideFloats?: number): GPUTextureHandle;
201
+ /**
202
+ * Creates a single, non-paged RGBA32F SVGA frame table. Three texels are
203
+ * stored per `(sprite, frame)` row. Upload/setup errors throw before a
204
+ * usable binding is returned, allowing the caller to select CPU fallback.
205
+ */
206
+ createSVGAFrameTable(packedData: Float32Array, options: SVGAFrameTableCreateOptions): WebGL2FrameTableBinding;
207
+ deleteSVGAFrameTable(binding: SVGAFrameTableBinding | null | undefined): void;
74
208
  createEmptyTexture(width: number, height: number, opts?: TextureOpts): GPUTextureHandle;
75
209
  updateTexture(handle: GPUTextureHandle, source: TexImageSource): void;
76
210
  updateTextureRegion(handle: GPUTextureHandle, source: TexImageSource, x: number, y: number, destWidth?: number, destHeight?: number): void;
77
211
  deleteTexture(handle: GPUTextureHandle): void;
78
- draw(cmd: DrawCommand): void;
212
+ draw(cmd: DrawCommand): BackendOperationResult;
213
+ private completeDrawResult;
214
+ private rejectDrawResult;
79
215
  clearStencil(): void;
80
216
  setScissor(x: number, y: number, w: number, h: number): void;
81
217
  resetScissor(): void;
@@ -88,6 +224,20 @@ export declare class WebGL2Backend implements GPUBackend {
88
224
  private deleteVertexArraysForBuffer;
89
225
  private deleteAllVertexArrays;
90
226
  private ensureInstancedSvgaInstanceBuffer;
227
+ /** Uploads four RGBA32F texels per Direct slot for the compact multi-slot path. */
228
+ private uploadSVGASlotStates;
229
+ private resolveSVGAFrameTableSlotState;
230
+ /**
231
+ * One draw covers all sprites for one slot/atlas-page group. The frame and
232
+ * UV tables are immutable textures. Direct draws upload no per-sprite rows;
233
+ * Hybrid draws may upload compact scheduling rows without child matrices or
234
+ * alpha. A malformed/unsupported command returns without touching the
235
+ * existing CPU-reference draw path.
236
+ */
237
+ private drawSVGAFrameTableGL;
238
+ /** Shape/clip meshes fetch their child transform from the same resident frame table. */
239
+ private drawSVGAFrameTableMeshGL;
240
+ private drawInstancedParticlesGL;
91
241
  private drawInstancedSvgaGL;
92
242
  private ensureInstancedClipMaskBuffer;
93
243
  private drawInstancedClipMaskGL;
@@ -1,8 +1,50 @@
1
- import type { GPUBackend, GPUBufferHandle, GPUTextureHandle, TextureOpts, BufferUsage, DrawCommand, GPUBufferSource } from '../types';
1
+ import type { GPUBackend, GPUBufferHandle, GPUTextureHandle, TextureOpts, BufferUsage, DrawCommand, GPUBufferSource, SVGAFrameTableBinding, SVGAFrameTableCreateOptions, BackendOperationResult } from '../types/index.js';
2
2
  export declare const WEBGPU_INSTANCED_STORAGE_RING_BYTES: number;
3
+ /** Three vec4 values per (sprite, frame): layout/affine, translation and alpha. */
4
+ export declare const WEBGPU_SVGA_FRAME_TABLE_FLOATS_PER_FRAME = 12;
5
+ /** Two vec4 values per resident sprite metadata record (UV rect + page/flags). */
6
+ export declare const WEBGPU_SVGA_SPRITE_METADATA_FLOATS = 8;
7
+ export declare const WEBGPU_SVGA_SPRITE_METADATA_STRIDE: number;
8
+ /** Projection plus slot state; the uniform ring still rounds this to 256 bytes. */
9
+ export declare const WEBGPU_SVGA_FRAME_TABLE_SLOT_UNIFORM_BYTES = 160;
10
+ export declare const WEBGPU_SVGA_FRAME_TABLE_SHADER: "svga-frame-table-instanced-premul";
11
+ /**
12
+ * Draw-command extension consumed by the WebGPU timeline path. The public
13
+ * DrawCommand/GPUBackend interfaces are intentionally kept in `src/types` so
14
+ * other backend work can add the same fields without widening this module's
15
+ * dependency surface. The aliases are accepted during the migration window.
16
+ */
17
+ export interface SVGAFrameTableDrawCommand extends DrawCommand {
18
+ svgaFrameTable?: GPUBufferHandle | SVGAFrameTableBinding | null;
19
+ svgaFrameTableBuffer?: GPUBufferHandle | null;
20
+ svgaFrameTableFrameCount?: number;
21
+ svgaFrameTableSpriteCount?: number;
22
+ svgaFrameTableFrameIndex?: number;
23
+ svgaFrameIndex?: number;
24
+ svgaSpriteBase?: number;
25
+ svgaFrameTableAtlasPage?: number;
26
+ svgaFrameTableParentAffine?: Float32Array;
27
+ svgaFrameTableParentTranslate?: Float32Array;
28
+ svgaFrameTableOpacity?: number;
29
+ svgaFrameTableClipRect?: Float32Array;
30
+ svgaSpriteMetadata?: GPUBufferHandle | null;
31
+ svgaSpriteMetadataBuffer?: GPUBufferHandle | null;
32
+ spriteMetadataBuffer?: GPUBufferHandle | null;
33
+ svgaFrameTableMetadataBase?: number;
34
+ svgaFrameTableSpriteBase?: number;
35
+ frameTableSpriteBase?: number;
36
+ svgaSpriteMetadataBase?: number;
37
+ svgaFrameTableSlotState?: Float32Array;
38
+ svgaSlotState?: Float32Array;
39
+ frameTableBuffer?: GPUBufferHandle | null;
40
+ frameTableFrameCount?: number;
41
+ frameTableSpriteCount?: number;
42
+ frameTableFrameIndex?: number;
43
+ }
3
44
  export declare function alignWebGPUByteLength(byteLength: number, alignment: number): number;
4
45
  export declare class WebGPUBackend implements GPUBackend {
5
46
  readonly type: "webgpu";
47
+ readonly supportsAtomicFrameReplay = true;
6
48
  readonly canvas: HTMLCanvasElement;
7
49
  readonly maxTextureSize: number;
8
50
  private adapter;
@@ -21,6 +63,7 @@ export declare class WebGPUBackend implements GPUBackend {
21
63
  private dualTexturedBindGroupLayout;
22
64
  private instancedTextureBindGroupLayout;
23
65
  private uniformOnlyBindGroupLayout;
66
+ private svgaFrameTableBindGroupLayout;
24
67
  /** `device.limits.minUniformBufferOffsetAlignment` (typically 256). */
25
68
  private uniformSlotStride;
26
69
  /** Ring size for per-draw uniforms (`queue.writeBuffer` must not overwrite before draw — see `draw()`). */
@@ -50,6 +93,9 @@ export declare class WebGPUBackend implements GPUBackend {
50
93
  private readonly uniformScratch160;
51
94
  /** Single 128-byte upload for uniform-only draws (clip-mask: projection + transform). */
52
95
  private readonly uniformScratch128;
96
+ /** Projection + parent/slot state + table-info for the table-aware SVGA pipeline. */
97
+ private readonly svgaFrameTableUniformScratch;
98
+ private readonly svgaFrameTableUniformWords;
53
99
  private readonly uniformOpacityScratch;
54
100
  private depthStencilTexture;
55
101
  private depthStencilView;
@@ -85,9 +131,15 @@ export declare class WebGPUBackend implements GPUBackend {
85
131
  private dualTexturedBindGroupCache;
86
132
  /** All instanced pipelines also share one texture layout. */
87
133
  private instancedTextureBindGroupCache;
134
+ private particleDataBindGroupCache;
135
+ private motionDataBindGroupCache;
136
+ /** Table-aware SVGA bind groups are keyed by immutable frame-table + metadata ids. */
137
+ private svgaFrameTableDataBindGroupCache;
88
138
  /** Batched SVGA sprites (pre-scaled affine, UVs, and packed framebuffer clip rect). */
89
139
  private static readonly SVGA_INSTANCED_MAX;
90
140
  private static readonly SVGA_INSTANCED_STRIDE;
141
+ private static readonly SVGA_FRAME_TABLE_INSTANCE_MAX;
142
+ private static readonly SVGA_FRAME_TABLE_ROW_BYTES;
91
143
  private static readonly CLIP_MASK_INSTANCED_MAX;
92
144
  private static readonly CLIP_MASK_INSTANCED_STRIDE;
93
145
  /** Batched alpha-video (storage instances + projection uniform). */
@@ -95,6 +147,7 @@ export declare class WebGPUBackend implements GPUBackend {
95
147
  private static readonly ALPHA_INSTANCED_STRIDE;
96
148
  private static readonly VAP_INSTANCED_MAX;
97
149
  private static readonly VAP_INSTANCED_STRIDE;
150
+ private static readonly PARTICLE_INSTANCED_MAX;
98
151
  /**
99
152
  * Multiple `queue.writeBuffer(..., offset 0)` to the same storage buffer before one `submit` only keep the
100
153
  * last write; one shared ring + dynamic offsets keeps all instanced paths non-overlapping until submit.
@@ -105,6 +158,9 @@ export declare class WebGPUBackend implements GPUBackend {
105
158
  private storageBindOffsetAlign;
106
159
  /** Reset in `beginFrame`; all instanced draw types reserve non-overlapping chunks. */
107
160
  private instancedStorageRingOffset;
161
+ private svgaCompactSlotStateUploadId;
162
+ private svgaCompactSlotStateStorageBase;
163
+ private svgaCompactSlotStateByteLength;
108
164
  /** Grow-only CPU mirror; expands to the frame's actual storage high-water mark. */
109
165
  private instancedStorageShadow;
110
166
  private instancedStorageShadowDirtyMax;
@@ -118,6 +174,23 @@ export declare class WebGPUBackend implements GPUBackend {
118
174
  private performanceBufferWriteBytes;
119
175
  private performanceStorageBufferWrites;
120
176
  private performanceStorageBufferWriteBytes;
177
+ private performanceSubmittedDrawCalls;
178
+ private performanceRejectedDrawCalls;
179
+ private performanceSVGADynamicUploadWrites;
180
+ private performanceSVGADynamicUploadBytes;
181
+ private runtimeSubmittedDrawCalls;
182
+ private runtimeRejectedDrawCalls;
183
+ private currentDrawResult;
184
+ private currentDrawRecorded;
185
+ private runtimeUncapturedErrors;
186
+ private runtimeBackendLosses;
187
+ private runtimeDiagnosticHandler;
188
+ private deviceLost;
189
+ /** An uncaptured validation/submission error can surface after queue.submit(). */
190
+ private uncapturedErrorRequiresQuarantine;
191
+ private deviceLostHandler;
192
+ private readonly handleDeviceLoss;
193
+ private readonly handleUncapturedError;
121
194
  constructor(canvas: HTMLCanvasElement, adapter: GPUAdapter, wantAntialias?: boolean);
122
195
  init(): Promise<void>;
123
196
  private configureCanvasContext;
@@ -131,6 +204,16 @@ export declare class WebGPUBackend implements GPUBackend {
131
204
  private ensureInstancedClipMaskPipeline;
132
205
  private ensureInstancedAlphaPipeline;
133
206
  private ensureInstancedVapPipeline;
207
+ /**
208
+ * Lazily creates the table-aware SVGA pipeline. The frame table and sprite
209
+ * metadata are immutable storage buffers; only the slot/global uniform uses
210
+ * the per-draw dynamic uniform ring.
211
+ */
212
+ private ensureSVGAFrameTableDataLayout;
213
+ private ensureSVGAFrameTablePipeline;
214
+ private ensureSVGAFrameTableMeshPipeline;
215
+ private ensureMotionSvgaPipeline;
216
+ private ensureParticlePipeline;
134
217
  private createInstancedSvgaPipeline;
135
218
  private createInstancedClipMaskPipeline;
136
219
  private createVapInstancedPipeline;
@@ -139,15 +222,34 @@ export declare class WebGPUBackend implements GPUBackend {
139
222
  private createClipMaskPipeline;
140
223
  beginFrame(options?: {
141
224
  stencil?: boolean;
142
- }): void;
143
- endFrame(): void;
225
+ }): BackendOperationResult;
226
+ endFrame(): BackendOperationResult;
227
+ abortFrame(): BackendOperationResult;
228
+ private errorMessage;
144
229
  getPerformanceSnapshot(): {
145
230
  bufferWrites: number;
146
231
  bufferWriteBytes: number;
147
232
  storageBufferWrites: number;
148
233
  storageBufferWriteBytes: number;
234
+ submittedDrawCalls: number;
235
+ rejectedDrawCalls: number;
236
+ svgaDynamicUploadWrites: number;
237
+ svgaDynamicUploadBytes: number;
149
238
  };
150
239
  resetPerformanceSnapshot(): void;
240
+ getRuntimeDiagnosticsSnapshot(): {
241
+ submittedDrawCalls: number;
242
+ rejectedDrawCalls: number;
243
+ webgpuUncapturedErrors: number;
244
+ backendLosses: number;
245
+ };
246
+ setRuntimeDiagnosticHandler(handler: ((event: {
247
+ type: 'gpu-uncaptured-error' | 'backend-lost';
248
+ message?: string;
249
+ }) => void) | null): void;
250
+ setDeviceLostHandler(handler: (() => void) | null): void;
251
+ private recordSubmittedDraw;
252
+ private rejectSVGAFastPathDraw;
151
253
  private writeBuffer;
152
254
  /** Uploads the touched range of `uniformShadow` in one call — must run before `queue.submit`. */
153
255
  private flushUniformShadow;
@@ -161,6 +263,17 @@ export declare class WebGPUBackend implements GPUBackend {
161
263
  private bufferSourceByteLength;
162
264
  private mappedUploadView;
163
265
  private writeBufferSource;
266
+ /**
267
+ * Creates an immutable, long-lived SVGA frame table in device-local storage.
268
+ *
269
+ * The table is deliberately not allocated from the per-frame instanced ring:
270
+ * the same decoded entity can be used by many slots and should be uploaded
271
+ * once, then referenced by every table-aware draw until the entity is released.
272
+ * The table layout is three vec4 values (48 bytes) per sprite/frame row.
273
+ */
274
+ createSVGAFrameTable(data: Float32Array, options: SVGAFrameTableCreateOptions): SVGAFrameTableBinding;
275
+ /** Releases a table created by {@link createSVGAFrameTable}. */
276
+ deleteSVGAFrameTable(binding: SVGAFrameTableBinding): void;
164
277
  createBuffer(data: GPUBufferSource, usage: BufferUsage): GPUBufferHandle;
165
278
  updateBuffer(handle: GPUBufferHandle, data: GPUBufferSource, offset?: number): void;
166
279
  deleteBuffer(handle: GPUBufferHandle): void;
@@ -186,10 +299,23 @@ export declare class WebGPUBackend implements GPUBackend {
186
299
  private copyVideoFrameToTextureRegionDirect;
187
300
  private drawVideoLikeSourceToTextureRegion;
188
301
  deleteTexture(handle: GPUTextureHandle): void;
189
- draw(cmd: DrawCommand): void;
302
+ draw(cmd: DrawCommand): BackendOperationResult;
303
+ private drawInternal;
190
304
  /** One `drawIndexed` with `instanceCount` for all SVGA sprites sharing the same atlas. */
191
305
  private drawInstancedSvga;
192
306
  private drawInstancedClipMask;
307
+ /**
308
+ * Draws table-aware SVGA sprites. The frame table and sprite metadata are
309
+ * resident storage buffers. `instanceCount` is the number of sprites in
310
+ * this slot/page draw, while the GPU builtin instance index selects the
311
+ * metadata record; the animation path never uploads N sprite records per
312
+ * frame. A malformed command returns so the caller can use CPU fallback.
313
+ */
314
+ private drawSVGAFrameTableInstanced;
315
+ private resolveSVGAFrameTableSlotUniform;
316
+ private reserveSVGAFrameTableUniform;
317
+ private drawMotionInstancedSvga;
318
+ private drawInstancedParticles;
193
319
  /** One `drawIndexed` with `instanceCount` for all gifts sharing the same video texture (e.g. atlas). */
194
320
  private drawInstancedAlpha;
195
321
  private drawInstancedVap;
package/dist/index.d.ts CHANGED
@@ -1,27 +1,36 @@
1
- export { GiftStage } from './core/gift-stage';
2
- export { RenderManager } from './core/render-manager';
3
- export { AudioManager } from './core/audio-manager';
4
- export { PostAnimator } from './core/post-animator';
5
- export { WebGL2Backend } from './gpu/webgl2-backend';
6
- export { WebGL1Backend } from './gpu/webgl1-backend';
7
- export { WebGPUBackend } from './gpu/webgpu-backend';
8
- export { createBackend } from './gpu/detect';
9
- export { SVGABatchRenderer } from './renderers/svga-batch-renderer';
10
- export { VAPRenderer } from './renderers/vap-renderer';
11
- export { AlphaVideoRenderer } from './renderers/alpha-video-renderer';
12
- export { ImageRenderer } from './renderers/image-renderer';
13
- export { buildBatchVerticesJS } from './renderers/vertex-builder';
14
- export { parseSVGA } from './parsers/svga-parser';
15
- export type { ParseSVGAOptions } from './parsers/svga-parser';
16
- export { buildAtlas } from './parsers/atlas-builder';
17
- export { parseVAPConfig } from './parsers/vap-config-parser';
18
- export { inflateJS } from './parsers/inflate-js';
19
- export { decodeSVGAProto } from './parsers/svga-proto-js';
20
- export * from './utils/easing';
21
- export { ortho, lerp, clamp, generateId } from './utils/math';
22
- export { BufferPool } from './utils/buffer-pool';
23
- export { canWebGPU, canWebGL2, canWebGL1, canSharedArrayBuffer } from './utils/detect';
24
- export { initWasm, isWasmReady } from './wasm/wasm-bridge';
25
- export { WebCodecsMp4Playback } from './video/webcodecs-mp4-playback';
26
- export type { WebCodecsMp4CreateOptions } from './video/webcodecs-mp4-playback';
27
- export type { WebCodecsPlaybackHandle, GPUBackend, GPUBufferHandle, GPUTextureHandle, TextureOpts, BufferUsage, DrawCommand, ShaderType, BackendType, GiftStageOptions, AddGiftOptions, GiftHandle, GiftSlot, GiftType, GiftObjectFit, GiftCoordinate, GiftState, GiftAnimationStep, GiftAnimationChain, SVGAMovieEntity, SVGAParams, SVGASpriteTable, SVGAAudio, SVGATransform, SVGAShape, VideoEntity, UVRect, FrameJobData, FlyAnimation, VAPConfig, VAPSrcItem, VAPFrameItem, VAPFrameObj, } from './types';
1
+ export { GiftStage } from './core/gift-stage.js';
2
+ export { RenderManager } from './core/render-manager.js';
3
+ export { AudioManager } from './core/audio-manager.js';
4
+ export { PostAnimator } from './core/post-animator.js';
5
+ export { PlaybackScopeImpl } from './plugin/playback-scope.js';
6
+ export { MotionTrackLeaseImpl } from './plugin/motion-track.js';
7
+ export { MOTION_TRACK_SAMPLE_FLOATS } from './plugin/types.js';
8
+ export { WebGL2Backend } from './gpu/webgl2-backend.js';
9
+ export { WebGL1Backend } from './gpu/webgl1-backend.js';
10
+ export { WebGPUBackend } from './gpu/webgpu-backend.js';
11
+ export { createBackend } from './gpu/detect.js';
12
+ export { SVGABatchRenderer } from './renderers/svga-batch-renderer.js';
13
+ export { VAPRenderer } from './renderers/vap-renderer.js';
14
+ export { AlphaVideoRenderer } from './renderers/alpha-video-renderer.js';
15
+ export { ImageRenderer } from './renderers/image-renderer.js';
16
+ export { ParticleBatchRenderer } from './renderers/particle-batch-renderer.js';
17
+ export { buildBatchVerticesJS } from './renderers/vertex-builder.js';
18
+ export { parseSVGA } from './parsers/svga-parser.js';
19
+ export type { ParseSVGAOptions } from './parsers/svga-parser.js';
20
+ export { buildAtlas } from './parsers/atlas-builder.js';
21
+ export { parseVAPConfig } from './parsers/vap-config-parser.js';
22
+ export { inflateJS } from './parsers/inflate-js.js';
23
+ export { decodeSVGAProto } from './parsers/svga-proto-js.js';
24
+ export * from './utils/easing.js';
25
+ export { ortho, lerp, clamp, generateId } from './utils/math.js';
26
+ export { BufferPool } from './utils/buffer-pool.js';
27
+ export { analyzeSVGAFrameTimelineEligibility, countSVGASpriteAtlasPages, estimateSVGAFrameTableBytes, isSVGAFrameTableBudgetAvailable, isSVGAFrameTableWithinBudget, packSVGASpriteMetadata, packSVGAFrameDataToVec4, packSVGAFrameTable, SVGA_FRAME_TABLE_BUDGET_BYTES, SVGA_FRAME_TABLE_FLOATS, SVGA_GPU_FRAME_TABLE_BUDGET_BYTES, SVGA_SPRITE_METADATA_FLAG_MISSING_RECT, SVGA_SPRITE_METADATA_FLOATS, } from './utils/svga-frame-timeline.js';
28
+ export type { SVGAFrameTimelineEligibility, SVGAFrameTimelineEligibilityInput } from './utils/svga-frame-timeline.js';
29
+ export type { SVGASpriteMetadataPackOptions } from './utils/svga-frame-timeline.js';
30
+ export { buildSVGAHybridCommandTable, SVGA_HYBRID_OP_TEXTURE, SVGA_HYBRID_OP_SHAPE, SVGA_HYBRID_OP_CLIP_WRITE, SVGA_HYBRID_OP_CLIP_TEST, SVGA_HYBRID_OP_CLIP_CLEAR, } from './utils/svga-hybrid-command-table.js';
31
+ export { canWebGPU, canWebGL2, canWebGL1, canSharedArrayBuffer } from './utils/detect.js';
32
+ export { initWasm, isWasmReady } from './wasm/wasm-bridge.js';
33
+ export { WebCodecsMp4Playback } from './video/webcodecs-mp4-playback.js';
34
+ export type { WebCodecsMp4CreateOptions } from './video/webcodecs-mp4-playback.js';
35
+ export type { WebCodecsPlaybackHandle, GPUBackend, BackendOperationFailureReason, BackendOperationResult, GPUBufferHandle, GPUTextureHandle, TextureOpts, BufferUsage, DrawCommand, ShaderType, BackendType, ParentMotionMode, SVGADrawBatchMode, SVGAFrameEvaluation, SVGAFrameEvaluationStrategy, SVGAFrameTableBinding, SVGAFrameTableBindingBase, SVGAFrameTableCreateOptions, SVGAFrameTableState, SVGAFrameTimelineFallbackReason, SVGAFrameTimelinePath, SVGAFrameTimelineRenderInfo, SVGAFrameTimelineStrategy, SVGAFrameTimelineTransport, SVGARenderFallbackReason, SVGARenderInfo, SVGARenderPath, SVGARenderPathState, SVGARenderPathChangeInfo, GiftStageRuntimeDiagnosticType, GiftStageRuntimeDiagnosticEvent, GiftStageRuntimeDiagnostics, SVGAHybridCommandTable, SVGAHybridOperation, SVGAHybridOperationType, SVGATimelineDrawRun, WebGL2FrameTableBinding, WebGPUFrameTableBinding, GiftStageOptions, AddGiftOptions, GiftHandle, GiftSlot, GiftType, GiftObjectFit, GiftCoordinate, GiftState, GiftAnimationStep, GiftAnimationChain, SVGAMovieEntity, SVGAParams, SVGASpriteTable, SVGAAudio, SVGATransform, SVGAShape, VideoEntity, UVRect, FrameJobData, FlyAnimation, VAPConfig, VAPSrcItem, VAPFrameItem, VAPFrameObj, } from './types/index.js';
36
+ export type { GiftAssetLease, GiftAssetMetadata, GiftStageCapabilities, SVGAFrameTimelineCapabilities, GiftStagePlugin, GiftStagePluginHost, MountedGiftStagePlugin, MotionBindingOptions, MotionTrackDescriptor, MotionTrackLease, ParticleBatchDescriptor, ParticleBatchHandle, PlaybackFrame, PlaybackScope, PlaybackScopeStartOptions, PlaybackScopeState, ReadonlyTableDescriptor, ReadonlyTableLease, } from './plugin/types.js';
@@ -1,4 +1,4 @@
1
- import type { GPUBackend, GPUTextureHandle, UVRect } from '../types';
1
+ import type { GPUBackend, GPUTextureHandle, UVRect } from '../types/index.js';
2
2
  export interface AtlasPageResult {
3
3
  textureHandle: GPUTextureHandle;
4
4
  atlasWidth: number;
@@ -1,7 +1,7 @@
1
- export { parseSVGA } from './svga-parser';
2
- export type { ParseResult } from './svga-parser';
3
- export { buildAtlas } from './atlas-builder';
4
- export type { AtlasResult } from './atlas-builder';
5
- export { parseVAPConfig, getVAPFrame, computeVAPUV } from './vap-config-parser';
6
- export { inflateJS } from './inflate-js';
7
- export { decodeSVGAProto } from './svga-proto-js';
1
+ export { parseSVGA } from './svga-parser.js';
2
+ export type { ParseResult } from './svga-parser.js';
3
+ export { buildAtlas } from './atlas-builder.js';
4
+ export type { AtlasResult } from './atlas-builder.js';
5
+ export { parseVAPConfig, getVAPFrame, computeVAPUV } from './vap-config-parser.js';
6
+ export { inflateJS } from './inflate-js.js';
7
+ export { decodeSVGAProto } from './svga-proto-js.js';
@@ -2,7 +2,7 @@
2
2
  * Dedicated Worker client for SVGA inflate + protobuf (see ../workers/parser-worker.ts).
3
3
  * ImageBitmap creation stays on the main thread.
4
4
  */
5
- import type { SVGAMovieEntity, SVGASpriteTable } from '../types';
5
+ import type { SVGAMovieEntity, SVGASpriteTable } from '../types/index.js';
6
6
  export interface SVGAParserWorkerOptions {
7
7
  profile?: boolean;
8
8
  workerTimeSliceMs?: number;
@@ -1,4 +1,4 @@
1
- import type { SVGAMovieEntity } from '../types';
1
+ import type { SVGAMovieEntity } from '../types/index.js';
2
2
  export interface ParseResult {
3
3
  movie: SVGAMovieEntity;
4
4
  imageBitmaps: Map<string, ImageBitmap>;
@@ -3,5 +3,5 @@
3
3
  * Falls back to this when WASM is unavailable.
4
4
  * Implements just enough proto2 wire format to decode the SVGA schema.
5
5
  */
6
- import type { SVGAMovieEntity } from '../types';
6
+ import type { SVGAMovieEntity } from '../types/index.js';
7
7
  export declare function decodeSVGAProto(data: Uint8Array): SVGAMovieEntity;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * Shared SoA sprite-table binary section (SGPB v2 / SGBC v14).
3
3
  */
4
- import type { SVGASpriteTable } from '../types';
4
+ import type { SVGASpriteTable } from '../types/index.js';
5
5
  declare function align4(offset: number): number;
6
6
  export interface SpriteTableBinaryWriter {
7
7
  u8(value: number): void;
@@ -2,7 +2,7 @@
2
2
  * SVGA sprite SoA table: flat frame floats + deduped clip/shapes side tables.
3
3
  * Replaces per-sprite `frames: SVGAFrame[]` object graphs on the hot path.
4
4
  */
5
- import type { SVGAParams, SVGAShape, SVGATransform } from '../types';
5
+ import type { SVGAParams, SVGAShape, SVGATransform } from '../types/index.js';
6
6
  /** Floats per frame in `frameData`: layoutW, layoutH, a, b, c, d, tx, ty, alpha. */
7
7
  export declare const SPRITE_FRAME_FLOATS = 9;
8
8
  export interface SVGASpriteTable {
@@ -1,6 +1,6 @@
1
- import type { SVGAMovieEntity } from '../types';
2
- import type { SVGAWorkerMoviePayload } from './svga-parser-worker-client';
3
- import { type SpriteTableCheckpoint } from './svga-sprite-table-binary';
1
+ import type { SVGAMovieEntity } from '../types/index.js';
2
+ import type { SVGAWorkerMoviePayload } from './svga-parser-worker-client.js';
3
+ import { type SpriteTableCheckpoint } from './svga-sprite-table-binary.js';
4
4
  export declare function serializeSVGAWorkerPayload(payload: SVGAWorkerMoviePayload): ArrayBuffer;
5
5
  export declare function serializeSVGAWorkerPayloadCooperative(payload: SVGAWorkerMoviePayload, checkpoint: SpriteTableCheckpoint): Promise<ArrayBuffer>;
6
6
  export declare function deserializeSVGAWorkerPayload(buffer: ArrayBuffer, debug?: Record<string, unknown>): SVGAWorkerMoviePayload;