@taole/giftstage 0.1.33 → 0.1.35
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.
- package/dist/assets/webcodecs-mp4.worker-DeS4ARzq.js +398 -0
- package/dist/core/audio-manager.d.ts +9 -2
- package/dist/core/gift-stage.d.ts +26 -0
- package/dist/core/render-manager.d.ts +32 -0
- package/dist/gift-stage.cjs.js +753 -634
- package/dist/gift-stage.es.js +6580 -5348
- package/dist/gpu/webgl1-backend.d.ts +17 -1
- package/dist/gpu/webgl2-backend.d.ts +29 -1
- package/dist/gpu/webgpu-backend.d.ts +45 -5
- package/dist/parsers/svga-sprite-table.d.ts +7 -1
- package/dist/parsers/vap-config-parser.d.ts +11 -9
- package/dist/renderers/alpha-video-renderer.d.ts +1 -0
- package/dist/renderers/image-renderer.d.ts +5 -0
- package/dist/renderers/svga-batch-renderer.d.ts +172 -1
- package/dist/renderers/vap-renderer.d.ts +24 -0
- package/dist/shaders/index.d.ts +5 -0
- package/dist/types/index.d.ts +93 -4
- package/dist/utils/gift-transform.d.ts +4 -3
- package/dist/utils/resource-cache.d.ts +13 -0
- package/dist/video/webcodecs-mp4-core.d.ts +51 -0
- package/dist/video/webcodecs-mp4-playback.d.ts +24 -0
- package/package.json +1 -1
- package/dist/assets/webcodecs-mp4.worker-BvV8Fiyc.js +0 -369
|
@@ -19,7 +19,23 @@ export declare class WebGL1Backend implements GPUBackend {
|
|
|
19
19
|
constructor(canvas: HTMLCanvasElement, antialias?: boolean);
|
|
20
20
|
init(): Promise<void>;
|
|
21
21
|
private initPrograms;
|
|
22
|
-
private
|
|
22
|
+
private makeProgramEntry;
|
|
23
|
+
/**
|
|
24
|
+
* `u_transform` on `svga-batch-premul` defaults to identity; shape draws overwrite it and
|
|
25
|
+
* this re-upload restores it for the next plain batch draw. Uploaded unconditionally because
|
|
26
|
+
* renderers mutate their scratch transform arrays in place (reference never changes).
|
|
27
|
+
*/
|
|
28
|
+
private applyIdentityTransform;
|
|
29
|
+
/** Sampler uniforms are constant per shader; set them once instead of every draw. */
|
|
30
|
+
private bindProgramSamplers;
|
|
31
|
+
/**
|
|
32
|
+
* `u_transform` always comes from a renderer-owned scratch `Float32Array` that gets
|
|
33
|
+
* overwritten in place per draw, so its reference never changes — only its content does.
|
|
34
|
+
* Skipping the upload based on reference equality would silently apply a stale transform,
|
|
35
|
+
* so unlike `u_projection` (whose cached arrays are replaced, not mutated, on resize) it is
|
|
36
|
+
* uploaded unconditionally here.
|
|
37
|
+
*/
|
|
38
|
+
private applyDrawUniforms;
|
|
23
39
|
beginFrame(options?: {
|
|
24
40
|
stencil?: boolean;
|
|
25
41
|
}): void;
|
|
@@ -22,8 +22,16 @@ export declare class WebGL2Backend implements GPUBackend {
|
|
|
22
22
|
private videoElementDirectUploadValidated;
|
|
23
23
|
/** DYNAMIC_DRAW upload target for `svga-instanced-premul` (`FrameJobData` per instance). */
|
|
24
24
|
private static readonly INST_SVGA_GL_MAX;
|
|
25
|
+
private static readonly INST_SVGA_GL_FLOATS;
|
|
26
|
+
private static readonly INST_SVGA_GL_STRIDE;
|
|
25
27
|
private static readonly INST_SVGA_GL_BYTES;
|
|
26
28
|
private instancedSvgaInstanceGLBuffer;
|
|
29
|
+
/** DYNAMIC_DRAW upload target for instanced clip-mask affine transforms. */
|
|
30
|
+
private static readonly INST_CLIP_MASK_GL_MAX;
|
|
31
|
+
private static readonly INST_CLIP_MASK_GL_FLOATS;
|
|
32
|
+
private static readonly INST_CLIP_MASK_GL_STRIDE;
|
|
33
|
+
private static readonly INST_CLIP_MASK_GL_BYTES;
|
|
34
|
+
private instancedClipMaskGLBuffer;
|
|
27
35
|
/** DYNAMIC_DRAW upload target for `alpha-video-instanced` (rect+atlasRemap+opacity per instance). */
|
|
28
36
|
private static readonly INST_ALPHA_GL_MAX;
|
|
29
37
|
private static readonly INST_ALPHA_GL_BYTES;
|
|
@@ -34,7 +42,25 @@ export declare class WebGL2Backend implements GPUBackend {
|
|
|
34
42
|
constructor(canvas: HTMLCanvasElement, antialias?: boolean);
|
|
35
43
|
init(): Promise<void>;
|
|
36
44
|
private initPrograms;
|
|
37
|
-
private
|
|
45
|
+
private makeProgramEntry;
|
|
46
|
+
/**
|
|
47
|
+
* `u_transform` on `svga-batch-premul` defaults to identity; shape draws overwrite it and
|
|
48
|
+
* this re-upload restores it for the next plain batch draw. Uploaded unconditionally because
|
|
49
|
+
* renderers mutate their scratch transform arrays in place (reference never changes).
|
|
50
|
+
*/
|
|
51
|
+
private applyIdentityTransform;
|
|
52
|
+
/** Sampler uniforms are constant per shader; set them once instead of every draw. */
|
|
53
|
+
private bindProgramSamplers;
|
|
54
|
+
/** Shared by `draw()` and the instanced draw paths, which only ever supply `u_projection`. */
|
|
55
|
+
private applyProjectionUniform;
|
|
56
|
+
/**
|
|
57
|
+
* `u_transform` always comes from a renderer-owned scratch `Float32Array` that gets
|
|
58
|
+
* overwritten in place per draw, so its reference never changes — only its content does.
|
|
59
|
+
* Skipping the upload based on reference equality would silently apply a stale transform,
|
|
60
|
+
* so unlike `u_projection` (whose cached arrays are replaced, not mutated, on resize) it is
|
|
61
|
+
* uploaded unconditionally here.
|
|
62
|
+
*/
|
|
63
|
+
private applyDrawUniforms;
|
|
38
64
|
beginFrame(options?: {
|
|
39
65
|
stencil?: boolean;
|
|
40
66
|
}): void;
|
|
@@ -63,6 +89,8 @@ export declare class WebGL2Backend implements GPUBackend {
|
|
|
63
89
|
private deleteAllVertexArrays;
|
|
64
90
|
private ensureInstancedSvgaInstanceBuffer;
|
|
65
91
|
private drawInstancedSvgaGL;
|
|
92
|
+
private ensureInstancedClipMaskBuffer;
|
|
93
|
+
private drawInstancedClipMaskGL;
|
|
66
94
|
private ensureInstancedAlphaInstanceBuffer;
|
|
67
95
|
private drawInstancedAlphaGL;
|
|
68
96
|
private ensureInstancedVapInstanceBuffer;
|
|
@@ -27,6 +27,19 @@ export declare class WebGPUBackend implements GPUBackend {
|
|
|
27
27
|
private readonly maxUniformSlots;
|
|
28
28
|
/** Resets each `beginFrame`. */
|
|
29
29
|
private uniformSlotIndex;
|
|
30
|
+
/**
|
|
31
|
+
* CPU-side mirror of `uniformBuffer`, sized identically. Per-draw uniform writes go here
|
|
32
|
+
* instead of `queue.writeBuffer` directly; `endFrame` uploads the touched byte range in one
|
|
33
|
+
* `writeBuffer` call before `submit`, cutting dozens of JS→native calls per frame down to one
|
|
34
|
+
* (writes are visible to the frame's command buffer as long as they land before `submit`).
|
|
35
|
+
* Eagerly sized from the default stride/slot count so it's always usable even before `init()`
|
|
36
|
+
* creates the real GPU buffer (matching size); `init()` reallocates it to the device's actual
|
|
37
|
+
* uniform offset alignment.
|
|
38
|
+
*/
|
|
39
|
+
private uniformShadow;
|
|
40
|
+
/** Half-open touched range `[min, max)` in `uniformShadow`; reset each `beginFrame`. */
|
|
41
|
+
private uniformShadowDirtyMin;
|
|
42
|
+
private uniformShadowDirtyMax;
|
|
30
43
|
/** Skip redundant `setPipeline` / stencil / VB-IB when drawing many quads with the same geometry. */
|
|
31
44
|
private lastDrawPipeline;
|
|
32
45
|
private lastStencilRef;
|
|
@@ -72,18 +85,16 @@ export declare class WebGPUBackend implements GPUBackend {
|
|
|
72
85
|
private dualTexturedBindGroupCache;
|
|
73
86
|
/** All instanced pipelines also share one texture layout. */
|
|
74
87
|
private instancedTextureBindGroupCache;
|
|
75
|
-
/** Batched SVGA sprites (
|
|
88
|
+
/** Batched SVGA sprites (pre-scaled affine, UVs, and packed framebuffer clip rect). */
|
|
76
89
|
private static readonly SVGA_INSTANCED_MAX;
|
|
77
90
|
private static readonly SVGA_INSTANCED_STRIDE;
|
|
91
|
+
private static readonly CLIP_MASK_INSTANCED_MAX;
|
|
92
|
+
private static readonly CLIP_MASK_INSTANCED_STRIDE;
|
|
78
93
|
/** Batched alpha-video (storage instances + projection uniform). */
|
|
79
94
|
private static readonly ALPHA_INSTANCED_MAX;
|
|
80
95
|
private static readonly ALPHA_INSTANCED_STRIDE;
|
|
81
96
|
private static readonly VAP_INSTANCED_MAX;
|
|
82
97
|
private static readonly VAP_INSTANCED_STRIDE;
|
|
83
|
-
/** One draw may bind up to this many bytes of instance storage (max instances × stride). */
|
|
84
|
-
private static readonly INSTANCED_SVGA_CHUNK_BYTES;
|
|
85
|
-
private static readonly INSTANCED_ALPHA_CHUNK_BYTES;
|
|
86
|
-
private static readonly INSTANCED_VAP_CHUNK_BYTES;
|
|
87
98
|
/**
|
|
88
99
|
* Multiple `queue.writeBuffer(..., offset 0)` to the same storage buffer before one `submit` only keep the
|
|
89
100
|
* last write; one shared ring + dynamic offsets keeps all instanced paths non-overlapping until submit.
|
|
@@ -94,9 +105,19 @@ export declare class WebGPUBackend implements GPUBackend {
|
|
|
94
105
|
private storageBindOffsetAlign;
|
|
95
106
|
/** Reset in `beginFrame`; all instanced draw types reserve non-overlapping chunks. */
|
|
96
107
|
private instancedStorageRingOffset;
|
|
108
|
+
/** Grow-only CPU mirror; expands to the frame's actual storage high-water mark. */
|
|
109
|
+
private instancedStorageShadow;
|
|
110
|
+
private instancedStorageShadowDirtyMax;
|
|
97
111
|
private readonly instancedProjectionCache;
|
|
98
112
|
private instancedProjectionValid;
|
|
113
|
+
/** Storage range written by the latest instanced clip-mask write pass; reused by its clear. */
|
|
114
|
+
private lastClipMaskStorageBase;
|
|
115
|
+
private lastClipMaskStorageByteLength;
|
|
99
116
|
private lastInstancedTextureBindGroup;
|
|
117
|
+
private performanceBufferWrites;
|
|
118
|
+
private performanceBufferWriteBytes;
|
|
119
|
+
private performanceStorageBufferWrites;
|
|
120
|
+
private performanceStorageBufferWriteBytes;
|
|
100
121
|
constructor(canvas: HTMLCanvasElement, adapter: GPUAdapter, wantAntialias?: boolean);
|
|
101
122
|
init(): Promise<void>;
|
|
102
123
|
private configureCanvasContext;
|
|
@@ -105,10 +126,13 @@ export declare class WebGPUBackend implements GPUBackend {
|
|
|
105
126
|
private ensureStencilPipelines;
|
|
106
127
|
private ensureInstancedProjectionBuffer;
|
|
107
128
|
private ensureInstancedStorageBuffer;
|
|
129
|
+
private ensureInstancedDataBindGroup;
|
|
108
130
|
private ensureInstancedSvgaPipeline;
|
|
131
|
+
private ensureInstancedClipMaskPipeline;
|
|
109
132
|
private ensureInstancedAlphaPipeline;
|
|
110
133
|
private ensureInstancedVapPipeline;
|
|
111
134
|
private createInstancedSvgaPipeline;
|
|
135
|
+
private createInstancedClipMaskPipeline;
|
|
112
136
|
private createVapInstancedPipeline;
|
|
113
137
|
private createInstancedAlphaVideoPipeline;
|
|
114
138
|
private createTexturedPipeline;
|
|
@@ -117,6 +141,21 @@ export declare class WebGPUBackend implements GPUBackend {
|
|
|
117
141
|
stencil?: boolean;
|
|
118
142
|
}): void;
|
|
119
143
|
endFrame(): void;
|
|
144
|
+
getPerformanceSnapshot(): {
|
|
145
|
+
bufferWrites: number;
|
|
146
|
+
bufferWriteBytes: number;
|
|
147
|
+
storageBufferWrites: number;
|
|
148
|
+
storageBufferWriteBytes: number;
|
|
149
|
+
};
|
|
150
|
+
resetPerformanceSnapshot(): void;
|
|
151
|
+
private writeBuffer;
|
|
152
|
+
/** Uploads the touched range of `uniformShadow` in one call — must run before `queue.submit`. */
|
|
153
|
+
private flushUniformShadow;
|
|
154
|
+
/** Uploads every instanced draw's non-overlapping shadow range in one call before submit. */
|
|
155
|
+
private flushInstancedStorageShadow;
|
|
156
|
+
private writeInstancedStorageShadow;
|
|
157
|
+
/** Records a per-draw uniform write into the CPU shadow instead of touching the GPU buffer. */
|
|
158
|
+
private writeUniformShadow;
|
|
120
159
|
private ensureInstancedProjection;
|
|
121
160
|
private gpuBufferUsage;
|
|
122
161
|
private bufferSourceByteLength;
|
|
@@ -150,6 +189,7 @@ export declare class WebGPUBackend implements GPUBackend {
|
|
|
150
189
|
draw(cmd: DrawCommand): void;
|
|
151
190
|
/** One `drawIndexed` with `instanceCount` for all SVGA sprites sharing the same atlas. */
|
|
152
191
|
private drawInstancedSvga;
|
|
192
|
+
private drawInstancedClipMask;
|
|
153
193
|
/** One `drawIndexed` with `instanceCount` for all gifts sharing the same video texture (e.g. atlas). */
|
|
154
194
|
private drawInstancedAlpha;
|
|
155
195
|
private drawInstancedVap;
|
|
@@ -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 { SVGAShape, SVGATransform } from '../types';
|
|
5
|
+
import type { SVGAParams, SVGAShape, SVGATransform } from '../types';
|
|
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 {
|
|
@@ -20,6 +20,7 @@ export interface SVGASpriteTable {
|
|
|
20
20
|
/** spriteCount × frameCount; -1 = none. */
|
|
21
21
|
shapesIndex: Int32Array;
|
|
22
22
|
hasAnyShapes: boolean;
|
|
23
|
+
allFramesInsideViewBox?: boolean;
|
|
23
24
|
}
|
|
24
25
|
/** Loose frame shape used when converting from AoS decode (JS proto / fixtures). */
|
|
25
26
|
export interface SVGAFrameLike {
|
|
@@ -55,5 +56,10 @@ export declare function getSpriteClipPath(table: SVGASpriteTable, spriteIndex: n
|
|
|
55
56
|
* Resolves shape `keep` chains to shared array references.
|
|
56
57
|
*/
|
|
57
58
|
export declare function spriteTableFromSprites(sprites: SVGASpriteLike[], frameCountHint?: number): SVGASpriteTable;
|
|
59
|
+
/**
|
|
60
|
+
* Compute the renderer's scissor-elision flag before the entity becomes renderable. Shapes are
|
|
61
|
+
* conservative because their geometry is not represented by the sprite layout rectangle.
|
|
62
|
+
*/
|
|
63
|
+
export declare function ensureAllFramesInsideViewBox(params: Pick<SVGAParams, 'viewBoxWidth' | 'viewBoxHeight'>, table: SVGASpriteTable): boolean;
|
|
58
64
|
/** Empty table used when there are no sprites. */
|
|
59
65
|
export declare function emptySpriteTable(frameCount?: number): SVGASpriteTable;
|
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
import type { VAPConfig, VAPFrameItem } from '../types';
|
|
2
2
|
export declare function parseVAPConfig(config: string | object): Promise<VAPConfig>;
|
|
3
3
|
export declare function getVAPFrame(config: VAPConfig, frameIndex: number): VAPFrameItem | undefined;
|
|
4
|
-
|
|
5
|
-
* Logical content size for layout/aspect (matches visible RGB frame, not full mp4 frame).
|
|
6
|
-
* `videoW`/`videoH` often include separate alpha bands; use `w`/`h` or `rgbFrame` w×h.
|
|
7
|
-
*/
|
|
8
|
-
export declare function getVAPContentSize(info: VAPConfig['info']): {
|
|
4
|
+
export interface VAPContentSize {
|
|
9
5
|
w: number;
|
|
10
6
|
h: number;
|
|
11
|
-
}
|
|
7
|
+
}
|
|
12
8
|
/**
|
|
13
|
-
*
|
|
9
|
+
* Logical content size for layout/aspect (matches visible RGB frame, not full mp4 frame).
|
|
10
|
+
* `videoW`/`videoH` often include separate alpha bands; use `w`/`h` or `rgbFrame` w×h.
|
|
14
11
|
*/
|
|
15
|
-
export declare function
|
|
12
|
+
export declare function getVAPContentSize(info: VAPConfig['info'], out?: VAPContentSize): VAPContentSize;
|
|
13
|
+
export interface VAPUVRect {
|
|
16
14
|
left: number;
|
|
17
15
|
right: number;
|
|
18
16
|
top: number;
|
|
19
17
|
bottom: number;
|
|
20
|
-
}
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Compute normalized UV coordinates for a frame region within the video texture.
|
|
21
|
+
*/
|
|
22
|
+
export declare function computeVAPUV(region: [number, number, number, number], videoW: number, videoH: number, out?: VAPUVRect): VAPUVRect;
|
|
@@ -10,6 +10,7 @@ export declare class AlphaVideoRenderer {
|
|
|
10
10
|
private scratchTransform;
|
|
11
11
|
private readonly contentSizeScratch;
|
|
12
12
|
private readonly layoutScratch;
|
|
13
|
+
private readonly clipScratch;
|
|
13
14
|
private readonly wcDbgFirstDraw;
|
|
14
15
|
private readonly wcDbgNullWarns;
|
|
15
16
|
private readonly htmlGate;
|
|
@@ -3,9 +3,14 @@ export declare class ImageRenderer {
|
|
|
3
3
|
private quadVB;
|
|
4
4
|
private quadIB;
|
|
5
5
|
private readonly scratchTransform;
|
|
6
|
+
private readonly layoutScratch;
|
|
7
|
+
private readonly clipScratch;
|
|
6
8
|
private projCacheW;
|
|
7
9
|
private projCacheH;
|
|
8
10
|
private projCache;
|
|
11
|
+
private readonly texturesScratch;
|
|
12
|
+
private readonly uniformsScratch;
|
|
13
|
+
private readonly drawCommand;
|
|
9
14
|
private static readonly QUAD_VERTS;
|
|
10
15
|
private static readonly QUAD_INDICES;
|
|
11
16
|
drawSlot(backend: GPUBackend, slot: GiftSlot): void;
|
|
@@ -12,6 +12,13 @@ export interface ClipMeshCache {
|
|
|
12
12
|
w: number;
|
|
13
13
|
h: number;
|
|
14
14
|
} | null;
|
|
15
|
+
/** Local-space bounds cached for conservative instanced stencil safety checks. */
|
|
16
|
+
bounds?: {
|
|
17
|
+
x0: number;
|
|
18
|
+
y0: number;
|
|
19
|
+
x1: number;
|
|
20
|
+
y1: number;
|
|
21
|
+
};
|
|
15
22
|
/** Lazily created static GPU buffers (local-space vertices, transformed via u_transform). */
|
|
16
23
|
vertexBuf?: GPUBufferHandle | null;
|
|
17
24
|
indexBuf?: GPUBufferHandle | null;
|
|
@@ -25,8 +32,16 @@ interface SVGAClipPrewarmOptions {
|
|
|
25
32
|
}
|
|
26
33
|
export type SVGAClipMeshMap = Map<string, ClipMeshCache>;
|
|
27
34
|
export declare class SVGABatchRenderer {
|
|
35
|
+
private readonly onClipMeshReady?;
|
|
28
36
|
private static readonly INSTANCED_QUAD_VERTS;
|
|
29
37
|
private static readonly INSTANCED_QUAD_INDICES;
|
|
38
|
+
/**
|
|
39
|
+
* @param onClipMeshReady Called once a background clip mesh build (queued by the hot-path
|
|
40
|
+
* lookup in `getClipMeshForSprite`, see `queueClipMeshBuild`) finishes, so the owner can
|
|
41
|
+
* `invalidate()` a redraw — otherwise a slot whose animation has stopped dirtying may never
|
|
42
|
+
* pick up the now-available precise clip.
|
|
43
|
+
*/
|
|
44
|
+
constructor(onClipMeshReady?: (() => void) | undefined);
|
|
30
45
|
private pool;
|
|
31
46
|
private vertexBufHandles;
|
|
32
47
|
private indexBufHandles;
|
|
@@ -42,60 +57,202 @@ export declare class SVGABatchRenderer {
|
|
|
42
57
|
private clipMeshCache;
|
|
43
58
|
/** Meshes with lazily created GPU buffers (released in destroy). */
|
|
44
59
|
private clipMeshesWithBuffers;
|
|
60
|
+
/** Clip paths queued by `queueClipMeshBuild`, awaiting the next background build flush. */
|
|
61
|
+
private pendingClipMeshPaths;
|
|
62
|
+
/** True while a background build (worker or frame-budgeted main thread) is in flight. */
|
|
63
|
+
private clipMeshBuildInFlight;
|
|
45
64
|
private clipFrameDataScratch;
|
|
65
|
+
/** One-off scratch used only to capture a row for `svgaStaticBatchCache` (P1-10); never read
|
|
66
|
+
* back — each captured entry clones out of it immediately via `.slice()`. */
|
|
67
|
+
private staticBatchCacheRowScratch;
|
|
46
68
|
private instancedFrameDataScratch;
|
|
69
|
+
private instancedFrameDataWords;
|
|
47
70
|
private clipSpriteVertsScratch;
|
|
48
71
|
private clipSpriteIndicesScratch;
|
|
49
|
-
private
|
|
72
|
+
private clipMaskBatchTransformsScratch;
|
|
50
73
|
private instancedQuadVB;
|
|
51
74
|
private instancedQuadIB;
|
|
52
75
|
private whiteTexture;
|
|
53
76
|
private shapeMeshCache;
|
|
77
|
+
/** Shape meshes with lazily created static GPU buffers (released in destroy). */
|
|
78
|
+
private shapeMeshesWithBuffers;
|
|
54
79
|
/** Column-major mat4 scratch for clip-mask u_transform (uploaded synchronously per draw). */
|
|
55
80
|
private clipTransformMat;
|
|
81
|
+
/** Column-major mat4 scratch for the shape draw's u_transform (consumed synchronously). */
|
|
82
|
+
private shapeTransformMat;
|
|
56
83
|
/** Scissor rect of the slot currently being drawn (canvas pixels), for clip intersection/restore. */
|
|
57
84
|
private slotScissor;
|
|
85
|
+
private slotClipX0;
|
|
86
|
+
private slotClipY0;
|
|
87
|
+
private slotClipX1;
|
|
88
|
+
private slotClipY1;
|
|
89
|
+
/**
|
|
90
|
+
* Whether `slotScissor` is currently the *active* GPU scissor rect (vs. the outer scissor
|
|
91
|
+
* having been intentionally skipped for a slot that cannot draw outside its own box — see
|
|
92
|
+
* `spriteTable.allFramesInsideViewBox`). Drives `restoreSlotScissor`'s fallback target.
|
|
93
|
+
*/
|
|
94
|
+
private slotScissorActive;
|
|
95
|
+
/**
|
|
96
|
+
* True while a clip stencil mask written for a shape is still live for its sprite sibling
|
|
97
|
+
* (texture + clip + shape single-write merge, P1-3). `drawClippedSprite` checks this to
|
|
98
|
+
* skip its own stencil write/clear.
|
|
99
|
+
*/
|
|
100
|
+
private sharedClipStencilActive;
|
|
101
|
+
private readonly layoutScratch;
|
|
58
102
|
/** Grow-only SpriteWork pool; cursor resets each flushGroup. */
|
|
59
103
|
private spriteWorkPool;
|
|
60
104
|
private spriteWorkCursor;
|
|
61
105
|
/** Reused scratch arrays (consumed synchronously). */
|
|
62
106
|
private batchSpritesScratch;
|
|
63
107
|
private drawGroupScratch;
|
|
108
|
+
private sharedSlotLayerWorkPool;
|
|
109
|
+
private sharedSlotLayerWorksScratch;
|
|
110
|
+
private clipLayerBatchPool;
|
|
111
|
+
private clipLayerBatchesScratch;
|
|
64
112
|
/** Per-entity result of the "any frame has shapes" scan (no-atlas render check). */
|
|
65
113
|
private entityHasShapesCache;
|
|
66
114
|
/** 0=no clip, 1=scissor-compatible clips only, 2=stencil required, 255=not analyzed. */
|
|
67
115
|
private entityFrameClipModeCache;
|
|
116
|
+
/**
|
|
117
|
+
* Per-entity `ClipMeshCache` lookup aligned with `spriteTable.clipPaths` (index = `clipPathIndex`
|
|
118
|
+
* value), so the hot per-sprite loop can resolve a clip mesh with a direct array read instead of
|
|
119
|
+
* `getSpriteClipPath` (string build) + a string-keyed `Map` lookup. `undefined` = not yet resolved;
|
|
120
|
+
* resolution always goes through `getClipMesh`'s string cache, so array entries never go stale.
|
|
121
|
+
*/
|
|
122
|
+
private entityClipMeshArrayCache;
|
|
68
123
|
private readonly affineScratch;
|
|
124
|
+
/**
|
|
125
|
+
* Reused DrawCommand/uniforms/textures per rendering branch (never allocated per draw).
|
|
126
|
+
* Backends consume `DrawCommand` synchronously inside `backend.draw`, so mutating these
|
|
127
|
+
* shared objects between calls is safe as long as no reference is retained past the call.
|
|
128
|
+
* Grouped by branch (plain instanced sprite / plain batch sprite / clipped instanced /
|
|
129
|
+
* clipped batch / clip-mask stencil / shape) per the uniform field sets each shader expects.
|
|
130
|
+
*/
|
|
131
|
+
private readonly plainInstancedTexturesScratch;
|
|
132
|
+
private readonly plainInstancedUniformsScratch;
|
|
133
|
+
private readonly plainInstancedDrawCommand;
|
|
134
|
+
private readonly plainBatchTexturesScratch;
|
|
135
|
+
private readonly plainBatchUniformsScratch;
|
|
136
|
+
private readonly plainBatchDrawCommand;
|
|
137
|
+
/** `drawClippedSprite`'s stencil-test pass on instanced backends (webgl2/webgpu). */
|
|
138
|
+
private readonly clipInstancedTexturesScratch;
|
|
139
|
+
private readonly clipInstancedUniformsScratch;
|
|
140
|
+
private readonly clipInstancedDrawCommand;
|
|
141
|
+
/** `drawClippedSprite`'s stencil-test pass on the WebGL1 fallback. */
|
|
142
|
+
private readonly clipBatchTexturesScratch;
|
|
143
|
+
private readonly clipBatchUniformsScratch;
|
|
144
|
+
private readonly clipBatchDrawCommand;
|
|
145
|
+
/**
|
|
146
|
+
* Clip-mask stencil write/clear, shared by `drawClippedSprite`'s pass-1 write,
|
|
147
|
+
* `drawShapeFrame`'s non-rect-clip write, and `clearClipStencil`'s clear (all mutate then
|
|
148
|
+
* synchronously `backend.draw`, never concurrently).
|
|
149
|
+
*/
|
|
150
|
+
private readonly clipMaskTexturesScratch;
|
|
151
|
+
private readonly clipMaskUniformsScratch;
|
|
152
|
+
private readonly clipMaskDrawCommand;
|
|
153
|
+
private readonly clipMaskInstancedUniformsScratch;
|
|
154
|
+
private readonly clipMaskInstancedDrawCommand;
|
|
155
|
+
/**
|
|
156
|
+
* `drawShapeFrame`'s fill/stroke draw (always the shared white texture). `u_transform`
|
|
157
|
+
* carries the per-frame sprite x slot transform so the static shape mesh stays on the GPU;
|
|
158
|
+
* `u_opacity` carries slot opacity (per-vertex alpha is baked into the mesh).
|
|
159
|
+
*/
|
|
160
|
+
private readonly shapeTexturesScratch;
|
|
161
|
+
private readonly shapeUniformsScratch;
|
|
162
|
+
private readonly shapeDrawCommand;
|
|
69
163
|
beginFrame(backend: GPUBackend): void;
|
|
70
164
|
flush(backend: GPUBackend, slots: Map<string, GiftSlot>): void;
|
|
71
165
|
drawSlot(backend: GPUBackend, slot: GiftSlot): void;
|
|
72
166
|
drawSlots(backend: GPUBackend, slots: Iterable<GiftSlot>): void;
|
|
73
167
|
requiresStencil(slots: Iterable<GiftSlot>): boolean;
|
|
168
|
+
/**
|
|
169
|
+
* Returns the target frame only when every clip path referenced by its visible sprites has a
|
|
170
|
+
* resolved cache entry. A miss queues background triangulation and keeps the previous complete
|
|
171
|
+
* frame on screen, preventing a partially built frame from being drawn without clipping.
|
|
172
|
+
*/
|
|
173
|
+
private resolveRenderableFrame;
|
|
174
|
+
private isFrameClipReady;
|
|
74
175
|
private getFrameClipMode;
|
|
75
176
|
prewarmClipMeshes(entity: Pick<VideoEntity, 'spriteTable'>, options?: SVGAClipPrewarmOptions): Promise<number>;
|
|
177
|
+
prewarmClipMeshesForFrame(entity: Pick<VideoEntity, 'spriteTable'>, frame: number, options?: SVGAClipPrewarmOptions): Promise<number>;
|
|
178
|
+
private collectFrameClipPaths;
|
|
179
|
+
/** Builds every not-yet-cached path in `paths`, worker-first with a frame-budgeted fallback. */
|
|
180
|
+
private buildMissingClipMeshes;
|
|
181
|
+
/**
|
|
182
|
+
* Called from the render-loop hot path (`getClipMeshForSprite`) when a clip path has no cached
|
|
183
|
+
* mesh yet — instead of triangulating synchronously inline, queue it and build it in the
|
|
184
|
+
* background (batched with any other paths queued in the same tick) so the current frame keeps
|
|
185
|
+
* moving. Safe to call repeatedly: paths already cached or already queued are no-ops.
|
|
186
|
+
*/
|
|
187
|
+
private queueClipMeshBuild;
|
|
188
|
+
private scheduleClipMeshBuildFlush;
|
|
189
|
+
private flushPendingClipMeshBuilds;
|
|
76
190
|
hydrateClipMeshes(meshes: SVGAClipMeshMap | null | undefined): void;
|
|
77
191
|
snapshotClipMeshes(entity: Pick<VideoEntity, 'spriteTable'>): SVGAClipMeshMap;
|
|
78
192
|
private flushGroup;
|
|
193
|
+
/**
|
|
194
|
+
* Transposes disjoint slots sharing one entity into sprite layers. Reordering across slots is
|
|
195
|
+
* safe because their outer clip bounds do not overlap; order within every slot remains sprite
|
|
196
|
+
* index order. Non-rect clips sharing one mesh become write -> instanced test -> clear.
|
|
197
|
+
*/
|
|
198
|
+
private tryFlushDisjointSharedEntityLayers;
|
|
199
|
+
private resetClipLayerBatches;
|
|
200
|
+
private acquireClipLayerBatch;
|
|
201
|
+
private resolveClipTransform;
|
|
202
|
+
private intersectWorkClipRect;
|
|
203
|
+
private drawBatchedClipLayer;
|
|
79
204
|
private acquireSpriteWork;
|
|
205
|
+
/**
|
|
206
|
+
* Like `acquireSpriteWork`, but for a P1-10 static batch cache replay entry: only `handle` and
|
|
207
|
+
* `cachedRow` matter, since `packFrameData` short-circuits on `cachedRow` and every other draw
|
|
208
|
+
* call only reads `work.handle`.
|
|
209
|
+
*/
|
|
210
|
+
private acquireCachedSpriteWork;
|
|
211
|
+
private updateSlotClipBounds;
|
|
212
|
+
private copyCurrentSlotClipToWork;
|
|
80
213
|
/** Drop object references so removed slots/entities are not retained by the pool. */
|
|
81
214
|
private releaseSpriteWorks;
|
|
215
|
+
/** Snapshot check for a P1-10 static batch cache: any mismatch means rebuild, never a stale hit. */
|
|
216
|
+
private staticBatchCacheMatches;
|
|
217
|
+
/** Clones the packed row for `work` into a fresh array so it survives past this frame's scratch reuse. */
|
|
218
|
+
private captureStaticBatchCacheEntry;
|
|
219
|
+
/** Replays a P1-10 static batch cache hit: same override/batch branching as the live loop, just
|
|
220
|
+
* sourced from pre-packed rows instead of recomputing layout/transform/texture lookups. */
|
|
221
|
+
private drawFromStaticBatchCache;
|
|
82
222
|
private getProjection;
|
|
83
223
|
private drawBatch;
|
|
84
224
|
private drawBatchInstancedWebGL;
|
|
85
225
|
private drawClippedSprite;
|
|
226
|
+
/**
|
|
227
|
+
* WebGL1 clipped-sprite draw: pack + upload the quad, then draw with stencil 'test'.
|
|
228
|
+
* Caller is responsible for the surrounding stencil write/clear. Uses separate buffers to
|
|
229
|
+
* avoid WebGPU writeBuffer aliasing with the batch draw.
|
|
230
|
+
*/
|
|
231
|
+
private drawBatchSpriteWithStencilTest;
|
|
86
232
|
/** Rect clip in canvas space intersected with the slot scissor. Returns false when fully clipped. */
|
|
87
233
|
private applyClipRectScissor;
|
|
88
234
|
private restoreSlotScissor;
|
|
89
235
|
private getClipRect;
|
|
236
|
+
private getClipMeshBounds;
|
|
90
237
|
private ensureClipMeshBuffers;
|
|
91
238
|
private packClipTransform;
|
|
92
239
|
private drawSingleSprite;
|
|
93
240
|
private clearClipStencil;
|
|
94
241
|
private rotateTransform;
|
|
95
242
|
private packFrameData;
|
|
243
|
+
private packInstancedFrameData;
|
|
244
|
+
private packClipCoordinatePair;
|
|
245
|
+
private packFrameDataAt;
|
|
96
246
|
/** Resolve atlas/override texture into a pooled SpriteWork entry. Returns false when missing. */
|
|
97
247
|
private resolveSpriteTextureInto;
|
|
98
248
|
private drawShapeFrame;
|
|
249
|
+
/**
|
|
250
|
+
* Clear the shared mask after a shape-first clip merge once the sprite sibling has drawn.
|
|
251
|
+
* Called by `drawClippedSprite`'s shared-mask branch.
|
|
252
|
+
*/
|
|
253
|
+
private clearSharedClipStencil;
|
|
254
|
+
private ensureShapeMeshBuffers;
|
|
255
|
+
private packShapeTransform;
|
|
99
256
|
private hasAtlasTexture;
|
|
100
257
|
private hasRenderableSVGA;
|
|
101
258
|
private getWhiteTexture;
|
|
@@ -107,6 +264,20 @@ export declare class SVGABatchRenderer {
|
|
|
107
264
|
private clamp01;
|
|
108
265
|
private cleanupPoints;
|
|
109
266
|
private getClipMesh;
|
|
267
|
+
/**
|
|
268
|
+
* Hot-path clip mesh lookup: reads `clipPathIndex` directly (no string build/compare) and
|
|
269
|
+
* memoizes the resolved mesh per (entity, clipPathIndex) so repeat frames skip the string-keyed
|
|
270
|
+
* `clipMeshCache` lookup too.
|
|
271
|
+
*
|
|
272
|
+
* Returns `undefined` (rather than triangulating inline) when the path hasn't been built yet —
|
|
273
|
+
* prewarm normally finishes before an entity is ever drawn, but with `svgaPrewarmClipMeshes:
|
|
274
|
+
* false`, an aborted/partially failed prewarm, or a slot rendered before prewarm completes, this
|
|
275
|
+
* lookup would otherwise pay a synchronous SVG-parse + triangulate cost inside the render loop.
|
|
276
|
+
* The path is queued for a background build instead (see `queueClipMeshBuild`); callers already
|
|
277
|
+
* treat a falsy return as "no clip this frame" (draw unclipped / assume stencil conservatively),
|
|
278
|
+
* and a redraw is requested once the build lands so later frames clip precisely.
|
|
279
|
+
*/
|
|
280
|
+
private getClipMeshForSprite;
|
|
110
281
|
private ensureVertexBuffer;
|
|
111
282
|
private ensureIndexBuffer;
|
|
112
283
|
private ensureClipSpriteVertexBuffer;
|
|
@@ -15,8 +15,32 @@ export declare class VAPRenderer {
|
|
|
15
15
|
private readonly scratchAtlasRemap;
|
|
16
16
|
private instancePackScratch;
|
|
17
17
|
private scratchTransform;
|
|
18
|
+
private readonly contentSizeScratch;
|
|
19
|
+
private readonly rgbUVScratch;
|
|
20
|
+
private readonly alphaUVScratch;
|
|
21
|
+
private readonly maskUVScratch;
|
|
18
22
|
private readonly processedHtmlGatesScratch;
|
|
19
23
|
private readonly vapVertexScratch;
|
|
24
|
+
private readonly layoutScratch;
|
|
25
|
+
private readonly clipScratch;
|
|
26
|
+
/** `drawInstancedVapBatches` grow-only scratch: avoids a fresh array/Map per frame. */
|
|
27
|
+
private readonly instancedListScratch;
|
|
28
|
+
private readonly instancedByTexScratch;
|
|
29
|
+
private readonly instancedTexturesScratch;
|
|
30
|
+
private readonly instancedUniformsScratch;
|
|
31
|
+
private readonly instancedDrawCommand;
|
|
32
|
+
/** `drawGeometry` (plain VAP quad) reused command/uniforms/textures. */
|
|
33
|
+
private readonly geometryTexturesScratch;
|
|
34
|
+
private readonly geometryUniformsScratch;
|
|
35
|
+
private readonly geometryDrawCommand;
|
|
36
|
+
/** `drawMixedGeometry` (composited rgba overlay) reused command/uniforms/textures. */
|
|
37
|
+
private readonly mixedGeometryTexturesScratch;
|
|
38
|
+
private readonly mixedGeometryUniformsScratch;
|
|
39
|
+
private readonly mixedGeometryDrawCommand;
|
|
40
|
+
/** `drawMixedDirectGeometry` per-frame-object overlay reused command/uniforms/textures. */
|
|
41
|
+
private readonly overlayTexturesScratch;
|
|
42
|
+
private readonly overlayUniformsScratch;
|
|
43
|
+
private readonly overlayDrawCommand;
|
|
20
44
|
constructor(onHtmlVideoFrame?: (video: HTMLVideoElement) => void);
|
|
21
45
|
private projCacheW;
|
|
22
46
|
private projCacheH;
|
package/dist/shaders/index.d.ts
CHANGED
|
@@ -35,6 +35,10 @@ export declare const glsl: {
|
|
|
35
35
|
readonly vert: string;
|
|
36
36
|
readonly frag: string;
|
|
37
37
|
};
|
|
38
|
+
readonly clipMaskInstanced: {
|
|
39
|
+
readonly vert: string;
|
|
40
|
+
readonly frag: string;
|
|
41
|
+
};
|
|
38
42
|
};
|
|
39
43
|
export declare const wgsl: {
|
|
40
44
|
readonly svgaBatchPremul: string;
|
|
@@ -46,4 +50,5 @@ export declare const wgsl: {
|
|
|
46
50
|
readonly alphaVideoInstanced: string;
|
|
47
51
|
readonly rgbaTextured: string;
|
|
48
52
|
readonly clipMask: string;
|
|
53
|
+
readonly clipMaskInstanced: string;
|
|
49
54
|
};
|