Skip to content

Releases: routersys/YMM4-LuaScript

v1.13.3

Choose a tag to compare

@github-actions github-actions released this 03 Jul 00:01

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

obj.setfont の引数の解釈を MoonSharp とネイティブの両エンジンで統一したリリースです。
これまで両エンジンは通常の呼び出しでは同じ結果を返していましたが、引数へ想定外の型や値を渡した場合の挙動が食い違っており、ネイティブエンジンにはスクリプト全体をエラーにする経路が存在しました。今回から、どのような引数を渡しても両エンジンが同一の結果を返します。
あわせて、スクリプトエディタの入力補完へ、ドキュメントに記載済みで未登録だった obj テーブルの関数 12 件を追加しました。
呼び出しの書き方と関数の引数に変更はありません。通常の使い方への影響はありません。


動作の変更

1. obj.setfont の引数の解釈を両エンジンで統一

obj.setfont(フォント名, サイズ, スタイル, 色) の各引数について、想定外の型や値を渡した場合の挙動を次のとおり統一しました。

  • フォント名へ数値を渡した場合、両エンジンとも文字列へ変換して採用します。これまで MoonSharp は無視し、ネイティブは真偽値やテーブルまで文字列化していました。文字列と数値以外の値は両エンジンとも無視し、直前の設定を保持します。
  • サイズへ数値文字列を渡した場合、両エンジンとも数値へ変換して採用します。これまでネイティブは文字列のまま保持し、後続の obj.load("text") の呼び出しでスクリプト全体が実行時エラーになっていました。数値へ変換できない値は両エンジンとも無視し、直前の設定を保持します。
  • スタイルへ数値へ変換できない値を渡した場合、両エンジンとも無視して直前の設定を保持します。これまで MoonSharp は 0 として太字と斜体を解除し、ネイティブは実行時エラーになっていました。
  • スタイルの小数と負数は、両エンジンとも床関数で整数化してからビットを判定します。これまで MoonSharp はゼロ方向への切り捨てを行っており、負の小数で結果が食い違っていました。
  • スタイルへ NaN・無限大・2^53 を超える数値を渡した場合も、両エンジンとも同一の結果(太字と斜体の解除)になります。これまで MoonSharp は変換の飽和により値ごとに異なるフラグが立つことがありました。
  • 色へ数値へ変換できない値を渡した場合、両エンジンとも無視して直前の設定を保持します。

2. スクリプトエディタの入力補完へ obj テーブルの関数 12 件を追加

ドキュメントに記載済みで入力補完に未登録だった次の関数を、候補へ追加しました。
obj.getobject、obj.putpixeldata、obj.setfont、obj.draw、obj.drawpoly、obj.copybuffer、obj.getvalue、obj.setoption、obj.getoption、obj.pixeloption、obj.setanchor、obj.effect の 12 件です。
並び順はドキュメントの「obj テーブル - 関数」の記載順に合わせています。


互換性・後方互換

  • 呼び出しの書き方と関数の引数に変更はありません。フォント名に文字列、サイズ・スタイル・色に数値を渡す通常の使い方の結果は変わりません。
  • 引数を省略した場合と nil を渡した場合は、両エンジンとも直前の設定を保持します。
  • フォントの既定値(フォント名なし・サイズ 34・標準スタイル・色 0xFFFFFF)と、実行ごとに既定値へ戻る仕様は変わりません。
  • scene.set / scene.get を含む v1.13.2 の仕様に変更はありません。

内部実装

  • MoonSharp 側の setfont の引数解釈とフォント状態を AviUtlFontState として独立した型へ抽出しました。LuaScriptEngine はフォントの 5 つのフィールドを持たず、この型へ委譲します。テストレーンはソースリンク方式で LuaScriptEngine を参照できないため、SceneTableRegistrar と同じ「純粋な単位を切り出してリンクする」構成に従ったものです。
  • スタイルのビット判定は Lua の剰余と同じ床剰余(値 - floor(値 / 除数) * 除数)で行います。C# の変換の飽和(NaN が 0、範囲外が最大値へ丸められる仕様)を経由しないため、非有限値と巨大な値でも LuaJIT の math.floor と剰余の結果に一致します。
  • worker.lua の setfont へ型検査と tonumber による変換を導入しました。フォント名は文字列と数値のみ受理し、サイズ・スタイル・色は数値へ変換できた場合のみ採用します。変換できない値が共有メモリの数値領域へ渡って ffi の変換エラーになる経路を排除しました。
  • 入力補完は LuaAutoCompletionStrategy の obj 名前空間の候補配列への追加のみで、補完の仕組みに変更はありません。
  • テストは 3092 件です。v1.13.2 の 3086 件から、AviUtlFontState の既定値とリセット、引数の変換規則、負数スタイルの床セマンティクス、非有限値の扱いの検証と、ネイティブワーカーで同一の呼び出し列を実行して同じ期待値と照合する等価性の検証を追加しました。

v1.13.2

Choose a tag to compare

@github-actions github-actions released this 02 Jul 23:32

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

scene.set / scene.get の値の見え方を、フレーム位置に対して決定論的なモデルへ変更したリリースです。
共有領域を「どのフレームで何を書き込んだか」を記録する履歴として再設計し、各フレームの読み取りは「そのフレームより前に確定した最新の値」を返すようにしました。これにより、タイムラインをどの順番でシークしても、同じフレームでは同じ値を読み取ります。あわせて、書き込みの確定に次のフレームの評価を必要としないようにし、同じフレームで複数のアイテムが同じ名前へ書き込んだ場合の優先規則を定め、動画出力とアイテムエフェクトの編集画面を編集中のプレビューから分離し、履歴が使うメモリへ上限を設けました。
呼び出しの書き方と関数の引数に変更はありません。scene.set / scene.get を使わないスクリプトへの影響はありません。


動作の変更

1. 値の見え方をフレーム位置に対して決定論的なモデルへ変更

v1.13.1 までは、各アイテムの書き込みを保留領域へため、次のフレームの評価が行われた時点で共有領域の現在値へ反映していました。このため、読み取れる値が「どのフレームを評価してきたか」というシークの経路に左右され、前のフレームへ戻ったときに後のフレームで書き込まれた値が見えることがありました。
今回から、書き込みをフレーム番号付きの履歴として記録し、scene.get は「自分のフレームより前に確定した最新の値」を返すようにしました。
自分のスクリプトが書き込んだ値は、同じ実行の中で直後の scene.get からそのまま読み取れます。他のアイテムが書き込んだ値は、次のフレーム以降の評価から読み取れます。
同じフレームの中では、アイテムがどの順番で評価されても scene.get が返す値は変わりません。

2. ランダムシークへの対応

タイムライン上をどの順番でシークしても、各フレームの読み取り結果は変わりません。
前へ戻ったフレームでは、そのフレームより後に書き込まれた値は見えず、そのフレームより前に書き込まれた値だけが見えます。
書き込んだフレームの直後のフレームを評価しなくても、それより後のどのフレームからでも読み取れます。
同じフレームを何度再評価しても、読み取れる値と書き込みの結果は同一です。

3. 同じフレームで複数のアイテムが同じ名前へ書き込んだ場合の規則

同じフレームで複数のアイテムが同じ名前へ書き込んだ場合、レイヤー番号の大きいアイテムの書き込みが優先されます。
アイテムは並列に評価されますが、この規則により結果は評価のタイミングに依存しません。
同じアイテムの中で複数の Lua スクリプトエフェクトが同じ名前へ書き込んだ場合は、エフェクトチェーンの後段の書き込みが優先されます。

4. 動画出力とアイテムエフェクトの編集画面を編集中のプレビューから分離

動画出力は編集中のプレビューとは独立した空の共有領域から始まります。編集画面での試行の途中経過が出力へ持ち込まれることがなくなり、同じプロジェクトを出力すれば毎回同じ結果になります。出力が終わると、その出力で使った共有領域は破棄されます。
アイテムエフェクトの編集画面のプレビューも独立した共有領域を使うため、編集画面を開いても編集中のプレビューの共有値は変化しません。
現在のフレームの画像出力は編集中のプレビューと同じ共有領域を参照するため、保存される画像はプレビューの表示と一致します。v1.13.1 までは画像出力が共有領域を全消去していましたが、この副作用はなくなりました。

5. 履歴のメモリへ上限を追加

各名前の最新の値を除いた履歴が使うメモリは 16MB までとし、超過した場合は全体で最も古い記録から順に間引きます。最新の値は間引きの対象になりません。
1 つのシーンに保存できる名前が 4096 個までである仕様は、v1.13.1 から変わりません。


互換性・後方互換

  • 呼び出しの書き方と関数の引数に変更はありません。scene.set / scene.get を使わないスクリプトへの影響はありません。
  • スクリプトがエラーまたはタイムアウトで終了したフレームの書き込みを反映しない仕様は、v1.13.1 から変わりません。
  • 名前と文字列値を UTF-8 換算で 4095 バイトへ切り詰める仕様は、v1.13.0 から変わりません。
  • nil を渡した削除は、削除の記録として履歴へ残ります。削除より前のフレームでは削除前の値を、削除より後のフレームでは nil を読み取ります。
  • 共有値はメモリ上にのみ保持し、プロジェクトファイルには保存しません。YMM4 を終了すると失われます。

内部実装

  • SceneSharedValues を世代スナップショット方式からフレーム索引付きの履歴方式へ再設計しました。名前ごとに「フレーム番号・レイヤー番号・値」の組をフレーム昇順で保持し、読み取りは自分のフレームより前の最新の組を二分探索で求めます。nil の書き込みは削除の記録として履歴へ残し、直前の値と同じ書き込みは記録しません。保留領域と世代の追跡、出力開始の検出によるリセットは撤廃しました。
  • 共有領域を描画パイプラインごとに分離しました。YMM4 は動画出力・画像出力・アイテムエフェクトの編集画面のそれぞれで専用のグラフィックデバイスを生成するため、デバイスのインスタンスを鍵とした ConditionalWeakTable で領域を引き当てることで、出力は毎回空の領域から始まり、出力の終了後は領域が GC で解放されます。編集中のプレビューはアプリケーションの実行中を通して同じデバイスを使うため、領域が維持されます。
  • 同じフレームの同じ名前への書き込みが競合した場合、レイヤー番号の大きい書き込みを採用し、同じレイヤーでは後から確定した書き込みで置き換えます。並列評価でも結果が発行順序に依存しません。
  • SceneValueSession の開始時にスコープとレイヤー番号を受け取るようにし、正常終了時の発行でフレーム番号とレイヤー番号を付けて履歴へ即時確定します。書き込みバッファと読み取りメモ化、参照の記録は従来どおりです。
  • LuaScriptEffectProcessor のフレームキャッシュの検証を履歴照合へ変更しました。記録した読み取り結果を現在のフレームの履歴と照合し、食い違うフレームでは再実行します。書き込みは履歴として保持され再発行が不要になったため、共有値を書き込んだフレームのキャッシュ再利用の禁止を撤廃しました。
  • 各名前の最新の組を除いた履歴のメモリ使用量を追跡し、16MB を超えた場合は全体で最も古い組から決定論的に間引きます。
  • NativeProtocol と worker.lua に変更はありません。ワーカーの実行内キャッシュのセマンティクスは新しいモデルとそのまま一致します。
  • テストは 3086 件です。v1.13.1 の 3080 件から、履歴の可視性とランダムシークの決定論、後戻りシークでの挿入、レイヤーによる競合解決、nil の削除記録、再発行の冪等性、履歴メモリの上限、スコープの分離の検証を追加しました。

v1.13.1

Choose a tag to compare

@github-actions github-actions released this 02 Jul 23:06

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

v1.13.0 で追加した scene.set / scene.get の値の見え方を、アイテムの評価順序に依存しない確定的なモデルへ変更したリリースです。
同じフレームの中ではどのアイテムから評価しても scene.get が返す値が変わらないようにし、他のアイテムが書き込んだ値は次のフレームの評価から読み取れるようにしました。あわせて、スクリプトがエラーやタイムアウトで終了したフレームの書き込みを共有領域へ反映しないようにし、動画出力の開始時に共有領域をリセットし、1 つのシーンに保存できる名前の数へ上限を設けました。
呼び出しの書き方と関数の引数に変更はありません。scene.set / scene.get を使わないスクリプトへの影響はありません。


動作の変更

1. scene.set / scene.get の値の見え方を確定的なモデルへ変更

これまで scene.set は共有領域へ即座に書き込んでいたため、同じフレーム内で別のアイテムが書き込んだ値を読み取れるかどうかが、アイテムの評価順序に左右されていました。
今回から、各アイテムの書き込みはそのアイテムの実行が正常に終わった時点でまとめて共有領域へ反映し、他のアイテムからは次のフレームの評価で読み取れるようにしました。
自分のスクリプトが書き込んだ値は、同じ実行の中で直後の scene.get からそのまま読み取れます。
同じフレームの中では、アイテムがどの順番で評価されても scene.get が返す値は変わりません。フレーム単位のスナップショットを読み取るため、評価順序に依存しない結果になります。

2. スクリプトがエラーまたはタイムアウトで終了したフレームは書き込みを反映しない

スクリプトがコンパイルエラー、実行時エラー、またはタイムアウトで終了したフレームでは、その実行の中で行った scene.set の書き込みを共有領域へ反映しないようにしました。
正常に最後まで実行できたフレームの書き込みのみが、次のフレームの評価へ引き継がれます。

3. 動画出力の開始時に共有領域をリセット

動画出力を開始すると、シーンの共有領域を空の状態から始めるようにしました。
編集画面での試行の途中経過が出力へ持ち込まれることがなくなり、同じプロジェクトを出力すれば毎回同じ結果になります。

4. 1 つのシーンに保存できる名前の数へ上限を追加

1 つのシーンに保存できる名前を 4096 個までとしました。
上限に達した後に新しい名前へ書き込もうとした場合、その書き込みは無視します。すでに保存されている名前への上書きと、nil を渡した削除は、上限に関わらず行えます。


互換性・後方互換

  • 呼び出しの書き方と関数の引数に変更はありません。scene.set / scene.get を使わないスクリプトへの影響はありません。
  • 同じフレーム内で他のアイテムの書き込みを読み取っていたスクリプトは、読み取れる値が 1 フレーム前の値へ変わります。フレームをまたいで値を受け渡す使い方には影響しません。
  • 名前と文字列値を UTF-8 換算で 4095 バイトへ切り詰める仕様は、v1.13.0 から変わりません。
  • 共有値はメモリ上にのみ保持し、プロジェクトファイルには保存しません。YMM4 を終了すると失われます。

内部実装

  • SceneSharedValues をシーンごとの世代スナップショット方式へ再設計しました。確定済みの値を保持する辞書と、次の世代へ反映する保留中の書き込みを保持する辞書を分け、タイムラインのフレーム番号を世代として、世代が変わったときに保留中の書き込みを確定済みへ反映します。出力中は、出力へ入った直後と世代が前へ戻ったときに、両方の辞書を空にします。名前の正規化と値の正規化を静的メソッドとして切り出しました。
  • SceneValueSession を追加しました。1 つのアイテムの実行の間、書き込みをバッファへため、読み取った結果をメモ化し、参照した名前と結果を記録します。実行の開始でシーン識別子と世代と出力中かどうかを受け取り、正常終了時に書き込みをまとめて共有領域へ発行します。書き込みを優先して返すため、同じ実行の中では直後の scene.get が書き込んだ値を返します。
  • AviUtlScriptContext のシーン共有値のアクセスを SceneValueSession への委譲へ変更しました。LuaScriptEffectProcessor は実行の準備で BeginSceneValues を呼んでセッションを開始し、スクリプトが正常に終わった後に PublishSceneValues を呼んで書き込みを発行します。スクリプトが例外で終了したフレームでは PublishSceneValues へ到達しないため、書き込みは発行されません。
  • LuaScriptEffectProcessor のフレームキャッシュの検証を世代対応へ変更しました。キャッシュの再利用可否を判定する際、記録した読み取り結果を現在のフレームと出力状態に対応するスナップショットと照合します。
  • NativeProtocol と worker.lua のコールバックタグ領域を 4096 バイトから 8192 バイトへ拡張しました。文字列を保存する scene.set は名前と値を区切り文字を挟んで 1 つのタグ領域へ格納するため、名前と値をそれぞれ 4095 バイトまで、互いを切り詰めずに転送できるようにしました。
  • worker.lua の scene.get / scene.set へ実行内キャッシュを追加しました。同じ実行の中で同じ名前を繰り返し読み取る場合や、書き込んだ直後に読み取る場合に、共有メモリ経由の往復を行わずに手元の値を返します。キャッシュは各実行の開始で消去します。
  • worker.lua の名前と文字列値の切り詰めを UTF-8 の文字境界で行うようにし、管理側の 4095 バイトの切り詰めと結果を一致させました。
  • テストは 3080 件です。v1.13.0 の 3063 件から、ストアの世代と出力時リセットと容量上限の検証、SceneValueSession の可視性とトランザクション性の検証、scene テーブルのセッション経由の検証、ネイティブワーカーでの IPC 回数と最大長の往復の検証を追加しました。

v1.13.0

Choose a tag to compare

@github-actions github-actions released this 02 Jul 14:35

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

シーン単位で値を共有する scene.set / scene.get と、AviUtl 互換のグローバル関数を追加したリリースです。
アイテムやフレームをまたいだ値の受け渡しと、RGB / HSV による色計算、ビット演算、デバッグ出力を、MoonSharp とネイティブの両エンジンで同一に扱えるようにしました。
いずれも既存のスクリプトと API に影響しない追加で、従来の呼び出しはそのまま動作します。


新機能

1. シーン単位で値を共有する scene.set / scene.get を追加

scene.set(name, value) はシーン単位の共有領域へ値を保存し、同じシーン内のすべての Lua スクリプトエフェクトから scene.get(name) で参照できます。
アイテムやフレームをまたいで値を受け渡せるため、グローバル変数がフレーム間で保持されない制約を、共有領域を介して回避できます。
保存できる値は数値・文字列・真偽値で、nil を渡すと削除します。テーブルや関数などそれ以外の値は保存しません。
scene.get は未設定の名前に対して nil を返します。
名前と文字列値は UTF-8 換算で 4095 バイトを超える部分を切り捨てます。
共有値はシーンごとに独立しており、シーン識別子を鍵として YMM4 を終了するまでメモリ上に保持します。プロジェクトファイルには保存しません。
アイテム間の評価順序は保証しないため、同一フレーム内での書き込みと読み取りの順序に依存する作りは避けてください。
MoonSharp とネイティブのどちらのエンジンでも同一に動作します。

2. AviUtl 互換のグローバル関数を追加

グローバルスコープから RGB / HSV / OR / AND / XOR / SHIFT / debug_print を直接呼び出せるようにしました。
RGB(r, g, b) は RGB 各要素を 0xRRGGBB の色情報へ合成し、RGB(col) は色情報を r, g, b の 3 値へ分解します。RGB(r1, g1, b1, r2, g2, b2) は obj.time / obj.totaltime の進行に合わせて一色目から二色目へ直線的に変化する色情報を返します。
HSV も同様に色相・彩度・明度と色情報を相互に変換し、6 引数指定で時間変化します。色相は 0 から 360、彩度と明度は 0 から 100 の範囲で扱います。
OR / AND / XOR は 32bit 整数のビット演算で、小数は 0.5 ちょうどまでを切り捨てて整数化します(2.50 は 2、2.51 は 3)。
SHIFT(a, shift) は算術シフトで、shift が正で左シフト、負で右シフトします。
debug_print(text) は文字列を OutputDebugString() へ送信し、DebugView などで確認できます。スクリプトの実行エラーも自動で送信します。
これらの関数は MoonSharp とネイティブのどちらのエンジンでも同一の結果を返します。

3. エディタの入力補完へ追加

上記のグローバル関数と scene.set / scene.get を、スクリプトエディタの入力補完の候補へ追加しました。


互換性・後方互換

  • 既存のスクリプトの書き方と API に変更はありません。追加した関数と scene.set / scene.get はいずれも新規で、従来の呼び出しに影響しません。
  • これまで未対応だった scene.set / scene.get に対応しました。AviUtl の同名関数を使うスクリプトが、シーン内での値共有として動作します。
  • RGB / HSV / OR / AND / XOR / SHIFT / debug_print はグローバル名として追加されます。スクリプト側で同名のグローバルを定義した場合は、スクリプト側の定義が優先されます。
  • 共有値はメモリ上にのみ保持し、プロジェクトファイルには保存しません。YMM4 を終了すると失われます。

内部実装

  • SceneSharedValues がシーン識別子ごとに共有辞書を保持し、名前と文字列値を UTF-8 で 4095 バイトへ切り詰めます。
  • AviUtlScriptContext がシーン共有値の取得と書き込みを仲介し、読み取った名前と結果、書き込みの有無を記録します。
  • LuaScriptEffectProcessor は記録した読み取り結果と書き込みの有無をフレームキャッシュへ持ち込み、共有値を書き込んだフレーム、または読み取った値が現在値と食い違うフレームではキャッシュを使わず再実行します。
  • MoonSharp では AviUtlGlobalRegistrar がグローバル関数を、SceneTableRegistrar が scene.set / scene.get を登録します。時間変化の割合は obj.time / obj.totaltime から求めます。
  • ネイティブでは NativeProtocol へ scene 取得と設定のコールバック種別を追加し、LuaJitWorker が名前と値を共有メモリ経由でやり取りします。文字列は名前と値を区切って 1 つのタグ領域へ格納します。
  • worker.lua が scene.get / scene.set のブリッジと時間変化の割合の設定を行い、shim.lua が RGB / HSV / OR / AND / XOR / SHIFT / debug_print を実装します。
  • スクリプトのタイムアウトと実行時例外のメッセージも、debug_print と同じ OutputDebugString の経路へ送信します。
  • テストは 3063 件です。v1.12.0 の 3041 件から、シーン共有値の保存と削除と切り詰め、scene テーブルへの登録、グローバル関数のエンジン間の一致、ネイティブワーカーでの往復などの検証を追加しました。

v1.12.0

Choose a tag to compare

@github-actions github-actions released this 02 Jul 10:56

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

ネイティブレーンとカーネルの性能をまとめて引き上げたリリースです。プロセス間の
画素転送、draw 呼び出しの往復、スクリプト本文の転送と比較、getpixeldata の実装、
CPU カーネルの命令並列という経路ごとの無駄を系統的に削りました。あわせて、
カーネル抽出の検査漏れや math.fmod の剰余の種類など、結果の正しさに関わる不具合を
修正しました。全体の設計は「識別子と版数による変更検知」と「消費される境界での
遅延実体化」で統一しています。


改善

1. ネイティブレーンの画素転送を直結化

ネイティブレーンでは、Direct2D のステージングビットマップと共有メモリの間に中間の
バッファを挟んでいたため、入力の転送で 2 回、結果の読み戻しで 2 回の複製が毎フレーム
発生していました。本リリースでは両者をポインタで直結し、入力はステージングの Map から
共有メモリへ、結果は共有メモリから出力ビットマップの CopyFromMemory へ、それぞれ
1 回の複製で転送します。

1920×1080 の BGRA フレームは約 8.3MB で、複製量は毎フレーム約 33MB から約 17MB へ
半減します。開発機の実測ではこの規模の複製 1 回が約 0.4ms なので、画素を書き換える
スクリプトで 1 フレームあたり約 0.8ms、4K では単純比例で約 3.2ms を複製から削れる
計算です。draw 合成やバッファ置換のように従来形式のバッファが必要な経路に限り、
そこでだけ実体化します。

2. draw と drawpoly の呼び出しをリングバッファで一括化

ネイティブレーンの obj.draw と obj.drawpoly は、1 回の呼び出しごとにプロセス間の
イベント往復を行っていました。本リリースでは共有メモリ上のリングバッファへ書き溜め、
容量の 4096 件に達したときと実行の終わりにまとめて回収します。1 フレームに 1000 回
draw するスクリプトなら、往復は 1000 回から 1 回になります。

3. getpixeldata を平坦な配列の遅延反映へ変更

ネイティブレーンの getpixeldata は、添字 1 回の読み書きごとに座標の分解と除算、
乗算済み表現との変換を行っていました。本リリースでは取得時に全画素を一度だけ
変換して平坦な配列を作り、以後の読み書きは配列参照 1 回になります。書き込みは
putpixeldata または次の画素操作の時点でまとめてフレームへ反映します。1920×1080 の
全画素を添字で走査すると約 830 万回のアクセスになるため、1 回あたりの費用の削減が
そのまま効きます。

4. getpixeldata の添字ループをカーネルとして実行

getpixeldata で得た画素を添字のループで書き換える定型を、getpixel と setpixel の
定型と同じようにカーネルとして抽出し、CPU カーネルで実行するようにしました。従来
この形はネイティブレーンで実行され、ワーカーへの画素転送を伴っていました。抽出後は
転送そのものが不要になります。出力は MoonSharp とバイト単位で一致します。

5. CPU カーネルに SIMD の実行経路を追加し、採用を実測で自動判定

CPU カーネルに Vector256 で 4 画素を同時に評価するブロック経路を追加しました。
倍精度で完全一致を保てる加減乗除、床剰余、符号反転、abs、floor、ceil、sqrt、比較と
選択だけを対象とし、min や max、pow、三角関数を含むカーネルは従来のスカラ経路で
実行します。出力はスカラ経路とバイト単位で一致します。

SIMD が有利かどうかはカーネルの内容と実行環境に依存し、並列実行でメモリ帯域が
飽和する環境では不利になる場合すらあります。そこで GPU カーネルのセルフ検証と同じ
流儀で、採用を実測で自動判定します。最初の数フレームで両経路を交互に実行して時間を
計測し、各経路の初回は JIT の暖機として計測から除いたうえで、速かった経路を
プログラム単位で恒久採用します。両経路の出力はバイト単位で一致するため、判定中の
切り替えが結果に現れることはありません。

開発機の 1920×1080 での実測では、単一スレッドの評価はグレースケール相当のカーネルで
約 1.6 倍から 2 倍、比較選択を多く含む重いカーネルで約 1.2 倍から 1.5 倍になりました。
フレーム全体の処理は行単位の並列実行でメモリ帯域が支配的になるため差は縮まり、
判定前の強制 SIMD では重いカーネルが約 2 割遅くなる場合がありましたが、自動判定に
よって常に速い側の経路で実行されます。

6. スクリプト本文の転送と比較を変更検知へ変更

ネイティブレーンはスクリプト本文を毎フレーム UTF-8 へ変換して共有メモリへ書き込んで
いました。本文は最大 128KB あるため、変換と複製と配列の割り当てが毎フレーム発生して
いました。本リリースでは本文へ版数を振り、変更したフレームだけ転送します。ワーカー側の
コンパイル結果も版数で保持し、同じ本文の再コンパイルを行いません。

フレームキャッシュの鍵も同様に、スクリプト本文の文字列比較から参照の版数比較へ
変更しました。長いスクリプトほど毎フレームの比較費用が大きかったため、これも定数時間に
なります。

7. copybuffer の複製でバッファを再利用

MoonSharp レーンの obj.copybuffer は、コピーのたびに新しい配列を割り当てていました。
寸法が同じ間は既存の配列へ上書きするように変更し、毎フレーム呼び出すスクリプトの
GC 圧力を取り除きました。


不具合修正

getpixeldata の未反映の書き込みをフレーム置換時に破棄

obj.load や obj.copybuffer でフレームが置き換わった直後に、置換前の getpixeldata へ
書き込んだ未反映の内容が新しいフレームへ流し込まれることがありました。フレームの
置換時に未反映の書き込みを破棄するように修正しました。

getpixeldata の色の復元順序を getpixel と統一

MoonSharp レーンの getpixeldata が乗算済み表現から色を復元する際の計算順序が
getpixel と食い違っており、丸めで 1 階調ずれる可能性がありました。getpixel の順序へ
統一し、MoonSharp、ネイティブ、カーネルの三経路が同じ結果を返すようにしました。

カーネル抽出の検査漏れを修正

ループ変数や getpixeldata の参照名を内側のローカル変数が同じ名前で覆い隠す
スクリプトを誤って抽出し、結果が変わる可能性がありました。該当する形の抽出を拒否し、
従来の経路で実行するように修正しました。あわせて、getpixeldata への書き込み値が
0 から 255 へ収められずにカーネル化されていた点を、MoonSharp と同じ挙動へ修正
しました。

math.fmod の剰余の種類を修正

カーネル実行の math.fmod が床方式の剰余で計算されており、負の値を渡したときに
Lua の math.fmod と符号の異なる結果を返していました。被除数の符号を保つ切り捨て
方式へ修正し、MoonSharp およびネイティブレーンと一致させました。

draw リングの読み出し件数を容量へ制限

ホストが共有メモリ上の draw の件数をそのまま信頼していたため、値が壊れた場合に
リングの範囲外を読み出す可能性がありました。件数を容量で制限するように修正しました。


互換性・後方互換

  • スクリプトの書き方と API に変更はありません。
  • カーネル実行で math.fmod を負の値に使っている場合は結果が変わります。従来の結果が
    誤りで、修正後は MoonSharp と同じ結果になります。
  • SIMD 経路の出力はスカラ経路とバイト単位で一致します。対象外の演算を含むカーネルは
    従来のスカラ経路で実行するため、出力の正しさに妥協はありません。採用の自動判定は
    実行時間だけを比較するもので、どちらの経路が選ばれても結果は同一です。
  • getpixeldata の書き込みがフレームへ反映されるのは putpixeldata または次の画素操作の
    時点になりましたが、読み出しの直前に必ず反映されるため、観測できる結果は変わり
    ません。
  • ネイティブ実行環境が無い場合は、従来どおり MoonSharp で実行します。

内部実装

  • 転送の契約を PixelRegionAccess へ統一し、LuaJitWorker と PixelBufferManager を
    ポインタで直結しました。ワーカーが報告する結果寸法は共有メモリの容量で検査し、
    アップロード中に例外が起きた場合はワーカーを破棄して次回の実行で再起動します。
  • NativeProtocol へ draw リング領域とスクリプト版数のヘッダを追加しました。リングは
    1 件 24 個の倍精度値で 4096 件です。
  • worker.lua が getpixeldata の平坦な配列と遅延反映、リングへの書き溜めを行います。
  • SimdKernelCompiler が式木から Vector256 のブロック委譲を生成し、CpuKernel が
    4 画素単位のブロックと端数のスカラ処理を組み合わせます。ClampByte は Math.Clamp の
    分岐順序を ConditionalSelect で再現し、byte への変換もスカラと同一です。
  • CpuKernel の自己校正は、経路ごとに暖機 1 回と計測 3 回を交互に行い、累積時間の
    短い経路を採用します。判定はカーネルのインスタンスごとに一度だけ行い、以後は
    分岐しません。
  • KernelExtractor が getpixeldata の添字ループの定型を認識します。
  • テストは 3041 件です。v1.11.4 の 2994 件から、リングの順序と容量、遅延反映の整合、
    SIMD とスカラの一致、採用判定の収束と交互計測、抽出の拒否、転送領域の容量保証
    などの検証を追加しました。
    Direct2D の実描画を伴う直結転送の最終確認は、従来の GPU 経路と同様に YMM4 上が
    対象です。

v1.11.4

Choose a tag to compare

@github-actions github-actions released this 02 Jul 05:00

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

毎ピクセル処理のスクリプト(カーネル)の実行先を、GPU と CPU から自動で選べるように
したリリースです。これまで GPU カーネルは --!gpu を明示したときだけ使っていましたが、
指定が無いときも利用できるかを自動で判断し、利用できる場合は GPU で実行します。正確性を
最優先し、初回に実機の GPU で CPU カーネルとの出力一致を検証し、許容差に収まった
プログラムだけ GPU で実行します。あわせて、GPU カーネルと CPU カーネルで食い違って
いた HLSL の座標原点と出力の丸めを、CPU カーネルに合わせて修正しました。


改善

1. カーネルの GPU/CPU 自動選択

これまで毎ピクセル処理のスクリプトは、--!gpu を明示したときだけ GPU カーネルで実行し、
指定が無いときは CPU カーネルで実行していました。本リリースでは、指定が無いときも
GPU カーネルを利用できるかを自動で判断し、利用できる場合は GPU で実行します。GPU
カーネルは CPU カーネルが必要とするピクセルの読み戻しとアップロードを伴わないため、
そのぶん高速です。実行先はプログラム単位で一度だけ決まり、フレームや画像サイズによって
切り替わらないため、途中で結果がちらつくことはありません。

2. 実行時のセルフ検証で正確性を担保

GPU カーネルを初めて構築したとき、固定の 64×64 の検証用画像を実機の GPU で処理し、
その結果を CPU カーネルの結果と比較します。全チャンネルの差が許容範囲に収まった
プログラムだけを GPU で実行し、収まらない場合や検証を実行できない場合は CPU カーネルで
実行します。GPU の出力が CPU カーネルと食い違うことはありません。検証の結果はログに
記録します。


不具合修正

GPU カーネルの座標原点のずれを修正

GPU カーネルの HLSL は、ピクセル座標を「テクスチャ座標 × 寸法」で求めていました。
テクスチャ座標はピクセルの中心を指すため、求まる座標は CPU カーネルが用いる整数の
添字より 0.5 大きく、ループ変数 xy を参照するスクリプトで結果がずれていました。
テクスチャ座標から 0.5 を引くように変更し、CPU カーネルの整数座標と一致させました。

GPU カーネルの出力の丸めを修正

Direct2D は出力を四捨五入で 8 ビットへ量子化する一方、CPU カーネルは切り捨てていた
ため、両者に系統的な 1 階調のずれがありました。シェーダ側で各チャンネルを切り捨てて
から量子化するように変更し、丸め方を CPU カーネルへ統一しました。


互換性・後方互換

  • スクリプトの書き方と API に変更はありません。
  • --!cpu は従来どおり CPU カーネルで実行します。--!gpu は GPU カーネルで実行しますが、
    検証に通らない場合は CPU カーネルへ切り替え、一度だけ警告を記録します。
  • 指定の無いカーネルは、検証に通れば GPU、通らなければ CPU で実行します。いずれも
    出力は CPU カーネルと許容差の範囲で一致します。
  • GPU カーネルは浮動小数点で計算するため、CPU カーネルと 1 階調程度異なることが
    あります。この差が許容範囲に収まることを検証で確認したプログラムだけを GPU で
    実行します。
  • GPU を利用できない環境では、従来どおり CPU カーネルで実行します。

内部実装

  • HlslKernelEmitter の座標を「テクスチャ座標 × 寸法 - 0.5」へ、出力の各チャンネルを
    floor(clamp(...)) へ変更し、CPU カーネルの整数座標と切り捨てへ揃えました。
  • GpuKernelVerify を追加しました。検証用画像を効果で描画して読み戻し、
    CpuKernel の結果と比較します。差が許容範囲に収まらない場合は GPU カーネルを
    採用しません。
  • LuaScriptEffectProcessorGetGpuKernel は検証に通った GPU カーネルだけを返し、
    判定をプログラム単位でキャッシュします。ExecuteKernelLane は指定が無いときと
    --!gpu のときに検証済みの GPU カーネルを優先し、無ければ CPU カーネルで実行します。
  • テストへ HLSL の座標原点と出力の丸めを検証するケースを追加しました(全 2994 件)。
    GPU カーネルの実行と検証は実機の GPU が必要なため、YMM4 上での確認が対象です。

v1.11.3

Choose a tag to compare

@github-actions github-actions released this 02 Jul 04:21

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

v1.11.2 で GPU 実行へ切り替えた tempbuffer への描画合成について、実行時の安定性を高め、
GPU 描画経路のリソースの後始末を整えたリリースです。GPU 合成をピクセルの読み出しと同じ
セマフォで直列化し、スクリプトのタイムアウトで破棄されたワーカースレッドの合成が後続
フレームと競合しないようにしました。あわせて、合成の契約をコマンド単位で委譲できる形へ
変更し、GPU で扱える寸法の上限を超えるバッファはそのコマンドだけ CPU 合成で処理する
ようにしました。さらに、GPU 描画経路で毎フレーム発生していたネイティブ参照の漏れを
解消しました。


改善

1. GPU 合成のスレッド安全性を強化

GPU での tempbuffer 合成を、ピクセルの読み出しと同じセマフォで直列化しました。
MoonSharp のスクリプトは専用のワーカースレッドで実行されるため、実行時間が上限を
超えてタイムアウトが発生すると、そのスレッドは破棄されて次回実行時に新しいスレッドが
生成されます。破棄されたスレッドに実行中の GPU 合成が残っていても、後続フレームの
DeviceContext の利用と競合しないようにしました。

2. GPU の上限を超えるバッファをコマンド単位で CPU 合成へ

GPU で扱える寸法の上限を超える合成は、そのコマンドだけ従来の CPU 合成で処理する
ようにしました。上限を超えたことを理由に GPU 合成全体が無効化されることはありません。
上限以下のサイズの後続コマンドは、引き続き GPU で合成します。


不具合修正

GPU 描画経路のネイティブ参照の漏れを解消

Vortice の TargetOutput のゲッターは、呼び出しのたびに参照数を増やした新しい
ラッパーを返します。従来はこのラッパーを毎フレーム生成したまま破棄しておらず、ネイティブ
の参照が少しずつ漏れていました。取得した Target を復元後に破棄し、効果の Output
生成時に一度だけ取得してキャッシュするように変更して、毎フレームのラッパー生成と
ネイティブ参照の漏れを無くしました。長時間のレンダリングでのメモリの使用が安定します。


互換性・後方互換

  • スクリプトの書き方と API に変更はありません。drawtarget の指定方法と描画結果の
    意味論は従来どおりです。
  • GPU を利用できない環境では、従来と同じ CPU 合成で動作します。
  • GPU で扱える寸法の上限を超える tempbuffer への合成は CPU 合成で処理し、結果は
    従来の CPU 合成と同じになります。
  • GPU 合成は浮動小数点で丸めるため、tempbuffer への合成結果が CPU 合成と 1 階調程度
    異なることがあります。ネイティブエンジンの tempbuffer 合成は従来どおりワーカー内の
    CPU で実行されるため、丸めの違いによりエンジン間で合成結果がごく僅かに異なることが
    あります。
  • framebuffer への描画合成は従来どおり GPU で実行され、意味論に変更はありません。

内部実装

  • 合成の契約 IBufferCompositorComposeTryCompose へ変更しました。合成器が
    処理を引き受けなかったときは false を返し、AviUtlScriptContext
    FallbackCompositor はコマンド単位で次の合成器へ委ねます。
  • SynchronizedCompositor を追加しました。内側の合成器の呼び出しを、指定した
    セマフォで直列化します。LuaScriptEffectProcessorHardwareCompositor
    ピクセル読み出し用のセマフォで包み、GPU 合成とピクセルの読み出しが同じ
    DeviceContext を同時に触らないようにしました。
  • HardwareCompositor へ寸法の上限 8192 を設け、合成元と合成先のいずれかがこれを
    超える場合は処理を引き受けずに false を返すようにしました。
  • FallbackCompositor は、GPU の合成器が例外を投げたときだけ CPU の合成器へ恒久的に
    降格し、通知コールバックを一度だけ呼び出します。合成器が処理を引き受けずに false
    を返した場合は降格として扱わず、そのコマンドだけ CPU 合成へ委ねます。
  • SoftwareCompositor を静的クラスから共有インスタンス SoftwareCompositor.Instance
    へ変更しました。合成の数学に変更はありません。
  • Vortice の TargetOutput のゲッターがラッパーを都度生成する問題へ対応しました。
    HardwareCompositorDrawCompositorPixelBufferManager は取得した Target
    復元後に破棄し、DrawCompositorPixelBufferManagerGpuKernel は効果の Output
    を生成時に一度だけ取得してキャッシュします。
  • テストへ SynchronizedCompositorTests を追加し、FallbackCompositor の引き受け拒否
    の経路と SoftwareCompositorTryCompose ディスパッチの検証を加えました
    (全 2992 件)。HardwareCompositor の描画出力はテスト環境で Direct2D を実行できない
    ため、YMM4 上での確認が対象です。

v1.11.2

Choose a tag to compare

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

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

tempbuffer への描画合成を GPU 実行へ置き換えたリリースです。MoonSharp エンジンで
obj.draw / obj.drawpolytempbuffer へ行う合成を、CPU のピクセルループから
Direct2D による GPU 合成へ変更しました。GPU を利用できない環境では従来の CPU 合成へ
自動的に切り替わります。あわせて、描画合成の変換行列の計算を一元化し、合成レーンの
ユニットテストを追加しました。


新機能・機能改善

1. tempbuffer への描画合成を GPU 実行へ変更

MoonSharp エンジンで obj.setoption("drawtarget", "tempbuffer") を指定した際の
obj.draw / obj.drawpoly の合成を、GPU で実行するようにしました。

  • 合成の意味論は従来と同一です。乗算済みアルファのソースオーバー、不透明度の乗算、
    antialias によるリニア・ニアレストの切り替えをそのまま維持しています。
  • GPU での合成に失敗した場合は従来の CPU 合成へ自動的に切り替わり、ログへ一度だけ
    警告を出します。切り替え後の動作は従来と完全に同じです。
  • 大きな tempbuffer へ繰り返し合成するスクリプトで、毎フレームの CPU 負荷が
    下がります。

2. 描画合成の変換行列を一元化

obj.draw の ox / oy / zoom / aspect と obj.drawpoly の 4 頂点から合成の変換行列を
求める処理を 1 箇所へ集約し、framebuffer への合成と tempbuffer への合成が同じ
定義を共有するようにしました。拡大率が 0 になる描画コマンドは、どちらの描画先でも
合成をスキップします。

3. ドキュメントの更新

内蔵ドキュメント(LuaScript/docs/LuaScript.*.txt)・README・サイトのドキュメントへ、
tempbuffer への合成が MoonSharp では GPU で実行されることと、GPU を利用できない
環境では CPU の合成へ自動的に切り替わることを各言語で追記しました。


互換性・後方互換

  • スクリプトの書き方と API に変更はありません。drawtarget の指定方法・描画結果の
    意味論は従来どおりです。
  • GPU を利用できない環境では、従来と同じ CPU 合成で動作します。
  • GPU 合成は浮動小数点で丸めるため、tempbuffer への合成結果が従来の CPU 合成と
    1 階調程度異なることがあります。ネイティブエンジンの tempbuffer 合成は従来どおり
    ワーカー内の CPU で実行されるため、丸めの違いによりエンジン間で合成結果がごく僅かに
    異なることがあります。
  • framebuffer への描画合成は従来どおり GPU で実行され、変更はありません。

内部実装

  • 合成の契約 IBufferCompositor を追加し、AviUtlScriptContexttempbuffer 合成が
    注入された合成器を使うようにしました。既定は CPU の SoftwareCompositor で、
    ネイティブレーンとテストの動作は変わりません。
  • HardwareCompositor を追加しました。PixelBufferManager と同じ手順で、合成元と
    合成先のアップロード、ソースオーバーでの描画、CPU 読み取り可能なステージング
    ビットマップ経由の読み戻しを行います。ビットマップはサイズ単位でキャッシュします。
  • FallbackCompositor を追加しました。GPU の合成器を優先し、初回の例外で恒久的に
    CPU の合成器へ降格して、通知コールバックを一度だけ呼び出します。
  • SoftwareCompositor を静的クラスからインスタンスクラスへ変更し、既存の合成処理を
    そのまま契約の実装として保持しました。合成の数学に変更はありません。
  • 変換行列の構築を DrawTransform.TryResolve へ集約し、DrawCompositor
    HardwareCompositor の双方が同じ数学を共有するようにしました。
  • LuaScriptEffectProcessorCreateEffect とタイムアウト後のコンテキスト再生成で
    合成器を注入するようにしました。
  • テストへ DrawTransformTestsFallbackCompositorTests と、SoftwareCompositor
    Compose ディスパッチの検証を追加しました(全 2987 件)。HardwareCompositor
    描画出力はテスト環境で Direct2D を実行できないため、YMM4 上での確認が対象です。

v1.11.1

Choose a tag to compare

@github-actions github-actions released this 01 Jul 23:45

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

実行性能を全面的に改善したリリースです。指定子を書いていないスクリプトの既定エンジンを
高速ランタイム(LuaJIT)へ変更し、ネイティブ実行のピクセル転送を初回アクセス時のみに
遅延化しました。あわせて、入力画像のサイズ変更でワーカープロセスを再起動しないように
変更し、共有メモリのピクセル転送をポインタ直接コピーへ置き換えています。
内蔵ドキュメント・README・サイトのドキュメントも各言語で更新しました。


新機能・機能改善

1. 既定エンジンを高速ランタイム(LuaJIT)へ変更

指定子を書いていないスクリプトを、native フォルダが配備されている場合に LuaJIT で
実行するようにしました。

  • 自ピクセル完結のピクセル写像は、従来どおり CPU カーネルへ変換して実行します。
  • native フォルダが配備されていない場合と空のスクリプトは、従来どおり MoonSharp で
    実行します(未配備の場合はログへ一度だけ警告を出します)。
  • --!moonsharp を書くと、従来どおり MoonSharp を強制できます。
  • 数式・描画ループが重いスクリプトが大幅に高速化されます(内部計測で数十倍)。

2. ネイティブ実行のピクセル転送を遅延化

ネイティブ実行で、スクリプトがピクセルへ初めてアクセスした時点でのみ GPU→CPU の
読み戻しと共有メモリへの転送を行うようにしました。

  • obj.getpixel / obj.setpixel / obj.getpixeldata / obj.copybuffer の作業画像読み取り、
    tempbuffer への描画合成が転送の対象です。
  • ピクセルへアクセスしないスクリプトでは転送を行いません(内部計測で 1080p の
    変形スクリプトが約 12ms/フレームから約 0.13ms/フレームへ短縮)。
  • ピクセルへアクセスするスクリプトの転送回数は毎フレーム 1 回のままで、挙動は
    変わりません。

3. ワーカープロセスの永続化

入力画像のサイズが変わってもネイティブワーカーを再起動しないようにしました。

  • 共有メモリは確保済みの容量が不足しない限り使い回し、容量は縮小しません。
  • 従来はサイズが変わるたびにプロセスの再起動(数十ミリ秒)と JIT の再コンパイルが
    発生していました(内部計測でサイズが毎フレーム変わる場合に約 0.25ms/フレームへ短縮)。
  • 文字列パラメータの容量が縮小方向へ変化しても再起動しません。

4. 共有メモリ転送の高速化

ピクセル領域の転送を、アクセサ経由のコピーからポインタ直接コピーへ置き換えました。
内部計測で 1080p の転送が片道約 12ms から約 2ms へ短縮され、ピクセルを扱う
スクリプトの毎フレームの転送コストが下がります。

5. ネイティブ実行のグローバル変数を MoonSharp と整合

  • time / frame / totalframe / framerate / layer / timelineframe /
    timelinetime を、ネイティブ実行でも裸のグローバル変数として参照できるようにしました。
  • スクリプトが定義したグローバル変数と、obj / scene / ymm4 テーブルへ追加した
    キーを、ネイティブ実行でも各フレームの実行開始時に取り除くようにしました。

6. ドキュメントの更新

内蔵ドキュメント(LuaScript/docs/LuaScript.*.txt)・README・サイトのドキュメントを
更新し、既定エンジンの変更とピクセル転送の遅延化を各言語へ反映しました。


互換性・後方互換

  • 既定エンジンの変更後も、--!moonsharp で従来の MoonSharp を強制できます。
  • native フォルダが配備されていない環境では、従来どおりすべて MoonSharp で実行されます。
  • CPU カーネルと LuaJIT の出力結果は従来どおり MoonSharp と一致します。GPU カーネルは
    従来どおり --!gpu の明示指定のみで使われます。
  • bit32 の範囲外の特殊ケースと math.random の乱数列は、従来からのネイティブ実行と
    同様にエンジン間で異なります。エンジン非依存の乱数には anim.rand を使用してください。
  • ピクセル転送の遅延化によるスクリプトの挙動の変化はありません。転送が発生する
    タイミングが「実行開始時」から「初回アクセス時」へ変わるのみです。

内部実装

  • ScriptDirective.ResolveAuto の既定を Native へ変更しました。空のスクリプトは
    ワーカーの起動を避けるため MoonSharp のままです。
  • ネイティブプロトコルへ CbKindRequestPixels を追加し、ワーカーがピクセルを初めて
    参照した時点でホストへ転送を要求するようにしました。worker.luaensurePixels
    ピクセルへ触れる API すべてを保護し、「変更あり ⇒ ピクセル領域が有効」の不変条件を
    維持します。
  • LuaJitWorker.Execute はピクセル配列の代わりに読み込み関数を受け取り、変更が
    あった場合のみ結果配列を返す契約へ変更しました。ホスト側の読み込みはメモ化され、
    同一フレーム内で 2 回読み戻すことはありません。
  • EnsureWorker の再起動判定を寸法一致から容量ベースへ変更し、共有メモリの確保量を
    単調増加としました。ResolveStringCapacity から縮小処理を削除しました。
  • ピクセル領域の転送を MemoryMappedViewAccessor.WriteArray / ReadArray から
    AcquirePointerBuffer.MemoryCopy による直接コピーへ置き換えました。
  • worker.luacaptureKeys / resetExtraKeys を追加し、サンドボックスと
    obj / scene / ymm4 の追加キーを毎フレーム取り除くようにしました。裸のグローバル
    変数は loadFields で設定します。
  • LuaScriptEffectProcessor の毎フレーム処理から、ピクセルローダーとネイティブ
    コールバックのクロージャ生成、ディレクティブの再解析を取り除きました。
  • ネイティブ往復テストへ、転送の遅延化(変形スクリプトは転送 0 回・ピクセル
    スクリプトは 1 回)、サイズ変更をまたぐワーカーの永続化、裸のグローバル変数、
    グローバル変数のリセットの検証を追加しました。

v1.11.0

Choose a tag to compare

@github-actions github-actions released this 01 Jul 13:31

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

AviUtl 互換の描画 API を拡張したリリースです。obj.draw / obj.drawpoly の合成モード、
作業画像の出力可否を切り替える draw_state、描画先を tmp バッファへ切り替える
drawtarget、アンカー座標を Lua 変数として扱う obj.setanchor を追加しました。
MoonSharp とネイティブの両エンジンで同じ API を使えるようにし、内蔵ドキュメントも
各言語で更新しました。


新機能・機能改善

1. obj.setoption("blend", 合成モード)

obj.draw / obj.drawpoly の合成モードを obj.setoption("blend", 番号) で指定できるように
しました。

  • 番号は YMM4 のプロパティパネルにある「合成モード」の並びと同じで、0 から始まります。
  • 0 は通常、1 はディザ合成、2 は比較(暗)、3 は乗算、4 は焼き込みカラー、5 は
    焼き込み(リニア)、6 は比較(明)、7 はスクリーン、8 は覆い焼きカラー、9 は
    覆い焼き(リニア) - 加算、10 は加算、11 はオーバーレイ、12 はソフトライト、13 は
    ハードライト、14 はビビッドライト、15 はリニアライト、16 はピンライト、17 は
    ハードミックス、18 は差分、19 は除外、20 は減算、21 は除算、22 は色相、23 は彩度、
    24 はカラー、25 は輝度、26 はカラー比較(明)、27 は背景、28 はカラー比較(暗)、
    29 は削除、30 は背景でクリッピング、31 は重ならない部分のみ、32 は色反転マスクです。
  • 範囲外の値や数値ではない値は通常として扱います。
  • MoonSharp とネイティブの両エンジンで、obj.drawobj.drawpoly の描画コマンドへ
    合成モードを渡します。

2. obj.setoption("draw_state", true / false)

このエフェクトが作業画像を出力するかどうかを、スクリプトから明示できるようにしました。

  • true を指定すると、setpixelobj.draw を使わない場合でも作業画像を出力します。
  • false を指定すると、このエフェクトの作業画像出力を抑制します。
  • 未指定の場合は従来どおり、ピクセル変更や描画コマンドの有無に従います。
  • MoonSharp とネイティブの両エンジンで動作します。

3. obj.setoption("drawtarget", "framebuffer" / "tempbuffer")

obj.draw / obj.drawpoly の描画先を切り替えられるようにしました。

  • "framebuffer" は既定の描画先です。描画コマンドはフレームバッファへ合成されます。
  • "tempbuffer" を指定すると、描画コマンドは作業用の tmp バッファへその場で合成されます。
  • obj.setoption("drawtarget", "tempbuffer", w, h) のように幅と高さを渡すと、そのサイズで
    tmp バッファを用意します。
  • tmp へ描いた結果は obj.copybuffer("obj", "tmp") で作業画像へ戻せます。
  • tempbuffer への合成は通常のソースオーバーで行い、blend はフレームバッファへの描画に
    適用します。
  • 描画先は毎フレーム既定の "framebuffer" へ戻ります。
  • MoonSharp とネイティブの両エンジンで動作します。

4. obj.setanchor(name, count [, option, ...])

アンカー座標を Lua 変数へ格納する obj.setanchor を追加しました。

  • name で指定した名前の Lua 変数へ、{x0, y0, x1, y1, ...} の配列を作成します。
  • "xyz" を指定した場合は {x0, y0, z0, x1, y1, z1, ...} の 3D 座標になります。
  • count は 0〜32 に制限され、戻り値は実際に設置した個数です。
  • 保存済みの座標がある場合はその値を使い、無い場合は 8 列の既定グリッド座標を使います。
  • "line" / "loop" / "star" / "arm" の線結び指定と、"xyz" の 3D 指定を受け付けます。
  • name"track" を指定するトラックバー連携は未対応で、0 を返します。
  • MoonSharp とネイティブの両エンジンで同じ座標テーブルを受け取れるようにしました。

5. 内蔵ドキュメントの更新

同梱される LuaScript/docs/LuaScript.*.txt を更新し、blenddraw_state
drawtargetobj.setanchor の説明を各言語へ追加しました。


互換性・後方互換

  • blend の既定値は 0 の通常です。指定しない既存スクリプトの合成結果は変わりません。
  • drawtarget の既定値は "framebuffer" です。フレームをまたいで前回の描画先は持ち越しません。
  • draw_state を指定しない場合は、従来どおりピクセル変更や描画コマンドに応じて出力します。
  • obj.setanchor を含むスクリプトは、自動判定では描画 API を使うスクリプトとして扱います。
    ネイティブで実行する場合は、従来どおり明示ディレクティブを使えます。
  • tempbuffer への描画は通常合成です。blend による合成モード指定は、フレームバッファへの
    obj.draw / obj.drawpoly に適用されます。
  • obj.setanchor("track", ...) によるトラックバー連携は未対応で、0 を返します。

内部実装

  • YMM4 の Blend 列挙値へ番号を対応させる BlendModeMap を追加し、DrawCommand
    合成モード番号を持たせました。
  • DrawCompositor は通常以外の合成モードで DrawImage / BlendImage を使い、Opacity の
    出力をキャッシュして毎描画ごとの COM オブジェクト確保を避けるようにしました。
  • SoftwareCompositor を追加し、MoonSharp 側で最近傍または線形補間による
    obj.draw / obj.drawpolytempbuffer 合成を行えるようにしました。
  • ネイティブワーカー側にも同等のソフトウェア合成処理を追加しました。
  • AviUtlScriptContextDrawStateOverride、描画先状態、アンカー入力元、アンカー要求一覧を
    追加しました。描画先が tempbuffer の場合は DrawCommand を通常の描画キューへ積まず、
    その場で tmp バッファへ合成します。
  • LuaAnchorPointAnchorSupport を追加し、アンカー数の制限、オプション解析、既定座標、
    保存済み座標の解決、ドラッグ後の座標更新を分離しました。
  • アンカー要求から生成した VideoEffectControllerDrawDescription.Controllers へ追加し、
    YMM4 のプレビュー操作へ渡すようにしました。
  • アンカー座標の変更をキャッシュキーへ含めるため、エフェクト側へ AnchorVersion を追加しました。
  • ネイティブプロトコルへ draw_state の書き戻しフィールドと setanchor コールバック種別を
    追加しました。LuaJitWorkerdraw / drawpoly の合成モード、draw_state
    setanchor の座標解決をワーカーとやり取りします。
  • ネイティブワーカーでは drawtarget 用の tmp バッファ、obj.setanchor
    draw_state の書き戻しを実装しました。
  • ネイティブワーカーの obj.copybuffer は、tmp や名前付きキャッシュへ書き込むときに
    バッファを複製するようにしました。
  • ScriptDirectiveobj.setanchor を描画 API として検出します。
  • NativeFieldMap から未使用の Epsilon 定数を削除しました。
  • AnchorSupportTestsSoftwareCompositorTests を追加し、ネイティブ往復テストへ
    blenddraw_statesetanchordrawtarget の検証を追加しました。