Import Tint changes from Dawn
Changes:
- 1b0266e46488b89b0a98ccb9c538d80cf7436c91 [tint][ir] Add Decode() overload that takes a protobuf st... by Ben Clayton <bclayton@google.com>
- efa2c60efb27f761a0c6e265c39d84d8371ecf28 [tint][type] Move private validity checks to static membe... by Ben Clayton <bclayton@google.com>
- f403412d25f8dd5d8f5e7c17232e53232c78ea78 [tint] Add constant::Invalid by Ben Clayton <bclayton@google.com>
- a6788bdfee90a790c2e4991ba795e2a8a61635eb [tint][core] Test that OOB Splat::Index() returns nullptr by Ben Clayton <bclayton@google.com>
- e4e461377ef4d02328f0f20b1ef79897f14d75b0 Tint: Add input_attachment as builtin type. by Le Hoang Quyen <lehoangquyen@chromium.org>
- 59eb7f31f5507fbddcfead963581523c78e69b8f Tint: Add input_attachment_index attribute class and def ... by Le Hoang Quyen <lehoangquyen@chromium.org>
- 81da61165530deb3049ad38a54309278c3565413 Make textureDimensions(texture_external) use the visible ... by Corentin Wallez <cwallez@chromium.org>
- 4e043e9741d726a213b588a369d0c5623370c910 [msl] Add ArrayLengthFromUniform transform by James Price <jrprice@google.com>
GitOrigin-RevId: 1b0266e46488b89b0a98ccb9c538d80cf7436c91
Change-Id: Idf601440a3444bcda88f60ebc28becf157d7d013
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/189661
Commit-Queue: James Price <jrprice@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: James Price <jrprice@google.com>
diff --git a/src/tint/cmd/fuzz/wgsl/dictionary.txt b/src/tint/cmd/fuzz/wgsl/dictionary.txt
index 39c4691..ffd821a 100644
--- a/src/tint/cmd/fuzz/wgsl/dictionary.txt
+++ b/src/tint/cmd/fuzz/wgsl/dictionary.txt
@@ -233,6 +233,7 @@
"if"
"info"
"input_attachment"
+"input_attachment_index"
"insertBits"
"instance_index"
"interpolate"
diff --git a/src/tint/lang/core/attribute.cc b/src/tint/lang/core/attribute.cc
index c6fa693..ead3dae 100644
--- a/src/tint/lang/core/attribute.cc
+++ b/src/tint/lang/core/attribute.cc
@@ -72,6 +72,9 @@
if (str == "id") {
return Attribute::kId;
}
+ if (str == "input_attachment_index") {
+ return Attribute::kInputAttachmentIndex;
+ }
if (str == "interpolate") {
return Attribute::kInterpolate;
}
@@ -120,6 +123,8 @@
return "group";
case Attribute::kId:
return "id";
+ case Attribute::kInputAttachmentIndex:
+ return "input_attachment_index";
case Attribute::kInterpolate:
return "interpolate";
case Attribute::kInvariant:
diff --git a/src/tint/lang/core/attribute.h b/src/tint/lang/core/attribute.h
index 28dd3d4..ecee8bc 100644
--- a/src/tint/lang/core/attribute.h
+++ b/src/tint/lang/core/attribute.h
@@ -59,6 +59,7 @@
kFragment,
kGroup,
kId,
+ kInputAttachmentIndex,
kInterpolate,
kInvariant,
kLocation,
@@ -86,9 +87,24 @@
Attribute ParseAttribute(std::string_view str);
constexpr std::string_view kAttributeStrings[] = {
- "align", "binding", "blend_src", "builtin", "color", "compute",
- "diagnostic", "fragment", "group", "id", "interpolate", "invariant",
- "location", "must_use", "size", "vertex", "workgroup_size",
+ "align",
+ "binding",
+ "blend_src",
+ "builtin",
+ "color",
+ "compute",
+ "diagnostic",
+ "fragment",
+ "group",
+ "id",
+ "input_attachment_index",
+ "interpolate",
+ "invariant",
+ "location",
+ "must_use",
+ "size",
+ "vertex",
+ "workgroup_size",
};
} // namespace tint::core
diff --git a/src/tint/lang/core/attribute_bench.cc b/src/tint/lang/core/attribute_bench.cc
index 924456c..171390e 100644
--- a/src/tint/lang/core/attribute_bench.cc
+++ b/src/tint/lang/core/attribute_bench.cc
@@ -115,55 +115,62 @@
"5O8",
"",
"DDbbB",
- "interpolaKKe",
- "33terpolate",
- "intoott6QQlate",
+ "input_attachment_indKKx",
+ "33nput_attacOmentindex",
+ "ittp6t_attaQQhmeoot_9ndex",
+ "input_attachment_index",
+ "nput_attac66ment_index",
+ "inpt_attachmOnx_inde6zz",
+ "input_attacyyment_index",
+ "nterZZHate",
+ "WWnerpolaq4e",
+ "interOOoate",
"interpolate",
- "66terpolate",
- "intxp66latOz",
- "yynterpolate",
- "HHnariZt",
- "iWW44rianq",
- "iOOvaiant",
+ "iYohepolte",
+ "inteolat",
+ "interoFate",
+ "invarwnt",
+ "GvrKanff",
+ "KKnqariant",
"invariant",
- "ivariYnt",
- "nvaria",
- "invaranF",
- "wocatio",
- "Kcatoff",
- "qocKKtion",
+ "invammia3t",
+ "invarint",
+ "inqriant",
+ "obbatibn",
+ "lcaiiio",
+ "loqatiOn",
"location",
- "lFcmmt3on",
- "locaion",
- "locaton",
- "ubbt_ube",
- "mstiius",
- "muqt_uOe",
+ "loTTatiovv",
+ "FFocation",
+ "fo00QPio",
+ "must_uPe",
+ "ust_uss77",
+ "mustCubbRe",
"must_use",
- "muTTt_usvv",
- "FFust_use",
- "fu00QPus",
- "siPe",
- "sis77",
- "CiRbbe",
+ "must_usXX",
+ "muOOt_CCse",
+ "sst_usL",
+ "sizX",
+ "sze",
+ "qq",
"size",
- "sizXX",
- "qCCOOO",
- "szL",
- "verteX",
- "verte",
- "qqrx",
+ "s22ze",
+ "iz0yz",
+ "VPzi",
+ "vrtCnn",
+ "ArqqHHx",
+ "ertex",
"vertex",
- "verte22",
- "vzzyrte",
- "eriVPx",
- "wokgroupnnsCze",
- "workgrouq_sizHA",
- "workgrup_size",
+ "vefKK",
+ "Pegge",
+ "verte",
+ "4orkgrouTT_Nizc",
+ "worgrouppp7lize",
+ "wgzrkgrup_siNe",
"workgroup_size",
- "forroupKKsize",
- "workrop_Pigge",
- "workgoup_size",
+ "uuorkgbop_sXXze",
+ "worgroup_size",
+ "worKgroQ_88ze",
};
for (auto _ : state) {
for (auto* str : kStrings) {
diff --git a/src/tint/lang/core/attribute_test.cc b/src/tint/lang/core/attribute_test.cc
index 4d4ed0d..c8eb487 100644
--- a/src/tint/lang/core/attribute_test.cc
+++ b/src/tint/lang/core/attribute_test.cc
@@ -67,6 +67,7 @@
{"fragment", Attribute::kFragment},
{"group", Attribute::kGroup},
{"id", Attribute::kId},
+ {"input_attachment_index", Attribute::kInputAttachmentIndex},
{"interpolate", Attribute::kInterpolate},
{"invariant", Attribute::kInvariant},
{"location", Attribute::kLocation},
@@ -107,27 +108,30 @@
{"HH", Attribute::kUndefined},
{"p", Attribute::kUndefined},
{"1ii", Attribute::kUndefined},
- {"interpoXXate", Attribute::kUndefined},
- {"intII99r55olate", Attribute::kUndefined},
- {"intaarpoSSrHHYe", Attribute::kUndefined},
- {"kkvHant", Attribute::kUndefined},
- {"jgaianRR", Attribute::kUndefined},
- {"inaianb", Attribute::kUndefined},
- {"locajion", Attribute::kUndefined},
- {"locaton", Attribute::kUndefined},
- {"loqion", Attribute::kUndefined},
- {"mustusNN", Attribute::kUndefined},
- {"usvvuse", Attribute::kUndefined},
- {"mut_QQse", Attribute::kUndefined},
- {"srf", Attribute::kUndefined},
- {"sije", Attribute::kUndefined},
- {"NNz2w", Attribute::kUndefined},
- {"vrtex", Attribute::kUndefined},
- {"rrertex", Attribute::kUndefined},
- {"vGrtex", Attribute::kUndefined},
- {"workgroup_sizFF", Attribute::kUndefined},
- {"wErkrp_size", Attribute::kUndefined},
- {"worgrroup_size", Attribute::kUndefined},
+ {"input_attachment_iXXdex", Attribute::kUndefined},
+ {"input_attnnIIhme99t55index", Attribute::kUndefined},
+ {"inputYarrHHacaamentSSindex", Attribute::kUndefined},
+ {"nHkkolate", Attribute::kUndefined},
+ {"jRRterogte", Attribute::kUndefined},
+ {"iterpolbe", Attribute::kUndefined},
+ {"invariajt", Attribute::kUndefined},
+ {"ivariant", Attribute::kUndefined},
+ {"ivariqt", Attribute::kUndefined},
+ {"locaioNN", Attribute::kUndefined},
+ {"ocvvion", Attribute::kUndefined},
+ {"loatQQon", Attribute::kUndefined},
+ {"musf_re", Attribute::kUndefined},
+ {"mujt_use", Attribute::kUndefined},
+ {"muswNN82e", Attribute::kUndefined},
+ {"sze", Attribute::kUndefined},
+ {"sirre", Attribute::kUndefined},
+ {"sGze", Attribute::kUndefined},
+ {"verFFex", Attribute::kUndefined},
+ {"vre", Attribute::kUndefined},
+ {"vrrrte", Attribute::kUndefined},
+ {"orkgroup_sze", Attribute::kUndefined},
+ {"DXkgroJJp_size", Attribute::kUndefined},
+ {"wo8kroup_sz", Attribute::kUndefined},
};
using AttributeParseTest = testing::TestWithParam<Case>;
diff --git a/src/tint/lang/core/builtin_type.cc b/src/tint/lang/core/builtin_type.cc
index 190cf7f..4fddb22 100644
--- a/src/tint/lang/core/builtin_type.cc
+++ b/src/tint/lang/core/builtin_type.cc
@@ -141,6 +141,9 @@
if (str == "i32") {
return BuiltinType::kI32;
}
+ if (str == "input_attachment") {
+ return BuiltinType::kInputAttachment;
+ }
if (str == "mat2x2") {
return BuiltinType::kMat2X2;
}
@@ -403,6 +406,8 @@
return "f32";
case BuiltinType::kI32:
return "i32";
+ case BuiltinType::kInputAttachment:
+ return "input_attachment";
case BuiltinType::kMat2X2:
return "mat2x2";
case BuiltinType::kMat2X2F:
diff --git a/src/tint/lang/core/builtin_type.h b/src/tint/lang/core/builtin_type.h
index ac0a22e..0f7a9f0 100644
--- a/src/tint/lang/core/builtin_type.h
+++ b/src/tint/lang/core/builtin_type.h
@@ -79,6 +79,7 @@
kF16,
kF32,
kI32,
+ kInputAttachment,
kMat2X2,
kMat2X2F,
kMat2X2H,
@@ -195,6 +196,7 @@
"f16",
"f32",
"i32",
+ "input_attachment",
"mat2x2",
"mat2x2f",
"mat2x2h",
diff --git a/src/tint/lang/core/builtin_type_bench.cc b/src/tint/lang/core/builtin_type_bench.cc
index f963bc7..1e5b673 100644
--- a/src/tint/lang/core/builtin_type_bench.cc
+++ b/src/tint/lang/core/builtin_type_bench.cc
@@ -276,447 +276,454 @@
"iJJ",
"UfCDD",
"i3g",
- "CCtx",
- "mt2x2",
- "mat2x__",
+ "inCCt_atachmen",
+ "iput_attachment",
+ "input__attachmenI",
+ "input_attachment",
+ "inpt_PttttaNment",
+ "input_attddc3ment",
+ "inKutyyattahment",
+ "mtx",
+ "mat03nn",
+ "mvtnCuuK",
"mat2x2",
- "attxPP",
- "mdd32x2",
- "yyK2x2",
- "m2uu",
- "ma0nnx2i",
- "KanuuCC2f",
- "mat2x2f",
- "mlX2x2f",
- "oat2pp2f",
- "wwat22f",
+ "lXatx2",
+ "matppxo",
+ "maw2x2",
"matguum",
"mt2ma2",
- "Tat2xZRRh",
+ "Tat2xZRRf",
+ "mat2x2f",
+ "ma8T2xOf",
+ "m0at2x2f",
+ "mBBt2x2f",
+ "at2ppM",
+ "matOO2h",
+ "mGG2x2G",
"mat2x2h",
- "ma8T2xOh",
- "m0at2x2h",
- "mBBt2x2h",
- "Matpp",
- "Oat2x3",
- "GGG2x3",
+ "mHHt2x11h",
+ "eat2x6Fh",
+ "atx2h",
+ "mKl2ii3",
+ "at2x3",
+ "9IIat2x3",
"mat2x3",
- "mHHt2113",
- "mateF63",
- "matx",
- "mat2ii3l",
- "mt2x3f",
- "IIvvt2x39",
- "mat2x3f",
- "mat23f",
- "mat2h3f",
- "mllt2xPzz",
- "t3h",
- "mtffxqqh",
+ "ma2x3",
+ "hat2x3",
+ "zzPt2xll",
+ "t3f",
+ "mtffxqqf",
"mtJJx3dd",
- "mat2x3h",
- "mzz2X3h",
+ "mat2x3f",
+ "mzz2X3f",
"matx32",
- "maN2yy3h",
- "atxO",
- "rauExP",
- "meet22dd",
+ "maN2yy3f",
+ "mt2O3",
+ "uZtrx3h",
+ "latdde23h",
+ "mat2x3h",
+ "matVVh",
+ "1IIt2x3",
+ "mat2xbh",
+ "t7i4",
+ "maio2x4",
+ "a5x4",
"mat2x4",
- "maV92",
- "maI2x1",
- "mab2x4",
- "matzf",
- "mao2ii4f",
- "mat45",
+ "St2x4",
+ "m22tx",
+ "maC7G4",
+ "maff284f",
+ "t2x4f",
+ "SSatJJx4f",
"mat2x4f",
- "at2xSf",
- "mat22f",
- "maG1C4f",
- "maff284h",
- "t2x4h",
- "SSatJJx4h",
+ "atx9f",
+ "maJJbbTT4f",
+ "66a2xf",
+ "ut2x466",
+ "aW2x4h",
+ "mtx4h",
"mat2x4h",
- "atx9h",
- "maJJbbTT4h",
- "66a2xh",
- "ma663u",
- "Wa3x2",
- "ma32",
+ "mOt2x4",
+ "THat2xBB",
+ "maRR2xh",
+ "VLLa30",
+ "at3KOO",
+ "awg3x2",
"mat3x2",
- "ma3x2",
- "rat3x2",
- "m2t3xB",
- "matxBBf",
- "maRR3xf",
- "maVV0Lf",
- "mat3x2f",
- "a3OOK2f",
- "magw3xf",
- "hht3L2f",
- "aKii3xh",
- "ma3x2h",
+ "maLhhp",
+ "iitEx2",
+ "at3x2",
"UUa3882",
- "mat3x2h",
- "rrvvt3x2h",
+ "rrvvt3x2f",
"m3xwmm",
- "j443x2h",
- "matXx3",
- "m8t3x3",
- "mat3vEE",
+ "mat3x2f",
+ "j443x2f",
+ "matXx2f",
+ "mat8x2f",
+ "mvEE3x2h",
+ "mai93zz",
+ "mQQJJnxGGh",
+ "mat3x2h",
+ "mass3x2h",
+ "matKxPh",
+ "mat3tth",
+ "atx3",
+ "maMM3x3",
+ "mJ0t3x3",
"mat3x3",
- "mzzi3x",
- "maGGQ3JJ3",
- "mat3ss3",
- "matKxPf",
- "mat3ttf",
- "mt3x3",
- "mat3x3f",
- "mMMt3x3f",
- "maJ03x3f",
- "V8x3",
- "maKggx3hh",
- "maf3x3h",
- "matQ7x3h",
- "mat3x3h",
- "mat3YYh",
+ "V38",
+ "hggat3x3",
+ "maf3x3",
+ "matQ7x3f",
+ "mat3YYf",
"mak3x3",
+ "mat3x3f",
"man3x2",
- "mFFx4",
- "GGatPPuUU",
- "mEEFa4",
+ "ma3FFf",
+ "uGGtIUPP3f",
+ "EEvFx3h",
+ "ddtBBDDeh",
+ "m55tMccE3",
+ "mat3x3h",
+ "aKKx3",
+ "mat3x3R",
+ "maDx39",
+ "mt3x4",
+ "aIt34",
+ "mat3x77",
"mat3x4",
- "mBet3dd4",
- "55atExcc",
- "txKK",
- "mat3x4R",
- "maDx49",
- "mt3x4f",
+ "matIx4",
+ "matd4",
+ "mt3x4",
+ "mtt4f",
+ "ma3XX3x4f",
+ "Eat34f",
"mat3x4f",
- "aaat3I",
- "m77t3x4f",
- "matIx4f",
- "md3x4h",
- "mat34h",
- "mtt4h",
- "mat3x4h",
- "ma3XX3x4h",
- "Eat34h",
"maXX3x4",
- "mxBt4x2",
- "Wt4x",
- "mat66x2",
+ "matxBx4f",
+ "m3x4f",
+ "mat3x466",
+ "matxv0",
+ "txh",
+ "mat3x4h",
+ "mpt3xh",
+ "at114h",
+ "EaJ3yBBh",
+ "mqIm4x2",
+ "ma4F2",
+ "aY4x2",
"mat4x2",
- "atTv0",
- "kt",
- "mpt4x",
- "at112f",
- "EaJ4yBBf",
- "mqIm4x2f",
+ "matDHh2",
+ "24H2",
+ "m4x2",
+ "matx2f",
+ "matx2f",
+ "matddx2f",
"mat4x2f",
- "ma4xFf",
- "Yt4x2f",
- "mHHtDh2f",
- "Ht22h",
- "matx2",
- "matx2h",
+ "Oat4x2f",
+ "atBbb2",
+ "m004x2f",
+ "mat4xhh",
+ "mgYtx2h",
+ "mat4O2h",
"mat4x2h",
- "matx2h",
- "matddx2h",
- "Oat4x2h",
- "bbtB3",
- "m00tx3",
- "hat4x3",
+ "ah4xh",
+ "fpaEEx2h",
+ "mavx2h",
+ "at4zz3",
+ "mat4x",
+ "OiiJt4",
"mat4x3",
- "matgYx",
- "Oat4x3",
- "mhx3",
- "fpaEEx3f",
- "mavx3f",
- "mzztx3f",
+ "mGt4xf",
+ "mTT224x3",
+ "lat4x3",
+ "bat4x3f",
+ "BBatx3f",
+ "PPIXt4S3f",
"mat4x3f",
- "ma4x3f",
- "OOaJxii",
- "mft4G3f",
- "mat4x322T",
- "datlx3h",
- "bat4x3h",
+ "mjjt4x3f",
+ "_at4xccf",
+ "ax6z4xSSf",
+ "a4xG",
+ "mx44N3v",
+ "atAAx00p",
"mat4x3h",
- "BBatx3h",
- "PPIXt4S3h",
- "mjjt4x3h",
- "macc4_4",
- "SS6zz4xx",
- "mtx",
+ "eeytyh",
+ "mabWWx0h",
+ "ttatMMxmh",
+ "4d4",
+ "mav_x",
+ "mVt4xEE",
"mat4x4",
- "mxxtvN",
- "AA00t44",
- "tyexy",
- "mabWWx0f",
- "ttatMMxmf",
- "madf",
+ "m4t4x4",
+ "mVVtgxX",
+ "oat4V4",
+ "ma4x4f",
+ "KKattxf",
+ "G4xf",
"mat4x4f",
- "mat_4f",
- "Vat4EE4f",
- "mat44f",
- "mRIxah",
- "ma4mmh",
- "at4x4p",
+ "ma4x4",
+ "mad4x4f",
+ "CCat4xPtf",
+ "matx4",
+ "m5t4x4h",
+ "m9jtffx4h",
"mat4x4h",
- "mat4xh",
- "aaxh",
- "mad4x4h",
- "pCPtd",
- "p",
- "5tr",
+ "matRvxXXh",
+ "ctx4h",
+ "XX8t5x4",
+ "t",
+ "ppcc",
+ "vtr",
"ptr",
- "ff99j",
- "YYvXR",
- "r",
- "XX8m5le",
- "mpler",
- "sccmlppr",
+ "EESS",
+ "p",
+ "",
+ "saplwwr",
+ "sa99plddr",
+ "99amplP",
"sampler",
- "sampver",
- "EESSmplr",
- "smplr",
- "samplecomp_risa",
- "sampler_co_prwwson",
- "samplerdd99omparison",
+ "saKKler",
+ "smDDooeM",
+ "smlei",
+ "samler_comparqon",
+ "samplercmparis0LLn",
+ "snvvpler_com66arison",
"sampler_comparison",
- "ampler_o99paPPison",
- "saplerKKcomparison",
- "saMpler_oomDDarison",
- "teiie_1B",
- "txureq1d",
- "txt00rLL_d",
+ "samplen_comparison",
+ "samlercompeerixxon",
+ "sONNpler_comparCCson",
+ "txture_1d",
+ "tex4uae_1d",
+ "extuNNe_1NN",
"texture_1d",
- "tnxture_16vv",
- "trrxtur_nd",
- "xxture_eed",
- "CCNOxture_2d",
- "txture_2d",
- "tex4uae_2d",
+ "texture1d",
+ "tuxtre1d",
+ "textErYYS1A",
+ "tex0ure_2d",
+ "texaaure_2d",
+ "tqqmmtur_d",
"texture_2d",
- "extuNNe_2NN",
- "texture2d",
- "tuxtre2d",
- "teYYtuAe_2d_arESy",
- "texture_2d_0rray",
- "texture_2d_aarray",
- "texture_2d_array",
- "texturmm_2d_arra",
- "texture_2d_aray",
- "teEuUUe_2darray",
+ "textue_2d",
+ "tUUxtureE",
"tKKture_Dd",
- "text__r0_3d",
- "tAtuel3p",
+ "0exture_2d_a__rat",
+ "tpturl_2_Array",
+ "txture_2M_array",
+ "texture_2d_array",
+ "BBexture_2d_array",
+ "nnxtbbre_2_a99ray",
+ "texturEE2d_aAAray",
+ "tex66ur5_3d",
+ "tHxture_3d",
+ "teHHuxe_3d",
"texture_3d",
- "textue_3d",
- "texturBB_3d",
- "nnbb99re_3d",
- "AAEExture_cub",
- "t66Ttu5e_cube",
- "textuHe_cube",
+ "tzxturny_0d",
+ "teture_3d",
+ "Hexture3k",
+ "textur_cubc",
+ "trrxtoorecbe",
+ "textreJJcub",
"texture_cube",
- "textrexxHcub",
- "tzx0uryy_cnbe",
- "texture_cue",
- "texurH_kube_array",
- "exture_cube_array",
- "ooexrrre_cbe_array",
+ "0Cxture_cube",
+ "99eFtureAAcbx",
+ "textcre_cube",
+ "Sexture_cube_array",
+ "txtureBBcobe_arras",
+ "teture_cube_array",
"texture_cube_array",
- "textre_cubJJarray",
- "tCCxtu0e_cube_arry",
- "texturAAcxbe99aFray",
- "textcre_depth_2d",
- "texture_Septh_2d",
- "textureodpthBB2d",
+ "texturemmebe_array",
+ "tQQturPP_cube_arragg",
+ "textr_cubBrray",
+ "teKKNllre_eth_2d",
+ "texture_ephrr2d",
+ "rppture_depth_2d",
"texture_depth_2d",
- "texture_dept_2d",
- "textummedepth_2d",
- "toxture_ggeQQtPP2d",
- "tetur_dptB_2d_rray",
- "texNure_deKKh2d_arrlly",
- "teture_dpth_2d_arrray",
+ "texture_deyPth_2d",
+ "extue_dZZpth_ccd",
+ "texure_depth_2",
+ "textu00e_depth_2d_array",
+ "tPJxture_BBsspth_2d_arry",
+ "teffture_wwepth_2dJJarra",
"texture_depth_2d_array",
- "texture_epth_ppd_array",
- "teyturPP_depth_2d_array",
- "texture_ZZptcc_2d_arry",
- "txtue_depth_cube",
- "texture00depth_cube",
- "texPPuBB_deJth_cusse",
+ "Iextu1e_dpth_2d_arraXX",
+ "extur_depth2_arry",
+ "texture_depth_2_array",
+ "tuxtreKKdepth_cube",
+ "44edture_depmh_ube",
+ "pexture_deoth_cube",
"texture_depth_cube",
- "texJJre_dffpwwh_fube",
- "textIre_depXXh_cub",
- "textur_ph_cue",
- "textue_depth_cube_array",
- "tKKxtue_depth_cube_array",
- "teture_d44ptm_cube_adray",
+ "textre_djphhhNNcHHbe",
+ "textu33e_depth_EuwwUU",
+ "texture_dethuucbe",
+ "excurrr_depddh_cube_array",
+ "2exturePPttpth_cube_array",
+ "texture_depthwwcub1sarray",
"texture_depth_cube_array",
- "pexture_deoth_cube_array",
- "thhHxtureNdepth_cubejarray",
- "texwwuUUe_depthEc33be_array",
- "texture_dept_multiuuampled_2",
- "ddextKre_depth_ultisampcerr_2d",
- "textuPPe_depr_multttsample2_2d",
+ "nnexture_depthcc11be_array",
+ "texture_depthcube_array",
+ "texture_depth_cube_arry",
+ "texture_deIth_multsa66pleaaSS2d",
+ "texture_depth_mDltisamEEld_2d",
+ "texture_Iepth_multiccamRleV_2d",
"texture_depth_multisampled_2d",
- "1exture_depth_wwsltisampled_2d",
- "textuce_depth_mnnltisamp11ed_2d",
- "texture_depth_multisapled_2d",
- "texture_externl",
- "teSS66ue_exaaeInal",
- "textuEEe_extenal",
+ "texture_dephmultisampled92d",
+ "texthraa_depth_multsampled_2d",
+ "texture_depth_SultisaLLped_2d",
+ "txfure_ertermma",
+ "teVturem4xqerna",
+ "textu___extenal",
"texture_external",
- "ccexture_exVerIRl",
- "te9tue_extrnal",
- "taaxture_exterha",
- "texture_multisamLLeS_2d",
- "tefurmm_mutisampled_2d",
- "texture_mul4isampld_qV",
+ "texurQ_eternal",
+ "textureddetRErnal",
+ "text9re_extenal",
+ "t0xtre_multisamCCe_2d",
+ "texure_zulisampled_2d",
+ "texccure_multisampled_2d",
"texture_multisampled_2d",
- "texture_multisa_pled_d",
- "texure_multisampledQd",
- "texRRuremultisampledEd2d",
- "textur_st9rage_1d",
- "tCCx0ure_strag_1",
- "textuezstorae_1d",
+ "tOxture_mu_tisampled2QQ",
+ "exture_multsampledtt2d",
+ "textCCEe_mult33samzzled_ppd",
+ "textudde_storaghh_1d",
+ "_etur77_66torage_1d",
+ "texture_storaPe_1d",
"texture_storage_1d",
- "texccure_storage_1d",
- "textureOQQ_orge_1d",
- "teturettstrage_1d",
- "textCCrepzzstEr33ge_2d",
- "textudde_storaghh_2d",
- "_etur77_66torage_2d",
+ "twxture_storage_1d",
+ "textur_straguu_1",
+ "texture_storaXXe_6d",
+ "textRRr_sorag_2d",
+ "textrestVVrag12d",
+ "texture_HHtorGGge_2d",
"texture_storage_2d",
- "texture_storaPe_2d",
- "twxture_storage_2d",
- "textur_straguu_2",
- "textureXXstorage_6d_array",
- "extuRRestorage_2d_aray",
- "txtre_storage_2dVVarr1",
+ "tFFxture_storMge_7d",
+ "texture_storage_d",
+ "3xTugge_stoage_2d",
+ "text_rP_Qtorage12d_arrKKy",
+ "tExture_strage_2d_array",
+ "extMre_storage_d_array",
"texture_storage_2d_array",
- "GGexture_storHHge_2d_array",
- "MFFxt7re_storage_2d_array",
- "texture_storage_d_array",
- "3xTugge_stoage_3d",
- "texturP_QtKKrag1__d",
- "textre_storageE3d",
+ "texturGGst77ragX_2d_SSrray",
+ "textturFF_storae_2d_arraK",
+ "textuoe_storage_2dssZarrUUy",
+ "texturestorage_3d",
+ "telture_storage_3d",
+ "texture_htorage_3d",
"texture_storage_3d",
- "tMture_storage_d",
- "t77xture_sGGorSSe_3d",
- "txtttre_storage_3FF",
- "uZZss2",
- "u2",
- "u3l",
+ "texturTTKstorage_d",
+ "texturww_storagee3",
+ "textureKsjjragvv_3d",
+ "Y2",
+ "EEI",
+ "u3QQ",
"u32",
- "u3h",
- "uTT",
- "ww2",
- "vKvjj",
- "vYY",
- "EcI2",
+ "P",
+ "H3ff",
+ "u3n",
+ "Fc66",
+ "ssech",
+ "llFec",
"vec2",
- "vecQQ",
- "Pc",
- "veffH",
- "vec2n",
- "g6F2f",
- "vssh8f",
- "vec2f",
- "veFllf",
- "00e2j",
- "gec2f",
- "vece",
- "ffc2h",
+ "jj20",
+ "veg2",
+ "vce",
+ "ffc2f",
"ve",
- "vec2h",
- "ve2h",
- "vqc2h",
+ "ve2f",
+ "vec2f",
+ "vqc2f",
"AAe",
- "ec2i",
+ "ec2f",
"vec2j",
- "ZZec2i",
- "vec2i",
+ "ZZec2h",
"PPecII2",
- "ZZec2i",
- "vnnc2i",
+ "vec2h",
+ "ZZec2h",
+ "vnnc2h",
"HekkZ222",
"ec2",
"RcNQQ",
- "vec2u",
- "eDu",
+ "eDi",
+ "vec2i",
"s3c2cu",
- "vRR2u",
- "vlJJ3",
- "MM",
- "vT63",
- "vec3",
- "QQec3",
- "vuA",
- "e3",
+ "vRR2i",
+ "vc2JJl",
+ "MMu",
+ "v66T7",
+ "vQQcJu",
+ "vec2u",
+ "Auc2",
+ "ve2",
"yeq3",
- "vec3xx",
- "crr",
- "vec3f",
- "v99cf",
- "vecf",
- "ecHl",
- "e_h",
+ "vxxc3",
+ "rr",
+ "e993",
+ "vec3",
+ "ec3",
+ "vlH",
+ "ec",
"uec3",
- "vc3h",
- "vec3h",
- "EEtmec3h",
+ "vc3f",
+ "EEtmec3f",
+ "vec3f",
"vec",
"ec3rr",
- "xc3i",
+ "xc3f",
"vezz",
"vec3e",
- "vec3i",
"uc3Zp",
+ "vec3h",
"00uc7TT",
"vvJJ",
- "vecQu",
+ "vecQh",
"ve3R",
"e",
- "vec3u",
"veprPP",
- "xxeDD88u",
- "lldmYYqqu",
- "FFec4",
- "rGecNN",
- "Mecl",
+ "vec3i",
+ "xxeDD88i",
+ "lldmYYqqi",
+ "vFFc__",
+ "rrNNc3u",
+ "leM3u",
+ "c3",
+ "vec3u",
+ "xlc3u",
+ "ec3u",
+ "ae44u",
+ "WWeG4",
+ "vjjc",
+ "vjjc4",
"vec4",
- "c",
- "qxl4",
+ "vj4",
"ve4",
- "ae44f",
- "vec4WW",
- "vecjj",
- "vec4f",
- "vjjc4f",
- "vj1f",
- "vc4f",
- "vec499",
- "vyVV4h",
+ "99ec4",
+ "vyVV4f",
"ec4xZ",
- "vec4h",
- "v33vvh",
+ "v33vvf",
+ "vec4f",
"vecs9",
"veF4",
- "uec4i",
+ "uec4f",
"eIKK",
"ve4J",
- "vec4i",
- "vSSCCXXi",
+ "vSSCCXXh",
+ "vec4h",
"JecWW6ZZ",
"ecd5",
"vBBcBU",
"JJ0c411",
- "vecttu",
- "vec4u",
+ "vectti",
"vttc",
- "veL4u",
- "v1c4u",
+ "vec4i",
+ "veL4i",
+ "v1c4i",
+ "veww4i",
+ "ece",
+ "vc4u",
+ "vec4NN",
+ "vec4u",
+ "vUlRR__u",
+ "vecHu",
+ "vrCC4u",
};
for (auto _ : state) {
for (auto* str : kStrings) {
diff --git a/src/tint/lang/core/builtin_type_test.cc b/src/tint/lang/core/builtin_type_test.cc
index 8fd8d6a..886a7e3 100644
--- a/src/tint/lang/core/builtin_type_test.cc
+++ b/src/tint/lang/core/builtin_type_test.cc
@@ -90,6 +90,7 @@
{"f16", BuiltinType::kF16},
{"f32", BuiltinType::kF32},
{"i32", BuiltinType::kI32},
+ {"input_attachment", BuiltinType::kInputAttachment},
{"mat2x2", BuiltinType::kMat2X2},
{"mat2x2f", BuiltinType::kMat2X2F},
{"mat2x2h", BuiltinType::kMat2X2H},
@@ -255,195 +256,198 @@
{"0yz2", BuiltinType::kUndefined},
{"iVP", BuiltinType::kUndefined},
{"Cnn", BuiltinType::kUndefined},
- {"AtqqHH2", BuiltinType::kUndefined},
- {"at2x2", BuiltinType::kUndefined},
- {"mafKK", BuiltinType::kUndefined},
- {"ltgg2f", BuiltinType::kUndefined},
- {"mat2xf", BuiltinType::kUndefined},
- {"NTTtcx4f", BuiltinType::kUndefined},
- {"ma7ppl2h", BuiltinType::kUndefined},
+ {"nput_attacAAmeHHt", BuiltinType::kUndefined},
+ {"nput_attachment", BuiltinType::kUndefined},
+ {"input_attKKfmen", BuiltinType::kUndefined},
+ {"Paggx", BuiltinType::kUndefined},
+ {"mat2x", BuiltinType::kUndefined},
+ {"maN2c42", BuiltinType::kUndefined},
+ {"ma7ppl2f", BuiltinType::kUndefined},
{"mNNt2xg", BuiltinType::kUndefined},
- {"uub2XX2h", BuiltinType::kUndefined},
- {"mt2x3", BuiltinType::kUndefined},
- {"m88xK", BuiltinType::kUndefined},
- {"maqx3", BuiltinType::kUndefined},
- {"m11t2x3f", BuiltinType::kUndefined},
- {"22at2iif", BuiltinType::kUndefined},
- {"at2x377", BuiltinType::kUndefined},
- {"m2t2xNh", BuiltinType::kUndefined},
- {"mVVt2x3h", BuiltinType::kUndefined},
- {"FaWW2w11h", BuiltinType::kUndefined},
- {"matww4", BuiltinType::kUndefined},
- {"mat2D4", BuiltinType::kUndefined},
- {"maKx4", BuiltinType::kUndefined},
- {"mat21PPhf", BuiltinType::kUndefined},
- {"mat24f", BuiltinType::kUndefined},
- {"mYYt2x4f", BuiltinType::kUndefined},
+ {"uub2XX2f", BuiltinType::kUndefined},
+ {"matx2h", BuiltinType::kUndefined},
+ {"Qt882h", BuiltinType::kUndefined},
+ {"mt9q2h", BuiltinType::kUndefined},
+ {"mat2113", BuiltinType::kUndefined},
+ {"Ft2xi22", BuiltinType::kUndefined},
+ {"m7t2x3", BuiltinType::kUndefined},
+ {"m2t2xNf", BuiltinType::kUndefined},
+ {"mVVt2x3f", BuiltinType::kUndefined},
+ {"FaWW2w11f", BuiltinType::kUndefined},
+ {"mawwx3h", BuiltinType::kUndefined},
+ {"Dat2x3h", BuiltinType::kUndefined},
+ {"mt2x3K", BuiltinType::kUndefined},
+ {"11at2xPP", BuiltinType::kUndefined},
+ {"mat2x", BuiltinType::kUndefined},
+ {"mat2xYY", BuiltinType::kUndefined},
{"mttHH4kk", BuiltinType::kUndefined},
- {"mat2rr4h", BuiltinType::kUndefined},
- {"WWas2x4h", BuiltinType::kUndefined},
- {"maYx2", BuiltinType::kUndefined},
- {"mq3f2", BuiltinType::kUndefined},
- {"vvafu222", BuiltinType::kUndefined},
- {"t3x2f", BuiltinType::kUndefined},
- {"YYat3f", BuiltinType::kUndefined},
- {"may3x2EYY", BuiltinType::kUndefined},
- {"da3xMoh", BuiltinType::kUndefined},
+ {"mat2rr4f", BuiltinType::kUndefined},
+ {"WWas2x4f", BuiltinType::kUndefined},
+ {"Yt2x4h", BuiltinType::kUndefined},
+ {"mt2qfh", BuiltinType::kUndefined},
+ {"mav222xuh", BuiltinType::kUndefined},
+ {"mt32", BuiltinType::kUndefined},
+ {"maY32", BuiltinType::kUndefined},
+ {"YYa7y3E2", BuiltinType::kUndefined},
+ {"da3xMof", BuiltinType::kUndefined},
{"matMMx2", BuiltinType::kUndefined},
- {"mat3x55h", BuiltinType::kUndefined},
- {"maN3", BuiltinType::kUndefined},
- {"ma33x3", BuiltinType::kUndefined},
- {"mt3x3", BuiltinType::kUndefined},
- {"mm66Issf", BuiltinType::kUndefined},
- {"mat3x1f", BuiltinType::kUndefined},
- {"Xt3x3", BuiltinType::kUndefined},
- {"LatIx3h", BuiltinType::kUndefined},
- {"at3fh", BuiltinType::kUndefined},
+ {"mat3x55f", BuiltinType::kUndefined},
+ {"maN32", BuiltinType::kUndefined},
+ {"ma3Ox33", BuiltinType::kUndefined},
+ {"m3t3x2h", BuiltinType::kUndefined},
+ {"mt3I3", BuiltinType::kUndefined},
+ {"mnnt3xr", BuiltinType::kUndefined},
+ {"mXX", BuiltinType::kUndefined},
+ {"LatIx3f", BuiltinType::kUndefined},
+ {"at3ff", BuiltinType::kUndefined},
{"mYtURD3", BuiltinType::kUndefined},
- {"mah3x4", BuiltinType::kUndefined},
- {"muqII4", BuiltinType::kUndefined},
- {"mat3xH", BuiltinType::kUndefined},
- {"at3QQvv", BuiltinType::kUndefined},
- {"at66ef", BuiltinType::kUndefined},
- {"ma7O4f", BuiltinType::kUndefined},
+ {"mah3x3h", BuiltinType::kUndefined},
+ {"uuIqt3x", BuiltinType::kUndefined},
+ {"maH3x3h", BuiltinType::kUndefined},
+ {"at3Qvv", BuiltinType::kUndefined},
+ {"66ate", BuiltinType::kUndefined},
+ {"mat7x", BuiltinType::kUndefined},
{"m55t3x0DD", BuiltinType::kUndefined},
{"maH3x4II", BuiltinType::kUndefined},
{"at3x4", BuiltinType::kUndefined},
- {"ma994x2", BuiltinType::kUndefined},
- {"mWWt4Gt2", BuiltinType::kUndefined},
- {"ay42", BuiltinType::kUndefined},
- {"mt4x2f", BuiltinType::kUndefined},
- {"IIaBB4x2f", BuiltinType::kUndefined},
- {"TTat4x833", BuiltinType::kUndefined},
- {"ddUUnntYYx2h", BuiltinType::kUndefined},
+ {"rat3x499", BuiltinType::kUndefined},
+ {"mGtt31W4h", BuiltinType::kUndefined},
+ {"yatx4", BuiltinType::kUndefined},
+ {"mt4x2", BuiltinType::kUndefined},
+ {"maBBI4x2", BuiltinType::kUndefined},
+ {"mat8TTx2", BuiltinType::kUndefined},
+ {"ddUUnntYYx2f", BuiltinType::kUndefined},
{"m5CCxxdZ", BuiltinType::kUndefined},
- {"matkkq2h", BuiltinType::kUndefined},
- {"5iitp00", BuiltinType::kUndefined},
- {"mnntIIx3", BuiltinType::kUndefined},
- {"ccaKx", BuiltinType::kUndefined},
- {"m43KK", BuiltinType::kUndefined},
- {"mat66x3f", BuiltinType::kUndefined},
- {"Et4PP3K", BuiltinType::kUndefined},
- {"xxatx3h", BuiltinType::kUndefined},
- {"qat4x3h", BuiltinType::kUndefined},
- {"MMayySrxh", BuiltinType::kUndefined},
- {"uat4", BuiltinType::kUndefined},
- {"tx4", BuiltinType::kUndefined},
- {"ma54FF4", BuiltinType::kUndefined},
- {"rra444z4f", BuiltinType::kUndefined},
- {"matWW", BuiltinType::kUndefined},
- {"CatZJXx4f", BuiltinType::kUndefined},
- {"maPPx4h", BuiltinType::kUndefined},
- {"mat4c4h", BuiltinType::kUndefined},
- {"matPPll6h", BuiltinType::kUndefined},
- {"9tyy", BuiltinType::kUndefined},
- {"ptKK", BuiltinType::kUndefined},
- {"x_", BuiltinType::kUndefined},
- {"ayKer", BuiltinType::kUndefined},
- {"szmpVek", BuiltinType::kUndefined},
- {"sampqeK", BuiltinType::kUndefined},
- {"sampler_comparisn", BuiltinType::kUndefined},
- {"sapler_comparisVVn", BuiltinType::kUndefined},
- {"samplerIcompaAUison", BuiltinType::kUndefined},
- {"jexurbRd", BuiltinType::kUndefined},
- {"exure_YYd", BuiltinType::kUndefined},
- {"exture_1d", BuiltinType::kUndefined},
+ {"matkkq2f", BuiltinType::kUndefined},
+ {"005itpxh", BuiltinType::kUndefined},
+ {"maIInnx2h", BuiltinType::kUndefined},
+ {"Ka4Wcc", BuiltinType::kUndefined},
+ {"mtKK", BuiltinType::kUndefined},
+ {"ma664x3", BuiltinType::kUndefined},
+ {"mKKtPx", BuiltinType::kUndefined},
+ {"xxatx3f", BuiltinType::kUndefined},
+ {"qat4x3f", BuiltinType::kUndefined},
+ {"MMayySrxf", BuiltinType::kUndefined},
+ {"mat3h", BuiltinType::kUndefined},
+ {"tx3h", BuiltinType::kUndefined},
+ {"ma5F4x3h", BuiltinType::kUndefined},
+ {"rraz44x4", BuiltinType::kUndefined},
+ {"aWWx", BuiltinType::kUndefined},
+ {"ZZJJtCxX", BuiltinType::kUndefined},
+ {"maPPx4f", BuiltinType::kUndefined},
+ {"mat4c4f", BuiltinType::kUndefined},
+ {"matPPll6f", BuiltinType::kUndefined},
+ {"mat994yy", BuiltinType::kUndefined},
+ {"mat4JKKh", BuiltinType::kUndefined},
+ {"mat4_h", BuiltinType::kUndefined},
+ {"K", BuiltinType::kUndefined},
+ {"kVz", BuiltinType::kUndefined},
+ {"KtS", BuiltinType::kUndefined},
+ {"ampler", BuiltinType::kUndefined},
+ {"aVVpler", BuiltinType::kUndefined},
+ {"AAamIlUr", BuiltinType::kUndefined},
+ {"jamper_compaRson", BuiltinType::kUndefined},
+ {"amplr44compYYriso", BuiltinType::kUndefined},
+ {"samper_comparison", BuiltinType::kUndefined},
{"texxxur_1d", BuiltinType::kUndefined},
- {"tJxucce_2d", BuiltinType::kUndefined},
+ {"tJxucce_1d", BuiltinType::kUndefined},
{"texure_JJd", BuiltinType::kUndefined},
- {"lDexture_fCC_arraU", BuiltinType::kUndefined},
- {"tegture_2d_array", BuiltinType::kUndefined},
- {"teCCure2d_arra", BuiltinType::kUndefined},
- {"textue_3d", BuiltinType::kUndefined},
- {"tIx__ure_3d", BuiltinType::kUndefined},
- {"texurettPP", BuiltinType::kUndefined},
- {"tddx3ure_cube", BuiltinType::kUndefined},
- {"teKyyur_cube", BuiltinType::kUndefined},
- {"teturecub", BuiltinType::kUndefined},
- {"textinne_c03e_array", BuiltinType::kUndefined},
- {"nextCCruuvcubK_array", BuiltinType::kUndefined},
- {"tXxturellcbe_array", BuiltinType::kUndefined},
- {"tppxture_depth_2d", BuiltinType::kUndefined},
- {"txture_deptww_2d", BuiltinType::kUndefined},
- {"gexturedemmthuu2", BuiltinType::kUndefined},
- {"texmmre_depthaa2daray", BuiltinType::kUndefined},
- {"texture_RRepth_Td_ccZray", BuiltinType::kUndefined},
- {"text88re_depthTOd_array", BuiltinType::kUndefined},
- {"texture_depth_cm00e", BuiltinType::kUndefined},
- {"texture_Bmepth_cube", BuiltinType::kUndefined},
- {"Mextre_ppeph_cube", BuiltinType::kUndefined},
- {"texturOO_depth_cub_array", BuiltinType::kUndefined},
- {"GeGGture_depthcube_array", BuiltinType::kUndefined},
- {"texture11Hdepth_cube_array", BuiltinType::kUndefined},
- {"textu6e_FFepth_multiameeled_2d", BuiltinType::kUndefined},
- {"texture_epth_mltisampled_2d", BuiltinType::kUndefined},
- {"texture_depth_mullKsaiipled_2d", BuiltinType::kUndefined},
- {"texture_extenal", BuiltinType::kUndefined},
- {"IIext99reexvvernal", BuiltinType::kUndefined},
- {"texture_externl", BuiltinType::kUndefined},
- {"texture_mhltisampled_2d", BuiltinType::kUndefined},
- {"texturemPllltisampzzed_2d", BuiltinType::kUndefined},
- {"exture_mltisamed_2d", BuiltinType::kUndefined},
- {"texture_qqtoragff_1", BuiltinType::kUndefined},
- {"textre_JJddorage_1W", BuiltinType::kUndefined},
- {"XXrxture_storae1zz", BuiltinType::kUndefined},
- {"texturestorag2_2d", BuiltinType::kUndefined},
- {"yyNxture_storage_2d", BuiltinType::kUndefined},
- {"etue_storage_2OO", BuiltinType::kUndefined},
- {"reutuPe_storZgeE2d_array", BuiltinType::kUndefined},
- {"texlure_storddeee_d_22rray", BuiltinType::kUndefined},
- {"texture_mtorage_2V_a9ra", BuiltinType::kUndefined},
- {"teII1re_storage_3d", BuiltinType::kUndefined},
- {"texture_storagb_3d", BuiltinType::kUndefined},
- {"texizrestorge73d", BuiltinType::kUndefined},
- {"u3oi", BuiltinType::kUndefined},
- {"3", BuiltinType::kUndefined},
- {"S2", BuiltinType::kUndefined},
- {"e22", BuiltinType::kUndefined},
- {"1eC2", BuiltinType::kUndefined},
- {"vf8c2", BuiltinType::kUndefined},
- {"c2f", BuiltinType::kUndefined},
- {"JJecSSf", BuiltinType::kUndefined},
- {"92f", BuiltinType::kUndefined},
+ {"lextuUe_2fDC", BuiltinType::kUndefined},
+ {"textgre_2d", BuiltinType::kUndefined},
+ {"CCxtue_2", BuiltinType::kUndefined},
+ {"txture_2d_array", BuiltinType::kUndefined},
+ {"textu__e_2d_arraI", BuiltinType::kUndefined},
+ {"texurPtt_2dNrray", BuiltinType::kUndefined},
+ {"tddx3ure_3d", BuiltinType::kUndefined},
+ {"teyytur_Kd", BuiltinType::kUndefined},
+ {"tetuuud", BuiltinType::kUndefined},
+ {"tex0unne_cu3e", BuiltinType::kUndefined},
+ {"uuexnure_cuvCK", BuiltinType::kUndefined},
+ {"tXllure_cube", BuiltinType::kUndefined},
+ {"texture_cppbo_array", BuiltinType::kUndefined},
+ {"teture_wwube_array", BuiltinType::kUndefined},
+ {"texturgm_cuube_aay", BuiltinType::kUndefined},
+ {"texmmre_deaath_", BuiltinType::kUndefined},
+ {"textRRcceTdeptZ_2d", BuiltinType::kUndefined},
+ {"te88tureOdTpth_2d", BuiltinType::kUndefined},
+ {"textume_00epth_2d_array", BuiltinType::kUndefined},
+ {"texturm_depth_BBd_array", BuiltinType::kUndefined},
+ {"texppur_depth_M_array", BuiltinType::kUndefined},
+ {"textre_deptOO_cube", BuiltinType::kUndefined},
+ {"texture_deptG_GGbe", BuiltinType::kUndefined},
+ {"tHHx11ure_depth_cube", BuiltinType::kUndefined},
+ {"texeere_depth_c6bFF_array", BuiltinType::kUndefined},
+ {"texure_depth_cub_array", BuiltinType::kUndefined},
+ {"tKxtiire_depth_cule_array", BuiltinType::kUndefined},
+ {"texture_depth_mulisampled_2d", BuiltinType::kUndefined},
+ {"texture99vdpth_multisIImpled_2d", BuiltinType::kUndefined},
+ {"texture_depth_multisampled_2", BuiltinType::kUndefined},
+ {"texture_hxternal", BuiltinType::kUndefined},
+ {"textullPP_extzzrna", BuiltinType::kUndefined},
+ {"texure_teral", BuiltinType::kUndefined},
+ {"texture_mufftiqqamled_2d", BuiltinType::kUndefined},
+ {"tddtuJJe_multisampled_2d", BuiltinType::kUndefined},
+ {"texuXXe_multisampldzz2d", BuiltinType::kUndefined},
+ {"texturestorag2_1d", BuiltinType::kUndefined},
+ {"yyNxture_storage_1d", BuiltinType::kUndefined},
+ {"etue_storage_1OO", BuiltinType::kUndefined},
+ {"reuEure_storZge_2P", BuiltinType::kUndefined},
+ {"teexture_sl2ddrage_d", BuiltinType::kUndefined},
+ {"tVVxture_9tagm_2d", BuiltinType::kUndefined},
+ {"tIIture_storage_2d_arr1y", BuiltinType::kUndefined},
+ {"texture_storagb_2d_array", BuiltinType::kUndefined},
+ {"texture_stzrage_2dai7a", BuiltinType::kUndefined},
+ {"texoure_storagii_3d", BuiltinType::kUndefined},
+ {"exture_ntor5ge3d", BuiltinType::kUndefined},
+ {"exture_storiSe_3d", BuiltinType::kUndefined},
+ {"22", BuiltinType::kUndefined},
+ {"uGC", BuiltinType::kUndefined},
+ {"f832", BuiltinType::kUndefined},
+ {"e2", BuiltinType::kUndefined},
+ {"SJJec2", BuiltinType::kUndefined},
+ {"9c", BuiltinType::kUndefined},
{"vbbJJ2TT", BuiltinType::kUndefined},
- {"e66h", BuiltinType::kUndefined},
- {"u662h", BuiltinType::kUndefined},
- {"vW2i", BuiltinType::kUndefined},
- {"v2i", BuiltinType::kUndefined},
- {"veci", BuiltinType::kUndefined},
- {"rec2u", BuiltinType::kUndefined},
+ {"e66f", BuiltinType::kUndefined},
+ {"u662f", BuiltinType::kUndefined},
+ {"vW2h", BuiltinType::kUndefined},
+ {"v2h", BuiltinType::kUndefined},
+ {"vech", BuiltinType::kUndefined},
+ {"rec2i", BuiltinType::kUndefined},
{"2ec2B", BuiltinType::kUndefined},
- {"vcBBu", BuiltinType::kUndefined},
- {"veRR", BuiltinType::kUndefined},
- {"VLL0", BuiltinType::kUndefined},
- {"KOe3", BuiltinType::kUndefined},
- {"vgwcf", BuiltinType::kUndefined},
- {"vLphf", BuiltinType::kUndefined},
- {"eiiEf", BuiltinType::kUndefined},
- {"ec3h", BuiltinType::kUndefined},
+ {"vcBBi", BuiltinType::kUndefined},
+ {"vRc2u", BuiltinType::kUndefined},
+ {"v2LL0", BuiltinType::kUndefined},
+ {"vKOOu", BuiltinType::kUndefined},
+ {"gwc3", BuiltinType::kUndefined},
+ {"hpLc", BuiltinType::kUndefined},
+ {"Eiic", BuiltinType::kUndefined},
+ {"ec3f", BuiltinType::kUndefined},
{"UU883", BuiltinType::kUndefined},
- {"rrecvvh", BuiltinType::kUndefined},
+ {"rrecvvf", BuiltinType::kUndefined},
{"ecmm", BuiltinType::kUndefined},
{"vec4j", BuiltinType::kUndefined},
{"vec3X", BuiltinType::kUndefined},
{"vec38", BuiltinType::kUndefined},
{"vecvEE", BuiltinType::kUndefined},
{"z99ci", BuiltinType::kUndefined},
- {"JJGeQQ4", BuiltinType::kUndefined},
- {"ssec4", BuiltinType::kUndefined},
- {"PecK", BuiltinType::kUndefined},
- {"tpc4f", BuiltinType::kUndefined},
- {"vec", BuiltinType::kUndefined},
- {"MMec4f", BuiltinType::kUndefined},
+ {"GGeJJA3u", BuiltinType::kUndefined},
+ {"vess3u", BuiltinType::kUndefined},
+ {"vPcKu", BuiltinType::kUndefined},
+ {"vtc4", BuiltinType::kUndefined},
+ {"e4", BuiltinType::kUndefined},
+ {"veMM4", BuiltinType::kUndefined},
{"vJJc40", BuiltinType::kUndefined},
{"8c", BuiltinType::kUndefined},
{"vecggKh", BuiltinType::kUndefined},
- {"vecfi", BuiltinType::kUndefined},
+ {"vecfh", BuiltinType::kUndefined},
{"vec47Q", BuiltinType::kUndefined},
- {"veY4i", BuiltinType::kUndefined},
- {"keSu", BuiltinType::kUndefined},
+ {"veY4h", BuiltinType::kUndefined},
+ {"keSi", BuiltinType::kUndefined},
{"n422", BuiltinType::kUndefined},
- {"vFFu", BuiltinType::kUndefined},
+ {"vFFi", BuiltinType::kUndefined},
+ {"GGIec4PP", BuiltinType::kUndefined},
+ {"aeEE4", BuiltinType::kUndefined},
+ {"ddBee4u", BuiltinType::kUndefined},
};
using BuiltinTypeParseTest = testing::TestWithParam<Case>;
diff --git a/src/tint/lang/core/constant/BUILD.bazel b/src/tint/lang/core/constant/BUILD.bazel
index b092c56..c58c65c 100644
--- a/src/tint/lang/core/constant/BUILD.bazel
+++ b/src/tint/lang/core/constant/BUILD.bazel
@@ -41,6 +41,7 @@
srcs = [
"composite.cc",
"eval.cc",
+ "invalid.cc",
"manager.cc",
"node.cc",
"scalar.cc",
@@ -51,6 +52,7 @@
"clone_context.h",
"composite.h",
"eval.h",
+ "invalid.h",
"manager.h",
"node.h",
"scalar.h",
@@ -93,6 +95,7 @@
"eval_test.h",
"eval_unary_op_test.cc",
"helper_test.h",
+ "invalid_test.cc",
"manager_test.cc",
"scalar_test.cc",
"splat_test.cc",
diff --git a/src/tint/lang/core/constant/BUILD.cmake b/src/tint/lang/core/constant/BUILD.cmake
index b7dbca1..c4f4558 100644
--- a/src/tint/lang/core/constant/BUILD.cmake
+++ b/src/tint/lang/core/constant/BUILD.cmake
@@ -44,6 +44,8 @@
lang/core/constant/composite.h
lang/core/constant/eval.cc
lang/core/constant/eval.h
+ lang/core/constant/invalid.cc
+ lang/core/constant/invalid.h
lang/core/constant/manager.cc
lang/core/constant/manager.h
lang/core/constant/node.cc
@@ -91,6 +93,7 @@
lang/core/constant/eval_test.h
lang/core/constant/eval_unary_op_test.cc
lang/core/constant/helper_test.h
+ lang/core/constant/invalid_test.cc
lang/core/constant/manager_test.cc
lang/core/constant/scalar_test.cc
lang/core/constant/splat_test.cc
diff --git a/src/tint/lang/core/constant/BUILD.gn b/src/tint/lang/core/constant/BUILD.gn
index 8549c0b..2a343e5 100644
--- a/src/tint/lang/core/constant/BUILD.gn
+++ b/src/tint/lang/core/constant/BUILD.gn
@@ -49,6 +49,8 @@
"composite.h",
"eval.cc",
"eval.h",
+ "invalid.cc",
+ "invalid.h",
"manager.cc",
"manager.h",
"node.cc",
@@ -93,6 +95,7 @@
"eval_test.h",
"eval_unary_op_test.cc",
"helper_test.h",
+ "invalid_test.cc",
"manager_test.cc",
"scalar_test.cc",
"splat_test.cc",
diff --git a/src/tint/lang/core/constant/invalid.cc b/src/tint/lang/core/constant/invalid.cc
new file mode 100644
index 0000000..ecf434a
--- /dev/null
+++ b/src/tint/lang/core/constant/invalid.cc
@@ -0,0 +1,45 @@
+// Copyright 2024 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "src/tint/lang/core/constant/invalid.h"
+
+#include "src/tint/lang/core/constant/manager.h"
+#include "src/tint/lang/core/type/invalid.h"
+
+TINT_INSTANTIATE_TYPEINFO(tint::core::constant::Invalid);
+
+namespace tint::core::constant {
+
+Invalid::Invalid(const core::type::Invalid* ty) : type(ty) {}
+
+Invalid::~Invalid() = default;
+
+const Invalid* Invalid::Clone(CloneContext& ctx) const {
+ return ctx.dst.Invalid();
+}
+
+} // namespace tint::core::constant
diff --git a/src/tint/lang/core/constant/invalid.h b/src/tint/lang/core/constant/invalid.h
new file mode 100644
index 0000000..e767172
--- /dev/null
+++ b/src/tint/lang/core/constant/invalid.h
@@ -0,0 +1,79 @@
+// Copyright 2024 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef SRC_TINT_LANG_CORE_CONSTANT_INVALID_H_
+#define SRC_TINT_LANG_CORE_CONSTANT_INVALID_H_
+
+#include "src/tint/lang/core/constant/value.h"
+#include "src/tint/lang/core/type/invalid.h"
+#include "src/tint/utils/rtti/castable.h"
+
+namespace tint::core::constant {
+
+/// Invalid represents an invalid constant, used as a placeholder in a failed parse / resolve.
+class Invalid : public Castable<Invalid, Value> {
+ public:
+ /// Constructor
+ /// @param ty the Invalid type
+ explicit Invalid(const core::type::Invalid* ty);
+ ~Invalid() override;
+
+ /// @returns the type of the Invalid
+ const core::type::Type* Type() const override { return type; }
+
+ /// Retrieve item at index @p i
+ /// @param i the index to retrieve
+ /// @returns the element, or nullptr if out of bounds
+ const Value* Index([[maybe_unused]] size_t i) const override { return nullptr; }
+
+ /// @copydoc Value::NumElements()
+ size_t NumElements() const override { return 0; }
+
+ /// @returns true if the element is zero
+ bool AllZero() const override { return false; }
+ /// @returns true if the element is zero
+ bool AnyZero() const override { return false; }
+
+ /// @returns the hash for the Invalid
+ HashCode Hash() const override { return tint::Hash(type); }
+
+ /// Clones the constant into the provided context
+ /// @param ctx the clone context
+ /// @returns the cloned node
+ const Invalid* Clone(CloneContext& ctx) const override;
+
+ /// The Invalid type
+ core::type::Invalid const* const type;
+
+ protected:
+ /// @returns a monostate variant.
+ std::variant<std::monostate, AInt, AFloat> InternalValue() const override { return {}; }
+};
+
+} // namespace tint::core::constant
+
+#endif // SRC_TINT_LANG_CORE_CONSTANT_INVALID_H_
diff --git a/src/tint/lang/core/constant/invalid_test.cc b/src/tint/lang/core/constant/invalid_test.cc
new file mode 100644
index 0000000..bcbcb7a
--- /dev/null
+++ b/src/tint/lang/core/constant/invalid_test.cc
@@ -0,0 +1,73 @@
+// Copyright 2024 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "src/tint/lang/core/constant/invalid.h"
+
+#include "src/tint/lang/core/constant/helper_test.h"
+#include "src/tint/lang/core/constant/scalar.h"
+#include "src/tint/lang/core/fluent_types.h"
+
+using namespace tint::core::number_suffixes; // NOLINT
+using namespace tint::core::fluent_types; // NOLINT
+
+namespace tint::core::constant {
+namespace {
+
+using ConstantTest_Invalid = TestHelper;
+
+TEST_F(ConstantTest_Invalid, AllZero) {
+ auto* invalid = constants.Invalid();
+ EXPECT_FALSE(invalid->AllZero());
+}
+
+TEST_F(ConstantTest_Invalid, AnyZero) {
+ auto* invalid = constants.Invalid();
+ EXPECT_FALSE(invalid->AnyZero());
+}
+
+TEST_F(ConstantTest_Invalid, Index) {
+ auto* invalid = constants.Invalid();
+ EXPECT_EQ(invalid->Index(0), nullptr);
+ EXPECT_EQ(invalid->Index(1), nullptr);
+ EXPECT_EQ(invalid->Index(2), nullptr);
+}
+
+TEST_F(ConstantTest_Invalid, Clone) {
+ auto* invalid = constants.Invalid();
+
+ constant::Manager mgr;
+ constant::CloneContext ctx{core::type::CloneContext{{nullptr}, {nullptr, &mgr.types}}, mgr};
+
+ auto* cloned = invalid->Clone(ctx);
+ EXPECT_NE(cloned, invalid);
+ ASSERT_NE(cloned, nullptr);
+ EXPECT_TRUE(cloned->type->Is<core::type::Invalid>());
+ EXPECT_TRUE(cloned->Is<core::constant::Invalid>());
+}
+
+} // namespace
+} // namespace tint::core::constant
diff --git a/src/tint/lang/core/constant/manager.cc b/src/tint/lang/core/constant/manager.cc
index ecd4a38..bf8a822 100644
--- a/src/tint/lang/core/constant/manager.cc
+++ b/src/tint/lang/core/constant/manager.cc
@@ -28,6 +28,7 @@
#include "src/tint/lang/core/constant/manager.h"
#include "src/tint/lang/core/constant/composite.h"
+#include "src/tint/lang/core/constant/invalid.h"
#include "src/tint/lang/core/constant/scalar.h"
#include "src/tint/lang/core/constant/splat.h"
#include "src/tint/lang/core/type/abstract_float.h"
@@ -162,7 +163,12 @@
[&](const core::type::F32*) { return Get(f32(0)); }, //
[&](const core::type::F16*) { return Get(f16(0)); }, //
[&](const core::type::Bool*) { return Get(false); }, //
+ [&](const core::type::Invalid*) { return Invalid(); }, //
TINT_ICE_ON_NO_MATCH);
}
+const constant::Invalid* Manager::Invalid() {
+ return values_.Get<constant::Invalid>(types.invalid());
+}
+
} // namespace tint::core::constant
diff --git a/src/tint/lang/core/constant/manager.h b/src/tint/lang/core/constant/manager.h
index 43497db..7105996 100644
--- a/src/tint/lang/core/constant/manager.h
+++ b/src/tint/lang/core/constant/manager.h
@@ -30,6 +30,7 @@
#include <utility>
+#include "src/tint/lang/core/constant/invalid.h"
#include "src/tint/lang/core/constant/value.h"
#include "src/tint/lang/core/number.h"
#include "src/tint/lang/core/type/manager.h"
@@ -144,6 +145,10 @@
/// @returns a constant zero-value for the type
const Value* Zero(const core::type::Type* type);
+ /// Constructs an invalid constant
+ /// @returns an invalid constant
+ const constant::Invalid* Invalid();
+
/// The type manager
core::type::Manager types;
diff --git a/src/tint/lang/core/constant/splat_test.cc b/src/tint/lang/core/constant/splat_test.cc
index 553cf14..10c67f2 100644
--- a/src/tint/lang/core/constant/splat_test.cc
+++ b/src/tint/lang/core/constant/splat_test.cc
@@ -80,6 +80,7 @@
ASSERT_NE(sp->Index(0), nullptr);
ASSERT_NE(sp->Index(1), nullptr);
ASSERT_NE(sp->Index(2), nullptr);
+ EXPECT_EQ(sp->Index(3), nullptr);
EXPECT_EQ(sp->Index(0)->As<Scalar<f32>>()->ValueOf(), 1.f);
EXPECT_EQ(sp->Index(1)->As<Scalar<f32>>()->ValueOf(), 1.f);
@@ -95,6 +96,7 @@
constant::CloneContext ctx{core::type::CloneContext{{nullptr}, {nullptr, &mgr.types}}, mgr};
auto* r = sp->Clone(ctx);
+ EXPECT_NE(r, sp);
ASSERT_NE(r, nullptr);
EXPECT_TRUE(r->type->Is<core::type::Vector>());
EXPECT_TRUE(r->el->Is<Scalar<i32>>());
diff --git a/src/tint/lang/core/constant/value.cc b/src/tint/lang/core/constant/value.cc
index f426010..97a64f1 100644
--- a/src/tint/lang/core/constant/value.cc
+++ b/src/tint/lang/core/constant/value.cc
@@ -29,6 +29,7 @@
#include "src/tint/lang/core/constant/splat.h"
#include "src/tint/lang/core/type/array.h"
+#include "src/tint/lang/core/type/invalid.h"
#include "src/tint/lang/core/type/matrix.h"
#include "src/tint/lang/core/type/struct.h"
#include "src/tint/lang/core/type/vector.h"
@@ -106,13 +107,8 @@
}
return false;
},
- [&](Default) {
- auto va = InternalValue();
- auto vb = b->InternalValue();
- TINT_ASSERT(!std::holds_alternative<std::monostate>(va));
- TINT_ASSERT(!std::holds_alternative<std::monostate>(vb));
- return va == vb;
- });
+ [&](const core::type::Invalid*) { return true; },
+ [&](Default) { return InternalValue() == b->InternalValue(); });
}
} // namespace tint::core::constant
diff --git a/src/tint/lang/core/core.def b/src/tint/lang/core/core.def
index 0f2d0d8..175f61c 100644
--- a/src/tint/lang/core/core.def
+++ b/src/tint/lang/core/core.def
@@ -161,6 +161,8 @@
texture_storage_3d
// https://www.w3.org/TR/WGSL/#external-texture-type
texture_external
+ // chromium_internal_input_attachments
+ input_attachment
// Internal types.
__packed_vec3 // note: not core type, but used by legacy MSL writer
@@ -217,6 +219,9 @@
// framebuffer-fetch input
color
+
+ // chromium_internal_input_attachments
+ input_attachment_index
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/src/tint/lang/core/ir/binary/decode.cc b/src/tint/lang/core/ir/binary/decode.cc
index 780afd2..1960c60 100644
--- a/src/tint/lang/core/ir/binary/decode.cc
+++ b/src/tint/lang/core/ir/binary/decode.cc
@@ -50,8 +50,9 @@
namespace {
struct Decoder {
- pb::Module& mod_in_;
- Module& mod_out_;
+ const pb::Module& mod_in_;
+
+ Module mod_out_{};
Vector<ir::Block*, 32> blocks_{};
Vector<const type::Type*, 32> types_{};
Vector<const core::constant::Value*, 32> constant_values_{};
@@ -65,7 +66,7 @@
Vector<ir::BreakIf*, 32> break_ifs_{};
Vector<ir::Continue*, 32> continues_{};
- void Decode() {
+ Result<Module> Decode() {
{
const size_t n = static_cast<size_t>(mod_in_.types().size());
types_.Reserve(n);
@@ -132,6 +133,8 @@
for (auto* cont : continues_) {
InferControlInstruction(cont, &Continue::SetLoop);
}
+
+ return std::move(mod_out_);
}
template <typename EXIT, typename CTRL_INST>
@@ -1395,10 +1398,11 @@
return Failure{"failed to deserialize protobuf"};
}
- Module mod_out;
- Decoder{mod_in, mod_out}.Decode();
+ return Decode(mod_in);
+}
- return mod_out;
+Result<Module> Decode(const pb::Module& mod_in) {
+ return Decoder{mod_in}.Decode();
}
} // namespace tint::core::ir::binary
diff --git a/src/tint/lang/core/ir/binary/decode.h b/src/tint/lang/core/ir/binary/decode.h
index d4810b3..3e1a3ed 100644
--- a/src/tint/lang/core/ir/binary/decode.h
+++ b/src/tint/lang/core/ir/binary/decode.h
@@ -30,15 +30,22 @@
#include "src/tint/utils/result/result.h"
-// Forward declarartion
+// Forward declarations
namespace tint::core::ir {
class Module;
} // namespace tint::core::ir
+namespace tint::core::ir::binary::pb {
+class Module;
+} // namespace tint::core::ir::binary::pb
namespace tint::core::ir::binary {
+/// @returns the decoded Module from the serialized protobuf.
Result<Module> Decode(Slice<const std::byte> encoded);
+/// @returns the decoded Module from the protobuf.
+Result<Module> Decode(const pb::Module& module);
+
} // namespace tint::core::ir::binary
#endif // SRC_TINT_LANG_CORE_IR_BINARY_DECODE_H_
diff --git a/src/tint/lang/core/ir/builder.h b/src/tint/lang/core/ir/builder.h
index e3b797b..48cad54 100644
--- a/src/tint/lang/core/ir/builder.h
+++ b/src/tint/lang/core/ir/builder.h
@@ -361,6 +361,10 @@
return Constant(ConstantValue(v));
}
+ /// Creates a new invalid ir::Constant
+ /// @returns the new constant
+ ir::Constant* InvalidConstant() { return Constant(ir.constant_values.Invalid()); }
+
/// Retrieves the inner constant from an ir::Constant
/// @param constant the ir constant
/// @returns the core::constant::Value inside the constant
diff --git a/src/tint/lang/core/ir/transform/BUILD.bazel b/src/tint/lang/core/ir/transform/BUILD.bazel
index 3ea71c4..6444ea9 100644
--- a/src/tint/lang/core/ir/transform/BUILD.bazel
+++ b/src/tint/lang/core/ir/transform/BUILD.bazel
@@ -40,6 +40,7 @@
name = "transform",
srcs = [
"add_empty_entry_point.cc",
+ "array_length_from_uniform.cc",
"bgra8unorm_polyfill.cc",
"binary_polyfill.cc",
"binding_remapper.cc",
@@ -60,6 +61,7 @@
],
hdrs = [
"add_empty_entry_point.h",
+ "array_length_from_uniform.h",
"bgra8unorm_polyfill.h",
"binary_polyfill.h",
"binding_remapper.h",
@@ -109,6 +111,7 @@
alwayslink = True,
srcs = [
"add_empty_entry_point_test.cc",
+ "array_length_from_uniform_test.cc",
"bgra8unorm_polyfill_test.cc",
"binary_polyfill_test.cc",
"binding_remapper_test.cc",
diff --git a/src/tint/lang/core/ir/transform/BUILD.cmake b/src/tint/lang/core/ir/transform/BUILD.cmake
index f3a8b32..d8c3431 100644
--- a/src/tint/lang/core/ir/transform/BUILD.cmake
+++ b/src/tint/lang/core/ir/transform/BUILD.cmake
@@ -43,6 +43,8 @@
tint_add_target(tint_lang_core_ir_transform lib
lang/core/ir/transform/add_empty_entry_point.cc
lang/core/ir/transform/add_empty_entry_point.h
+ lang/core/ir/transform/array_length_from_uniform.cc
+ lang/core/ir/transform/array_length_from_uniform.h
lang/core/ir/transform/bgra8unorm_polyfill.cc
lang/core/ir/transform/bgra8unorm_polyfill.h
lang/core/ir/transform/binary_polyfill.cc
@@ -109,6 +111,7 @@
################################################################################
tint_add_target(tint_lang_core_ir_transform_test test
lang/core/ir/transform/add_empty_entry_point_test.cc
+ lang/core/ir/transform/array_length_from_uniform_test.cc
lang/core/ir/transform/bgra8unorm_polyfill_test.cc
lang/core/ir/transform/binary_polyfill_test.cc
lang/core/ir/transform/binding_remapper_test.cc
@@ -189,6 +192,7 @@
################################################################################
tint_add_target(tint_lang_core_ir_transform_fuzz fuzz
lang/core/ir/transform/add_empty_entry_point_fuzz.cc
+ lang/core/ir/transform/array_length_from_uniform_fuzz.cc
lang/core/ir/transform/bgra8unorm_polyfill_fuzz.cc
lang/core/ir/transform/binary_polyfill_fuzz.cc
lang/core/ir/transform/binding_remapper_fuzz.cc
diff --git a/src/tint/lang/core/ir/transform/BUILD.gn b/src/tint/lang/core/ir/transform/BUILD.gn
index db194b7..16765ad 100644
--- a/src/tint/lang/core/ir/transform/BUILD.gn
+++ b/src/tint/lang/core/ir/transform/BUILD.gn
@@ -46,6 +46,8 @@
sources = [
"add_empty_entry_point.cc",
"add_empty_entry_point.h",
+ "array_length_from_uniform.cc",
+ "array_length_from_uniform.h",
"bgra8unorm_polyfill.cc",
"bgra8unorm_polyfill.h",
"binary_polyfill.cc",
@@ -109,6 +111,7 @@
tint_unittests_source_set("unittests") {
sources = [
"add_empty_entry_point_test.cc",
+ "array_length_from_uniform_test.cc",
"bgra8unorm_polyfill_test.cc",
"binary_polyfill_test.cc",
"binding_remapper_test.cc",
@@ -180,6 +183,7 @@
tint_fuzz_source_set("fuzz") {
sources = [
"add_empty_entry_point_fuzz.cc",
+ "array_length_from_uniform_fuzz.cc",
"bgra8unorm_polyfill_fuzz.cc",
"binary_polyfill_fuzz.cc",
"binding_remapper_fuzz.cc",
diff --git a/src/tint/lang/core/ir/transform/array_length_from_uniform.cc b/src/tint/lang/core/ir/transform/array_length_from_uniform.cc
new file mode 100644
index 0000000..79dfb0a
--- /dev/null
+++ b/src/tint/lang/core/ir/transform/array_length_from_uniform.cc
@@ -0,0 +1,235 @@
+// Copyright 2024 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "src/tint/lang/core/ir/transform/array_length_from_uniform.h"
+
+#include <algorithm>
+#include <utility>
+
+#include "src/tint/lang/core/ir/builder.h"
+#include "src/tint/lang/core/ir/module.h"
+#include "src/tint/lang/core/ir/validator.h"
+
+using namespace tint::core::fluent_types; // NOLINT
+using namespace tint::core::number_suffixes; // NOLINT
+
+namespace tint::core::ir::transform {
+
+namespace {
+
+/// PIMPL state for the transform.
+struct State {
+ /// The IR module.
+ Module& ir;
+
+ /// The binding point to use for the uniform buffer.
+ BindingPoint ubo_binding;
+
+ /// The map from binding point to the element index which holds the size of that buffer.
+ const std::unordered_map<BindingPoint, uint32_t>& bindpoint_to_size_index;
+
+ /// The IR builder.
+ core::ir::Builder b{ir};
+
+ /// The type manager.
+ core::type::Manager& ty{ir.Types()};
+
+ /// The uniform buffer variable that holds the total size of each storage buffer.
+ Var* buffer_sizes_var = nullptr;
+
+ /// A map from an array function parameter to the function parameter that holds its length.
+ Hashmap<FunctionParam*, FunctionParam*, 8> array_param_to_length_param{};
+
+ /// Process the module.
+ void Process() {
+ // Look for and replace calls to the array length builtin.
+ for (auto* inst : ir.Instructions()) {
+ if (auto* call = inst->As<CoreBuiltinCall>()) {
+ if (call->Func() == BuiltinFn::kArrayLength) {
+ MaybeReplace(call);
+ }
+ }
+ }
+ }
+
+ /// Replace a call to an array length builtin, if the variable appears in the bindpoint map.
+ /// @param call the arrayLength call to replace
+ void MaybeReplace(CoreBuiltinCall* call) {
+ if (auto* length = GetComputedLength(call->Args()[0], call)) {
+ call->Result(0)->ReplaceAllUsesWith(length);
+ call->Destroy();
+ }
+ }
+
+ /// Get the computed length value for a runtime-sized array pointer.
+ /// @param ptr the pointer to the runtime-sized array
+ /// @param insertion_point the insertion point for new instructions
+ /// @returns the computed length, or nullptr if the original builtin should be used
+ Value* GetComputedLength(Value* ptr, Instruction* insertion_point) {
+ // Trace back from the value until we reach the originating variable.
+ while (true) {
+ if (auto* param = ptr->As<FunctionParam>()) {
+ // The length of an array pointer passed as a function parameter will be passed as
+ // an additional parameter to the function.
+ return GetArrayLengthParam(param);
+ }
+
+ if (auto* result = ptr->As<InstructionResult>()) {
+ if (auto* var = result->Instruction()->As<Var>()) {
+ // We found the originating variable, so compute its array length.
+ return ComputeArrayLength(var, insertion_point);
+ }
+ if (auto* access = result->Instruction()->As<Access>()) {
+ ptr = access->Object();
+ continue;
+ }
+ if (auto* let = result->Instruction()->As<Let>()) {
+ ptr = let->Value();
+ continue;
+ }
+ TINT_UNREACHABLE() << "unhandled source of a storage buffer pointer: "
+ << result->Instruction()->TypeInfo().name;
+ }
+ TINT_UNREACHABLE() << "unhandled source of a storage buffer pointer: "
+ << ptr->TypeInfo().name;
+ }
+ }
+
+ /// Get (or create) the array length parameter that corresponds to an array parameter.
+ /// @param array_param the array parameter
+ /// @returns the array length parameter
+ FunctionParam* GetArrayLengthParam(FunctionParam* array_param) {
+ return array_param_to_length_param.GetOrAdd(array_param, [&] {
+ // Add a new parameter to receive the array length.
+ auto* length = b.FunctionParam<u32>("tint_array_length");
+ array_param->Function()->AppendParam(length);
+
+ // Update callsites of this function to pass the array length to it.
+ array_param->Function()->ForEachUse([&](core::ir::Usage use) {
+ if (auto* call = use.instruction->As<core::ir::UserCall>()) {
+ // Get the length of the array in the calling function and pass that.
+ auto* arg = call->Args()[array_param->Index()];
+ call->AppendArg(GetComputedLength(arg, call));
+ }
+ });
+
+ return length;
+ });
+ }
+
+ /// Compute the array length of the runtime-sized array that is inside a storage buffer
+ /// variable. If the variable's binding point is not found in the bindpoint map, returns nullptr
+ /// to indicate that the original arrayLength builtin should be used instead.
+ ///
+ /// @param var the storage buffer variable that contains the runtime-sized array
+ /// @param insertion_point the insertion point for new instructions
+ /// @returns the length of the array, or nullptr if the original builtin should be used
+ Value* ComputeArrayLength(Var* var, Instruction* insertion_point) {
+ auto binding = var->BindingPoint();
+ TINT_ASSERT(binding);
+
+ auto idx_it = bindpoint_to_size_index.find(*binding);
+ if (idx_it == bindpoint_to_size_index.end()) {
+ // If the bindpoint_to_size_index map does not contain an entry for the storage buffer,
+ // then we preserve the arrayLength() call.
+ return nullptr;
+ }
+
+ Value* result = nullptr;
+ b.InsertBefore(insertion_point, [&] {
+ // Load the total storage buffer size from the uniform buffer.
+ // The sizes are packed into vec4s to satisfy the 16-byte alignment requirement for
+ // array elements in uniform buffers, so we have to find the vector and element that
+ // correspond to the index that we want.
+ const uint32_t size_index = idx_it->second;
+ const uint32_t array_index = size_index / 4;
+ const uint32_t vec_index = size_index % 4;
+ auto* vec_ptr = b.Access<ptr<uniform, vec4<u32>>>(BufferSizes(), u32(array_index));
+ auto* total_buffer_size = b.LoadVectorElement(vec_ptr, u32(vec_index))->Result(0);
+
+ // Calculate actual array length:
+ // total_buffer_size - array_offset
+ // array_length = --------------------------------
+ // array_stride
+ auto* array_size = total_buffer_size;
+ auto* storage_buffer_type = var->Result(0)->Type()->UnwrapPtr();
+ const type::Array* array_type = nullptr;
+ if (auto* str = storage_buffer_type->As<core::type::Struct>()) {
+ // The variable is a struct, so subtract the byte offset of the array member.
+ auto* member = str->Members().Back();
+ array_type = member->Type()->As<core::type::Array>();
+ array_size = b.Subtract<u32>(total_buffer_size, u32(member->Offset()))->Result(0);
+ } else {
+ array_type = storage_buffer_type->As<core::type::Array>();
+ }
+ TINT_ASSERT(array_type);
+ result = b.Divide<u32>(array_size, u32(array_type->Stride()))->Result(0);
+ });
+ return result;
+ }
+
+ /// Get (or create, on first call) the uniform buffer that contains the storage buffer sizes.
+ /// @returns the uniform buffer pointer
+ Value* BufferSizes() {
+ if (buffer_sizes_var) {
+ return buffer_sizes_var->Result(0);
+ }
+
+ // Find the largest index declared in the map, in order to determine the number of elements
+ // needed in the array of buffer sizes.
+ // The buffer sizes will be packed into vec4s to satisfy the 16-byte alignment requirement
+ // for array elements in uniform buffers.
+ uint32_t max_index = 0;
+ for (auto& entry : bindpoint_to_size_index) {
+ max_index = std::max(max_index, entry.second);
+ }
+ uint32_t num_elements = (max_index / 4) + 1;
+ b.Append(ir.root_block, [&] {
+ buffer_sizes_var = b.Var("tint_storage_buffer_sizes",
+ ty.ptr<uniform>(ty.array(ty.vec4<u32>(), num_elements)));
+ });
+ return buffer_sizes_var->Result(0);
+ }
+};
+
+} // namespace
+
+Result<SuccessType> ArrayLengthFromUniform(
+ Module& ir,
+ BindingPoint ubo_binding,
+ const std::unordered_map<BindingPoint, uint32_t>& bindpoint_to_size_index) {
+ auto result = ValidateAndDumpIfNeeded(ir, "ArrayLengthFromUniform transform");
+ if (result != Success) {
+ return result;
+ }
+
+ State{ir, ubo_binding, bindpoint_to_size_index}.Process();
+
+ return Success;
+}
+
+} // namespace tint::core::ir::transform
diff --git a/src/tint/lang/core/ir/transform/array_length_from_uniform.h b/src/tint/lang/core/ir/transform/array_length_from_uniform.h
new file mode 100644
index 0000000..1128aa8
--- /dev/null
+++ b/src/tint/lang/core/ir/transform/array_length_from_uniform.h
@@ -0,0 +1,67 @@
+// Copyright 2024 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef SRC_TINT_LANG_CORE_IR_TRANSFORM_ARRAY_LENGTH_FROM_UNIFORM_H_
+#define SRC_TINT_LANG_CORE_IR_TRANSFORM_ARRAY_LENGTH_FROM_UNIFORM_H_
+
+#include <unordered_map>
+
+#include "src/tint/api/common/binding_point.h"
+#include "src/tint/utils/result/result.h"
+
+// Forward declarations.
+namespace tint::core::ir {
+class Module;
+}
+
+namespace tint::core::ir::transform {
+
+/// ArrayLengthFromUniform is a transform that replaces calls to the arrayLength() builtin by
+/// calculating the array length from the total size of the storage buffer, which is received via a
+/// uniform buffer.
+///
+/// The generated uniform buffer will have the form:
+/// ```
+/// @group(0) @binding(30)
+/// var<uniform> buffer_size_ubo : array<vec4<u32>, 8>;
+/// ```
+/// The binding group and number used for this uniform buffer is provided via the transform config.
+/// The transform config also defines the mapping from a storage buffer's `BindingPoint` to the
+/// element index that will be used to get the size of that buffer.
+///
+/// @param module the module to transform
+/// @param ubo_binding the binding point to use for the uniform buffer
+/// @param bindpoint_to_size_index the map from binding point to an index which holds the size
+/// @returns success or failure
+Result<SuccessType> ArrayLengthFromUniform(
+ Module& module,
+ BindingPoint ubo_binding,
+ const std::unordered_map<BindingPoint, uint32_t>& bindpoint_to_size_index);
+
+} // namespace tint::core::ir::transform
+
+#endif // SRC_TINT_LANG_CORE_IR_TRANSFORM_ARRAY_LENGTH_FROM_UNIFORM_H_
diff --git a/src/tint/lang/core/ir/transform/array_length_from_uniform_fuzz.cc b/src/tint/lang/core/ir/transform/array_length_from_uniform_fuzz.cc
new file mode 100644
index 0000000..8228b05
--- /dev/null
+++ b/src/tint/lang/core/ir/transform/array_length_from_uniform_fuzz.cc
@@ -0,0 +1,54 @@
+// Copyright 2024 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "src/tint/lang/core/ir/transform/array_length_from_uniform.h"
+
+#include "src/tint/cmd/fuzz/ir/fuzz.h"
+#include "src/tint/lang/core/ir/validator.h"
+
+namespace tint::core::ir::transform {
+namespace {
+
+void ArrayLengthFromUniformFuzzer(
+ Module& module,
+ BindingPoint ubo_binding,
+ const std::unordered_map<BindingPoint, uint32_t>& bindpoint_to_size_index) {
+ if (auto res = ArrayLengthFromUniform(module, ubo_binding, bindpoint_to_size_index);
+ res != Success) {
+ return;
+ }
+
+ Capabilities capabilities;
+ if (auto res = Validate(module, capabilities); res != Success) {
+ TINT_ICE() << "result of ArrayLengthFromUniform failed IR validation\n" << res.Failure();
+ }
+}
+
+} // namespace
+} // namespace tint::core::ir::transform
+
+TINT_IR_MODULE_FUZZER(tint::core::ir::transform::ArrayLengthFromUniformFuzzer);
diff --git a/src/tint/lang/core/ir/transform/array_length_from_uniform_test.cc b/src/tint/lang/core/ir/transform/array_length_from_uniform_test.cc
new file mode 100644
index 0000000..b418de9
--- /dev/null
+++ b/src/tint/lang/core/ir/transform/array_length_from_uniform_test.cc
@@ -0,0 +1,1069 @@
+// Copyright 2024 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "src/tint/lang/core/ir/transform/array_length_from_uniform.h"
+
+#include <utility>
+
+#include "src/tint/lang/core/ir/transform/helper_test.h"
+
+namespace tint::core::ir::transform {
+namespace {
+
+using namespace tint::core::fluent_types; // NOLINT
+using namespace tint::core::number_suffixes; // NOLINT
+
+using IR_ArrayLengthFromUniformTest = TransformTest;
+
+TEST_F(IR_ArrayLengthFromUniformTest, NoModify_UserFunction) {
+ auto* arr = ty.array<i32>();
+ auto* arr_ptr = ty.ptr<storage>(arr);
+
+ auto* buffer = b.Var("buffer", arr_ptr);
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* user_func = b.Function("arrayLength", ty.u32());
+ auto* param = b.FunctionParam("arr", arr_ptr);
+ user_func->SetParams({param});
+ b.Append(user_func->Block(), [&] { //
+ b.Return(user_func, 42_u);
+ });
+
+ auto* func = b.Function("foo", ty.void_());
+ b.Append(func->Block(), [&] {
+ b.Call(user_func, buffer);
+ b.Return(func);
+ });
+
+ auto* src = R"(
+$B1: { # root
+ %buffer:ptr<storage, array<i32>, read_write> = var @binding_point(0, 0)
+}
+
+%arrayLength = func(%arr:ptr<storage, array<i32>, read_write>):u32 {
+ $B2: {
+ ret 42u
+ }
+}
+%foo = func():void {
+ $B3: {
+ %5:u32 = call %arrayLength, %buffer
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = src;
+
+ std::unordered_map<BindingPoint, uint32_t> bindpoint_to_index;
+ bindpoint_to_index[{0, 0}] = 0;
+ Run(ArrayLengthFromUniform, BindingPoint{1, 2}, bindpoint_to_index);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_ArrayLengthFromUniformTest, DirectUse) {
+ auto* arr = ty.array<i32>();
+ auto* arr_ptr = ty.ptr<storage>(arr);
+
+ auto* buffer = b.Var("buffer", arr_ptr);
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* func = b.Function("foo", ty.u32());
+ b.Append(func->Block(), [&] {
+ auto* len = b.Call<u32>(BuiltinFn::kArrayLength, buffer);
+ b.Return(func, len);
+ });
+
+ auto* src = R"(
+$B1: { # root
+ %buffer:ptr<storage, array<i32>, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func():u32 {
+ $B2: {
+ %3:u32 = arrayLength %buffer
+ ret %3
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+$B1: { # root
+ %buffer:ptr<storage, array<i32>, read_write> = var @binding_point(0, 0)
+ %tint_storage_buffer_sizes:ptr<uniform, array<vec4<u32>, 1>, read> = var
+}
+
+%foo = func():u32 {
+ $B2: {
+ %4:ptr<uniform, vec4<u32>, read> = access %tint_storage_buffer_sizes, 0u
+ %5:u32 = load_vector_element %4, 0u
+ %6:u32 = div %5, 4u
+ ret %6
+ }
+}
+)";
+
+ std::unordered_map<BindingPoint, uint32_t> bindpoint_to_index;
+ bindpoint_to_index[{0, 0}] = 0;
+ Run(ArrayLengthFromUniform, BindingPoint{1, 2}, bindpoint_to_index);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_ArrayLengthFromUniformTest, DirectUse_NonZeroIndex) {
+ auto* arr = ty.array<i32>();
+ auto* arr_ptr = ty.ptr<storage>(arr);
+
+ auto* buffer = b.Var("buffer", arr_ptr);
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* func = b.Function("foo", ty.u32());
+ b.Append(func->Block(), [&] {
+ auto* len = b.Call<u32>(BuiltinFn::kArrayLength, buffer);
+ b.Return(func, len);
+ });
+
+ auto* src = R"(
+$B1: { # root
+ %buffer:ptr<storage, array<i32>, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func():u32 {
+ $B2: {
+ %3:u32 = arrayLength %buffer
+ ret %3
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+$B1: { # root
+ %buffer:ptr<storage, array<i32>, read_write> = var @binding_point(0, 0)
+ %tint_storage_buffer_sizes:ptr<uniform, array<vec4<u32>, 2>, read> = var
+}
+
+%foo = func():u32 {
+ $B2: {
+ %4:ptr<uniform, vec4<u32>, read> = access %tint_storage_buffer_sizes, 1u
+ %5:u32 = load_vector_element %4, 3u
+ %6:u32 = div %5, 4u
+ ret %6
+ }
+}
+)";
+
+ std::unordered_map<BindingPoint, uint32_t> bindpoint_to_index;
+ bindpoint_to_index[{0, 0}] = 7;
+ Run(ArrayLengthFromUniform, BindingPoint{1, 2}, bindpoint_to_index);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_ArrayLengthFromUniformTest, DirectUse_NotInMap) {
+ auto* arr = ty.array<i32>();
+ auto* arr_ptr = ty.ptr<storage>(arr);
+
+ auto* buffer = b.Var("buffer", arr_ptr);
+ buffer->SetBindingPoint(0, 1);
+ mod.root_block->Append(buffer);
+
+ auto* func = b.Function("foo", ty.u32());
+ b.Append(func->Block(), [&] {
+ auto* len = b.Call<u32>(BuiltinFn::kArrayLength, buffer);
+ b.Return(func, len);
+ });
+
+ auto* src = R"(
+$B1: { # root
+ %buffer:ptr<storage, array<i32>, read_write> = var @binding_point(0, 1)
+}
+
+%foo = func():u32 {
+ $B2: {
+ %3:u32 = arrayLength %buffer
+ ret %3
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+$B1: { # root
+ %buffer:ptr<storage, array<i32>, read_write> = var @binding_point(0, 1)
+}
+
+%foo = func():u32 {
+ $B2: {
+ %3:u32 = arrayLength %buffer
+ ret %3
+ }
+}
+)";
+
+ std::unordered_map<BindingPoint, uint32_t> bindpoint_to_index;
+ bindpoint_to_index[{0, 0}] = 0;
+ Run(ArrayLengthFromUniform, BindingPoint{1, 2}, bindpoint_to_index);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_ArrayLengthFromUniformTest, ViaAccess) {
+ auto* arr = ty.array<i32>();
+ auto* arr_ptr = ty.ptr<storage>(arr);
+
+ auto* buffer = b.Var("buffer", arr_ptr);
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* func = b.Function("foo", ty.u32());
+ b.Append(func->Block(), [&] {
+ auto* len = b.Call<u32>(BuiltinFn::kArrayLength, b.Access(arr_ptr, buffer));
+ b.Return(func, len);
+ });
+
+ auto* src = R"(
+$B1: { # root
+ %buffer:ptr<storage, array<i32>, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func():u32 {
+ $B2: {
+ %3:ptr<storage, array<i32>, read_write> = access %buffer
+ %4:u32 = arrayLength %3
+ ret %4
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+$B1: { # root
+ %buffer:ptr<storage, array<i32>, read_write> = var @binding_point(0, 0)
+ %tint_storage_buffer_sizes:ptr<uniform, array<vec4<u32>, 1>, read> = var
+}
+
+%foo = func():u32 {
+ $B2: {
+ %4:ptr<storage, array<i32>, read_write> = access %buffer
+ %5:ptr<uniform, vec4<u32>, read> = access %tint_storage_buffer_sizes, 0u
+ %6:u32 = load_vector_element %5, 0u
+ %7:u32 = div %6, 4u
+ ret %7
+ }
+}
+)";
+
+ std::unordered_map<BindingPoint, uint32_t> bindpoint_to_index;
+ bindpoint_to_index[{0, 0}] = 0;
+ Run(ArrayLengthFromUniform, BindingPoint{1, 2}, bindpoint_to_index);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_ArrayLengthFromUniformTest, ViaAccess_StructMember) {
+ auto* arr = ty.array<i32>();
+ auto* structure = ty.Struct(mod.symbols.New("MyStruct"), {
+ {mod.symbols.New("a"), arr},
+ });
+ auto* arr_ptr = ty.ptr<storage>(arr);
+ auto* structure_ptr = ty.ptr<storage>(structure);
+
+ auto* buffer = b.Var("buffer", structure_ptr);
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* func = b.Function("foo", ty.u32());
+ b.Append(func->Block(), [&] {
+ auto* len = b.Call<u32>(BuiltinFn::kArrayLength, b.Access(arr_ptr, buffer, 0_u));
+ b.Return(func, len);
+ });
+
+ auto* src = R"(
+MyStruct = struct @align(4) {
+ a:array<i32> @offset(0)
+}
+
+$B1: { # root
+ %buffer:ptr<storage, MyStruct, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func():u32 {
+ $B2: {
+ %3:ptr<storage, array<i32>, read_write> = access %buffer, 0u
+ %4:u32 = arrayLength %3
+ ret %4
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+MyStruct = struct @align(4) {
+ a:array<i32> @offset(0)
+}
+
+$B1: { # root
+ %buffer:ptr<storage, MyStruct, read_write> = var @binding_point(0, 0)
+ %tint_storage_buffer_sizes:ptr<uniform, array<vec4<u32>, 1>, read> = var
+}
+
+%foo = func():u32 {
+ $B2: {
+ %4:ptr<storage, array<i32>, read_write> = access %buffer, 0u
+ %5:ptr<uniform, vec4<u32>, read> = access %tint_storage_buffer_sizes, 0u
+ %6:u32 = load_vector_element %5, 0u
+ %7:u32 = sub %6, 0u
+ %8:u32 = div %7, 4u
+ ret %8
+ }
+}
+)";
+
+ std::unordered_map<BindingPoint, uint32_t> bindpoint_to_index;
+ bindpoint_to_index[{0, 0}] = 0;
+ Run(ArrayLengthFromUniform, BindingPoint{1, 2}, bindpoint_to_index);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_ArrayLengthFromUniformTest, ViaAccess_StructMember_NonZeroOffset) {
+ auto* arr = ty.array<i32>();
+ auto* structure = ty.Struct(mod.symbols.New("MyStruct"), {
+ {mod.symbols.New("u1"), ty.u32()},
+ {mod.symbols.New("u2"), ty.u32()},
+ {mod.symbols.New("u3"), ty.u32()},
+ {mod.symbols.New("u4"), ty.u32()},
+ {mod.symbols.New("u5"), ty.u32()},
+ {mod.symbols.New("a"), arr},
+ });
+ auto* arr_ptr = ty.ptr<storage>(arr);
+ auto* structure_ptr = ty.ptr<storage>(structure);
+
+ auto* buffer = b.Var("buffer", structure_ptr);
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* func = b.Function("foo", ty.u32());
+ b.Append(func->Block(), [&] {
+ auto* len = b.Call<u32>(BuiltinFn::kArrayLength, b.Access(arr_ptr, buffer, 5_u));
+ b.Return(func, len);
+ });
+
+ auto* src = R"(
+MyStruct = struct @align(4) {
+ u1:u32 @offset(0)
+ u2:u32 @offset(4)
+ u3:u32 @offset(8)
+ u4:u32 @offset(12)
+ u5:u32 @offset(16)
+ a:array<i32> @offset(20)
+}
+
+$B1: { # root
+ %buffer:ptr<storage, MyStruct, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func():u32 {
+ $B2: {
+ %3:ptr<storage, array<i32>, read_write> = access %buffer, 5u
+ %4:u32 = arrayLength %3
+ ret %4
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+MyStruct = struct @align(4) {
+ u1:u32 @offset(0)
+ u2:u32 @offset(4)
+ u3:u32 @offset(8)
+ u4:u32 @offset(12)
+ u5:u32 @offset(16)
+ a:array<i32> @offset(20)
+}
+
+$B1: { # root
+ %buffer:ptr<storage, MyStruct, read_write> = var @binding_point(0, 0)
+ %tint_storage_buffer_sizes:ptr<uniform, array<vec4<u32>, 1>, read> = var
+}
+
+%foo = func():u32 {
+ $B2: {
+ %4:ptr<storage, array<i32>, read_write> = access %buffer, 5u
+ %5:ptr<uniform, vec4<u32>, read> = access %tint_storage_buffer_sizes, 0u
+ %6:u32 = load_vector_element %5, 0u
+ %7:u32 = sub %6, 20u
+ %8:u32 = div %7, 4u
+ ret %8
+ }
+}
+)";
+
+ std::unordered_map<BindingPoint, uint32_t> bindpoint_to_index;
+ bindpoint_to_index[{0, 0}] = 0;
+ Run(ArrayLengthFromUniform, BindingPoint{1, 2}, bindpoint_to_index);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_ArrayLengthFromUniformTest, ViaLet) {
+ auto* arr = ty.array<i32>();
+ auto* arr_ptr = ty.ptr<storage>(arr);
+
+ auto* buffer = b.Var("buffer", arr_ptr);
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* func = b.Function("foo", ty.u32());
+ b.Append(func->Block(), [&] {
+ auto* len = b.Call<u32>(BuiltinFn::kArrayLength, b.Let("let", buffer));
+ b.Return(func, len);
+ });
+
+ auto* src = R"(
+$B1: { # root
+ %buffer:ptr<storage, array<i32>, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func():u32 {
+ $B2: {
+ %let:ptr<storage, array<i32>, read_write> = let %buffer
+ %4:u32 = arrayLength %let
+ ret %4
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+$B1: { # root
+ %buffer:ptr<storage, array<i32>, read_write> = var @binding_point(0, 0)
+ %tint_storage_buffer_sizes:ptr<uniform, array<vec4<u32>, 1>, read> = var
+}
+
+%foo = func():u32 {
+ $B2: {
+ %let:ptr<storage, array<i32>, read_write> = let %buffer
+ %5:ptr<uniform, vec4<u32>, read> = access %tint_storage_buffer_sizes, 0u
+ %6:u32 = load_vector_element %5, 0u
+ %7:u32 = div %6, 4u
+ ret %7
+ }
+}
+)";
+
+ std::unordered_map<BindingPoint, uint32_t> bindpoint_to_index;
+ bindpoint_to_index[{0, 0}] = 0;
+ Run(ArrayLengthFromUniform, BindingPoint{1, 2}, bindpoint_to_index);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_ArrayLengthFromUniformTest, ViaParameter) {
+ auto* arr = ty.array<i32>();
+ auto* arr_ptr = ty.ptr<storage>(arr);
+
+ auto* buffer = b.Var("buffer", arr_ptr);
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* bar = b.Function("bar", ty.u32());
+ auto* param = b.FunctionParam("param", arr_ptr);
+ bar->SetParams({param});
+ b.Append(bar->Block(), [&] {
+ auto* len = b.Call<u32>(BuiltinFn::kArrayLength, param);
+ b.Return(bar, len);
+ });
+
+ auto* foo = b.Function("foo", ty.u32());
+ b.Append(foo->Block(), [&] {
+ auto* len = b.Call<u32>(bar, buffer);
+ b.Return(foo, len);
+ });
+
+ auto* src = R"(
+$B1: { # root
+ %buffer:ptr<storage, array<i32>, read_write> = var @binding_point(0, 0)
+}
+
+%bar = func(%param:ptr<storage, array<i32>, read_write>):u32 {
+ $B2: {
+ %4:u32 = arrayLength %param
+ ret %4
+ }
+}
+%foo = func():u32 {
+ $B3: {
+ %6:u32 = call %bar, %buffer
+ ret %6
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+$B1: { # root
+ %buffer:ptr<storage, array<i32>, read_write> = var @binding_point(0, 0)
+ %tint_storage_buffer_sizes:ptr<uniform, array<vec4<u32>, 1>, read> = var
+}
+
+%bar = func(%param:ptr<storage, array<i32>, read_write>, %tint_array_length:u32):u32 {
+ $B2: {
+ ret %tint_array_length
+ }
+}
+%foo = func():u32 {
+ $B3: {
+ %7:ptr<uniform, vec4<u32>, read> = access %tint_storage_buffer_sizes, 0u
+ %8:u32 = load_vector_element %7, 0u
+ %9:u32 = div %8, 4u
+ %10:u32 = call %bar, %buffer, %9
+ ret %10
+ }
+}
+)";
+
+ std::unordered_map<BindingPoint, uint32_t> bindpoint_to_index;
+ bindpoint_to_index[{0, 0}] = 0;
+ Run(ArrayLengthFromUniform, BindingPoint{1, 2}, bindpoint_to_index);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_ArrayLengthFromUniformTest, ViaParameterChain) {
+ auto* arr = ty.array<i32>();
+ auto* arr_ptr = ty.ptr<storage>(arr);
+
+ auto* buffer = b.Var("buffer", arr_ptr);
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* zoo = b.Function("foo", ty.u32());
+ auto* param_zoo = b.FunctionParam("param_zoo", arr_ptr);
+ zoo->SetParams({param_zoo});
+ b.Append(zoo->Block(), [&] {
+ auto* len = b.Call<u32>(BuiltinFn::kArrayLength, param_zoo);
+ b.Return(zoo, len);
+ });
+
+ auto* bar = b.Function("foo", ty.u32());
+ auto* param_bar = b.FunctionParam("param_bar", arr_ptr);
+ bar->SetParams({param_bar});
+ b.Append(bar->Block(), [&] {
+ auto* len = b.Call<u32>(zoo, param_bar);
+ b.Return(bar, len);
+ });
+
+ auto* foo = b.Function("foo", ty.u32());
+ b.Append(foo->Block(), [&] {
+ auto* len = b.Call<u32>(bar, buffer);
+ b.Return(foo, len);
+ });
+
+ auto* src = R"(
+$B1: { # root
+ %buffer:ptr<storage, array<i32>, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func(%param_zoo:ptr<storage, array<i32>, read_write>):u32 {
+ $B2: {
+ %4:u32 = arrayLength %param_zoo
+ ret %4
+ }
+}
+%foo_1 = func(%param_bar:ptr<storage, array<i32>, read_write>):u32 { # %foo_1: 'foo'
+ $B3: {
+ %7:u32 = call %foo, %param_bar
+ ret %7
+ }
+}
+%foo_2 = func():u32 { # %foo_2: 'foo'
+ $B4: {
+ %9:u32 = call %foo_1, %buffer
+ ret %9
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+$B1: { # root
+ %buffer:ptr<storage, array<i32>, read_write> = var @binding_point(0, 0)
+ %tint_storage_buffer_sizes:ptr<uniform, array<vec4<u32>, 1>, read> = var
+}
+
+%foo = func(%param_zoo:ptr<storage, array<i32>, read_write>, %tint_array_length:u32):u32 {
+ $B2: {
+ ret %tint_array_length
+ }
+}
+%foo_1 = func(%param_bar:ptr<storage, array<i32>, read_write>, %tint_array_length_1:u32):u32 { # %foo_1: 'foo', %tint_array_length_1: 'tint_array_length'
+ $B3: {
+ %9:u32 = call %foo, %param_bar, %tint_array_length_1
+ ret %9
+ }
+}
+%foo_2 = func():u32 { # %foo_2: 'foo'
+ $B4: {
+ %11:ptr<uniform, vec4<u32>, read> = access %tint_storage_buffer_sizes, 0u
+ %12:u32 = load_vector_element %11, 0u
+ %13:u32 = div %12, 4u
+ %14:u32 = call %foo_1, %buffer, %13
+ ret %14
+ }
+}
+)";
+
+ std::unordered_map<BindingPoint, uint32_t> bindpoint_to_index;
+ bindpoint_to_index[{0, 0}] = 0;
+ Run(ArrayLengthFromUniform, BindingPoint{1, 2}, bindpoint_to_index);
+
+ EXPECT_EQ(expect, str());
+}
+
+// Test that we re-use the length parameter for multiple arrayLength calls on the same parameter.
+TEST_F(IR_ArrayLengthFromUniformTest, ViaParameter_MultipleCallsSameParameter) {
+ auto* arr = ty.array<i32>();
+ auto* arr_ptr = ty.ptr<storage>(arr);
+
+ auto* buffer = b.Var("buffer", arr_ptr);
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* bar = b.Function("bar", ty.u32());
+ auto* param = b.FunctionParam("param", arr_ptr);
+ bar->SetParams({param});
+ b.Append(bar->Block(), [&] {
+ auto* len_a = b.Call<u32>(BuiltinFn::kArrayLength, param);
+ auto* len_b = b.Call<u32>(BuiltinFn::kArrayLength, param);
+ auto* len_c = b.Call<u32>(BuiltinFn::kArrayLength, param);
+ b.Return(bar, b.Add<u32>(len_a, b.Add<u32>(len_b, len_c)));
+ });
+
+ auto* foo = b.Function("foo", ty.u32());
+ b.Append(foo->Block(), [&] {
+ auto* len = b.Call<u32>(bar, buffer);
+ b.Return(foo, len);
+ });
+
+ auto* src = R"(
+$B1: { # root
+ %buffer:ptr<storage, array<i32>, read_write> = var @binding_point(0, 0)
+}
+
+%bar = func(%param:ptr<storage, array<i32>, read_write>):u32 {
+ $B2: {
+ %4:u32 = arrayLength %param
+ %5:u32 = arrayLength %param
+ %6:u32 = arrayLength %param
+ %7:u32 = add %5, %6
+ %8:u32 = add %4, %7
+ ret %8
+ }
+}
+%foo = func():u32 {
+ $B3: {
+ %10:u32 = call %bar, %buffer
+ ret %10
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+$B1: { # root
+ %buffer:ptr<storage, array<i32>, read_write> = var @binding_point(0, 0)
+ %tint_storage_buffer_sizes:ptr<uniform, array<vec4<u32>, 1>, read> = var
+}
+
+%bar = func(%param:ptr<storage, array<i32>, read_write>, %tint_array_length:u32):u32 {
+ $B2: {
+ %6:u32 = add %tint_array_length, %tint_array_length
+ %7:u32 = add %tint_array_length, %6
+ ret %7
+ }
+}
+%foo = func():u32 {
+ $B3: {
+ %9:ptr<uniform, vec4<u32>, read> = access %tint_storage_buffer_sizes, 0u
+ %10:u32 = load_vector_element %9, 0u
+ %11:u32 = div %10, 4u
+ %12:u32 = call %bar, %buffer, %11
+ ret %12
+ }
+}
+)";
+
+ std::unordered_map<BindingPoint, uint32_t> bindpoint_to_index;
+ bindpoint_to_index[{0, 0}] = 0;
+ Run(ArrayLengthFromUniform, BindingPoint{1, 2}, bindpoint_to_index);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_ArrayLengthFromUniformTest, ViaParameter_MultipleCallsDifferentParameters) {
+ auto* arr = ty.array<i32>();
+ auto* arr_ptr = ty.ptr<storage>(arr);
+
+ auto* buffer = b.Var("buffer", arr_ptr);
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* bar = b.Function("bar", ty.u32());
+ auto* param_a = b.FunctionParam("param_a", arr_ptr);
+ auto* param_b = b.FunctionParam("param_b", arr_ptr);
+ auto* param_c = b.FunctionParam("param_c", arr_ptr);
+ bar->SetParams({param_a, param_b, param_c});
+ b.Append(bar->Block(), [&] {
+ auto* len_a = b.Call<u32>(BuiltinFn::kArrayLength, param_a);
+ auto* len_b = b.Call<u32>(BuiltinFn::kArrayLength, param_b);
+ auto* len_c = b.Call<u32>(BuiltinFn::kArrayLength, param_c);
+ b.Return(bar, b.Add<u32>(len_a, b.Add<u32>(len_b, len_c)));
+ });
+
+ auto* foo = b.Function("foo", ty.u32());
+ b.Append(foo->Block(), [&] {
+ auto* len = b.Call<u32>(bar, buffer, buffer, buffer);
+ b.Return(foo, len);
+ });
+
+ auto* src = R"(
+$B1: { # root
+ %buffer:ptr<storage, array<i32>, read_write> = var @binding_point(0, 0)
+}
+
+%bar = func(%param_a:ptr<storage, array<i32>, read_write>, %param_b:ptr<storage, array<i32>, read_write>, %param_c:ptr<storage, array<i32>, read_write>):u32 {
+ $B2: {
+ %6:u32 = arrayLength %param_a
+ %7:u32 = arrayLength %param_b
+ %8:u32 = arrayLength %param_c
+ %9:u32 = add %7, %8
+ %10:u32 = add %6, %9
+ ret %10
+ }
+}
+%foo = func():u32 {
+ $B3: {
+ %12:u32 = call %bar, %buffer, %buffer, %buffer
+ ret %12
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+$B1: { # root
+ %buffer:ptr<storage, array<i32>, read_write> = var @binding_point(0, 0)
+ %tint_storage_buffer_sizes:ptr<uniform, array<vec4<u32>, 1>, read> = var
+}
+
+%bar = func(%param_a:ptr<storage, array<i32>, read_write>, %param_b:ptr<storage, array<i32>, read_write>, %param_c:ptr<storage, array<i32>, read_write>, %tint_array_length:u32, %tint_array_length_1:u32, %tint_array_length_2:u32):u32 { # %tint_array_length_1: 'tint_array_length', %tint_array_length_2: 'tint_array_length'
+ $B2: {
+ %10:u32 = add %tint_array_length_1, %tint_array_length_2
+ %11:u32 = add %tint_array_length, %10
+ ret %11
+ }
+}
+%foo = func():u32 {
+ $B3: {
+ %13:ptr<uniform, vec4<u32>, read> = access %tint_storage_buffer_sizes, 0u
+ %14:u32 = load_vector_element %13, 0u
+ %15:u32 = div %14, 4u
+ %16:ptr<uniform, vec4<u32>, read> = access %tint_storage_buffer_sizes, 0u
+ %17:u32 = load_vector_element %16, 0u
+ %18:u32 = div %17, 4u
+ %19:ptr<uniform, vec4<u32>, read> = access %tint_storage_buffer_sizes, 0u
+ %20:u32 = load_vector_element %19, 0u
+ %21:u32 = div %20, 4u
+ %22:u32 = call %bar, %buffer, %buffer, %buffer, %15, %18, %21
+ ret %22
+ }
+}
+)";
+
+ std::unordered_map<BindingPoint, uint32_t> bindpoint_to_index;
+ bindpoint_to_index[{0, 0}] = 0;
+ Run(ArrayLengthFromUniform, BindingPoint{1, 2}, bindpoint_to_index);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_ArrayLengthFromUniformTest, ViaComplexChain) {
+ auto* arr = ty.array<i32>();
+ auto* structure = ty.Struct(mod.symbols.New("MyStruct"), {
+ {mod.symbols.New("u1"), ty.u32()},
+ {mod.symbols.New("a"), arr},
+ });
+ auto* arr_ptr = ty.ptr<storage>(arr);
+ auto* structure_ptr = ty.ptr<storage>(structure);
+
+ auto* buffer = b.Var("buffer", structure_ptr);
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* bar = b.Function("bar", ty.u32());
+ auto* param = b.FunctionParam("param", arr_ptr);
+ bar->SetParams({param});
+ b.Append(bar->Block(), [&] {
+ auto* access = b.Access(arr_ptr, param);
+ auto* let = b.Let("let", access);
+ auto* len = b.Call<u32>(BuiltinFn::kArrayLength, let);
+ b.Return(bar, len);
+ });
+
+ auto* foo = b.Function("foo", ty.u32());
+ b.Append(foo->Block(), [&] {
+ auto* access = b.Access(arr_ptr, buffer, 1_u);
+ auto* let = b.Let("let", access);
+ auto* len = b.Call<u32>(bar, let);
+ b.Return(foo, len);
+ });
+
+ auto* src = R"(
+MyStruct = struct @align(4) {
+ u1:u32 @offset(0)
+ a:array<i32> @offset(4)
+}
+
+$B1: { # root
+ %buffer:ptr<storage, MyStruct, read_write> = var @binding_point(0, 0)
+}
+
+%bar = func(%param:ptr<storage, array<i32>, read_write>):u32 {
+ $B2: {
+ %4:ptr<storage, array<i32>, read_write> = access %param
+ %let:ptr<storage, array<i32>, read_write> = let %4
+ %6:u32 = arrayLength %let
+ ret %6
+ }
+}
+%foo = func():u32 {
+ $B3: {
+ %8:ptr<storage, array<i32>, read_write> = access %buffer, 1u
+ %let_1:ptr<storage, array<i32>, read_write> = let %8 # %let_1: 'let'
+ %10:u32 = call %bar, %let_1
+ ret %10
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+MyStruct = struct @align(4) {
+ u1:u32 @offset(0)
+ a:array<i32> @offset(4)
+}
+
+$B1: { # root
+ %buffer:ptr<storage, MyStruct, read_write> = var @binding_point(0, 0)
+ %tint_storage_buffer_sizes:ptr<uniform, array<vec4<u32>, 1>, read> = var
+}
+
+%bar = func(%param:ptr<storage, array<i32>, read_write>, %tint_array_length:u32):u32 {
+ $B2: {
+ %6:ptr<storage, array<i32>, read_write> = access %param
+ %let:ptr<storage, array<i32>, read_write> = let %6
+ ret %tint_array_length
+ }
+}
+%foo = func():u32 {
+ $B3: {
+ %9:ptr<storage, array<i32>, read_write> = access %buffer, 1u
+ %let_1:ptr<storage, array<i32>, read_write> = let %9 # %let_1: 'let'
+ %11:ptr<uniform, vec4<u32>, read> = access %tint_storage_buffer_sizes, 0u
+ %12:u32 = load_vector_element %11, 0u
+ %13:u32 = sub %12, 4u
+ %14:u32 = div %13, 4u
+ %15:u32 = call %bar, %let_1, %14
+ ret %15
+ }
+}
+)";
+
+ std::unordered_map<BindingPoint, uint32_t> bindpoint_to_index;
+ bindpoint_to_index[{0, 0}] = 0;
+ Run(ArrayLengthFromUniform, BindingPoint{1, 2}, bindpoint_to_index);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_ArrayLengthFromUniformTest, ElementStrideLargerThanSize) {
+ auto* arr = ty.array<vec3<i32>>();
+ auto* arr_ptr = ty.ptr<storage>(arr);
+
+ auto* buffer = b.Var("buffer", arr_ptr);
+ buffer->SetBindingPoint(0, 0);
+ mod.root_block->Append(buffer);
+
+ auto* func = b.Function("foo", ty.u32());
+ b.Append(func->Block(), [&] {
+ auto* len = b.Call<u32>(BuiltinFn::kArrayLength, buffer);
+ b.Return(func, len);
+ });
+
+ auto* src = R"(
+$B1: { # root
+ %buffer:ptr<storage, array<vec3<i32>>, read_write> = var @binding_point(0, 0)
+}
+
+%foo = func():u32 {
+ $B2: {
+ %3:u32 = arrayLength %buffer
+ ret %3
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+$B1: { # root
+ %buffer:ptr<storage, array<vec3<i32>>, read_write> = var @binding_point(0, 0)
+ %tint_storage_buffer_sizes:ptr<uniform, array<vec4<u32>, 1>, read> = var
+}
+
+%foo = func():u32 {
+ $B2: {
+ %4:ptr<uniform, vec4<u32>, read> = access %tint_storage_buffer_sizes, 0u
+ %5:u32 = load_vector_element %4, 0u
+ %6:u32 = div %5, 16u
+ ret %6
+ }
+}
+)";
+
+ std::unordered_map<BindingPoint, uint32_t> bindpoint_to_index;
+ bindpoint_to_index[{0, 0}] = 0;
+ Run(ArrayLengthFromUniform, BindingPoint{1, 2}, bindpoint_to_index);
+
+ EXPECT_EQ(expect, str());
+}
+
+TEST_F(IR_ArrayLengthFromUniformTest, MultipleVars) {
+ auto* arr = ty.array<i32>();
+ auto* arr_ptr = ty.ptr<storage>(arr);
+
+ auto* buffer_a = b.Var("buffer_a", arr_ptr);
+ auto* buffer_b = b.Var("buffer_b", arr_ptr);
+ auto* buffer_c = b.Var("buffer_c", arr_ptr);
+ auto* buffer_d = b.Var("buffer_d", arr_ptr);
+ auto* buffer_e = b.Var("buffer_e", arr_ptr);
+ buffer_a->SetBindingPoint(0, 0);
+ buffer_b->SetBindingPoint(0, 1);
+ buffer_c->SetBindingPoint(1, 0);
+ buffer_d->SetBindingPoint(1, 1);
+ buffer_e->SetBindingPoint(2, 3);
+ mod.root_block->Append(buffer_a);
+ mod.root_block->Append(buffer_b);
+ mod.root_block->Append(buffer_c);
+ mod.root_block->Append(buffer_d);
+ mod.root_block->Append(buffer_e);
+
+ auto* func = b.Function("foo", ty.void_());
+ b.Append(func->Block(), [&] {
+ b.Call<u32>(BuiltinFn::kArrayLength, buffer_a);
+ b.Call<u32>(BuiltinFn::kArrayLength, buffer_b);
+ b.Call<u32>(BuiltinFn::kArrayLength, buffer_c);
+ b.Call<u32>(BuiltinFn::kArrayLength, buffer_d);
+ b.Call<u32>(BuiltinFn::kArrayLength, buffer_e);
+ b.Return(func);
+ });
+
+ auto* src = R"(
+$B1: { # root
+ %buffer_a:ptr<storage, array<i32>, read_write> = var @binding_point(0, 0)
+ %buffer_b:ptr<storage, array<i32>, read_write> = var @binding_point(0, 1)
+ %buffer_c:ptr<storage, array<i32>, read_write> = var @binding_point(1, 0)
+ %buffer_d:ptr<storage, array<i32>, read_write> = var @binding_point(1, 1)
+ %buffer_e:ptr<storage, array<i32>, read_write> = var @binding_point(2, 3)
+}
+
+%foo = func():void {
+ $B2: {
+ %7:u32 = arrayLength %buffer_a
+ %8:u32 = arrayLength %buffer_b
+ %9:u32 = arrayLength %buffer_c
+ %10:u32 = arrayLength %buffer_d
+ %11:u32 = arrayLength %buffer_e
+ ret
+ }
+}
+)";
+ EXPECT_EQ(src, str());
+
+ auto* expect = R"(
+$B1: { # root
+ %buffer_a:ptr<storage, array<i32>, read_write> = var @binding_point(0, 0)
+ %buffer_b:ptr<storage, array<i32>, read_write> = var @binding_point(0, 1)
+ %buffer_c:ptr<storage, array<i32>, read_write> = var @binding_point(1, 0)
+ %buffer_d:ptr<storage, array<i32>, read_write> = var @binding_point(1, 1)
+ %buffer_e:ptr<storage, array<i32>, read_write> = var @binding_point(2, 3)
+ %tint_storage_buffer_sizes:ptr<uniform, array<vec4<u32>, 2>, read> = var
+}
+
+%foo = func():void {
+ $B2: {
+ %8:ptr<uniform, vec4<u32>, read> = access %tint_storage_buffer_sizes, 0u
+ %9:u32 = load_vector_element %8, 0u
+ %10:u32 = div %9, 4u
+ %11:ptr<uniform, vec4<u32>, read> = access %tint_storage_buffer_sizes, 1u
+ %12:u32 = load_vector_element %11, 1u
+ %13:u32 = div %12, 4u
+ %14:ptr<uniform, vec4<u32>, read> = access %tint_storage_buffer_sizes, 0u
+ %15:u32 = load_vector_element %14, 3u
+ %16:u32 = div %15, 4u
+ %17:ptr<uniform, vec4<u32>, read> = access %tint_storage_buffer_sizes, 0u
+ %18:u32 = load_vector_element %17, 2u
+ %19:u32 = div %18, 4u
+ %20:ptr<uniform, vec4<u32>, read> = access %tint_storage_buffer_sizes, 1u
+ %21:u32 = load_vector_element %20, 0u
+ %22:u32 = div %21, 4u
+ ret
+ }
+}
+)";
+
+ std::unordered_map<BindingPoint, uint32_t> bindpoint_to_index;
+ bindpoint_to_index[{0, 0}] = 0;
+ bindpoint_to_index[{0, 1}] = 5;
+ bindpoint_to_index[{1, 0}] = 3;
+ bindpoint_to_index[{1, 1}] = 2;
+ bindpoint_to_index[{2, 3}] = 4;
+ Run(ArrayLengthFromUniform, BindingPoint{1, 2}, bindpoint_to_index);
+
+ EXPECT_EQ(expect, str());
+}
+
+} // namespace
+} // namespace tint::core::ir::transform
diff --git a/src/tint/lang/core/ir/transform/multiplanar_external_texture.cc b/src/tint/lang/core/ir/transform/multiplanar_external_texture.cc
index 8637697..4a0de1f 100644
--- a/src/tint/lang/core/ir/transform/multiplanar_external_texture.cc
+++ b/src/tint/lang/core/ir/transform/multiplanar_external_texture.cc
@@ -228,8 +228,14 @@
},
[&](CoreBuiltinCall* call) {
if (call->Func() == core::BuiltinFn::kTextureDimensions) {
- // Use the first plane for the `textureDimensions()` call.
- call->SetOperand(use.operand_index, plane_0);
+ // Use params.visibleSize + vec2u(1, 1) instead of the textureDimensions.
+ b.InsertBefore(call, [&] {
+ auto* visible_size = b.Access<vec2<u32>>(params, 12_u);
+ auto* vec2u_1_1 = b.Splat<vec2<u32>>(1_u);
+ auto* dimensions = b.Add<vec2<u32>>(visible_size, vec2u_1_1);
+ dimensions->SetResults(Vector{call->DetachResult()});
+ });
+ call->Destroy();
} else if (call->Func() == core::BuiltinFn::kTextureLoad) {
// Convert the coordinates to unsigned integers if necessary.
auto* coords = call->Args()[1];
@@ -410,11 +416,10 @@
auto* yuv_to_rgb_conversion_only = b.Access(ty.u32(), params, 1_u);
auto* yuv_to_rgb_conversion = b.Access(ty.mat3x4<f32>(), params, 2_u);
auto* load_transform_matrix = b.Access(ty.mat3x2<f32>(), params, 7_u);
- auto* display_visible_rect_max = b.Access(ty.vec2<u32>(), params, 12_u);
+ auto* visible_size = b.Access(ty.vec2<u32>(), params, 12_u);
auto* plane1_coord_factor = b.Access(ty.vec2<f32>(), params, 13_u);
- auto* clamped_coords =
- b.Call(vec2u, core::BuiltinFn::kMin, coords, display_visible_rect_max);
+ auto* clamped_coords = b.Call(vec2u, core::BuiltinFn::kMin, coords, visible_size);
auto* clamped_coords_f = b.Convert(vec2f, clamped_coords);
auto* modified_coords =
b.Multiply(vec2f, load_transform_matrix, b.Construct(vec3f, clamped_coords_f, 1_f));
diff --git a/src/tint/lang/core/ir/transform/multiplanar_external_texture_test.cc b/src/tint/lang/core/ir/transform/multiplanar_external_texture_test.cc
index 39b06e8..c8dc646 100644
--- a/src/tint/lang/core/ir/transform/multiplanar_external_texture_test.cc
+++ b/src/tint/lang/core/ir/transform/multiplanar_external_texture_test.cc
@@ -270,7 +270,8 @@
%5:texture_2d<f32> = load %texture_plane0
%6:texture_2d<f32> = load %texture_plane1
%7:tint_ExternalTextureParams = load %texture_params
- %result:vec2<u32> = textureDimensions %5
+ %8:vec2<u32> = access %7, 12u
+ %result:vec2<u32> = add %8, vec2<u32>(1u)
ret %result
}
}
@@ -1071,99 +1072,100 @@
%15:texture_2d<f32> = load %texture_plane0
%16:texture_2d<f32> = load %texture_plane1
%17:tint_ExternalTextureParams = load %texture_params
- %18:vec2<u32> = textureDimensions %15
- %19:texture_2d<f32> = load %texture_plane0
- %20:texture_2d<f32> = load %texture_plane1
- %21:tint_ExternalTextureParams = load %texture_params
- %22:vec4<f32> = call %tint_TextureSampleExternal, %19, %20, %21, %sampler_1, %coords_1
- %23:texture_2d<f32> = load %texture_plane0
- %24:texture_2d<f32> = load %texture_plane1
- %25:tint_ExternalTextureParams = load %texture_params
- %26:vec4<f32> = call %tint_TextureSampleExternal, %23, %24, %25, %sampler_1, %coords_1
- %27:texture_2d<f32> = load %texture_plane0
- %28:texture_2d<f32> = load %texture_plane1
- %29:tint_ExternalTextureParams = load %texture_params
- %result_a:vec4<f32> = call %foo, %27, %28, %29, %sampler_1, %coords_1
- %result_b:vec4<f32> = call %foo, %27, %28, %29, %sampler_1, %coords_1
- %32:vec4<f32> = add %result_a, %result_b
- ret %32
+ %18:vec2<u32> = access %17, 12u
+ %19:vec2<u32> = add %18, vec2<u32>(1u)
+ %20:texture_2d<f32> = load %texture_plane0
+ %21:texture_2d<f32> = load %texture_plane1
+ %22:tint_ExternalTextureParams = load %texture_params
+ %23:vec4<f32> = call %tint_TextureSampleExternal, %20, %21, %22, %sampler_1, %coords_1
+ %24:texture_2d<f32> = load %texture_plane0
+ %25:texture_2d<f32> = load %texture_plane1
+ %26:tint_ExternalTextureParams = load %texture_params
+ %27:vec4<f32> = call %tint_TextureSampleExternal, %24, %25, %26, %sampler_1, %coords_1
+ %28:texture_2d<f32> = load %texture_plane0
+ %29:texture_2d<f32> = load %texture_plane1
+ %30:tint_ExternalTextureParams = load %texture_params
+ %result_a:vec4<f32> = call %foo, %28, %29, %30, %sampler_1, %coords_1
+ %result_b:vec4<f32> = call %foo, %28, %29, %30, %sampler_1, %coords_1
+ %33:vec4<f32> = add %result_a, %result_b
+ ret %33
}
}
%tint_TextureSampleExternal = func(%plane_0:texture_2d<f32>, %plane_1:texture_2d<f32>, %params:tint_ExternalTextureParams, %sampler_2:sampler, %coords_2:vec2<f32>):vec4<f32> { # %sampler_2: 'sampler', %coords_2: 'coords'
$B4: {
- %38:u32 = access %params, 1u
- %39:mat3x4<f32> = access %params, 2u
- %40:mat3x2<f32> = access %params, 6u
- %41:vec2<f32> = access %params, 8u
- %42:vec2<f32> = access %params, 9u
- %43:vec2<f32> = access %params, 10u
- %44:vec2<f32> = access %params, 11u
- %45:vec3<f32> = construct %coords_2, 1.0f
- %46:vec2<f32> = mul %40, %45
- %47:vec2<f32> = clamp %46, %41, %42
- %48:u32 = access %params, 0u
- %49:bool = eq %48, 1u
- %50:vec3<f32>, %51:f32 = if %49 [t: $B5, f: $B6] { # if_1
+ %39:u32 = access %params, 1u
+ %40:mat3x4<f32> = access %params, 2u
+ %41:mat3x2<f32> = access %params, 6u
+ %42:vec2<f32> = access %params, 8u
+ %43:vec2<f32> = access %params, 9u
+ %44:vec2<f32> = access %params, 10u
+ %45:vec2<f32> = access %params, 11u
+ %46:vec3<f32> = construct %coords_2, 1.0f
+ %47:vec2<f32> = mul %41, %46
+ %48:vec2<f32> = clamp %47, %42, %43
+ %49:u32 = access %params, 0u
+ %50:bool = eq %49, 1u
+ %51:vec3<f32>, %52:f32 = if %50 [t: $B5, f: $B6] { # if_1
$B5: { # true
- %52:vec4<f32> = textureSampleLevel %plane_0, %sampler_2, %47, 0.0f
- %53:vec3<f32> = swizzle %52, xyz
- %54:f32 = access %52, 3u
- exit_if %53, %54 # if_1
+ %53:vec4<f32> = textureSampleLevel %plane_0, %sampler_2, %48, 0.0f
+ %54:vec3<f32> = swizzle %53, xyz
+ %55:f32 = access %53, 3u
+ exit_if %54, %55 # if_1
}
$B6: { # false
- %55:vec4<f32> = textureSampleLevel %plane_0, %sampler_2, %47, 0.0f
- %56:f32 = access %55, 0u
- %57:vec2<f32> = clamp %46, %43, %44
- %58:vec4<f32> = textureSampleLevel %plane_1, %sampler_2, %57, 0.0f
- %59:vec2<f32> = swizzle %58, xy
- %60:vec4<f32> = construct %56, %59, 1.0f
- %61:vec3<f32> = mul %60, %39
- exit_if %61, 1.0f # if_1
+ %56:vec4<f32> = textureSampleLevel %plane_0, %sampler_2, %48, 0.0f
+ %57:f32 = access %56, 0u
+ %58:vec2<f32> = clamp %47, %44, %45
+ %59:vec4<f32> = textureSampleLevel %plane_1, %sampler_2, %58, 0.0f
+ %60:vec2<f32> = swizzle %59, xy
+ %61:vec4<f32> = construct %57, %60, 1.0f
+ %62:vec3<f32> = mul %61, %40
+ exit_if %62, 1.0f # if_1
}
}
- %62:bool = eq %38, 0u
- %63:vec3<f32> = if %62 [t: $B7, f: $B8] { # if_2
+ %63:bool = eq %39, 0u
+ %64:vec3<f32> = if %63 [t: $B7, f: $B8] { # if_2
$B7: { # true
- %64:tint_GammaTransferParams = access %params, 3u
- %65:tint_GammaTransferParams = access %params, 4u
- %66:mat3x3<f32> = access %params, 5u
- %67:vec3<f32> = call %tint_GammaCorrection, %50, %64
- %69:vec3<f32> = mul %66, %67
- %70:vec3<f32> = call %tint_GammaCorrection, %69, %65
- exit_if %70 # if_2
+ %65:tint_GammaTransferParams = access %params, 3u
+ %66:tint_GammaTransferParams = access %params, 4u
+ %67:mat3x3<f32> = access %params, 5u
+ %68:vec3<f32> = call %tint_GammaCorrection, %51, %65
+ %70:vec3<f32> = mul %67, %68
+ %71:vec3<f32> = call %tint_GammaCorrection, %70, %66
+ exit_if %71 # if_2
}
$B8: { # false
- exit_if %50 # if_2
+ exit_if %51 # if_2
}
}
- %71:vec4<f32> = construct %63, %51
- ret %71
+ %72:vec4<f32> = construct %64, %52
+ ret %72
}
}
%tint_GammaCorrection = func(%v:vec3<f32>, %params_1:tint_GammaTransferParams):vec3<f32> { # %params_1: 'params'
$B9: {
- %74:f32 = access %params_1, 0u
- %75:f32 = access %params_1, 1u
- %76:f32 = access %params_1, 2u
- %77:f32 = access %params_1, 3u
- %78:f32 = access %params_1, 4u
- %79:f32 = access %params_1, 5u
- %80:f32 = access %params_1, 6u
- %81:vec3<f32> = construct %74
- %82:vec3<f32> = construct %78
- %83:vec3<f32> = abs %v
- %84:vec3<f32> = sign %v
- %85:vec3<bool> = lt %83, %82
- %86:vec3<f32> = mul %77, %83
- %87:vec3<f32> = add %86, %80
- %88:vec3<f32> = mul %84, %87
- %89:vec3<f32> = mul %75, %83
- %90:vec3<f32> = add %89, %76
- %91:vec3<f32> = pow %90, %81
- %92:vec3<f32> = add %91, %79
- %93:vec3<f32> = mul %84, %92
- %94:vec3<f32> = select %93, %88, %85
- ret %94
+ %75:f32 = access %params_1, 0u
+ %76:f32 = access %params_1, 1u
+ %77:f32 = access %params_1, 2u
+ %78:f32 = access %params_1, 3u
+ %79:f32 = access %params_1, 4u
+ %80:f32 = access %params_1, 5u
+ %81:f32 = access %params_1, 6u
+ %82:vec3<f32> = construct %75
+ %83:vec3<f32> = construct %79
+ %84:vec3<f32> = abs %v
+ %85:vec3<f32> = sign %v
+ %86:vec3<bool> = lt %84, %83
+ %87:vec3<f32> = mul %78, %84
+ %88:vec3<f32> = add %87, %81
+ %89:vec3<f32> = mul %85, %88
+ %90:vec3<f32> = mul %76, %84
+ %91:vec3<f32> = add %90, %77
+ %92:vec3<f32> = pow %91, %82
+ %93:vec3<f32> = add %92, %80
+ %94:vec3<f32> = mul %85, %93
+ %95:vec3<f32> = select %94, %89, %86
+ ret %95
}
}
)";
diff --git a/src/tint/lang/core/type/depth_multisampled_texture.cc b/src/tint/lang/core/type/depth_multisampled_texture.cc
index 5daed0e..81bf7de 100644
--- a/src/tint/lang/core/type/depth_multisampled_texture.cc
+++ b/src/tint/lang/core/type/depth_multisampled_texture.cc
@@ -37,17 +37,10 @@
TINT_INSTANTIATE_TYPEINFO(tint::core::type::DepthMultisampledTexture);
namespace tint::core::type {
-namespace {
-
-bool IsValidDepthDimension(TextureDimension dim) {
- return dim == TextureDimension::k2d;
-}
-
-} // namespace
DepthMultisampledTexture::DepthMultisampledTexture(TextureDimension dim)
: Base(Hash(TypeCode::Of<DepthMultisampledTexture>().bits, dim), dim) {
- TINT_ASSERT(IsValidDepthDimension(dim));
+ TINT_ASSERT(IsValidDimension(dim));
}
DepthMultisampledTexture::~DepthMultisampledTexture() = default;
@@ -69,4 +62,7 @@
return ctx.dst.mgr->Get<DepthMultisampledTexture>(dim());
}
+bool DepthMultisampledTexture::IsValidDimension(TextureDimension dim) {
+ return dim == TextureDimension::k2d;
+}
} // namespace tint::core::type
diff --git a/src/tint/lang/core/type/depth_multisampled_texture.h b/src/tint/lang/core/type/depth_multisampled_texture.h
index 4774ead..0771f8f 100644
--- a/src/tint/lang/core/type/depth_multisampled_texture.h
+++ b/src/tint/lang/core/type/depth_multisampled_texture.h
@@ -56,6 +56,9 @@
/// @param ctx the clone context
/// @returns a clone of this type
DepthMultisampledTexture* Clone(CloneContext& ctx) const override;
+
+ /// @returns true if @p dim is a valid TextureDimension for a DepthMultisampledTexture
+ static bool IsValidDimension(TextureDimension dim);
};
} // namespace tint::core::type
diff --git a/src/tint/lang/core/type/depth_texture.cc b/src/tint/lang/core/type/depth_texture.cc
index a246ed7..b6a2e2b 100644
--- a/src/tint/lang/core/type/depth_texture.cc
+++ b/src/tint/lang/core/type/depth_texture.cc
@@ -37,18 +37,10 @@
TINT_INSTANTIATE_TYPEINFO(tint::core::type::DepthTexture);
namespace tint::core::type {
-namespace {
-
-bool IsValidDepthDimension(TextureDimension dim) {
- return dim == TextureDimension::k2d || dim == TextureDimension::k2dArray ||
- dim == TextureDimension::kCube || dim == TextureDimension::kCubeArray;
-}
-
-} // namespace
DepthTexture::DepthTexture(TextureDimension dim)
: Base(Hash(TypeCode::Of<DepthTexture>().bits, dim), dim) {
- TINT_ASSERT(IsValidDepthDimension(dim));
+ TINT_ASSERT(IsValidDimension(dim));
}
DepthTexture::~DepthTexture() = default;
@@ -70,4 +62,9 @@
return ctx.dst.mgr->Get<DepthTexture>(dim());
}
+bool DepthTexture::IsValidDimension(TextureDimension dim) {
+ return dim == TextureDimension::k2d || dim == TextureDimension::k2dArray ||
+ dim == TextureDimension::kCube || dim == TextureDimension::kCubeArray;
+}
+
} // namespace tint::core::type
diff --git a/src/tint/lang/core/type/depth_texture.h b/src/tint/lang/core/type/depth_texture.h
index 2f1e738..62171a5 100644
--- a/src/tint/lang/core/type/depth_texture.h
+++ b/src/tint/lang/core/type/depth_texture.h
@@ -56,6 +56,9 @@
/// @param ctx the clone context
/// @returns a clone of this type
DepthTexture* Clone(CloneContext& ctx) const override;
+
+ /// @returns true iff @p dim is a valid TextureDimension for a DepthTexture
+ static bool IsValidDimension(TextureDimension dim);
};
} // namespace tint::core::type
diff --git a/src/tint/lang/msl/writer/raise/raise.cc b/src/tint/lang/msl/writer/raise/raise.cc
index fea8afd..09caa3c 100644
--- a/src/tint/lang/msl/writer/raise/raise.cc
+++ b/src/tint/lang/msl/writer/raise/raise.cc
@@ -29,6 +29,7 @@
#include <utility>
+#include "src/tint/lang/core/ir/transform/array_length_from_uniform.h"
#include "src/tint/lang/core/ir/transform/binary_polyfill.h"
#include "src/tint/lang/core/ir/transform/binding_remapper.h"
#include "src/tint/lang/core/ir/transform/builtin_polyfill.h"
@@ -93,6 +94,9 @@
}
RUN_TRANSFORM(core::ir::transform::MultiplanarExternalTexture, external_texture_options);
+ RUN_TRANSFORM(core::ir::transform::ArrayLengthFromUniform,
+ BindingPoint{0u, array_length_from_uniform_options.ubo_binding},
+ array_length_from_uniform_options.bindpoint_to_size_index);
if (!options.disable_workgroup_init) {
RUN_TRANSFORM(core::ir::transform::ZeroInitWorkgroupMemory);
diff --git a/src/tint/lang/wgsl/ast/BUILD.bazel b/src/tint/lang/wgsl/ast/BUILD.bazel
index b45a457..be215b2 100644
--- a/src/tint/lang/wgsl/ast/BUILD.bazel
+++ b/src/tint/lang/wgsl/ast/BUILD.bazel
@@ -81,6 +81,7 @@
"if_statement.cc",
"increment_decrement_statement.cc",
"index_accessor_expression.cc",
+ "input_attachment_index_attribute.cc",
"int_literal_expression.cc",
"internal_attribute.cc",
"interpolate_attribute.cc",
@@ -161,6 +162,7 @@
"if_statement.h",
"increment_decrement_statement.h",
"index_accessor_expression.h",
+ "input_attachment_index_attribute.h",
"int_literal_expression.h",
"internal_attribute.h",
"interpolate_attribute.h",
@@ -267,6 +269,7 @@
"if_statement_test.cc",
"increment_decrement_statement_test.cc",
"index_accessor_expression_test.cc",
+ "input_attachment_index_attribute_test.cc",
"int_literal_expression_test.cc",
"interpolate_attribute_test.cc",
"location_attribute_test.cc",
diff --git a/src/tint/lang/wgsl/ast/BUILD.cmake b/src/tint/lang/wgsl/ast/BUILD.cmake
index c144385..3d36157 100644
--- a/src/tint/lang/wgsl/ast/BUILD.cmake
+++ b/src/tint/lang/wgsl/ast/BUILD.cmake
@@ -125,6 +125,8 @@
lang/wgsl/ast/increment_decrement_statement.h
lang/wgsl/ast/index_accessor_expression.cc
lang/wgsl/ast/index_accessor_expression.h
+ lang/wgsl/ast/input_attachment_index_attribute.cc
+ lang/wgsl/ast/input_attachment_index_attribute.h
lang/wgsl/ast/int_literal_expression.cc
lang/wgsl/ast/int_literal_expression.h
lang/wgsl/ast/internal_attribute.cc
@@ -267,6 +269,7 @@
lang/wgsl/ast/if_statement_test.cc
lang/wgsl/ast/increment_decrement_statement_test.cc
lang/wgsl/ast/index_accessor_expression_test.cc
+ lang/wgsl/ast/input_attachment_index_attribute_test.cc
lang/wgsl/ast/int_literal_expression_test.cc
lang/wgsl/ast/interpolate_attribute_test.cc
lang/wgsl/ast/location_attribute_test.cc
diff --git a/src/tint/lang/wgsl/ast/BUILD.gn b/src/tint/lang/wgsl/ast/BUILD.gn
index 249bb50..165f2a7 100644
--- a/src/tint/lang/wgsl/ast/BUILD.gn
+++ b/src/tint/lang/wgsl/ast/BUILD.gn
@@ -128,6 +128,8 @@
"increment_decrement_statement.h",
"index_accessor_expression.cc",
"index_accessor_expression.h",
+ "input_attachment_index_attribute.cc",
+ "input_attachment_index_attribute.h",
"int_literal_expression.cc",
"int_literal_expression.h",
"internal_attribute.cc",
@@ -267,6 +269,7 @@
"if_statement_test.cc",
"increment_decrement_statement_test.cc",
"index_accessor_expression_test.cc",
+ "input_attachment_index_attribute_test.cc",
"int_literal_expression_test.cc",
"interpolate_attribute_test.cc",
"location_attribute_test.cc",
diff --git a/src/tint/lang/wgsl/ast/builder.h b/src/tint/lang/wgsl/ast/builder.h
index c4eb4f1..b643fc4 100644
--- a/src/tint/lang/wgsl/ast/builder.h
+++ b/src/tint/lang/wgsl/ast/builder.h
@@ -46,6 +46,7 @@
#include "src/tint/lang/core/type/f16.h"
#include "src/tint/lang/core/type/f32.h"
#include "src/tint/lang/core/type/i32.h"
+#include "src/tint/lang/core/type/input_attachment.h"
#include "src/tint/lang/core/type/matrix.h"
#include "src/tint/lang/core/type/multisampled_texture.h"
#include "src/tint/lang/core/type/pointer.h"
@@ -86,6 +87,7 @@
#include "src/tint/lang/wgsl/ast/if_statement.h"
#include "src/tint/lang/wgsl/ast/increment_decrement_statement.h"
#include "src/tint/lang/wgsl/ast/index_accessor_expression.h"
+#include "src/tint/lang/wgsl/ast/input_attachment_index_attribute.h"
#include "src/tint/lang/wgsl/ast/int_literal_expression.h"
#include "src/tint/lang/wgsl/ast/interpolate_attribute.h"
#include "src/tint/lang/wgsl/ast/invariant_attribute.h"
@@ -1297,6 +1299,12 @@
/// @returns the external texture
ast::Type external_texture() const { return (*this)("texture_external"); }
+ /// @param subtype the texture subtype.
+ /// @returns the input attachment
+ ast::Type input_attachment(ast::Type subtype) const {
+ return (*this)("input_attachment", subtype);
+ }
+
/// @param source the Source of the node
/// @returns the external texture
ast::Type external_texture(const Source& source) const {
@@ -3240,6 +3248,24 @@
return create<ast::IdAttribute>(Expr(std::forward<EXPR>(id)));
}
+ /// Creates an ast::InputAttachmentIndexAttribute
+ /// @param index the index value expression
+ /// @returns the index attribute pointer
+ template <typename EXPR>
+ const ast::InputAttachmentIndexAttribute* InputAttachmentIndex(EXPR&& index) {
+ return create<ast::InputAttachmentIndexAttribute>(source_, Expr(std::forward<EXPR>(index)));
+ }
+
+ /// Creates an ast::InputAttachmentIndexAttribute
+ /// @param source the source information
+ /// @param index the index value expression
+ /// @returns the index attribute pointer
+ template <typename EXPR>
+ const ast::InputAttachmentIndexAttribute* InputAttachmentIndex(const Source& source,
+ EXPR&& index) {
+ return create<ast::InputAttachmentIndexAttribute>(source, Expr(std::forward<EXPR>(index)));
+ }
+
/// Creates an ast::StageAttribute
/// @param source the source information
/// @param stage the pipeline stage
diff --git a/src/tint/lang/wgsl/ast/input_attachment_index_attribute.cc b/src/tint/lang/wgsl/ast/input_attachment_index_attribute.cc
new file mode 100644
index 0000000..5441ec4
--- /dev/null
+++ b/src/tint/lang/wgsl/ast/input_attachment_index_attribute.cc
@@ -0,0 +1,58 @@
+// Copyright 2024 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "src/tint/lang/wgsl/ast/input_attachment_index_attribute.h"
+
+#include <string>
+
+#include "src/tint/lang/wgsl/ast/builder.h"
+#include "src/tint/lang/wgsl/ast/clone_context.h"
+
+TINT_INSTANTIATE_TYPEINFO(tint::ast::InputAttachmentIndexAttribute);
+
+namespace tint::ast {
+
+InputAttachmentIndexAttribute::InputAttachmentIndexAttribute(GenerationID pid,
+ NodeID nid,
+ const Source& src,
+ const Expression* exp)
+ : Base(pid, nid, src), expr(exp) {}
+
+InputAttachmentIndexAttribute::~InputAttachmentIndexAttribute() = default;
+
+std::string InputAttachmentIndexAttribute::Name() const {
+ return "input_attachment_index";
+}
+
+const InputAttachmentIndexAttribute* InputAttachmentIndexAttribute::Clone(CloneContext& ctx) const {
+ // Clone arguments outside of create() call to have deterministic ordering
+ auto src = ctx.Clone(source);
+ auto* expr_ = ctx.Clone(expr);
+ return ctx.dst->create<InputAttachmentIndexAttribute>(src, expr_);
+}
+
+} // namespace tint::ast
diff --git a/src/tint/lang/wgsl/ast/input_attachment_index_attribute.h b/src/tint/lang/wgsl/ast/input_attachment_index_attribute.h
new file mode 100644
index 0000000..3477070
--- /dev/null
+++ b/src/tint/lang/wgsl/ast/input_attachment_index_attribute.h
@@ -0,0 +1,72 @@
+// Copyright 2024 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef SRC_TINT_LANG_WGSL_AST_INPUT_ATTACHMENT_INDEX_ATTRIBUTE_H_
+#define SRC_TINT_LANG_WGSL_AST_INPUT_ATTACHMENT_INDEX_ATTRIBUTE_H_
+
+#include <string>
+
+#include "src/tint/lang/wgsl/ast/attribute.h"
+
+// Forward declarations
+namespace tint::ast {
+class Expression;
+}
+
+namespace tint::ast {
+
+/// An input attachment attribute (enabled with the input attachments extension)
+class InputAttachmentIndexAttribute final
+ : public Castable<InputAttachmentIndexAttribute, Attribute> {
+ public:
+ /// constructor
+ /// @param pid the identifier of the program that owns this node
+ /// @param nid the unique node identifier
+ /// @param src the source of this node
+ /// @param expr the input attachment index value
+ InputAttachmentIndexAttribute(GenerationID pid,
+ NodeID nid,
+ const Source& src,
+ const Expression* expr);
+ ~InputAttachmentIndexAttribute() override;
+
+ /// @returns the WGSL name for the attribute
+ std::string Name() const override;
+
+ /// Clones this node and all transitive child nodes using the `CloneContext`
+ /// `ctx`.
+ /// @param ctx the clone context
+ /// @return the newly cloned node
+ const InputAttachmentIndexAttribute* Clone(CloneContext& ctx) const override;
+
+ /// The index value expression
+ const Expression* const expr;
+};
+
+} // namespace tint::ast
+
+#endif // SRC_TINT_LANG_WGSL_AST_INPUT_ATTACHMENT_INDEX_ATTRIBUTE_H_
diff --git a/src/tint/lang/wgsl/ast/input_attachment_index_attribute_test.cc b/src/tint/lang/wgsl/ast/input_attachment_index_attribute_test.cc
new file mode 100644
index 0000000..28ce19d
--- /dev/null
+++ b/src/tint/lang/wgsl/ast/input_attachment_index_attribute_test.cc
@@ -0,0 +1,45 @@
+// Copyright 2024 The Dawn & Tint Authors
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are met:
+//
+// 1. Redistributions of source code must retain the above copyright notice, this
+// list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright notice,
+// this list of conditions and the following disclaimer in the documentation
+// and/or other materials provided with the distribution.
+//
+// 3. Neither the name of the copyright holder nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "src/tint/lang/wgsl/ast/input_attachment_index_attribute.h"
+#include "src/tint/lang/wgsl/ast/helper_test.h"
+
+using namespace tint::core::number_suffixes; // NOLINT
+
+namespace tint::ast {
+namespace {
+
+using InputAttachmentIndexAttributeTest = TestHelper;
+
+TEST_F(InputAttachmentIndexAttributeTest, Creation) {
+ auto* expr = Expr(1_u);
+ auto* c = InputAttachmentIndex(expr);
+ EXPECT_EQ(c->expr, expr);
+}
+
+} // namespace
+} // namespace tint::ast
diff --git a/src/tint/lang/wgsl/ast/transform/multiplanar_external_texture.cc b/src/tint/lang/wgsl/ast/transform/multiplanar_external_texture.cc
index 0b59b7d..c9b1313 100644
--- a/src/tint/lang/wgsl/ast/transform/multiplanar_external_texture.cc
+++ b/src/tint/lang/wgsl/ast/transform/multiplanar_external_texture.cc
@@ -221,13 +221,12 @@
// Transform the external texture builtin calls into calls to the external texture
// functions.
- ctx.ReplaceAll([&](const CallExpression* expr) -> const CallExpression* {
+ ctx.ReplaceAll([&](const CallExpression* expr) -> const Expression* {
auto* call = sem.Get(expr)->UnwrapMaterialize()->As<sem::Call>();
auto* builtin = call->Target()->As<sem::BuiltinFn>();
if (builtin && !builtin->Parameters().IsEmpty() &&
- builtin->Parameters()[0]->Type()->Is<core::type::ExternalTexture>() &&
- builtin->Fn() != wgsl::BuiltinFn::kTextureDimensions) {
+ builtin->Parameters()[0]->Type()->Is<core::type::ExternalTexture>()) {
if (auto* var_user =
sem.GetVal(expr->args[0])->UnwrapLoad()->As<sem::VariableUser>()) {
auto it = new_binding_symbols.find(var_user->Variable());
@@ -245,6 +244,8 @@
return createTextureLoad(call, syms);
case wgsl::BuiltinFn::kTextureSampleBaseClampToEdge:
return createTextureSampleBaseClampToEdge(expr, syms);
+ case wgsl::BuiltinFn::kTextureDimensions:
+ return createTextureDimensions(call, syms);
default:
break;
}
@@ -553,6 +554,19 @@
return b.Call(texture_load_external_sym, plane_0_binding_arg, syms.plane_1,
ctx.Clone(args[1]->Declaration()), syms.params);
}
+
+ /// Returns the expression used to replace a textureDimensions call.
+ /// @param call the call expression being transformed
+ /// @param syms the expanded symbols to be used in the new call
+ /// @returns a load of params.visibleSize
+ const Expression* createTextureDimensions(const sem::Call* call, NewBindingSymbols syms) {
+ if (TINT_UNLIKELY(call->Arguments().Length() != 1)) {
+ TINT_ICE() << "expected textureDimensions call with a texture_external to have 1 "
+ "arguments, found "
+ << call->Arguments().Length() << " arguments";
+ }
+ return b.Add(b.MemberAccessor(syms.params, "visibleSize"), b.Call<vec2<u32>>(1_a));
+ }
};
MultiplanarExternalTexture::NewBindingPoints::NewBindingPoints() = default;
diff --git a/src/tint/lang/wgsl/ast/transform/multiplanar_external_texture_test.cc b/src/tint/lang/wgsl/ast/transform/multiplanar_external_texture_test.cc
index 65c7b41..a16eb09 100644
--- a/src/tint/lang/wgsl/ast/transform/multiplanar_external_texture_test.cc
+++ b/src/tint/lang/wgsl/ast/transform/multiplanar_external_texture_test.cc
@@ -171,7 +171,7 @@
@fragment
fn main(@builtin(position) coord : vec4<f32>) -> @location(0) vec4<f32> {
var dim : vec2<u32>;
- dim = textureDimensions(ext_tex);
+ dim = (ext_tex_params.visibleSize + vec2<u32>(1));
return vec4<f32>(0.0, 0.0, 0.0, 0.0);
}
)";
@@ -318,7 +318,7 @@
@fragment
fn main(@builtin(position) coord : vec4<f32>) -> @location(0) vec4<f32> {
var dim : vec2<u32>;
- dim = textureDimensions(ext_tex);
+ dim = (ext_tex_params.visibleSize + vec2<u32>(1));
return vec4<f32>(0.0, 0.0, 0.0, 0.0);
}
@@ -1791,7 +1791,7 @@
}
fn f(ext_tex : texture_2d<f32>, ext_tex_plane_1 : texture_2d<f32>, ext_tex_params : ExternalTextureParams) -> vec2<u32> {
- return textureDimensions(ext_tex);
+ return (ext_tex_params.visibleSize + vec2<u32>(1));
}
)";
diff --git a/src/tint/lang/wgsl/ast/transform/renamer_test.cc b/src/tint/lang/wgsl/ast/transform/renamer_test.cc
index b3aa2ac..6912b2e 100644
--- a/src/tint/lang/wgsl/ast/transform/renamer_test.cc
+++ b/src/tint/lang/wgsl/ast/transform/renamer_test.cc
@@ -1866,7 +1866,8 @@
std::vector<std::string_view> out;
for (auto type : core::kBuiltinTypeStrings) {
if (type != "ptr" && type != "atomic" && !tint::HasPrefix(type, "sampler") &&
- !tint::HasPrefix(type, "texture") && !tint::HasPrefix(type, "__")) {
+ !tint::HasPrefix(type, "texture") && !tint::HasPrefix(type, "__") &&
+ !tint::HasPrefix(type, "input_attachment")) {
out.push_back(type);
}
}
diff --git a/src/tint/lang/wgsl/reader/parser/error_resync_test.cc b/src/tint/lang/wgsl/reader/parser/error_resync_test.cc
index 54818ea..f5d39eb 100644
--- a/src/tint/lang/wgsl/reader/parser/error_resync_test.cc
+++ b/src/tint/lang/wgsl/reader/parser/error_resync_test.cc
@@ -67,7 +67,7 @@
^
test.wgsl:4:2 error: expected attribute
-Possible values: 'align', 'binding', 'blend_src', 'builtin', 'color', 'compute', 'diagnostic', 'fragment', 'group', 'id', 'interpolate', 'invariant', 'location', 'must_use', 'size', 'vertex', 'workgroup_size'
+Possible values: 'align', 'binding', 'blend_src', 'builtin', 'color', 'compute', 'diagnostic', 'fragment', 'group', 'id', 'input_attachment_index', 'interpolate', 'invariant', 'location', 'must_use', 'size', 'vertex', 'workgroup_size'
@_ fn -> {}
^
)");
@@ -135,7 +135,7 @@
^^^^
test.wgsl:7:6 error: expected attribute
-Possible values: 'align', 'binding', 'blend_src', 'builtin', 'color', 'compute', 'diagnostic', 'fragment', 'group', 'id', 'interpolate', 'invariant', 'location', 'must_use', 'size', 'vertex', 'workgroup_size'
+Possible values: 'align', 'binding', 'blend_src', 'builtin', 'color', 'compute', 'diagnostic', 'fragment', 'group', 'id', 'input_attachment_index', 'interpolate', 'invariant', 'location', 'must_use', 'size', 'vertex', 'workgroup_size'
@- x : i32,
^
)");
diff --git a/src/tint/lang/wgsl/reader/parser/function_attribute_list_test.cc b/src/tint/lang/wgsl/reader/parser/function_attribute_list_test.cc
index 3e66246..99e5cb6 100644
--- a/src/tint/lang/wgsl/reader/parser/function_attribute_list_test.cc
+++ b/src/tint/lang/wgsl/reader/parser/function_attribute_list_test.cc
@@ -66,7 +66,7 @@
EXPECT_TRUE(attrs.value.IsEmpty());
EXPECT_EQ(p->error(), R"(1:2: expected attribute
Did you mean 'invariant'?
-Possible values: 'align', 'binding', 'blend_src', 'builtin', 'color', 'compute', 'diagnostic', 'fragment', 'group', 'id', 'interpolate', 'invariant', 'location', 'must_use', 'size', 'vertex', 'workgroup_size')");
+Possible values: 'align', 'binding', 'blend_src', 'builtin', 'color', 'compute', 'diagnostic', 'fragment', 'group', 'id', 'input_attachment_index', 'interpolate', 'invariant', 'location', 'must_use', 'size', 'vertex', 'workgroup_size')");
}
} // namespace
diff --git a/src/tint/lang/wgsl/reader/parser/variable_attribute_list_test.cc b/src/tint/lang/wgsl/reader/parser/variable_attribute_list_test.cc
index 7b82086..c1361b7 100644
--- a/src/tint/lang/wgsl/reader/parser/variable_attribute_list_test.cc
+++ b/src/tint/lang/wgsl/reader/parser/variable_attribute_list_test.cc
@@ -64,7 +64,7 @@
EXPECT_TRUE(attrs.value.IsEmpty());
EXPECT_EQ(p->error(), R"(1:2: expected attribute
Did you mean 'invariant'?
-Possible values: 'align', 'binding', 'blend_src', 'builtin', 'color', 'compute', 'diagnostic', 'fragment', 'group', 'id', 'interpolate', 'invariant', 'location', 'must_use', 'size', 'vertex', 'workgroup_size')");
+Possible values: 'align', 'binding', 'blend_src', 'builtin', 'color', 'compute', 'diagnostic', 'fragment', 'group', 'id', 'input_attachment_index', 'interpolate', 'invariant', 'location', 'must_use', 'size', 'vertex', 'workgroup_size')");
}
} // namespace
diff --git a/src/tint/lang/wgsl/resolver/resolver.cc b/src/tint/lang/wgsl/resolver/resolver.cc
index 34d3af3..0a17841 100644
--- a/src/tint/lang/wgsl/resolver/resolver.cc
+++ b/src/tint/lang/wgsl/resolver/resolver.cc
@@ -46,6 +46,7 @@
#include "src/tint/lang/core/type/depth_multisampled_texture.h"
#include "src/tint/lang/core/type/depth_texture.h"
#include "src/tint/lang/core/type/external_texture.h"
+#include "src/tint/lang/core/type/input_attachment.h"
#include "src/tint/lang/core/type/memory_view.h"
#include "src/tint/lang/core/type/multisampled_texture.h"
#include "src/tint/lang/core/type/pointer.h"
@@ -2654,6 +2655,8 @@
return StorageTexture(ident, core::type::TextureDimension::k2dArray);
case core::BuiltinType::kTextureStorage3D:
return StorageTexture(ident, core::type::TextureDimension::k3d);
+ case core::BuiltinType::kInputAttachment:
+ return InputAttachment(ident);
case core::BuiltinType::kPackedVec3:
return PackedVec3T(ident);
case core::BuiltinType::kAtomicCompareExchangeResultI32:
@@ -2968,6 +2971,21 @@
return tex;
}
+core::type::InputAttachment* Resolver::InputAttachment(const ast::Identifier* ident) {
+ auto* tmpl_ident = TemplatedIdentifier(ident, 1);
+ if (TINT_UNLIKELY(!tmpl_ident)) {
+ return nullptr;
+ }
+
+ auto* ty_expr = sem_.GetType(tmpl_ident->arguments[0]);
+ if (TINT_UNLIKELY(!ty_expr)) {
+ return nullptr;
+ }
+
+ auto* out = b.create<core::type::InputAttachment>(ty_expr);
+ return validator_.InputAttachment(out, ident->source) ? out : nullptr;
+}
+
core::type::Vector* Resolver::PackedVec3T(const ast::Identifier* ident) {
auto* tmpl_ident = TemplatedIdentifier(ident, 1);
if (TINT_UNLIKELY(!tmpl_ident)) {
diff --git a/src/tint/lang/wgsl/resolver/resolver.h b/src/tint/lang/wgsl/resolver/resolver.h
index 715d62a..df18f91 100644
--- a/src/tint/lang/wgsl/resolver/resolver.h
+++ b/src/tint/lang/wgsl/resolver/resolver.h
@@ -223,6 +223,9 @@
core::type::StorageTexture* StorageTexture(const ast::Identifier* ident,
core::type::TextureDimension dim);
+ /// @returns an input attachment resolved from the templated identifier @p ident
+ core::type::InputAttachment* InputAttachment(const ast::Identifier* ident);
+
/// @returns a packed vec3 resolved from the templated identifier @p ident.
core::type::Vector* PackedVec3T(const ast::Identifier* ident);
diff --git a/src/tint/lang/wgsl/resolver/validator.cc b/src/tint/lang/wgsl/resolver/validator.cc
index 155aaf1..f482497 100644
--- a/src/tint/lang/wgsl/resolver/validator.cc
+++ b/src/tint/lang/wgsl/resolver/validator.cc
@@ -441,6 +441,15 @@
return true;
}
+bool Validator::InputAttachment(const core::type::InputAttachment* t, const Source& source) const {
+ if (!t->type()->UnwrapRef()->IsAnyOf<core::type::F32, core::type::I32, core::type::U32>()) {
+ AddError(source) << "input_attachment<type>: type must be f32, i32 or u32";
+ return false;
+ }
+
+ return true;
+}
+
bool Validator::Materialize(const core::type::Type* to,
const core::type::Type* from,
const Source& source) const {
diff --git a/src/tint/lang/wgsl/resolver/validator.h b/src/tint/lang/wgsl/resolver/validator.h
index 0fa3bd9..6cdbfaf 100644
--- a/src/tint/lang/wgsl/resolver/validator.h
+++ b/src/tint/lang/wgsl/resolver/validator.h
@@ -428,6 +428,12 @@
/// @returns true on success, false otherwise
bool MultisampledTexture(const core::type::MultisampledTexture* t, const Source& source) const;
+ /// Validates a input attachment
+ /// @param t the input attachment to validate
+ /// @param source the source of the input attachment
+ /// @returns true on success, false otherwise
+ bool InputAttachment(const core::type::InputAttachment* t, const Source& source) const;
+
/// Validates a structure
/// @param str the structure to validate
/// @param stage the current pipeline stage