Repository navigation
[Bug] 型をまたぐ静的フィールドの初期化の環が、診断なく本文が触れる順に依存した値を捨てる #249
Description
領域
シェーダーのHLSLへの変換
パッケージの版数
ComputeWeave 2.6.0(既定ブランチの a8245449、v2.6.0 のタグと同じ木)の生成器に PR #243 の枝(5cce9d1f)を重ねた木で測りました。PR #243 の歩きは同じ型の中の順序だけを見るので、この形は既定ブランチでも同じです。
診断ID
無し。
期待した挙動
外の型が2つあり、それぞれの静的フィールドの初期化子が相手の型を読む形は、断られること。C# は型の静的初期化子を、その型が最初に触れられたときに走らせるので、この形の値は本文がどちらの型を先に触れるかで変わります。生成HLSLは取り込みが終わった順で1つの値を計算するので、片方の順にしか一致しません。
実際の挙動
診断なく通り、本文が後ろの型を先に触れる形では C# と違う値を計算します。
| 値 | C#(本文が B を先に触れる) | C#(本文が A を先に触れる) | 生成HLSL |
|---|---|---|---|
A.X |
1 | 11 | 11 |
B.Y |
10 | 10 | 10 |
C# の列はコンソールで走らせて読み、生成HLSLの列は生成物と同じ並びの手書きの HLSL を同梱の DXC(1.7.2308.7)と SDK 10.0.26100.0 の FXC へ当てて格納される値を読みました。実機では読んでいません。
再現手順
using ComputeWeave;
namespace Shaders;
internal static class A
{
public static readonly float W = 5.0f;
public static readonly float X = B.Y + 1;
}
internal static class B
{
public static readonly float Y = A.W * 2;
}
[ThreadGroupSize(DefaultThreadGroupSizes.X)]
[GeneratedComputeShaderDescriptor]
internal readonly partial struct Shader : IComputeShader
{
private readonly ReadWriteBuffer<float> buffer;
public void Execute()
{
this.buffer[0] = B.Y;
this.buffer[1] = A.X;
}
}C# では本文が B.Y を先に触れるので B の初期化子が走り、A.W を読んだ時点で A の初期化子が走ります。そこで A.X が B.Y を読みますが、B の初期化はまだ途中で Y は既定値の 0 なので、A.X は 1 です。生成HLSLは取り込みが終わった順に並び、B.Y が初期化された後に A.X が読むので 11 になります。
static const float Shaders_A_W = 5.0;
static const float Shaders_B_Y = Shaders_A_W * 2;
static const float Shaders_A_X = Shaders_B_Y + 1;切り分け
どちらの型にも、同じ型の後ろのフィールドを読む形はありません。PR #243 の歩きは、初期化子ごとにその型の順番がまだ来ていないフィールドの読み書きを報告するもので、この形では A.X の歩きが B.Y の初期化子へ入って A.W を読みますが、W は X より前なので報告しません。型をまたぐ環は、型の初期化がどちらから始まるかという別の軸です。
本文が A.X を先に触れる形では C# も 11 を計算し、生成HLSLと一致します。生成HLSLは本文の順を見ず、取り込みが終わった順で1つの並びを選びます。
何を保証すべきか
C# の値が本文の触れる順で変わる形は、生成HLSLが1つの順を選ぶ以上、写せません。取り込んだ型の初期化子が互いの型へ届く環は断るのが筋です。断る位置は、環を閉じる側の読みです。
測っていないこと
実機の値。Direct2D 側。3つ以上の型で閉じる環。
デバイス
統合GPU
アダプターとドライバー
Intel(R) Iris(R) Xe Graphics, 32.0.101.7085
Windowsの版数
Windows 11 Pro 24H2, 26200
.NET SDKの版数
10.0.400
デバッグレイヤーの出力
No response
その他
PR #243 の自己再評価で、歩きの模型「他の型の初期化子は、その型が最初に触れられたときに走る」の裏を取る中で見つけました。同じ型の中の順序(課題 #239、#240、#245)とは別の族なので、別の課題にします。
提出の前に
- 最新の公開版を使っています。
- 既存の課題を検索し、重複でないことを確認しました。
- 独自の ID3D12MemoryAllocator を設定していないことを確認しました。
Activity