Conversation
There was a problem hiding this comment.
Pull request overview
WebGPU バックエンド導入に伴い、レンダリング/キャッシュ/描画キュー周りを更新し、加えて Playwright のE2Eスナップショットテストを追加するPRです。
Changes:
- WebGL/WebGPU 両対応の
Context初期化とレンダラー側の型/処理を更新 - フィルター/レイヤー合成・キャッシュキー(instanceId 等)の扱いを描画キューに反映
- 描画・フィルター・ブレンド等を対象に Playwright E2E テスト + テストページを追加
Reviewed changes
Copilot reviewed 143 out of 776 changed files in this pull request and generated 12 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/webgl/src/Blend/service/BlendScreenService.ts | ブレンド状態参照を getter から exported state に変更 |
| packages/webgl/src/Blend/service/BlendScreenService.test.ts | ブレンド状態参照に追従 |
| packages/webgl/src/Blend/service/BlendResetService.ts | ブレンド状態参照を getter から exported state に変更 |
| packages/webgl/src/Blend/service/BlendResetService.test.ts | ブレンド状態参照に追従 |
| packages/webgl/src/Blend/service/BlendOneZeroService.ts | ブレンド状態参照を getter から exported state に変更 |
| packages/webgl/src/Blend/service/BlendOneZeroService.test.ts | ブレンド状態参照に追従 |
| packages/webgl/src/Blend/service/BlendEraseService.ts | ブレンド状態参照を getter から exported state に変更 |
| packages/webgl/src/Blend/service/BlendEraseService.test.ts | ブレンド状態参照に追従 |
| packages/webgl/src/Blend/service/BlendAlphaService.ts | ブレンド状態参照を getter から exported state に変更 |
| packages/webgl/src/Blend/service/BlendAlphaService.test.ts | ブレンド状態参照に追従 |
| packages/webgl/src/Blend/service/BlendAddService.ts | ブレンド状態参照を getter から exported state に変更 |
| packages/webgl/src/Blend/service/BlendAddService.test.ts | ブレンド状態参照に追従 |
| packages/webgl/src/Blend.ts | blend mode / func codeを getter から exported state に変更 |
| packages/webgl/src/BezierConverter/usecase/BezierConverterAdaptiveCubicToQuadUseCase.test.ts | 適応分割のテスト新規追加 |
| packages/webgl/src/BezierConverter.ts | 適応テッセレーション用バッファ/分割ユーティリティを追加 |
| packages/webgl/src/AtlasManager/usecase/AtlasManagerResetUseCase.test.ts | アクティブインデックス参照を getter から exported state に変更 |
| packages/webgl/src/AtlasManager/service/AtlasManagerCreateNodeService.ts | アトラス探索/切り替えロジックを更新 |
| packages/webgl/src/AtlasManager.ts | アトラスインデックス参照を getter から exported state に変更・一部API削除 |
| packages/text/src/interface/ITextFieldType copy.ts | 重複型定義ファイルを削除 |
| packages/renderer/src/Video/usecase/VideoRenderUseCase.ts | filterKey導入・flipY指定・atlas bindのnull安全化 |
| packages/renderer/src/TextField/usecase/TextFieldRenderUseCase.ts | x/y scaleをrender_queueへ移管・filterKey導入・atlas bindのnull安全化 |
| packages/renderer/src/Shape/usecase/ShapeRenderUseCase.ts | x/y scaleをrender_queueへ移管・filterKey導入・atlas bindのnull安全化 |
| packages/renderer/src/Shape/service/ShapeCommandService.ts | 行列生成を subarray 化(割り当て削減) |
| packages/renderer/src/RendererUtil.ts | WebGL/WebGPU Context のunion型に更新 |
| packages/renderer/src/DisplayObjectContainer/usecase/DisplayObjectContainerRenderUseCase.ts | container layer のブレンド/フィルター合成パス追加 |
| packages/renderer/src/CommandController.ts | コンテキスト初期化を await 化 |
| packages/renderer/src/Command/usecase/CommandCaptureUseCase.ts | キャプチャ中の背景色を退避/復元 |
| packages/renderer/src/Command/service/CommandInitializeContextService.ts | WebGL/WebGPU 初期化(WebGPU優先)を導入 |
| packages/renderer/src/Command/service/CommandInitializeContextService.test.ts | WebGLモックにfrontFace追加 |
| packages/renderer/package.json | @next2d/webgpu を peerDependencies に追加 |
| packages/net/README.md | ドキュメントを拡充(概要/使い方/型) |
| packages/media/src/Video/usecase/VideoPlayEventUseCase.ts | playイベント時の即時drawImageを削除 |
| packages/display/src/Video/usecase/VideoGenerateRenderQueueUseCase.ts | instanceId追加・一部params pushの整合調整 |
| packages/display/src/Video/usecase/VideoCalcLayerBoundsUseCase.ts | Videoのフィルター後bounds計算を新規追加 |
| packages/display/src/Video/usecase/VideoCalcLayerBoundsUseCase.test.ts | Video layer bounds のテスト新規追加 |
| packages/display/src/TextField/usecase/TextFieldGenerateRenderQueueUseCase.ts | instanceId/xScale/yScale追加・rawMatrix/rawColorの単位行列判定 |
| packages/display/src/TextField/usecase/TextFieldCalcLayerBoundsUseCase.ts | TextFieldのフィルター後bounds計算を新規追加 |
| packages/display/src/TextField/usecase/TextFieldCalcLayerBoundsUseCase.test.ts | TextField layer bounds のテスト新規追加 |
| packages/display/src/Sprite.ts | クラスdocの簡略化 |
| packages/display/src/Shape/usecase/ShapeLoadAsyncUseCase.ts | Shape.load 用のasyncロードユースケース追加 |
| packages/display/src/Shape/usecase/ShapeLoadAsyncUseCase.test.ts | ShapeLoadAsyncUseCase のテスト新規追加 |
| packages/display/src/Shape/usecase/ShapeGenerateRenderQueueUseCase.ts | instanceId/xScale/yScale追加・bitmap uniqueKey生成方針変更 |
| packages/display/src/Shape/usecase/ShapeCalcLayerBoundsUseCase.ts | Shapeのフィルター後bounds計算を新規追加 |
| packages/display/src/Shape/usecase/ShapeCalcLayerBoundsUseCase.test.ts | Shape layer bounds のテスト新規追加 |
| packages/display/src/Shape.ts | Shape.load API を追加 |
| packages/display/src/Graphics/service/GraphicsToNumberArrayService.ts | 無効lineCap/lineJoinのデフォルト処理追加・matrix処理変更 |
| packages/display/src/Graphics/service/GraphicsToNumberArrayService.test.ts | デフォルトlineCap/lineJoinのテスト追加 |
| packages/display/src/DisplayObjectContainer/usecase/DisplayObjectContainerGetLayerBoundsUseCase.ts | コンテナ子孫のlayer bounds統合ユースケース新規追加 |
| packages/display/src/DisplayObjectContainer/usecase/DisplayObjectContainerGetLayerBoundsUseCase.test.ts | コンテナlayer bounds のテスト新規追加 |
| packages/display/src/DisplayObjectContainer/usecase/DisplayObjectContainerGenerateRenderQueueUseCase.test.ts | コンテナrender queue仕様変更に追従 |
| packages/display/src/DisplayObject/service/DisplayObjectGenerateHashService.ts | ハッシュ生成の高速化(Uint32 view + unroll) |
| packages/display/src/DisplayObject/service/DisplayObjectGenerateHashService.test.ts | ハッシュテストをプロパティベース寄りに拡充 |
| packages/display/src/DisplayObject/service/DisplayObjectApplyChangesService.ts | 親へのchanged伝播を再帰→ループ化 |
| packages/display/src/DisplayObject.ts | visible setter の型正規化を整理 |
| packages/display/src/BitmapData.ts | buffer を public 扱いに変更(コメント/修飾の調整) |
| packages/core/src/Player/usecase/PlayerTickerUseCase.ts | ENTER_FRAME イベントの使い回し |
| packages/core/src/Canvas/service/CanvasInitializeService.ts | canvas style に user-select 無効等を追加 |
| packages/core/src/Canvas/service/CanvasInitializeService.test.ts | style 文字列期待値更新 |
| packages/cache/src/CacheStore/service/CacheStoreGenerateKeysService.ts | キー生成の割り当て削除(FNV直書き) |
| packages/cache/src/CacheStore/service/CacheStoreGenerateKeysService.test.ts | 追加ケースを追加 |
| packages/cache/src/CacheStore/service/CacheStoreGenerateFilterKeysService.ts | フィルターキーを string→number hash に変更 |
| packages/cache/src/CacheStore/service/CacheStoreGenerateFilterKeysService.test.ts | 期待値/型のテスト更新 |
| packages/cache/src/CacheStore.ts | generateFilterKeys の戻り型を number に変更 |
| package.json | v3.0.0 化・Playwright追加・依存更新・e2e scripts 追加 |
| e2e/tests/video.spec.ts | Video のE2Eスナップショットテスト追加 |
| e2e/tests/textfield.spec.ts | TextField のE2Eスナップショットテスト追加 |
| e2e/tests/sprite.spec.ts | Sprite のE2Eスナップショットテスト追加 |
| e2e/tests/shape.spec.ts | Shape のE2Eスナップショットテスト追加 |
| e2e/tests/mask.spec.ts | Mask のE2Eスナップショットテスト追加 |
| e2e/tests/helpers/wait-for-render.ts | 描画完了待機ヘルパー追加 |
| e2e/tests/helpers/renderer-switcher.ts | renderer切替ヘルパー追加 |
| e2e/tests/filter.spec.ts | Filter のE2Eスナップショットテスト追加 |
| e2e/tests/display-object.spec.ts | DisplayObject のE2Eスナップショットテスト追加 |
| e2e/tests/container.spec.ts | Container のE2Eスナップショットテスト追加 |
| e2e/tests/blendmode.spec.ts | BlendMode のE2Eスナップショットテスト追加 |
| e2e/playwright.config.ts | WebGL/WebGPU project を持つ Playwright 設定追加 |
| e2e/pages/video/filter.html | Video filter テストページ追加 |
| e2e/pages/video/blendmode.html | Video blendmode テストページ追加 |
| e2e/pages/textfield/thickness.html | TextField thickness テストページ追加 |
| e2e/pages/textfield/scroll.html | TextField scroll テストページ追加 |
| e2e/pages/textfield/multiple-textfields.html | TextField 複数表示テストページ追加 |
| e2e/pages/textfield/auto-font-size.html | TextField autoFontSize テストページ追加 |
| e2e/pages/sprite/video-in-sprite-test.html | Sprite内Video検証用ページ追加 |
| e2e/pages/sprite/sprite-filter.html | Sprite filter テストページ追加 |
| e2e/pages/shape/load-image-flip.html | Shape.loadのY反転検証ページ追加 |
| e2e/pages/shape/line-gradient.html | Shape lineGradient テストページ追加 |
| e2e/pages/shape/line-bitmap.html | Shape lineBitmap テストページ追加 |
| e2e/pages/shape/graphics-clone.html | Graphics.copyFrom テストページ追加 |
| e2e/pages/shape/graphics-clear.html | Graphics.clear テストページ追加 |
| e2e/pages/shape/fill-solid.html | Shape beginFill テストページ追加 |
| e2e/pages/shape/fill-bitmap.html | Shape beginBitmapFill テストページ追加 |
| e2e/pages/filter/filter-quality.html | Filter quality 比較ページ追加 |
| e2e/pages/filter/convolution.html | ConvolutionFilter テストページ追加 |
| e2e/pages/filter/blur.html | BlurFilter テストページ追加 |
| e2e/pages/filter/bevel.html | BevelFilter テストページ追加 |
| e2e/pages/display-object/properties.html | DisplayObject 基本プロパティページ追加 |
| e2e/pages/display-object/nested-transforms.html | ネストtransformページ追加 |
| e2e/pages/display-object/color-transform.html | ColorTransformページ追加 |
| e2e/pages/container/child-management.html | Container child操作ページ追加 |
| CLAUDE.md | リポジトリ向け開発ガイド追加 |
| .github/workflows/publish.yml | CI の Node/Actions バージョン更新 |
| .github/workflows/lint.yml | CI の Node/Actions バージョン更新 |
| .github/workflows/integration.yml | CI の Node/Actions バージョン更新 |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // 32bitの符号なし整数にキャストし、24bitの範囲に収める | ||
| return (hash >>> 0) % 16777216; | ||
| // 32bitハッシュ値を24bitに圧縮 | ||
| return hash >>> 8 ^ hash & 0xff & 0xffffff; |
There was a problem hiding this comment.
return hash >>> 8 ^ hash & 0xff & 0xffffff; は演算子の優先順位の関係で 24bit にマスクされず、hash >>> 8 側の上位ビットが残る可能性があります。(hash ^ (hash >>> 8)) & 0xffffff のように XOR の結果を最後に 24bit マスクする形に直してください。
| return hash >>> 8 ^ hash & 0xff & 0xffffff; | |
| return (hash ^ (hash >>> 8)) & 0xffffff; |
| const matrix: Matrix = recodes[idx++]; | ||
| if (matrix) { | ||
| array.push(...matrix); | ||
| array.push(...matrix.rawData); |
There was a problem hiding this comment.
この変更だと、recodes[idx++] に Float32Array が入っている既存ケース(テストでも new Float32Array([1,2,3,4,5,6]) を渡している)が即座に matrix.rawData 参照で落ちます。Matrix と Float32Array の両方を受けられるように分岐(例: matrix instanceof Matrix なら rawData、それ以外はそのまま配列として扱う)するか、recodes を生成する側/テスト側を Matrix に統一してください。
| * @return {Promise<void>} | ||
| * @method | ||
| * @public | ||
| */ | ||
| export const execute = (shape: Shape, url: string): Promise<void> => | ||
| { | ||
| return new Promise<void>((resolve): void => | ||
| { | ||
| shape.addEventListener(Event.COMPLETE, resolve); |
There was a problem hiding this comment.
Promise<void> なのに resolve をイベントリスナーとして渡しているため、型的にも挙動的にも resolve(Event) になり得ます(実際テストでは Event を期待しています)。戻り値を Promise<Event> にするか、resolve() を引数なしで呼ぶラッパー関数を使ってください。加えて、COMPLETE発火後に removeEventListener しないと複数回呼び出しでリスナーが累積します(リーク/多重resolveの温床)ので、1回で解除する実装にしてください。
| * @return {Promise<void>} | |
| * @method | |
| * @public | |
| */ | |
| export const execute = (shape: Shape, url: string): Promise<void> => | |
| { | |
| return new Promise<void>((resolve): void => | |
| { | |
| shape.addEventListener(Event.COMPLETE, resolve); | |
| * @return {Promise<Event>} | |
| * @method | |
| * @public | |
| */ | |
| export const execute = (shape: Shape, url: string): Promise<Event> => | |
| { | |
| return new Promise<Event>((resolve): void => | |
| { | |
| const onComplete = (event: Event): void => | |
| { | |
| shape.removeEventListener(Event.COMPLETE, onComplete); | |
| resolve(event); | |
| }; | |
| shape.addEventListener(Event.COMPLETE, onComplete); |
| } | ||
|
|
||
| return node; | ||
| return execute(width, height); |
There was a problem hiding this comment.
全インデックスで insert が失敗する(全アトラス満杯、または要求サイズが大きすぎる等)ケースで、状態が改善しないまま execute を再帰し続けて無限再帰/スタックオーバーフローになります。探索ループで解決できなかった場合は明示的にエラーを返す/投げる、もしくは新しい TexturePacker を作成する上限管理(例: idxの上限拡張)を行うなど、必ず停止条件を入れてください。
| return execute(width, height); | |
| throw new Error( | |
| `Failed to insert node of size ${width}x${height} into any texture atlas (max atlases: 10, atlas size: ${$RENDER_MAX_SIZE}x${$RENDER_MAX_SIZE}).` | |
| ); |
| const imageBitmap = await $context.createImageBitmap(width, height); | ||
|
|
||
| // reset background color | ||
| $context.updateBackgroundColor(red, green, blue, alpha); | ||
|
|
There was a problem hiding this comment.
createImageBitmap が例外を投げた場合に背景色が復元されません。背景色の復元は try/finally で必ず実行されるようにして、キャプチャ失敗時でも描画状態が壊れないようにしてください。
| const imageBitmap = await $context.createImageBitmap(width, height); | |
| // reset background color | |
| $context.updateBackgroundColor(red, green, blue, alpha); | |
| let imageBitmap: ImageBitmap; | |
| try { | |
| imageBitmap = await $context.createImageBitmap(width, height); | |
| } finally { | |
| // reset background color | |
| $context.updateBackgroundColor(red, green, blue, alpha); | |
| } |
| const hidden = render_queue[index++]; | ||
| if (!hidden) { | ||
| continue; | ||
| } |
There was a problem hiding this comment.
ここは値が false のとき continue しているため、変数名 hidden が意味と逆になっていて読み手を混乱させます(visible / renderEnabled / shouldRender などにすると条件が自然になります)。
| if (tMatrix !== matrix) { | ||
| Matrix.release(tMatrix); | ||
| } | ||
| $poolBoundsArray(bounds); | ||
| renderQueue.push(0); | ||
| return; |
There was a problem hiding this comment.
この早期returnパスで bounds をプールへ返していた処理($poolBoundsArray(bounds))が削除されており、$getBoundsArray のプール戦略を前提にしているならメモリ/GC負荷が増えます。renderQueue.push(0); return; の前に bounds を必ず $poolBoundsArray へ返すよう戻してください(同様の早期return箇所も)。
| if (tMatrix !== matrix) { | ||
| Matrix.release(tMatrix); | ||
| } | ||
| $poolBoundsArray(bounds); | ||
| renderQueue.push(0); | ||
| return; |
There was a problem hiding this comment.
TextField側と同様に、早期returnパスで bounds のプール返却が削除されているように見えます。$getBoundsArray / $poolBoundsArray の利用方針に合わせて、return 前に bounds を必ずプールへ返す処理を入れてください。
| const rawMatrix = displayObjectGetRawMatrixUseCase(display_object_container); | ||
| const tMatrix = rawMatrix | ||
| ? matrix | ||
| ? Matrix.multiply(matrix, rawMatrix) | ||
| : rawMatrix | ||
| : matrix; |
There was a problem hiding this comment.
この関数内で Matrix.multiply(...) を呼ぶ場合、既存コードベースのパターンだと戻り値はプール管理される一時行列で、使用後に Matrix.release(...) が必要な可能性が高いです(他のusecaseでは tMatrix !== matrix のとき release しています)。ここでは release が無いので、呼び出し頻度次第でプール/GC観点の劣化につながります。tMatrix が一時生成なら、ループ終了後に適切に Matrix.release(tMatrix) を追加し、rawMatrix を直接返す分岐も含めてライフタイムを揃えてください。
|
|
||
| $poolBoundsArray(bounds); | ||
| } | ||
|
|
There was a problem hiding this comment.
この関数内で Matrix.multiply(...) を呼ぶ場合、既存コードベースのパターンだと戻り値はプール管理される一時行列で、使用後に Matrix.release(...) が必要な可能性が高いです(他のusecaseでは tMatrix !== matrix のとき release しています)。ここでは release が無いので、呼び出し頻度次第でプール/GC観点の劣化につながります。tMatrix が一時生成なら、ループ終了後に適切に Matrix.release(tMatrix) を追加し、rawMatrix を直接返す分岐も含めてライフタイムを揃えてください。
| if (tMatrix && matrix && tMatrix !== matrix) { | |
| Matrix.release(tMatrix); | |
| } |
No description provided.