Skip to content

Releases: routersys/YMM4-LuaScript

v1.20.3

Choose a tag to compare

@github-actions github-actions released this 05 Jul 10:54

v1.20.3 - Lua スクリプト for YMM4

[fast] マーカーの注意書きを補うドキュメント更新リリースです。v1.20.2 で [fast] は obj.fill / obj.convolve / obj.resize の処理量のしきい値を無視して GPU へ委譲する仕様になりましたが、処理量が小さいときは GPU への委譲自体の往復コストが CPU 実行を上回り、かえって遅くなる場合があることを明記しました。動作に関わる実装、API、実行結果、エラーの扱いに変更はありません。


変更

[fast] は小さな処理で遅くなる場合があることを明記

[fast] は obj.fill / obj.convolve / obj.resize のしきい値を無視しますが、GPU への委譲には往復コストがあります。処理量が小さいときは CPU 実行のほうが速い場合があるため、README、サイト、付属ドキュメントに注意書きを追加しました。

  • 付属の 8 言語ドキュメントの [fast] の節へ、同じ注意書きを追加しました。

互換性・後方互換

  • 動作に関わる実装の変更はありません。
  • API、構文、エンジンの自動振り分け、GPU 検証、CPU への自動フォールバックに変更はありません。
  • v1.20.2 の [fast] の強制委譲仕様に変更はありません。

内部実装

  • 動作に関わるコード変更はありません。
  • リリース対象のバージョン表記を v1.20.3 へ更新しました。

v1.20.2

Choose a tag to compare

@github-actions github-actions released this 05 Jul 10:27

v1.20.2 - Lua スクリプト for YMM4

[fast] マーカーに実効性を戻すリリースです。v1.20.1 で obj.fill / obj.convolve / obj.resize の GPU 委譲を自動判定に統一した結果、[fast] は委譲の意図を明示するだけの補助マーカーとなり、付けても付けなくても同じ判定を通るため動作に差がありませんでした。本バージョンから [fast] は処理量のしきい値を無視して強制的に GPU へ委譲します。GPU が使えない環境や、GPU の結果が CPU と一致しないと判定された環境では、[fast] を付けても自動で CPU 実行に戻るため、結果が壊れることはありません。


変更

[fast] はしきい値を無視して GPU 委譲を強制

obj.fill / obj.convolve / obj.resize は、v1.20.1 と同じく処理量がしきい値以上で GPU の結果が CPU と一致すると確認できたときに自動で GPU へ委譲します。呼び出しの直前に [fast] を置いたときだけ、この処理量のしきい値を無視します。

  • しきい値のみを無視し、Direct3D 11 のハードウェアデバイスが利用できることと、GPU の結果が CPU 基準とバイト単位で一致することの確認は、[fast] を付けても変わらず行います。どちらかが成立しない環境では CPU 実装へ戻ります。
  • convolve のカーネルサイズの上限(31×31)など、GPU 側の対応可否そのものに関わる制約は [fast] でも変わりません。
  • [fast] を付けない呼び出しは v1.20.1 までと同じく、しきい値未満の小さな処理では GPU へ委譲しません。

互換性・後方互換

  • [fast] を付けない呼び出しの動作は v1.20.1 と同一です。
  • GPU が使えない環境や検証に通らないカーネルでは、[fast] を付けた呼び出しも CPU 実装が結果を保証するため、実行結果が変わることはありません。
  • 関数の引数・戻り値・エラーの扱い、構文・置ける位置(単独の行または同じ行)、3 関数以外へ付けたときのエラー表示に変更はありません。
  • エンジンの自動振り分け、エンジン指定ディレクティブの仕様と優先順位、カーネル化の対象、v1.20.1 までの構文拡張と既存の API に変更はありません。

内部実装

  • IPixelBufferProcessor.TryFill / TryConvolve / TryResize に force 引数を追加しました。GpuFillOperation / GpuConvolveOperation / GpuResizeOperation は force が真のときだけ内部のしきい値判定を飛ばし、ハードウェア対応の確認と CPU/GPU 一致検証はそのまま行います。
  • 従来エンジンは AviUtlScriptContext.FillBuffer / Convolve / Resize と LuaScriptEngine の FillCore / ConvolveCore / ResizeCore に force 引数を復元し、__fast_fill / __fast_convolve / __fast_resize が force: true を、obj.fill / obj.convolve / obj.resize が force: false を渡します。
  • 高速ランタイムは worker.lua の fillImpl / convolveImpl / resizeImpl に force 引数を復元しました。_fast* 側は force: true、obj.* 側は force: false を渡し、force が真のときは worker.lua 側のしきい値判定も飛ばして常にホストへ照会します。ホストとの往復では cbResult の未使用スロット(10 番目)で force フラグを伝え、LuaJitWorker が読み取って IPixelBufferProcessor へ引き渡します。プロトコルの新しい定数は追加していません。
  • テストは 3404 件です。v1.20.1 の 3400 件から、_fast* がしきい値未満でもホストプロセッサへ委譲されることの検証を両レーンに 3 件ずつ、標準呼び出しが force: false を渡すことの検証を追加しました。ソリューションは x64 で 0 個の警告、0 個のエラーです。
  • ドキュメントは付属の 8 言語の [fast] の節、サイトの構文拡張と obj の関数のページ、README を強制委譲の仕様へ更新しました。

v1.20.1

Choose a tag to compare

@github-actions github-actions released this 05 Jul 09:50

v1.20.1 - Lua スクリプト for YMM4

画像加工の GPU 委譲を自動判定へ変更したリリースです。v1.20.0 では obj.fill / obj.convolve / obj.resize は [fast] マーカーを付けたときだけ GPU へ委譲していましたが、本バージョンからは標準の呼び出しでも、処理量がしきい値以上で GPU の結果が CPU と一致すると確認できたとき、自動で GPU へ委譲します。マーカーを知らなくても大きな処理は速くなり、成立しない場合は従来どおり CPU で実行するため結果は変わりません。[fast] は構文・診断ともそのまま残り、委譲の意図を明示する補助マーカーになりました。置いても動作は変わりません。


変更

画像加工の GPU 委譲を自動判定へ

obj.fill / obj.convolve / obj.resize は書き方を変えることなく、条件が成立したとき自動で GPU へ委譲します。委譲が成立する条件は v1.20.0 の [fast] と同じで、いずれかを満たさない場合は自動で CPU 実行になり、処理は失敗しません。

  • Direct3D 11 のハードウェアデバイスが利用できること。ソフトウェアラスタライザ(WARP)へは委譲しません。CPU 実装より遅くなるためです。
  • 処理量がしきい値以上であること。fill は画像全体で 1,048,576 画素以上、矩形指定では同じ画素数に加えて塗り面積が画像の 3/4 以上、resize は出力が 262,144 画素以上、convolve は画素数×係数の個数が 262,144 以上です。小さな処理は委譲の往復コストが上回るため CPU で実行します。
  • convolve のカーネルは 31×31 までです。それを超えるサイズは CPU で実行します。
  • 初回に小さな検証画像で GPU の結果を CPU 基準とバイト単位で比較し、一致した組み合わせだけを GPU へ委譲すること。不一致の環境やカーネルでは CPU 実行へ戻ります。

[fast] マーカーは補助的な明示へ

判定が自動になったため、[fast] は委譲の意図を明示する補助マーカーになりました。

  • 構文・置ける位置(単独の行または同じ行)・内部プリミティブへの書き換えは v1.20.0 から変わりません。
  • 3 関数以外へ付けたときのエラー表示もそのまま機能します。
  • [fast] を付けた呼び出しと付けない呼び出しは同じ判定を通るため、動作の差はありません。既存の [fast] 付きスクリプトはそのまま動きます。

互換性・後方互換

  • しきい値未満の小さな処理、GPU が使えない環境、検証に通らないカーネルでは、実行結果は v1.20.0 と同一です。
  • GPU 委譲は事前の検証で CPU 基準とバイト単位まで一致した組み合わせに限って行い、成立しない場合は常に CPU 実装が結果を保証します。
  • 関数の引数・戻り値・エラーの扱いに変更はありません。スクリプトの書き換えは不要です。
  • エンジンの自動振り分け、エンジン指定ディレクティブの仕様と優先順位、カーネル化の対象、v1.20.0 までの構文拡張と既存の API に変更はありません。

内部実装

  • 3 実行系(MoonSharp・LuaJIT ワーカー・コンテキスト契約)から委譲の明示フラグ accelerate を削除しました。[fast] の書き換え先である __fast_fill / __fast_convolve / __fast_resize は標準の関数と同じ実装の別名になり、マーカーの有無で経路が分かれることは構造的にありません。
  • 従来エンジンは AviUtlScriptContext の fill / convolve / resize が常にプロセッサへ照会し、不成立なら CPU 実装へ落ちます。しきい値の判定は GPU 演算側(GpuFillOperation / GpuConvolveOperation / GpuResizeOperation)が持ちます。
  • 高速ランタイムは worker.lua がしきい値の成立時のみホストへ往復し、しきい値未満は往復せず Lua 内で完結します。成立し得ない委譲のプロセス間往復コストは発生しません。
  • GPU 基盤(専用プロジェクト・事前 DXBC コンパイル・検証キャッシュ・再生成予算)は v1.20.0 のまま変更していません。
  • ドキュメントは付属の 8 言語の [fast] の節、サイトの構文拡張と obj の関数のページ、README を自動判定の仕様へ更新しました。
  • テストは 3400 件です。v1.20.0 の 3396 件から、標準呼び出しがホストプロセッサへ委譲されることの検証へ両レーンの既定経路テストを反転し、しきい値未満では委譲しないことの検証 3 件と、従来エンジンの委譲と CPU フォールバックの検証 1 件を追加しました。ソリューションは x64 で 0 個の警告、0 個のエラーです。

v1.20.0

Choose a tag to compare

@github-actions github-actions released this 05 Jul 08:47

v1.20.0 - Lua スクリプト for YMM4

画像加工を GPU へ委譲する高速化マーカー [fast] を追加したリリースです。obj.fill / obj.convolve / obj.resize の呼び出しの直前に [fast] を置くと、その処理を Direct3D 11 のピクセルシェーダーで実行します。AviUtl に無い YMM4 独自の拡張で、従来エンジン(MoonSharp)と高速ランタイム(LuaJIT)の両方で動作します。[fast] を付けない呼び出しは従来どおり CPU で実行し、既存のスクリプトの実行結果は変わりません。あわせて、エディタの補完候補へ fast を登録し、高速ランタイムのタイムアウト計測からホスト側の処理時間を除外する修正を行いました。


新機能

[fast] 高速化マーカー

対象の呼び出しと同じ行の直前、または直前の単独の行に置きます。

[fast]
obj.convolve(kernel, 5)

[fast] obj.fill(0, 0, 0, 0)
[fast] obj.resize(obj.w * 2, obj.h * 2)
  • 対象は obj.fill / obj.convolve / obj.resize の 3 関数です。マーカーは内部プリミティブ(__fast_fill / __fast_convolve / __fast_resize)への書き換えとして展開します。
  • 3 関数以外へ付けるとエラー「[fast]: only obj.fill, obj.convolve and obj.resize can be accelerated.」をマーカーの行へ表示します。この場合マーカーだけを取り除き、対象の呼び出しは通常どおり実行します。拡張構文の書き換え診断はエディタの誤り表示へ届くよう全経路へ通しました。
  • t[fast] のような添字アクセス、テーブルコンストラクタのキー、文字列やコメントの中の [fast] は書き換えません。
  • GPU で実行できない場合は、同じ呼び出しを従来の CPU 実装で実行します。処理は失敗せず、結果は CPU 実行と同じです。

GPU 実行が成立する条件は次のとおりです。いずれかを満たさない場合は自動で CPU 実行になります。

  • Direct3D 11 のハードウェアデバイスが利用できること。ソフトウェアラスタライザ(WARP)へは委譲しません。CPU 実装より遅くなるためです。
  • 処理量がしきい値以上であること。fill は画像全体で 1,048,576 画素以上、矩形指定では同じ画素数に加えて塗り面積が画像の 3/4 以上、resize は出力が 262,144 画素以上、convolve は画素数×係数の個数が 262,144 以上です。小さな処理は委譲の往復コストが上回るため CPU で実行します。
  • convolve のカーネルは 31×31 までです。それを超えるサイズは CPU で実行します。
  • 初回に小さな検証画像で GPU の結果を CPU 基準とバイト単位で比較し、一致した組み合わせだけを GPU へ委譲すること。不一致の環境やカーネルでは CPU 実行へ戻ります。検証の結果は fill と resize はモードごとに、convolve はカーネル・除数・オフセットの組ごとに記憶します(最大 64 組)。

補完候補への fast の登録

エディタの補完辞書へ fast を登録しました。[fa まで入力すると fast が候補の先頭に現れ、別の単語へ置き換わる誤補完を避けられます。構文規則の属性に IsCatalog と Keyword を追加し、登録が必要な構文拡張のキーワードをソースジェネレーターが補完カタログへ自動で載せる仕組みです。


修正

高速ランタイムのタイムアウトからホスト側の処理時間を除外

高速ランタイムのタイムアウト(5000ms)は、これまで画像の読み込み・シーン描画・GPU 委譲などホスト側コールバックに費やした時間もスクリプトの実行時間として計上していました。このためホスト側の処理が遅い環境では、スクリプト自体は制限内に収まるのにタイムアウトと判定され、[fast] の CPU フォールバックが動作しない問題がありました。コールバックの所要時間を計測して実行予算から除外し、タイムアウトが監視する対象をスクリプトの実行時間だけへ正しました。

ハードウェアデバイスの再生成に予算制限を適用

GPU 実行が失敗し続ける環境で、Direct3D 11 デバイスを毎フレーム作り直し続ける問題を修正しました。再生成の予算(3 回)を使い切った後はハードウェア実行を無効化し、以後は即座に CPU 実行へ移ります。


互換性・後方互換

  • [fast] を付けない obj.fill / obj.convolve / obj.resize は従来と同一の CPU 実装で実行し、結果はバイト単位まで変わりません。
  • [fast] は AviUtl / AviUtl2 に存在しない YMM4 独自の拡張です。AviUtl 向けに書かれた既存スクリプトへの影響はありません。
  • GPU 委譲は事前の検証で CPU 基準と一致した組み合わせに限って行い、成立しない場合は常に CPU 実装が結果を保証します。
  • エンジンの自動振り分け、エンジン指定ディレクティブの仕様と優先順位、カーネル化の対象、v1.19.2 までの構文拡張と既存の API に変更はありません。
  • 補完候補は fast の 1 語が増えるのみで、既存の候補と順序の規則(長さ順)は変わりません。

内部実装

  • GPU 基盤を専用プロジェクト LuaScript.Gpu へ分離しました。obj.pixelshader の実行器(PixelShaderRunner)を移設し、[fast] の 3 演算(GpuFillOperation / GpuConvolveOperation / GpuResizeOperation)と入口の GpuPixelBufferProcessor を追加しました。演算はロックで直列化し、実行器のデバイスと定数バッファ・レンダーターゲット・ステージングテクスチャを再利用します。
  • 委譲の契約は IPixelBufferProcessor として Runtime に置き、プラグイン層が GPU 実装を注入します。従来エンジンは AviUtlScriptContext の fill / convolve / resize に明示フラグ accelerate を追加して委譲し、既定値 false のため既存呼び出しの経路は変わりません。
  • CPU 基準の実装は PixelBufferSoftwareProcessor として共有化しました。従来エンジンの実行とGPU 検証の基準の両方が同じコードを参照し、基準の二重管理をなくしています。等価性の基準は従来どおり MoonSharp です。
  • 内部シェーダー(fill / convolve / resize の HLSL)は、GpuPixelOperationShaderAttribute を読むソースジェネレーターがビルド時に DXBC へ事前コンパイルし、実行メソッドを partial として発行します。実行時のシェーダーコンパイルは発生しません。ユーザーの obj.pixelshader は従来どおり実行時コンパイルです。畳み込みシェーダーは HLSL の予約語との衝突を修正しています。
  • 高速ランタイムはプロセス間手順へ呼出種別 CbKindPixelProcess を 1 つ追加しました。畳み込みのカーネルはタグ領域へ double 列として渡します。ホストの処理失敗は「画像を変更しない」を表す 0、プロセッサ不在は -1 で伝え、-1 を受けたワーカーはその実行内の以後の委譲を試みません。
  • タイムアウトの修正は、コールバック 1 回ごとの所要時間を実行予算へ加算する方式です。予算と開始時刻のローカル変数 2 つのみで、毎フレームの割り当てはありません。
  • 補完への登録は、構文規則の生成物(LuaSyntaxRuleRegistry)へ CatalogKeywords 配列を追加し、補完ソースが候補構築時に連結する形です。キーワードの文字列は規則クラスの定数を属性と判定処理で共有し、重複定義がありません。
  • ソースジェネレーターは Lua / Gpu の領域へ整理し、型宣言を 1 ファイル 1 型へ分離しました。増分生成のキャッシュ鍵は EquatableArray へ統一しています。
  • テストは 3396 件です。v1.19.2 の 3366 件から、[fast] の書き換え(同一行・単独行・ブロック内・非対象の括弧の除外・診断の行番号)、両エンジンの高速化プリミティブの往復、ホストプロセッサの呼び出しと既定経路の除外、タイムアウト予算の除外、補完カタログの fast を検証しました。ソリューションは x64 で 0 個の警告、0 個のエラーです。

v1.19.2

Choose a tag to compare

@github-actions github-actions released this 04 Jul 23:59

v1.19.2 - Lua スクリプト for YMM4

従来エンジン(MoonSharp)の毎フレームのグローバル変数更新を高速化したパッチリリースです。スクリプトの書き方と実行結果は一切変わりません。高速ランタイム(LuaJIT)の実装にも変更はありません。


改善

毎フレームのグローバル変数更新のボックス化を除去

従来エンジンは実行のたびに obj / scene / ymm4 / グローバルの約 70 個の変数をテーブルへ書き込みます。この書き込みが object 型のインデクサ経由で、数値・真偽値のボックス化と型変換のディスパッチを毎回発生させていました。ソースジェネレーターの発行を型付きの Table.Set へ変更し、ボックス化と変換ディスパッチを削除しました。

  • 数値は DynValue.NewNumber、文字列は DynValue.NewString の直接生成になります。
  • 真偽値は MoonSharp が共有する DynValue の参照になり、割り当てが完全になくなります。
  • obj.load / obj.copybuffer / obj.resize の後の寸法更新(obj.w 等の 8 個)も同じ形へ揃えました。

互換性・後方互換

  • すべての変数の名前・型・値に変更はありません。ボックス化と変換ディスパッチの除去のみで、テーブルへ格納される内容は従来と同一です。
  • 両エンジンの実行結果はバイト単位まで一致したままです。
  • v1.19.1 までの構文拡張と既存の API に変更はありません。

内部実装

  • 型付き発行は LuaApiGenerator が担います。更新メソッドの戻り値型(double / int / bool / string とその null 許容)から値種別を判定し、DynValue.NewNumber / NewBoolean / NewString を包んだ Table.Set を発行します。未知の型は従来のインデクサ発行へ残すため、後方互換は構造的に保たれます。
  • 発行部 1 箇所の変更で全レジストラ(AviUtlGlobalRegistrar / SceneTableRegistrar / Ymm4TableRegistrar / obj テーブル)に波及します。個別の書き換えはありません。
  • 数値の DynValue 生成自体は値が毎フレーム変わるため残ります。共有インスタンスの書き換えはスクリプトが参照を保持しうるため行いません。
  • テストは 3366 件のまま全件成功です。ソリューションは x64 で 0 個の警告、0 個のエラーです。

v1.19.1

Choose a tag to compare

@github-actions github-actions released this 04 Jul 23:42

v1.19.1 - Lua スクリプト for YMM4

v1.19.0 で追加した画像加工関数のうち、obj.getpixelregion の従来エンジン(MoonSharp)での実行を高速化したパッチリリースです。スクリプトの書き方と実行結果は一切変わりません。高速ランタイム(LuaJIT)の実装にも変更はありません。


改善

obj.getpixelregion の従来エンジンでの高速化

従来エンジンが返す配列の値生成を、0~255 の整数値 256 個の共有インスタンスの参照へ置き換えました。ストレート RGBA の成分は不透明な画素では必ず 0~255 の整数になるため、一般的な画像では値の生成が新規の割り当てなしで済みます。

  • 256×256 の不透明画像に対する obj.getpixelregion(0, 0, obj.w, obj.h) の内部計測で、実行時間は約 199ms から約 151ms(約 24% 短縮)、ヒープ割り当ては約 55MB から約 43MB(約 22% 削減)になりました。
  • 非整数の成分(半透明画素の脱プリマルチプライ結果)は従来どおり都度生成します。値の内容は変わりません。

互換性・後方互換

  • v1.19.0 で追加した 5 関数(obj.fill / obj.getpixelregion / obj.putpixelregion / obj.convolve / obj.resize)の引数・戻り値・計算式に変更はありません。
  • 両エンジンの実行結果はバイト単位まで一致したままです。
  • v1.19.0 までの構文拡張と既存の API に変更はありません。

内部実装

  • 共有インスタンスは MoonSharp 自身が DynValue.True 等で行っているのと同じ手口です。数値の DynValue は不変のため、複数のテーブルとスクリプトで安全に共有できます。読み取り専用として生成し、静的配列に 256 個だけ保持します。
  • 残る割り当ては MoonSharp の Table.Set が内部で行う要素ごとのキー生成と連結リストノードで、公開 API では削減できません。従来エンジンは低速フォールバックであり、高速な処理が必要なスクリプトは既定で高速ランタイムへ振り分けられます。
  • テストは 3366 件のまま全件成功です。ソリューションは x64 で 0 個の警告、0 個のエラーです。

v1.19.0

Choose a tag to compare

@github-actions github-actions released this 04 Jul 23:31

v1.19.0 - Lua スクリプト for YMM4

作業画像をまとめて加工する 5 つの関数 obj.fill / obj.getpixelregion / obj.putpixelregion / obj.convolve / obj.resize を追加したリリースです。単色での塗りつぶし、矩形領域の一括読み書き、畳み込みによるぼかしやシャープや輪郭抽出、そして拡大縮小を、1 つのスクリプト欄で行えます。いずれも AviUtl に無い YMM4 独自の拡張で、従来エンジン(MoonSharp)と高速ランタイム(LuaJIT)の両方で動作します。処理は各エンジンが自前の作業画像上で完結し、両エンジンは同じ計算式でバイト単位まで一致した結果を返します。既存のスクリプトの実行結果は変わりません。


新機能

obj.fill(r, g, b [, a, x, y, w, h])

作業画像を指定色で塗りつぶします。

obj.fill(0, 0, 0, 0)                       -- 全体を透明で消去
obj.fill(255, 0, 0, 255, 10, 10, 20, 20)   -- 矩形を赤で塗る
  • 色は obj.getpixel / obj.setpixel と同じ 0~255 のストレート RGBA で指定します。a を省略すると 255 になります。
  • x, y, w, h を省略すると画像全体を塗りつぶします。矩形を指定した場合は範囲外を切り詰めます。

obj.getpixelregion(x, y, w, h)

矩形領域の画素をストレート RGBA の配列で取得します。

local t = obj.getpixelregion(0, 0, obj.w, obj.h)
  • 戻り値は長さ wh4 の配列です。並びは画素ごとに r, g, b, a の順で、索引は (行*w+列)*4+1 から始まる 1 始まりです。
  • 画像の範囲外の画素は 0,0,0,0 になります。

obj.putpixelregion(x, y, w, h, data)

obj.getpixelregion と同じ並びの配列を矩形領域へ書き戻します。

obj.putpixelregion(0, 0, obj.w, obj.h, t)
  • data は長さ wh4 のストレート RGBA 配列で、1 始まりです。
  • 画像の範囲外へはみ出した画素は書き込みません。

obj.convolve(kernel, size [, divisor, offset])

作業画像へ size×size の畳み込みを適用します。

obj.convolve({ 1,1,1, 1,1,1, 1,1,1 }, 3)          -- 平均ぼかし
obj.convolve({ 0,-1,0, -1,5,-1, 0,-1,0 }, 3)      -- シャープ
obj.convolve({ -1,-1,-1, -1,8,-1, -1,-1,-1 }, 3, 1, 0)  -- 輪郭抽出
  • kernel は size*size 個の係数配列で、行優先の 1 始まりです。size は奇数で、偶数や 1 未満は無視します。
  • divisor は各画素の合計を割る値です。省略するとカーネルの合計になり、合計が 0 のときは 1 になります。
  • offset は除算後に各成分へ加算する値で、省略すると 0 です。
  • 端の画素は最も近い画素で補います。r, g, b, a のすべてに適用します。

obj.resize(w, h [, filter])

作業画像を指定サイズへ拡大縮小します。

obj.resize(obj.w * 2, obj.h * 2)
obj.resize(320, 240, "nearest")
  • obj.w / obj.h / obj.cx / obj.diagonal などの寸法も更新します。
  • filter は "nearest" で最近傍、省略で線形補間です。

互換性・後方互換

  • 追加した 5 関数はいずれも AviUtl / AviUtl2 に存在しない YMM4 独自の拡張です。AviUtl 向けに書かれた既存スクリプトへの影響はありません。
  • 色の表現は obj.getpixel / obj.setpixel と同じ 0~255 のストレート RGBA に統一しました。配列の索引は obj.getpixeldata と同じ 1 始まり、r, g, b, a の並びです。
  • 引数の不足、奇数でない size、範囲外の座標や矩形は、エラーにせず無変更または切り詰めで扱い、スクリプトを停止させません。
  • エンジンの自動振り分け、エンジン指定ディレクティブの仕様と優先順位、カーネル化の対象、v1.18.0 までの構文拡張と既存の API に変更はありません。

内部実装

  • 5 関数はいずれも作業画像と寸法だけで完結する純粋なバッファ演算のため、プロセス間手順の呼出種別もホスト側の資源も新設していません。契約(AviUtlScriptContext)とワーカーの往復手順は変更していません。従来エンジンは AviUtlScriptContext のバッファへ、高速ランタイムは worker.lua が共有メモリの画素領域へ、それぞれ同じ計算式で直接書き込みます。
  • 等価性の基準は従来どおり MoonSharp です。各成分の脱プリマルチプライ(255/a)・畳み込みの累算順・除算とオフセット・再プリマルチプライ・端の座標クランプ・拡大縮小の座標写像とバイリニアの重みを、両エンジンでバイト単位まで一致するよう同一に実装しました。fill / putpixelregion / convolve は obj.setpixel と同じ丸め、resize はプリマルチプライド BGRA のまま標本化します。
  • convolve は脱プリマルチプライした元画像の控えを取ってから書き込むため、入出力の別配列を保ちます。resize は元画像の控えと出力を別の再利用バッファへ分け、連続呼び出しでも自己参照の破壊が起きないようにしました。控えと出力の緩衝は伸長のみの再利用で、定常状態の毎フレームの割り当てはありません。高速ランタイムでは結果が最大画像サイズを超える場合は変更しません。
  • resize は寸法の更新後に作業画像を置き換えるため、obj.load や obj.copybuffer と同じ描画キャッシュの迂回と寸法反映の経路に載ります。
  • ドキュメントは付属の 8 言語、サイトの obj の関数・リファレンス・トップのページ、README を更新しました。
  • テストは 3366 件です。v1.18.0 の 3347 件から、従来エンジンの塗りつぶし・矩形の限定・領域の往復と範囲外・畳み込みの恒等と平均ぼかし・拡大縮小の最近傍複製と寸法更新、高速ランタイムの同じ 9 件、補完カタログへの 5 関数の追加を検証しました。両エンジンは同じ期待値へバイト単位まで一致します。ソリューションは x64 で 0 個の警告、0 個のエラーです。

v1.18.0

Choose a tag to compare

@github-actions github-actions released this 04 Jul 22:43

v1.18.0 - Lua スクリプト for YMM4

AviUtl の音声取得関数 obj.getaudio を追加したリリースです。編集中のシーン全体の音声、エフェクトを付けたアイテム自身の音声、任意の音声ファイルから、PCM・周波数スペクトラム・フーリエ変換のデータを取得し、音に反応する演出をスクリプトで作れます。あわせて obj.getobject が返すテーブルへ他アイテムのメタデータを追加し、合成音声アイテムも参照の対象にしました。どちらも従来エンジン(MoonSharp)と高速ランタイム(LuaJIT)の両方で動作し、音声の取得とメタデータの解決はホスト側で一度だけ行うため、実行結果は両エンジンで一致します。


新機能

obj.getaudio(buf, file [, type, size])

音声データを取得します。

local buf = {}
local n, rate = obj.getaudio(buf, "audiobuffer", "spectrum", 32)
for i = 1, n do
  obj.draw((i - n / 2) * 8, -buf[i] / 200)
end
  • buf に渡したテーブルの buf[1]~buf[n] へデータを格納し、取得したデータ数とサンプリングレートを返します。buf に nil を渡すと、テーブルを 3 番目の戻り値として返します。
  • file には音声ファイルのパスを指定します。特別な名前として "audiobuffer" と "itembuffer" を受け付けます。
  • "audiobuffer" は編集中のシーン全体の音声で、タイムライン上の全アイテムを合成した音声を取得します。AviUtl の「編集中の音声データ」と同じ解釈です。読み取り位置はタイムラインの現在の再生位置です。
  • "itembuffer" は AviUtl に存在しない YMM4 向けの独自拡張で、このエフェクトを付けたアイテム自身の音声を取得します。音量・パン・フェード・音声エフェクトを適用した後の音声で、合成音声アイテムに付ければそのセリフの音声だけに反応できます。音声を持たないアイテム(画像や図形等)ではデータ数 0 になります。
  • type は取得するデータの種類で、省略すると "pcm" になります。
    • "pcm" : 16bit スケール基準(-32768~32767)のモノラル PCM です。現在位置から連続したサンプルを返します。
    • "spectrum" : 周波数帯ごとの音量データです。size は分割する帯域の数で、最大 512、省略時は 32 です。
    • "fourier" : 離散フーリエ変換の振幅データ(0.0~1.0 目安)です。周波数範囲は 1/2048~1/2 で、省略時は 1024 個です。
    • "xxxx.l" / "xxxx.r" : 上記種別の左 / 右チャンネル版です。無指定のときは左右の平均です。
  • size は取得するデータ数で、取得できた数が指定より少ないことがあります。1 回で取得できるデータ数は最大 1024 個です。
  • ファイルと "itembuffer" の読み取り位置はオブジェクトの現在の再生位置(obj.time)です。spectrum / fourier は読み取り位置からの区間を解析して返します。
  • 取得できない場合はデータ数 0 を返し、エラーにはなりません。

obj.getobject のメタデータ

obj.getobject(tag [, frame]) が返すテーブルへ、他アイテムのメタデータを追加しました。

local o = obj.getobject("BGM")
if o and o.exist then
  obj.load("text", o.character .. ": " .. o.text)
end
  • .length : アイテムのフレーム数を返します。
  • .volume : 音量設定の現在値を返します。合成音声アイテム以外は 0 です。
  • .character : キャラクター名を返します。合成音声アイテム以外は空文字列です。
  • .text : セリフまたは表示テキストを返します。合成音声アイテムとテキストアイテム以外は空文字列です。
  • .kind : アイテムの種別名を返します。
  • 合成音声アイテムが参照の対象になりました。座標・拡大率・回転・不透明度は字幕の表示情報を返します。

互換性・後方互換

  • obj.getaudio は AviUtl 互換の関数として追加しました。"audiobuffer" の意味は AviUtl の「編集中の音声データ」に合わせています。buf の添字は 1 始まりで、AviUtl 向けの既存スクリプトの慣例と同じです。
  • "itembuffer" は AviUtl / AviUtl2 に存在しない YMM4 向けの独自拡張です。AviUtl 向けに書かれた既存スクリプトへの影響はありません。
  • obj.getaudio が 1 回で取得できるデータ数の上限は 1024 個です。AviUtl の代表的な用途(spectrum の帯域数 32 前後、fourier の 1024 個、pcm の 1000 個前後)はいずれも上限の範囲に収まります。
  • obj.getobject の既存フィールドの意味と値に変更はありません。メタデータは追加のみで、従来の呼び出しはそのまま動きます。
  • 未対応の type や読み取りの失敗はデータ数 0 の戻り値で表し、スクリプトを停止させません。
  • エンジンの自動振り分け、エンジン指定ディレクティブの仕様と優先順位、カーネル化の対象、v1.17.0 までの構文拡張と既存の API に変更はありません。

内部実装

  • PCM・スペクトラム・フーリエ変換の計算は LuaScript.Compat へ追加した AviUtlAudioConverter が担います。pcm は ±32768 のスケール、spectrum は窓 1024 の FFT の帯域平均を 2/N×32768 で正規化、fourier は窓 2048 の FFT の振幅を 2/N で正規化した値です。計算はホスト側で一度だけ行い、両エンジンは同じ結果を受け取るため、エンジン間の一致は構造的に保証されます。
  • 音声の取得は新設の AudioSampleProvider が担い、3 つの経路を持ちます。"audiobuffer" はシーンの公開メソッド Scene.TryCreateAudioSource で得たタイムライン音源を用います。これは公式コミュニティプラグインの音量取得系の映像エフェクトが同じ状況(映像エフェクトからの音声参照)で使っているのと同じ経路です。ファイルはプラグイン公開 API の AudioFileSourceFactory を用います。
  • "itembuffer" は EffectedItemSourceForEditorInfo を直接生成します。これは YMM4 のエディタ向けインターフェイス IEditorInfo.CreateItemAudioSource が返す実体と同じ公開クラスで、プロジェクトのサンプリングレートと音声アップサンプリング設定を反映した、YMM4 本体の編集時再生と同じ音声を返します。ただしこのクラスはプラグイン公開 API のアセンブリ(YukkuriMovieMaker.Plugin)ではなく本体側にあり、互換性の保証がありません。そのため生成はインライン展開を禁止した専用メソッドへ隔離し、将来の本体更新で型が失われた場合に発生する TypeLoadException を捕捉して、プラグイン公開 API の IAudioItem.CreateAudioSource(音量等を適用する前の音声)へ縮退します。例外がスクリプトへ漏れることはありません。
  • "itembuffer" の自アイテムの特定は、シーンのアイテム一覧から自分のエフェクトを VideoEffects に含むアイテムを参照の同一性で探します。
  • 音源はファイルパス・シーン・アイテムごとに 1 件ずつキャッシュし、対象が変わったときだけ作り直します。読み取り緩衝と結果配列は伸長のみの再利用で、定常状態の毎フレームの割り当てはありません。失敗はすべてデータ数 0 の戻り値で表し、例外を制御フローに使いません。
  • 高速ランタイムにはプロセス間手順の呼出種別 CbKindGetAudio を追加しました。要求はタグ領域へ file と type の 2 文字列、応答は同じタグ領域へ double 配列で返します。タグ領域は 8192 バイトのため、1 回の取得上限が 1024 個になります。この返却方法は obj.setanchor の座標返却と同じ手口です。
  • 音声は描画鍵で検知できない外部状態のため、obj.getaudio でデータを取得したフレームは描画キャッシュを使わず毎回再実行します。obj.load("scene") と同じ扱いです。
  • obj.getobject のメタデータは、SceneObjectInfo へ Length / Volume / Character / Text / Kind を追加し、シーンオブジェクトリゾルバーを IVideoItem 基準へ改めて合成音声アイテムも列挙の対象にしました。高速ランタイムの応答は、数値を既存の結果領域、3 つの文字列をタグ領域へ区切り文字付きで返します。同じタグと同じフレームへの連続した問い合わせのフレーム内キャッシュは従来のままです。
  • obj.effect と obj.brush が共有するパラメータ適用部品の名前を Ymm4PropertyBinder から ParameterBinder へ改めました。実装と適用結果に変更はありません。
  • ドキュメントは付属の 8 言語、サイトの obj の関数・リファレンス・トップ・制限事項のページ、README を更新しました。あわせて既存ドキュメントの冗長なカッコ補足と強調記法を整理しました。
  • テストは 3347 件です。v1.17.0 の 3332 件から、音声変換の pcm のスケールとチャンネル選択・不足時の短縮・スペクトラムの帯域位置・フーリエの正規化・未対応種別、MoonSharp レーンの getaudio の委譲の往復・既定値・失敗時の 0 返し・データ数の切り詰め、高速ランタイムの getaudio の呼出種別の往復と失敗時の 0 返し、両エンジンの getobject のメタデータの往復の検証を追加しました。ソリューションは x64 で 0 個の警告、0 個のエラーです。

v1.17.0

Choose a tag to compare

@github-actions github-actions released this 04 Jul 13:08

v1.17.0 - Lua スクリプト for YMM4

YMM4 のシーンと模様(ブラシ)をスクリプトから利用できるようにしたリリースです。obj.load へ読込種別 "scene" と "brush" を追加し、プロジェクト内の別シーンの映像と、模様で塗り潰した画像を、オブジェクトの画像として読み込めるようにしました。さらに obj.brush を追加し、obj.effect と同じ「名前と値の組」で模様のパラメータを変更しながら描画できるようにしました。いずれも AviUtl / AviUtl2 の obj.load と obj には存在しない YMM4 向けの独自拡張で、シーンの描画も模様の描画も YMM4 のプラグイン公開 API だけで実装しています。従来エンジン(MoonSharp)と高速ランタイム(LuaJIT)の両方で動作し、実行結果は両エンジンで一致します。


新機能

obj.load("scene", シーン名 [, 時間])

プロジェクト内の別シーンを指定時刻で描画し、オブジェクトのバッファを置き換えます。

obj.load("scene", "サブシーン", obj.time)
  • シーン名には YMM4 のシーン一覧に表示される名前を指定します。時間は秒で、省略すると obj.time を用います。読み込み後は obj.w / obj.h などの寸法がシーンの解像度へ更新され、load 直後の getpixel でも参照できます。
  • シーンの描画には YMM4 のプラグイン公開 API である ISceneInfo.TryCreateVideoSource を用います。YMM4 本体のシーンアイテムと同じ経路で描画するため、シーンの内容もエフェクトもそのまま反映されます。
  • 現在のオブジェクトが乗っているシーン自身は指定できません。シーン描画の中からさらにシーンを読み込む形も拒否し、シーン同士の相互参照による無限再帰を防ぎます。
  • 参照先シーンの内容の変化は描画鍵では検知できないため、シーンを読み込んだフレームは描画キャッシュを使わず毎回再実行します。編集中の参照先シーンの変更が、そのまま次の描画へ反映されます。

obj.load("brush", 模様名 [, 幅, 高さ])

YMM4 の模様(ブラシ)で塗り潰した画像を生成し、オブジェクトのバッファを置き換えます。

obj.load("brush", "縞模様", 400, 300)
  • 模様名には YMM4 の模様一覧に表示される名前を指定します。ブラシプラグインで追加した模様もそのまま使えます。
  • 幅と高さを省略すると現在の obj.w / obj.h を用います。模様のパラメータは既定値で描画されます。
  • 塗り潰しは Direct2D のブラシで中心原点の矩形に対して行い、生成した画像は他の読込種別と同じ乗算済みアルファの BGRA として扱われます。

obj.brush(模様名 [, 幅, 高さ] [, パラメータ名, 値, ...])

模様のパラメータを変更しながら描画します。描画は obj.load("brush") と同じで、加えて obj.effect と同じ「名前と値の組」を受け付けます。

obj.brush("縞模様", "Angle", 45, "Color1", 0xff3366)
  • パラメータ名には模様の設定項目の表示名、または内部のプロパティ名を指定します。値は数値・真偽値・文字列に対応し、色は 0xRRGGBB の数値で指定します。
  • 模様名の直後に数値を 2 つ並べたときだけ、それを幅と高さとして解釈します。パラメータ名は常に文字列のため、サイズと組が曖昧になることはありません。
  • 指定しなかったパラメータは既定値で描画されます。組をすべて省略した呼び出しは obj.load("brush") と同じです。
  • パラメータの解決は obj.effect と同じ仕組みです。表示名と内部名の両方を受け付け、対応しない名前の組は無視されます。

互換性・後方互換

  • 既存の読込種別 "figure" / "text" / "image" / "movie" の挙動に変更はありません。新設の読込に失敗した場合は、従来の読込の失敗時と同様に現在の画像を保持します。
  • "scene" / "brush" / obj.brush は AviUtl / AviUtl2 に存在しない YMM4 向けの独自拡張です。AviUtl 向けに書かれた既存スクリプトへの影響はありません。
  • obj.effect のパラメータ適用の実装を模様と共有する形へ整理しましたが、名前の解決規則、値の変換、互換マップの扱いのいずれも従来のままで、適用結果は変わりません。
  • エンジンの自動振り分け、エンジン指定ディレクティブの仕様と優先順位、カーネル化の対象、v1.16.3 までの構文拡張と既存の API に変更はありません。

内部実装

  • シーンの描画は新設の SceneImageRenderer が担います。シーン ID ごとに ITimelineSource をキャッシュし、専用のデバイスコンテキストで描画した出力をステージングビットマップ経由で読み戻します。読み戻し用の緩衝は伸長のみの再利用で、定常状態の毎フレームの割り当てはありません。入れ子のシーン読込の拒否はスレッド静的な深さガードで行い、同一スレッド上の再帰だけを対象にするため競合はありません。
  • 模様の描画は新設の BrushImageRenderer が担います。模様名ごとにブラシのパラメータとソースの組をキャッシュし、PixelBufferManager へ追加した LoadBrushPixels で中心原点の矩形を塗り潰して読み戻します。ブラシのソースは Update のたびにパラメータの現在値を読み直すため、キャッシュしたソースへのパラメータ変更がそのまま反映されます。
  • obj.brush のパラメータの組が前回の呼び出しと異なる名前の集合になったときは、パラメータを既定値から作り直してから適用します。結果が現在の呼び出しの引数だけで決まり、以前の呼び出しで変更した値が残らないようにするためです。同じ名前の集合の間は値の上書きだけで済ませ、毎フレームの作り直しを避けます。
  • パラメータの適用機構は VideoEffectChain から Ymm4PropertyBinder へ抽出し、obj.effect と obj.brush が同じ実装を共有します。プロパティ表のキャッシュは、エフェクトの適用が描画スレッド、模様の適用がスクリプトの実行スレッドで走るようになったため、ロックで保護しました。
  • どちらのレンダラーもエフェクトプロセッサの画素読込セマフォの中で実行し、実行スレッドと描画スレッドの Direct2D の競合を既存の合成経路と同じ方法で防ぎます。
  • 高速ランタイムにはプロセス間手順の呼出種別 CbKindLoadScene / CbKindLoadBrush / CbKindBrush を追加しました。シーンは動画読込と同じ経路、obj.brush は obj.effect と同じ名前と値の符号化に幅と高さを添えた経路で、ホスト側の描画結果を共有メモリへ書き戻します。名前と値の組の符号化と復号は、ワーカー側もホスト側も obj.effect の実装と共有しています。
  • MoonSharp レーンはコンテキストへ追加した読込委譲 SceneImageLoader / BrushImageLoader を経由してホスト側のレンダラーを呼び出します。委譲が未設定のテスト環境では読込は無操作になります。
  • ドキュメントは付属の 8 言語、サイトの obj の関数・リファレンス・トップのページ、README を更新しました。
  • テストは 3332 件です。v1.16.3 の 3317 件から、MoonSharp レーンの scene / brush 読込の委譲の往復・時間とサイズの既定値・失敗時の画像保持、obj.brush の組の解析・先頭サイズの解釈・組なしの呼び出し、高速ランタイムの scene / brush / obj.brush の呼出種別の往復の検証を追加しました。ソリューションは x64 で 0 個の警告、0 個のエラーです。

v1.16.3

Choose a tag to compare

@github-actions github-actions released this 04 Jul 09:29

v1.16.3 - Lua スクリプト for YMM4

再生中の毎フレームのヒープ割り当てを一箇所排除した保守リリースです。エフェクトプロセッサは、キャッシュが一致しないフレームの末尾で、シーンの照会の結果を配列へ写し取り、次フレームの一致判定に備えます。再生中はフレーム番号が毎フレーム変わるため描画鍵が必ず変化し、この末尾が毎フレーム実行されます。従来はここで、シーンのオブジェクトやシーン共有値を照会するスクリプトのために SceneObjectQuery と SceneValueQuery の配列を毎フレーム新規に確保していました。本リリースでは、照会の個数が安定している通常の場合にスナップショットの配列を使い回し、この場合の毎フレームの割り当てをゼロにします。実行結果に変更はなく、スクリプトの挙動もエンジンの振り分けも従来のままです。


パフォーマンス

シーンの照会のスナップショットの配列の使い回し

エフェクトプロセッサの非キャッシュ経路の末尾で毎フレーム起きていた配列の確保を、通常の場合に排除しました。

  • エフェクトプロセッサは、描画鍵と照会の結果が前フレームと一致するときは前フレームの出力をそのまま返し、一致しないときだけスクリプトを実行します。再生中はフレーム番号が毎フレーム変わり描画鍵が必ず変化するため、非キャッシュ経路が毎フレーム走ります。この経路の末尾では、次フレームの一致判定のために、そのフレームで行われたシーンの照会の結果をスナップショットとして配列へ写し取ります。
  • 従来はこの写し取りを毎フレーム新しい配列の確保で行っていました。obj.getoption などでシーンのオブジェクトを照会するスクリプトや、シーン共有値を読むスクリプトでは、SceneObjectQuery または SceneValueQuery の配列がフレームごとに確保され、ガベージコレクションの圧力になっていました。
  • 本リリースでは、照会の個数が前フレームと同じであればスナップショットの配列を使い回し、要素だけを書き戻します。同じスクリプトが同じ個数の照会を行う通常の場合、毎フレームの割り当てが起きなくなります。個数が変わったフレームだけ新しい配列を確保します。
  • 照会を一切行わないスクリプトは、従来どおり共有の空配列を用い、割り当ては起きません。
  • 対象はエフェクトプロセッサの内部の毎フレームの固定費だけです。カーネルレーン、高速ランタイム、MoonSharp のいずれの実行経路も、選び方も、実行結果も変わりません。

互換性・後方互換

  • 実行結果に変更はありません。本変更は毎フレームの割り当ての排除だけを目的とし、スクリプトの挙動、出力、描画記述のいずれも変わりません。
  • スナップショットの配列は、そのフレームで行われた照会の結果を毎フレームすべて書き戻すため、使い回しても内容は毎フレーム新規に確保していた従来と同一です。一致判定に使う値に差は生じません。
  • エンジンの自動振り分け、エンジン指定ディレクティブの仕様と優先順位、カーネル化の対象、v1.16.2 までの構文拡張と既存の API に変更はありません。

内部実装

  • 追加した SnapshotQueries<T>(IReadOnlyList<T> source, T[] existing) は、照会の個数が 0 のときは共有の空配列を返し、既存の配列の長さが個数と一致するときはその配列へ要素を書き戻し、一致しないときだけ新しい配列を確保します。照会の個数はスクリプトが同じであればフレーム間で安定するため、その場合は毎フレームの割り当てが起きません。
  • 使い回しが安全なのは、SceneObjectQuery と SceneValueQuery がいずれも readonly record struct の値であり、前フレームのスナップショットが当該フレームのキャッシュの一致判定で読み終えた後に上書きされるためです。判定より前に上書きが起きることはなく、配列の使い回しによる別名の干渉はありません。既存の compute-once / zero per-frame allocation の設計思想に沿った統一的な変更です。
  • あわせて、他の毎フレームの経路がいずれも自らのレーンの中で割り当てを持たないことを再確認しました。GPU カーネルの適用は定数の緩衝と出力を再利用し、CPU カーネルと SIMD、ネイティブレーンのワーカー、カーネルのユニフォームの充填、ネイティブのフィールドの写し取り、コンテキストの充填、構造体の複製による出力記述の生成のいずれにも毎フレームの割り当てはありません。
  • 精査の上で見送った項目があります。ネイティブレーンの文字列パラメータの毎フレームの再エンコードは、短い文字列に対する処理であり、それが乗るプロセス間の往復に比べて無視できる量のため据え置きました。ディレクティブ解決の二重の走査は、参照の同一性でキャッシュされスクリプトの編集ごとに一度だけ走るため据え置きました。MoonSharp レーンの数値のボックス化は、低速フォールバック専用として従来どおり据え置きました。
  • テストは 3317 件で変更はありません。本変更は実行結果を変えないため、既存のキャッシュとシーンの照会の一致判定の検証で挙動が担保されます。ソリューションは Release x64 で 0 個の警告、0 個のエラーです。