tint/msl: Preserve trailing vec3 padding

In order to preserve padding properly for MSL, we need to use its
packed_vec type for all vec3 types in storage buffers, not just struct
members. This commit includes a complete rewrite of the PackedVec3
transform to achieve this. The key details are:

* An internal `__packed_vec3<>` type was added, which corresponds to a
  `type::Vector` with an additional flag to indicate that it will be
  emitted as packed vector.

* The `PackedVec3` transform replaces all vec3 types used in
  host-shareable address spaces with the internal `__packed_vec3`
  type. This includes vec3 types that appear as the store type of a
  pointer.

* When used as an array element, these `__packed_vec3` types are
  wrapped in a struct that contains a single `__packed_vec3`
  member. This allows us to add an `@align()` attribute that ensures
  that `array<vec3<T>>` still has the correct array element stride.

* When the `vec3<T>` appears as a struct member in the input program,
  we apply the `@align()` to that member to ensure that we do not
  change its offset.

* Matrix types with three rows that are used in memory are replaced
  with an array of columns, where each column uses a `__packed_vec3`
  inside an aligned wrapper structure as above.

* Accesses to host-shareable memory that involve any of these types
  invoke a "pack" or "unpack" helper function to convert them to the
  equivalent type that uses `__packed_vec3` or a regular `vec3` as
  required.

* The `chromium_internal_relaxed_uniform_layout` extension is used to
  avoid issues where modifying a type in the uniform address space
  triggers stricter layout validation rules.

Bug: tint:1571
Fixed: tint:1837
Change-Id: Idaf2da2f5bcb2be00c85ec657edfb614186476bb
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/121200
Reviewed-by: Ben Clayton <bclayton@google.com>
Commit-Queue: James Price <jrprice@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
This commit is contained in:
James Price
2023-02-27 20:21:03 +00:00
committed by Dawn LUCI CQ
parent 55183e6c3a
commit 4d3af66bbd
389 changed files with 16692 additions and 3527 deletions

View File

@@ -28,6 +28,9 @@ namespace tint::builtin {
/// @param str the string to parse
/// @returns the parsed enum, or Builtin::kUndefined if the string could not be parsed.
Builtin ParseBuiltin(std::string_view str) {
if (str == "__packed_vec3") {
return Builtin::kPackedVec3;
}
if (str == "array") {
return Builtin::kArray;
}
@@ -242,6 +245,8 @@ std::ostream& operator<<(std::ostream& out, Builtin value) {
switch (value) {
case Builtin::kUndefined:
return out << "undefined";
case Builtin::kPackedVec3:
return out << "__packed_vec3";
case Builtin::kArray:
return out << "array";
case Builtin::kAtomic:

View File

@@ -30,6 +30,7 @@ namespace tint::builtin {
/// An enumerator of builtin builtin.
enum class Builtin {
kUndefined,
kPackedVec3,
kArray,
kAtomic,
kBool,
@@ -112,6 +113,7 @@ std::ostream& operator<<(std::ostream& out, Builtin value);
Builtin ParseBuiltin(std::string_view str);
constexpr const char* kBuiltinStrings[] = {
"__packed_vec3",
"array",
"atomic",
"bool",

View File

@@ -31,489 +31,496 @@ namespace {
void BuiltinParser(::benchmark::State& state) {
const char* kStrings[] = {
"arccy",
"3a",
"aVray",
"__acked_veccc",
"_pac3ed_v3",
"__packeV_vec3",
"__packed_vec3",
"__pa1ked_vec3",
"_qqJcked_vec3",
"__pack77d_vllc3",
"arqHapp",
"vy",
"Grby",
"array",
"arra1",
"qqrJy",
"arrll7y",
"atppmHHc",
"cto",
"abGmi",
"arviay",
"ar8WWy",
"Mxxra",
"atXggi",
"Xoic",
"ato3ic",
"atomic",
"atvmiii",
"atWWm8c",
"xxtomc",
"bXgg",
"Xu",
"b3ol",
"aEomic",
"toTTiPP",
"ddtoxxi",
"44ool",
"VVSSol",
"RoRl",
"bool",
"booE",
"TTPol",
"xxool",
"4416",
"fSVV6",
"RR2",
"oFl",
"boo",
"ORVHl",
"y1",
"l77rrn6",
"4016",
"f16",
"96",
"f1",
"VOR6",
"y3",
"l77rrn2",
"4032",
"f32",
"5",
"u377",
"kk2",
"ii",
"i3XX",
"u16",
"f",
"f3kk",
"fi",
"f3XX",
"f32",
"55399II",
"i32",
"irSSHHa",
"frSSHHa",
"U",
"jV3",
"ax2",
"t2SGG",
"q2x2",
"mat2x2",
"at2",
"majjx",
"",
"GG",
"i32",
"2",
"",
"jj",
"a2xrf",
"mat2xjf",
"mNNw2x28",
"matx2f",
"mat2x2f",
"mrrt2x2f",
"Gat2x2f",
"mat2j2",
"m82wNN2",
"mat2x2",
"mt2x2",
"rrat2x2",
"mGt2x2",
"mat2x2FF",
"at2h",
"marrx2h",
"t2x2h",
"mat2x2h",
"Da2xJJh",
"at2f",
"marrx2f",
"mat2x2f",
"t2x2f",
"Da2xJJf",
"ma82",
"m11k2",
"matx3",
"maJx3",
"cat2x3",
"mat2x3",
"mat2O3",
"ttKavv2x__",
"matx2h",
"maJx2h",
"mat2x2h",
"mat2c2h",
"mat2x2O",
"KK_atvvtt2h",
"5txxx8",
"__qatF3",
"matqx3f",
"33atOx3f",
"mat2x3f",
"mtt62x9oQQ",
"ma2x66f",
"a__xqq",
"maqq2x",
"mat2x3",
"ma32x66",
"mttQQo2x3",
"mat66x",
"mtOxzz66",
"mat2yy3h",
"mat2yy3f",
"ZaHH3Z",
"4WWt2q3h",
"mat2x3h",
"mOO2x3h",
"oatY3h",
"mat2x3f",
"4WWt2q3f",
"mOO2x3f",
"oatY3f",
"matx",
"ma2x4",
"matw4",
"ma2Gf",
"mat2x4",
"qatKKx4",
"mmmt2x4",
"ma2xFh",
"at2x3w",
"mat2x3h",
"fGtxKh",
"matqKx3h",
"matmmxFh",
"at2x4",
"mt2x4q",
"mat2xbb",
"mi2x4f",
"mat2x4f",
"maOO2xq",
"matTvvx4f",
"matxq",
"mb2bb4",
"mat2x4",
"it2x4",
"mOO2xq",
"mat2Tvv4",
"maFF2x4f",
"Pa00xQh",
"mPt2x4h",
"Pa00xQf",
"mPt2x4f",
"mat2x4f",
"ma772xss",
"mat2x4h",
"RRCbb2x4h",
"mXXt2x4h",
"RRCbb2x4f",
"mXXt2x4f",
"qaCC2xOOh",
"mtsuL",
"mat3xX",
"mat3x",
"mat3x2",
"qqt2",
"mat3x22",
"ma2s4L",
"mXt2x4h",
"mat2x4h",
"mat24h",
"qa2O4",
"mat2x22h",
"mzzyt3x",
"matVViP",
"mannC2f",
"atx2AHHq",
"atiVP2",
"mt3Cnn",
"mat3x2",
"AtqqHH2",
"at3x2",
"mafKK",
"ltgg2f",
"mat3xf",
"NTTtcx4f",
"mat3x2f",
"may3x2",
"aOOOZZf",
"Vt12f",
"mff__3x2h",
"qaTMMl4h",
"ma7ppl2f",
"mNNt3xg",
"mat3x2h",
"uub3XX2h",
"uub3XX2f",
"matx2h",
"Qt882h",
"maqx3",
"mat3113",
"Ft3xi22",
"mat3x3",
"m7t3x3",
"mt9q2h",
"mat3x2h",
"m11t3x2h",
"22at3iih",
"at3x277",
"NNa323",
"VVat3x3",
"FaWW3w11f",
"mawwx3f",
"Dat3x3f",
"mat3x3f",
"mt3x3K",
"ma11F3w3",
"mat3x3",
"matww3",
"mat3D3",
"maKx3",
"mat31PPhf",
"mat33f",
"mYYt3x3h",
"mYYt3x3f",
"mat3x3f",
"mttHH3kk",
"mat3rr3h",
"mat3x3h",
"WWas3x3h",
"mat3rr3f",
"WWas3x3f",
"Yt3x3h",
"mt3qfh",
"vvafu224",
"mt34",
"maY34",
"mat3x4",
"YYa7y3E4",
"mav223xuh",
"mat3x3h",
"t3x3h",
"YYat3h",
"may3x3EYY",
"Moatd4",
"mt3xMM",
"mat3x55f",
"maN34",
"ma3Ox33",
"m55t3x4",
"mat3x4",
"maN4",
"ma33x4",
"mt3x3",
"mm66Issf",
"mat3x1f",
"Xt3x4",
"mat3x4f",
"m3t3x4f",
"mam3xI",
"mnnt3r4K",
"m3XX",
"LatIx4h",
"at3fh",
"mat3x4h",
"LatIx4f",
"at3ff",
"mYtURD4",
"mah3x4h",
"uuIqt3x",
"mat4xH",
"at4Qvv",
"66ate",
"mat4x2",
"mat7x",
"maH3x4h",
"mat3x4h",
"at3QQvv",
"at66eh",
"ma7O4h",
"m0t55DD2",
"IIaH4x2",
"at4x2",
"rat4x299",
"mGtt41W2f",
"mat4x2f",
"yatx2",
"mat4x",
"mat4x2",
"mt4r2",
"mat4xl",
"mGttx2",
"mat4y2",
"mt4x2f",
"IIaBB4x2f",
"mat4x2f",
"TTat4x833",
"ddUUnntYYx2h",
"ddUUnntYYx2f",
"m5CCxxdZ",
"mat4x2h",
"matkkq2h",
"005itpxh",
"maIInnx2h",
"ccaKx",
"mtKK",
"ma664x3",
"mat4x3",
"mat4x2h",
"Ka4Wcc",
"m42KK",
"mat66x2h",
"mKKtPx",
"maxx43",
"matqx3",
"MMayySrxf",
"mat3f",
"tx3f",
"mat4x3f",
"mat4x3",
"rMtyyxSS",
"uat4",
"tx3",
"ma5F4x3f",
"rra444z3f",
"matWW",
"CatZJXx3h",
"maPPx3h",
"mat4c3h",
"mat4x3h",
"mat4x3f",
"CatZJXx3f",
"maPPx3f",
"mat4c3f",
"matPPll6h",
"mat993yy",
"mat4JKKh",
"ma_x4",
"a4K4",
"kVt4xz",
"mat4x4",
"mat4x3h",
"mat4_h",
"ayK3h",
"mzt4V3k",
"qaSKx4",
"mat44",
"ma4xVV",
"AAatIxUf",
"mbj4f",
"YY444x",
"mat4x4f",
"mat4x4",
"mAAt4xI",
"jb44",
"t4YYx",
"mao4x4",
"mtx114f",
"mtmxccf",
"aJJ4x4h",
"mat4x4f",
"aJJ4x4f",
"fCCDD4x4U",
"mgt4x4h",
"mat4x4h",
"mgt4x4f",
"CCx4h",
"mat4x66",
"maN4M4h",
"pt",
"KW",
"pzzee",
"ptr",
"mat4x4h",
"mattth",
"maKWxh",
"mateezx4h",
"",
"w9",
"4tnn",
"sllDler",
"oamp4er",
"wEaggler",
"sampler",
"ptr",
"tll",
"4to",
"wEgg",
"gamler",
"spleS",
"aampl",
"sampZcRTr_comparison",
"sampler_88TmparisOn",
"sampler_comparim00n",
"sampler_comparison",
"sampler",
"TamplZRRr",
"sa8TplOr",
"m0ampler",
"sampler_Bmomparison",
"Mamper_ppomarison",
"samper_compOOrison",
"teGtGre_1d",
"tex11ureHH1d",
"6exeeur_1FF",
"texture_1d",
"sampler_comparison",
"sampler_compGrGGon",
"sHHm11ler_comparison",
"sa6ler_FFeemparison",
"texure_1",
"tKiilure_1d",
"exture_1d",
"99etvIIre_2d",
"texture_1d",
"99etvIIre_1d",
"texture_d",
"texture_hd",
"texture_2d",
"llxzzure_PPd",
"exue2d",
"tffqqtre_2d",
"texJJre_2dd_arWay",
"teXXzzre_2darray",
"textu2_2d_array",
"texture_2d_array",
"texture_2d",
"texturJdd_d",
"trXXtu_2zz",
"textu2e2d",
"tNyyture_2d_array",
"txture_2d_rOOa",
"textureErduaZPay",
"22lxtredd3ee",
"texVVe93d",
"teture_I1d",
"texture_3d",
"texture_2d_array",
"exl22re_2dd_areeay",
"mextureVV_ar9ay",
"teIItu1_2d_array",
"tebture_3d",
"ie7ure3d",
"teotiire_3d",
"entre_cube",
"texturScube",
"tex22r_cube",
"texture_cube",
"texture_3d",
"extre_35",
"textre_iS",
"t22xtur_3",
"teC711recuGe",
"texture8cffbe",
"textue_cue",
"tJJxture_SSube_array",
"texture_9ue_arry",
"TbbJJxture_cube_array",
"texture_cube_array",
"texture_cube",
"texture_SSJJbe",
"textrecu9e",
"TTeJJbture_cube",
"t66ture_cube_aray",
"textur66_cubu_arra",
"textureWubeyarray",
"texture_deth_d",
"texture_epth_2d",
"texture_derth_2d",
"texture_depth_2d",
"texture_cube_array",
"texture_cube_ara",
"texture_ube_array",
"rexture_cube_array",
"tex2ure_depth_2B",
"texture_dpBBh_2d",
"texture_dpth_RRd",
"tLLxture_deptVV0darray",
"textuOOe_dethKK2d_arra",
"textuwe_ggepth_2d_rray",
"texture_depth_2d_array",
"texture_depth_2d",
"tLL0Vure_deth_2d",
"tetKKredOOpth_2d",
"textgwre_dpth_2d",
"textue_depthLh2d_arpay",
"texture_depEh2diiKrray",
"texture_dept_2d_array",
"textuUUe88dept_cbe",
"texrrure_depvvh_cube",
"texure_wepmmh_ube",
"texture_depth_cube",
"texture_depth_2d_array",
"t88xtuUUe_deph_2d_rray",
"texrruvve_depth_2d_array",
"texture_depmm_2d_wray",
"tjture_d44pth_cube",
"texture_depth_cXbe",
"t8xture_depth_cube",
"textre_depth_cubeEEarrvvy",
"tzzture_d9pth_cuie_array",
"teAture_depth_QQube_GGrrJJy",
"texture_depth_cube_array",
"texture_depth_cube",
"textur_devvth_cubEE",
"tzxturi99epth_cube",
"teQQtuJJGe_nepth_cuAe",
"texture_depth_cusse_array",
"texture_Pepth_cKbe_array",
"texture_dppp_cube_attray",
"texture_depth_multisample_2",
"texture_depth_multisamplMMd_2d",
"texJJure_de0th_multisampled_2d",
"texture_depth_multisampled_2d",
"texture_depth_cube_array",
"exture_deth_cube_array",
"texture_depth_MMube_array",
"tJJxture_depth_cube_a0ray",
"textu8_dpth_mulisampled_2V",
"texture_dhhpth_mKltisggmpled_2d",
"texture_depth_multisampledf2d",
"tex77ure_exQernal",
"tYYxture_externa",
"tektur_exterSal",
"texture_external",
"texture_depth_multisampled_2d",
"te77ture_depth_multisamQled_2d",
"teture_depthYYmultisampled_2d",
"texture_deptk_multiampled_Sd",
"txturn_ext2rnal",
"txture_FFternal",
"texUPPIre_GGxuernal",
"txtuEEe_mulaisFmpledv2d",
"ddexBBure_mltDDeampled_2d",
"teMture_EEulccisam55led_2",
"texture_multisampled_2d",
"texture_external",
"taxtuvEE_externl",
"textureexBddernDDl",
"tEEMtur_e55tccrnal",
"texturemuKKtisample_d",
"texture_multisRmpled_2d",
"texturemulDisampl9d_2d",
"texturestorage_1d",
"textIre_storaa_1d",
"texture_sto77age_1d",
"texture_storage_1d",
"texture_multisampled_2d",
"teture_multisampled_2d",
"textuIa_multisampld_2d",
"texture_multisamp77ed_2d",
"texIure_storage_1d",
"texture_storagedd",
"texture_storae_1d",
"texture_storage_1d",
"texture_strate_d",
"texture33stoXXcge_2d",
"texturestorage_2E",
"texture_storage_2d",
"texture33stoXXcge_1d",
"texturestorage_1E",
"textuXXestorage_2d",
"texture_stoBaxxe_2d",
"texte_storWge_2G",
"texture_storage_2d_ar66ay",
"t0xTTr_storave_2d_array",
"kexure_orage_2d_rray",
"texture_storage_2d_array",
"texture_storage_2d",
"texture_s66orage_2d",
"textvTr_so0age_2d",
"textureorgek2d",
"textppre_stoae_2d_array",
"textre_stora11e_d_array",
"textureystorBEgeJ2d_array",
"textqreIImtxrage_3d",
"texture_toFage_3d",
"exture_Ytorage_3d",
"texture_storage_3d",
"texture_storage_2d_array",
"texture_mtorage_2dxIqrray",
"teture_storageF2d_array",
"textur_Ytorage_2d_array",
"heDture_sHHorage_3d",
"texturstorage23H",
"teture_strage_3d",
"u2",
"u2",
"dd32",
"u32",
"texture_storage_3d",
"texture_storage_d",
"texturestorage_3d",
"ddexture_storage_3d",
"uPO",
"ba",
"u02",
"veh2",
"vgY2",
"Oec2",
"vec2",
"u32",
"h32",
"gYY",
"O32",
"eh",
"ppfe2",
"vev",
"vc2zz",
"vaac2",
"Ouuicf",
"vec2f",
"vec2",
"vzz2",
"vc2",
"OOii",
"vGc2f",
"22ecTTf",
"dlc2f",
"vecbh",
"vec2f",
"vecbf",
"ec2BB",
"IIScXPP",
"vec2h",
"jjec2h",
"cc_c2h",
"zz6xx2h",
"vec2h",
"c2",
"4xx2N",
"p0AAei",
"vec2i",
"p0AAeh",
"vey2",
"vbWW0i",
"meMMtti",
"du",
"vec2i",
"di",
"vvc_",
"VEEc2u",
"vec2u",
"VEEc2i",
"vec24",
"VVeX2u",
"veVou",
"vec",
"KKc3",
"G",
"vec3",
"vec2u",
"ve2u",
"ecKKt",
"eG",
"ea3",
"OOc",
"G",
"v5c3f",
"99jcfff",
"XXvYY3R",
"vec3f",
"vec3",
"ve53",
"9fjec3",
"vvXcRY",
"ccf",
"v8XX5",
"ec3",
"vec3f",
"ppc3cc",
"vecvh",
"vecvf",
"eEE3SS",
"vec3h",
"vec",
"eh",
"ec3ww",
"vecd99i",
"vec3h",
"vecd99h",
"ve99P",
"KKec3",
"vec3i",
"ooMcDD",
"vei",
"vqi",
"vec3i",
"veL30",
"vncvv66",
"vrrn3",
"vec3u",
"vxxce",
"NCCOc3u",
"vc3u",
"veca",
"veNNN",
"vec",
"vec4",
"vec3u",
"aec4u",
"NNc3NN",
"ve3u",
"vc",
"vAYS4",
"vec0",
"vecaaf",
"vmm4f",
"ec4f",
"vec4f",
"vec4",
"vecaa",
"mmcq",
"vc4",
"vE4U",
"veKD4",
"v0t4__",
"vec4f",
"cpA",
"ec4h",
"vBBc4h",
"vec4h",
"ec4f",
"vBBc4f",
"vbnn99",
"EEcAAh",
"v5c66h",
"vHc4i",
"vecxi",
"vec4h",
"vHc4h",
"vecxh",
"vzyn40",
"vec4i",
"ve4i",
"kH4i",
"veci",
"vec4i",
"oo4rr",
"JJc4",
"vcCC0",
"vec4u",
"xAA99F",
"veccu",
"vec4S",
"vec4u",
"vocBB",
"ec4u",
"veemm",
};
for (auto _ : state) {
for (auto* str : kStrings) {

View File

@@ -43,6 +43,7 @@ inline std::ostream& operator<<(std::ostream& out, Case c) {
}
static constexpr Case kValidCases[] = {
{"__packed_vec3", Builtin::kPackedVec3},
{"array", Builtin::kArray},
{"atomic", Builtin::kAtomic},
{"bool", Builtin::kBool},
@@ -115,213 +116,216 @@ static constexpr Case kValidCases[] = {
};
static constexpr Case kInvalidCases[] = {
{"arccy", Builtin::kUndefined},
{"3a", Builtin::kUndefined},
{"aVray", Builtin::kUndefined},
{"1tomic", Builtin::kUndefined},
{"aoqqic", Builtin::kUndefined},
{"atomll77", Builtin::kUndefined},
{"ppqooH", Builtin::kUndefined},
{"c", Builtin::kUndefined},
{"bGo", Builtin::kUndefined},
{"f1vi", Builtin::kUndefined},
{"f8WW", Builtin::kUndefined},
{"fxx", Builtin::kUndefined},
{"__acked_veccc", Builtin::kUndefined},
{"_pac3ed_v3", Builtin::kUndefined},
{"__packeV_vec3", Builtin::kUndefined},
{"arra1", Builtin::kUndefined},
{"qqrJy", Builtin::kUndefined},
{"arrll7y", Builtin::kUndefined},
{"atppmHHc", Builtin::kUndefined},
{"cto", Builtin::kUndefined},
{"abGmi", Builtin::kUndefined},
{"bovii", Builtin::kUndefined},
{"boWWl", Builtin::kUndefined},
{"Mxxl", Builtin::kUndefined},
{"fgg", Builtin::kUndefined},
{"X", Builtin::kUndefined},
{"332", Builtin::kUndefined},
{"iE2", Builtin::kUndefined},
{"iPTT", Builtin::kUndefined},
{"316", Builtin::kUndefined},
{"fE2", Builtin::kUndefined},
{"fPTT", Builtin::kUndefined},
{"dxx2", Builtin::kUndefined},
{"44at2x2", Builtin::kUndefined},
{"mSSVV2x2", Builtin::kUndefined},
{"mat2R2", Builtin::kUndefined},
{"mF2x9f", Builtin::kUndefined},
{"matx2f", Builtin::kUndefined},
{"VOORRH2f", Builtin::kUndefined},
{"ma2xyh", Builtin::kUndefined},
{"llnarr2772h", Builtin::kUndefined},
{"4432", Builtin::kUndefined},
{"iSVV2", Builtin::kUndefined},
{"RR2", Builtin::kUndefined},
{"at292", Builtin::kUndefined},
{"mat2x", Builtin::kUndefined},
{"Vat2OR2", Builtin::kUndefined},
{"ma2xyf", Builtin::kUndefined},
{"llnarr2772f", Builtin::kUndefined},
{"mat24200", Builtin::kUndefined},
{"m2oo", Builtin::kUndefined},
{"atzz3", Builtin::kUndefined},
{"1it2xpp", Builtin::kUndefined},
{"mat2xXXf", Builtin::kUndefined},
{"9II5ann2x3f", Builtin::kUndefined},
{"mataSSrHHYf", Builtin::kUndefined},
{"makkh", Builtin::kUndefined},
{"a2ooh", Builtin::kUndefined},
{"zz2x2h", Builtin::kUndefined},
{"miitppx1", Builtin::kUndefined},
{"maXX2x3", Builtin::kUndefined},
{"55IIt2nn99", Builtin::kUndefined},
{"aHHrrt2xSS", Builtin::kUndefined},
{"makkf", Builtin::kUndefined},
{"jatgRx", Builtin::kUndefined},
{"mb2x3", Builtin::kUndefined},
{"mat2j4", Builtin::kUndefined},
{"mt2x4", Builtin::kUndefined},
{"m2q4", Builtin::kUndefined},
{"matNN4f", Builtin::kUndefined},
{"at24vv", Builtin::kUndefined},
{"QQt2x4f", Builtin::kUndefined},
{"maffxr", Builtin::kUndefined},
{"mat2xjh", Builtin::kUndefined},
{"at2x3h", Builtin::kUndefined},
{"q2x3h", Builtin::kUndefined},
{"mNN2x4", Builtin::kUndefined},
{"mavv4", Builtin::kUndefined},
{"maQQx4", Builtin::kUndefined},
{"maffxr", Builtin::kUndefined},
{"mat2xjf", Builtin::kUndefined},
{"mNNw2x48", Builtin::kUndefined},
{"mt3x2", Builtin::kUndefined},
{"rrat3x2", Builtin::kUndefined},
{"mGt3x2", Builtin::kUndefined},
{"mat3x2FF", Builtin::kUndefined},
{"at3f", Builtin::kUndefined},
{"marrx2f", Builtin::kUndefined},
{"t3x2h", Builtin::kUndefined},
{"Da3xJJh", Builtin::kUndefined},
{"matx4h", Builtin::kUndefined},
{"mrrt2x4h", Builtin::kUndefined},
{"Gat2x4h", Builtin::kUndefined},
{"matFFx2", Builtin::kUndefined},
{"mtx", Builtin::kUndefined},
{"mrrt3x", Builtin::kUndefined},
{"t3x2f", Builtin::kUndefined},
{"Da3xJJf", Builtin::kUndefined},
{"ma82", Builtin::kUndefined},
{"1k33", Builtin::kUndefined},
{"matx3", Builtin::kUndefined},
{"maJx3", Builtin::kUndefined},
{"mat3c3f", Builtin::kUndefined},
{"mat3x3O", Builtin::kUndefined},
{"KK_atvvtt3f", Builtin::kUndefined},
{"xx83x3h", Builtin::kUndefined},
{"m11k2", Builtin::kUndefined},
{"matx2h", Builtin::kUndefined},
{"maJx2h", Builtin::kUndefined},
{"cat3x3", Builtin::kUndefined},
{"mat3O3", Builtin::kUndefined},
{"ttKavv3x__", Builtin::kUndefined},
{"xx83x3f", Builtin::kUndefined},
{"__qatF3", Builtin::kUndefined},
{"matqx3h", Builtin::kUndefined},
{"ma33x66", Builtin::kUndefined},
{"mttQQo3x4", Builtin::kUndefined},
{"mat66x", Builtin::kUndefined},
{"mtOxzz66", Builtin::kUndefined},
{"mat3yy4f", Builtin::kUndefined},
{"ZaHH4Z", Builtin::kUndefined},
{"4WWt3q4h", Builtin::kUndefined},
{"mOO3x4h", Builtin::kUndefined},
{"oatY4h", Builtin::kUndefined},
{"ax2", Builtin::kUndefined},
{"ma4x2", Builtin::kUndefined},
{"matw2", Builtin::kUndefined},
{"fGtxKf", Builtin::kUndefined},
{"matqKx2f", Builtin::kUndefined},
{"matmmxFf", Builtin::kUndefined},
{"at4x2h", Builtin::kUndefined},
{"matqx3f", Builtin::kUndefined},
{"33atOx3h", Builtin::kUndefined},
{"mtt63x9oQQ", Builtin::kUndefined},
{"ma3x66h", Builtin::kUndefined},
{"66aOzx4", Builtin::kUndefined},
{"myyt3x4", Builtin::kUndefined},
{"HHZx4", Builtin::kUndefined},
{"4WWt3q4f", Builtin::kUndefined},
{"mOO3x4f", Builtin::kUndefined},
{"oatY4f", Builtin::kUndefined},
{"matx", Builtin::kUndefined},
{"ma3xFh", Builtin::kUndefined},
{"at3x4w", Builtin::kUndefined},
{"ma4Gf", Builtin::kUndefined},
{"qatKKx2", Builtin::kUndefined},
{"mmmt4x2", Builtin::kUndefined},
{"at4x2f", Builtin::kUndefined},
{"mt4x2q", Builtin::kUndefined},
{"mat4xbb", Builtin::kUndefined},
{"it4x3", Builtin::kUndefined},
{"mOO4xq", Builtin::kUndefined},
{"mat4Tvv3", Builtin::kUndefined},
{"maFF4x3f", Builtin::kUndefined},
{"Pa00xQf", Builtin::kUndefined},
{"mPt4x3f", Builtin::kUndefined},
{"mi4x2h", Builtin::kUndefined},
{"maOO4xq", Builtin::kUndefined},
{"matTvvx2h", Builtin::kUndefined},
{"mat4FF3", Builtin::kUndefined},
{"mtQ00P", Builtin::kUndefined},
{"maP4x3", Builtin::kUndefined},
{"ma774xss", Builtin::kUndefined},
{"RRCbb4x3h", Builtin::kUndefined},
{"mXXt4x3h", Builtin::kUndefined},
{"CCt4OOOO", Builtin::kUndefined},
{"mtsuL", Builtin::kUndefined},
{"mat4xX", Builtin::kUndefined},
{"mat44f", Builtin::kUndefined},
{"qa4O4", Builtin::kUndefined},
{"mat4x22f", Builtin::kUndefined},
{"RRCbb4x3f", Builtin::kUndefined},
{"mXXt4x3f", Builtin::kUndefined},
{"qaCC4xOOh", Builtin::kUndefined},
{"ma4s3L", Builtin::kUndefined},
{"mXt4x3h", Builtin::kUndefined},
{"mat4x", Builtin::kUndefined},
{"qqt4", Builtin::kUndefined},
{"mat4x22", Builtin::kUndefined},
{"myzz40XX", Builtin::kUndefined},
{"matVViP", Builtin::kUndefined},
{"mannC4h", Builtin::kUndefined},
{"pHAq", Builtin::kUndefined},
{"tr", Builtin::kUndefined},
{"Kf", Builtin::kUndefined},
{"lmgger", Builtin::kUndefined},
{"samplr", Builtin::kUndefined},
{"NTTmcl4r", Builtin::kUndefined},
{"sampler_clmppri77on", Builtin::kUndefined},
{"samplg_czzmparNNso", Builtin::kUndefined},
{"smpleuuXXomparibbon", Builtin::kUndefined},
{"texture_1", Builtin::kUndefined},
{"t88tueQ1K", Builtin::kUndefined},
{"texturq9d", Builtin::kUndefined},
{"text11re_2d", Builtin::kUndefined},
{"teiiu22eF2d", Builtin::kUndefined},
{"tex77ur_2d", Builtin::kUndefined},
{"textNNr2_d_array", Builtin::kUndefined},
{"textVVre_2d_array", Builtin::kUndefined},
{"texwure_WWF_11rray", Builtin::kUndefined},
{"txture_3ww", Builtin::kUndefined},
{"texturD_3d", Builtin::kUndefined},
{"teKture_d", Builtin::kUndefined},
{"11exPPufe_cubh", Builtin::kUndefined},
{"textue_cube", Builtin::kUndefined},
{"texture_cubYY", Builtin::kUndefined},
{"texttr_cube_HHkkVay", Builtin::kUndefined},
{"texture_crrbe_array", Builtin::kUndefined},
{"texturesscubeWWaray", Builtin::kUndefined},
{"texture_deptY_d", Builtin::kUndefined},
{"teLturq_defh_2d", Builtin::kUndefined},
{"texvvre_duu22th_2d", Builtin::kUndefined},
{"texure_deth_2d_array", Builtin::kUndefined},
{"texturYY_depth_2daray", Builtin::kUndefined},
{"texturE_77epth_2d_aryYay", Builtin::kUndefined},
{"Mexdoore_depth_cue", Builtin::kUndefined},
{"texturedepMMh_cube", Builtin::kUndefined},
{"texture55depth_cube", Builtin::kUndefined},
{"textue_depth_cbe_aNray", Builtin::kUndefined},
{"texture_dpth_c33be_array", Builtin::kUndefined},
{"texture_depth_cub3_array", Builtin::kUndefined},
{"texIure_mepth_mulisampled_2d", Builtin::kUndefined},
{"texture_depthrmKltisampled_2nn", Builtin::kUndefined},
{"textur_depth_multismXld_2d", Builtin::kUndefined},
{"texpure_exLLeIna", Builtin::kUndefined},
{"txture_exfrnal", Builtin::kUndefined},
{"teUture_extYRRDl", Builtin::kUndefined},
{"texturehmultisampled_2d", Builtin::kUndefined},
{"texturqmultsIImuuled_2d", Builtin::kUndefined},
{"Hexture_multisampled_2d", Builtin::kUndefined},
{"texQQur_storge_vvd", Builtin::kUndefined},
{"texeure_66oage_1d", Builtin::kUndefined},
{"texture_stoage71d", Builtin::kUndefined},
{"texture_s55or0ge_2DD", Builtin::kUndefined},
{"teHture_storIIge_2d", Builtin::kUndefined},
{"textue_storage_2d", Builtin::kUndefined},
{"texturestorage_2d_rrray", Builtin::kUndefined},
{"textule_storage_2d_array", Builtin::kUndefined},
{"tetture_JJtorage_Gd_arra", Builtin::kUndefined},
{"yexture_storage3d", Builtin::kUndefined},
{"texturestorage_3d", Builtin::kUndefined},
{"texture_IItorBBge_3d", Builtin::kUndefined},
{"TTK33", Builtin::kUndefined},
{"nnUYdSS2", Builtin::kUndefined},
{"x5dZ", Builtin::kUndefined},
{"veckq", Builtin::kUndefined},
{"ii500", Builtin::kUndefined},
{"vecIIn", Builtin::kUndefined},
{"cceW", Builtin::kUndefined},
{"cKK", Builtin::kUndefined},
{"vec66f", Builtin::kUndefined},
{"vePPK", Builtin::kUndefined},
{"vexxh", Builtin::kUndefined},
{"qec2h", Builtin::kUndefined},
{"mannC4f", Builtin::kUndefined},
{"atx4AHHq", Builtin::kUndefined},
{"may4x4", Builtin::kUndefined},
{"aOOOZZh", Builtin::kUndefined},
{"V", Builtin::kUndefined},
{"ptf__", Builtin::kUndefined},
{"4lMT", Builtin::kUndefined},
{"sNNmplg", Builtin::kUndefined},
{"uubpXXer", Builtin::kUndefined},
{"samler", Builtin::kUndefined},
{"m88ler_cQmparisoK", Builtin::kUndefined},
{"qa9ler_comparison", Builtin::kUndefined},
{"sampler_comparis11n", Builtin::kUndefined},
{"teiiu22eF1d", Builtin::kUndefined},
{"tex77ur_1d", Builtin::kUndefined},
{"te2urNN_1d", Builtin::kUndefined},
{"texturVV_2d", Builtin::kUndefined},
{"WWFxtu11e_wd", Builtin::kUndefined},
{"txture_2ww", Builtin::kUndefined},
{"texture_2d_arrDy", Builtin::kUndefined},
{"teKtre_2d_array", Builtin::kUndefined},
{"texhure_2fra11raPP", Builtin::kUndefined},
{"texture3d", Builtin::kUndefined},
{"texture_3YY", Builtin::kUndefined},
{"HHtxtrkk_3d", Builtin::kUndefined},
{"texrrure_cube", Builtin::kUndefined},
{"tssxturWW_cue", Builtin::kUndefined},
{"teYure_cube", Builtin::kUndefined},
{"txture_Lufe_arraq", Builtin::kUndefined},
{"te22ture_uuubevvfray", Builtin::kUndefined},
{"texturecube_aray", Builtin::kUndefined},
{"texture_Yepth_2", Builtin::kUndefined},
{"teytYYEe_77epth_2d", Builtin::kUndefined},
{"teMture_deootd2d", Builtin::kUndefined},
{"texMMre_depth_2d_array", Builtin::kUndefined},
{"texture_depth_2d_arra55", Builtin::kUndefined},
{"texture_deh_2d_aNray", Builtin::kUndefined},
{"te3ture_dpth_cO3be", Builtin::kUndefined},
{"texture_depth_cub3", Builtin::kUndefined},
{"Iexturedepth_cume", Builtin::kUndefined},
{"texture_depthnncube_Krrry", Builtin::kUndefined},
{"texture_dth_XXube_rra", Builtin::kUndefined},
{"textIre_depph_ubeLLarray", Builtin::kUndefined},
{"txtfre_depthmultisampled_2d", Builtin::kUndefined},
{"texURuYe_Depthmultisampled_2d", Builtin::kUndefined},
{"texture_depth_multisamphed_2d", Builtin::kUndefined},
{"teqtureuIIextnal", Builtin::kUndefined},
{"texture_externaH", Builtin::kUndefined},
{"texre_externaQvv", Builtin::kUndefined},
{"textureemultismp66ed_d", Builtin::kUndefined},
{"tW7trO_multisampled_2d", Builtin::kUndefined},
{"texture_mult550ampled_2DD", Builtin::kUndefined},
{"teHture_storIIge_1d", Builtin::kUndefined},
{"textue_storage_1d", Builtin::kUndefined},
{"rexture_storae_1d", Builtin::kUndefined},
{"texture_stolage_2d", Builtin::kUndefined},
{"txture_JJtGrgtt_2d", Builtin::kUndefined},
{"yexture_storage2d", Builtin::kUndefined},
{"texture_storage_2d_rray", Builtin::kUndefined},
{"texture_IItorage_2d_BBrray", Builtin::kUndefined},
{"33exture_TTtorge_Kd_ar88ay", Builtin::kUndefined},
{"texSnnYUUure_storage_3d", Builtin::kUndefined},
{"textuxe_5torCCdZ_3d", Builtin::kUndefined},
{"tkkxture_storaqe_3d", Builtin::kUndefined},
{"5i00", Builtin::kUndefined},
{"unII2", Builtin::kUndefined},
{"cc", Builtin::kUndefined},
{"KK", Builtin::kUndefined},
{"66ec2", Builtin::kUndefined},
{"PPEK", Builtin::kUndefined},
{"vexxf", Builtin::kUndefined},
{"qec2f", Builtin::kUndefined},
{"veSyMMr", Builtin::kUndefined},
{"v2u", Builtin::kUndefined},
{"ec", Builtin::kUndefined},
{"5eFF2u", Builtin::kUndefined},
{"5eFF2h", Builtin::kUndefined},
{"rrecz44", Builtin::kUndefined},
{"vWW", Builtin::kUndefined},
{"ZJJCcX", Builtin::kUndefined},
{"vcPP", Builtin::kUndefined},
{"vec", Builtin::kUndefined},
{"3Le003f", Builtin::kUndefined},
{"MMec3RR", Builtin::kUndefined},
{"vec39K", Builtin::kUndefined},
{"yyecm", Builtin::kUndefined},
{"v__cD", Builtin::kUndefined},
{"vec3U", Builtin::kUndefined},
{"ze333i", Builtin::kUndefined},
{"eKti", Builtin::kUndefined},
{"ve3V", Builtin::kUndefined},
{"jbR3K", Builtin::kUndefined},
{"e44344", Builtin::kUndefined},
{"00u", Builtin::kUndefined},
{"WK4", Builtin::kUndefined},
{"m", Builtin::kUndefined},
{"vJJ", Builtin::kUndefined},
{"lDDcUfC", Builtin::kUndefined},
{"vec4g", Builtin::kUndefined},
{"CCe", Builtin::kUndefined},
{"ec4h", Builtin::kUndefined},
{"vIc__h", Builtin::kUndefined},
{"XJecCZZ", Builtin::kUndefined},
{"vePP2", Builtin::kUndefined},
{"vec2c", Builtin::kUndefined},
{"ve6ll2u", Builtin::kUndefined},
{"vey99", Builtin::kUndefined},
{"vKKc3", Builtin::kUndefined},
{"x_3", Builtin::kUndefined},
{"Ky3", Builtin::kUndefined},
{"zek3f", Builtin::kUndefined},
{"veKSf", Builtin::kUndefined},
{"vc3h", Builtin::kUndefined},
{"ec3VV", Builtin::kUndefined},
{"IAAc3h", Builtin::kUndefined},
{"jbR", Builtin::kUndefined},
{"veY4", Builtin::kUndefined},
{"ec3i", Builtin::kUndefined},
{"vc911", Builtin::kUndefined},
{"mmccu", Builtin::kUndefined},
{"vJJcu", Builtin::kUndefined},
{"lDCfcU", Builtin::kUndefined},
{"veg4", Builtin::kUndefined},
{"CC", Builtin::kUndefined},
{"ec4f", Builtin::kUndefined},
{"vIc__f", Builtin::kUndefined},
{"ePPtt", Builtin::kUndefined},
{"v3dc4i", Builtin::kUndefined},
{"vcyyi", Builtin::kUndefined},
{"v3dc4h", Builtin::kUndefined},
{"vcyyh", Builtin::kUndefined},
{"u4", Builtin::kUndefined},
{"v03nnu", Builtin::kUndefined},
{"v03nni", Builtin::kUndefined},
{"Cuuecnv", Builtin::kUndefined},
{"vX4ll", Builtin::kUndefined},
{"vocppu", Builtin::kUndefined},
{"vwwc4", Builtin::kUndefined},
{"veuug", Builtin::kUndefined},
};
using BuiltinParseTest = testing::TestWithParam<Case>;

View File

@@ -211,6 +211,9 @@ enum builtin_type {
texture_storage_3d
// https://www.w3.org/TR/WGSL/#external-texture-type
texture_external
// Internal types.
__packed_vec3
}
// https://gpuweb.github.io/gpuweb/wgsl/#attributes
@@ -289,6 +292,7 @@ type texture_storage_2d<F: texel_format, A: access>
type texture_storage_2d_array<F: texel_format, A: access>
type texture_storage_3d<F: texel_format, A: access>
type texture_external
type packedVec3<T>
@display("__modf_result_{T}") type __modf_result<T>
@display("__modf_result_vec{N}_{T}") type __modf_result_vec<N: num, T>
@@ -1001,6 +1005,9 @@ ctor mat4x4<T: fa_f32_f16>(T, T, T, T,
@must_use @const conv mat4x4<T: f16>(mat4x4<f32>) -> mat4x4<f16>
@must_use @const conv mat4x4<T: f32>(mat4x4<f16>) -> mat4x4<f32>
// Conversion from vec3 to internal __packed_vec3 type.
@must_use @const conv packedVec3<T: concrete_scalar>(vec3<T>) -> packedVec3<T>
////////////////////////////////////////////////////////////////////////////////
// Operators //
// //

View File

@@ -62,6 +62,8 @@ const char* str(CtorConvIntrinsic i) {
return "mat4x3";
case CtorConvIntrinsic::kMat4x4:
return "mat4x4";
case CtorConvIntrinsic::kPackedVec3:
return "packedVec3";
}
return "<unknown>";
}

View File

@@ -48,6 +48,7 @@ enum class CtorConvIntrinsic {
kMat4x2,
kMat4x3,
kMat4x4,
kPackedVec3,
};
/// @returns the name of the type.

View File

@@ -456,6 +456,25 @@ constexpr auto build_vec2 = build_vec<2>;
constexpr auto build_vec3 = build_vec<3>;
constexpr auto build_vec4 = build_vec<4>;
bool match_packedVec3(MatchState&, const type::Type* ty, const type::Type*& T) {
if (ty->Is<Any>()) {
T = ty;
return true;
}
if (auto* v = ty->As<type::Vector>()) {
if (v->Packed()) {
T = v->type();
return true;
}
}
return false;
}
const type::Vector* build_packedVec3(MatchState& state, const type::Type* el) {
return state.builder.create<type::Vector>(el, 3u, /* packed */ true);
}
bool match_mat(MatchState&, const type::Type* ty, Number& M, Number& N, const type::Type*& T) {
if (ty->Is<Any>()) {
M = Number::any;

File diff suppressed because it is too large Load Diff

View File

@@ -2045,6 +2045,10 @@ sem::Call* Resolver::Call(const ast::CallExpression* expr) {
[&](const type::F32*) { return ctor_or_conv(CtorConvIntrinsic::kF32, nullptr); },
[&](const type::Bool*) { return ctor_or_conv(CtorConvIntrinsic::kBool, nullptr); },
[&](const type::Vector* v) {
if (v->Packed()) {
TINT_ASSERT(Resolver, v->Width() == 3u);
return ctor_or_conv(CtorConvIntrinsic::kPackedVec3, v->type());
}
return ctor_or_conv(VectorCtorConvIntrinsic(v->Width()), v->type());
},
[&](const type::Matrix* m) {
@@ -2574,6 +2578,24 @@ type::Type* Resolver::BuiltinType(builtin::Builtin builtin_ty, const ast::Identi
}
return tex;
};
auto packed_vec3_t = [&]() -> type::Vector* {
auto* tmpl_ident = templated_identifier(1);
if (TINT_UNLIKELY(!tmpl_ident)) {
return nullptr;
}
auto* el_ty = Type(tmpl_ident->arguments[0]);
if (TINT_UNLIKELY(!el_ty)) {
return nullptr;
}
if (TINT_UNLIKELY(!el_ty)) {
return nullptr;
}
if (TINT_UNLIKELY(!validator_.Vector(el_ty, ident->source))) {
return nullptr;
}
return b.create<type::Vector>(el_ty, 3u, true);
};
switch (builtin_ty) {
case builtin::Builtin::kBool:
@@ -2720,6 +2742,9 @@ type::Type* Resolver::BuiltinType(builtin::Builtin builtin_ty, const ast::Identi
return storage_texture(type::TextureDimension::k2dArray);
case builtin::Builtin::kTextureStorage3D:
return storage_texture(type::TextureDimension::k3d);
case builtin::Builtin::kPackedVec3: {
return packed_vec3_t();
}
case builtin::Builtin::kUndefined:
break;
}

View File

@@ -18,16 +18,23 @@
#include <string>
#include <utility>
#include "src/tint/ast/assignment_statement.h"
#include "src/tint/builtin/builtin.h"
#include "src/tint/program_builder.h"
#include "src/tint/sem/array_count.h"
#include "src/tint/sem/index_accessor_expression.h"
#include "src/tint/sem/member_accessor_expression.h"
#include "src/tint/sem/load.h"
#include "src/tint/sem/statement.h"
#include "src/tint/sem/type_expression.h"
#include "src/tint/sem/variable.h"
#include "src/tint/type/array.h"
#include "src/tint/type/reference.h"
#include "src/tint/type/vector.h"
#include "src/tint/utils/hashmap.h"
#include "src/tint/utils/hashset.h"
#include "src/tint/utils/vector.h"
TINT_INSTANTIATE_TYPEINFO(tint::transform::PackedVec3);
TINT_INSTANTIATE_TYPEINFO(tint::transform::PackedVec3::Attribute);
using namespace tint::number_suffixes; // NOLINT
@@ -39,105 +46,447 @@ struct PackedVec3::State {
/// @param program the source program
explicit State(const Program* program) : src(program) {}
/// The name of the struct member used when wrapping packed vec3 types.
static constexpr const char* kStructMemberName = "elements";
/// The names of the structures used to wrap packed vec3 types.
utils::Hashmap<const type::Type*, Symbol, 4> packed_vec3_wrapper_struct_names;
/// A cache of host-shareable structures that have been rewritten.
utils::Hashmap<const type::Type*, Symbol, 4> rewritten_structs;
/// A map from type to the name of a helper function used to pack that type.
utils::Hashmap<const type::Type*, Symbol, 4> pack_helpers;
/// A map from type to the name of a helper function used to unpack that type.
utils::Hashmap<const type::Type*, Symbol, 4> unpack_helpers;
/// @param ty the type to test
/// @returns true if `ty` is a vec3, false otherwise
bool IsVec3(const type::Type* ty) {
if (auto* vec = ty->As<type::Vector>()) {
if (vec->Width() == 3) {
return true;
}
}
return false;
}
/// @param ty the type to test
/// @returns true if `ty` is or contains a vec3, false otherwise
bool ContainsVec3(const type::Type* ty) {
return Switch(
ty, //
[&](const type::Vector* vec) { return IsVec3(vec); },
[&](const type::Matrix* mat) { return ContainsVec3(mat->ColumnType()); },
[&](const type::Array* arr) { return ContainsVec3(arr->ElemType()); },
[&](const type::Struct* str) {
for (auto* member : str->Members()) {
if (ContainsVec3(member->Type())) {
return true;
}
}
return false;
});
}
/// Create a `__packed_vec3` type with the same element type as `ty`.
/// @param ty a three-element vector type
/// @returns the new AST type
ast::Type MakePackedVec3(const type::Type* ty) {
auto* vec = ty->As<type::Vector>();
TINT_ASSERT(Transform, vec != nullptr && vec->Width() == 3);
return b.ty(builtin::Builtin::kPackedVec3, CreateASTTypeFor(ctx, vec->type()));
}
/// Recursively rewrite a type using `__packed_vec3`, if needed.
/// When used as an array element type, the `__packed_vec3` type will be wrapped in a structure
/// and given an `@align()` attribute to give it alignment it needs to yield the correct array
/// element stride. For vec3 types used in structures directly, the `@align()` attribute is
/// placed on the containing structure instead. Matrices with three rows become arrays of
/// columns, and used the aligned wrapper struct for the column type.
/// @param ty the type to rewrite
/// @param array_element `true` if this is being called for the element of an array
/// @returns the new AST type, or nullptr if rewriting was not necessary
ast::Type RewriteType(const type::Type* ty, bool array_element = false) {
return Switch(
ty,
[&](const type::Vector* vec) -> ast::Type {
if (IsVec3(vec)) {
if (array_element) {
// Create a struct with a single `__packed_vec3` member.
// Give the struct member the same alignment as the original unpacked vec3
// type, to avoid changing the array element stride.
return b.ty(packed_vec3_wrapper_struct_names.GetOrCreate(vec, [&]() {
auto name = b.Symbols().New(
"tint_packed_vec3_" + vec->type()->FriendlyName(src->Symbols()) +
(array_element ? "_array_element" : "_struct_member"));
auto* member =
b.Member(kStructMemberName, MakePackedVec3(vec),
utils::Vector{b.MemberAlign(AInt(vec->Align()))});
b.Structure(b.Ident(name), utils::Vector{member}, utils::Empty);
return name;
}));
} else {
return MakePackedVec3(vec);
}
}
return {};
},
[&](const type::Matrix* mat) -> ast::Type {
// Rewrite the matrix as an array of columns that use the aligned wrapper struct.
auto new_col_type = RewriteType(mat->ColumnType(), /* array_element */ true);
if (new_col_type) {
return b.ty.array(new_col_type, u32(mat->columns()));
}
return {};
},
[&](const type::Array* arr) -> ast::Type {
// Rewrite the array with the modified element type.
auto new_type = RewriteType(arr->ElemType(), /* array_element */ true);
if (new_type) {
utils::Vector<const ast::Attribute*, 1> attrs;
if (arr->Count()->Is<type::RuntimeArrayCount>()) {
return b.ty.array(new_type, std::move(attrs));
} else if (auto count = arr->ConstantCount()) {
return b.ty.array(new_type, u32(count.value()), std::move(attrs));
} else {
TINT_ICE(Transform, b.Diagnostics())
<< type::Array::kErrExpectedConstantCount;
return {};
}
}
return {};
},
[&](const sem::Struct* str) -> ast::Type {
if (ContainsVec3(str)) {
auto name = rewritten_structs.GetOrCreate(str, [&]() {
utils::Vector<const ast::StructMember*, 4> members;
for (auto* member : str->Members()) {
// If the member type contains a vec3, rewrite it.
auto new_type = RewriteType(member->Type());
if (new_type) {
// Copy the member attributes.
bool needs_align = true;
utils::Vector<const ast::Attribute*, 4> attributes;
for (auto* attr : member->Declaration()->attributes) {
if (attr->IsAnyOf<ast::StructMemberAlignAttribute,
ast::StructMemberOffsetAttribute>()) {
needs_align = false;
}
attributes.Push(ctx.Clone(attr));
}
// If the alignment wasn't already specified, add an attribute to
// make sure that we don't alter the alignment when using the packed
// vector type.
if (needs_align) {
attributes.Push(b.MemberAlign(AInt(member->Align())));
}
members.Push(b.Member(ctx.Clone(member->Name()), new_type,
std::move(attributes)));
} else {
// No vec3s, just clone the member as is.
members.Push(ctx.Clone(member->Declaration()));
}
}
// Create the new structure.
auto struct_name = b.Symbols().New(
src->Symbols().NameFor(str->Declaration()->name->symbol) +
"_tint_packed_vec3");
b.Structure(struct_name, std::move(members));
return struct_name;
});
return b.ty(name);
}
return {};
});
}
/// Create a helper function to recursively pack or unpack a composite that contains vec3 types.
/// @param name_prefix the name of the helper function
/// @param ty the composite type to pack or unpack
/// @param pack_or_unpack_element a function that packs or unpacks an element with a given type
/// @param in_type a function that create an AST type for the input type
/// @param out_type a function that create an AST type for the output type
/// @returns the name of the helper function
Symbol MakePackUnpackHelper(
const char* name_prefix,
const type::Type* ty,
const std::function<const ast::Expression*(const ast::Expression*, const type::Type*)>&
pack_or_unpack_element,
const std::function<ast::Type()>& in_type,
const std::function<ast::Type()>& out_type) {
// Allocate a variable to hold the return value of the function.
utils::Vector<const ast::Statement*, 4> statements;
statements.Push(b.Decl(b.Var("result", out_type())));
// Helper that generates a loop to copy and pack/unpack elements of an array to the result:
// for (var i = 0u; i < num_elements; i = i + 1) {
// result[i] = pack_or_unpack_element(in[i]);
// }
auto copy_array_elements = [&](uint32_t num_elements, const type::Type* element_type) {
// Generate an expression for packing or unpacking an element of the array.
auto* element = pack_or_unpack_element(b.IndexAccessor("in", "i"), element_type);
statements.Push(b.For( //
b.Decl(b.Var("i", b.ty.u32())), //
b.LessThan("i", u32(num_elements)), //
b.Assign("i", b.Add("i", 1_a)), //
b.Block(utils::Vector{
b.Assign(b.IndexAccessor("result", "i"), element),
})));
};
// Copy the elements of the value over to the result.
Switch(
ty,
[&](const type::Array* arr) {
TINT_ASSERT(Transform, arr->ConstantCount());
copy_array_elements(arr->ConstantCount().value(), arr->ElemType());
},
[&](const type::Matrix* mat) {
copy_array_elements(mat->columns(), mat->ColumnType());
},
[&](const sem::Struct* str) {
// Copy the struct members over one at a time, packing/unpacking as necessary.
for (auto* member : str->Members()) {
const ast::Expression* element =
b.MemberAccessor("in", b.Ident(ctx.Clone(member->Name())));
if (ContainsVec3(member->Type())) {
element = pack_or_unpack_element(element, member->Type());
}
statements.Push(b.Assign(
b.MemberAccessor("result", b.Ident(ctx.Clone(member->Name()))), element));
}
});
// Return the result.
statements.Push(b.Return("result"));
// Create the function and return its name.
auto name = b.Symbols().New(name_prefix);
b.Func(name, utils::Vector{b.Param("in", in_type())}, out_type(), std::move(statements));
return name;
}
/// Unpack the composite value `expr` to the unpacked type `ty`. If `ty` is a matrix, this will
/// produce a regular matNx3 value from an array of packed column vectors.
/// @param expr the composite value expression to unpack
/// @param ty the unpacked type
/// @returns an expression that holds the unpacked value
const ast::Expression* UnpackComposite(const ast::Expression* expr, const type::Type* ty) {
auto helper = unpack_helpers.GetOrCreate(ty, [&]() {
return MakePackUnpackHelper(
"tint_unpack_vec3_in_composite", ty,
[&](const ast::Expression* element,
const type::Type* element_type) -> const ast::Expression* {
if (element_type->Is<type::Vector>()) {
// Unpack a `__packed_vec3` by casting it to a regular vec3.
// If it is an array element, extract the vector from the wrapper struct.
if (element->Is<ast::IndexAccessorExpression>()) {
element = b.MemberAccessor(element, kStructMemberName);
}
return b.Call(CreateASTTypeFor(ctx, element_type), element);
} else {
return UnpackComposite(element, element_type);
}
},
[&]() { return RewriteType(ty); }, //
[&]() { return CreateASTTypeFor(ctx, ty); });
});
return b.Call(helper, expr);
}
/// Pack the composite value `expr` from the unpacked type `ty`. If `ty` is a matrix, this will
/// produce an array of packed column vectors.
/// @param expr the composite value expression to pack
/// @param ty the unpacked type
/// @returns an expression that holds the packed value
const ast::Expression* PackComposite(const ast::Expression* expr, const type::Type* ty) {
auto helper = pack_helpers.GetOrCreate(ty, [&]() {
return MakePackUnpackHelper(
"tint_pack_vec3_in_composite", ty,
[&](const ast::Expression* element,
const type::Type* element_type) -> const ast::Expression* {
if (element_type->Is<type::Vector>()) {
// Pack a vector element by casting it to a packed_vec3.
// If it is an array element, construct a wrapper struct.
auto* packed = b.Call(MakePackedVec3(element_type), element);
if (element->Is<ast::IndexAccessorExpression>()) {
packed = b.Call(RewriteType(element_type, true), packed);
}
return packed;
} else {
return PackComposite(element, element_type);
}
},
[&]() { return CreateASTTypeFor(ctx, ty); }, //
[&]() { return RewriteType(ty); });
});
return b.Call(helper, expr);
}
/// @returns true if there are host-shareable vec3's that need transforming
bool ShouldRun() {
// Check for vec3s in the types of all uniform and storage buffer variables to determine
// if the transform is necessary.
for (auto* decl : src->AST().GlobalVariables()) {
auto* var = sem.Get<sem::GlobalVariable>(decl);
if (var && builtin::IsHostShareable(var->AddressSpace()) &&
ContainsVec3(var->Type()->UnwrapRef())) {
return true;
}
}
return false;
}
/// Runs the transform
/// @returns the new program or SkipTransform if the transform is not required
ApplyResult Run() {
// Packed vec3<T> struct members
utils::Hashset<const sem::StructMember*, 8> members;
// Find all the packed vector struct members, and apply the @internal(packed_vector)
// attribute.
for (auto* decl : ctx.src->AST().GlobalDeclarations()) {
if (auto* str = sem.Get<sem::Struct>(decl)) {
if (str->IsHostShareable()) {
for (auto* member : str->Members()) {
if (auto* vec = member->Type()->As<type::Vector>()) {
if (vec->Width() == 3) {
members.Add(member);
// Apply the PackedVec3::Attribute to the member
ctx.InsertFront(
member->Declaration()->attributes,
b.ASTNodes().Create<Attribute>(b.ID(), b.AllocateNodeID()));
}
}
}
}
}
}
if (members.IsEmpty()) {
if (!ShouldRun()) {
return SkipTransform;
}
// Walk the nodes, starting with the most deeply nested, finding all the AST expressions
// that load a whole packed vector (not a scalar / swizzle of the vector).
utils::Hashset<const sem::ValueExpression*, 16> refs;
// Changing the types of certain structure members can trigger stricter layout validation
// rules for the uniform address space. In particular, replacing 16-bit matrices with arrays
// violates the requirement that the array element stride is a multiple of 16 bytes, and
// replacing vec3s with a structure violates the requirement that there must be at least 16
// bytes from the start of a structure to the start of the next member.
// Disable these validation rules using an internal extension, as MSL does not have these
// restrictions.
b.Enable(builtin::Extension::kChromiumInternalRelaxedUniformLayout);
// Track expressions that need to be packed or unpacked.
utils::Hashset<const sem::ValueExpression*, 8> to_pack;
utils::Hashset<const sem::ValueExpression*, 8> to_unpack;
// Replace vec3 types in host-shareable address spaces with `__packed_vec3` types, and
// collect expressions that need to be converted to or from values that use the
// `__packed_vec3` type.
for (auto* node : ctx.src->ASTNodes().Objects()) {
auto* sem_node = sem.Get(node);
if (sem_node) {
if (auto* expr = sem_node->As<sem::ValueExpression>()) {
sem_node = expr->UnwrapLoad();
}
}
Switch(
sem_node, //
[&](const sem::StructMemberAccess* access) {
if (members.Contains(access->Member())) {
// Access to a packed vector member. Seed the expression tracking.
refs.Add(access);
}
},
[&](const sem::IndexAccessorExpression* access) {
// Not loading a whole packed vector. Ignore.
refs.Remove(access->Object()->UnwrapLoad());
},
[&](const sem::Swizzle* access) {
// Not loading a whole packed vector. Ignore.
refs.Remove(access->Object()->UnwrapLoad());
},
[&](const sem::VariableUser* user) {
auto* v = user->Variable();
if (v->Declaration()->Is<ast::Let>() && // if variable is let...
v->Type()->Is<type::Pointer>() && // and let is a pointer...
refs.Contains(v->Initializer())) { // and pointer is to a packed vector...
refs.Add(user); // then propagate tracking to pointer usage
}
},
[&](const sem::ValueExpression* expr) {
if (auto* unary = expr->Declaration()->As<ast::UnaryOpExpression>()) {
if (unary->op == ast::UnaryOp::kAddressOf ||
unary->op == ast::UnaryOp::kIndirection) {
// Memory access on the packed vector. Track these.
auto* inner = sem.GetVal(unary->expr);
if (refs.Remove(inner)) {
refs.Add(expr);
}
sem.Get(node),
[&](const sem::TypeExpression* type) {
// Rewrite pointers to types that contain vec3s.
auto* ptr = type->Type()->As<type::Pointer>();
if (ptr && builtin::IsHostShareable(ptr->AddressSpace())) {
auto new_store_type = RewriteType(ptr->StoreType());
if (new_store_type) {
auto access = ptr->AddressSpace() == builtin::AddressSpace::kStorage
? ptr->Access()
: builtin::Access::kUndefined;
auto new_ptr_type =
b.ty.pointer(new_store_type, ptr->AddressSpace(), access);
ctx.Replace(node, new_ptr_type.expr);
}
// Note: non-memory ops (e.g. '-') are ignored, leaving any tracked
// reference at the inner expression, so we'd cast, then apply the unary op.
}
},
[&](const sem::Statement* e) {
if (auto* assign = e->Declaration()->As<ast::AssignmentStatement>()) {
// We don't want to cast packed_vectors if they're being assigned to.
refs.Remove(sem.GetVal(assign->lhs));
[&](const sem::Variable* var) {
if (!builtin::IsHostShareable(var->AddressSpace())) {
return;
}
// Rewrite the var type, if it contains vec3s.
auto new_store_type = RewriteType(var->Type()->UnwrapRef());
if (new_store_type) {
ctx.Replace(var->Declaration()->type.expr, new_store_type.expr);
}
},
[&](const sem::Statement* stmt) {
// Pack the RHS of assignment statements that are writing to packed types.
if (auto* assign = stmt->Declaration()->As<ast::AssignmentStatement>()) {
auto* lhs = sem.GetVal(assign->lhs);
auto* rhs = sem.GetVal(assign->rhs);
if (!ContainsVec3(rhs->Type()) ||
!builtin::IsHostShareable(
lhs->Type()->As<type::Reference>()->AddressSpace())) {
// Skip assignments to address spaces that are not host-shareable, or
// that do not contain vec3 types.
return;
}
// Pack the RHS expression.
if (to_unpack.Contains(rhs)) {
// The expression will already be packed, so skip the pending unpack.
to_unpack.Remove(rhs);
// If the expression produces a vec3 from an array element, extract
// the packed vector from the wrapper struct.
if (IsVec3(rhs->Type()) &&
rhs->UnwrapLoad()->Is<sem::IndexAccessorExpression>()) {
ctx.Replace(rhs->Declaration(),
b.MemberAccessor(ctx.Clone(rhs->Declaration()),
kStructMemberName));
}
} else if (rhs) {
to_pack.Add(rhs);
}
}
},
[&](const sem::Load* load) {
// Unpack loads of types that contain vec3s in host-shareable address spaces.
if (ContainsVec3(load->Type()) &&
builtin::IsHostShareable(load->ReferenceType()->AddressSpace())) {
to_unpack.Add(load);
}
},
[&](const sem::IndexAccessorExpression* accessor) {
// If the expression produces a reference to a vec3 in a host-shareable address
// space from an array element, extract the packed vector from the wrapper
// struct.
if (auto* ref = accessor->Type()->As<type::Reference>()) {
if (IsVec3(ref->StoreType()) &&
builtin::IsHostShareable(ref->AddressSpace())) {
ctx.Replace(node, b.MemberAccessor(ctx.Clone(accessor->Declaration()),
kStructMemberName));
}
}
});
}
// Wrap the load expressions with a cast to the unpacked type.
utils::Hashmap<const type::Vector*, Symbol, 3> unpack_fns;
for (auto* ref : refs) {
// ref is either a packed vec3 that needs casting, or a pointer to a vec3 which we just
// leave alone.
if (auto* vec_ty = ref->Type()->UnwrapRef()->As<type::Vector>()) {
auto* expr = ref->Declaration();
ctx.Replace(expr, [this, vec_ty, expr] { //
auto* packed = ctx.CloneWithoutTransform(expr);
return b.Call(CreateASTTypeFor(ctx, vec_ty), packed);
});
// Sort the pending pack/unpack operations by AST node ID to make the order deterministic.
auto to_unpack_sorted = to_unpack.Vector();
auto to_pack_sorted = to_pack.Vector();
auto pred = [&](auto* expr_a, auto* expr_b) {
return expr_a->Declaration()->node_id < expr_b->Declaration()->node_id;
};
to_unpack_sorted.Sort(pred);
to_pack_sorted.Sort(pred);
// Apply all of the pending unpack operations that we have collected.
for (auto* expr : to_unpack_sorted) {
TINT_ASSERT(Transform, ContainsVec3(expr->Type()));
auto* packed = ctx.Clone(expr->Declaration());
const ast::Expression* unpacked = nullptr;
if (IsVec3(expr->Type())) {
if (expr->UnwrapLoad()->Is<sem::IndexAccessorExpression>()) {
// If we are unpacking a vec3 from an array element, extract the vector from the
// wrapper struct.
packed = b.MemberAccessor(packed, kStructMemberName);
}
// Cast the packed vector to a regular vec3.
unpacked = b.Call(CreateASTTypeFor(ctx, expr->Type()), packed);
} else {
// Use a helper function to unpack an array or matrix.
unpacked = UnpackComposite(packed, expr->Type());
}
TINT_ASSERT(Transform, unpacked != nullptr);
ctx.Replace(expr->Declaration(), unpacked);
}
// Apply all of the pending pack operations that we have collected.
for (auto* expr : to_pack_sorted) {
TINT_ASSERT(Transform, ContainsVec3(expr->Type()));
auto* unpacked = ctx.Clone(expr->Declaration());
const ast::Expression* packed = nullptr;
if (IsVec3(expr->Type())) {
// Cast the regular vec3 to a packed vector type.
packed = b.Call(MakePackedVec3(expr->Type()), unpacked);
} else {
// Use a helper function to pack an array or matrix.
packed = PackComposite(unpacked, expr->Type());
}
TINT_ASSERT(Transform, packed != nullptr);
ctx.Replace(expr->Declaration(), packed);
}
ctx.Clone();
@@ -153,21 +502,8 @@ struct PackedVec3::State {
CloneContext ctx = {&b, src, /* auto_clone_symbols */ true};
/// Alias to the semantic info in ctx.src
const sem::Info& sem = ctx.src->Sem();
/// Alias to the symbols in ctx.src
const SymbolTable& sym = ctx.src->Symbols();
};
PackedVec3::Attribute::Attribute(ProgramID pid, ast::NodeID nid) : Base(pid, nid) {}
PackedVec3::Attribute::~Attribute() = default;
const PackedVec3::Attribute* PackedVec3::Attribute::Clone(CloneContext* ctx) const {
return ctx->dst->ASTNodes().Create<Attribute>(ctx->dst->ID(), ctx->dst->AllocateNodeID());
}
std::string PackedVec3::Attribute::InternalName() const {
return "packed_vector";
}
PackedVec3::PackedVec3() = default;
PackedVec3::~PackedVec3() = default;

View File

@@ -15,42 +15,31 @@
#ifndef SRC_TINT_TRANSFORM_PACKED_VEC3_H_
#define SRC_TINT_TRANSFORM_PACKED_VEC3_H_
#include <string>
#include "src/tint/ast/internal_attribute.h"
#include "src/tint/transform/transform.h"
namespace tint::transform {
/// A transform to be used by the MSL backend which will:
/// * Apply the `@internal('packed_vector')` attribute (PackedVec3::Attribute) to all host-sharable
/// structure members that have a vec3<T> type.
/// * Replace `vec3<T>` types with an internal `__packed_vec3` type when they are used in
/// host-shareable address spaces.
/// * Wrap generated `__packed_vec3` types in a structure when they are used in arrays, so that we
/// ensure that the array has the correct element stride.
/// * Multi-version structures that contain `vec3<T>` types when they are used in host-shareable
/// memory, to avoid modifying uses in other address spaces.
/// * Rewrite matrix types that have three rows into arrays of column vectors.
/// * Insert calls to helper functions to convert expressions that use these types to or from the
/// regular vec3 types when accessing host-shareable memory.
/// * Cast all direct (not sub-accessed) loads of these packed vectors to the 'unpacked' vec3<T>
/// type before usage.
///
/// This transform papers over overload holes in the MSL standard library where an MSL
/// `packed_vector` type cannot be interchangable used as a regular `vec` type.
/// This transform is necessary in order to emit vec3 types with the correct size (so that scalars
/// can follow them in structures), and also to ensure that padding bytes are preserved when writing
/// to a vec3, an array of vec3 elements, or a matrix with vec3 column type.
///
/// @note Depends on the following transforms to have been run first:
/// * ExpandCompoundAssignment
class PackedVec3 final : public Castable<PackedVec3, Transform> {
public:
/// Attribute is the attribute applied to padded vector structure members.
class Attribute final : public Castable<Attribute, ast::InternalAttribute> {
public:
/// Constructor
/// @param pid the identifier of the program that owns this node
/// @param nid the unique node identifier
Attribute(ProgramID pid, ast::NodeID nid);
/// Destructor
~Attribute() override;
/// @returns "packed_vector".
std::string InternalName() const override;
/// Performs a deep clone of this object using the CloneContext `ctx`.
/// @param ctx the clone context
/// @return the newly cloned object
const Attribute* Clone(CloneContext* ctx) const override;
};
/// Constructor
PackedVec3();
/// Destructor

File diff suppressed because it is too large Load Diff

View File

@@ -1714,7 +1714,7 @@ std::vector<const char*> ConstructableTypes() {
for (auto* ty : builtin::kBuiltinStrings) {
std::string_view type(ty);
if (type != "ptr" && type != "atomic" && !utils::HasPrefix(type, "sampler") &&
!utils::HasPrefix(type, "texture")) {
!utils::HasPrefix(type, "texture") && !utils::HasPrefix(type, "__")) {
out.push_back(ty);
}
}
@@ -1924,7 +1924,9 @@ INSTANTIATE_TEST_SUITE_P(RenamerBuiltinTypeTest,
std::vector<const char*> Identifiers() {
std::vector<const char*> out;
for (auto* ident : builtin::kBuiltinStrings) {
out.push_back(ident);
if (!utils::HasPrefix(ident, "__")) {
out.push_back(ident);
}
}
for (auto* ident : builtin::kAddressSpaceStrings) {
if (!utils::HasPrefix(ident, "_")) {

View File

@@ -17,6 +17,7 @@
#include <algorithm>
#include <string>
#include "src/tint/builtin/builtin.h"
#include "src/tint/program_builder.h"
#include "src/tint/sem/block_statement.h"
#include "src/tint/sem/for_loop_statement.h"
@@ -98,7 +99,12 @@ ast::Type Transform::CreateASTTypeFor(CloneContext& ctx, const type::Type* ty) {
}
if (auto* v = ty->As<type::Vector>()) {
auto el = CreateASTTypeFor(ctx, v->type());
return ctx.dst->ty.vec(el, v->Width());
if (v->Packed()) {
TINT_ASSERT(Transform, v->Width() == 3u);
return ctx.dst->ty(builtin::Builtin::kPackedVec3, el);
} else {
return ctx.dst->ty.vec(el, v->Width());
}
}
if (auto* a = ty->As<type::Array>()) {
auto el = CreateASTTypeFor(ctx, a->ElemType());

View File

@@ -23,15 +23,16 @@ TINT_INSTANTIATE_TYPEINFO(tint::type::Vector);
namespace tint::type {
Vector::Vector(Type const* subtype, uint32_t width)
: Base(utils::Hash(TypeInfo::Of<Vector>().full_hashcode, width, subtype),
Vector::Vector(Type const* subtype, uint32_t width, bool packed /* = false */)
: Base(utils::Hash(TypeInfo::Of<Vector>().full_hashcode, width, subtype, packed),
type::Flags{
Flag::kConstructable,
Flag::kCreationFixedFootprint,
Flag::kFixedFootprint,
}),
subtype_(subtype),
width_(width) {
width_(width),
packed_(packed) {
TINT_ASSERT(Type, width_ > 1);
TINT_ASSERT(Type, width_ < 5);
}
@@ -40,13 +41,16 @@ Vector::~Vector() = default;
bool Vector::Equals(const UniqueNode& other) const {
if (auto* v = other.As<Vector>()) {
return v->width_ == width_ && v->subtype_ == subtype_;
return v->width_ == width_ && v->subtype_ == subtype_ && v->packed_ == packed_;
}
return false;
}
std::string Vector::FriendlyName(const SymbolTable& symbols) const {
std::ostringstream out;
if (packed_) {
out << "__packed_";
}
out << "vec" << width_ << "<" << subtype_->FriendlyName(symbols) << ">";
return out.str();
}
@@ -60,7 +64,7 @@ uint32_t Vector::Align() const {
case 2:
return subtype_->Size() * 2;
case 3:
return subtype_->Size() * 4;
return subtype_->Size() * (packed_ ? 1 : 4);
case 4:
return subtype_->Size() * 4;
}
@@ -69,7 +73,7 @@ uint32_t Vector::Align() const {
Vector* Vector::Clone(CloneContext& ctx) const {
auto* subtype = subtype_->Clone(ctx);
return ctx.dst.mgr->Get<Vector>(subtype, width_);
return ctx.dst.mgr->Get<Vector>(subtype, width_, packed_);
}
} // namespace tint::type

View File

@@ -22,12 +22,13 @@
namespace tint::type {
/// A vector type.
class Vector final : public Castable<Vector, Type> {
class Vector : public Castable<Vector, Type> {
public:
/// Constructor
/// @param subtype the vector element type
/// @param size the number of elements in the vector
Vector(Type const* subtype, uint32_t size);
/// @param packed the optional 'packed' modifier
Vector(Type const* subtype, uint32_t size, bool packed = false);
/// Destructor
~Vector() override;
@@ -50,10 +51,12 @@ class Vector final : public Castable<Vector, Type> {
/// @returns the size in bytes of the type. This may include tail padding.
uint32_t Size() const override;
/// @returns the alignment in bytes of the type. This may include tail
/// padding.
/// @returns the alignment in bytes of the type. This may include tail padding.
uint32_t Align() const override;
/// @returns `true` if this vector is packed, false otherwise
bool Packed() const { return packed_; }
/// @param width the width of the vector
/// @returns the size in bytes of a vector of the given width.
static uint32_t SizeOf(uint32_t width);
@@ -69,6 +72,7 @@ class Vector final : public Castable<Vector, Type> {
private:
Type const* const subtype_;
const uint32_t width_;
const bool packed_;
};
} // namespace tint::type

View File

@@ -34,6 +34,21 @@ TEST_F(VectorTest, Creation) {
EXPECT_NE(a, d);
}
TEST_F(VectorTest, Creation_Packed) {
auto* v = create<Vector>(create<F32>(), 3u);
auto* p1 = create<Vector>(create<F32>(), 3u, true);
auto* p2 = create<Vector>(create<F32>(), 3u, true);
EXPECT_FALSE(v->Packed());
EXPECT_EQ(p1->type(), create<F32>());
EXPECT_EQ(p1->Width(), 3u);
EXPECT_TRUE(p1->Packed());
EXPECT_NE(v, p1);
EXPECT_EQ(p1, p2);
}
TEST_F(VectorTest, Hash) {
auto* a = create<Vector>(create<I32>(), 2u);
auto* b = create<Vector>(create<I32>(), 2u);
@@ -59,6 +74,12 @@ TEST_F(VectorTest, FriendlyName) {
EXPECT_EQ(v->FriendlyName(Symbols()), "vec3<f32>");
}
TEST_F(VectorTest, FriendlyName_Packed) {
auto* f32 = create<F32>();
auto* v = create<Vector>(f32, 3u, true);
EXPECT_EQ(v->FriendlyName(Symbols()), "__packed_vec3<f32>");
}
TEST_F(VectorTest, Clone) {
auto* a = create<Vector>(create<I32>(), 2u);
@@ -68,6 +89,19 @@ TEST_F(VectorTest, Clone) {
auto* vec = a->Clone(ctx);
EXPECT_TRUE(vec->type()->Is<I32>());
EXPECT_EQ(vec->Width(), 2u);
EXPECT_FALSE(vec->Packed());
}
TEST_F(VectorTest, Clone_Packed) {
auto* a = create<Vector>(create<I32>(), 3u, true);
type::Manager mgr;
type::CloneContext ctx{{nullptr}, {nullptr, &mgr}};
auto* vec = a->Clone(ctx);
EXPECT_TRUE(vec->type()->Is<I32>());
EXPECT_EQ(vec->Width(), 3u);
EXPECT_TRUE(vec->Packed());
}
} // namespace

View File

@@ -245,8 +245,9 @@ SanitizedResult Sanitize(const Program* in, const Options& options) {
// ArrayLengthFromUniform must come after SimplifyPointers, as
// it assumes that the form of the array length argument is &var.array.
manager.Add<transform::ArrayLengthFromUniform>();
manager.Add<transform::ModuleScopeVarToEntryPointParam>();
// PackedVec3 must come after ExpandCompoundAssignment.
manager.Add<transform::PackedVec3>();
manager.Add<transform::ModuleScopeVarToEntryPointParam>();
data.Add<transform::ArrayLengthFromUniform::Config>(std::move(array_length_from_uniform_cfg));
data.Add<transform::CanonicalizeEntryPointIO::Config>(std::move(entry_point_io_cfg));
auto out = manager.Run(in, data);
@@ -273,6 +274,7 @@ bool GeneratorImpl::Generate() {
builtin::Extension::kChromiumDisableUniformityAnalysis,
builtin::Extension::kChromiumExperimentalFullPtrParameters,
builtin::Extension::kChromiumExperimentalPushConstant,
builtin::Extension::kChromiumInternalRelaxedUniformLayout,
builtin::Extension::kF16,
})) {
return false;
@@ -2374,25 +2376,20 @@ bool GeneratorImpl::EmitMemberAccessor(std::ostream& out,
return Switch(
sem,
[&](const sem::Swizzle* swizzle) {
// Metal 1.x does not support swizzling of packed vector types.
// For single element swizzles, we can use the index operator.
// For multi-element swizzles, we need to cast to a regular vector type
// first. Note that we do not currently allow assignments to swizzles, so
// the casting which will convert the l-value to r-value is fine.
// Metal did not add support for swizzle syntax with packed vector types until
// Metal 2.1, so we need to use the index operator for single-element selection instead.
// For multi-component swizzles, the PackedVec3 transform will have inserted casts to
// the non-packed types, so we can safely use swizzle syntax here.
if (swizzle->Indices().Length() == 1) {
if (!write_lhs()) {
return false;
}
out << "[" << swizzle->Indices()[0] << "]";
} else {
if (!EmitType(out, swizzle->Object()->Type()->UnwrapRef(), "")) {
return false;
}
out << "(";
if (!write_lhs()) {
return false;
}
out << ")." << program_->Symbols().NameFor(expr->member->symbol);
out << "." << program_->Symbols().NameFor(expr->member->symbol);
}
return true;
},
@@ -2731,6 +2728,9 @@ bool GeneratorImpl::EmitType(std::ostream& out,
return true;
},
[&](const type::Vector* vec) {
if (vec->Packed()) {
out << "packed_";
}
if (!EmitType(out, vec->type(), "")) {
return false;
}
@@ -2838,11 +2838,6 @@ bool GeneratorImpl::EmitStructType(TextBuffer* b, const sem::Struct* str) {
add_byte_offset_comment(out, msl_offset);
}
if (auto* decl = mem->Declaration()) {
if (ast::HasAttribute<transform::PackedVec3::Attribute>(decl->attributes)) {
out << "packed_";
}
}
if (!EmitType(out, mem->Type(), mem_name)) {
return false;
}
@@ -2924,7 +2919,6 @@ bool GeneratorImpl::EmitStructType(TextBuffer* b, const sem::Struct* str) {
[&](const ast::StructMemberOffsetAttribute*) { return true; },
[&](const ast::StructMemberAlignAttribute*) { return true; },
[&](const ast::StructMemberSizeAttribute*) { return true; },
[&](const transform::PackedVec3::Attribute*) { return true; },
[&](Default) {
TINT_ICE(Writer, diagnostics_)
<< "unhandled struct member attribute: " << attr->Name();

View File

@@ -41,7 +41,7 @@ TEST_F(MslGeneratorImplTest, EmitExpression_MemberAccessor_Swizzle_xyz) {
GeneratorImpl& gen = Build();
std::stringstream out;
ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
EXPECT_EQ(out.str(), "float4(my_vec).xyz");
EXPECT_EQ(out.str(), "my_vec.xyz");
}
TEST_F(MslGeneratorImplTest, EmitExpression_MemberAccessor_Swizzle_gbr) {
@@ -53,7 +53,7 @@ TEST_F(MslGeneratorImplTest, EmitExpression_MemberAccessor_Swizzle_gbr) {
GeneratorImpl& gen = Build();
std::stringstream out;
ASSERT_TRUE(gen.EmitExpression(out, expr)) << gen.error();
EXPECT_EQ(out.str(), "float4(my_vec).gbr");
EXPECT_EQ(out.str(), "my_vec.gbr");
}
} // namespace