Skip to content

シェーダー自身のメソッドの限定子付きの呼び出しを名前だけで書き出す - #252

Merged
routersys merged 6 commits into
mainfrom
dev/ComputeWeave.QualifiedShaderMethodCall
Sep 18, 2026
Merged

routersys merged 6 commits into
mainfrom
dev/ComputeWeave.QualifiedShaderMethodCall

Conversation

@routersys

@routersys routersys commented Sep 15, 2026 •

Copy link
Copy Markdown
Owner

Summary / 概要

課題 #244 を直します。シェーダー自身のメソッドを Shader.Twice() のように型名を付けて呼ぶと、型名がそのまま生成HLSLへ出て、シェーダーコンパイラが宣言の無い識別子として断ります。届くのは生成物の行を名指す CMPW0046 で、利用者は自分の書いた行を知らされません。Twice() と書けば通るので、書き方で建つかどうかが変わっていました。

型名だけではありません。名前空間や global:: を付けた形、using の別名を付けた形、インスタンスメソッドを this.Twice() と書いた形も同じです。this. を必ず付ける規約(StyleCop の SA1101)の下で書かれたシェーダーでは、インスタンスメソッドの呼び出しがすべてこの形になります。生成器はシェーダー自身のメソッドを最上位の関数として名前だけで書き出すので、どの限定子も生成HLSLの中では何も指しません。呼び出しを、生成器がそのメソッドを書き出す名前だけの形へ揃えます。

Linked issue / 関連する課題

Closes #244

Kind / 種別

  • Bug fix / 不具合修正
  • Analyzer or generator / アナライザーまたはジェネレーター

Behavior change / 挙動の変更

シェーダー自身のメソッドを限定子付きで呼ぶ形が建つようになります。これまではどの形も CMPW0046(Direct2D側は CMPWD2D0034)で止まっていたので、既に建っているシェーダーの生成HLSLは1バイトも変わりません。公開APIも診断の一覧も変わりません。

Verification / 検証

dotnet build tests/ComputeWeave.Tests.SourceGenerators/ComputeWeave.Tests.SourceGenerators.csproj -c Release -p:Platform=x64
dotnet tests/ComputeWeave.Tests.SourceGenerators/bin/x64/Release/net10.0/ComputeWeave.Tests.SourceGenerators.dll
dotnet build tests/ComputeWeave.D2D1.Tests.SourceGenerators/ComputeWeave.D2D1.Tests.SourceGenerators.csproj -c Release -p:Platform=x64
dotnet tests/ComputeWeave.D2D1.Tests.SourceGenerators/bin/x64/Release/net10.0/ComputeWeave.D2D1.Tests.SourceGenerators.dll
pwsh build/audit-upstream-divergence.ps1

土台は 39bf66af、実装のコミットは 3210e52f です。

スイート 変更前 変更後
計算側の生成器 合計557、失敗0 合計565、失敗0
Direct2D側の生成器 合計232、失敗0 合計235、失敗0

変更前の値は 2026-09-14 に v2.6.0 の a8245449 で採ったもので、そこから土台までに生成器のプロジェクトとその試験プロジェクトへ触れたコミットはありません。増える8件と3件は、足した試験の本数と一致します。実装のコミットだけでも2つの試験プロジェクトが建つことを、そのコミットだけを別の作業ツリーへ取り出して確かめました。乖離の監査は待ち行列が空であると述べます。

課題の形を族として測り直しました

土台で、限定子の付け方ごとに生成器を直接通し、生成HLSLの行と診断を採りました。計算側は15形、Direct2D側は10形です。

書いた形 土台 この枝
本文で Shader.Twice() CMPW0046(use of undeclared identifier 'Shader') Twice() になり建つ
自身の静的フィールドの初期化子で Shader.Twice() 同上 同上
取り込んだ外の型のメソッドから Shader.Twice() 同上 同上
取り込んだ外の型が持つ静的フィールドの初期化子から Shader.Twice() 同上 同上
取り込んだ補助型のインスタンスメソッドから Shader.Twice() 同上 同上
静的な局所関数から Shader.Twice() 同上 同上
引数を取る Shader.Twice(x) 同上 同上
名前空間を付けた Shaders.Shader.Twice() CMPW0046('Shaders') 同上
global::Shaders.Shader.Twice() CMPW0046('global') 同上
using S = Shaders.Shader; の S.Twice() CMPW0046('S') 同上
本文で this.Twice()(インスタンスメソッド) CMPW0046(invalid use of 'this' outside of a non-static member function) 同上
別のインスタンスメソッドから this.Twice() 同上 同上
対照。Twice()(静的、インスタンスの2形) 建つ 変わらない
対照。静的フィールドの Shader.Factor 建つ(#182) 変わらない

課題が挙げていたのは上の3行です。Direct2D側は、課題が測っていなかったので同じ形を10形で測り、限定子を付けた7形が CMPWD2D0034 になり、対照の3形が建つことを見ました。この枝では10形とも建ちます。

生成物を全数で突き合わせました

解全体の生成器が走る11プロジェクトを -t:Rebuild と -p:EmitCompilerGeneratedFiles=true で建て直し、生成されたファイルをすべて数え取って土台と比べています。

数えたもの 件数
生成されたファイル 1080
増えたもの、消えたもの 0
1バイト同一 1078
差が出たもの 2

差が出た2件はどちらも Direct2D の記述子で、差は埋め込まれたバイトコードの配列の中だけにあり、その前後の文字列はバイト単位で同一です。同じコミットを2回建てても動く2件で、#182 のときと同じものです。

変異

実装をコミットしてから壊しています。壊す前の木は 71d44e92 です。

変異 計算側 Direct2D側
補助が限定子を落とさない(修正前の形) 8 3
本文の書き換え器の静的メソッドの箇所だけ戻す 6 1
初期化子の書き換え器の箇所だけ戻す 1 1
this を付けた呼び出しの箇所だけ戻す 1 1
落とした限定子の代わりに記号の名前を書く 1 0

落ちるのはどれも足した試験だけで、既存の試験は1件も落ちません。1行目は足した11件がすべて落ち、2行目から4行目は3つの箇所がそれぞれ本文、初期化子、this の行を落とします。最後の行が落とすのは HLSL の予約語と重なる名前のメソッドの行だけです。宣言は __reserved__ を付けた名前で書き出されるので、記号の名前で呼び出しを書くとその1形だけが建ちません。歩いたあとの名前を残す形にしたのはそのためです。

Adapter and driver tested / 試したアダプターとドライバー: 走らせていません。生成器の試験はデバイスを開きません。

Checklist / 確認

  • 一つの論理的な変更にまとまっており、無関係な整理や整形を含まない。
  • 各コミットが単独でビルドできる。
  • 実装の変更と検証テストを別のコミットに分けた。
  • 既定ブランチへ入った、またはリリースタグが指すコミットを書き換えていない。
  • 変更は、その部分で既に確立された実装パターンに従っている。
  • public と protected のAPIに、リポジトリが求めるXMLドキュメントを付けた。
  • 既存のドキュメントコメントを維持した。
  • 暗黙の代替動作や互換性のための繕いを持ち込んでいない。
  • 無関係な依存関係を更新していない。
  • 上流から受け継いだファイルを変更したので、乖離台帳へ行を足し、実装のコミットを引きました。監査の道具は指摘を出しません。

If this touches a guarded area / 慎重を要する箇所に触れる場合

  • 試験が守るべき挙動そのものを動かしており、その挙動を意図的に壊すと落ちることを確認した。
  • 任意の待ち時間、固定の再試行回数、非同期処理の速さへの仮定に依存する試験が無い。
  • 生成される記述子に触れる変更なので、解全体の生成物を全数で突き合わせた。

Notes for the reviewer / 査読者への注記

直した場所

書き換え器は2つあり、本文と取り込んだ宣言を書き換えるものと、静的フィールドの初期化子を書き換えるものです。どちらもシェーダー自身の静的メソッドの呼び出しを「生成器が別の経路で書き出すので触らない」として素通りさせていました。限定子を落とす補助を、両方が派生する型に1つ置き、3箇所から呼びます。本文の書き換え器の静的メソッドの分岐、同じ書き換え器のインスタンスメソッドの分岐、初期化子の書き換え器の静的メソッドの分岐です。静的フィールドの型名を落とした #182 が2つの書き換え器に同じ分岐を置いたのが前例で、今回は3箇所になるので共有の置き場にしました。

静的フィールドと違って、メンバーアクセスの式を見る箇所では判定していません。呼び出しの対象になっているメンバーアクセスの式は意味解析の操作を持たず、フィールドの読みのように記号を引けないと読んでいます。呼び出しの操作は対象のメソッドを持つので、そこで判定します。

歩いたあとの名前を残しています

補助は呼び出しの式がメンバーアクセスの式なら、その右側の名前だけを残します。記号から名前を読み直してはいません。書き換え器は識別子の字句を歩くときに HLSL の予約語と重なる名前を __reserved__ 付きへ改名していて、メソッドの宣言もその名前で書き出されるためです。記号の名前で書く形は、sample のような名前のメソッドで建たなくなります。その形を変異として当て、予約語の行だけが落ちることを見ています。

断らずに直した理由

C# で同じ呼び出しを指す2つの書き方が同じHLSLになるのが、この生成器の他の箇所の振る舞いです。静的フィールドの Shader.Factor は型名を落として Factor になり、this.field は this を落とします。メソッドだけを診断で断つ形は、C# として正しい上に意味の曖昧さも無い書き方を断ることになるので採りませんでした。

触っていないもの

メソッドの名前そのものは変えていません。取り込んだ外の型のメソッドは今までどおり型名を含む名前へ改名され、シェーダー自身のメソッドは今までどおり名前だけです。this を落とすのはシェーダー自身のインスタンスメソッドの呼び出しだけで、補助型のインスタンスメソッドの呼び出しは受け手を残します。HLSL の構造体のメソッドはその形で呼ぶためです。

限定子を落とした名前が、同じ名前の局所変数や引数に生成HLSLで隠される形は、この変更の外です。この変更の自己再評価で測り、#256 として出しました。フィールドの読みでは #182 とそれ以前から値が黙って変わり、メソッドの呼び出しではこの変更の前も後も CMPW0046 で止まるので、この変更で悪くなった形はありません。

測っていないこと

実機で走らせていません。直したあとの生成HLSLは、名前だけで書いた呼び出しと同じ文字列になるので、生成器の試験がシェーダーコンパイラを通すことで建つことまでを見ています。生成器の試験2本以外のスイートは手元で走らせていません。解全体の生成物が土台と同一なので、実行時の挙動は変わらないためです。CI の8本は併合後の先端で通っています。

main を併合しています

出したあとで main が c050699d へ進み、乖離台帳の末尾の行が衝突したので、main を枝へ併合しました。衝突は main の行を先に、この枝の行をその後ろに置く形で解いています。併合後の先端 7508bed3 で生成器の試験2本を走らせ、計算側は合計575、Direct2D側は合計237で失敗0でした。併合した main の同じスイートは、2026-09-15 の手元の記録で567と234で、差は足した8件と3件です。乖離の監査は併合後も待ち行列が空です。

そのあとで main が fa7f369e へ進み(#243、#253、#254)、もう一度併合しました(7b459899)。衝突は乖離台帳の末尾と、静的メソッドの呼び出しを扱う2つの箇所です。#243 が同じ箇所から環の歩きの呼び出しを外していたので、その形の上に名前だけへ揃える1行を置き、台帳は main の行を先に置いて解きました。併合後の先端で生成器の試験2本を走らせ、計算側は合計624、Direct2D側は合計243で失敗0、足した8件と3件はどれも通っています。CI も4本とも通っています。

2026-09-17 に main が 4e654727(#258)へ進み、乖離台帳の末尾がまた衝突したので、三度目の併合をしました(6ca5a299)。解き方は同じで、併合後の先端で生成器の試験2本は計算側 624、Direct2D側 250 で失敗0です。

@routersys routersys added bug Something isn't working / 不具合が起きている analyzer or generator Analyzer or generator / アナライザーまたはジェネレーター labels Sep 15, 2026
@github-actions

github-actions Bot commented Sep 15, 2026 •

Copy link
Copy Markdown

PRレビュー / PR review

変更 6 ファイル、コミット 6 件。 / 6 files, 6 commits.

検証の要否 / Verification required

以下を走らせ、失敗した試験の名前と失敗の様子を変更前と突き合わせてください。総数だけで判断しないでください。
Run the following and compare the names and failure modes against the same suites before your change. Do not judge by totals alone.

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

ビルドエラーを出す診断を変えた場合は、アナライザーの試験に加えて解全体の検証が要ります。
If a diagnostic that produces build errors changed, verify the complete solution as well.

慎重を要する箇所 / Guarded areas touched

  • 寿命と破棄 / lifetime and disposal
    • src/ComputeWeave.SourceGeneration.Hlsl/SyntaxRewriters/HlslSourceRewriter.cs
    • src/ComputeWeave.SourceGeneration.Hlsl/SyntaxRewriters/ShaderSourceRewriter.cs
    • src/ComputeWeave.SourceGeneration.Hlsl/SyntaxRewriters/StaticFieldRewriter.cs

寿命の追跡と危険の追跡は別々の保証です。一方を保っても他方が保たれるとは限りません。
Lifetime tracking and hazard tracking are separate guarantees; preserving one does not preserve the other.

確認できた点 / Confirmed

  • 概要が書かれています。 / A summary is present.
  • 検証の結果が書かれています。 / Verification results are present.
  • 関連する課題が示されています。 / A linked issue is referenced.
  • 実装と検証テストが別のコミットに分かれています。 / Implementation and tests are in separate commits.

これは自動の確認で、査読の代わりにはなりません。指摘は判断の材料であって、従う義務はありません。
This is an automated check, not a substitute for review. Findings are input to a decision, not obligations.

@routersys
routersys merged commit ecca89f into main Sep 18, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

analyzer or generator Analyzer or generator / アナライザーまたはジェネレーター bug Something isn't working / 不具合が起きている

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] シェーダー型の静的メソッドを型名付きで呼ぶと、型名が生成HLSLに残る

1 participant