Repository navigation
局所変数や引数に隠されるシェーダーのメンバーの読みと呼び出しを診断で断つ - #263
Conversation
PRレビュー / PR review変更 15 ファイル、コミット 9 件。 / 15 files, 9 commits. 検証の要否 / Verification required以下を走らせ、失敗した試験の名前と失敗の様子を変更前と突き合わせてください。総数だけで判断しないでください。 dotnet build ComputeWeave.sln -c Release -p:Platform=x64
dotnet test tests/ComputeWeave.Tests.SourceGenerators/ComputeWeave.Tests.SourceGenerators.csproj -c Release -p:Platform=x64
dotnet test tests/ComputeWeave.Tests.Internals/ComputeWeave.Tests.Internals.csproj -c Release -p:Platform=x64
dotnet test tests/ComputeWeave.Tests/ComputeWeave.Tests.csproj -c Release -p:Platform=x64
dotnet test tests/ComputeWeave.Tests.DeviceLost/ComputeWeave.Tests.DeviceLost.csproj -c Release -p:Platform=x64
dotnet test tests/ComputeWeave.D2D1.Tests.SourceGenerators/ComputeWeave.D2D1.Tests.SourceGenerators.csproj -c Release -p:Platform=x64
dotnet test tests/ComputeWeave.D2D1.Tests/ComputeWeave.D2D1.Tests.csproj -c Release -p:Platform=x64
dotnet test tests/ComputeWeave.D2D1.Tests.AssemblyLevelAttributes/ComputeWeave.D2D1.Tests.AssemblyLevelAttributes.csproj -c Release -p:Platform=x64ビルドエラーを出す診断を変えた場合は、アナライザーの試験に加えて解全体の検証が要ります。 慎重を要する箇所 / Guarded areas touched
寿命の追跡と危険の追跡は別々の保証です。一方を保っても他方が保たれるとは限りません。 公開APIまたは生成される記述子を変えた場合は、該当部分の互換性、生成の決定性、基準データの検査を走らせてください。 確認できた点 / Confirmed
これは自動の確認で、査読の代わりにはなりません。指摘は判断の材料であって、従う義務はありません。 |
…enShaderMember # Conflicts: # CONTRIBUTING.md # src/ComputeWeave.D2D1.SourceGenerators/AnalyzerReleases.Unshipped.md # src/ComputeWeave.SourceGenerators/AnalyzerReleases.Unshipped.md
…enShaderMember # Conflicts: # CONTRIBUTING.md
Summary / 概要
課題 #256 のうち、値が黙って変わる形を直します。生成器はシェーダー自身のメンバーを名前だけで書き出すので、
this.amountやShader.Factorのように限定子を付けて読んだメンバーは、同じ関数に同じ名前の局所変数や引数が在ると生成HLSLではそちらに隠されます。C# ではメンバーを指していた読みが局所変数を指し、シェーダーは C# と違う値を診断なく計算していました。この読みを、著者の書いた位置を名指す誤りの診断
CMPW0131(Direct2D側はCMPWD2D0104)で断ちます。見るのは、生成HLSLがその関数の中でその読みより前に宣言する局所変数と引数だけです。Linked issue / 関連する課題
#256 のフィールドの3形を直します。メソッドの呼び出しの3形は、限定子を落とす箇所そのものが #252 で入るので、#252 が入ったあとに同じ報告をその箇所へ足します。この PR では課題を閉じません。
Kind / 種別
Behavior change / 挙動の変更
新しい診断が2つ増えます。
CMPW0131とCMPWD2D0104で、どちらも誤りの重大度です。同梱する文書が述べる診断の件数が、計算側は113から114へ、Direct2D側は102から103へ変わります。計算側のCMPW0130は #257 が取っている番号で、Direct2D側のCMPWD2D0103は #257 が #258 と重なったCMPWD2D0102から取り直す番号として空けています。公開APIは変わりません。断つのは、限定子を付けて読んだシェーダーのメンバーの名前が、同じ関数の中でその読みより前に宣言された局所変数か引数と同じである形です。これまではどの形も診断なく建ち、装置では局所変数の値を読んでいました。
Verification / 検証
土台は
fa7f369e、実装のコミットは2fb7f200です。出したときの main は4e654727(#258 の併合)で、そこまでを枝へ併合してあります。増える10件と2件は、足した試験の本数と一致します。実装のコミットだけでも2つの試験プロジェクトが建つことを、そのコミットだけを別の作業ツリーへ取り出して確かめました。件数の検査と出荷の記録の検査は通り、乖離の監査は待ち行列が空であると述べます。
課題の形を測り直しました
課題 #256 で
7508bed3に通した形と装置の値をそのまま挙げます。限定子を落とす箇所は土台fa7f369eでも同じで、右の列はこの枝で同じ形を生成器へ通した結果です。float amount = 3; x = this.amount;(捕捉したフィールドは 10)CMPW0131float Factor = 3; x = Shader.Factor;(静的フィールドは 2)CMPW0131float Go(float amount) => this.amount + amount;をGo(1)(フィールドは 10)CMPW0131float amount = this.amount;CMPW0131。局所変数は自分の初期化子の中でも見えていますx = this.amount; Hlsl.Modf(2.5f, out float amount);CMPW0131。引数の中の宣言は本体の先頭へ持ち上げられるので、あとに書いても隠しますif (c) { Hlsl.Modf(2.5f, out float amount); } x = this.amount;CMPW0131。持ち上げられた宣言は、C# では見えないブロックの外でも隠しますx = this.amount; float amount = 3;float Factor = 3; static float Read() => Shader.Factor;float amount = 3;const float Scale = 2; float Scale = 3; Shader.ScaleDirect2D側は最初の形と、あとで宣言する形の2つを同じ試験で固定しました。判定は共有の書き換え器にあり、Direct2D側の試験はその経路が届いて自分の識別子で答えることを見ています。
解全体を建て直しました
ビルドエラーを出す診断なので、生成器が走る11プロジェクトを
-t:Rebuildと-p:EmitCompilerGeneratedFiles=trueで建て直し、11プロジェクトとも建ちました。この木にはこの断りに掛かるシェーダーが1つも無いということです。生成された1080件のファイルを土台と突き合わせると1078件が同一で、差が出た2件は Direct2D の記述子の埋め込みバイトコードの中だけです。同じコミットを2回建てても動く既知の2件で、新しい断りは生成物を変えていません。変異
実装をコミットしてから壊しています。壊す前の木は
dd0c7766です。thisを付けたフィールドの読みの箇所だけ戻す落ちるのはどれも足した試験だけで、既存の試験は1件も落ちません。1行目は持ち上げられる宣言を集める側を残しているので、持ち上げの2行を除く4件が落ちます。2行目と4行目は、断たない側の対照(あとで宣言する形と、局所関数の中の形)だけが落ちます。断つ側だけを測ると、位置も囲む関数も見ない実装で全部の行が緑になるので、この2つの対照が要ります。
Adapter and driver tested / 試したアダプターとドライバー: Intel(R) Iris(R) Xe Graphics, 32.0.101.7085(土台の3形の値を読み戻したときのものです。この枝の試験はデバイスを開きません)
Checklist / 確認
If this touches a guarded area / 慎重を要する箇所に触れる場合
Notes for the reviewer / 査読者への注記
断つ形をどう決めたか
生成HLSLがその関数の中で読みより前に宣言する名前だけを見ます。引数は常にそうです。局所変数は、読みより前に宣言されたものと、引数の中で宣言されたものです。後者は書き換え器が本体の先頭へ持ち上げるので、書いた位置に関わらず、C# では見えないブロックの中に在っても隠します。意味解析の名前の引き当てはブロックの外の宣言を返さないので、持ち上げられる宣言だけは関数の構文を歩いて集めています。読みより後ろで宣言された局所変数は、HLSL でも C# の名前解決と同じく宣言の位置から先しか見えないので、断ちません。断つと C# として正しく、生成HLSLも正しく建つ形を断つことになります。
局所関数の中の読みでは、囲む関数の局所変数を除きます。局所関数は別の関数として書き出されるので、囲む関数の局所変数はそこに在りません。意味解析が返す名前を、読みの位置を囲む宣言の記号で絞っています。
直した場所と、触っていない場所
報告は両方の書き換え器が派生する型に1つ置き、本文の書き換え器が限定子を落とす2箇所(
thisを付けたフィールド、型名を付けた静的フィールド)から呼びます。初期化子の書き換え器も型名を落としますが、初期化子には局所変数も引数も無いので呼びません。その旨をその場に書いています。定数は
__Shaders_Shader__Scaleのような名前で書き出され、局所関数は__Execute__Readのように改名されるので、どちらも隠されません。試験で固定しています。断つ以外の道を退けた理由
局所変数のほうを改名して読みを通す形も採れます。採らなかったのは、著者が同じ関数に C# では区別できる2つの名前を書いていて、HLSL ではそれを区別できないという事実を、生成器が黙って解決することになるためです。どちらを指すかを決めるのは著者で、名前を変えれば通ります。
main を併合しています
出す前に main が
4e654727(#258)へ進み、Direct2D側の記述子と未出荷の記録と乖離台帳の末尾が衝突したので、main を枝へ併合しました(7607c7fc)。衝突はどれも main の側を先に置く形で解き、#258 が足した診断の分だけ Direct2D側の件数を103へ数え直しています。併合後の先端で生成器の試験2本は、計算側 626、Direct2D側 249 で失敗0です。測っていないこと
Direct2D側の装置の値は読み戻していません。書き換え器は共有で、生成HLSLは同じ形になります。この枝の生成器の試験はデバイスを開きません。