@taole/giftstage 0.3.1 → 0.3.3
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/README.md +96 -85
- package/dist/gift-stage.cjs +612 -612
- package/dist/gift-stage.es.js +716 -694
- package/dist/plugin/playback-scope.d.ts +1 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -87,11 +87,11 @@ npm run perf:record
|
|
|
87
87
|
npm run test:perf
|
|
88
88
|
```
|
|
89
89
|
|
|
90
|
-
基线覆盖冷/热启动、100 个静态图片、SVGA Direct 的 1/2/10/50 个同资源实例、
|
|
91
|
-
复杂 Clip/Shape Hybrid 的 Auto/CPU 对照、20 个共享 VAP 和 20 个共享 AlphaVideo。
|
|
92
|
-
除首帧、P50/P95/P99、长任务、堆变化、draw/Stencil 外,还记录 SVGA CPU Sprite
|
|
93
|
-
展开数、GPU 帧表上传、每帧动态上传字节、路径晋升与回退。可用
|
|
94
|
-
`npm run test:perf -- --project=chromium-webgl2 --scenarios=<逗号分隔场景>` 做聚焦复测。
|
|
90
|
+
基线覆盖冷/热启动、100 个静态图片、SVGA Direct 的 1/2/10/50 个同资源实例、
|
|
91
|
+
复杂 Clip/Shape Hybrid 的 Auto/CPU 对照、20 个共享 VAP 和 20 个共享 AlphaVideo。
|
|
92
|
+
除首帧、P50/P95/P99、长任务、堆变化、draw/Stencil 外,还记录 SVGA CPU Sprite
|
|
93
|
+
展开数、GPU 帧表上传、每帧动态上传字节、路径晋升与回退。可用
|
|
94
|
+
`npm run test:perf -- --project=chromium-webgl2 --scenarios=<逗号分隔场景>` 做聚焦复测。
|
|
95
95
|
基线保存在 `tests/performance/baselines/`;Windows 会自动探测系统 Chrome,也可通过
|
|
96
96
|
`PLAYWRIGHT_CHROME_EXECUTABLE_PATH` 指定浏览器。
|
|
97
97
|
|
|
@@ -141,21 +141,21 @@ mounted.destroy();
|
|
|
141
141
|
|
|
142
142
|
- `preload()`:复用 GiftStage 的 SVGA/Image 缓存并返回引用计数资源租约。
|
|
143
143
|
- `createPlaybackScope()`:使用 GiftStage 唯一 RAF、逻辑时钟和作用域清理;SVGA、WebCodecs、HTMLVideo 回退与定时图片均按 Scope 绝对时间定位,不叠加 RenderManager 的全局 `dt`。SVGA 的可见帧、`onFrame` 与嵌入音频由同一个绝对时间入口同步,跨帧、seek、循环和暂停恢复会重建正确音频偏移,且 `start()` 前不会触发首帧音频/回调。HTMLVideo 在 Scope 内保持暂停并使用独立实例,显式暂停和页面隐藏期间逻辑时间冻结。
|
|
144
|
-
- `createMotionTrack()`:接收 8-float TypedArray/SoA 父级轨道。WebGPU 可把它与核心 SVGA 帧表在同一顶点着色器中合成;WebGL2 的 SVGA 内部帧仍可走 GPU Direct/Hybrid,但父级 MotionTrack 继续使用确定性 CPU reference sampler。图片与 WebGL1 同样使用 CPU reference。
|
|
145
|
-
- `createParticleBatch()`:保留 16-float `ballistic-v1` ABI,WebGPU/WebGL2 使用持久实例缓冲和 GPU 弹道求值;缺省仍在媒体之后合成。
|
|
146
|
-
- `host.createParticleAtlas()` + `scope.createParticleBatchGroup()`:可选 `sprite-v2` 能力。插件上传一次不可变预乘 RGBA8 atlas,再以原子 group 发布多个 24-float sprite batch。group 任一 draw 失败会 abort 整帧并以同一权威时间重放,不会显示 smoke-only 等局部结果。
|
|
147
|
-
- 粒子 `compositeLayer` 支持 `behind-media` / `above-media`;正式帧顺序为 `begin → behind particles → media → above particles → end`,`zIndex` 只在同一 phase 内排序。WebGL1 明确不可用,不提供 Canvas2D 粒子后端。
|
|
148
|
-
- `stage.capabilities`:插件可在播放前判断实际后端、GPU 轨道媒体范围和粒子能力。
|
|
149
|
-
|
|
150
|
-
### ParticleBatch v2 迁移
|
|
151
|
-
|
|
152
|
-
`stage.capabilities.particles.formats` 包含 `sprite-v2`,且同时具备 `spriteAtlas`、`compositeLayers`、`batchEnvelope`、`atomicBatchGroup` 和 `maxInstancesPerBatch` 时,插件才能启用纹理粒子;不得只按 `apiVersion` 判断。旧核心缺少这些可选字段时继续使用原有 v1 或明确跳过效果。
|
|
153
|
-
|
|
154
|
-
`sprite-v2` 每实例为 24 floats:`0–15` 完全延续 birth/lifetime/弹道/scale/rotation/RGBA,`16–17` 是 CSS 逻辑宽高,`18–19` 是归一化 anchor,`20–23` 是 atlas UV。header 为 8 floats:秒制时间、已求值 opacity、已求值 size、fade mode、`sx/sy` 与两个零 padding。WebGL2 的实例 stride 为 96 bytes、header 为 32 bytes;WebGPU 从 `8 + instanceIndex × 24` 读取。非均匀 backing scale 只在最终顶点应用,不能再用 `sqrt(sx × sy)` 近似 v2 尺寸。
|
|
155
|
-
|
|
156
|
-
atlas descriptor 必须提供 `width × height × 4` 的不可变 `Uint8Array`,声明 `colorSpace:'srgb'` 与 `alphaMode:'premultiplied'`。透明像素 RGB 应为零;shader 不会再次乘采样 alpha。`ParticleAtlasHandle.destroy()` 只释放调用方 lease,存活 group 会保留内部引用;context/device loss 后旧 handle 的 `lost` 为 true,不能在新设备上复活。
|
|
157
|
-
|
|
158
|
-
envelope 使用绝对毫秒半开区间 `[startMs,endMs)`,支持 `linear` / `hold`,边界右连续,因此可以表达中心闪光的瞬时跳变。`setTime()` 仅更新每 batch header,实例 buffer 创建后保持不变;pause 不产生写入,seek 直接求值绝对时间。
|
|
144
|
+
- `createMotionTrack()`:接收 8-float TypedArray/SoA 父级轨道。WebGPU 可把它与核心 SVGA 帧表在同一顶点着色器中合成;WebGL2 的 SVGA 内部帧仍可走 GPU Direct/Hybrid,但父级 MotionTrack 继续使用确定性 CPU reference sampler。图片与 WebGL1 同样使用 CPU reference。
|
|
145
|
+
- `createParticleBatch()`:保留 16-float `ballistic-v1` ABI,WebGPU/WebGL2 使用持久实例缓冲和 GPU 弹道求值;缺省仍在媒体之后合成。
|
|
146
|
+
- `host.createParticleAtlas()` + `scope.createParticleBatchGroup()`:可选 `sprite-v2` 能力。插件上传一次不可变预乘 RGBA8 atlas,再以原子 group 发布多个 24-float sprite batch。group 任一 draw 失败会 abort 整帧并以同一权威时间重放,不会显示 smoke-only 等局部结果。
|
|
147
|
+
- 粒子 `compositeLayer` 支持 `behind-media` / `above-media`;正式帧顺序为 `begin → behind particles → media → above particles → end`,`zIndex` 只在同一 phase 内排序。WebGL1 明确不可用,不提供 Canvas2D 粒子后端。
|
|
148
|
+
- `stage.capabilities`:插件可在播放前判断实际后端、GPU 轨道媒体范围和粒子能力。
|
|
149
|
+
|
|
150
|
+
### ParticleBatch v2 迁移
|
|
151
|
+
|
|
152
|
+
`stage.capabilities.particles.formats` 包含 `sprite-v2`,且同时具备 `spriteAtlas`、`compositeLayers`、`batchEnvelope`、`atomicBatchGroup` 和 `maxInstancesPerBatch` 时,插件才能启用纹理粒子;不得只按 `apiVersion` 判断。旧核心缺少这些可选字段时继续使用原有 v1 或明确跳过效果。
|
|
153
|
+
|
|
154
|
+
`sprite-v2` 每实例为 24 floats:`0–15` 完全延续 birth/lifetime/弹道/scale/rotation/RGBA,`16–17` 是 CSS 逻辑宽高,`18–19` 是归一化 anchor,`20–23` 是 atlas UV。header 为 8 floats:秒制时间、已求值 opacity、已求值 size、fade mode、`sx/sy` 与两个零 padding。WebGL2 的实例 stride 为 96 bytes、header 为 32 bytes;WebGPU 从 `8 + instanceIndex × 24` 读取。非均匀 backing scale 只在最终顶点应用,不能再用 `sqrt(sx × sy)` 近似 v2 尺寸。
|
|
155
|
+
|
|
156
|
+
atlas descriptor 必须提供 `width × height × 4` 的不可变 `Uint8Array`,声明 `colorSpace:'srgb'` 与 `alphaMode:'premultiplied'`。透明像素 RGB 应为零;shader 不会再次乘采样 alpha。`ParticleAtlasHandle.destroy()` 只释放调用方 lease,存活 group 会保留内部引用;context/device loss 后旧 handle 的 `lost` 为 true,不能在新设备上复活。
|
|
157
|
+
|
|
158
|
+
envelope 使用绝对毫秒半开区间 `[startMs,endMs)`,支持 `linear` / `hold`,边界右连续,因此可以表达中心闪光的瞬时跳变。`setTime()` 仅更新每 batch header,实例 buffer 创建后保持不变;pause 不产生写入,seek 直接求值绝对时间。
|
|
159
159
|
|
|
160
160
|
## 核心 API
|
|
161
161
|
|
|
@@ -221,46 +221,46 @@ envelope 使用绝对毫秒半开区间 `[startMs,endMs)`,支持 `linear` / `h
|
|
|
221
221
|
- `svgaWorkerTaskConcurrency?: number`
|
|
222
222
|
parser、图片解码、atlas 和 clip 等 CPU 密集 Worker 的全局并发上限,默认 `1`。Atlas 首帧页面可提前返回,但后台 PNG 编码完成前仍持有该名额,避免与其他重载 Worker 叠加。
|
|
223
223
|
|
|
224
|
-
- `svgaWorkerImageDecodeConcurrency?: number`
|
|
225
|
-
图片解码 Worker 内 `createImageBitmap` 并发上限,默认 `2`。运行时可按批次耗时收缩并发,负载恢复后回升,但不会超过该上限。
|
|
226
|
-
|
|
227
|
-
- `svgaFrameEvaluation?: 'auto' | 'cpu'`
|
|
228
|
-
SVGA 帧动画求值策略,默认 `auto`。`auto` 按后端能力、表大小和资源计划选择 `gpu-direct`、`gpu-hybrid` 或 `cpu-reference`;`cpu` 强制使用 CPU reference。普通单礼物和同资源多实例都经过同一策略。
|
|
229
|
-
|
|
230
|
-
- `svgaGpuFrameTableBudgetBytes?: number`
|
|
231
|
-
所有活动 SVGA GPU 帧表、静态 Sprite metadata 和 Hybrid Command Table 共享的全局预算,默认 `32 MiB`。预算不足时仅当前资源回退到 `cpu-reference`,不会影响已存在的其他礼物。
|
|
224
|
+
- `svgaWorkerImageDecodeConcurrency?: number`
|
|
225
|
+
图片解码 Worker 内 `createImageBitmap` 并发上限,默认 `2`。运行时可按批次耗时收缩并发,负载恢复后回升,但不会超过该上限。
|
|
226
|
+
|
|
227
|
+
- `svgaFrameEvaluation?: 'auto' | 'cpu'`
|
|
228
|
+
SVGA 帧动画求值策略,默认 `auto`。`auto` 按后端能力、表大小和资源计划选择 `gpu-direct`、`gpu-hybrid` 或 `cpu-reference`;`cpu` 强制使用 CPU reference。普通单礼物和同资源多实例都经过同一策略。
|
|
229
|
+
|
|
230
|
+
- `svgaGpuFrameTableBudgetBytes?: number`
|
|
231
|
+
所有活动 SVGA GPU 帧表、静态 Sprite metadata 和 Hybrid Command Table 共享的全局预算,默认 `32 MiB`。预算不足时仅当前资源回退到 `cpu-reference`,不会影响已存在的其他礼物。
|
|
232
232
|
|
|
233
233
|
- `svgaParseProfile?: boolean`
|
|
234
234
|
是否输出 `[GiftStage:SVGA:Profile]` 结构化解析日志,默认 `false`。日志包含 `DecompressionStream` 格式尝试、输入/输出 chunk、解压耗时以及 protobuf/payload 构建耗时;WASM payload 路径还会拆分 `prostDecodeMs`、`metadataAndImagesMs`、`frameTableMs`、`finalizeMs` 和 WASM 边界复制耗时。缓存命中不输出。
|
|
235
235
|
|
|
236
236
|
SVGA 礼物在加载阶段被 `destroy()` / `removeGift()` 时,会取消排队任务并终止正在执行的 parser、图片解码、atlas 或 clip Worker。相同 URL 的共享加载按消费者计数,单个礼物取消不会中断其他仍在等待的礼物。
|
|
237
237
|
|
|
238
|
-
- `onError?: (error: Error) => void`
|
|
239
|
-
统一错误回调。
|
|
240
|
-
|
|
241
|
-
- `onSVGARenderPathChange?: (info) => void`
|
|
242
|
-
当 SVGA 礼物完成资格分析、帧表上传、原子晋升或发生回退时通知路径变化。除资源与路径字段外,`info` 还包含 `pathState`、`frameTableBytes`、`commandTableBytes`、`drawBatchMode` 和 `drawCompatibleInstanceCount`。
|
|
243
|
-
|
|
244
|
-
- `onRuntimeDiagnostic?: (event) => void`
|
|
245
|
-
接收 frame abort、replay failure、无时钟 retry、frame controller failure、运行期 fallback、Clip 协议/网格异常、Stencil 事务失败、Atlas 命令无效、Particle group 原子失败、Backend 操作拒绝/隔离、WebGPU uncaptured error、backend loss 和 observer error 等结构化事件。事件只在本地回调,不会由 GiftStage 上传;回调异常会被隔离,不能中断渲染降级事务。
|
|
238
|
+
- `onError?: (error: Error) => void`
|
|
239
|
+
统一错误回调。
|
|
240
|
+
|
|
241
|
+
- `onSVGARenderPathChange?: (info) => void`
|
|
242
|
+
当 SVGA 礼物完成资格分析、帧表上传、原子晋升或发生回退时通知路径变化。除资源与路径字段外,`info` 还包含 `pathState`、`frameTableBytes`、`commandTableBytes`、`drawBatchMode` 和 `drawCompatibleInstanceCount`。
|
|
243
|
+
|
|
244
|
+
- `onRuntimeDiagnostic?: (event) => void`
|
|
245
|
+
接收 frame abort、replay failure、无时钟 retry、frame controller failure、运行期 fallback、Clip 协议/网格异常、Stencil 事务失败、Atlas 命令无效、Particle group 原子失败、Backend 操作拒绝/隔离、WebGPU uncaptured error、backend loss 和 observer error 等结构化事件。事件只在本地回调,不会由 GiftStage 上传;回调异常会被隔离,不能中断渲染降级事务。
|
|
246
246
|
|
|
247
247
|
### `await stage.ready`
|
|
248
248
|
|
|
249
249
|
等待底层后端和运行环境初始化完成。建议在第一次 `addGift()` 前等待。
|
|
250
250
|
|
|
251
|
-
### `stage.addGift(options)`
|
|
251
|
+
### `stage.addGift(options)`
|
|
252
252
|
|
|
253
253
|
插入一个礼物,返回:
|
|
254
254
|
|
|
255
255
|
```ts
|
|
256
|
-
Promise<GiftHandle>;
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
### `stage.getDiagnostics()`
|
|
260
|
-
|
|
261
|
-
返回当前 Stage 生命周期内的累计运行诊断快照,包括 frame abort/replay/retry、FastPath fallback、native submitted/rejected draw、WebGPU uncaptured error、backend loss、observer error 以及最后一个结构化事件。该快照不会被性能测试采样窗口重置,返回对象可安全交给业务遥测系统;GiftStage 自身不上传数据。
|
|
256
|
+
Promise<GiftHandle>;
|
|
257
|
+
```
|
|
262
258
|
|
|
263
|
-
### `
|
|
259
|
+
### `stage.getDiagnostics()`
|
|
260
|
+
|
|
261
|
+
返回当前 Stage 生命周期内的累计运行诊断快照,包括 frame abort/replay/retry、FastPath fallback、native submitted/rejected draw、WebGPU uncaptured error、backend loss、observer error 以及最后一个结构化事件。该快照不会被性能测试采样窗口重置,返回对象可安全交给业务遥测系统;GiftStage 自身不上传数据。
|
|
262
|
+
|
|
263
|
+
### `GiftHandle` API
|
|
264
264
|
|
|
265
265
|
`addGift()` 返回的句柄可用于控制单个礼物:
|
|
266
266
|
|
|
@@ -269,11 +269,11 @@ Promise<GiftHandle>;
|
|
|
269
269
|
- `gift.pause()`
|
|
270
270
|
- `gift.resume()`
|
|
271
271
|
- 暂停期间礼物播放时钟、图片 `duration` 和后置动画都会冻结
|
|
272
|
-
- `gift.destroy()`
|
|
273
|
-
- 立即移除当前礼物
|
|
274
|
-
- `gift.getRenderInfo()`
|
|
275
|
-
- 返回 SVGA 的实时路径诊断;非 SVGA 或尚未形成资源计划时返回 `null`。`pathState` 为 `preparing | settled | fallback`,`drawBatchMode` 为 `multi-slot | per-slot | hybrid-scheduled`,可直接区分资源共享与实际 Draw 合批状态。
|
|
276
|
-
- `gift.animate(stepOrSteps?)`
|
|
272
|
+
- `gift.destroy()`
|
|
273
|
+
- 立即移除当前礼物
|
|
274
|
+
- `gift.getRenderInfo()`
|
|
275
|
+
- 返回 SVGA 的实时路径诊断;非 SVGA 或尚未形成资源计划时返回 `null`。`pathState` 为 `preparing | settled | fallback`,`drawBatchMode` 为 `multi-slot | per-slot | hybrid-scheduled`,可直接区分资源共享与实际 Draw 合批状态。
|
|
276
|
+
- `gift.animate(stepOrSteps?)`
|
|
277
277
|
- 创建链式动画并返回 `GiftAnimationChain`
|
|
278
278
|
|
|
279
279
|
`GiftAnimationChain` 支持:
|
|
@@ -307,25 +307,25 @@ Promise<GiftHandle>;
|
|
|
307
307
|
|
|
308
308
|
恢复舞台。
|
|
309
309
|
|
|
310
|
-
### `stage.destroy()`
|
|
311
|
-
|
|
312
|
-
销毁舞台并释放资源。
|
|
313
|
-
|
|
314
|
-
### SVGA 帧动画路径
|
|
315
|
-
|
|
316
|
-
SVGA 资源的 9-float 帧行会在准备阶段打包为 3 个 `vec4`。WebGPU 使用持久 storage buffer,WebGL2 使用 `RGBA32F + NEAREST + texelFetch` 数据纹理。CPU 始终权威维护帧号、循环、暂停、Seek、音频与回调;GPU 根据该帧号读取子 Sprite 矩阵、透明度和可见性。
|
|
317
|
-
|
|
318
|
-
Direct 对连续且兼容的同资源 slot 使用 4 个 `vec4`/slot 的父级状态并进行 slot-major 实例化合批;多 Atlas、不同 MotionTrack binding 或无法证明重排安全的区间继续使用 per-slot Direct,不回退 CPU。Hybrid 在资源准备期生成 `frameOffsets + operations + spriteIndices + meshReferences` 不可变命令表,并把连续同 Atlas 的纹理操作进一步预编译为 execution run;运行时只读取当前帧 run slice。Texture、Shape 和 Clip Mask Shader 读取同一核心帧表,每帧动态上传仍只有 slot 父级状态。结构相同的不同权威帧可通过 `frameScheduleIds` 共用一次合批;矩形纹理 Clip 使用静态本地裁剪 metadata,不增加 Stencil pass。MoveTo-only、线段、重复点或零面积 Clip 按 SVG/Canvas 的空裁剪语义直接隐藏对应 Sprite,不创建 Mesh/Stencil,也不会触发资源回退。
|
|
319
|
-
|
|
320
|
-
- `gpu-direct`:普通 atlas sprite 的帧变换、透明度和布局由 GPU 求值。
|
|
321
|
-
- `gpu-hybrid`:Shape/Clip 的精确 paint order 与 Draw/Stencil 提交由 CPU 按不可变命令表调度,Texture、Shape、Clip Mask 的动画属性都由 GPU 帧表求值。
|
|
322
|
-
- `cpu-reference`:WebGL1、动态 `svgaSlots`、表校验/上传失败、预算不足或策略为 `cpu` 时使用确定性的 CPU 路径。
|
|
323
|
-
|
|
324
|
-
插件可通过 `stage.capabilities.svgaFrameTimeline` 判断 `transport`(`storage-buffer`、`float-texture` 或 `unavailable`)、正式 `direct`/`hybrid` 能力、`supportedPaths` 和 `maxTableBytes`,不需要启用 experimental policy。同一解析资源的多个实例共享帧表、静态 metadata 和 Hybrid Command Table;`compatibleInstanceCount` 表示资源共享数,实际本帧合批数量由 `drawCompatibleInstanceCount` 报告。
|
|
325
|
-
|
|
326
|
-
`addGift()` 不等待 GPU 帧表:非预加载礼物先显示 CPU reference 首帧,再在完整帧边界原子晋升。`preload('svga')` 会等待同一资源级帧表与调度准备完成。FastPath 提交若被后端拒绝,会丢弃未提交帧、同步降级该资源,并在同一 RAF 以原顺序完整重放一次;重放再次失败时 WebGL2 会清成透明帧,并在下一 RAF 不推进 CPU 权威时间轴地重试。不支持该帧事务的自定义 Backend 会直接使用 CPU Reference。WebGL1、动态 `svgaSlots`、能力/尺寸/预算校验失败和上传失败均按资源缓存回退,不逐帧重试;Stage 与单礼物都可用 `svgaFrameEvaluation: 'cpu'` 强制关闭。
|
|
327
|
-
|
|
328
|
-
性能诊断中的 `submittedDrawCalls` 仅表示命令已经到达 WebGL `drawElements*` 或 WebGPU `drawIndexed` 调用/编码;它不表示 GPU 已经执行完成。`rejectedDrawCalls` 表示在原生提交前被后端校验或容量检查拒绝。GPU error scope、pipeline validation 与 framebuffer 像素门禁用于补充验证执行结果。
|
|
310
|
+
### `stage.destroy()`
|
|
311
|
+
|
|
312
|
+
销毁舞台并释放资源。
|
|
313
|
+
|
|
314
|
+
### SVGA 帧动画路径
|
|
315
|
+
|
|
316
|
+
SVGA 资源的 9-float 帧行会在准备阶段打包为 3 个 `vec4`。WebGPU 使用持久 storage buffer,WebGL2 使用 `RGBA32F + NEAREST + texelFetch` 数据纹理。CPU 始终权威维护帧号、循环、暂停、Seek、音频与回调;GPU 根据该帧号读取子 Sprite 矩阵、透明度和可见性。
|
|
317
|
+
|
|
318
|
+
Direct 对连续且兼容的同资源 slot 使用 4 个 `vec4`/slot 的父级状态并进行 slot-major 实例化合批;多 Atlas、不同 MotionTrack binding 或无法证明重排安全的区间继续使用 per-slot Direct,不回退 CPU。Hybrid 在资源准备期生成 `frameOffsets + operations + spriteIndices + meshReferences` 不可变命令表,并把连续同 Atlas 的纹理操作进一步预编译为 execution run;运行时只读取当前帧 run slice。Texture、Shape 和 Clip Mask Shader 读取同一核心帧表,每帧动态上传仍只有 slot 父级状态。结构相同的不同权威帧可通过 `frameScheduleIds` 共用一次合批;矩形纹理 Clip 使用静态本地裁剪 metadata,不增加 Stencil pass。MoveTo-only、线段、重复点或零面积 Clip 按 SVG/Canvas 的空裁剪语义直接隐藏对应 Sprite,不创建 Mesh/Stencil,也不会触发资源回退。
|
|
319
|
+
|
|
320
|
+
- `gpu-direct`:普通 atlas sprite 的帧变换、透明度和布局由 GPU 求值。
|
|
321
|
+
- `gpu-hybrid`:Shape/Clip 的精确 paint order 与 Draw/Stencil 提交由 CPU 按不可变命令表调度,Texture、Shape、Clip Mask 的动画属性都由 GPU 帧表求值。
|
|
322
|
+
- `cpu-reference`:WebGL1、动态 `svgaSlots`、表校验/上传失败、预算不足或策略为 `cpu` 时使用确定性的 CPU 路径。
|
|
323
|
+
|
|
324
|
+
插件可通过 `stage.capabilities.svgaFrameTimeline` 判断 `transport`(`storage-buffer`、`float-texture` 或 `unavailable`)、正式 `direct`/`hybrid` 能力、`supportedPaths` 和 `maxTableBytes`,不需要启用 experimental policy。同一解析资源的多个实例共享帧表、静态 metadata 和 Hybrid Command Table;`compatibleInstanceCount` 表示资源共享数,实际本帧合批数量由 `drawCompatibleInstanceCount` 报告。
|
|
325
|
+
|
|
326
|
+
`addGift()` 不等待 GPU 帧表:非预加载礼物先显示 CPU reference 首帧,再在完整帧边界原子晋升。`preload('svga')` 会等待同一资源级帧表与调度准备完成。FastPath 提交若被后端拒绝,会丢弃未提交帧、同步降级该资源,并在同一 RAF 以原顺序完整重放一次;重放再次失败时 WebGL2 会清成透明帧,并在下一 RAF 不推进 CPU 权威时间轴地重试。不支持该帧事务的自定义 Backend 会直接使用 CPU Reference。WebGL1、动态 `svgaSlots`、能力/尺寸/预算校验失败和上传失败均按资源缓存回退,不逐帧重试;Stage 与单礼物都可用 `svgaFrameEvaluation: 'cpu'` 强制关闭。
|
|
327
|
+
|
|
328
|
+
性能诊断中的 `submittedDrawCalls` 仅表示命令已经到达 WebGL `drawElements*` 或 WebGPU `drawIndexed` 调用/编码;它不表示 GPU 已经执行完成。`rejectedDrawCalls` 表示在原生提交前被后端校验或容量检查拒绝。GPU error scope、pipeline validation 与 framebuffer 像素门禁用于补充验证执行结果。
|
|
329
329
|
|
|
330
330
|
## `addGift()` 参数
|
|
331
331
|
|
|
@@ -741,9 +741,20 @@ await stage.addGift({
|
|
|
741
741
|
异常情况处理:
|
|
742
742
|
|
|
743
743
|
- `IndexedDB` 不可用、事务失败、写入失败、容量不足时,会自动降级
|
|
744
|
-
- 损坏的 `SVGA` 磁盘缓存会自动删除并重新生成
|
|
745
|
-
|
|
746
|
-
|
|
744
|
+
- 损坏的 `SVGA` 磁盘缓存会自动删除并重新生成
|
|
745
|
+
|
|
746
|
+
### SVGA 半透明边缘与 Safari 首播
|
|
747
|
+
|
|
748
|
+
Worker 首次合成图集和缓存 PNG 解码都显式使用 `premultiplyAlpha: 'premultiply'`,
|
|
749
|
+
上传时声明 `sourcePremultiplied: true`。不要改回直接使用 `transferToImageBitmap()`:
|
|
750
|
+
WebKit 的该路径可能丢失预乘标记,而 WebGL 对 ImageBitmap 会忽略上传时的预乘开关,
|
|
751
|
+
导致无缓存首播的半透明边缘发白、过亮,缓存播放却正常。
|
|
752
|
+
|
|
753
|
+
运行 `node scripts/verify-svga-atlas-alpha.mjs` 可在 Chromium 中检查 WebGL1/2 的
|
|
754
|
+
Worker 首次合成、PNG 缓存解码及主线程回退像素;加 `--webkit` 可使用已安装的
|
|
755
|
+
Playwright WebKit。该检查不替代真实 iPhone / Mac Safari 的素材回归。
|
|
756
|
+
|
|
757
|
+
## 项目结构
|
|
747
758
|
|
|
748
759
|
主要目录:
|
|
749
760
|
|
|
@@ -764,7 +775,7 @@ await stage.addGift({
|
|
|
764
775
|
|
|
765
776
|
- [src/index.ts](/D:/MyDocuments/UnityProjects/SVGAPlayer-Unity/gift-stage/src/index.ts)
|
|
766
777
|
|
|
767
|
-
主要导出:
|
|
778
|
+
主要导出:
|
|
768
779
|
|
|
769
780
|
- `GiftStage`
|
|
770
781
|
- `createBackend`
|
|
@@ -774,19 +785,19 @@ await stage.addGift({
|
|
|
774
785
|
- `parseSVGA`
|
|
775
786
|
- `buildAtlas`
|
|
776
787
|
- `parseVAPConfig`
|
|
777
|
-
- 相关类型定义
|
|
778
|
-
|
|
779
|
-
### 第三方 `GPUBackend` 迁移
|
|
780
|
-
|
|
781
|
-
`GPUBackend` 的帧与提交操作使用显式结果契约。第三方实现必须让 `beginFrame()`、`draw(command)`、`endFrame()` 和 `abortFrame()` 返回:
|
|
782
|
-
|
|
783
|
-
```ts
|
|
784
|
-
{ submitted: true }
|
|
785
|
-
// 或
|
|
786
|
-
{ submitted: false, reason, message? }
|
|
787
|
-
```
|
|
788
|
-
|
|
789
|
-
稳定的 `reason` 为 `backend-lost | invalid-command | missing-resource | capacity | validation-error | submission-error`。只有真正到达原生 `drawElements` / `drawIndexed` 或成功完成对应帧操作时才能返回 `submitted: true`;不得再实现或依赖 `wasLastDrawSubmitted()`,也不得用性能计数差值推断提交结果。`abortFrame()` 拒绝表示无法保证失败帧被丢弃,Stage 会立即隔离该 Backend。
|
|
788
|
+
- 相关类型定义
|
|
789
|
+
|
|
790
|
+
### 第三方 `GPUBackend` 迁移
|
|
791
|
+
|
|
792
|
+
`GPUBackend` 的帧与提交操作使用显式结果契约。第三方实现必须让 `beginFrame()`、`draw(command)`、`endFrame()` 和 `abortFrame()` 返回:
|
|
793
|
+
|
|
794
|
+
```ts
|
|
795
|
+
{ submitted: true }
|
|
796
|
+
// 或
|
|
797
|
+
{ submitted: false, reason, message? }
|
|
798
|
+
```
|
|
799
|
+
|
|
800
|
+
稳定的 `reason` 为 `backend-lost | invalid-command | missing-resource | capacity | validation-error | submission-error`。只有真正到达原生 `drawElements` / `drawIndexed` 或成功完成对应帧操作时才能返回 `submitted: true`;不得再实现或依赖 `wasLastDrawSubmitted()`,也不得用性能计数差值推断提交结果。`abortFrame()` 拒绝表示无法保证失败帧被丢弃,Stage 会立即隔离该 Backend。
|
|
790
801
|
|
|
791
802
|
## Demo
|
|
792
803
|
|