Import Tint changes from Dawn
Changes:
- cc636969b7b7bb04043ca15673c82dc94e7fdc17 [tint][wgsl] Replace size_t with uint32_t for IDs, Source. by Ben Clayton <bclayton@google.com>
- 144ebed4c7ee7c6ecddeedfa81d607bbf256e8f2 tint/hlsl: widen scope of workaround of DXC bug with cons... by Antonio Maiorano <amaiorano@google.com>
- 0880e0643379ff2535187662cb21a803ce974cfa Rename @index -> @blend_src by Corentin Wallez <cwallez@chromium.org>
- dfb4eb05d2a4e65e22fbb3b0441e74f136fa9190 Add @blend_src as an alias for @index. by Corentin Wallez <cwallez@chromium.org>
- 31a1592736e3465599145aa6f9ea9333bfd05196 [tint][sem] Replace more uses of std::vector with tint::V... by Ben Clayton <bclayton@google.com>
- 8be957f698baa57c87eca49aa5f93315081172a3 [tint] Replace std containers with Tint's containers in n... by Ben Clayton <bclayton@google.com>
- 5ff42f8900bae798cfc57d45953d387a994089a9 [tint][core] Don't create throw-away StructMembers by Ben Clayton <bclayton@google.com>
- f9ffc45753f3eb668c058b0b8e62a77a0a3cb331 [tint][resolver] Don't create throwaway sem::Parameters by Ben Clayton <bclayton@google.com>
- 10f1b6bdb4a7bd8e316d389230471654290cda66 [tint][utils] Fix Hashmap's small vector size by Ben Clayton <bclayton@google.com>
- 80144d262ecef9331783faaa8ca4dfa6dfcfd60c [tint][hlsl] Fix names of vector / matrix setter utils by Ben Clayton <bclayton@google.com>
- 652353953be36fd60ffc26788e7b5f3833a41dc4 [tint] Move unrestricted_pointer_paramters to kShippedWit... by Ben Clayton <bclayton@google.com>
- 4eeb0bd6e2dc3f608a079b7e62ff3fd3befccdef Implement push_constant-based firstIndex transform. by Stephen White <senorblanco@chromium.org>
- c65ac40803c289104fa26156113ebfd37280dd7a [tint][wgsl] Consider builtin calls as part of ptr analysis by Ben Clayton <bclayton@google.com>
- 868380669fb051756b154d531beb805a990a6674 Move ClampFragDepth transform to WGSL transforms. by Stephen White <senorblanco@chromium.org>
- c6ed507397f87c5ee96b01d2eed3eb77a0899c25 [tint][wgsl] Use tint's containers for ptr analysis by Ben Clayton <bclayton@google.com>
- 02262d895ff373badfc4d2233f8e14108d185687 [tint][msl] Fix C++17 warning. by Ben Clayton <bclayton@google.com>
- a840d5132ac88153efb26c92a24178d7d68eddef Replace CMAKE_SOURCE_DIR with PROJECT_SOURCE_DIR by amirsojoodi <amir@distributive.network>
- 15d2710c84b3420bd20da25b8ccbe5681521df84 Remove data returned from `TextureBuiltinFromUniform` tra... by dan sinclair <dsinclair@chromium.org>
GitOrigin-RevId: cc636969b7b7bb04043ca15673c82dc94e7fdc17
Change-Id: I949ec6ab831105ee01a2b5e92e96db023a9a469e
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/171360
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/tint/CMakeLists.txt b/src/tint/CMakeLists.txt
index 9a4eba5..eb95b38 100644
--- a/src/tint/CMakeLists.txt
+++ b/src/tint/CMakeLists.txt
@@ -690,10 +690,10 @@
install(FILES ${TINT_HEADERS} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/tint/)
- file(GLOB_RECURSE TINT_SRC_HEADERS RELATIVE ${CMAKE_SOURCE_DIR}/src/tint/ "*.h")
+ file(GLOB_RECURSE TINT_SRC_HEADERS RELATIVE ${TINT_ROOT_SOURCE_DIR} "*.h")
foreach(TINT_HEADER_FILE ${TINT_SRC_HEADERS})
get_filename_component(TINT_HEADER_DIR ${TINT_HEADER_FILE} DIRECTORY)
- install(FILES ${CMAKE_SOURCE_DIR}/src/tint/${TINT_HEADER_FILE} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/src/tint/${TINT_HEADER_DIR})
+ install(FILES ${TINT_ROOT_SOURCE_DIR}/${TINT_HEADER_FILE} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/src/tint/${TINT_HEADER_DIR})
endforeach ()
endif()
diff --git a/src/tint/api/options/texture_builtins_from_uniform.h b/src/tint/api/options/texture_builtins_from_uniform.h
index bddb274..ac107e5 100644
--- a/src/tint/api/options/texture_builtins_from_uniform.h
+++ b/src/tint/api/options/texture_builtins_from_uniform.h
@@ -28,8 +28,7 @@
#ifndef SRC_TINT_API_OPTIONS_TEXTURE_BUILTINS_FROM_UNIFORM_H_
#define SRC_TINT_API_OPTIONS_TEXTURE_BUILTINS_FROM_UNIFORM_H_
-#include <unordered_map>
-#include <utility>
+#include <vector>
#include "src/tint/api/common/binding_point.h"
#include "src/tint/utils/reflection/reflection.h"
@@ -39,25 +38,16 @@
/// Options used to specify a mapping of binding points to indices into a UBO
/// from which to load buffer sizes.
struct TextureBuiltinsFromUniformOptions {
- /// Indicate the type of field for each entry to push.
- enum class Field {
- /// The number of mip levels of the bonnd texture view.
- TextureNumLevels,
- /// The number of samples per texel of the bound multipsampled texture.
- TextureNumSamples,
- };
-
- /// Records the field and the byte offset of the data to push in the internal uniform buffer.
- using FieldAndOffset = std::pair<Field, uint32_t>;
- /// Maps from binding point to data entry with the information to populate the data.
- using BindingPointToFieldAndOffset = std::unordered_map<BindingPoint, FieldAndOffset>;
-
/// The binding point to use to generate a uniform buffer from which to read
/// buffer sizes.
BindingPoint ubo_binding = {};
+ /// Ordered list of binding points in the uniform buffer for polyfilling `textureNumSamples` and
+ /// `textureNumLevels`
+ std::vector<BindingPoint> ubo_bindingpoint_ordering = {};
+
/// Reflect the fields of this class so that it can be used by tint::ForeachField()
- TINT_REFLECT(ubo_binding);
+ TINT_REFLECT(ubo_binding, ubo_bindingpoint_ordering);
};
} // namespace tint
diff --git a/src/tint/cmd/tint/main.cc b/src/tint/cmd/tint/main.cc
index 474088e..9797feb 100644
--- a/src/tint/cmd/tint/main.cc
+++ b/src/tint/cmd/tint/main.cc
@@ -1040,6 +1040,8 @@
std::cerr << "GLSL writer not enabled in tint build" << std::endl;
return false;
#else
+ tint::inspector::Inspector inspector(program);
+
auto generate = [&](const tint::Program& prg, const std::string entry_point_name,
[[maybe_unused]] tint::ast::PipelineStage stage) -> bool {
tint::glsl::writer::Options gen_options;
@@ -1049,7 +1051,20 @@
tint::TextureBuiltinsFromUniformOptions textureBuiltinsFromUniform;
constexpr uint32_t kMaxBindGroups = 4u;
+
textureBuiltinsFromUniform.ubo_binding = {kMaxBindGroups, 0u};
+
+ auto textureBuiltinsFromUniformData = inspector.GetTextureQueries(entry_point_name);
+ if (!textureBuiltinsFromUniformData.empty()) {
+ for (size_t i = 0; i < textureBuiltinsFromUniformData.size(); ++i) {
+ const auto& info = textureBuiltinsFromUniformData[i];
+
+ // This is the unmodified binding point from the WGSL shader.
+ tint::BindingPoint srcBindingPoint{info.group, info.binding};
+ textureBuiltinsFromUniform.ubo_bindingpoint_ordering.emplace_back(srcBindingPoint);
+ }
+ }
+
gen_options.texture_builtins_from_uniform = std::move(textureBuiltinsFromUniform);
auto result = tint::glsl::writer::Generate(prg, gen_options, entry_point_name);
@@ -1086,8 +1101,6 @@
return true;
};
- tint::inspector::Inspector inspector(program);
-
if (inspector.GetEntryPoints().empty()) {
// Pass empty string here so that the GLSL generator will generate
// code for all functions, reachable or not.
diff --git a/src/tint/lang/core/attribute.cc b/src/tint/lang/core/attribute.cc
index 2568294..c6fa693 100644
--- a/src/tint/lang/core/attribute.cc
+++ b/src/tint/lang/core/attribute.cc
@@ -48,6 +48,9 @@
if (str == "binding") {
return Attribute::kBinding;
}
+ if (str == "blend_src") {
+ return Attribute::kBlendSrc;
+ }
if (str == "builtin") {
return Attribute::kBuiltin;
}
@@ -69,9 +72,6 @@
if (str == "id") {
return Attribute::kId;
}
- if (str == "index") {
- return Attribute::kIndex;
- }
if (str == "interpolate") {
return Attribute::kInterpolate;
}
@@ -104,6 +104,8 @@
return "align";
case Attribute::kBinding:
return "binding";
+ case Attribute::kBlendSrc:
+ return "blend_src";
case Attribute::kBuiltin:
return "builtin";
case Attribute::kColor:
@@ -118,8 +120,6 @@
return "group";
case Attribute::kId:
return "id";
- case Attribute::kIndex:
- return "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 46d7619..28dd3d4 100644
--- a/src/tint/lang/core/attribute.h
+++ b/src/tint/lang/core/attribute.h
@@ -51,6 +51,7 @@
kUndefined,
kAlign,
kBinding,
+ kBlendSrc,
kBuiltin,
kColor,
kCompute,
@@ -58,7 +59,6 @@
kFragment,
kGroup,
kId,
- kIndex,
kInterpolate,
kInvariant,
kLocation,
@@ -86,9 +86,9 @@
Attribute ParseAttribute(std::string_view str);
constexpr std::string_view kAttributeStrings[] = {
- "align", "binding", "builtin", "color", "compute", "diagnostic",
- "fragment", "group", "id", "index", "interpolate", "invariant",
- "location", "must_use", "size", "vertex", "workgroup_size",
+ "align", "binding", "blend_src", "builtin", "color", "compute",
+ "diagnostic", "fragment", "group", "id", "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 16a660c..924456c 100644
--- a/src/tint/lang/core/attribute_bench.cc
+++ b/src/tint/lang/core/attribute_bench.cc
@@ -59,111 +59,111 @@
"bindiivg",
"8WWnding",
"bxxding",
- "bXltigg",
- "ultXn",
- "buil3in",
+ "bXnd_ggrc",
+ "bleXVuc",
+ "3lend_src",
+ "blend_src",
+ "blend_sEc",
+ "blTTPn_src",
+ "ddlen_sxxc",
+ "b44iltin",
+ "buSSltVVn",
+ "RuiR22n",
"builtin",
- "Euiltin",
- "bPTTltin",
- "builtdxx",
- "c44lor",
- "coVVSSr",
- "22RRr",
+ "bFlt9n",
+ "buitin",
+ "VOORRHin",
+ "olyr",
+ "n77rrllGr",
+ "colo40",
"color",
- "cFor",
- "colr",
- "ROOHVr",
- "copuye",
- "llnorrp77te",
- "comp4t00",
+ "oor",
+ "cozz",
+ "1ippor",
+ "compuXXe",
+ "9II5onnpute",
+ "comaSSrHHYe",
"compute",
- "opooe",
- "zzpute",
- "ciimppu1",
- "XXiagnostic",
- "IIia99nonnt55c",
- "dYagSSrrstHHac",
+ "cokke",
+ "jomgRu",
+ "cbput",
+ "diagnojtic",
+ "dagnostic",
+ "diagosqi",
"diagnostic",
- "dakkoHtc",
- "jiagnsgRR",
- "diagbost",
- "fragjent",
- "fragmnt",
- "frqent",
+ "diagnNNstc",
+ "dignvvtic",
+ "diagnostiQ",
+ "frafmrt",
+ "frjgment",
+ "frawNN82t",
"fragment",
- "fragenNN",
- "ravvent",
- "frgmQQnt",
- "grof",
- "grojp",
- "NNrw2u",
+ "fragmnt",
+ "frrrgment",
+ "fGagment",
+ "grFFup",
+ "gE",
+ "grrrp",
"group",
- "grup",
- "grroup",
- "Group",
- "iFF",
- "NN",
- "iAA",
+ "grp",
+ "grJJD",
+ "gu",
+ "K",
+ "FsJ",
+ "KK_v",
"id",
- "d",
- "L",
- "yy",
- "nek",
- "indx",
- "Jndx",
- "index",
- "incex",
- "iOdex",
- "__nttKKvv",
- "int8rpoxx5e",
- "inteqq__lte",
- "interpqlate",
- "interpolate",
- "33ntOpolat66",
+ "5O8",
+ "",
+ "DDbbB",
+ "interpolaKKe",
+ "33terpolate",
"intoott6QQlate",
+ "interpolate",
"66terpolate",
- "zzxvO6rint",
- "invayyiant",
+ "intxp66latOz",
+ "yynterpolate",
"HHnariZt",
- "invariant",
"iWW44rianq",
"iOOvaiant",
+ "invariant",
"ivariYnt",
- "ltion",
- "loaFion",
+ "nvaria",
+ "invaranF",
"wocatio",
- "location",
"Kcatoff",
"qocKKtion",
+ "location",
"lFcmmt3on",
- "mustuse",
- "must_se",
+ "locaion",
+ "locaton",
"ubbt_ube",
- "must_use",
"mstiius",
"muqt_uOe",
+ "must_use",
"muTTt_usvv",
- "FFize",
- "QP00",
+ "FFust_use",
+ "fu00QPus",
"siPe",
- "size",
"sis77",
"CiRbbe",
+ "size",
"sizXX",
- "CCrtOOOO",
- "vrsuL",
+ "qCCOOO",
+ "szL",
"verteX",
- "vertex",
"verte",
"qqrx",
+ "vertex",
"verte22",
- "workgou0yzzizXX",
- "workgrop_VPize",
+ "vzzyrte",
+ "eriVPx",
"wokgroupnnsCze",
- "workgroup_size",
"workgrouq_sizHA",
"workgrup_size",
+ "workgroup_size",
"forroupKKsize",
+ "workrop_Pigge",
+ "workgoup_size",
};
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 10d8e72..4d4ed0d 100644
--- a/src/tint/lang/core/attribute_test.cc
+++ b/src/tint/lang/core/attribute_test.cc
@@ -59,6 +59,7 @@
static constexpr Case kValidCases[] = {
{"align", Attribute::kAlign},
{"binding", Attribute::kBinding},
+ {"blend_src", Attribute::kBlendSrc},
{"builtin", Attribute::kBuiltin},
{"color", Attribute::kColor},
{"compute", Attribute::kCompute},
@@ -66,7 +67,6 @@
{"fragment", Attribute::kFragment},
{"group", Attribute::kGroup},
{"id", Attribute::kId},
- {"index", Attribute::kIndex},
{"interpolate", Attribute::kInterpolate},
{"invariant", Attribute::kInvariant},
{"location", Attribute::kLocation},
@@ -83,30 +83,30 @@
{"bind1ng", Attribute::kUndefined},
{"bqnJing", Attribute::kUndefined},
{"bindin7ll", Attribute::kUndefined},
- {"ppqqiliHH", Attribute::kUndefined},
- {"bucv", Attribute::kUndefined},
- {"biltGn", Attribute::kUndefined},
- {"covior", Attribute::kUndefined},
- {"co8WWr", Attribute::kUndefined},
- {"Mxxlo", Attribute::kUndefined},
- {"cXputgg", Attribute::kUndefined},
- {"opuXe", Attribute::kUndefined},
- {"comp3te", Attribute::kUndefined},
- {"diagnostiE", Attribute::kUndefined},
- {"TTiagnosPPi", Attribute::kUndefined},
- {"diagdoxxtic", Attribute::kUndefined},
- {"44ragment", Attribute::kUndefined},
- {"fSSagmenVV", Attribute::kUndefined},
- {"Rag2Rent", Attribute::kUndefined},
- {"gFup", Attribute::kUndefined},
- {"grop", Attribute::kUndefined},
- {"ROOHVp", Attribute::kUndefined},
- {"y", Attribute::kUndefined},
- {"Gn77rl", Attribute::kUndefined},
- {"04d", Attribute::kUndefined},
- {"oox", Attribute::kUndefined},
- {"inzz", Attribute::kUndefined},
- {"1ippex", Attribute::kUndefined},
+ {"blen_sppqHH", Attribute::kUndefined},
+ {"blen_r", Attribute::kUndefined},
+ {"bbndGsrc", Attribute::kUndefined},
+ {"builiivn", Attribute::kUndefined},
+ {"8WWiltin", Attribute::kUndefined},
+ {"bxxltin", Attribute::kUndefined},
+ {"cggor", Attribute::kUndefined},
+ {"VoX", Attribute::kUndefined},
+ {"colo3", Attribute::kUndefined},
+ {"Eompute", Attribute::kUndefined},
+ {"cPTTpute", Attribute::kUndefined},
+ {"compudxx", Attribute::kUndefined},
+ {"diagno44tic", Attribute::kUndefined},
+ {"diaVVSnostic", Attribute::kUndefined},
+ {"2iRRnostic", Attribute::kUndefined},
+ {"rFg9ent", Attribute::kUndefined},
+ {"frament", Attribute::kUndefined},
+ {"ROOrHgeVt", Attribute::kUndefined},
+ {"royp", Attribute::kUndefined},
+ {"n77rrloGp", Attribute::kUndefined},
+ {"grou40", Attribute::kUndefined},
+ {"HH", Attribute::kUndefined},
+ {"p", Attribute::kUndefined},
+ {"1ii", Attribute::kUndefined},
{"interpoXXate", Attribute::kUndefined},
{"intII99r55olate", Attribute::kUndefined},
{"intaarpoSSrHHYe", Attribute::kUndefined},
diff --git a/src/tint/lang/core/core.def b/src/tint/lang/core/core.def
index 2606174..4a5ed76 100644
--- a/src/tint/lang/core/core.def
+++ b/src/tint/lang/core/core.def
@@ -198,13 +198,13 @@
enum attribute {
align
binding
+ blend_src
builtin
compute
diagnostic
fragment
group
id
- index
interpolate
invariant
location
diff --git a/src/tint/lang/core/ir/binary/decode.cc b/src/tint/lang/core/ir/binary/decode.cc
index 8b3d75d..a65c48f 100644
--- a/src/tint/lang/core/ir/binary/decode.cc
+++ b/src/tint/lang/core/ir/binary/decode.cc
@@ -610,8 +610,8 @@
if (attributes_in.has_location()) {
attributes_out.location = attributes_in.location();
}
- if (attributes_in.has_index()) {
- attributes_out.index = attributes_in.index();
+ if (attributes_in.has_blend_src()) {
+ attributes_out.blend_src = attributes_in.blend_src();
}
if (attributes_in.has_color()) {
attributes_out.color = attributes_in.color();
diff --git a/src/tint/lang/core/ir/binary/encode.cc b/src/tint/lang/core/ir/binary/encode.cc
index 6f57223..ed03faa 100644
--- a/src/tint/lang/core/ir/binary/encode.cc
+++ b/src/tint/lang/core/ir/binary/encode.cc
@@ -423,8 +423,8 @@
if (attrs_in.location) {
member_out.mutable_attributes()->set_location(*attrs_in.location);
}
- if (attrs_in.index) {
- member_out.mutable_attributes()->set_index(*attrs_in.index);
+ if (attrs_in.blend_src) {
+ member_out.mutable_attributes()->set_blend_src(*attrs_in.blend_src);
}
if (attrs_in.color) {
member_out.mutable_attributes()->set_color(*attrs_in.color);
diff --git a/src/tint/lang/core/ir/binary/ir.proto b/src/tint/lang/core/ir/binary/ir.proto
index 20933ce..e59a9cb 100644
--- a/src/tint/lang/core/ir/binary/ir.proto
+++ b/src/tint/lang/core/ir/binary/ir.proto
@@ -366,7 +366,7 @@
////////////////////////////////////////////////////////////////////////////////
message AttributesStructMember {
optional uint32 location = 1;
- optional uint32 index = 2;
+ optional uint32 blend_src = 2;
optional uint32 color = 3;
optional BuiltinValue builtin = 4;
optional Interpolation interpolation = 5;
diff --git a/src/tint/lang/core/ir/binary/roundtrip_test.cc b/src/tint/lang/core/ir/binary/roundtrip_test.cc
index cf6bbcc..94e2f5b 100644
--- a/src/tint/lang/core/ir/binary/roundtrip_test.cc
+++ b/src/tint/lang/core/ir/binary/roundtrip_test.cc
@@ -276,7 +276,7 @@
TEST_F(IRBinaryRoundtripTest, StructMemberAttributes) {
type::StructMemberAttributes attrs{};
attrs.location = 1;
- attrs.index = 2;
+ attrs.blend_src = 2;
attrs.color = 3;
attrs.builtin = core::BuiltinValue::kFragDepth;
attrs.interpolation = core::Interpolation{
diff --git a/src/tint/lang/core/ir/disassembler.cc b/src/tint/lang/core/ir/disassembler.cc
index cfa2e30..6397f8a 100644
--- a/src/tint/lang/core/ir/disassembler.cc
+++ b/src/tint/lang/core/ir/disassembler.cc
@@ -506,8 +506,8 @@
if (v->Attributes().location.has_value()) {
out_ << " @location(" << v->Attributes().location.value() << ")";
}
- if (v->Attributes().index.has_value()) {
- out_ << " @index(" << v->Attributes().index.value() << ")";
+ if (v->Attributes().blend_src.has_value()) {
+ out_ << " @blend_src(" << v->Attributes().blend_src.value() << ")";
}
if (v->Attributes().interpolation.has_value()) {
auto& interp = v->Attributes().interpolation.value();
diff --git a/src/tint/lang/core/ir/var.h b/src/tint/lang/core/ir/var.h
index 4220a4c..d6a73d3 100644
--- a/src/tint/lang/core/ir/var.h
+++ b/src/tint/lang/core/ir/var.h
@@ -42,8 +42,8 @@
struct IOAttributes {
/// The value of a `@location` attribute.
std::optional<uint32_t> location;
- /// The value of a `@index` attribute.
- std::optional<uint32_t> index;
+ /// The value of a `@blend_src` attribute.
+ std::optional<uint32_t> blend_src;
/// The value of a `@builtin` attribute.
std::optional<core::BuiltinValue> builtin;
/// The values of a `@interpolate` attribute.
diff --git a/src/tint/lang/core/ir/var_test.cc b/src/tint/lang/core/ir/var_test.cc
index 3353672..5e41f29 100644
--- a/src/tint/lang/core/ir/var_test.cc
+++ b/src/tint/lang/core/ir/var_test.cc
@@ -100,8 +100,8 @@
EXPECT_TRUE(attrs.location.has_value());
EXPECT_EQ(3u, attrs.location.value());
- EXPECT_TRUE(attrs.index.has_value());
- EXPECT_EQ(4u, attrs.index.value());
+ EXPECT_TRUE(attrs.blend_src.has_value());
+ EXPECT_EQ(4u, attrs.blend_src.value());
EXPECT_TRUE(attrs.builtin.has_value());
EXPECT_EQ(core::BuiltinValue::kFragDepth, attrs.builtin.value());
diff --git a/src/tint/lang/core/type/builtin_structs.cc b/src/tint/lang/core/type/builtin_structs.cc
index 8f319d5..31af873 100644
--- a/src/tint/lang/core/type/builtin_structs.cc
+++ b/src/tint/lang/core/type/builtin_structs.cc
@@ -70,7 +70,11 @@
Struct* CreateModfResult(Manager& types, SymbolTable& symbols, const Type* ty) {
auto build = [&](core::BuiltinType name, const Type* t) {
- return types.Struct(symbols.Register(tint::ToString(name)),
+ auto symbol = symbols.Register(tint::ToString(name));
+ if (auto* existing = types.Find<type::Struct>(symbol)) {
+ return existing;
+ }
+ return types.Struct(symbol,
{{symbols.Register("fract"), t}, {symbols.Register("whole"), t}});
};
return Switch(
@@ -127,9 +131,12 @@
Struct* CreateFrexpResult(Manager& types, SymbolTable& symbols, const Type* ty) {
auto build = [&](core::BuiltinType name, const Type* fract_ty, const Type* exp_ty) {
+ auto symbol = symbols.Register(tint::ToString(name));
+ if (auto* existing = types.Find<type::Struct>(symbol)) {
+ return existing;
+ }
return types.Struct(
- symbols.Register(tint::ToString(name)),
- {{symbols.Register("fract"), fract_ty}, {symbols.Register("exp"), exp_ty}});
+ symbol, {{symbols.Register("fract"), fract_ty}, {symbols.Register("exp"), exp_ty}});
};
return Switch(
ty, //
@@ -172,11 +179,14 @@
Struct* CreateAtomicCompareExchangeResult(Manager& types, SymbolTable& symbols, const Type* ty) {
auto build = [&](core::BuiltinType name) {
- return types.Struct(symbols.Register(tint::ToString(name)),
- {
- {symbols.Register("old_value"), ty},
- {symbols.Register("exchanged"), types.bool_()},
- });
+ auto symbol = symbols.Register(tint::ToString(name));
+ if (auto* existing = types.Find<type::Struct>(symbol)) {
+ return existing;
+ }
+ return types.Struct(symbol, {
+ {symbols.Register("old_value"), ty},
+ {symbols.Register("exchanged"), types.bool_()},
+ });
};
return Switch(
ty, //
diff --git a/src/tint/lang/core/type/manager.cc b/src/tint/lang/core/type/manager.cc
index ff70390..f158770 100644
--- a/src/tint/lang/core/type/manager.cc
+++ b/src/tint/lang/core/type/manager.cc
@@ -42,6 +42,7 @@
#include "src/tint/lang/core/type/u32.h"
#include "src/tint/lang/core/type/vector.h"
#include "src/tint/lang/core/type/void.h"
+#include "src/tint/utils/macros/compiler.h"
namespace tint::core::type {
@@ -198,6 +199,11 @@
}
core::type::Struct* Manager::Struct(Symbol name, VectorRef<const StructMember*> members) {
+ if (auto* existing = Find<type::Struct>(name); TINT_UNLIKELY(existing)) {
+ TINT_ICE() << "attempting to construct two structs named " << name.NameView();
+ return existing;
+ }
+
uint32_t max_align = 0u;
for (const auto& m : members) {
max_align = std::max(max_align, m->Align());
@@ -208,6 +214,11 @@
}
core::type::Struct* Manager::Struct(Symbol name, VectorRef<StructMemberDesc> md) {
+ if (auto* existing = Find<type::Struct>(name); TINT_UNLIKELY(existing)) {
+ TINT_ICE() << "attempting to construct two structs named " << name.NameView();
+ return existing;
+ }
+
tint::Vector<const StructMember*, 4> members;
uint32_t current_size = 0u;
uint32_t max_align = 0u;
diff --git a/src/tint/lang/core/type/manager.h b/src/tint/lang/core/type/manager.h
index 6c12a6c..f02290b 100644
--- a/src/tint/lang/core/type/manager.h
+++ b/src/tint/lang/core/type/manager.h
@@ -475,18 +475,21 @@
/// Create a new structure declaration.
/// @param name the name of the structure
/// @param members the list of structure members
+ /// @note a structure must not already exist with the same name
/// @returns the structure type
core::type::Struct* Struct(Symbol name, VectorRef<const StructMember*> members);
/// Create a new structure declaration.
/// @param name the name of the structure
/// @param members the list of structure member descriptors
+ /// @note a structure must not already exist with the same name
/// @returns the structure type
core::type::Struct* Struct(Symbol name, VectorRef<StructMemberDesc> members);
/// Create a new structure declaration.
/// @param name the name of the structure
/// @param members the list of structure member descriptors
+ /// @note a structure must not already exist with the same name
/// @returns the structure type
core::type::Struct* Struct(Symbol name, std::initializer_list<StructMemberDesc> members) {
return Struct(name, tint::Vector<StructMemberDesc, 4>(members));
diff --git a/src/tint/lang/core/type/struct.cc b/src/tint/lang/core/type/struct.cc
index c916e4b..ff08e35 100644
--- a/src/tint/lang/core/type/struct.cc
+++ b/src/tint/lang/core/type/struct.cc
@@ -43,8 +43,8 @@
namespace tint::core::type {
namespace {
-core::type::Flags FlagsFrom(VectorRef<const StructMember*> members) {
- core::type::Flags flags{
+Flags FlagsFrom(VectorRef<const StructMember*> members) {
+ Flags flags{
Flag::kConstructable,
Flag::kCreationFixedFootprint,
Flag::kFixedFootprint,
@@ -65,6 +65,14 @@
} // namespace
+Struct::Struct(Symbol name)
+ : Base(Hash(tint::TypeInfo::Of<Struct>().full_hashcode, name), type::Flags{}),
+ name_(name),
+ members_{},
+ align_(0),
+ size_(0),
+ size_no_padding_(0) {}
+
Struct::Struct(Symbol name,
VectorRef<const StructMember*> members,
uint32_t align,
diff --git a/src/tint/lang/core/type/struct.h b/src/tint/lang/core/type/struct.h
index 228c8b8..539c27b 100644
--- a/src/tint/lang/core/type/struct.h
+++ b/src/tint/lang/core/type/struct.h
@@ -31,7 +31,6 @@
#include <cstdint>
#include <optional>
#include <string>
-#include <unordered_set>
#include <utility>
#include "src/tint/lang/core/address_space.h"
@@ -39,6 +38,7 @@
#include "src/tint/lang/core/interpolation.h"
#include "src/tint/lang/core/type/node.h"
#include "src/tint/lang/core/type/type.h"
+#include "src/tint/utils/containers/hashset.h"
#include "src/tint/utils/containers/vector.h"
#include "src/tint/utils/symbol/symbol.h"
@@ -72,6 +72,12 @@
class Struct : public Castable<Struct, Type> {
public:
/// Constructor
+ /// Note: this constructs an empty structure, which should only be used find a struct with the
+ /// same name in a type::Manager.
+ /// @param name the name of the structure
+ explicit Struct(Symbol name);
+
+ /// Constructor
/// @param name the name of the structure
/// @param members the structure members
/// @param align the byte alignment of the structure
@@ -130,16 +136,14 @@
/// Adds the AddressSpace usage to the structure.
/// @param usage the storage usage
- void AddUsage(core::AddressSpace usage) { address_space_usage_.emplace(usage); }
+ void AddUsage(core::AddressSpace usage) { address_space_usage_.Add(usage); }
/// @returns the set of address space uses of this structure
- const std::unordered_set<core::AddressSpace>& AddressSpaceUsage() const {
- return address_space_usage_;
- }
+ const Hashset<core::AddressSpace, 1>& AddressSpaceUsage() const { return address_space_usage_; }
/// @param usage the AddressSpace usage type to query
/// @returns true iff this structure has been used as the given address space
- bool UsedAs(core::AddressSpace usage) const { return address_space_usage_.count(usage) > 0; }
+ bool UsedAs(core::AddressSpace usage) const { return address_space_usage_.Contains(usage); }
/// @returns true iff this structure has been used by address space that's
/// host-shareable.
@@ -154,12 +158,10 @@
/// Adds the pipeline stage usage to the structure.
/// @param usage the storage usage
- void AddUsage(PipelineStageUsage usage) { pipeline_stage_uses_.emplace(usage); }
+ void AddUsage(PipelineStageUsage usage) { pipeline_stage_uses_.Add(usage); }
/// @returns the set of entry point uses of this structure
- const std::unordered_set<PipelineStageUsage>& PipelineStageUses() const {
- return pipeline_stage_uses_;
- }
+ const Hashset<PipelineStageUsage, 1>& PipelineStageUses() const { return pipeline_stage_uses_; }
/// @returns the name for this type that closely resembles how it would be
/// declared in WGSL.
@@ -195,8 +197,8 @@
const uint32_t size_;
const uint32_t size_no_padding_;
core::type::StructFlags struct_flags_;
- std::unordered_set<core::AddressSpace> address_space_usage_;
- std::unordered_set<PipelineStageUsage> pipeline_stage_uses_;
+ Hashset<core::AddressSpace, 1> address_space_usage_;
+ Hashset<PipelineStageUsage, 1> pipeline_stage_uses_;
tint::Vector<const Struct*, 2> concrete_types_;
};
@@ -204,8 +206,8 @@
struct StructMemberAttributes {
/// The value of a `@location` attribute
std::optional<uint32_t> location;
- /// The value of a `@index` attribute
- std::optional<uint32_t> index;
+ /// The value of a `@blend_src` attribute
+ std::optional<uint32_t> blend_src;
/// The value of a `@color` attribute
std::optional<uint32_t> color;
/// The value of a `@builtin` attribute
diff --git a/src/tint/lang/glsl/writer/ast_printer/ast_printer.cc b/src/tint/lang/glsl/writer/ast_printer/ast_printer.cc
index 2026bd2..1a66806 100644
--- a/src/tint/lang/glsl/writer/ast_printer/ast_printer.cc
+++ b/src/tint/lang/glsl/writer/ast_printer/ast_printer.cc
@@ -67,6 +67,7 @@
#include "src/tint/lang/wgsl/ast/transform/expand_compound_assignment.h"
#include "src/tint/lang/wgsl/ast/transform/manager.h"
#include "src/tint/lang/wgsl/ast/transform/multiplanar_external_texture.h"
+#include "src/tint/lang/wgsl/ast/transform/offset_first_index.h"
#include "src/tint/lang/wgsl/ast/transform/preserve_padding.h"
#include "src/tint/lang/wgsl/ast/transform/promote_initializers_to_let.h"
#include "src/tint/lang/wgsl/ast/transform/promote_side_effects_to_decl.h"
@@ -152,8 +153,6 @@
data.Add<ast::transform::SingleEntryPoint::Config>(entry_point);
}
- data.Add<ast::transform::AddBlockAttribute::Config>(true);
-
manager.Add<ast::transform::PreservePadding>(); // Must come before DirectVariableAccess
manager.Add<ast::transform::Unshadow>(); // Must come before DirectVariableAccess
@@ -203,6 +202,8 @@
manager.Add<ast::transform::ZeroInitWorkgroupMemory>();
}
+ manager.Add<ast::transform::OffsetFirstIndex>();
+
// CanonicalizeEntryPointIO must come after Robustness
manager.Add<ast::transform::CanonicalizeEntryPointIO>();
@@ -217,11 +218,10 @@
// TextureBuiltinsFromUniform must come before CombineSamplers to preserve texture binding point
// info, instead of combined sampler binding point. As a result, TextureBuiltinsFromUniform also
// comes before BindingRemapper so the binding point info it reflects is before remapping.
- if (options.texture_builtins_from_uniform) {
- manager.Add<TextureBuiltinsFromUniform>();
- data.Add<TextureBuiltinsFromUniform::Config>(
- options.texture_builtins_from_uniform->ubo_binding);
- }
+ manager.Add<TextureBuiltinsFromUniform>();
+ data.Add<TextureBuiltinsFromUniform::Config>(
+ options.texture_builtins_from_uniform.ubo_binding,
+ options.texture_builtins_from_uniform.ubo_bindingpoint_ordering);
data.Add<CombineSamplers::BindingInfo>(options.binding_map, options.placeholder_binding_point);
manager.Add<CombineSamplers>();
@@ -246,13 +246,11 @@
data.Add<ast::transform::CanonicalizeEntryPointIO::Config>(
ast::transform::CanonicalizeEntryPointIO::ShaderStyle::kGlsl);
+ data.Add<ast::transform::OffsetFirstIndex::Config>(std::nullopt, options.first_instance_offset);
+
SanitizedResult result;
ast::transform::DataMap outputs;
result.program = manager.Run(in, data, outputs);
- if (auto* res = outputs.Get<TextureBuiltinsFromUniform::Result>()) {
- result.needs_internal_uniform_buffer = true;
- result.bindpoint_to_data = std::move(res->bindpoint_to_data);
- }
return result;
}
@@ -302,7 +300,8 @@
}
bool is_block =
ast::HasAttribute<ast::transform::AddBlockAttribute::BlockAttribute>(
- str->attributes);
+ str->attributes) &&
+ !sem->UsedAs(core::AddressSpace::kPushConstant);
if (!has_rt_arr && !is_block) {
EmitStructType(current_buffer_, sem);
}
@@ -2098,6 +2097,7 @@
auto name = decl->name->symbol.Name();
auto* type = var->Type()->UnwrapRef();
+ out << "layout(location=0) ";
EmitTypeAndName(out, type, var->AddressSpace(), var->Access(), name);
out << ";";
}
diff --git a/src/tint/lang/glsl/writer/ast_printer/ast_printer.h b/src/tint/lang/glsl/writer/ast_printer/ast_printer.h
index cfaf716..b35664f 100644
--- a/src/tint/lang/glsl/writer/ast_printer/ast_printer.h
+++ b/src/tint/lang/glsl/writer/ast_printer/ast_printer.h
@@ -67,13 +67,6 @@
/// The sanitized program.
Program program;
-
- /// True if the shader needs a UBO.
- bool needs_internal_uniform_buffer = false;
-
- /// Store a map of global texture variable binding point to the byte offset and data type to
- /// push into the internal uniform buffer.
- TextureBuiltinsFromUniformOptions::BindingPointToFieldAndOffset bindpoint_to_data;
};
/// Sanitize a program in preparation for generating GLSL.
diff --git a/src/tint/lang/glsl/writer/ast_raise/BUILD.bazel b/src/tint/lang/glsl/writer/ast_raise/BUILD.bazel
index 540f314..c23fd29 100644
--- a/src/tint/lang/glsl/writer/ast_raise/BUILD.bazel
+++ b/src/tint/lang/glsl/writer/ast_raise/BUILD.bazel
@@ -52,7 +52,6 @@
],
deps = [
"//src/tint/api/common",
- "//src/tint/api/options",
"//src/tint/lang/core",
"//src/tint/lang/core/constant",
"//src/tint/lang/core/type",
@@ -92,7 +91,6 @@
],
deps = [
"//src/tint/api/common",
- "//src/tint/api/options",
"//src/tint/lang/core",
"//src/tint/lang/core/constant",
"//src/tint/lang/core/ir",
diff --git a/src/tint/lang/glsl/writer/ast_raise/BUILD.cmake b/src/tint/lang/glsl/writer/ast_raise/BUILD.cmake
index 0ca869d..1a658c0 100644
--- a/src/tint/lang/glsl/writer/ast_raise/BUILD.cmake
+++ b/src/tint/lang/glsl/writer/ast_raise/BUILD.cmake
@@ -53,7 +53,6 @@
tint_target_add_dependencies(tint_lang_glsl_writer_ast_raise lib
tint_api_common
- tint_api_options
tint_lang_core
tint_lang_core_constant
tint_lang_core_type
@@ -96,7 +95,6 @@
tint_target_add_dependencies(tint_lang_glsl_writer_ast_raise_test test
tint_api_common
- tint_api_options
tint_lang_core
tint_lang_core_constant
tint_lang_core_ir
diff --git a/src/tint/lang/glsl/writer/ast_raise/BUILD.gn b/src/tint/lang/glsl/writer/ast_raise/BUILD.gn
index 23c0067..166a313 100644
--- a/src/tint/lang/glsl/writer/ast_raise/BUILD.gn
+++ b/src/tint/lang/glsl/writer/ast_raise/BUILD.gn
@@ -55,7 +55,6 @@
]
deps = [
"${tint_src_dir}/api/common",
- "${tint_src_dir}/api/options",
"${tint_src_dir}/lang/core",
"${tint_src_dir}/lang/core/constant",
"${tint_src_dir}/lang/core/type",
@@ -96,7 +95,6 @@
deps = [
"${tint_src_dir}:gmock_and_gtest",
"${tint_src_dir}/api/common",
- "${tint_src_dir}/api/options",
"${tint_src_dir}/lang/core",
"${tint_src_dir}/lang/core/constant",
"${tint_src_dir}/lang/core/ir",
diff --git a/src/tint/lang/glsl/writer/ast_raise/texture_builtins_from_uniform.cc b/src/tint/lang/glsl/writer/ast_raise/texture_builtins_from_uniform.cc
index bc40549..5ac9fec 100644
--- a/src/tint/lang/glsl/writer/ast_raise/texture_builtins_from_uniform.cc
+++ b/src/tint/lang/glsl/writer/ast_raise/texture_builtins_from_uniform.cc
@@ -27,8 +27,6 @@
#include "src/tint/lang/glsl/writer/ast_raise/texture_builtins_from_uniform.h"
-#include <memory>
-#include <queue>
#include <string>
#include <utility>
#include <variant>
@@ -49,7 +47,6 @@
TINT_INSTANTIATE_TYPEINFO(tint::glsl::writer::TextureBuiltinsFromUniform);
TINT_INSTANTIATE_TYPEINFO(tint::glsl::writer::TextureBuiltinsFromUniform::Config);
-TINT_INSTANTIATE_TYPEINFO(tint::glsl::writer::TextureBuiltinsFromUniform::Result);
namespace tint::glsl::writer {
@@ -58,27 +55,10 @@
/// The member name of the texture builtin values.
constexpr std::string_view kTextureBuiltinValuesMemberNamePrefix = "texture_builtin_value_";
-bool ShouldRun(const Program& program) {
- for (auto* fn : program.AST().Functions()) {
- if (auto* sem_fn = program.Sem().Get(fn)) {
- for (auto* builtin : sem_fn->DirectlyCalledBuiltins()) {
- // GLSL ES has no native support for the counterpart of
- // textureNumLevels (textureQueryLevels) and textureNumSamples (textureSamples)
- if (builtin->Fn() == wgsl::BuiltinFn::kTextureNumLevels) {
- return true;
- }
- if (builtin->Fn() == wgsl::BuiltinFn::kTextureNumSamples) {
- return true;
- }
- }
- }
- }
- return false;
-}
-
} // namespace
TextureBuiltinsFromUniform::TextureBuiltinsFromUniform() = default;
+
TextureBuiltinsFromUniform::~TextureBuiltinsFromUniform() = default;
/// PIMPL state for the transform
@@ -86,11 +66,8 @@
/// Constructor
/// @param program the source program
/// @param in the input transform data
- /// @param out the output transform data
- explicit State(const Program& program,
- const ast::transform::DataMap& in,
- ast::transform::DataMap& out)
- : src(program), inputs(in), outputs(out) {}
+ explicit State(const Program& program, const ast::transform::DataMap& in)
+ : src(program), inputs(in) {}
/// Runs the transform
/// @returns the new program or SkipTransform if the transform is not required
@@ -103,12 +80,14 @@
std::string(tint::TypeInfo::Of<TextureBuiltinsFromUniform>().name));
return resolver::Resolve(b);
}
+ ubo_bindingpoint_ordering = cfg->ubo_bindingpoint_ordering;
- if (!ShouldRun(src)) {
+ // If there's no interested texture builtin at all, skip the transform.
+ if (ubo_bindingpoint_ordering.empty()) {
return SkipTransform;
}
- // The dependency order declartions guaranteed that we traverse interested functions in the
+ // The dependency order declarations guaranteed that we traverse interested functions in the
// following order:
// 1. texture builtins
// 2. user function directly calls texture builtins
@@ -143,21 +122,17 @@
auto* texture_sem = sem.GetVal(texture_expr)->RootIdentifier();
TINT_ASSERT(texture_sem);
- TextureBuiltinsFromUniformOptions::Field dataType =
- GetFieldFromBuiltinFunctionType(builtin->Fn());
-
tint::Switch(
texture_sem,
[&](const sem::GlobalVariable* global) {
// This texture variable is a global variable.
- auto binding = GetAndRecordGlobalBinding(global, dataType);
+ auto binding = GetGlobalBinding(global);
// Record the call and binding to be replaced later.
builtin_to_replace.Add(call_expr, binding);
},
[&](const sem::Variable* variable) {
// This texture variable is a user function parameter.
- auto new_param =
- GetAndRecordFunctionParameter(fn, variable, dataType);
+ auto new_param = GetAndRecordFunctionParameter(fn, variable);
// Record the call and new_param to be replaced later.
builtin_to_replace.Add(call_expr, new_param);
}, //
@@ -187,15 +162,14 @@
texture_sem,
[&](const sem::GlobalVariable* global) {
// This texture variable is a global variable.
- auto binding =
- GetAndRecordGlobalBinding(global, info->field);
+ auto binding = GetGlobalBinding(global);
// Record the binding to add to args.
args.Push(binding);
},
[&](const sem::Variable* variable) {
// This texture variable is a user function parameter.
- auto new_param = GetAndRecordFunctionParameter(
- fn, variable, info->field);
+ auto new_param =
+ GetAndRecordFunctionParameter(fn, variable);
// Record adding extra function parameter
args.Push(new_param);
}, //
@@ -207,11 +181,6 @@
}
}
- // If there's no interested texture builtin at all, skip the transform.
- if (bindpoint_to_data.empty()) {
- return SkipTransform;
- }
-
// If any functions need extra params, add them now.
if (!fn_to_data.IsEmpty()) {
for (auto pair : fn_to_data) {
@@ -263,8 +232,6 @@
}
}
- outputs.Add<Result>(bindpoint_to_data);
-
ctx.Clone();
return resolver::Resolve(b);
}
@@ -274,8 +241,6 @@
const Program& src;
/// The transform inputs
const ast::transform::DataMap& inputs;
- /// The transform outputs
- ast::transform::DataMap& outputs;
/// The target program builder
ProgramBuilder b;
/// The clone context
@@ -283,19 +248,10 @@
/// Alias to the semantic info in ctx.src
const sem::Info& sem = src.Sem();
- /// The bindpoint to byte offset and field to pass out in transform result.
- /// For one texture type, it could only be passed into one of the
- /// textureNumLevels or textureNumSamples because their accepting param texture
- /// type is different. There cannot be a binding entry with both field type.
- /// Note: because this transform must be run before CombineSampler and BindingRemapper,
- /// the binding number here is before remapped.
- Result::BindingPointToFieldAndOffset bindpoint_to_data;
+ /// Ordered list of binding points for where they appear in the UBO
+ std::vector<BindingPoint> ubo_bindingpoint_ordering;
struct FunctionExtraParamInfo {
- using Field = TextureBuiltinsFromUniformOptions::Field;
- // The kind of texture information this parameter holds.
- Field field = Field::TextureNumLevels;
-
// The extra passed in param that corresponds to the texture param.
const ast::Parameter* param = nullptr;
@@ -337,6 +293,7 @@
/// The internal uniform buffer
const ast::Variable* ubo = nullptr;
+
/// Get or create a UBO including u32 scalars for texture builtin values.
/// @returns the symbol of the uniform buffer variable.
Symbol GetUboSym() {
@@ -348,15 +305,13 @@
auto* cfg = inputs.Get<Config>();
Vector<const ast::StructMember*, 16> new_members;
- new_members.Resize(bindpoint_to_data.size());
- for (auto it : bindpoint_to_data) {
- // Emit a u32 scalar for each binding that needs builtin value passed in.
- size_t i = it.second.second / sizeof(uint32_t);
- TINT_ASSERT(i < new_members.Length());
+ new_members.Resize(ubo_bindingpoint_ordering.size());
+
+ for (size_t i = 0; i < ubo_bindingpoint_ordering.size(); ++i) {
// Append the vector index with the variable name to avoid unstable naming issue.
auto sym = b.Symbols().New(std::string(kTextureBuiltinValuesMemberNamePrefix) +
std::to_string(i));
- bindpoint_to_syms.Add(it.first, sym);
+ bindpoint_to_syms.Add(ubo_bindingpoint_ordering[i], sym);
new_members[i] = b.Member(sym, b.ty.u32());
}
@@ -403,48 +358,31 @@
/// @param binding of the global variable.
/// @returns an expression of the builtin value.
const ast::Expression* GetUniformValue(const BindingPoint& binding) {
- auto iter = bindpoint_to_data.find(binding);
- TINT_ASSERT(iter != bindpoint_to_data.end());
-
// Make sure GetUboSym() is called first to initialize the uniform buffer struct.
auto ubo_sym = GetUboSym();
+
// Load the builtin value from the UBO.
auto member_sym = bindpoint_to_syms.Get(binding);
TINT_ASSERT(member_sym.has_value());
- auto* builtin_value = b.MemberAccessor(ubo_sym, *member_sym);
- return builtin_value;
+ return b.MemberAccessor(ubo_sym, *member_sym);
}
- /// Get and return the binding of the global texture variable. Record in bindpoint_to_data if
- /// first visited.
+ /// Get and return the binding of the global texture variable.
/// @param global global variable of the texture variable.
- /// @param field type of the interested builtin function data related to this texture.
/// @returns binding of the global variable.
- BindingPoint GetAndRecordGlobalBinding(const sem::GlobalVariable* global,
- TextureBuiltinsFromUniformOptions::Field field) {
- auto binding = global->Attributes().binding_point.value();
- auto iter = bindpoint_to_data.find(binding);
- if (iter == bindpoint_to_data.end()) {
- // First visit, recording the binding.
- uint32_t index = static_cast<uint32_t>(bindpoint_to_data.size());
- bindpoint_to_data.emplace(
- binding,
- Result::FieldAndOffset{field, index * static_cast<uint32_t>(sizeof(uint32_t))});
- }
- return binding;
+ BindingPoint GetGlobalBinding(const sem::GlobalVariable* global) {
+ return global->Attributes().binding_point.value();
}
/// Find which function param is the given texture variable.
- /// Add a new u32 param relates to this texture param. Record in fn_to_data if first visited.
+ /// Add a new u32 param relates to this texture param. Record in fn_to_data if first
+ /// visited.
/// @param fn the current function scope.
/// @param var the texture variable.
- /// @param field type of the interested builtin function data related to this texture.
/// @returns the new u32 function parameter.
- const ast::Parameter* GetAndRecordFunctionParameter(
- const sem::Function* fn,
- const sem::Variable* var,
- TextureBuiltinsFromUniformOptions::Field field) {
+ const ast::Parameter* GetAndRecordFunctionParameter(const sem::Function* fn,
+ const sem::Variable* var) {
auto& param_to_info = fn_to_data.GetOrCreate(
fn, [&] { return Hashmap<const ast::Parameter*, FunctionExtraParamInfo, 4>(); });
@@ -456,50 +394,36 @@
}
}
TINT_ASSERT(param);
+
// Get or record a new u32 param to this function if first visited.
auto entry = param_to_info.Get(param);
if (entry.has_value()) {
return entry->param;
}
+
const ast::Parameter* new_param = b.Param(b.Sym(), b.ty.u32());
size_t idx = param_to_info.Count();
- param_to_info.Add(param, FunctionExtraParamInfo{field, new_param, idx});
+ param_to_info.Add(param, FunctionExtraParamInfo{new_param, idx});
return new_param;
}
-
- /// Get the uniform options field for the builtin function.
- /// @param type of the builtin function
- /// @returns corresponding TextureBuiltinsFromUniformOptions::Field for the builtin
- static TextureBuiltinsFromUniformOptions::Field GetFieldFromBuiltinFunctionType(
- wgsl::BuiltinFn type) {
- switch (type) {
- case wgsl::BuiltinFn::kTextureNumLevels:
- return TextureBuiltinsFromUniformOptions::Field::TextureNumLevels;
- case wgsl::BuiltinFn::kTextureNumSamples:
- return TextureBuiltinsFromUniformOptions::Field::TextureNumSamples;
- default:
- TINT_UNREACHABLE() << "unsupported builtin function type " << type;
- }
- return TextureBuiltinsFromUniformOptions::Field::TextureNumLevels;
- }
};
ast::transform::Transform::ApplyResult TextureBuiltinsFromUniform::Apply(
const Program& src,
const ast::transform::DataMap& inputs,
- ast::transform::DataMap& outputs) const {
- return State{src, inputs, outputs}.Run();
+ ast::transform::DataMap&) const {
+ return State{src, inputs}.Run();
}
-TextureBuiltinsFromUniform::Config::Config(BindingPoint ubo_bp) : ubo_binding(ubo_bp) {}
+TextureBuiltinsFromUniform::Config::Config(BindingPoint ubo_bp,
+ const std::vector<BindingPoint>& ordering)
+ : ubo_binding(ubo_bp), ubo_bindingpoint_ordering(ordering) {}
+
TextureBuiltinsFromUniform::Config::Config(const Config&) = default;
+
TextureBuiltinsFromUniform::Config& TextureBuiltinsFromUniform::Config::operator=(const Config&) =
default;
-TextureBuiltinsFromUniform::Config::~Config() = default;
-TextureBuiltinsFromUniform::Result::Result(BindingPointToFieldAndOffset bindpoint_to_data_in)
- : bindpoint_to_data(std::move(bindpoint_to_data_in)) {}
-TextureBuiltinsFromUniform::Result::Result(const Result&) = default;
-TextureBuiltinsFromUniform::Result::~Result() = default;
+TextureBuiltinsFromUniform::Config::~Config() = default;
} // namespace tint::glsl::writer
diff --git a/src/tint/lang/glsl/writer/ast_raise/texture_builtins_from_uniform.h b/src/tint/lang/glsl/writer/ast_raise/texture_builtins_from_uniform.h
index a54f02b..550e0f8 100644
--- a/src/tint/lang/glsl/writer/ast_raise/texture_builtins_from_uniform.h
+++ b/src/tint/lang/glsl/writer/ast_raise/texture_builtins_from_uniform.h
@@ -28,11 +28,9 @@
#ifndef SRC_TINT_LANG_GLSL_WRITER_AST_RAISE_TEXTURE_BUILTINS_FROM_UNIFORM_H_
#define SRC_TINT_LANG_GLSL_WRITER_AST_RAISE_TEXTURE_BUILTINS_FROM_UNIFORM_H_
-#include <unordered_map>
-#include <unordered_set>
+#include <vector>
#include "src/tint/api/common/binding_point.h"
-#include "src/tint/api/options/texture_builtins_from_uniform.h"
#include "src/tint/lang/wgsl/ast/transform/transform.h"
// Forward declarations
@@ -47,6 +45,7 @@
/// builtin functions are not available in some version of GLSL.
///
/// The generated uniform buffer will have the form:
+///
/// ```
/// struct internal_uniform {
/// texture_builtin_value_0 : u32,
@@ -54,15 +53,17 @@
///
/// @group(0) @binding(0) var tex : texture_2d<f32>;
/// ```
+///
/// The binding group and number used for this uniform buffer are provided via
/// the `Config` transform input.
///
-/// The transform coverts the texture builtins calls into values lookup from the internal
-/// buffer. If the texture is a function parameter instead of a global variable, this transform
-/// also takes care of adding extra paramters and arguments to these functions and their callsites.
+/// The transform coverts the texture builtins calls into values lookup from the internal buffer. If
+/// the texture is a function parameter instead of a global variable, this transform also takes care
+/// of adding extra parameters and arguments to these functions and their call-sites.
///
/// This transform must run before `CombineSamplers` transform so that the binding point of the
/// original texture object can be preserved.
+///
class TextureBuiltinsFromUniform final
: public Castable<TextureBuiltinsFromUniform, ast::transform::Transform> {
public:
@@ -75,7 +76,8 @@
struct Config final : public Castable<Config, ast::transform::Data> {
/// Constructor
/// @param ubo_bp the binding point to use for the generated uniform buffer.
- explicit Config(BindingPoint ubo_bp);
+ /// @param ordering the ordered list of binding points to appear in the UBO
+ Config(BindingPoint ubo_bp, const std::vector<BindingPoint>& ordering);
/// Copy constructor
Config(const Config&);
@@ -89,34 +91,14 @@
/// The binding point to use for the generated uniform buffer.
BindingPoint ubo_binding;
- };
- /// Information produced about what the transform did.
- /// If there were no calls to the textureNumLevels() or textureNumSamples() builtin, then no
- /// Result will be emitted.
- struct Result final : public Castable<Result, ast::transform::Data> {
- /// Using for shorter names
- /// Records the field and the byte offset of the data to push in the internal uniform
- /// buffer.
- using FieldAndOffset = TextureBuiltinsFromUniformOptions::FieldAndOffset;
- /// Maps from binding point to data entry with the information to populate the data.
- using BindingPointToFieldAndOffset =
- TextureBuiltinsFromUniformOptions::BindingPointToFieldAndOffset;
-
- /// Constructor
- /// @param bindpoint_to_data_in mapping from binding points of global texture variables to
- /// the byte offsets and data types needed to be pushed into the internal uniform buffer.
- explicit Result(BindingPointToFieldAndOffset bindpoint_to_data_in);
-
- /// Copy constructor
- Result(const Result&);
-
- /// Destructor
- ~Result() override;
-
- /// A map of global texture variable binding point to the byte offset and data type to push
- /// into the internal uniform buffer.
- BindingPointToFieldAndOffset bindpoint_to_data;
+ /// The set of binding points which will be in the extra UBO buffer. The binding points are
+ /// provided in the order that the data will be in the UBO buffer.
+ ///
+ /// Note, a given `BindingPoint` _must_ only appear once in the ordering list. This works
+ /// because the two types of calls we're substituting `textureNumLevels` and
+ /// `textureNumSamples` work on a disjoint set of texture types.
+ std::vector<BindingPoint> ubo_bindingpoint_ordering;
};
/// @copydoc ast::transform::Transform::Apply
diff --git a/src/tint/lang/glsl/writer/ast_raise/texture_builtins_from_uniform_test.cc b/src/tint/lang/glsl/writer/ast_raise/texture_builtins_from_uniform_test.cc
index cabe7e1..3ee9775 100644
--- a/src/tint/lang/glsl/writer/ast_raise/texture_builtins_from_uniform_test.cc
+++ b/src/tint/lang/glsl/writer/ast_raise/texture_builtins_from_uniform_test.cc
@@ -36,53 +36,6 @@
using TextureBuiltinsFromUniformTest = ast::transform::TransformTest;
-TEST_F(TextureBuiltinsFromUniformTest, ShouldRunEmptyModule) {
- auto* src = R"()";
-
- TextureBuiltinsFromUniform::Config cfg({0, 30u});
-
- ast::transform::DataMap data;
- data.Add<TextureBuiltinsFromUniform::Config>(std::move(cfg));
-
- EXPECT_FALSE(ShouldRun<TextureBuiltinsFromUniform>(src, data));
-}
-
-TEST_F(TextureBuiltinsFromUniformTest, ShouldRunNoTextureNumLevels) {
- auto* src = R"(
-@group(0) @binding(0) var t : texture_2d<f32>;
-
-@compute @workgroup_size(1)
-fn main() {
- _ = textureDimensions(t);
-}
-)";
-
- TextureBuiltinsFromUniform::Config cfg({0, 30u});
-
- ast::transform::DataMap data;
- data.Add<TextureBuiltinsFromUniform::Config>(std::move(cfg));
-
- EXPECT_FALSE(ShouldRun<TextureBuiltinsFromUniform>(src, data));
-}
-
-TEST_F(TextureBuiltinsFromUniformTest, ShouldRunWithTextureNumLevels) {
- auto* src = R"(
-@group(0) @binding(0) var t : texture_2d<f32>;
-
-@compute @workgroup_size(1)
-fn main() {
- var len : u32 = textureNumLevels(t);
-}
-)";
-
- TextureBuiltinsFromUniform::Config cfg({0, 30u});
-
- ast::transform::DataMap data;
- data.Add<TextureBuiltinsFromUniform::Config>(std::move(cfg));
-
- EXPECT_TRUE(ShouldRun<TextureBuiltinsFromUniform>(src, data));
-}
-
TEST_F(TextureBuiltinsFromUniformTest, Error_MissingTransformData) {
auto* src = R"(
@group(0) @binding(0) var t : texture_2d<f32>;
@@ -126,25 +79,14 @@
}
)";
- TextureBuiltinsFromUniform::Config cfg({0, 30u});
+ std::vector<BindingPoint> bps = {{0, 0}};
+ TextureBuiltinsFromUniform::Config cfg({0, 30u}, bps);
ast::transform::DataMap data;
data.Add<TextureBuiltinsFromUniform::Config>(std::move(cfg));
auto got = Run<TextureBuiltinsFromUniform>(src, data);
-
EXPECT_EQ(expect, str(got));
- auto* val = got.data.Get<TextureBuiltinsFromUniform::Result>();
- ASSERT_NE(val, nullptr);
- // Note: Using the following EXPECT_EQ directly on BindingPointToFieldAndOffset seems to cause
- // compiler to hang. EXPECT_EQ(
- // TextureBuiltinsFromUniformOptions::BindingPointToFieldAndOffset{
- // {BindgPoint{0u, 0u},
- // std::make_pair(TextureBuiltinsFromUniformOptions::Field::TextureNumLevels, 0u)}},
- // val->bindpoint_to_data);
- EXPECT_EQ(1u, val->bindpoint_to_data.size());
- EXPECT_EQ(std::make_pair(TextureBuiltinsFromUniformOptions::Field::TextureNumLevels, 0u),
- val->bindpoint_to_data.at(BindingPoint{0, 0}));
}
TEST_F(TextureBuiltinsFromUniformTest, BasicTextureNumSamples) {
@@ -172,19 +114,14 @@
}
)";
- TextureBuiltinsFromUniform::Config cfg({0, 30u});
+ std::vector<BindingPoint> bps = {{0, 0}};
+ TextureBuiltinsFromUniform::Config cfg({0, 30u}, bps);
ast::transform::DataMap data;
data.Add<TextureBuiltinsFromUniform::Config>(std::move(cfg));
auto got = Run<TextureBuiltinsFromUniform>(src, data);
-
EXPECT_EQ(expect, str(got));
- auto* val = got.data.Get<TextureBuiltinsFromUniform::Result>();
- ASSERT_NE(val, nullptr);
- EXPECT_EQ(1u, val->bindpoint_to_data.size());
- EXPECT_EQ(std::make_pair(TextureBuiltinsFromUniformOptions::Field::TextureNumSamples, 0u),
- val->bindpoint_to_data.at(BindingPoint{0, 0}));
}
TEST_F(TextureBuiltinsFromUniformTest, SameBuiltinCalledMultipleTimes) {
@@ -214,19 +151,14 @@
}
)";
- TextureBuiltinsFromUniform::Config cfg({0, 30u});
+ std::vector<BindingPoint> bps = {{0, 0}};
+ TextureBuiltinsFromUniform::Config cfg({0, 30u}, bps);
ast::transform::DataMap data;
data.Add<TextureBuiltinsFromUniform::Config>(std::move(cfg));
auto got = Run<TextureBuiltinsFromUniform>(src, data);
-
EXPECT_EQ(expect, str(got));
- auto* val = got.data.Get<TextureBuiltinsFromUniform::Result>();
- ASSERT_NE(val, nullptr);
- EXPECT_EQ(1u, val->bindpoint_to_data.size());
- EXPECT_EQ(std::make_pair(TextureBuiltinsFromUniformOptions::Field::TextureNumLevels, 0u),
- val->bindpoint_to_data.at(BindingPoint{0, 0}));
}
TEST_F(TextureBuiltinsFromUniformTest, SameBuiltinCalledMultipleTimesTextureNumSamples) {
@@ -256,19 +188,14 @@
}
)";
- TextureBuiltinsFromUniform::Config cfg({0, 30u});
+ std::vector<BindingPoint> bps = {{0, 0}};
+ TextureBuiltinsFromUniform::Config cfg({0, 30u}, bps);
ast::transform::DataMap data;
data.Add<TextureBuiltinsFromUniform::Config>(std::move(cfg));
auto got = Run<TextureBuiltinsFromUniform>(src, data);
-
EXPECT_EQ(expect, str(got));
- auto* val = got.data.Get<TextureBuiltinsFromUniform::Result>();
- ASSERT_NE(val, nullptr);
- EXPECT_EQ(1u, val->bindpoint_to_data.size());
- EXPECT_EQ(std::make_pair(TextureBuiltinsFromUniformOptions::Field::TextureNumSamples, 0u),
- val->bindpoint_to_data.at(BindingPoint{0, 0}));
}
TEST_F(TextureBuiltinsFromUniformTest, TextureAsFunctionParameterBasic) {
@@ -304,19 +231,14 @@
}
)";
- TextureBuiltinsFromUniform::Config cfg({0, 30u});
+ std::vector<BindingPoint> bps = {{0, 0}};
+ TextureBuiltinsFromUniform::Config cfg({0, 30u}, bps);
ast::transform::DataMap data;
data.Add<TextureBuiltinsFromUniform::Config>(std::move(cfg));
auto got = Run<TextureBuiltinsFromUniform>(src, data);
-
EXPECT_EQ(expect, str(got));
- auto* val = got.data.Get<TextureBuiltinsFromUniform::Result>();
- ASSERT_NE(val, nullptr);
- EXPECT_EQ(1u, val->bindpoint_to_data.size());
- EXPECT_EQ(std::make_pair(TextureBuiltinsFromUniformOptions::Field::TextureNumLevels, 0u),
- val->bindpoint_to_data.at(BindingPoint{0, 0}));
}
TEST_F(TextureBuiltinsFromUniformTest, TextureAsFunctionParameterUsedTwice) {
@@ -356,19 +278,14 @@
}
)";
- TextureBuiltinsFromUniform::Config cfg({0, 30u});
+ std::vector<BindingPoint> bps = {{0, 0}};
+ TextureBuiltinsFromUniform::Config cfg({0, 30u}, bps);
ast::transform::DataMap data;
data.Add<TextureBuiltinsFromUniform::Config>(std::move(cfg));
auto got = Run<TextureBuiltinsFromUniform>(src, data);
-
EXPECT_EQ(expect, str(got));
- auto* val = got.data.Get<TextureBuiltinsFromUniform::Result>();
- ASSERT_NE(val, nullptr);
- EXPECT_EQ(1u, val->bindpoint_to_data.size());
- EXPECT_EQ(std::make_pair(TextureBuiltinsFromUniformOptions::Field::TextureNumLevels, 0u),
- val->bindpoint_to_data.at(BindingPoint{0, 0}));
}
TEST_F(TextureBuiltinsFromUniformTest, TextureAsFunctionParameterMultipleParameters) {
@@ -412,23 +329,14 @@
}
)";
- TextureBuiltinsFromUniform::Config cfg({0, 30u});
+ std::vector<BindingPoint> bps = {{0, 0}, {0, 1}, {0, 2}};
+ TextureBuiltinsFromUniform::Config cfg({0, 30u}, bps);
ast::transform::DataMap data;
data.Add<TextureBuiltinsFromUniform::Config>(std::move(cfg));
auto got = Run<TextureBuiltinsFromUniform>(src, data);
-
EXPECT_EQ(expect, str(got));
- auto* val = got.data.Get<TextureBuiltinsFromUniform::Result>();
- ASSERT_NE(val, nullptr);
- EXPECT_EQ(3u, val->bindpoint_to_data.size());
- EXPECT_EQ(std::make_pair(TextureBuiltinsFromUniformOptions::Field::TextureNumLevels, 0u),
- val->bindpoint_to_data.at(BindingPoint{0, 0}));
- EXPECT_EQ(std::make_pair(TextureBuiltinsFromUniformOptions::Field::TextureNumLevels, 4u),
- val->bindpoint_to_data.at(BindingPoint{0, 1}));
- EXPECT_EQ(std::make_pair(TextureBuiltinsFromUniformOptions::Field::TextureNumLevels, 8u),
- val->bindpoint_to_data.at(BindingPoint{0, 2}));
}
TEST_F(TextureBuiltinsFromUniformTest, TextureAsFunctionParameterNested) {
@@ -472,19 +380,14 @@
}
)";
- TextureBuiltinsFromUniform::Config cfg({0, 30u});
+ std::vector<BindingPoint> bps = {{0, 0}};
+ TextureBuiltinsFromUniform::Config cfg({0, 30u}, bps);
ast::transform::DataMap data;
data.Add<TextureBuiltinsFromUniform::Config>(std::move(cfg));
auto got = Run<TextureBuiltinsFromUniform>(src, data);
-
EXPECT_EQ(expect, str(got));
- auto* val = got.data.Get<TextureBuiltinsFromUniform::Result>();
- ASSERT_NE(val, nullptr);
- EXPECT_EQ(1u, val->bindpoint_to_data.size());
- EXPECT_EQ(std::make_pair(TextureBuiltinsFromUniformOptions::Field::TextureNumLevels, 0u),
- val->bindpoint_to_data.at(BindingPoint{0, 0}));
}
TEST_F(TextureBuiltinsFromUniformTest, TextureAsFunctionParameterMixed) {
@@ -549,25 +452,14 @@
}
)";
- TextureBuiltinsFromUniform::Config cfg({0, 30u});
+ std::vector<BindingPoint> bps = {{0, 1}, {0, 3}, {0, 0}, {0, 2}};
+ TextureBuiltinsFromUniform::Config cfg({0, 30u}, bps);
ast::transform::DataMap data;
data.Add<TextureBuiltinsFromUniform::Config>(std::move(cfg));
auto got = Run<TextureBuiltinsFromUniform>(src, data);
-
EXPECT_EQ(expect, str(got));
- auto* val = got.data.Get<TextureBuiltinsFromUniform::Result>();
- ASSERT_NE(val, nullptr);
- EXPECT_EQ(4u, val->bindpoint_to_data.size());
- EXPECT_EQ(std::make_pair(TextureBuiltinsFromUniformOptions::Field::TextureNumLevels, 0u),
- val->bindpoint_to_data.at(BindingPoint{0, 1}));
- EXPECT_EQ(std::make_pair(TextureBuiltinsFromUniformOptions::Field::TextureNumLevels, 4u),
- val->bindpoint_to_data.at(BindingPoint{0, 3}));
- EXPECT_EQ(std::make_pair(TextureBuiltinsFromUniformOptions::Field::TextureNumLevels, 8u),
- val->bindpoint_to_data.at(BindingPoint{0, 0}));
- EXPECT_EQ(std::make_pair(TextureBuiltinsFromUniformOptions::Field::TextureNumLevels, 12u),
- val->bindpoint_to_data.at(BindingPoint{0, 2}));
}
TEST_F(TextureBuiltinsFromUniformTest, MultipleTextures) {
@@ -625,7 +517,8 @@
}
)";
- TextureBuiltinsFromUniform::Config cfg({0, 30u});
+ std::vector<BindingPoint> bps = {{0, 0}, {0, 1}, {0, 2}, {0, 3}, {0, 4}, {1, 0}};
+ TextureBuiltinsFromUniform::Config cfg({0, 30u}, bps);
ast::transform::DataMap data;
data.Add<TextureBuiltinsFromUniform::Config>(std::move(cfg));
@@ -633,21 +526,6 @@
auto got = Run<TextureBuiltinsFromUniform>(src, data);
EXPECT_EQ(expect, str(got));
- auto* val = got.data.Get<TextureBuiltinsFromUniform::Result>();
- ASSERT_NE(val, nullptr);
- EXPECT_EQ(6u, val->bindpoint_to_data.size());
- EXPECT_EQ(std::make_pair(TextureBuiltinsFromUniformOptions::Field::TextureNumLevels, 0u),
- val->bindpoint_to_data.at(BindingPoint{0, 0}));
- EXPECT_EQ(std::make_pair(TextureBuiltinsFromUniformOptions::Field::TextureNumSamples, 4u),
- val->bindpoint_to_data.at(BindingPoint{0, 1}));
- EXPECT_EQ(std::make_pair(TextureBuiltinsFromUniformOptions::Field::TextureNumLevels, 8u),
- val->bindpoint_to_data.at(BindingPoint{0, 2}));
- EXPECT_EQ(std::make_pair(TextureBuiltinsFromUniformOptions::Field::TextureNumLevels, 12u),
- val->bindpoint_to_data.at(BindingPoint{0, 3}));
- EXPECT_EQ(std::make_pair(TextureBuiltinsFromUniformOptions::Field::TextureNumLevels, 16u),
- val->bindpoint_to_data.at(BindingPoint{0, 4}));
- EXPECT_EQ(std::make_pair(TextureBuiltinsFromUniformOptions::Field::TextureNumSamples, 20u),
- val->bindpoint_to_data.at(BindingPoint{1, 0}));
}
TEST_F(TextureBuiltinsFromUniformTest, BindingPointExist) {
@@ -682,7 +560,8 @@
}
)";
- TextureBuiltinsFromUniform::Config cfg({0, 30u});
+ std::vector<BindingPoint> bps = {{0, 0}};
+ TextureBuiltinsFromUniform::Config cfg({0, 30u}, bps);
ast::transform::DataMap data;
data.Add<TextureBuiltinsFromUniform::Config>(std::move(cfg));
@@ -690,10 +569,6 @@
auto got = Run<TextureBuiltinsFromUniform>(src, data);
EXPECT_EQ(expect, str(got));
- auto* val = got.data.Get<TextureBuiltinsFromUniform::Result>();
- ASSERT_NE(val, nullptr);
- EXPECT_EQ(std::make_pair(TextureBuiltinsFromUniformOptions::Field::TextureNumLevels, 0u),
- val->bindpoint_to_data.at(BindingPoint{0, 0}));
}
} // namespace
diff --git a/src/tint/lang/glsl/writer/common/BUILD.bazel b/src/tint/lang/glsl/writer/common/BUILD.bazel
index 1a61a9b..71f4677 100644
--- a/src/tint/lang/glsl/writer/common/BUILD.bazel
+++ b/src/tint/lang/glsl/writer/common/BUILD.bazel
@@ -50,7 +50,6 @@
deps = [
"//src/tint/api/common",
"//src/tint/api/options",
- "//src/tint/lang/core",
"//src/tint/lang/wgsl/sem",
"//src/tint/utils/macros",
"//src/tint/utils/math",
diff --git a/src/tint/lang/glsl/writer/common/BUILD.cmake b/src/tint/lang/glsl/writer/common/BUILD.cmake
index 8c176fe..a015049 100644
--- a/src/tint/lang/glsl/writer/common/BUILD.cmake
+++ b/src/tint/lang/glsl/writer/common/BUILD.cmake
@@ -51,7 +51,6 @@
tint_target_add_dependencies(tint_lang_glsl_writer_common lib
tint_api_common
tint_api_options
- tint_lang_core
tint_lang_wgsl_sem
tint_utils_macros
tint_utils_math
diff --git a/src/tint/lang/glsl/writer/common/BUILD.gn b/src/tint/lang/glsl/writer/common/BUILD.gn
index a91c610..e833eb3 100644
--- a/src/tint/lang/glsl/writer/common/BUILD.gn
+++ b/src/tint/lang/glsl/writer/common/BUILD.gn
@@ -49,7 +49,6 @@
deps = [
"${tint_src_dir}/api/common",
"${tint_src_dir}/api/options",
- "${tint_src_dir}/lang/core",
"${tint_src_dir}/lang/wgsl/sem",
"${tint_src_dir}/utils/macros",
"${tint_src_dir}/utils/math",
diff --git a/src/tint/lang/glsl/writer/common/options.h b/src/tint/lang/glsl/writer/common/options.h
index b795d10..1f5298f 100644
--- a/src/tint/lang/glsl/writer/common/options.h
+++ b/src/tint/lang/glsl/writer/common/options.h
@@ -35,7 +35,6 @@
#include "src/tint/api/options/binding_remapper.h"
#include "src/tint/api/options/external_texture.h"
#include "src/tint/api/options/texture_builtins_from_uniform.h"
-#include "src/tint/lang/core/access.h"
#include "src/tint/lang/glsl/writer/common/version.h"
#include "src/tint/lang/wgsl/sem/sampler_texture_pair.h"
@@ -80,10 +79,13 @@
/// Options used in the binding mappings for external textures
ExternalTextureOptions external_texture_options = {};
+ /// Offset of the firstInstance push constant.
+ std::optional<int32_t> first_instance_offset;
+
/// Options used to map WGSL textureNumLevels/textureNumSamples builtins to internal uniform
/// buffer values. If not specified, emits corresponding GLSL builtins
/// textureQueryLevels/textureSamples directly.
- std::optional<TextureBuiltinsFromUniformOptions> texture_builtins_from_uniform = std::nullopt;
+ TextureBuiltinsFromUniformOptions texture_builtins_from_uniform = {};
/// Reflect the fields of this class so that it can be used by tint::ForeachField()
TINT_REFLECT(disable_robustness,
diff --git a/src/tint/lang/glsl/writer/output.h b/src/tint/lang/glsl/writer/output.h
index bb52015..8f205d1 100644
--- a/src/tint/lang/glsl/writer/output.h
+++ b/src/tint/lang/glsl/writer/output.h
@@ -32,7 +32,6 @@
#include <utility>
#include <vector>
-#include "src/tint/api/options/texture_builtins_from_uniform.h"
#include "src/tint/lang/wgsl/ast/pipeline_stage.h"
namespace tint::glsl::writer {
@@ -50,13 +49,6 @@
/// The generated GLSL.
std::string glsl = "";
-
- /// True if the shader needs a UBO.
- bool needs_internal_uniform_buffer = false;
-
- /// Store a map of global texture variable binding points to the byte offset and data type to
- /// push into the internal uniform buffer.
- TextureBuiltinsFromUniformOptions::BindingPointToFieldAndOffset bindpoint_to_data;
};
} // namespace tint::glsl::writer
diff --git a/src/tint/lang/glsl/writer/writer.cc b/src/tint/lang/glsl/writer/writer.cc
index c1ff290..17bd7ef 100644
--- a/src/tint/lang/glsl/writer/writer.cc
+++ b/src/tint/lang/glsl/writer/writer.cc
@@ -76,8 +76,6 @@
}
output.glsl = impl->Result();
- output.needs_internal_uniform_buffer = sanitized_result.needs_internal_uniform_buffer;
- output.bindpoint_to_data = std::move(sanitized_result.bindpoint_to_data);
return output;
}
diff --git a/src/tint/lang/hlsl/writer/ast_printer/assign_test.cc b/src/tint/lang/hlsl/writer/ast_printer/assign_test.cc
index 40384c2..f2734ca 100644
--- a/src/tint/lang/hlsl/writer/ast_printer/assign_test.cc
+++ b/src/tint/lang/hlsl/writer/ast_printer/assign_test.cc
@@ -69,15 +69,15 @@
ASSERT_TRUE(gen.Generate());
EXPECT_EQ(gen.Result(),
- R"(void set_float3(inout float3 vec, int idx, float val) {
+ R"(void set_vector_element(inout float3 vec, int idx, float val) {
vec = (idx.xxx == int3(0, 1, 2)) ? val.xxx : vec;
}
void fn() {
float3 lhs = float3(0.0f, 0.0f, 0.0f);
float rhs = 0.0f;
- const uint index = 0u;
- set_float3(lhs, index, rhs);
+ uint index = 0u;
+ set_vector_element(lhs, index, rhs);
}
)");
}
@@ -116,7 +116,7 @@
ASSERT_TRUE(gen.Generate());
EXPECT_EQ(gen.Result(),
- R"(void set_float3(inout float3 vec, int idx, float val) {
+ R"(void set_vector_element(inout float3 vec, int idx, float val) {
vec = (idx.xxx == int3(0, 1, 2)) ? val.xxx : vec;
}
@@ -124,7 +124,7 @@
float3 lhs = float3(0.0f, 0.0f, 0.0f);
float rhs = 0.0f;
uint index = 0u;
- set_float3(lhs, index, rhs);
+ set_vector_element(lhs, index, rhs);
}
)");
}
@@ -142,7 +142,7 @@
ASSERT_TRUE(gen.Generate());
EXPECT_EQ(gen.Result(),
- R"(void set_vector_float4x2(inout float4x2 mat, int col, float2 val) {
+ R"(void set_matrix_column(inout float4x2 mat, int col, float2 val) {
switch (col) {
case 0: mat[0] = val; break;
case 1: mat[1] = val; break;
@@ -154,8 +154,8 @@
void fn() {
float4x2 lhs = float4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
float2 rhs = float2(0.0f, 0.0f);
- const uint index = 0u;
- set_vector_float4x2(lhs, index, rhs);
+ uint index = 0u;
+ set_matrix_column(lhs, index, rhs);
}
)");
}
@@ -194,7 +194,7 @@
ASSERT_TRUE(gen.Generate());
EXPECT_EQ(gen.Result(),
- R"(void set_vector_float4x2(inout float4x2 mat, int col, float2 val) {
+ R"(void set_matrix_column(inout float4x2 mat, int col, float2 val) {
switch (col) {
case 0: mat[0] = val; break;
case 1: mat[1] = val; break;
@@ -207,7 +207,7 @@
float4x2 lhs = float4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
float2 rhs = float2(0.0f, 0.0f);
uint index = 0u;
- set_vector_float4x2(lhs, index, rhs);
+ set_matrix_column(lhs, index, rhs);
}
)");
}
@@ -228,7 +228,7 @@
ASSERT_TRUE(gen.Generate());
EXPECT_EQ(gen.Result(),
- R"(void set_scalar_float4x2(inout float4x2 mat, int col, int row, float val) {
+ R"(void set_matrix_scalar(inout float4x2 mat, int col, int row, float val) {
switch (col) {
case 0:
mat[0] = (row.xx == int2(0, 1)) ? val.xx : mat[0];
@@ -248,9 +248,9 @@
void fn() {
float4x2 lhs = float4x2(0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f);
float rhs = 0.0f;
- const uint col = 0u;
- const uint row = 1u;
- set_scalar_float4x2(lhs, col, row, rhs);
+ uint col = 0u;
+ uint row = 1u;
+ set_matrix_scalar(lhs, col, row, rhs);
}
)");
}
@@ -295,7 +295,7 @@
ASSERT_TRUE(gen.Generate());
EXPECT_EQ(gen.Result(),
- R"(void set_scalar_float4x2(inout float4x2 mat, int col, int row, float val) {
+ R"(void set_matrix_scalar(inout float4x2 mat, int col, int row, float val) {
switch (col) {
case 0:
mat[0] = (row.xx == int2(0, 1)) ? val.xx : mat[0];
@@ -317,7 +317,119 @@
float rhs = 0.0f;
uint col = 0u;
uint row = 0u;
- set_scalar_float4x2(lhs, col, row, rhs);
+ set_matrix_scalar(lhs, col, row, rhs);
+}
+)");
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Assignment to composites of f16
+// See crbug.com/tint/2146
+////////////////////////////////////////////////////////////////////////////////
+TEST_F(HlslASTPrinterTest_Assign, Emit_Vector_f16_Assign) {
+ Enable(wgsl::Extension::kF16);
+
+ Func("fn", tint::Empty, ty.void_(),
+ Vector{
+ Decl(Var("lhs", ty.vec3<f16>())),
+ Decl(Var("rhs", ty.f16())),
+ Decl(Let("index", ty.u32(), Expr(0_u))),
+ Assign(IndexAccessor("lhs", "index"), "rhs"),
+ });
+
+ ASTPrinter& gen = Build();
+
+ ASSERT_TRUE(gen.Generate());
+ EXPECT_EQ(gen.Result(),
+ R"(void set_vector_element(inout vector<float16_t, 3> vec, int idx, float16_t val) {
+ vec = (idx.xxx == int3(0, 1, 2)) ? val.xxx : vec;
+}
+
+void fn() {
+ vector<float16_t, 3> lhs = vector<float16_t, 3>(float16_t(0.0h), float16_t(0.0h), float16_t(0.0h));
+ float16_t rhs = float16_t(0.0h);
+ uint index = 0u;
+ set_vector_element(lhs, index, rhs);
+}
+)");
+}
+
+TEST_F(HlslASTPrinterTest_Assign, Emit_Matrix_f16_Assign_Vector) {
+ Enable(wgsl::Extension::kF16);
+
+ Func("fn", tint::Empty, ty.void_(),
+ Vector{
+ Decl(Var("lhs", ty.mat4x2<f16>())),
+ Decl(Var("rhs", ty.vec2<f16>())),
+ Decl(Let("index", ty.u32(), Expr(0_u))),
+ Assign(IndexAccessor("lhs", "index"), "rhs"),
+ });
+
+ ASTPrinter& gen = Build();
+
+ ASSERT_TRUE(gen.Generate());
+ EXPECT_EQ(
+ gen.Result(),
+ R"(void set_matrix_column(inout matrix<float16_t, 4, 2> mat, int col, vector<float16_t, 2> val) {
+ switch (col) {
+ case 0: mat[0] = val; break;
+ case 1: mat[1] = val; break;
+ case 2: mat[2] = val; break;
+ case 3: mat[3] = val; break;
+ }
+}
+
+void fn() {
+ matrix<float16_t, 4, 2> lhs = matrix<float16_t, 4, 2>(float16_t(0.0h), float16_t(0.0h), float16_t(0.0h), float16_t(0.0h), float16_t(0.0h), float16_t(0.0h), float16_t(0.0h), float16_t(0.0h));
+ vector<float16_t, 2> rhs = vector<float16_t, 2>(float16_t(0.0h), float16_t(0.0h));
+ uint index = 0u;
+ set_matrix_column(lhs, index, rhs);
+}
+)");
+}
+
+TEST_F(HlslASTPrinterTest_Assign, Emit_Matrix_f16_Assign_Scalar) {
+ Enable(wgsl::Extension::kF16);
+
+ auto* col = IndexAccessor("lhs", "col");
+ auto* el = IndexAccessor(col, "row");
+ Func("fn", tint::Empty, ty.void_(),
+ Vector{
+ Decl(Var("lhs", ty.mat4x2<f16>())),
+ Decl(Var("rhs", ty.f16())),
+ Decl(Let("col", ty.u32(), Expr(0_u))),
+ Decl(Let("row", ty.u32(), Expr(1_u))),
+ Assign(el, "rhs"),
+ });
+
+ ASTPrinter& gen = Build();
+
+ ASSERT_TRUE(gen.Generate());
+ EXPECT_EQ(
+ gen.Result(),
+ R"(void set_matrix_scalar(inout matrix<float16_t, 4, 2> mat, int col, int row, float16_t val) {
+ switch (col) {
+ case 0:
+ mat[0] = (row.xx == int2(0, 1)) ? val.xx : mat[0];
+ break;
+ case 1:
+ mat[1] = (row.xx == int2(0, 1)) ? val.xx : mat[1];
+ break;
+ case 2:
+ mat[2] = (row.xx == int2(0, 1)) ? val.xx : mat[2];
+ break;
+ case 3:
+ mat[3] = (row.xx == int2(0, 1)) ? val.xx : mat[3];
+ break;
+ }
+}
+
+void fn() {
+ matrix<float16_t, 4, 2> lhs = matrix<float16_t, 4, 2>(float16_t(0.0h), float16_t(0.0h), float16_t(0.0h), float16_t(0.0h), float16_t(0.0h), float16_t(0.0h), float16_t(0.0h), float16_t(0.0h));
+ float16_t rhs = float16_t(0.0h);
+ uint col = 0u;
+ uint row = 1u;
+ set_matrix_scalar(lhs, col, row, rhs);
}
)");
}
diff --git a/src/tint/lang/hlsl/writer/ast_printer/ast_printer.cc b/src/tint/lang/hlsl/writer/ast_printer/ast_printer.cc
index d6eec1a..9070b70 100644
--- a/src/tint/lang/hlsl/writer/ast_printer/ast_printer.cc
+++ b/src/tint/lang/hlsl/writer/ast_printer/ast_printer.cc
@@ -425,9 +425,9 @@
[&](const ast::Struct* str) {
auto* ty = builder_.Sem().Get(str);
auto address_space_uses = ty->AddressSpaceUsage();
- if (address_space_uses.size() !=
- (address_space_uses.count(core::AddressSpace::kStorage) +
- address_space_uses.count(core::AddressSpace::kUniform))) {
+ if (address_space_uses.Count() !=
+ ((address_space_uses.Contains(core::AddressSpace::kStorage) ? 1u : 0u) +
+ (address_space_uses.Contains(core::AddressSpace::kUniform) ? 1u : 0u))) {
// The structure is used as something other than a storage buffer or
// uniform buffer, so it needs to be emitted.
// Storage buffer are read and written to via a ByteAddressBuffer
@@ -461,15 +461,7 @@
bool ASTPrinter::EmitDynamicVectorAssignment(const ast::AssignmentStatement* stmt,
const core::type::Vector* vec) {
auto name = tint::GetOrCreate(dynamic_vector_write_, vec, [&]() -> std::string {
- std::string fn;
- {
- StringStream ss;
- if (!EmitType(ss, vec, tint::core::AddressSpace::kUndefined, core::Access::kUndefined,
- "")) {
- return "";
- }
- fn = UniqueIdentifier("set_" + ss.str());
- }
+ std::string fn = UniqueIdentifier("set_vector_element");
{
auto out = Line(&helpers_);
out << "void " << fn << "(inout ";
@@ -534,15 +526,7 @@
bool ASTPrinter::EmitDynamicMatrixVectorAssignment(const ast::AssignmentStatement* stmt,
const core::type::Matrix* mat) {
auto name = tint::GetOrCreate(dynamic_matrix_vector_write_, mat, [&]() -> std::string {
- std::string fn;
- {
- StringStream ss;
- if (!EmitType(ss, mat, tint::core::AddressSpace::kUndefined, core::Access::kUndefined,
- "")) {
- return "";
- }
- fn = UniqueIdentifier("set_vector_" + ss.str());
- }
+ std::string fn = UniqueIdentifier("set_matrix_column");
{
auto out = Line(&helpers_);
out << "void " << fn << "(inout ";
@@ -603,15 +587,7 @@
auto* lhs_col_access = lhs_row_access->object->As<ast::IndexAccessorExpression>();
auto name = tint::GetOrCreate(dynamic_matrix_scalar_write_, mat, [&]() -> std::string {
- std::string fn;
- {
- StringStream ss;
- if (!EmitType(ss, mat, tint::core::AddressSpace::kUndefined, core::Access::kUndefined,
- "")) {
- return "";
- }
- fn = UniqueIdentifier("set_scalar_" + ss.str());
- }
+ std::string fn = UniqueIdentifier("set_matrix_scalar");
{
auto out = Line(&helpers_);
out << "void " << fn << "(inout ";
@@ -4578,21 +4554,22 @@
if (auto location = attributes.location) {
auto& pipeline_stage_uses = str->PipelineStageUses();
- if (TINT_UNLIKELY(pipeline_stage_uses.size() != 1)) {
+ if (TINT_UNLIKELY(pipeline_stage_uses.Count() != 1)) {
TINT_ICE() << "invalid entry point IO struct uses";
}
- if (pipeline_stage_uses.count(core::type::PipelineStageUsage::kVertexInput)) {
+ if (pipeline_stage_uses.Contains(core::type::PipelineStageUsage::kVertexInput)) {
post += " : TEXCOORD" + std::to_string(location.value());
- } else if (pipeline_stage_uses.count(
+ } else if (pipeline_stage_uses.Contains(
core::type::PipelineStageUsage::kVertexOutput)) {
post += " : TEXCOORD" + std::to_string(location.value());
- } else if (pipeline_stage_uses.count(
+ } else if (pipeline_stage_uses.Contains(
core::type::PipelineStageUsage::kFragmentInput)) {
post += " : TEXCOORD" + std::to_string(location.value());
- } else if (TINT_LIKELY(pipeline_stage_uses.count(
+ } else if (TINT_LIKELY(pipeline_stage_uses.Contains(
core::type::PipelineStageUsage::kFragmentOutput))) {
- if (auto index = attributes.index) {
- post += " : SV_Target" + std::to_string(location.value() + index.value());
+ if (auto blend_src = attributes.blend_src) {
+ post +=
+ " : SV_Target" + std::to_string(location.value() + blend_src.value());
} else {
post += " : SV_Target" + std::to_string(location.value());
}
@@ -4688,41 +4665,11 @@
return true;
}
-bool ASTPrinter::IsStructOrArrayOfMatrix(const core::type::Type* ty) {
- if (!ty->IsAnyOf<core::type::Struct, core::type::Array>()) {
- return false;
- }
- return GetOrCreate(is_struct_or_array_of_matrix_, ty, [&]() {
- Vector<const core::type::Type*, 4> to_visit({ty});
- while (!to_visit.IsEmpty()) {
- auto* curr = to_visit.Pop();
- if (curr->Is<core::type::Matrix>()) {
- return true;
- }
- auto [child_ty, child_count] = curr->Elements();
- if (child_ty) {
- to_visit.Push(child_ty);
- } else {
- for (uint32_t i = 0; i < child_count; ++i) {
- to_visit.Push(curr->Element(i));
- }
- }
- }
- return false;
- });
-}
-
bool ASTPrinter::EmitLet(const ast::Let* let) {
auto* sem = builder_.Sem().Get(let);
auto* type = sem->Type()->UnwrapRef();
auto out = Line();
-
- // TODO(crbug.com/tint/2059): Workaround DXC bug with const instances of struct/array-of-matrix.
- if (!IsStructOrArrayOfMatrix(type)) {
- out << "const ";
- }
-
if (!EmitTypeAndName(out, type, core::AddressSpace::kUndefined, core::Access::kUndefined,
let->name->symbol.Name())) {
return false;
diff --git a/src/tint/lang/hlsl/writer/ast_printer/ast_printer.h b/src/tint/lang/hlsl/writer/ast_printer/ast_printer.h
index 3d14eac..9e60718 100644
--- a/src/tint/lang/hlsl/writer/ast_printer/ast_printer.h
+++ b/src/tint/lang/hlsl/writer/ast_printer/ast_printer.h
@@ -596,10 +596,6 @@
return builder_.TypeOf(ptr);
}
- /// @return true if ty is a struct or array with a matrix member (recursively), false otherwise.
- /// @param ty the type that will be queried.
- bool IsStructOrArrayOfMatrix(const core::type::Type* ty);
-
ProgramBuilder builder_;
/// Helper functions emitted at the top of the output
@@ -618,7 +614,6 @@
std::unordered_map<const core::type::Matrix*, std::string> dynamic_matrix_scalar_write_;
std::unordered_map<const core::type::Type*, std::string> value_or_one_if_zero_;
std::unordered_set<const core::type::Struct*> emitted_structs_;
- std::unordered_map<const core::type::Type*, bool> is_struct_or_array_of_matrix_;
// The line index in current_buffer_ of the current global declaration / function.
size_t global_insertion_point_ = 0;
diff --git a/src/tint/lang/hlsl/writer/ast_printer/bitcast_test.cc b/src/tint/lang/hlsl/writer/ast_printer/bitcast_test.cc
index 8c5b101..bb89d6f 100644
--- a/src/tint/lang/hlsl/writer/ast_printer/bitcast_test.cc
+++ b/src/tint/lang/hlsl/writer/ast_printer/bitcast_test.cc
@@ -128,13 +128,13 @@
[numthreads(1, 1, 1)]
void test_function() {
- const vector<float16_t, 2> a = vector<float16_t, 2>(float16_t(1.0h), float16_t(2.0h));
- const int b = tint_bitcast_from_f16(a);
- const vector<float16_t, 2> c = tint_bitcast_to_f16(b);
- const float d = tint_bitcast_from_f16_1(c);
- const vector<float16_t, 2> e = tint_bitcast_to_f16_1(d);
- const uint f = tint_bitcast_from_f16_2(e);
- const vector<float16_t, 2> g = tint_bitcast_to_f16_2(f);
+ vector<float16_t, 2> a = vector<float16_t, 2>(float16_t(1.0h), float16_t(2.0h));
+ int b = tint_bitcast_from_f16(a);
+ vector<float16_t, 2> c = tint_bitcast_to_f16(b);
+ float d = tint_bitcast_from_f16_1(c);
+ vector<float16_t, 2> e = tint_bitcast_to_f16_1(d);
+ uint f = tint_bitcast_from_f16_2(e);
+ vector<float16_t, 2> g = tint_bitcast_to_f16_2(f);
return;
}
)");
@@ -194,13 +194,13 @@
[numthreads(1, 1, 1)]
void test_function() {
- const vector<float16_t, 4> a = vector<float16_t, 4>(float16_t(1.0h), float16_t(2.0h), float16_t(3.0h), float16_t(4.0h));
- const int2 b = tint_bitcast_from_f16(a);
- const vector<float16_t, 4> c = tint_bitcast_to_f16(b);
- const float2 d = tint_bitcast_from_f16_1(c);
- const vector<float16_t, 4> e = tint_bitcast_to_f16_1(d);
- const uint2 f = tint_bitcast_from_f16_2(e);
- const vector<float16_t, 4> g = tint_bitcast_to_f16_2(f);
+ vector<float16_t, 4> a = vector<float16_t, 4>(float16_t(1.0h), float16_t(2.0h), float16_t(3.0h), float16_t(4.0h));
+ int2 b = tint_bitcast_from_f16(a);
+ vector<float16_t, 4> c = tint_bitcast_to_f16(b);
+ float2 d = tint_bitcast_from_f16_1(c);
+ vector<float16_t, 4> e = tint_bitcast_to_f16_1(d);
+ uint2 f = tint_bitcast_from_f16_2(e);
+ vector<float16_t, 4> g = tint_bitcast_to_f16_2(f);
return;
}
)");
diff --git a/src/tint/lang/hlsl/writer/ast_printer/builtin_test.cc b/src/tint/lang/hlsl/writer/ast_printer/builtin_test.cc
index 803be81..00788ed 100644
--- a/src/tint/lang/hlsl/writer/ast_printer/builtin_test.cc
+++ b/src/tint/lang/hlsl/writer/ast_printer/builtin_test.cc
@@ -407,8 +407,8 @@
[numthreads(1, 1, 1)]
void test_function() {
- const float f = 1.5f;
- const modf_result_f32 v = tint_modf(f);
+ float f = 1.5f;
+ modf_result_f32 v = tint_modf(f);
return;
}
)");
@@ -435,8 +435,8 @@
[numthreads(1, 1, 1)]
void test_function() {
- const float16_t f = float16_t(1.5h);
- const modf_result_f16 v = tint_modf(f);
+ float16_t f = float16_t(1.5h);
+ modf_result_f16 v = tint_modf(f);
return;
}
)");
@@ -461,8 +461,8 @@
[numthreads(1, 1, 1)]
void test_function() {
- const float3 f = float3(1.5f, 2.5f, 3.5f);
- const modf_result_vec3_f32 v = tint_modf(f);
+ float3 f = float3(1.5f, 2.5f, 3.5f);
+ modf_result_vec3_f32 v = tint_modf(f);
return;
}
)");
@@ -489,8 +489,8 @@
[numthreads(1, 1, 1)]
void test_function() {
- const vector<float16_t, 3> f = vector<float16_t, 3>(float16_t(1.5h), float16_t(2.5h), float16_t(3.5h));
- const modf_result_vec3_f16 v = tint_modf(f);
+ vector<float16_t, 3> f = vector<float16_t, 3>(float16_t(1.5h), float16_t(2.5h), float16_t(3.5h));
+ modf_result_vec3_f16 v = tint_modf(f);
return;
}
)");
@@ -508,7 +508,7 @@
};
[numthreads(1, 1, 1)]
void test_function() {
- const modf_result_f32 v = {0.5f, 1.0f};
+ modf_result_f32 v = {0.5f, 1.0f};
return;
}
)");
@@ -528,7 +528,7 @@
};
[numthreads(1, 1, 1)]
void test_function() {
- const modf_result_f16 v = {float16_t(0.5h), float16_t(1.0h)};
+ modf_result_f16 v = {float16_t(0.5h), float16_t(1.0h)};
return;
}
)");
@@ -546,7 +546,7 @@
};
[numthreads(1, 1, 1)]
void test_function() {
- const modf_result_vec3_f32 v = {(0.5f).xxx, float3(1.0f, 2.0f, 3.0f)};
+ modf_result_vec3_f32 v = {(0.5f).xxx, float3(1.0f, 2.0f, 3.0f)};
return;
}
)");
@@ -566,7 +566,7 @@
};
[numthreads(1, 1, 1)]
void test_function() {
- const modf_result_vec3_f16 v = {(float16_t(0.5h)).xxx, vector<float16_t, 3>(float16_t(1.0h), float16_t(2.0h), float16_t(3.0h))};
+ modf_result_vec3_f16 v = {(float16_t(0.5h)).xxx, vector<float16_t, 3>(float16_t(1.0h), float16_t(2.0h), float16_t(3.0h))};
return;
}
)");
@@ -722,7 +722,7 @@
};
[numthreads(1, 1, 1)]
void test_function() {
- const frexp_result_f32 v = {0.5f, 1};
+ frexp_result_f32 v = {0.5f, 1};
return;
}
)");
@@ -742,7 +742,7 @@
};
[numthreads(1, 1, 1)]
void test_function() {
- const frexp_result_f16 v = {float16_t(0.5h), 1};
+ frexp_result_f16 v = {float16_t(0.5h), 1};
return;
}
)");
@@ -760,7 +760,7 @@
};
[numthreads(1, 1, 1)]
void test_function() {
- const frexp_result_vec3_f32 v = (frexp_result_vec3_f32)0;
+ frexp_result_vec3_f32 v = (frexp_result_vec3_f32)0;
return;
}
)");
@@ -780,7 +780,7 @@
};
[numthreads(1, 1, 1)]
void test_function() {
- const frexp_result_vec3_f16 v = (frexp_result_vec3_f16)0;
+ frexp_result_vec3_f16 v = (frexp_result_vec3_f16)0;
return;
}
)");
@@ -827,7 +827,7 @@
[numthreads(1, 1, 1)]
void test_function() {
float val = 0.0f;
- const float tint_symbol = tint_degrees(val);
+ float tint_symbol = tint_degrees(val);
return;
}
)");
@@ -848,7 +848,7 @@
[numthreads(1, 1, 1)]
void test_function() {
float3 val = float3(0.0f, 0.0f, 0.0f);
- const float3 tint_symbol = tint_degrees(val);
+ float3 tint_symbol = tint_degrees(val);
return;
}
)");
@@ -871,7 +871,7 @@
[numthreads(1, 1, 1)]
void test_function() {
float16_t val = float16_t(0.0h);
- const float16_t tint_symbol = tint_degrees(val);
+ float16_t tint_symbol = tint_degrees(val);
return;
}
)");
@@ -894,7 +894,7 @@
[numthreads(1, 1, 1)]
void test_function() {
vector<float16_t, 3> val = vector<float16_t, 3>(float16_t(0.0h), float16_t(0.0h), float16_t(0.0h));
- const vector<float16_t, 3> tint_symbol = tint_degrees(val);
+ vector<float16_t, 3> tint_symbol = tint_degrees(val);
return;
}
)");
@@ -915,7 +915,7 @@
[numthreads(1, 1, 1)]
void test_function() {
float val = 0.0f;
- const float tint_symbol = tint_radians(val);
+ float tint_symbol = tint_radians(val);
return;
}
)");
@@ -936,7 +936,7 @@
[numthreads(1, 1, 1)]
void test_function() {
float3 val = float3(0.0f, 0.0f, 0.0f);
- const float3 tint_symbol = tint_radians(val);
+ float3 tint_symbol = tint_radians(val);
return;
}
)");
@@ -959,7 +959,7 @@
[numthreads(1, 1, 1)]
void test_function() {
float16_t val = float16_t(0.0h);
- const float16_t tint_symbol = tint_radians(val);
+ float16_t tint_symbol = tint_radians(val);
return;
}
)");
@@ -982,7 +982,7 @@
[numthreads(1, 1, 1)]
void test_function() {
vector<float16_t, 3> val = vector<float16_t, 3>(float16_t(0.0h), float16_t(0.0h), float16_t(0.0h));
- const vector<float16_t, 3> tint_symbol = tint_radians(val);
+ vector<float16_t, 3> tint_symbol = tint_radians(val);
return;
}
)");
@@ -999,7 +999,7 @@
EXPECT_EQ(gen.Result(), R"([numthreads(1, 1, 1)]
void test_function() {
int val = 0;
- const int tint_symbol = int(sign(val));
+ int tint_symbol = int(sign(val));
return;
}
)");
@@ -1016,7 +1016,7 @@
EXPECT_EQ(gen.Result(), R"([numthreads(1, 1, 1)]
void test_function() {
int3 val = int3(0, 0, 0);
- const int3 tint_symbol = int3(sign(val));
+ int3 tint_symbol = int3(sign(val));
return;
}
)");
@@ -1033,7 +1033,7 @@
EXPECT_EQ(gen.Result(), R"([numthreads(1, 1, 1)]
void test_function() {
float val = 0.0f;
- const float tint_symbol = float(sign(val));
+ float tint_symbol = float(sign(val));
return;
}
)");
@@ -1050,7 +1050,7 @@
EXPECT_EQ(gen.Result(), R"([numthreads(1, 1, 1)]
void test_function() {
float3 val = float3(0.0f, 0.0f, 0.0f);
- const float3 tint_symbol = float3(sign(val));
+ float3 tint_symbol = float3(sign(val));
return;
}
)");
@@ -1069,7 +1069,7 @@
EXPECT_EQ(gen.Result(), R"([numthreads(1, 1, 1)]
void test_function() {
float16_t val = float16_t(0.0h);
- const float16_t tint_symbol = float16_t(sign(val));
+ float16_t tint_symbol = float16_t(sign(val));
return;
}
)");
@@ -1088,7 +1088,7 @@
EXPECT_EQ(gen.Result(), R"([numthreads(1, 1, 1)]
void test_function() {
vector<float16_t, 3> val = vector<float16_t, 3>(float16_t(0.0h), float16_t(0.0h), float16_t(0.0h));
- const vector<float16_t, 3> tint_symbol = vector<float16_t, 3>(sign(val));
+ vector<float16_t, 3> tint_symbol = vector<float16_t, 3>(sign(val));
return;
}
)");
@@ -1109,7 +1109,7 @@
[numthreads(1, 1, 1)]
void test_function() {
float val = 0.0f;
- const float tint_symbol = tint_trunc(val);
+ float tint_symbol = tint_trunc(val);
return;
}
)");
@@ -1130,7 +1130,7 @@
[numthreads(1, 1, 1)]
void test_function() {
float3 val = float3(0.0f, 0.0f, 0.0f);
- const float3 tint_symbol = tint_trunc(val);
+ float3 tint_symbol = tint_trunc(val);
return;
}
)");
@@ -1153,7 +1153,7 @@
[numthreads(1, 1, 1)]
void test_function() {
float16_t val = float16_t(0.0h);
- const float16_t tint_symbol = tint_trunc(val);
+ float16_t tint_symbol = tint_trunc(val);
return;
}
)");
@@ -1176,7 +1176,7 @@
[numthreads(1, 1, 1)]
void test_function() {
vector<float16_t, 3> val = vector<float16_t, 3>(float16_t(0.0h), float16_t(0.0h), float16_t(0.0h));
- const vector<float16_t, 3> tint_symbol = tint_trunc(val);
+ vector<float16_t, 3> tint_symbol = tint_trunc(val);
return;
}
)");
@@ -1468,7 +1468,7 @@
void test_function() {
uint val1 = 0u;
uint val2 = 0u;
- const int tint_symbol = tint_dot4I8Packed(val1, val2);
+ int tint_symbol = tint_dot4I8Packed(val1, val2);
return;
}
)");
@@ -1494,7 +1494,7 @@
void test_function() {
uint val1 = 0u;
uint val2 = 0u;
- const uint tint_symbol = tint_dot4U8Packed(val1, val2);
+ uint tint_symbol = tint_dot4U8Packed(val1, val2);
return;
}
)");
@@ -1511,7 +1511,7 @@
EXPECT_EQ(gen.Result(), R"([numthreads(1, 1, 1)]
void test_function() {
int val1 = 0;
- const int tint_symbol = asint(countbits(asuint(val1)));
+ int tint_symbol = asint(countbits(asuint(val1)));
return;
}
)");
@@ -1528,7 +1528,7 @@
EXPECT_EQ(gen.Result(), R"([numthreads(1, 1, 1)]
void test_function() {
int val1 = 0;
- const int tint_symbol = asint(reversebits(asuint(val1)));
+ int tint_symbol = asint(reversebits(asuint(val1)));
return;
}
)");
diff --git a/src/tint/lang/hlsl/writer/ast_printer/constructor_test.cc b/src/tint/lang/hlsl/writer/ast_printer/constructor_test.cc
index 7b8b51b..5a9a9a3 100644
--- a/src/tint/lang/hlsl/writer/ast_printer/constructor_test.cc
+++ b/src/tint/lang/hlsl/writer/ast_printer/constructor_test.cc
@@ -204,7 +204,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_THAT(gen.Result(), HasSubstr(R"(float v = 2.0f;
- const float3 tint_symbol = float3((v).xxx);)"));
+ float3 tint_symbol = float3((v).xxx);)"));
}
TEST_F(HlslASTPrinterTest_Constructor, Type_Vec_SingleScalar_F16_Var) {
@@ -218,7 +218,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_THAT(gen.Result(), HasSubstr(R"(float16_t v = float16_t(2.0h);
- const vector<float16_t, 3> tint_symbol = vector<float16_t, 3>((v).xxx);)"));
+ vector<float16_t, 3> tint_symbol = vector<float16_t, 3>((v).xxx);)"));
}
TEST_F(HlslASTPrinterTest_Constructor, Type_Vec_SingleScalar_Bool_Literal) {
@@ -239,7 +239,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_THAT(gen.Result(), HasSubstr(R"(bool v = true;
- const bool3 tint_symbol = bool3((v).xxx);)"));
+ bool3 tint_symbol = bool3((v).xxx);)"));
}
TEST_F(HlslASTPrinterTest_Constructor, Type_Vec_SingleScalar_Int) {
diff --git a/src/tint/lang/hlsl/writer/ast_printer/function_test.cc b/src/tint/lang/hlsl/writer/ast_printer/function_test.cc
index 6158a91..2f6822c 100644
--- a/src/tint/lang/hlsl/writer/ast_printer/function_test.cc
+++ b/src/tint/lang/hlsl/writer/ast_printer/function_test.cc
@@ -158,7 +158,7 @@
}
tint_symbol_2 frag_main(tint_symbol_1 tint_symbol) {
- const float inner_result = frag_main_inner(tint_symbol.foo);
+ float inner_result = frag_main_inner(tint_symbol.foo);
tint_symbol_2 wrapper_result = (tint_symbol_2)0;
wrapper_result.value = inner_result;
return wrapper_result;
@@ -197,7 +197,7 @@
}
tint_symbol_2 frag_main(tint_symbol_1 tint_symbol) {
- const float inner_result = frag_main_inner(float4(tint_symbol.coord.xyz, (1.0f / tint_symbol.coord.w)));
+ float inner_result = frag_main_inner(float4(tint_symbol.coord.xyz, (1.0f / tint_symbol.coord.w)));
tint_symbol_2 wrapper_result = (tint_symbol_2)0;
wrapper_result.value = inner_result;
return wrapper_result;
@@ -256,12 +256,12 @@
};
Interface vert_main_inner() {
- const Interface tint_symbol_3 = {(0.0f).xxxx, 0.5f, 0.25f};
+ Interface tint_symbol_3 = {(0.0f).xxxx, 0.5f, 0.25f};
return tint_symbol_3;
}
tint_symbol vert_main() {
- const Interface inner_result = vert_main_inner();
+ Interface inner_result = vert_main_inner();
tint_symbol wrapper_result = (tint_symbol)0;
wrapper_result.pos = inner_result.pos;
wrapper_result.col1 = inner_result.col1;
@@ -276,13 +276,13 @@
};
void frag_main_inner(Interface inputs) {
- const float r = inputs.col1;
- const float g = inputs.col2;
- const float4 p = inputs.pos;
+ float r = inputs.col1;
+ float g = inputs.col2;
+ float4 p = inputs.pos;
}
void frag_main(tint_symbol_2 tint_symbol_1) {
- const Interface tint_symbol_4 = {float4(tint_symbol_1.pos.xyz, (1.0f / tint_symbol_1.pos.w)), tint_symbol_1.col1, tint_symbol_1.col2};
+ Interface tint_symbol_4 = {float4(tint_symbol_1.pos.xyz, (1.0f / tint_symbol_1.pos.w)), tint_symbol_1.col1, tint_symbol_1.col2};
frag_main_inner(tint_symbol_4);
return;
}
@@ -332,7 +332,7 @@
};
VertexOutput foo(float x) {
- const VertexOutput tint_symbol_2 = {float4(x, x, x, 1.0f)};
+ VertexOutput tint_symbol_2 = {float4(x, x, x, 1.0f)};
return tint_symbol_2;
}
@@ -345,7 +345,7 @@
}
tint_symbol vert_main1() {
- const VertexOutput inner_result = vert_main1_inner();
+ VertexOutput inner_result = vert_main1_inner();
tint_symbol wrapper_result = (tint_symbol)0;
wrapper_result.pos = inner_result.pos;
return wrapper_result;
@@ -360,7 +360,7 @@
}
tint_symbol_1 vert_main2() {
- const VertexOutput inner_result_1 = vert_main2_inner();
+ VertexOutput inner_result_1 = vert_main2_inner();
tint_symbol_1 wrapper_result_1 = (tint_symbol_1)0;
wrapper_result_1.pos = inner_result_1.pos;
return wrapper_result_1;
diff --git a/src/tint/lang/hlsl/writer/ast_printer/member_accessor_test.cc b/src/tint/lang/hlsl/writer/ast_printer/member_accessor_test.cc
index 20ebf39..f06ef68 100644
--- a/src/tint/lang/hlsl/writer/ast_printer/member_accessor_test.cc
+++ b/src/tint/lang/hlsl/writer/ast_printer/member_accessor_test.cc
@@ -1405,7 +1405,7 @@
RWByteAddressBuffer data : register(u0, space1);
Inner data_load(uint offset) {
- const Inner tint_symbol = {asint(data.Load((offset + 0u)))};
+ Inner tint_symbol = {asint(data.Load((offset + 0u)))};
return tint_symbol;
}
@@ -1458,7 +1458,7 @@
Inner data_load(uint offset) {
const uint scalar_offset = ((offset + 0u)) / 4;
- const Inner tint_symbol = {asint(data[scalar_offset / 4][scalar_offset % 4])};
+ Inner tint_symbol = {asint(data[scalar_offset / 4][scalar_offset % 4])};
return tint_symbol;
}
diff --git a/src/tint/lang/hlsl/writer/ast_printer/module_constant_test.cc b/src/tint/lang/hlsl/writer/ast_printer/module_constant_test.cc
index 59f3289..17559d3 100644
--- a/src/tint/lang/hlsl/writer/ast_printer/module_constant_test.cc
+++ b/src/tint/lang/hlsl/writer/ast_printer/module_constant_test.cc
@@ -45,7 +45,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_EQ(gen.Result(), R"(void f() {
- const int l = 1;
+ int l = 1;
}
)");
}
@@ -59,7 +59,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_EQ(gen.Result(), R"(void f() {
- const float l = 1.0f;
+ float l = 1.0f;
}
)");
}
@@ -73,7 +73,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_EQ(gen.Result(), R"(void f() {
- const int l = 1;
+ int l = 1;
}
)");
}
@@ -87,7 +87,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_EQ(gen.Result(), R"(void f() {
- const uint l = 1u;
+ uint l = 1u;
}
)");
}
@@ -101,7 +101,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_EQ(gen.Result(), R"(void f() {
- const float l = 1.0f;
+ float l = 1.0f;
}
)");
}
@@ -117,7 +117,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_EQ(gen.Result(), R"(void f() {
- const float16_t l = float16_t(1.0h);
+ float16_t l = float16_t(1.0h);
}
)");
}
@@ -131,7 +131,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_EQ(gen.Result(), R"(void f() {
- const int3 l = int3(1, 2, 3);
+ int3 l = int3(1, 2, 3);
}
)");
}
@@ -145,7 +145,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_EQ(gen.Result(), R"(void f() {
- const float3 l = float3(1.0f, 2.0f, 3.0f);
+ float3 l = float3(1.0f, 2.0f, 3.0f);
}
)");
}
@@ -159,7 +159,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_EQ(gen.Result(), R"(void f() {
- const float3 l = float3(1.0f, 2.0f, 3.0f);
+ float3 l = float3(1.0f, 2.0f, 3.0f);
}
)");
}
@@ -175,7 +175,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_EQ(gen.Result(), R"(void f() {
- const vector<float16_t, 3> l = vector<float16_t, 3>(float16_t(1.0h), float16_t(2.0h), float16_t(3.0h));
+ vector<float16_t, 3> l = vector<float16_t, 3>(float16_t(1.0h), float16_t(2.0h), float16_t(3.0h));
}
)");
}
@@ -189,7 +189,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_EQ(gen.Result(), R"(void f() {
- const float2x3 l = float2x3(float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f));
+ float2x3 l = float2x3(float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f));
}
)");
}
@@ -203,7 +203,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_EQ(gen.Result(), R"(void f() {
- const float2x3 l = float2x3(float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f));
+ float2x3 l = float2x3(float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f));
}
)");
}
@@ -219,7 +219,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_EQ(gen.Result(), R"(void f() {
- const matrix<float16_t, 2, 3> l = matrix<float16_t, 2, 3>(vector<float16_t, 3>(float16_t(1.0h), float16_t(2.0h), float16_t(3.0h)), vector<float16_t, 3>(float16_t(4.0h), float16_t(5.0h), float16_t(6.0h)));
+ matrix<float16_t, 2, 3> l = matrix<float16_t, 2, 3>(vector<float16_t, 3>(float16_t(1.0h), float16_t(2.0h), float16_t(3.0h)), vector<float16_t, 3>(float16_t(4.0h), float16_t(5.0h), float16_t(6.0h)));
}
)");
}
@@ -233,7 +233,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_EQ(gen.Result(), R"(void f() {
- const float l[3] = {1.0f, 2.0f, 3.0f};
+ float l[3] = {1.0f, 2.0f, 3.0f};
}
)");
}
@@ -250,7 +250,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_EQ(gen.Result(), R"(void f() {
- const bool2 l[3] = {bool2(true, false), bool2(false, true), (true).xx};
+ bool2 l[3] = {bool2(true, false), bool2(false, true), (true).xx};
}
)");
}
diff --git a/src/tint/lang/hlsl/writer/ast_printer/sanitizer_test.cc b/src/tint/lang/hlsl/writer/ast_printer/sanitizer_test.cc
index d9ebaf3..5823771 100644
--- a/src/tint/lang/hlsl/writer/ast_printer/sanitizer_test.cc
+++ b/src/tint/lang/hlsl/writer/ast_printer/sanitizer_test.cc
@@ -61,7 +61,7 @@
void a_func() {
uint tint_symbol_1 = 0u;
b.GetDimensions(tint_symbol_1);
- const uint tint_symbol_2 = ((tint_symbol_1 - 0u) / 4u);
+ uint tint_symbol_2 = ((tint_symbol_1 - 0u) / 4u);
uint len = tint_symbol_2;
return;
}
@@ -95,7 +95,7 @@
void a_func() {
uint tint_symbol_1 = 0u;
b.GetDimensions(tint_symbol_1);
- const uint tint_symbol_2 = ((tint_symbol_1 - 4u) / 4u);
+ uint tint_symbol_2 = ((tint_symbol_1 - 4u) / 4u);
uint len = tint_symbol_2;
return;
}
@@ -132,7 +132,7 @@
void a_func() {
uint tint_symbol_1 = 0u;
b.GetDimensions(tint_symbol_1);
- const uint tint_symbol_2 = ((tint_symbol_1 - 0u) / 4u);
+ uint tint_symbol_2 = ((tint_symbol_1 - 0u) / 4u);
uint len = tint_symbol_2;
return;
}
@@ -175,7 +175,7 @@
void a_func() {
uint tint_symbol_3 = 0u;
b.GetDimensions(tint_symbol_3);
- const uint tint_symbol_4 = ((tint_symbol_3 - 0u) / 4u);
+ uint tint_symbol_4 = ((tint_symbol_3 - 0u) / 4u);
uint len = (tint_symbol_4 + ((tint_symbol_1[1].w - 0u) / 4u));
return;
}
@@ -202,7 +202,7 @@
auto got = gen.Result();
auto* expect = R"(void main() {
int idx = 3;
- const int tint_symbol[4] = {1, 2, 3, 4};
+ int tint_symbol[4] = {1, 2, 3, 4};
int pos = tint_symbol[idx];
return;
}
@@ -243,7 +243,7 @@
void main() {
float runtime_value = 3.0f;
- const S tint_symbol = {1, float3(2.0f, runtime_value, 4.0f), 4};
+ S tint_symbol = {1, float3(2.0f, runtime_value, 4.0f), 4};
float3 pos = tint_symbol.b;
return;
}
diff --git a/src/tint/lang/hlsl/writer/ast_printer/variable_decl_statement_test.cc b/src/tint/lang/hlsl/writer/ast_printer/variable_decl_statement_test.cc
index 8e52ea8..e546046 100644
--- a/src/tint/lang/hlsl/writer/ast_printer/variable_decl_statement_test.cc
+++ b/src/tint/lang/hlsl/writer/ast_printer/variable_decl_statement_test.cc
@@ -62,7 +62,7 @@
gen.IncrementIndent();
ASSERT_TRUE(gen.EmitStatement(stmt)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), " const float a = 0.0f;\n");
+ EXPECT_EQ(gen.Result(), " float a = 0.0f;\n");
}
TEST_F(HlslASTPrinterTest_VariableDecl, Emit_VariableDeclStatement_Const) {
@@ -91,7 +91,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_EQ(gen.Result(), R"(void f() {
- const int l = 1;
+ int l = 1;
}
)");
}
@@ -109,7 +109,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_EQ(gen.Result(), R"(void f() {
- const float l = 1.0f;
+ float l = 1.0f;
}
)");
}
@@ -127,7 +127,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_EQ(gen.Result(), R"(void f() {
- const int l = 1;
+ int l = 1;
}
)");
}
@@ -145,7 +145,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_EQ(gen.Result(), R"(void f() {
- const uint l = 1u;
+ uint l = 1u;
}
)");
}
@@ -163,7 +163,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_EQ(gen.Result(), R"(void f() {
- const float l = 1.0f;
+ float l = 1.0f;
}
)");
}
@@ -183,7 +183,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_EQ(gen.Result(), R"(void f() {
- const float16_t l = float16_t(1.0h);
+ float16_t l = float16_t(1.0h);
}
)");
}
@@ -201,7 +201,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_EQ(gen.Result(), R"(void f() {
- const int3 l = int3(1, 2, 3);
+ int3 l = int3(1, 2, 3);
}
)");
}
@@ -219,7 +219,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_EQ(gen.Result(), R"(void f() {
- const float3 l = float3(1.0f, 2.0f, 3.0f);
+ float3 l = float3(1.0f, 2.0f, 3.0f);
}
)");
}
@@ -237,7 +237,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_EQ(gen.Result(), R"(void f() {
- const float3 l = float3(1.0f, 2.0f, 3.0f);
+ float3 l = float3(1.0f, 2.0f, 3.0f);
}
)");
}
@@ -257,7 +257,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_EQ(gen.Result(), R"(void f() {
- const vector<float16_t, 3> l = vector<float16_t, 3>(float16_t(1.0h), float16_t(2.0h), float16_t(3.0h));
+ vector<float16_t, 3> l = vector<float16_t, 3>(float16_t(1.0h), float16_t(2.0h), float16_t(3.0h));
}
)");
}
@@ -275,7 +275,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_EQ(gen.Result(), R"(void f() {
- const float2x3 l = float2x3(float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f));
+ float2x3 l = float2x3(float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f));
}
)");
}
@@ -293,7 +293,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_EQ(gen.Result(), R"(void f() {
- const float2x3 l = float2x3(float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f));
+ float2x3 l = float2x3(float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f));
}
)");
}
@@ -313,7 +313,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_EQ(gen.Result(), R"(void f() {
- const matrix<float16_t, 2, 3> l = matrix<float16_t, 2, 3>(vector<float16_t, 3>(float16_t(1.0h), float16_t(2.0h), float16_t(3.0h)), vector<float16_t, 3>(float16_t(4.0h), float16_t(5.0h), float16_t(6.0h)));
+ matrix<float16_t, 2, 3> l = matrix<float16_t, 2, 3>(vector<float16_t, 3>(float16_t(1.0h), float16_t(2.0h), float16_t(3.0h)), vector<float16_t, 3>(float16_t(4.0h), float16_t(5.0h), float16_t(6.0h)));
}
)");
}
@@ -331,7 +331,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_EQ(gen.Result(), R"(void f() {
- const float l[3] = {1.0f, 2.0f, 3.0f};
+ float l[3] = {1.0f, 2.0f, 3.0f};
}
)");
}
@@ -352,7 +352,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_EQ(gen.Result(), R"(void f() {
- const bool2 l[3] = {bool2(true, false), bool2(false, true), (true).xx};
+ bool2 l[3] = {bool2(true, false), bool2(false, true), (true).xx};
}
)");
}
@@ -456,7 +456,7 @@
ASSERT_TRUE(gen.Generate()) << gen.Diagnostics();
EXPECT_EQ(gen.Result(), R"(void f() {
- const float2x3 l = float2x3(float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f));
+ float2x3 l = float2x3(float3(1.0f, 2.0f, 3.0f), float3(4.0f, 5.0f, 6.0f));
}
)");
}
diff --git a/src/tint/lang/msl/writer/ast_printer/ast_printer.cc b/src/tint/lang/msl/writer/ast_printer/ast_printer.cc
index 718770e..d7d744c 100644
--- a/src/tint/lang/msl/writer/ast_printer/ast_printer.cc
+++ b/src/tint/lang/msl/writer/ast_printer/ast_printer.cc
@@ -2798,22 +2798,24 @@
if (auto location = attributes.location) {
auto& pipeline_stage_uses = str->PipelineStageUses();
- if (TINT_UNLIKELY(pipeline_stage_uses.size() != 1)) {
+ if (TINT_UNLIKELY(pipeline_stage_uses.Count() != 1)) {
TINT_ICE() << "invalid entry point IO struct uses for " << str->Name().NameView();
return false;
}
- if (pipeline_stage_uses.count(core::type::PipelineStageUsage::kVertexInput)) {
+ if (pipeline_stage_uses.Contains(core::type::PipelineStageUsage::kVertexInput)) {
out << " [[attribute(" + std::to_string(location.value()) + ")]]";
- } else if (pipeline_stage_uses.count(core::type::PipelineStageUsage::kVertexOutput)) {
+ } else if (pipeline_stage_uses.Contains(
+ core::type::PipelineStageUsage::kVertexOutput)) {
out << " [[user(locn" + std::to_string(location.value()) + ")]]";
- } else if (pipeline_stage_uses.count(core::type::PipelineStageUsage::kFragmentInput)) {
+ } else if (pipeline_stage_uses.Contains(
+ core::type::PipelineStageUsage::kFragmentInput)) {
out << " [[user(locn" + std::to_string(location.value()) + ")]]";
- } else if (TINT_LIKELY(pipeline_stage_uses.count(
+ } else if (TINT_LIKELY(pipeline_stage_uses.Contains(
core::type::PipelineStageUsage::kFragmentOutput))) {
- if (auto index = attributes.index) {
+ if (auto blend_src = attributes.blend_src) {
out << " [[color(" + std::to_string(location.value()) + ") index(" +
- std::to_string(index.value()) + ")]]";
+ std::to_string(blend_src.value()) + ")]]";
} else {
out << " [[color(" + std::to_string(location.value()) + ")]]";
}
@@ -3018,16 +3020,17 @@
return true;
}
-std::string_view ASTPrinter::IsolateUB() {
+std::string ASTPrinter::IsolateUB() {
if (isolate_ub_macro_name_.empty()) {
isolate_ub_macro_name_ = UniqueIdentifier("TINT_ISOLATE_UB");
- auto volatile_true = UniqueIdentifier("tint_volatile_true");
- Line(&helpers_) << "#define " << isolate_ub_macro_name_ << " \\";
- Line(&helpers_) << " if (volatile bool " << volatile_true << " = true; " << volatile_true
- << ")";
+ Line(&helpers_) << "#define " << isolate_ub_macro_name_ << "(VOLATILE_NAME) \\";
+ Line(&helpers_) << " volatile bool VOLATILE_NAME = true; \\";
+ Line(&helpers_) << " if (VOLATILE_NAME)";
Line(&helpers_);
}
- return isolate_ub_macro_name_;
+ StringStream ss;
+ ss << isolate_ub_macro_name_ << "(" << UniqueIdentifier("tint_volatile_true") << ")";
+ return ss.str();
}
template <typename F>
diff --git a/src/tint/lang/msl/writer/ast_printer/ast_printer.h b/src/tint/lang/msl/writer/ast_printer/ast_printer.h
index 70269c9..a9e9378 100644
--- a/src/tint/lang/msl/writer/ast_printer/ast_printer.h
+++ b/src/tint/lang/msl/writer/ast_printer/ast_printer.h
@@ -380,8 +380,8 @@
/// Lazilly generates the TINT_ISOLATE_UB macro, used to prevent UB statements from affecting
/// later logic.
- /// @return the unique name of the TINT_ISOLATE_UB macro.
- std::string_view IsolateUB();
+ /// @return the MSL to call the TINT_ISOLATE_UB macro.
+ std::string IsolateUB();
/// Handles generating a builtin name
/// @param builtin the semantic info for the builtin
diff --git a/src/tint/lang/msl/writer/ast_printer/ast_printer_test.cc b/src/tint/lang/msl/writer/ast_printer/ast_printer_test.cc
index 74d8fdd..28a2d3e 100644
--- a/src/tint/lang/msl/writer/ast_printer/ast_printer_test.cc
+++ b/src/tint/lang/msl/writer/ast_printer/ast_printer_test.cc
@@ -226,15 +226,16 @@
T elements[N];
};
-#define TINT_ISOLATE_UB \
- if (volatile bool tint_volatile_true = true; tint_volatile_true)
+#define TINT_ISOLATE_UB(VOLATILE_NAME) \
+ volatile bool VOLATILE_NAME = true; \
+ if (VOLATILE_NAME)
struct tint_symbol_3 {
tint_array<float2x2, 4> m;
};
void comp_main_inner(uint local_invocation_index, threadgroup tint_array<float2x2, 4>* const tint_symbol) {
- TINT_ISOLATE_UB for(uint idx = local_invocation_index; (idx < 4u); idx = (idx + 1u)) {
+ TINT_ISOLATE_UB(tint_volatile_true) for(uint idx = local_invocation_index; (idx < 4u); idx = (idx + 1u)) {
uint const i = idx;
(*(tint_symbol))[i] = float2x2(float2(0.0f), float2(0.0f));
}
diff --git a/src/tint/lang/msl/writer/ast_printer/continue_test.cc b/src/tint/lang/msl/writer/ast_printer/continue_test.cc
index 727f05c..ad68153 100644
--- a/src/tint/lang/msl/writer/ast_printer/continue_test.cc
+++ b/src/tint/lang/msl/writer/ast_printer/continue_test.cc
@@ -44,11 +44,12 @@
using namespace metal;
-#define TINT_ISOLATE_UB \
- if (volatile bool tint_volatile_true = true; tint_volatile_true)
+#define TINT_ISOLATE_UB(VOLATILE_NAME) \
+ volatile bool VOLATILE_NAME = true; \
+ if (VOLATILE_NAME)
kernel void test_function() {
- TINT_ISOLATE_UB while(true) {
+ TINT_ISOLATE_UB(tint_volatile_true) while(true) {
if (false) {
break;
}
diff --git a/src/tint/lang/msl/writer/ast_printer/loop_test.cc b/src/tint/lang/msl/writer/ast_printer/loop_test.cc
index 7aed227..3d1dd64 100644
--- a/src/tint/lang/msl/writer/ast_printer/loop_test.cc
+++ b/src/tint/lang/msl/writer/ast_printer/loop_test.cc
@@ -51,11 +51,12 @@
using namespace metal;
-#define TINT_ISOLATE_UB \
- if (volatile bool tint_volatile_true = true; tint_volatile_true)
+#define TINT_ISOLATE_UB(VOLATILE_NAME) \
+ volatile bool VOLATILE_NAME = true; \
+ if (VOLATILE_NAME)
fragment void F() {
- TINT_ISOLATE_UB while(true) {
+ TINT_ISOLATE_UB(tint_volatile_true) while(true) {
break;
}
return;
@@ -80,14 +81,15 @@
using namespace metal;
-#define TINT_ISOLATE_UB \
- if (volatile bool tint_volatile_true = true; tint_volatile_true)
+#define TINT_ISOLATE_UB(VOLATILE_NAME) \
+ volatile bool VOLATILE_NAME = true; \
+ if (VOLATILE_NAME)
void a_statement() {
}
fragment void F() {
- TINT_ISOLATE_UB while(true) {
+ TINT_ISOLATE_UB(tint_volatile_true) while(true) {
break;
{
a_statement();
@@ -115,14 +117,15 @@
using namespace metal;
-#define TINT_ISOLATE_UB \
- if (volatile bool tint_volatile_true = true; tint_volatile_true)
+#define TINT_ISOLATE_UB(VOLATILE_NAME) \
+ volatile bool VOLATILE_NAME = true; \
+ if (VOLATILE_NAME)
void a_statement() {
}
fragment void F() {
- TINT_ISOLATE_UB while(true) {
+ TINT_ISOLATE_UB(tint_volatile_true) while(true) {
break;
{
a_statement();
@@ -156,8 +159,8 @@
ASTPrinter& gen = Build();
ASSERT_TRUE(gen.EmitStatement(outer)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(TINT_ISOLATE_UB while(true) {
- TINT_ISOLATE_UB while(true) {
+ EXPECT_EQ(gen.Result(), R"(TINT_ISOLATE_UB(tint_volatile_true) while(true) {
+ TINT_ISOLATE_UB(tint_volatile_true_1) while(true) {
break;
{
a_statement();
@@ -194,7 +197,7 @@
ASTPrinter& gen = Build();
ASSERT_TRUE(gen.EmitStatement(outer)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(TINT_ISOLATE_UB while(true) {
+ EXPECT_EQ(gen.Result(), R"(TINT_ISOLATE_UB(tint_volatile_true) while(true) {
float lhs = 2.5f;
float other = 0.0f;
break;
@@ -217,7 +220,7 @@
ASTPrinter& gen = Build();
ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(TINT_ISOLATE_UB for(; ; ) {
+ EXPECT_EQ(gen.Result(), R"(TINT_ISOLATE_UB(tint_volatile_true) for(; ; ) {
return;
}
)");
@@ -235,7 +238,7 @@
ASTPrinter& gen = Build();
ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(TINT_ISOLATE_UB for(int i = 0; ; ) {
+ EXPECT_EQ(gen.Result(), R"(TINT_ISOLATE_UB(tint_volatile_true) for(int i = 0; ; ) {
return;
}
)");
@@ -266,7 +269,7 @@
f(1);
f(2);
}
- TINT_ISOLATE_UB for(; ; ) {
+ TINT_ISOLATE_UB(tint_volatile_true) for(; ; ) {
return;
}
}
@@ -285,7 +288,7 @@
ASTPrinter& gen = Build();
ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(TINT_ISOLATE_UB for(; true; ) {
+ EXPECT_EQ(gen.Result(), R"(TINT_ISOLATE_UB(tint_volatile_true) for(; true; ) {
return;
}
)");
@@ -304,8 +307,9 @@
ASTPrinter& gen = Build();
ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(),
- R"(TINT_ISOLATE_UB for(; ; i = as_type<int>((as_type<uint>(i) + as_type<uint>(1)))) {
+ EXPECT_EQ(
+ gen.Result(),
+ R"(TINT_ISOLATE_UB(tint_volatile_true) for(; ; i = as_type<int>((as_type<uint>(i) + as_type<uint>(1)))) {
return;
}
)");
@@ -331,7 +335,7 @@
ASTPrinter& gen = Build();
ASSERT_TRUE(gen.EmitStatement(loop)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(TINT_ISOLATE_UB while(true) {
+ EXPECT_EQ(gen.Result(), R"(TINT_ISOLATE_UB(tint_volatile_true) while(true) {
return;
{
f(1);
@@ -357,7 +361,7 @@
ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
EXPECT_EQ(
gen.Result(),
- R"(TINT_ISOLATE_UB for(int i = 0; true; i = as_type<int>((as_type<uint>(i) + as_type<uint>(1)))) {
+ R"(TINT_ISOLATE_UB(tint_volatile_true) for(int i = 0; true; i = as_type<int>((as_type<uint>(i) + as_type<uint>(1)))) {
a_statement();
}
)");
@@ -389,7 +393,7 @@
f(1);
f(2);
}
- TINT_ISOLATE_UB while(true) {
+ TINT_ISOLATE_UB(tint_volatile_true) while(true) {
if (!(true)) { break; }
return;
{
@@ -412,7 +416,7 @@
ASTPrinter& gen = Build();
ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(TINT_ISOLATE_UB while(true) {
+ EXPECT_EQ(gen.Result(), R"(TINT_ISOLATE_UB(tint_volatile_true) while(true) {
return;
}
)");
@@ -429,7 +433,7 @@
ASTPrinter& gen = Build();
ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(TINT_ISOLATE_UB while(true) {
+ EXPECT_EQ(gen.Result(), R"(TINT_ISOLATE_UB(tint_volatile_true) while(true) {
continue;
}
)");
@@ -449,7 +453,7 @@
ASTPrinter& gen = Build();
ASSERT_TRUE(gen.EmitStatement(f)) << gen.Diagnostics();
- EXPECT_EQ(gen.Result(), R"(TINT_ISOLATE_UB while((t && false)) {
+ EXPECT_EQ(gen.Result(), R"(TINT_ISOLATE_UB(tint_volatile_true) while((t && false)) {
return;
}
)");
diff --git a/src/tint/lang/msl/writer/printer/printer.cc b/src/tint/lang/msl/writer/printer/printer.cc
index e2950c5..0e8988e 100644
--- a/src/tint/lang/msl/writer/printer/printer.cc
+++ b/src/tint/lang/msl/writer/printer/printer.cc
@@ -1263,20 +1263,20 @@
if (auto location = attributes.location) {
auto& pipeline_stage_uses = str->PipelineStageUses();
- if (TINT_UNLIKELY(pipeline_stage_uses.size() != 1)) {
+ if (TINT_UNLIKELY(pipeline_stage_uses.Count() != 1)) {
TINT_IR_ICE(ir_) << "invalid entry point IO struct uses";
return;
}
- if (pipeline_stage_uses.count(core::type::PipelineStageUsage::kVertexInput)) {
+ if (pipeline_stage_uses.Contains(core::type::PipelineStageUsage::kVertexInput)) {
out << " [[attribute(" + std::to_string(location.value()) + ")]]";
- } else if (pipeline_stage_uses.count(
+ } else if (pipeline_stage_uses.Contains(
core::type::PipelineStageUsage::kVertexOutput)) {
out << " [[user(locn" + std::to_string(location.value()) + ")]]";
- } else if (pipeline_stage_uses.count(
+ } else if (pipeline_stage_uses.Contains(
core::type::PipelineStageUsage::kFragmentInput)) {
out << " [[user(locn" + std::to_string(location.value()) + ")]]";
- } else if (TINT_LIKELY(pipeline_stage_uses.count(
+ } else if (TINT_LIKELY(pipeline_stage_uses.Contains(
core::type::PipelineStageUsage::kFragmentOutput))) {
out << " [[color(" + std::to_string(location.value()) + ")]]";
} else {
diff --git a/src/tint/lang/spirv/validate/validate.cc b/src/tint/lang/spirv/validate/validate.cc
index 8d85413..c692a53 100644
--- a/src/tint/lang/spirv/validate/validate.cc
+++ b/src/tint/lang/spirv/validate/validate.cc
@@ -44,8 +44,8 @@
[&](spv_message_level_t level, const char*, const spv_position_t& pos, const char* msg) {
diag::Diagnostic diag;
diag.message = msg;
- diag.source.range.begin.line = pos.line + 1;
- diag.source.range.begin.column = pos.column + 1;
+ diag.source.range.begin.line = static_cast<uint32_t>(pos.line) + 1;
+ diag.source.range.begin.column = static_cast<uint32_t>(pos.column) + 1;
diag.source.range.end = diag.source.range.begin;
switch (level) {
case SPV_MSG_FATAL:
diff --git a/src/tint/lang/spirv/writer/ast_printer/ast_printer.cc b/src/tint/lang/spirv/writer/ast_printer/ast_printer.cc
index 5e5055f..346f46d 100644
--- a/src/tint/lang/spirv/writer/ast_printer/ast_printer.cc
+++ b/src/tint/lang/spirv/writer/ast_printer/ast_printer.cc
@@ -29,7 +29,6 @@
#include <unordered_map>
-#include "src/tint/lang/spirv/writer/ast_raise/clamp_frag_depth.h"
#include "src/tint/lang/spirv/writer/ast_raise/for_loop_to_loop.h"
#include "src/tint/lang/spirv/writer/ast_raise/merge_return.h"
#include "src/tint/lang/spirv/writer/ast_raise/var_for_dynamic_index.h"
@@ -41,6 +40,7 @@
#include "src/tint/lang/wgsl/ast/transform/binding_remapper.h"
#include "src/tint/lang/wgsl/ast/transform/builtin_polyfill.h"
#include "src/tint/lang/wgsl/ast/transform/canonicalize_entry_point_io.h"
+#include "src/tint/lang/wgsl/ast/transform/clamp_frag_depth.h"
#include "src/tint/lang/wgsl/ast/transform/demote_to_helper.h"
#include "src/tint/lang/wgsl/ast/transform/direct_variable_access.h"
#include "src/tint/lang/wgsl/ast/transform/disable_uniformity_analysis.h"
@@ -65,7 +65,7 @@
ast::transform::DataMap data;
if (options.clamp_frag_depth) {
- manager.Add<ClampFragDepth>();
+ manager.Add<ast::transform::ClampFragDepth>();
}
manager.Add<ast::transform::DisableUniformityAnalysis>();
diff --git a/src/tint/lang/spirv/writer/ast_printer/builder.cc b/src/tint/lang/spirv/writer/ast_printer/builder.cc
index 1895d11..143a7ab 100644
--- a/src/tint/lang/spirv/writer/ast_printer/builder.cc
+++ b/src/tint/lang/spirv/writer/ast_printer/builder.cc
@@ -801,7 +801,7 @@
Operand(sem->Attributes().location.value())});
return true;
},
- [&](const ast::IndexAttribute*) {
+ [&](const ast::BlendSrcAttribute*) {
module_.PushAnnot(spv::Op::OpDecorate,
{Operand(var_id), U32Operand(SpvDecorationIndex),
Operand(sem->Attributes().index.value())});
diff --git a/src/tint/lang/spirv/writer/ast_raise/BUILD.bazel b/src/tint/lang/spirv/writer/ast_raise/BUILD.bazel
index e13d946..275f6e5 100644
--- a/src/tint/lang/spirv/writer/ast_raise/BUILD.bazel
+++ b/src/tint/lang/spirv/writer/ast_raise/BUILD.bazel
@@ -39,7 +39,6 @@
cc_library(
name = "ast_raise",
srcs = [
- "clamp_frag_depth.cc",
"for_loop_to_loop.cc",
"merge_return.cc",
"var_for_dynamic_index.cc",
@@ -47,7 +46,6 @@
"while_to_loop.cc",
],
hdrs = [
- "clamp_frag_depth.h",
"for_loop_to_loop.h",
"merge_return.h",
"var_for_dynamic_index.h",
@@ -88,7 +86,6 @@
name = "test",
alwayslink = True,
srcs = [
- "clamp_frag_depth_test.cc",
"for_loop_to_loop_test.cc",
"merge_return_test.cc",
"var_for_dynamic_index_test.cc",
diff --git a/src/tint/lang/spirv/writer/ast_raise/BUILD.cmake b/src/tint/lang/spirv/writer/ast_raise/BUILD.cmake
index 9cd1d16..409ca99 100644
--- a/src/tint/lang/spirv/writer/ast_raise/BUILD.cmake
+++ b/src/tint/lang/spirv/writer/ast_raise/BUILD.cmake
@@ -41,8 +41,6 @@
# Condition: TINT_BUILD_SPV_WRITER
################################################################################
tint_add_target(tint_lang_spirv_writer_ast_raise lib
- lang/spirv/writer/ast_raise/clamp_frag_depth.cc
- lang/spirv/writer/ast_raise/clamp_frag_depth.h
lang/spirv/writer/ast_raise/for_loop_to_loop.cc
lang/spirv/writer/ast_raise/for_loop_to_loop.h
lang/spirv/writer/ast_raise/merge_return.cc
@@ -91,7 +89,6 @@
# Condition: TINT_BUILD_SPV_WRITER AND TINT_BUILD_WGSL_READER AND TINT_BUILD_WGSL_WRITER
################################################################################
tint_add_target(tint_lang_spirv_writer_ast_raise_test test
- lang/spirv/writer/ast_raise/clamp_frag_depth_test.cc
lang/spirv/writer/ast_raise/for_loop_to_loop_test.cc
lang/spirv/writer/ast_raise/merge_return_test.cc
lang/spirv/writer/ast_raise/var_for_dynamic_index_test.cc
diff --git a/src/tint/lang/spirv/writer/ast_raise/BUILD.gn b/src/tint/lang/spirv/writer/ast_raise/BUILD.gn
index b18ddb5..f24dbdd 100644
--- a/src/tint/lang/spirv/writer/ast_raise/BUILD.gn
+++ b/src/tint/lang/spirv/writer/ast_raise/BUILD.gn
@@ -44,8 +44,6 @@
if (tint_build_spv_writer) {
libtint_source_set("ast_raise") {
sources = [
- "clamp_frag_depth.cc",
- "clamp_frag_depth.h",
"for_loop_to_loop.cc",
"for_loop_to_loop.h",
"merge_return.cc",
@@ -91,7 +89,6 @@
tint_build_wgsl_writer) {
tint_unittests_source_set("unittests") {
sources = [
- "clamp_frag_depth_test.cc",
"for_loop_to_loop_test.cc",
"merge_return_test.cc",
"var_for_dynamic_index_test.cc",
diff --git a/src/tint/lang/spirv/writer/printer/printer.cc b/src/tint/lang/spirv/writer/printer/printer.cc
index 8eec980..cc4e35c 100644
--- a/src/tint/lang/spirv/writer/printer/printer.cc
+++ b/src/tint/lang/spirv/writer/printer/printer.cc
@@ -2008,9 +2008,9 @@
module_.PushAnnot(spv::Op::OpDecorate,
{id, U32Operand(SpvDecorationLocation), *attrs.location});
}
- if (attrs.index) {
+ if (attrs.blend_src) {
module_.PushAnnot(spv::Op::OpDecorate,
- {id, U32Operand(SpvDecorationIndex), *attrs.index});
+ {id, U32Operand(SpvDecorationIndex), *attrs.blend_src});
}
if (attrs.interpolation) {
switch (attrs.interpolation->type) {
diff --git a/src/tint/lang/spirv/writer/raise/shader_io.cc b/src/tint/lang/spirv/writer/raise/shader_io.cc
index b4a8be9..8266f23 100644
--- a/src/tint/lang/spirv/writer/raise/shader_io.cc
+++ b/src/tint/lang/spirv/writer/raise/shader_io.cc
@@ -106,8 +106,8 @@
}
if (io.attributes.location) {
name << "_loc" << io.attributes.location.value();
- if (io.attributes.index.has_value()) {
- name << "_idx" << io.attributes.index.value();
+ if (io.attributes.blend_src.has_value()) {
+ name << "_idx" << io.attributes.blend_src.value();
}
}
name << name_suffix;
@@ -117,7 +117,7 @@
auto* var = b.Var(name.str(), ptr);
var->SetAttributes(core::ir::IOAttributes{
io.attributes.location,
- io.attributes.index,
+ io.attributes.blend_src,
io.attributes.builtin,
io.attributes.interpolation,
io.attributes.invariant,
diff --git a/src/tint/lang/spirv/writer/raise/shader_io_test.cc b/src/tint/lang/spirv/writer/raise/shader_io_test.cc
index a2c5feb..5738a20 100644
--- a/src/tint/lang/spirv/writer/raise/shader_io_test.cc
+++ b/src/tint/lang/spirv/writer/raise/shader_io_test.cc
@@ -679,8 +679,8 @@
}
%b1 = block { # root
- %foo_loc0_idx0_Output:ptr<__out, f32, write> = var @location(0) @index(0)
- %foo_loc0_idx1_Output:ptr<__out, f32, write> = var @location(0) @index(1)
+ %foo_loc0_idx0_Output:ptr<__out, f32, write> = var @location(0) @blend_src(0)
+ %foo_loc0_idx1_Output:ptr<__out, f32, write> = var @location(0) @blend_src(1)
}
%foo_inner = func():Output -> %b2 {
diff --git a/src/tint/lang/wgsl/ast/BUILD.bazel b/src/tint/lang/wgsl/ast/BUILD.bazel
index 6eca7ad..a30fcff 100644
--- a/src/tint/lang/wgsl/ast/BUILD.bazel
+++ b/src/tint/lang/wgsl/ast/BUILD.bazel
@@ -46,6 +46,7 @@
"binary_expression.cc",
"binding_attribute.cc",
"bitcast_expression.cc",
+ "blend_src_attribute.cc",
"block_statement.cc",
"bool_literal_expression.cc",
"break_if_statement.cc",
@@ -81,7 +82,6 @@
"if_statement.cc",
"increment_decrement_statement.cc",
"index_accessor_expression.cc",
- "index_attribute.cc",
"int_literal_expression.cc",
"internal_attribute.cc",
"interpolate_attribute.cc",
@@ -127,6 +127,7 @@
"binary_expression.h",
"binding_attribute.h",
"bitcast_expression.h",
+ "blend_src_attribute.h",
"block_statement.h",
"bool_literal_expression.h",
"break_if_statement.h",
@@ -162,7 +163,6 @@
"if_statement.h",
"increment_decrement_statement.h",
"index_accessor_expression.h",
- "index_attribute.h",
"int_literal_expression.h",
"internal_attribute.h",
"interpolate_attribute.h",
@@ -235,6 +235,7 @@
"binary_expression_test.cc",
"binding_attribute_test.cc",
"bitcast_expression_test.cc",
+ "blend_src_attribute_test.cc",
"block_statement_test.cc",
"bool_literal_expression_test.cc",
"break_if_statement_test.cc",
@@ -269,7 +270,6 @@
"if_statement_test.cc",
"increment_decrement_statement_test.cc",
"index_accessor_expression_test.cc",
- "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 767496f..fd20e97 100644
--- a/src/tint/lang/wgsl/ast/BUILD.cmake
+++ b/src/tint/lang/wgsl/ast/BUILD.cmake
@@ -55,6 +55,8 @@
lang/wgsl/ast/binding_attribute.h
lang/wgsl/ast/bitcast_expression.cc
lang/wgsl/ast/bitcast_expression.h
+ lang/wgsl/ast/blend_src_attribute.cc
+ lang/wgsl/ast/blend_src_attribute.h
lang/wgsl/ast/block_statement.cc
lang/wgsl/ast/block_statement.h
lang/wgsl/ast/bool_literal_expression.cc
@@ -125,8 +127,6 @@
lang/wgsl/ast/increment_decrement_statement.h
lang/wgsl/ast/index_accessor_expression.cc
lang/wgsl/ast/index_accessor_expression.h
- lang/wgsl/ast/index_attribute.cc
- lang/wgsl/ast/index_attribute.h
lang/wgsl/ast/int_literal_expression.cc
lang/wgsl/ast/int_literal_expression.h
lang/wgsl/ast/internal_attribute.cc
@@ -235,6 +235,7 @@
lang/wgsl/ast/binary_expression_test.cc
lang/wgsl/ast/binding_attribute_test.cc
lang/wgsl/ast/bitcast_expression_test.cc
+ lang/wgsl/ast/blend_src_attribute_test.cc
lang/wgsl/ast/block_statement_test.cc
lang/wgsl/ast/bool_literal_expression_test.cc
lang/wgsl/ast/break_if_statement_test.cc
@@ -269,7 +270,6 @@
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/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 f42bd86..b46a056 100644
--- a/src/tint/lang/wgsl/ast/BUILD.gn
+++ b/src/tint/lang/wgsl/ast/BUILD.gn
@@ -58,6 +58,8 @@
"binding_attribute.h",
"bitcast_expression.cc",
"bitcast_expression.h",
+ "blend_src_attribute.cc",
+ "blend_src_attribute.h",
"block_statement.cc",
"block_statement.h",
"bool_literal_expression.cc",
@@ -128,8 +130,6 @@
"increment_decrement_statement.h",
"index_accessor_expression.cc",
"index_accessor_expression.h",
- "index_attribute.cc",
- "index_attribute.h",
"int_literal_expression.cc",
"int_literal_expression.h",
"internal_attribute.cc",
@@ -235,6 +235,7 @@
"binary_expression_test.cc",
"binding_attribute_test.cc",
"bitcast_expression_test.cc",
+ "blend_src_attribute_test.cc",
"block_statement_test.cc",
"bool_literal_expression_test.cc",
"break_if_statement_test.cc",
@@ -269,7 +270,6 @@
"if_statement_test.cc",
"increment_decrement_statement_test.cc",
"index_accessor_expression_test.cc",
- "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/index_attribute.cc b/src/tint/lang/wgsl/ast/blend_src_attribute.cc
similarity index 82%
rename from src/tint/lang/wgsl/ast/index_attribute.cc
rename to src/tint/lang/wgsl/ast/blend_src_attribute.cc
index 6650066..089ce1e 100644
--- a/src/tint/lang/wgsl/ast/index_attribute.cc
+++ b/src/tint/lang/wgsl/ast/blend_src_attribute.cc
@@ -25,34 +25,34 @@
// 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/index_attribute.h"
+#include "src/tint/lang/wgsl/ast/blend_src_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::IndexAttribute);
+TINT_INSTANTIATE_TYPEINFO(tint::ast::BlendSrcAttribute);
namespace tint::ast {
-IndexAttribute::IndexAttribute(GenerationID pid,
+BlendSrcAttribute::BlendSrcAttribute(GenerationID pid,
NodeID nid,
const Source& src,
const Expression* exp)
: Base(pid, nid, src), expr(exp) {}
-IndexAttribute::~IndexAttribute() = default;
+BlendSrcAttribute::~BlendSrcAttribute() = default;
-std::string IndexAttribute::Name() const {
- return "index";
+std::string BlendSrcAttribute::Name() const {
+ return "blend_src";
}
-const IndexAttribute* IndexAttribute::Clone(CloneContext& ctx) const {
+const BlendSrcAttribute* BlendSrcAttribute::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<IndexAttribute>(src, expr_);
+ return ctx.dst->create<BlendSrcAttribute>(src, expr_);
}
} // namespace tint::ast
diff --git a/src/tint/lang/wgsl/ast/index_attribute.h b/src/tint/lang/wgsl/ast/blend_src_attribute.h
similarity index 79%
rename from src/tint/lang/wgsl/ast/index_attribute.h
rename to src/tint/lang/wgsl/ast/blend_src_attribute.h
index 215ffe9..9133182 100644
--- a/src/tint/lang/wgsl/ast/index_attribute.h
+++ b/src/tint/lang/wgsl/ast/blend_src_attribute.h
@@ -25,8 +25,8 @@
// 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_INDEX_ATTRIBUTE_H_
-#define SRC_TINT_LANG_WGSL_AST_INDEX_ATTRIBUTE_H_
+#ifndef SRC_TINT_LANG_WGSL_AST_BLEND_SRC_ATTRIBUTE_H_
+#define SRC_TINT_LANG_WGSL_AST_BLEND_SRC_ATTRIBUTE_H_
#include <string>
@@ -35,16 +35,16 @@
namespace tint::ast {
-/// An id attribute for pipeline-overridable constants
-class IndexAttribute final : public Castable<IndexAttribute, Attribute> {
+/// An blend_src attribute for shader IO.
+class BlendSrcAttribute final : public Castable<BlendSrcAttribute, Attribute> {
public:
- /// Create an index attribute.
+ /// Create a blend_src ttribute.
/// @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 numeric id expression
- IndexAttribute(GenerationID pid, NodeID nid, const Source& src, const Expression* expr);
- ~IndexAttribute() override;
+ BlendSrcAttribute(GenerationID pid, NodeID nid, const Source& src, const Expression* expr);
+ ~BlendSrcAttribute() override;
/// @returns the WGSL name for the attribute
std::string Name() const override;
@@ -53,12 +53,12 @@
/// `ctx`.
/// @param ctx the clone context
/// @return the newly cloned node
- const IndexAttribute* Clone(CloneContext& ctx) const override;
+ const BlendSrcAttribute* Clone(CloneContext& ctx) const override;
- /// The id expression
+ /// The blend_src expression
const Expression* const expr;
};
} // namespace tint::ast
-#endif // SRC_TINT_LANG_WGSL_AST_INDEX_ATTRIBUTE_H_
+#endif // SRC_TINT_LANG_WGSL_AST_BLEND_SRC_ATTRIBUTE_H_
diff --git a/src/tint/lang/wgsl/ast/index_attribute_test.cc b/src/tint/lang/wgsl/ast/blend_src_attribute_test.cc
similarity index 91%
rename from src/tint/lang/wgsl/ast/index_attribute_test.cc
rename to src/tint/lang/wgsl/ast/blend_src_attribute_test.cc
index 38cd550..f954dc0 100644
--- a/src/tint/lang/wgsl/ast/index_attribute_test.cc
+++ b/src/tint/lang/wgsl/ast/blend_src_attribute_test.cc
@@ -25,7 +25,7 @@
// 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/id_attribute.h"
+#include "src/tint/lang/wgsl/ast/blend_src_attribute.h"
#include "src/tint/lang/wgsl/ast/helper_test.h"
@@ -33,10 +33,10 @@
namespace {
using namespace tint::core::number_suffixes; // NOLINT
-using IndexAttributeTest = TestHelper;
+using BlendSrcAttributeTest = TestHelper;
-TEST_F(IndexAttributeTest, Creation) {
- auto* d = Index(1_a);
+TEST_F(BlendSrcAttributeTest, Creation) {
+ auto* d = BlendSrc(1_a);
EXPECT_TRUE(d->expr->Is<IntLiteralExpression>());
}
diff --git a/src/tint/lang/wgsl/ast/builder.h b/src/tint/lang/wgsl/ast/builder.h
index 7bdaf1e..b037caa 100644
--- a/src/tint/lang/wgsl/ast/builder.h
+++ b/src/tint/lang/wgsl/ast/builder.h
@@ -61,6 +61,7 @@
#include "src/tint/lang/wgsl/ast/binary_expression.h"
#include "src/tint/lang/wgsl/ast/binding_attribute.h"
#include "src/tint/lang/wgsl/ast/bitcast_expression.h"
+#include "src/tint/lang/wgsl/ast/blend_src_attribute.h"
#include "src/tint/lang/wgsl/ast/bool_literal_expression.h"
#include "src/tint/lang/wgsl/ast/break_if_statement.h"
#include "src/tint/lang/wgsl/ast/break_statement.h"
@@ -86,7 +87,6 @@
#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/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"
@@ -3193,21 +3193,21 @@
return create<ast::LocationAttribute>(source_, Expr(std::forward<EXPR>(location)));
}
- /// Creates an ast::IndexAttribute
+ /// Creates an ast::BlendSrcAttribute
/// @param source the source information
- /// @param index the index value expression
- /// @returns the index attribute pointer
+ /// @param blend_src the blend_src value expression
+ /// @returns the blend_src attribute pointer
template <typename EXPR>
- const ast::IndexAttribute* Index(const Source& source, EXPR&& index) {
- return create<ast::IndexAttribute>(source, Expr(std::forward<EXPR>(index)));
+ const ast::BlendSrcAttribute* BlendSrc(const Source& source, EXPR&& blend_src) {
+ return create<ast::BlendSrcAttribute>(source, Expr(std::forward<EXPR>(blend_src)));
}
- /// Creates an ast::IndexAttribute
- /// @param index the index value expression
- /// @returns the index attribute pointer
+ /// Creates an ast::BlendSrcAttribute
+ /// @param blend_src the blend_src value expression
+ /// @returns the blend_src attribute pointer
template <typename EXPR>
- const ast::IndexAttribute* Index(EXPR&& index) {
- return create<ast::IndexAttribute>(source_, Expr(std::forward<EXPR>(index)));
+ const ast::BlendSrcAttribute* BlendSrc(EXPR&& blend_src) {
+ return create<ast::BlendSrcAttribute>(source_, Expr(std::forward<EXPR>(blend_src)));
}
/// Creates an ast::IdAttribute
diff --git a/src/tint/lang/wgsl/ast/node_id.h b/src/tint/lang/wgsl/ast/node_id.h
index 556f6fe..36096c3 100644
--- a/src/tint/lang/wgsl/ast/node_id.h
+++ b/src/tint/lang/wgsl/ast/node_id.h
@@ -29,6 +29,7 @@
#define SRC_TINT_LANG_WGSL_AST_NODE_ID_H_
#include <stddef.h>
+#include <stdint.h>
namespace tint::ast {
@@ -46,7 +47,7 @@
bool operator<(NodeID other) const { return value < other.value; }
/// The numerical value for the node identifier
- size_t value = 0;
+ uint32_t value = 0;
};
} // namespace tint::ast
diff --git a/src/tint/lang/wgsl/ast/transform/BUILD.bazel b/src/tint/lang/wgsl/ast/transform/BUILD.bazel
index cb9c9b1..6229a94 100644
--- a/src/tint/lang/wgsl/ast/transform/BUILD.bazel
+++ b/src/tint/lang/wgsl/ast/transform/BUILD.bazel
@@ -45,6 +45,7 @@
"binding_remapper.cc",
"builtin_polyfill.cc",
"canonicalize_entry_point_io.cc",
+ "clamp_frag_depth.cc",
"data.cc",
"demote_to_helper.cc",
"direct_variable_access.cc",
@@ -55,6 +56,7 @@
"hoist_to_decl_before.cc",
"manager.cc",
"multiplanar_external_texture.cc",
+ "offset_first_index.cc",
"preserve_padding.cc",
"promote_initializers_to_let.cc",
"promote_side_effects_to_decl.cc",
@@ -79,6 +81,7 @@
"binding_remapper.h",
"builtin_polyfill.h",
"canonicalize_entry_point_io.h",
+ "clamp_frag_depth.h",
"data.h",
"demote_to_helper.h",
"direct_variable_access.h",
@@ -89,6 +92,7 @@
"hoist_to_decl_before.h",
"manager.h",
"multiplanar_external_texture.h",
+ "offset_first_index.h",
"preserve_padding.h",
"promote_initializers_to_let.h",
"promote_side_effects_to_decl.h",
@@ -146,6 +150,7 @@
"binding_remapper_test.cc",
"builtin_polyfill_test.cc",
"canonicalize_entry_point_io_test.cc",
+ "clamp_frag_depth_test.cc",
"demote_to_helper_test.cc",
"direct_variable_access_test.cc",
"disable_uniformity_analysis_test.cc",
@@ -156,6 +161,7 @@
"hoist_to_decl_before_test.cc",
"manager_test.cc",
"multiplanar_external_texture_test.cc",
+ "offset_first_index_test.cc",
"preserve_padding_test.cc",
"promote_initializers_to_let_test.cc",
"promote_side_effects_to_decl_test.cc",
diff --git a/src/tint/lang/wgsl/ast/transform/BUILD.cmake b/src/tint/lang/wgsl/ast/transform/BUILD.cmake
index c432f09..068369c 100644
--- a/src/tint/lang/wgsl/ast/transform/BUILD.cmake
+++ b/src/tint/lang/wgsl/ast/transform/BUILD.cmake
@@ -51,6 +51,8 @@
lang/wgsl/ast/transform/builtin_polyfill.h
lang/wgsl/ast/transform/canonicalize_entry_point_io.cc
lang/wgsl/ast/transform/canonicalize_entry_point_io.h
+ lang/wgsl/ast/transform/clamp_frag_depth.cc
+ lang/wgsl/ast/transform/clamp_frag_depth.h
lang/wgsl/ast/transform/data.cc
lang/wgsl/ast/transform/data.h
lang/wgsl/ast/transform/demote_to_helper.cc
@@ -71,6 +73,8 @@
lang/wgsl/ast/transform/manager.h
lang/wgsl/ast/transform/multiplanar_external_texture.cc
lang/wgsl/ast/transform/multiplanar_external_texture.h
+ lang/wgsl/ast/transform/offset_first_index.cc
+ lang/wgsl/ast/transform/offset_first_index.h
lang/wgsl/ast/transform/preserve_padding.cc
lang/wgsl/ast/transform/preserve_padding.h
lang/wgsl/ast/transform/promote_initializers_to_let.cc
@@ -146,6 +150,7 @@
lang/wgsl/ast/transform/binding_remapper_test.cc
lang/wgsl/ast/transform/builtin_polyfill_test.cc
lang/wgsl/ast/transform/canonicalize_entry_point_io_test.cc
+ lang/wgsl/ast/transform/clamp_frag_depth_test.cc
lang/wgsl/ast/transform/demote_to_helper_test.cc
lang/wgsl/ast/transform/direct_variable_access_test.cc
lang/wgsl/ast/transform/disable_uniformity_analysis_test.cc
@@ -156,6 +161,7 @@
lang/wgsl/ast/transform/hoist_to_decl_before_test.cc
lang/wgsl/ast/transform/manager_test.cc
lang/wgsl/ast/transform/multiplanar_external_texture_test.cc
+ lang/wgsl/ast/transform/offset_first_index_test.cc
lang/wgsl/ast/transform/preserve_padding_test.cc
lang/wgsl/ast/transform/promote_initializers_to_let_test.cc
lang/wgsl/ast/transform/promote_side_effects_to_decl_test.cc
diff --git a/src/tint/lang/wgsl/ast/transform/BUILD.gn b/src/tint/lang/wgsl/ast/transform/BUILD.gn
index 1214968..b94227e 100644
--- a/src/tint/lang/wgsl/ast/transform/BUILD.gn
+++ b/src/tint/lang/wgsl/ast/transform/BUILD.gn
@@ -56,6 +56,8 @@
"builtin_polyfill.h",
"canonicalize_entry_point_io.cc",
"canonicalize_entry_point_io.h",
+ "clamp_frag_depth.cc",
+ "clamp_frag_depth.h",
"data.cc",
"data.h",
"demote_to_helper.cc",
@@ -76,6 +78,8 @@
"manager.h",
"multiplanar_external_texture.cc",
"multiplanar_external_texture.h",
+ "offset_first_index.cc",
+ "offset_first_index.h",
"preserve_padding.cc",
"preserve_padding.h",
"promote_initializers_to_let.cc",
@@ -147,6 +151,7 @@
"binding_remapper_test.cc",
"builtin_polyfill_test.cc",
"canonicalize_entry_point_io_test.cc",
+ "clamp_frag_depth_test.cc",
"demote_to_helper_test.cc",
"direct_variable_access_test.cc",
"disable_uniformity_analysis_test.cc",
@@ -157,6 +162,7 @@
"hoist_to_decl_before_test.cc",
"manager_test.cc",
"multiplanar_external_texture_test.cc",
+ "offset_first_index_test.cc",
"preserve_padding_test.cc",
"promote_initializers_to_let_test.cc",
"promote_side_effects_to_decl_test.cc",
diff --git a/src/tint/lang/wgsl/ast/transform/add_block_attribute.cc b/src/tint/lang/wgsl/ast/transform/add_block_attribute.cc
index 607bf54..82e0716 100644
--- a/src/tint/lang/wgsl/ast/transform/add_block_attribute.cc
+++ b/src/tint/lang/wgsl/ast/transform/add_block_attribute.cc
@@ -39,7 +39,6 @@
TINT_INSTANTIATE_TYPEINFO(tint::ast::transform::AddBlockAttribute);
TINT_INSTANTIATE_TYPEINFO(tint::ast::transform::AddBlockAttribute::BlockAttribute);
-TINT_INSTANTIATE_TYPEINFO(tint::ast::transform::AddBlockAttribute::Config);
namespace tint::ast::transform {
@@ -48,13 +47,12 @@
AddBlockAttribute::~AddBlockAttribute() = default;
Transform::ApplyResult AddBlockAttribute::Apply(const Program& src,
- const DataMap& inputs,
+ const DataMap&,
DataMap&) const {
ProgramBuilder b;
program::CloneContext ctx{&b, &src, /* auto_clone_symbols */ true};
auto& sem = src.Sem();
- auto* cfg = inputs.Get<Config>();
// A map from a type in the source program to a block-decorated wrapper that contains it in the
// destination program.
@@ -82,11 +80,6 @@
bool needs_wrapping = !str || // Type is not a structure
str->HasFixedFootprint(); // Struct has a fixed footprint
- if (cfg && cfg->skip_push_constants &&
- var->AddressSpace() == core::AddressSpace::kPushConstant) {
- continue;
- }
-
if (needs_wrapping) {
const char* kMemberName = "inner";
@@ -136,8 +129,4 @@
ctx.dst->AllocateNodeID());
}
-AddBlockAttribute::Config::Config(bool skip_push_consts) : skip_push_constants(skip_push_consts) {}
-
-AddBlockAttribute::Config::~Config() = default;
-
} // namespace tint::ast::transform
diff --git a/src/tint/lang/wgsl/ast/transform/add_block_attribute.h b/src/tint/lang/wgsl/ast/transform/add_block_attribute.h
index 61a884d..544e1ee 100644
--- a/src/tint/lang/wgsl/ast/transform/add_block_attribute.h
+++ b/src/tint/lang/wgsl/ast/transform/add_block_attribute.h
@@ -66,19 +66,6 @@
/// Destructor
~AddBlockAttribute() override;
- /// Transform configuration options
- struct Config final : public Castable<Config, ast::transform::Data> {
- /// Constructor
- /// @param skip_push_const whether to skip push constants
- explicit Config(bool skip_push_const);
-
- /// Destructor
- ~Config() override;
-
- /// Whether to skip push constants
- bool skip_push_constants;
- };
-
/// @copydoc Transform::Apply
ApplyResult Apply(const Program& program,
const DataMap& inputs,
diff --git a/src/tint/lang/wgsl/ast/transform/canonicalize_entry_point_io.cc b/src/tint/lang/wgsl/ast/transform/canonicalize_entry_point_io.cc
index 9bfa463..b056a6a 100644
--- a/src/tint/lang/wgsl/ast/transform/canonicalize_entry_point_io.cc
+++ b/src/tint/lang/wgsl/ast/transform/canonicalize_entry_point_io.cc
@@ -109,7 +109,7 @@
// Returns true if `attr` is a shader IO attribute.
bool IsShaderIOAttribute(const Attribute* attr) {
return attr->IsAnyOf<BuiltinAttribute, InterpolateAttribute, InvariantAttribute,
- LocationAttribute, ColorAttribute, IndexAttribute>();
+ LocationAttribute, ColorAttribute, BlendSrcAttribute>();
}
} // namespace
@@ -128,8 +128,8 @@
const Expression* value;
/// The output location.
std::optional<uint32_t> location;
- /// The output index.
- std::optional<uint32_t> index;
+ /// The output blend_src.
+ std::optional<uint32_t> blend_src;
};
/// The clone context.
@@ -374,13 +374,13 @@
/// @param name the name of the shader output
/// @param type the type of the shader output
/// @param location the location if provided
- /// @param index the index if provided
+ /// @param blend_src the blend_src if provided
/// @param attrs the attributes to apply to the shader output
/// @param value the value of the shader output
void AddOutput(std::string name,
const core::type::Type* type,
std::optional<uint32_t> location,
- std::optional<uint32_t> index,
+ std::optional<uint32_t> blend_src,
tint::Vector<const Attribute*, 8> attrs,
const Expression* value) {
auto builtin_attr = BuiltinOf(attrs);
@@ -412,7 +412,7 @@
output.attributes = std::move(attrs);
output.value = value;
output.location = location;
- output.index = index;
+ output.blend_src = blend_src;
wrapper_output_values.Push(output);
}
@@ -510,7 +510,7 @@
// Extract the original structure member.
AddOutput(name, member->Type(), member->Attributes().location,
- member->Attributes().index, std::move(attributes),
+ member->Attributes().blend_src, std::move(attributes),
b.MemberAccessor(original_result, name));
}
} else if (!inner_ret_type->Is<core::type::Void>()) {
@@ -658,7 +658,7 @@
wrapper_struct_output_members.Push({
/* member */ b.Member(name, outval.type, std::move(outval.attributes)),
/* location */ outval.location,
- /* index */ outval.index,
+ /* blend_src */ outval.blend_src,
/* color */ std::nullopt,
});
assignments.Push(b.Assign(b.MemberAccessor(wrapper_result, name), outval.value));
diff --git a/src/tint/lang/wgsl/ast/transform/canonicalize_entry_point_io_test.cc b/src/tint/lang/wgsl/ast/transform/canonicalize_entry_point_io_test.cc
index 468bb82..7c33b29 100644
--- a/src/tint/lang/wgsl/ast/transform/canonicalize_entry_point_io_test.cc
+++ b/src/tint/lang/wgsl/ast/transform/canonicalize_entry_point_io_test.cc
@@ -4134,8 +4134,8 @@
enable chromium_internal_dual_source_blending;
struct FragOutput {
- @location(0) @index(0) color : vec4<f32>,
- @location(0) @index(1) blend : vec4<f32>,
+ @location(0) @blend_src(0) color : vec4<f32>,
+ @location(0) @blend_src(1) blend : vec4<f32>,
@builtin(frag_depth) depth : f32,
@builtin(sample_mask) mask : u32,
};
@@ -4154,9 +4154,9 @@
auto* expect = R"(
enable chromium_internal_dual_source_blending;
-@location(0) @index(0) @internal(disable_validation__ignore_address_space) var<__out> color_1 : vec4<f32>;
+@location(0) @blend_src(0) @internal(disable_validation__ignore_address_space) var<__out> color_1 : vec4<f32>;
-@location(0) @index(1) @internal(disable_validation__ignore_address_space) var<__out> blend_1 : vec4<f32>;
+@location(0) @blend_src(1) @internal(disable_validation__ignore_address_space) var<__out> blend_1 : vec4<f32>;
@builtin(frag_depth) @internal(disable_validation__ignore_address_space) var<__out> depth_1 : f32;
@@ -4200,8 +4200,8 @@
enable chromium_internal_dual_source_blending;
struct FragOutput {
- @location(0) @index(0) color : vec4<f32>,
- @location(0) @index(1) blend : vec4<f32>,
+ @location(0) @blend_src(0) color : vec4<f32>,
+ @location(0) @blend_src(1) blend : vec4<f32>,
@builtin(frag_depth) depth : f32,
@builtin(sample_mask) mask : u32,
};
@@ -4228,9 +4228,9 @@
}
struct tint_symbol {
- @location(0) @index(0)
+ @location(0) @blend_src(0)
color : vec4<f32>,
- @location(0) @index(1)
+ @location(0) @blend_src(1)
blend : vec4<f32>,
@builtin(frag_depth)
depth : f32,
@@ -4271,8 +4271,8 @@
enable chromium_internal_dual_source_blending;
struct FragOutput {
- @location(0) @index(0) color : vec4<f32>,
- @location(0) @index(1) blend : vec4<f32>,
+ @location(0) @blend_src(0) color : vec4<f32>,
+ @location(0) @blend_src(1) blend : vec4<f32>,
@builtin(frag_depth) depth : f32,
@builtin(sample_mask) mask : u32,
};
@@ -4299,9 +4299,9 @@
}
struct tint_symbol {
- @location(0) @index(0)
+ @location(0) @blend_src(0)
color : vec4<f32>,
- @location(0) @index(1)
+ @location(0) @blend_src(1)
blend : vec4<f32>,
@builtin(frag_depth)
depth : f32,
diff --git a/src/tint/lang/spirv/writer/ast_raise/clamp_frag_depth.cc b/src/tint/lang/wgsl/ast/transform/clamp_frag_depth.cc
similarity index 97%
rename from src/tint/lang/spirv/writer/ast_raise/clamp_frag_depth.cc
rename to src/tint/lang/wgsl/ast/transform/clamp_frag_depth.cc
index 6683f18..c87fa15 100644
--- a/src/tint/lang/spirv/writer/ast_raise/clamp_frag_depth.cc
+++ b/src/tint/lang/wgsl/ast/transform/clamp_frag_depth.cc
@@ -25,7 +25,7 @@
// 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/spirv/writer/ast_raise/clamp_frag_depth.h"
+#include "src/tint/lang/wgsl/ast/transform/clamp_frag_depth.h"
#include <utility>
@@ -44,9 +44,9 @@
#include "src/tint/utils/containers/vector.h"
#include "src/tint/utils/macros/scoped_assignment.h"
-TINT_INSTANTIATE_TYPEINFO(tint::spirv::writer::ClampFragDepth);
+TINT_INSTANTIATE_TYPEINFO(tint::ast::transform::ClampFragDepth);
-namespace tint::spirv::writer {
+namespace tint::ast::transform {
/// PIMPL state for the transform
struct ClampFragDepth::State {
@@ -242,4 +242,4 @@
return State{src}.Run();
}
-} // namespace tint::spirv::writer
+} // namespace tint::ast::transform
diff --git a/src/tint/lang/spirv/writer/ast_raise/clamp_frag_depth.h b/src/tint/lang/wgsl/ast/transform/clamp_frag_depth.h
similarity index 91%
rename from src/tint/lang/spirv/writer/ast_raise/clamp_frag_depth.h
rename to src/tint/lang/wgsl/ast/transform/clamp_frag_depth.h
index 521ba2e..5bcd3ea 100644
--- a/src/tint/lang/spirv/writer/ast_raise/clamp_frag_depth.h
+++ b/src/tint/lang/wgsl/ast/transform/clamp_frag_depth.h
@@ -25,12 +25,12 @@
// 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_SPIRV_WRITER_AST_RAISE_CLAMP_FRAG_DEPTH_H_
-#define SRC_TINT_LANG_SPIRV_WRITER_AST_RAISE_CLAMP_FRAG_DEPTH_H_
+#ifndef SRC_TINT_LANG_WGSL_AST_TRANSFORM_CLAMP_FRAG_DEPTH_H_
+#define SRC_TINT_LANG_WGSL_AST_TRANSFORM_CLAMP_FRAG_DEPTH_H_
#include "src/tint/lang/wgsl/ast/transform/transform.h"
-namespace tint::spirv::writer {
+namespace tint::ast::transform {
/// Add clamping of the `@builtin(frag_depth)` output of fragment shaders using two push constants
/// provided by the outside environment. For example the following code:
@@ -78,6 +78,6 @@
struct State;
};
-} // namespace tint::spirv::writer
+} // namespace tint::ast::transform
-#endif // SRC_TINT_LANG_SPIRV_WRITER_AST_RAISE_CLAMP_FRAG_DEPTH_H_
+#endif // SRC_TINT_LANG_WGSL_AST_TRANSFORM_CLAMP_FRAG_DEPTH_H_
diff --git a/src/tint/lang/spirv/writer/ast_raise/clamp_frag_depth_test.cc b/src/tint/lang/wgsl/ast/transform/clamp_frag_depth_test.cc
similarity index 98%
rename from src/tint/lang/spirv/writer/ast_raise/clamp_frag_depth_test.cc
rename to src/tint/lang/wgsl/ast/transform/clamp_frag_depth_test.cc
index 9a71665..cc09c6f 100644
--- a/src/tint/lang/spirv/writer/ast_raise/clamp_frag_depth_test.cc
+++ b/src/tint/lang/wgsl/ast/transform/clamp_frag_depth_test.cc
@@ -25,11 +25,11 @@
// 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/spirv/writer/ast_raise/clamp_frag_depth.h"
+#include "src/tint/lang/wgsl/ast/transform/clamp_frag_depth.h"
#include "src/tint/lang/wgsl/ast/transform/helper_test.h"
-namespace tint::spirv::writer {
+namespace tint::ast::transform {
namespace {
using ClampFragDepthTest = ast::transform::TransformTest;
@@ -391,4 +391,4 @@
}
} // namespace
-} // namespace tint::spirv::writer
+} // namespace tint::ast::transform
diff --git a/src/tint/lang/wgsl/ast/transform/offset_first_index.cc b/src/tint/lang/wgsl/ast/transform/offset_first_index.cc
new file mode 100644
index 0000000..eb64f60
--- /dev/null
+++ b/src/tint/lang/wgsl/ast/transform/offset_first_index.cc
@@ -0,0 +1,201 @@
+// 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/transform/offset_first_index.h"
+
+#include <memory>
+#include <unordered_map>
+#include <utility>
+
+#include "src/tint/lang/core/builtin_value.h"
+#include "src/tint/lang/core/fluent_types.h"
+#include "src/tint/lang/wgsl/program/clone_context.h"
+#include "src/tint/lang/wgsl/program/program_builder.h"
+#include "src/tint/lang/wgsl/resolver/resolve.h"
+#include "src/tint/lang/wgsl/sem/function.h"
+#include "src/tint/lang/wgsl/sem/member_accessor_expression.h"
+#include "src/tint/lang/wgsl/sem/struct.h"
+#include "src/tint/lang/wgsl/sem/variable.h"
+
+using namespace tint::core::fluent_types; // NOLINT
+
+TINT_INSTANTIATE_TYPEINFO(tint::ast::transform::OffsetFirstIndex);
+TINT_INSTANTIATE_TYPEINFO(tint::ast::transform::OffsetFirstIndex::Config);
+
+namespace tint::ast::transform {
+namespace {
+
+// Push constant names
+constexpr char kFirstVertexName[] = "first_vertex";
+constexpr char kFirstInstanceName[] = "first_instance";
+
+bool ShouldRun(const Program& program) {
+ for (auto* fn : program.AST().Functions()) {
+ if (fn->PipelineStage() == PipelineStage::kVertex) {
+ return true;
+ }
+ }
+ return false;
+}
+
+} // namespace
+
+OffsetFirstIndex::OffsetFirstIndex() = default;
+OffsetFirstIndex::~OffsetFirstIndex() = default;
+
+Transform::ApplyResult OffsetFirstIndex::Apply(const Program& src,
+ const DataMap& inputs,
+ DataMap&) const {
+ if (!ShouldRun(src)) {
+ return SkipTransform;
+ }
+
+ const Config* cfg = inputs.Get<Config>();
+ if (!cfg) {
+ return SkipTransform;
+ }
+
+ ProgramBuilder b;
+ program::CloneContext ctx{&b, &src, /* auto_clone_symbols */ true};
+
+ // Map of builtin usages
+ std::unordered_map<const sem::Variable*, const char*> builtin_vars;
+ std::unordered_map<const core::type::StructMember*, const char*> builtin_members;
+
+ bool has_vertex_index = false;
+ bool has_instance_index = false;
+
+ // Traverse the AST scanning for builtin accesses via variables (includes
+ // parameters) or structure member accesses.
+ for (auto* node : ctx.src->ASTNodes().Objects()) {
+ if (auto* var = node->As<Variable>()) {
+ for (auto* attr : var->attributes) {
+ if (auto* builtin_attr = attr->As<BuiltinAttribute>()) {
+ core::BuiltinValue builtin = src.Sem().Get(builtin_attr)->Value();
+ if (builtin == core::BuiltinValue::kVertexIndex && cfg &&
+ cfg->first_vertex_offset.has_value()) {
+ auto* sem_var = ctx.src->Sem().Get(var);
+ builtin_vars.emplace(sem_var, kFirstVertexName);
+ has_vertex_index = true;
+ }
+ if (builtin == core::BuiltinValue::kInstanceIndex && cfg &&
+ cfg->first_instance_offset.has_value()) {
+ auto* sem_var = ctx.src->Sem().Get(var);
+ builtin_vars.emplace(sem_var, kFirstInstanceName);
+ has_instance_index = true;
+ }
+ }
+ }
+ }
+ if (auto* member = node->As<StructMember>()) {
+ for (auto* attr : member->attributes) {
+ if (auto* builtin_attr = attr->As<BuiltinAttribute>()) {
+ core::BuiltinValue builtin = src.Sem().Get(builtin_attr)->Value();
+ if (builtin == core::BuiltinValue::kVertexIndex && cfg &&
+ cfg->first_vertex_offset.has_value()) {
+ auto* sem_mem = ctx.src->Sem().Get(member);
+ builtin_members.emplace(sem_mem, kFirstVertexName);
+ has_vertex_index = true;
+ }
+ if (builtin == core::BuiltinValue::kInstanceIndex && cfg &&
+ cfg->first_instance_offset.has_value()) {
+ auto* sem_mem = ctx.src->Sem().Get(member);
+ builtin_members.emplace(sem_mem, kFirstInstanceName);
+ has_instance_index = true;
+ }
+ }
+ }
+ }
+ }
+
+ if (!has_vertex_index && !has_instance_index) {
+ return SkipTransform;
+ }
+
+ // Abort on any use of push constants in the module.
+ for (auto* global : src.AST().GlobalVariables()) {
+ if (auto* var = global->As<ast::Var>()) {
+ auto* v = src.Sem().Get(var);
+ if (TINT_UNLIKELY(v->AddressSpace() == core::AddressSpace::kPushConstant)) {
+ TINT_ICE()
+ << "OffsetFirstIndex doesn't know how to handle module that already use push "
+ "constants (yet)";
+ return resolver::Resolve(b);
+ }
+ }
+ }
+
+ b.Enable(wgsl::Extension::kChromiumExperimentalPushConstant);
+
+ // Add push constant members and calculate byte offsets
+ tint::Vector<const StructMember*, 8> members;
+ if (has_vertex_index) {
+ members.Push(b.Member(kFirstVertexName, b.ty.u32(),
+ Vector{b.MemberOffset(AInt(*cfg->first_vertex_offset))}));
+ }
+ if (has_instance_index) {
+ members.Push(b.Member(kFirstInstanceName, b.ty.u32(),
+ Vector{b.MemberOffset(AInt(*cfg->first_instance_offset))}));
+ }
+ auto struct_ = b.Structure(b.Symbols().New("PushConstants"), std::move(members));
+ // Create a global to hold the uniform buffer
+ Symbol buffer_name = b.Symbols().New("push_constants");
+ b.GlobalVar(buffer_name, b.ty.Of(struct_), core::AddressSpace::kPushConstant);
+
+ // Fix up all references to the builtins with the offsets
+ ctx.ReplaceAll([&](const Expression* expr) -> const Expression* {
+ if (auto* sem = ctx.src->Sem().GetVal(expr)) {
+ if (auto* user = sem->UnwrapLoad()->As<sem::VariableUser>()) {
+ auto it = builtin_vars.find(user->Variable());
+ if (it != builtin_vars.end()) {
+ return ctx.dst->Add(ctx.CloneWithoutTransform(expr),
+ ctx.dst->MemberAccessor(buffer_name, it->second));
+ }
+ }
+ if (auto* access = sem->As<sem::StructMemberAccess>()) {
+ auto it = builtin_members.find(access->Member());
+ if (it != builtin_members.end()) {
+ return ctx.dst->Add(ctx.CloneWithoutTransform(expr),
+ ctx.dst->MemberAccessor(buffer_name, it->second));
+ }
+ }
+ }
+ // Not interested in this expression. Just clone.
+ return nullptr;
+ });
+
+ ctx.Clone();
+ return resolver::Resolve(b);
+}
+
+OffsetFirstIndex::Config::Config(std::optional<int32_t> first_vertex_off,
+ std::optional<int32_t> first_instance_off)
+ : first_vertex_offset(first_vertex_off), first_instance_offset(first_instance_off) {}
+
+OffsetFirstIndex::Config::~Config() = default;
+
+} // namespace tint::ast::transform
diff --git a/src/tint/lang/wgsl/ast/transform/offset_first_index.h b/src/tint/lang/wgsl/ast/transform/offset_first_index.h
new file mode 100644
index 0000000..aa37559
--- /dev/null
+++ b/src/tint/lang/wgsl/ast/transform/offset_first_index.h
@@ -0,0 +1,111 @@
+// 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_TRANSFORM_OFFSET_FIRST_INDEX_H_
+#define SRC_TINT_LANG_WGSL_AST_TRANSFORM_OFFSET_FIRST_INDEX_H_
+
+#include "src/tint/lang/wgsl/ast/transform/transform.h"
+
+namespace tint::ast::transform {
+
+/// Adds firstVertex/Instance (injected via push constants) to
+/// vertex/instance index builtins.
+///
+/// This transform assumes that Name transform has been run before.
+///
+/// Some shading languages start vertex and instance numbering at 0,
+/// regardless of the firstVertex/firstInstance value specified. This transform
+/// adds the value of firstVertex/firstInstance to each builtin. This action is
+/// performed by adding a new push constant equal to original builtin +
+/// firstVertex/firstInstance to each function that references one of
+/// these builtins.
+///
+/// For D3D, this affects both firstVertex and firstInstance. For OpenGL,
+/// it applies to only firstInstance. For this reason, the first_vertex_offset
+/// and first_instance_offset are optional, where std::nullopt indicates that
+/// no subsitution is to be performed.
+///
+/// Before:
+/// ```
+/// @builtin(vertex_index) var<in> vert_idx : u32;
+/// @builtin(instance_index) var<in> inst_idx : u32;
+/// fn func() -> u32 {
+/// return vert_idx * inst_idx;
+/// }
+/// ```
+///
+/// After:
+/// ```
+/// struct PushConstants {
+/// first_vertex : u32,
+/// first_instance : u32,
+/// }
+///
+/// var<push_constant> push_constants : PushConstants;
+///
+/// @builtin(vertex_index) var<in> vert_idx : u32;
+/// @builtin(instance_index) var<in> inst_idx : u32;
+/// fn func() -> u32 {
+/// return (vert_idx + push_constants.first_vertex) * (inst_idx +
+/// push_constants.first_instance);
+/// }
+/// ```
+///
+class OffsetFirstIndex final : public Castable<OffsetFirstIndex, Transform> {
+ public:
+ /// Transform configuration options
+ struct Config final : public Castable<Config, ast::transform::Data> {
+ /// Constructor
+ /// @param first_vertex_off Offset of the firstVertex push constant
+ /// @param first_instance_off Location of the firstInstance push constant
+ Config(std::optional<int32_t> first_vertex_off, std::optional<int32_t> first_instance_off);
+
+ /// Destructor
+ ~Config() override;
+
+ /// Offset of the firstVertex push constant
+ const std::optional<uint32_t> first_vertex_offset;
+
+ /// Offset of the firstInstance push constant
+ const std::optional<uint32_t> first_instance_offset;
+ };
+
+ /// Constructor
+ OffsetFirstIndex();
+
+ /// Destructor
+ ~OffsetFirstIndex() override;
+
+ /// @copydoc Transform::Apply
+ ApplyResult Apply(const Program& program,
+ const DataMap& inputs,
+ DataMap& outputs) const override;
+};
+
+} // namespace tint::ast::transform
+
+#endif // SRC_TINT_LANG_WGSL_AST_TRANSFORM_OFFSET_FIRST_INDEX_H_
diff --git a/src/tint/lang/wgsl/ast/transform/offset_first_index_test.cc b/src/tint/lang/wgsl/ast/transform/offset_first_index_test.cc
new file mode 100644
index 0000000..37a79a9
--- /dev/null
+++ b/src/tint/lang/wgsl/ast/transform/offset_first_index_test.cc
@@ -0,0 +1,856 @@
+// 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/transform/offset_first_index.h"
+
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "src/tint/lang/wgsl/ast/transform/helper_test.h"
+
+namespace tint::ast::transform {
+namespace {
+
+using OffsetFirstIndexTest = TransformTest;
+
+TEST_F(OffsetFirstIndexTest, ShouldRunEmptyModule) {
+ auto* src = R"()";
+
+ DataMap config;
+ config.Add<OffsetFirstIndex::Config>(0, 4);
+ EXPECT_FALSE(ShouldRun<OffsetFirstIndex>(src, config));
+}
+
+TEST_F(OffsetFirstIndexTest, ShouldRunFragmentStage) {
+ auto* src = R"(
+@fragment
+fn entry() {
+ return;
+}
+)";
+
+ DataMap config;
+ config.Add<OffsetFirstIndex::Config>(0, 4);
+ EXPECT_FALSE(ShouldRun<OffsetFirstIndex>(src, config));
+}
+
+TEST_F(OffsetFirstIndexTest, ShouldRunVertexStage) {
+ auto* src = R"(
+@vertex
+fn entry() -> @builtin(position) vec4<f32> {
+ return vec4<f32>();
+}
+)";
+
+ DataMap config;
+ config.Add<OffsetFirstIndex::Config>(0, 4);
+ EXPECT_FALSE(ShouldRun<OffsetFirstIndex>(src, config));
+}
+
+TEST_F(OffsetFirstIndexTest, ShouldRunVertexStageWithVertexIndex) {
+ auto* src = R"(
+@vertex
+fn entry(@builtin(vertex_index) vert_idx : u32) -> @builtin(position) vec4<f32> {
+ return vec4<f32>();
+}
+)";
+
+ DataMap config;
+ config.Add<OffsetFirstIndex::Config>(0, 4);
+ EXPECT_TRUE(ShouldRun<OffsetFirstIndex>(src, config));
+}
+
+TEST_F(OffsetFirstIndexTest, ShouldRunVertexStageWithInstanceIndex) {
+ auto* src = R"(
+@vertex
+fn entry(@builtin(instance_index) inst_idx : u32) -> @builtin(position) vec4<f32> {
+ return vec4<f32>();
+}
+)";
+
+ DataMap config;
+ config.Add<OffsetFirstIndex::Config>(0, 4);
+ EXPECT_TRUE(ShouldRun<OffsetFirstIndex>(src, config));
+}
+
+TEST_F(OffsetFirstIndexTest, EmptyModule) {
+ auto* src = "";
+ auto* expect = "";
+
+ DataMap config;
+ config.Add<OffsetFirstIndex::Config>(0, 4);
+ auto got = Run<OffsetFirstIndex>(src, std::move(config));
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(OffsetFirstIndexTest, BasicVertexShader) {
+ auto* src = R"(
+@vertex
+fn entry() -> @builtin(position) vec4<f32> {
+ return vec4<f32>();
+}
+)";
+ auto* expect = src;
+
+ DataMap config;
+ config.Add<OffsetFirstIndex::Config>(0, 4);
+ auto got = Run<OffsetFirstIndex>(src, std::move(config));
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(OffsetFirstIndexTest, BasicModuleVertexIndex) {
+ auto* src = R"(
+fn test(vert_idx : u32) -> u32 {
+ return vert_idx;
+}
+
+@vertex
+fn entry(@builtin(vertex_index) vert_idx : u32) -> @builtin(position) vec4<f32> {
+ test(vert_idx);
+ return vec4<f32>();
+}
+)";
+
+ auto* expect = R"(
+enable chromium_experimental_push_constant;
+
+struct PushConstants {
+ /* @offset(0) */
+ first_vertex : u32,
+}
+
+var<push_constant> push_constants : PushConstants;
+
+fn test(vert_idx : u32) -> u32 {
+ return vert_idx;
+}
+
+@vertex
+fn entry(@builtin(vertex_index) vert_idx : u32) -> @builtin(position) vec4<f32> {
+ test((vert_idx + push_constants.first_vertex));
+ return vec4<f32>();
+}
+)";
+
+ DataMap config;
+ config.Add<OffsetFirstIndex::Config>(0, 4);
+ auto got = Run<OffsetFirstIndex>(src, std::move(config));
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(OffsetFirstIndexTest, BasicModuleVertexIndex_OutOfOrder) {
+ auto* src = R"(
+@vertex
+fn entry(@builtin(vertex_index) vert_idx : u32) -> @builtin(position) vec4<f32> {
+ test(vert_idx);
+ return vec4<f32>();
+}
+
+fn test(vert_idx : u32) -> u32 {
+ return vert_idx;
+}
+)";
+
+ auto* expect = R"(
+enable chromium_experimental_push_constant;
+
+struct PushConstants {
+ /* @offset(0) */
+ first_vertex : u32,
+}
+
+var<push_constant> push_constants : PushConstants;
+
+@vertex
+fn entry(@builtin(vertex_index) vert_idx : u32) -> @builtin(position) vec4<f32> {
+ test((vert_idx + push_constants.first_vertex));
+ return vec4<f32>();
+}
+
+fn test(vert_idx : u32) -> u32 {
+ return vert_idx;
+}
+)";
+
+ DataMap config;
+ config.Add<OffsetFirstIndex::Config>(0, 4);
+ auto got = Run<OffsetFirstIndex>(src, std::move(config));
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(OffsetFirstIndexTest, BasicModuleInstanceIndex) {
+ auto* src = R"(
+fn test(inst_idx : u32) -> u32 {
+ return inst_idx;
+}
+
+@vertex
+fn entry(@builtin(instance_index) inst_idx : u32) -> @builtin(position) vec4<f32> {
+ test(inst_idx);
+ return vec4<f32>();
+}
+)";
+
+ auto* expect = R"(
+enable chromium_experimental_push_constant;
+
+struct PushConstants {
+ @size(4)
+ padding_0 : u32,
+ /* @offset(4) */
+ first_instance : u32,
+}
+
+var<push_constant> push_constants : PushConstants;
+
+fn test(inst_idx : u32) -> u32 {
+ return inst_idx;
+}
+
+@vertex
+fn entry(@builtin(instance_index) inst_idx : u32) -> @builtin(position) vec4<f32> {
+ test((inst_idx + push_constants.first_instance));
+ return vec4<f32>();
+}
+)";
+
+ DataMap config;
+ config.Add<OffsetFirstIndex::Config>(0, 4);
+ auto got = Run<OffsetFirstIndex>(src, std::move(config));
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(OffsetFirstIndexTest, BasicModuleInstanceIndex_OutOfOrder) {
+ auto* src = R"(
+@vertex
+fn entry(@builtin(instance_index) inst_idx : u32) -> @builtin(position) vec4<f32> {
+ test(inst_idx);
+ return vec4<f32>();
+}
+
+fn test(inst_idx : u32) -> u32 {
+ return inst_idx;
+}
+)";
+
+ auto* expect = R"(
+enable chromium_experimental_push_constant;
+
+struct PushConstants {
+ @size(4)
+ padding_0 : u32,
+ /* @offset(4) */
+ first_instance : u32,
+}
+
+var<push_constant> push_constants : PushConstants;
+
+@vertex
+fn entry(@builtin(instance_index) inst_idx : u32) -> @builtin(position) vec4<f32> {
+ test((inst_idx + push_constants.first_instance));
+ return vec4<f32>();
+}
+
+fn test(inst_idx : u32) -> u32 {
+ return inst_idx;
+}
+)";
+
+ DataMap config;
+ config.Add<OffsetFirstIndex::Config>(0, 4);
+ auto got = Run<OffsetFirstIndex>(src, std::move(config));
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(OffsetFirstIndexTest, BasicModuleBothIndexes) {
+ auto* src = R"(
+fn test(instance_idx : u32, vert_idx : u32) -> u32 {
+ return instance_idx + vert_idx;
+}
+
+struct Inputs {
+ @builtin(instance_index) instance_idx : u32,
+ @builtin(vertex_index) vert_idx : u32,
+};
+
+@vertex
+fn entry(inputs : Inputs) -> @builtin(position) vec4<f32> {
+ test(inputs.instance_idx, inputs.vert_idx);
+ return vec4<f32>();
+}
+)";
+
+ auto* expect = R"(
+enable chromium_experimental_push_constant;
+
+struct PushConstants {
+ /* @offset(0) */
+ first_vertex : u32,
+ /* @offset(4) */
+ first_instance : u32,
+}
+
+var<push_constant> push_constants : PushConstants;
+
+fn test(instance_idx : u32, vert_idx : u32) -> u32 {
+ return (instance_idx + vert_idx);
+}
+
+struct Inputs {
+ @builtin(instance_index)
+ instance_idx : u32,
+ @builtin(vertex_index)
+ vert_idx : u32,
+}
+
+@vertex
+fn entry(inputs : Inputs) -> @builtin(position) vec4<f32> {
+ test((inputs.instance_idx + push_constants.first_instance), (inputs.vert_idx + push_constants.first_vertex));
+ return vec4<f32>();
+}
+)";
+
+ DataMap config;
+ config.Add<OffsetFirstIndex::Config>(0, 4);
+ auto got = Run<OffsetFirstIndex>(src, std::move(config));
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(OffsetFirstIndexTest, BasicModuleBothIndexes_OutOfOrder) {
+ auto* src = R"(
+@vertex
+fn entry(inputs : Inputs) -> @builtin(position) vec4<f32> {
+ test(inputs.instance_idx, inputs.vert_idx);
+ return vec4<f32>();
+}
+
+struct Inputs {
+ @builtin(instance_index) instance_idx : u32,
+ @builtin(vertex_index) vert_idx : u32,
+};
+
+fn test(instance_idx : u32, vert_idx : u32) -> u32 {
+ return instance_idx + vert_idx;
+}
+)";
+
+ auto* expect = R"(
+enable chromium_experimental_push_constant;
+
+struct PushConstants {
+ /* @offset(0) */
+ first_vertex : u32,
+ /* @offset(4) */
+ first_instance : u32,
+}
+
+var<push_constant> push_constants : PushConstants;
+
+@vertex
+fn entry(inputs : Inputs) -> @builtin(position) vec4<f32> {
+ test((inputs.instance_idx + push_constants.first_instance), (inputs.vert_idx + push_constants.first_vertex));
+ return vec4<f32>();
+}
+
+struct Inputs {
+ @builtin(instance_index)
+ instance_idx : u32,
+ @builtin(vertex_index)
+ vert_idx : u32,
+}
+
+fn test(instance_idx : u32, vert_idx : u32) -> u32 {
+ return (instance_idx + vert_idx);
+}
+)";
+
+ DataMap config;
+ config.Add<OffsetFirstIndex::Config>(0, 4);
+ auto got = Run<OffsetFirstIndex>(src, std::move(config));
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(OffsetFirstIndexTest, BasicModuleBothIndexesVertexDisabled) {
+ auto* src = R"(
+fn test(instance_idx : u32, vert_idx : u32) -> u32 {
+ return instance_idx + vert_idx;
+}
+
+struct Inputs {
+ @builtin(instance_index) instance_idx : u32,
+ @builtin(vertex_index) vert_idx : u32,
+};
+
+@vertex
+fn entry(inputs : Inputs) -> @builtin(position) vec4<f32> {
+ test(inputs.instance_idx, inputs.vert_idx);
+ return vec4<f32>();
+}
+)";
+
+ auto* expect = R"(
+enable chromium_experimental_push_constant;
+
+struct PushConstants {
+ /* @offset(0) */
+ first_instance : u32,
+}
+
+var<push_constant> push_constants : PushConstants;
+
+fn test(instance_idx : u32, vert_idx : u32) -> u32 {
+ return (instance_idx + vert_idx);
+}
+
+struct Inputs {
+ @builtin(instance_index)
+ instance_idx : u32,
+ @builtin(vertex_index)
+ vert_idx : u32,
+}
+
+@vertex
+fn entry(inputs : Inputs) -> @builtin(position) vec4<f32> {
+ test((inputs.instance_idx + push_constants.first_instance), inputs.vert_idx);
+ return vec4<f32>();
+}
+)";
+
+ DataMap config;
+ config.Add<OffsetFirstIndex::Config>(std::nullopt, 0);
+ auto got = Run<OffsetFirstIndex>(src, std::move(config));
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(OffsetFirstIndexTest, BasicModuleBothIndexesInstanceDisabled) {
+ auto* src = R"(
+fn test(instance_idx : u32, vert_idx : u32) -> u32 {
+ return instance_idx + vert_idx;
+}
+
+struct Inputs {
+ @builtin(instance_index) instance_idx : u32,
+ @builtin(vertex_index) vert_idx : u32,
+};
+
+@vertex
+fn entry(inputs : Inputs) -> @builtin(position) vec4<f32> {
+ test(inputs.instance_idx, inputs.vert_idx);
+ return vec4<f32>();
+}
+)";
+
+ auto* expect = R"(
+enable chromium_experimental_push_constant;
+
+struct PushConstants {
+ /* @offset(0) */
+ first_vertex : u32,
+}
+
+var<push_constant> push_constants : PushConstants;
+
+fn test(instance_idx : u32, vert_idx : u32) -> u32 {
+ return (instance_idx + vert_idx);
+}
+
+struct Inputs {
+ @builtin(instance_index)
+ instance_idx : u32,
+ @builtin(vertex_index)
+ vert_idx : u32,
+}
+
+@vertex
+fn entry(inputs : Inputs) -> @builtin(position) vec4<f32> {
+ test(inputs.instance_idx, (inputs.vert_idx + push_constants.first_vertex));
+ return vec4<f32>();
+}
+)";
+
+ DataMap config;
+ config.Add<OffsetFirstIndex::Config>(0, std::nullopt);
+ auto got = Run<OffsetFirstIndex>(src, std::move(config));
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(OffsetFirstIndexTest, BasicModuleBothIndexesBothDisabled) {
+ auto* src = R"(
+fn test(instance_idx : u32, vert_idx : u32) -> u32 {
+ return (instance_idx + vert_idx);
+}
+
+struct Inputs {
+ @builtin(instance_index)
+ instance_idx : u32,
+ @builtin(vertex_index)
+ vert_idx : u32,
+}
+
+@vertex
+fn entry(inputs : Inputs) -> @builtin(position) vec4<f32> {
+ test(inputs.instance_idx, inputs.vert_idx);
+ return vec4<f32>();
+}
+)";
+
+ auto* expect = src;
+
+ DataMap config;
+ config.Add<OffsetFirstIndex::Config>(std::nullopt, std::nullopt);
+ auto got = Run<OffsetFirstIndex>(src, std::move(config));
+
+ EXPECT_EQ(expect, str(got));
+}
+
+// Test a shader with a user-declared struct called PushConstants, to force
+// renaming of the Tint-provided PushConstants struct.
+TEST_F(OffsetFirstIndexTest, ForceRenamingPushConstantsStruct) {
+ auto* src = R"(
+struct PushConstants {
+ f : f32,
+}
+
+@group(0) @binding(0) var<uniform> p : PushConstants;
+
+@vertex
+fn entry(@builtin(vertex_index) vert_idx : u32) -> @builtin(position) vec4<f32> {
+ return vec4<f32>(f32(vert_idx) + p.f);
+}
+)";
+
+ auto* expect = R"(
+enable chromium_experimental_push_constant;
+
+struct PushConstants_1 {
+ /* @offset(0) */
+ first_vertex : u32,
+}
+
+var<push_constant> push_constants : PushConstants_1;
+
+struct PushConstants {
+ f : f32,
+}
+
+@group(0) @binding(0) var<uniform> p : PushConstants;
+
+@vertex
+fn entry(@builtin(vertex_index) vert_idx : u32) -> @builtin(position) vec4<f32> {
+ return vec4<f32>((f32((vert_idx + push_constants.first_vertex)) + p.f));
+}
+)";
+
+ DataMap config;
+ config.Add<OffsetFirstIndex::Config>(0, 4);
+ auto got = Run<OffsetFirstIndex>(src, std::move(config));
+
+ EXPECT_EQ(expect, str(got));
+}
+
+// Test a shader with a user-declared variable called push_constants, to force
+// renaming of the Tint-provided push_constants variable.
+TEST_F(OffsetFirstIndexTest, ForceRenamingPushConstantsVar) {
+ auto* src = R"(
+@group(0) @binding(0) var<uniform> push_constants : u32;
+
+@vertex
+fn entry(@builtin(vertex_index) vert_idx : u32) -> @builtin(position) vec4<f32> {
+ return vec4<f32>(f32(vert_idx));
+}
+)";
+
+ auto* expect = R"(
+enable chromium_experimental_push_constant;
+
+struct PushConstants {
+ /* @offset(0) */
+ first_vertex : u32,
+}
+
+var<push_constant> push_constants_1 : PushConstants;
+
+@group(0) @binding(0) var<uniform> push_constants : u32;
+
+@vertex
+fn entry(@builtin(vertex_index) vert_idx : u32) -> @builtin(position) vec4<f32> {
+ return vec4<f32>(f32((vert_idx + push_constants_1.first_vertex)));
+}
+)";
+
+ DataMap config;
+ config.Add<OffsetFirstIndex::Config>(0, 4);
+ auto got = Run<OffsetFirstIndex>(src, std::move(config));
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(OffsetFirstIndexTest, NestedCalls) {
+ auto* src = R"(
+fn func1(vert_idx : u32) -> u32 {
+ return vert_idx;
+}
+
+fn func2(vert_idx : u32) -> u32 {
+ return func1(vert_idx);
+}
+
+@vertex
+fn entry(@builtin(vertex_index) vert_idx : u32) -> @builtin(position) vec4<f32> {
+ func2(vert_idx);
+ return vec4<f32>();
+}
+)";
+
+ auto* expect = R"(
+enable chromium_experimental_push_constant;
+
+struct PushConstants {
+ /* @offset(0) */
+ first_vertex : u32,
+}
+
+var<push_constant> push_constants : PushConstants;
+
+fn func1(vert_idx : u32) -> u32 {
+ return vert_idx;
+}
+
+fn func2(vert_idx : u32) -> u32 {
+ return func1(vert_idx);
+}
+
+@vertex
+fn entry(@builtin(vertex_index) vert_idx : u32) -> @builtin(position) vec4<f32> {
+ func2((vert_idx + push_constants.first_vertex));
+ return vec4<f32>();
+}
+)";
+
+ DataMap config;
+ config.Add<OffsetFirstIndex::Config>(0, 4);
+ auto got = Run<OffsetFirstIndex>(src, std::move(config));
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(OffsetFirstIndexTest, NestedCalls_OutOfOrder) {
+ auto* src = R"(
+@vertex
+fn entry(@builtin(vertex_index) vert_idx : u32) -> @builtin(position) vec4<f32> {
+ func2(vert_idx);
+ return vec4<f32>();
+}
+
+fn func2(vert_idx : u32) -> u32 {
+ return func1(vert_idx);
+}
+
+fn func1(vert_idx : u32) -> u32 {
+ return vert_idx;
+}
+)";
+
+ auto* expect = R"(
+enable chromium_experimental_push_constant;
+
+struct PushConstants {
+ /* @offset(0) */
+ first_vertex : u32,
+}
+
+var<push_constant> push_constants : PushConstants;
+
+@vertex
+fn entry(@builtin(vertex_index) vert_idx : u32) -> @builtin(position) vec4<f32> {
+ func2((vert_idx + push_constants.first_vertex));
+ return vec4<f32>();
+}
+
+fn func2(vert_idx : u32) -> u32 {
+ return func1(vert_idx);
+}
+
+fn func1(vert_idx : u32) -> u32 {
+ return vert_idx;
+}
+)";
+
+ DataMap config;
+ config.Add<OffsetFirstIndex::Config>(0, 4);
+ auto got = Run<OffsetFirstIndex>(src, std::move(config));
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(OffsetFirstIndexTest, MultipleEntryPoints) {
+ auto* src = R"(
+fn func(i : u32) -> u32 {
+ return i;
+}
+
+@vertex
+fn entry_a(@builtin(vertex_index) vert_idx : u32) -> @builtin(position) vec4<f32> {
+ func(vert_idx);
+ return vec4<f32>();
+}
+
+@vertex
+fn entry_b(@builtin(vertex_index) vert_idx : u32, @builtin(instance_index) inst_idx : u32) -> @builtin(position) vec4<f32> {
+ func(vert_idx + inst_idx);
+ return vec4<f32>();
+}
+
+@vertex
+fn entry_c(@builtin(instance_index) inst_idx : u32) -> @builtin(position) vec4<f32> {
+ func(inst_idx);
+ return vec4<f32>();
+}
+)";
+
+ auto* expect = R"(
+enable chromium_experimental_push_constant;
+
+struct PushConstants {
+ /* @offset(0) */
+ first_vertex : u32,
+ /* @offset(4) */
+ first_instance : u32,
+}
+
+var<push_constant> push_constants : PushConstants;
+
+fn func(i : u32) -> u32 {
+ return i;
+}
+
+@vertex
+fn entry_a(@builtin(vertex_index) vert_idx : u32) -> @builtin(position) vec4<f32> {
+ func((vert_idx + push_constants.first_vertex));
+ return vec4<f32>();
+}
+
+@vertex
+fn entry_b(@builtin(vertex_index) vert_idx : u32, @builtin(instance_index) inst_idx : u32) -> @builtin(position) vec4<f32> {
+ func(((vert_idx + push_constants.first_vertex) + (inst_idx + push_constants.first_instance)));
+ return vec4<f32>();
+}
+
+@vertex
+fn entry_c(@builtin(instance_index) inst_idx : u32) -> @builtin(position) vec4<f32> {
+ func((inst_idx + push_constants.first_instance));
+ return vec4<f32>();
+}
+)";
+
+ DataMap config;
+ config.Add<OffsetFirstIndex::Config>(0, 4);
+ auto got = Run<OffsetFirstIndex>(src, std::move(config));
+
+ EXPECT_EQ(expect, str(got));
+}
+
+TEST_F(OffsetFirstIndexTest, MultipleEntryPoints_OutOfOrder) {
+ auto* src = R"(
+@vertex
+fn entry_a(@builtin(vertex_index) vert_idx : u32) -> @builtin(position) vec4<f32> {
+ func(vert_idx);
+ return vec4<f32>();
+}
+
+@vertex
+fn entry_b(@builtin(vertex_index) vert_idx : u32, @builtin(instance_index) inst_idx : u32) -> @builtin(position) vec4<f32> {
+ func(vert_idx + inst_idx);
+ return vec4<f32>();
+}
+
+@vertex
+fn entry_c(@builtin(instance_index) inst_idx : u32) -> @builtin(position) vec4<f32> {
+ func(inst_idx);
+ return vec4<f32>();
+}
+
+fn func(i : u32) -> u32 {
+ return i;
+}
+)";
+
+ auto* expect = R"(
+enable chromium_experimental_push_constant;
+
+struct PushConstants {
+ /* @offset(0) */
+ first_vertex : u32,
+ /* @offset(4) */
+ first_instance : u32,
+}
+
+var<push_constant> push_constants : PushConstants;
+
+@vertex
+fn entry_a(@builtin(vertex_index) vert_idx : u32) -> @builtin(position) vec4<f32> {
+ func((vert_idx + push_constants.first_vertex));
+ return vec4<f32>();
+}
+
+@vertex
+fn entry_b(@builtin(vertex_index) vert_idx : u32, @builtin(instance_index) inst_idx : u32) -> @builtin(position) vec4<f32> {
+ func(((vert_idx + push_constants.first_vertex) + (inst_idx + push_constants.first_instance)));
+ return vec4<f32>();
+}
+
+@vertex
+fn entry_c(@builtin(instance_index) inst_idx : u32) -> @builtin(position) vec4<f32> {
+ func((inst_idx + push_constants.first_instance));
+ return vec4<f32>();
+}
+
+fn func(i : u32) -> u32 {
+ return i;
+}
+)";
+
+ DataMap config;
+ config.Add<OffsetFirstIndex::Config>(0, 4);
+ auto got = Run<OffsetFirstIndex>(src, std::move(config));
+
+ EXPECT_EQ(expect, str(got));
+}
+
+} // namespace
+} // namespace tint::ast::transform
diff --git a/src/tint/lang/wgsl/diagnostic_severity.h b/src/tint/lang/wgsl/diagnostic_severity.h
index dfccb5d..88eba28 100644
--- a/src/tint/lang/wgsl/diagnostic_severity.h
+++ b/src/tint/lang/wgsl/diagnostic_severity.h
@@ -38,9 +38,9 @@
#define SRC_TINT_LANG_WGSL_DIAGNOSTIC_SEVERITY_H_
#include <string>
-#include <unordered_map>
#include "src/tint/lang/wgsl/diagnostic_rule.h"
+#include "src/tint/utils/containers/hashmap.h"
#include "src/tint/utils/diagnostic/diagnostic.h"
#include "src/tint/utils/traits/traits.h"
@@ -83,7 +83,7 @@
diag::Severity ToSeverity(DiagnosticSeverity sc);
/// DiagnosticRuleSeverities is a map from diagnostic rule to diagnostic severity.
-using DiagnosticRuleSeverities = std::unordered_map<DiagnosticRule, DiagnosticSeverity>;
+using DiagnosticRuleSeverities = Hashmap<DiagnosticRule, DiagnosticSeverity, 1>;
} // namespace tint::wgsl
diff --git a/src/tint/lang/wgsl/diagnostic_severity.h.tmpl b/src/tint/lang/wgsl/diagnostic_severity.h.tmpl
index 045591f..40714cb 100644
--- a/src/tint/lang/wgsl/diagnostic_severity.h.tmpl
+++ b/src/tint/lang/wgsl/diagnostic_severity.h.tmpl
@@ -15,11 +15,11 @@
#define SRC_TINT_LANG_WGSL_DIAGNOSTIC_SEVERITY_H_
#include <string>
-#include <unordered_map>
-#include "src/tint/utils/traits/traits.h"
#include "src/tint/lang/wgsl/diagnostic_rule.h"
+#include "src/tint/utils/containers/hashmap.h"
#include "src/tint/utils/diagnostic/diagnostic.h"
+#include "src/tint/utils/traits/traits.h"
namespace tint::wgsl {
@@ -30,7 +30,7 @@
diag::Severity ToSeverity(DiagnosticSeverity sc);
/// DiagnosticRuleSeverities is a map from diagnostic rule to diagnostic severity.
-using DiagnosticRuleSeverities = std::unordered_map<DiagnosticRule, DiagnosticSeverity>;
+using DiagnosticRuleSeverities = Hashmap<DiagnosticRule, DiagnosticSeverity, 1>;
} // namespace tint::wgsl
diff --git a/src/tint/lang/wgsl/features/status.cc b/src/tint/lang/wgsl/features/status.cc
index 2fe2f02..334c1b6 100644
--- a/src/tint/lang/wgsl/features/status.cc
+++ b/src/tint/lang/wgsl/features/status.cc
@@ -33,14 +33,23 @@
FeatureStatus GetLanguageFeatureStatus(LanguageFeature f) {
switch (f) {
+ ////////////////////////////////////////////////////////////////////
+ // Experimental features
+ ///////////////////////////////////////////////////////////////////
case LanguageFeature::kPacked4X8IntegerDotProduct:
case LanguageFeature::kPointerCompositeAccess:
case LanguageFeature::kReadonlyAndReadwriteStorageTextures:
- case LanguageFeature::kUnrestrictedPointerParameters:
return FeatureStatus::kExperimental;
- case LanguageFeature::kUndefined:
- return FeatureStatus::kUnknown;
+ ////////////////////////////////////////////////////////////////////
+ // Enabled features
+ ////////////////////////////////////////////////////////////////////
+ case LanguageFeature::kUnrestrictedPointerParameters:
+ return FeatureStatus::kShippedWithKillswitch;
+
+ ////////////////////////////////////////////////////////////////////
+ // Testing / special cases
+ ////////////////////////////////////////////////////////////////////
case LanguageFeature::kChromiumTestingUnimplemented:
return FeatureStatus::kUnimplemented;
case LanguageFeature::kChromiumTestingUnsafeExperimental:
@@ -51,6 +60,8 @@
return FeatureStatus::kShippedWithKillswitch;
case LanguageFeature::kChromiumTestingShipped:
return FeatureStatus::kShipped;
+ case LanguageFeature::kUndefined:
+ return FeatureStatus::kUnknown;
}
return FeatureStatus::kUnknown;
diff --git a/src/tint/lang/wgsl/inspector/inspector.cc b/src/tint/lang/wgsl/inspector/inspector.cc
index d7fe564..6c5d935 100644
--- a/src/tint/lang/wgsl/inspector/inspector.cc
+++ b/src/tint/lang/wgsl/inspector/inspector.cc
@@ -814,14 +814,14 @@
}
auto* call_func = call->Stmt()->Function();
- std::vector<const sem::Function*> entry_points;
+ Vector<const sem::Function*, 4> entry_points;
if (call_func->Declaration()->IsEntryPoint()) {
entry_points = {call_func};
} else {
entry_points = call_func->AncestorEntryPoints();
}
- if (entry_points.empty()) {
+ if (entry_points.IsEmpty()) {
continue;
}
@@ -974,7 +974,7 @@
globals[i] = global;
} else if (auto* param = root_ident->As<sem::Parameter>()) {
auto* func = tint::As<sem::Function>(param->Owner());
- if (func->CallSites().empty()) {
+ if (func->CallSites().IsEmpty()) {
// One or more of the expressions is a parameter, but this function
// is not called. Ignore.
return;
@@ -1141,6 +1141,7 @@
});
}
}
+
return res;
}
diff --git a/src/tint/lang/wgsl/ir_roundtrip_test.cc b/src/tint/lang/wgsl/ir_roundtrip_test.cc
index d3497d0..9b7b522 100644
--- a/src/tint/lang/wgsl/ir_roundtrip_test.cc
+++ b/src/tint/lang/wgsl/ir_roundtrip_test.cc
@@ -256,7 +256,7 @@
struct S {
a : i32,
- @location(0u) @index(0u)
+ @location(0u) @blend_src(0u)
b : u32,
c : f32,
}
diff --git a/src/tint/lang/wgsl/reader/parser/const_literal_test.cc b/src/tint/lang/wgsl/reader/parser/const_literal_test.cc
index 4cb239f..eff472c 100644
--- a/src/tint/lang/wgsl/reader/parser/const_literal_test.cc
+++ b/src/tint/lang/wgsl/reader/parser/const_literal_test.cc
@@ -147,7 +147,8 @@
EXPECT_EQ(c->As<ast::FloatLiteralExpression>()->suffix,
ast::FloatLiteralExpression::Suffix::kNone);
}
- EXPECT_EQ(c->source.range, (Source::Range{{1u, 1u}, {1u, 1u + params.input.size()}}));
+ EXPECT_EQ(c->source.range,
+ (Source::Range{{1u, 1u}, {1u, 1u + static_cast<uint32_t>(params.input.size())}}));
}
using FloatLiteralTestCaseList = std::vector<FloatLiteralTestCase>;
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 a38fd87..d818893 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', 'builtin', 'color', 'compute', 'diagnostic', 'fragment', 'group', 'id', 'index', 'interpolate', 'invariant', 'location', 'must_use', 'size', 'vertex', 'workgroup_size'
+Possible values: 'align', 'binding', 'blend_src', 'builtin', 'color', 'compute', 'diagnostic', 'fragment', 'group', 'id', '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', 'builtin', 'color', 'compute', 'diagnostic', 'fragment', 'group', 'id', 'index', 'interpolate', 'invariant', 'location', 'must_use', 'size', 'vertex', 'workgroup_size'
+Possible values: 'align', 'binding', 'blend_src', 'builtin', 'color', 'compute', 'diagnostic', 'fragment', 'group', 'id', '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 4fae501..3e66246 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
@@ -31,7 +31,7 @@
namespace tint::wgsl::reader {
namespace {
-TEST_F(WGSLParserTest, AttributeList_Parses) {
+TEST_F(WGSLParserTest, FunctionAttributeList_Parses) {
auto p = parser("@workgroup_size(2) @compute");
auto attrs = p->attribute_list();
EXPECT_FALSE(p->has_error()) << p->error();
@@ -57,7 +57,7 @@
EXPECT_EQ(attr_1->As<ast::StageAttribute>()->stage, ast::PipelineStage::kCompute);
}
-TEST_F(WGSLParserTest, AttributeList_Invalid) {
+TEST_F(WGSLParserTest, FunctionAttributeList_Invalid) {
auto p = parser("@invalid");
auto attrs = p->attribute_list();
EXPECT_TRUE(p->has_error());
@@ -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', 'builtin', 'color', 'compute', 'diagnostic', 'fragment', 'group', 'id', 'index', 'interpolate', 'invariant', 'location', 'must_use', 'size', 'vertex', 'workgroup_size')");
+Possible values: 'align', 'binding', 'blend_src', 'builtin', 'color', 'compute', 'diagnostic', 'fragment', 'group', 'id', 'interpolate', 'invariant', 'location', 'must_use', 'size', 'vertex', 'workgroup_size')");
}
} // namespace
diff --git a/src/tint/lang/wgsl/reader/parser/lexer.cc b/src/tint/lang/wgsl/reader/parser/lexer.cc
index a133cb6..1ee2bcb 100644
--- a/src/tint/lang/wgsl/reader/parser/lexer.cc
+++ b/src/tint/lang/wgsl/reader/parser/lexer.cc
@@ -58,7 +58,10 @@
// programs and being a bit bigger then those need (atan2-const-eval is the outlier here).
static constexpr size_t kDefaultListSize = 4092;
-bool read_blankspace(std::string_view str, size_t i, bool* is_blankspace, size_t* blankspace_size) {
+bool read_blankspace(std::string_view str,
+ size_t i,
+ bool* is_blankspace,
+ uint32_t* blankspace_size) {
// See https://www.w3.org/TR/WGSL/#blankspace
auto* utf8 = reinterpret_cast<const uint8_t*>(&str[i]);
@@ -75,7 +78,7 @@
if (cp == kSpace || cp == kHTab || cp == kL2R || cp == kR2L) {
*is_blankspace = true;
- *blankspace_size = n;
+ *blankspace_size = static_cast<uint32_t>(n);
return true;
}
@@ -139,15 +142,15 @@
return file_->content.lines[location_.line - 1];
}
-size_t Lexer::pos() const {
+uint32_t Lexer::pos() const {
return location_.column - 1;
}
-size_t Lexer::length() const {
- return line().size();
+uint32_t Lexer::length() const {
+ return static_cast<uint32_t>(line().size());
}
-const char& Lexer::at(size_t pos) const {
+const char& Lexer::at(uint32_t pos) const {
auto l = line();
// Unlike for std::string, if pos == l.size(), indexing `l[pos]` is UB for
// std::string_view.
@@ -158,15 +161,15 @@
return l[pos];
}
-std::string_view Lexer::substr(size_t offset, size_t count) {
+std::string_view Lexer::substr(uint32_t offset, uint32_t count) {
return line().substr(offset, count);
}
-void Lexer::advance(size_t offset) {
+void Lexer::advance(uint32_t offset) {
location_.column += offset;
}
-void Lexer::set_pos(size_t pos) {
+void Lexer::set_pos(uint32_t pos) {
location_.column = pos + 1;
}
@@ -235,19 +238,18 @@
bool Lexer::is_digit(char ch) const {
return std::isdigit(static_cast<unsigned char>(ch));
}
-
bool Lexer::is_hex(char ch) const {
return std::isxdigit(static_cast<unsigned char>(ch));
}
-bool Lexer::matches(size_t pos, std::string_view sub_string) {
+bool Lexer::matches(uint32_t pos, std::string_view sub_string) {
if (pos >= length()) {
return false;
}
- return substr(pos, sub_string.size()) == sub_string;
+ return substr(pos, static_cast<uint32_t>(sub_string.size())) == sub_string;
}
-bool Lexer::matches(size_t pos, char ch) {
+bool Lexer::matches(uint32_t pos, char ch) {
if (pos >= length()) {
return false;
}
@@ -264,7 +266,7 @@
}
bool is_blankspace;
- size_t blankspace_size;
+ uint32_t blankspace_size;
if (!read_blankspace(line(), pos(), &is_blankspace, &blankspace_size)) {
return Token{Token::Type::kError, begin_source(), "invalid UTF-8"};
}
@@ -383,7 +385,7 @@
}
// Parse the exponent if one exists
- std::optional<size_t> exponent_value_position;
+ std::optional<uint32_t> exponent_value_position;
bool negative_exponent = false;
if (end < length() && (matches(end, 'e') || matches(end, 'E'))) {
end++;
@@ -893,8 +895,8 @@
}
Token Lexer::build_token_from_int_if_possible(Source source,
- size_t start,
- size_t prefix_count,
+ uint32_t start,
+ uint32_t prefix_count,
int32_t base) {
const char* start_ptr = &at(start);
// The call to `from_chars` will return the pointer to just after the last parsed character.
@@ -907,7 +909,7 @@
int64_t value = 0;
auto res = std::from_chars(start_ptr, end_ptr, value, base);
const bool overflow = res.ec != std::errc();
- advance(static_cast<size_t>(res.ptr - start_ptr) + prefix_count);
+ advance(static_cast<uint32_t>(res.ptr - start_ptr) + prefix_count);
if (matches(pos(), 'u')) {
if (!overflow && core::CheckedConvert<u32>(AInt(value)) == Success) {
@@ -993,7 +995,7 @@
return {};
}
// Consume start codepoint
- advance(n);
+ advance(static_cast<uint32_t>(n));
}
while (!is_eol()) {
@@ -1009,7 +1011,7 @@
}
// Consume continuing codepoint
- advance(n);
+ advance(static_cast<uint32_t>(n));
if (pos() - start == 2 && substr(start, 2) == "__") {
// Identifiers prefixed with two or more underscores are not allowed.
diff --git a/src/tint/lang/wgsl/reader/parser/lexer.h b/src/tint/lang/wgsl/reader/parser/lexer.h
index 6e97551..50cce07 100644
--- a/src/tint/lang/wgsl/reader/parser/lexer.h
+++ b/src/tint/lang/wgsl/reader/parser/lexer.h
@@ -61,8 +61,8 @@
std::optional<Token> skip_comment();
Token build_token_from_int_if_possible(Source source,
- size_t start,
- size_t prefix_count,
+ uint32_t start,
+ uint32_t prefix_count,
int32_t base);
std::optional<Token::Type> parse_keyword(std::string_view);
@@ -88,17 +88,17 @@
/// @returns view of current line
std::string_view line() const;
/// @returns position in current line
- size_t pos() const;
+ uint32_t pos() const;
/// @returns length of current line
- size_t length() const;
+ uint32_t length() const;
/// @returns reference to character at `pos` within current line
- const char& at(size_t pos) const;
+ const char& at(uint32_t pos) const;
/// @returns substring view at `offset` within current line of length `count`
- std::string_view substr(size_t offset, size_t count);
+ std::string_view substr(uint32_t offset, uint32_t count);
/// advances current position by `offset` within current line
- void advance(size_t offset = 1);
+ void advance(uint32_t offset = 1);
/// sets current position to `pos` within current line
- void set_pos(size_t pos);
+ void set_pos(uint32_t pos);
/// advances current position to next line
void advance_line();
/// @returns true if the end of the input has been reached.
@@ -115,9 +115,9 @@
/// @returns true if 'ch' is a hexadecimal digit
bool is_hex(char ch) const;
/// @returns true if string at `pos` matches `substr`
- bool matches(size_t pos, std::string_view substr);
+ bool matches(uint32_t pos, std::string_view substr);
/// @returns true if char at `pos` matches `ch`
- bool matches(size_t pos, char ch);
+ bool matches(uint32_t pos, char ch);
/// The source file content
Source::File const* const file_;
/// The current location within the input
diff --git a/src/tint/lang/wgsl/reader/parser/parser.cc b/src/tint/lang/wgsl/reader/parser/parser.cc
index 104f37d..b00c274 100644
--- a/src/tint/lang/wgsl/reader/parser/parser.cc
+++ b/src/tint/lang/wgsl/reader/parser/parser.cc
@@ -3099,6 +3099,8 @@
return create<ast::StructMemberAlignAttribute>(t.source(), args[0]);
case core::Attribute::kBinding:
return create<ast::BindingAttribute>(t.source(), args[0]);
+ case core::Attribute::kBlendSrc:
+ return create<ast::BlendSrcAttribute>(t.source(), args[0]);
case core::Attribute::kBuiltin:
return create<ast::BuiltinAttribute>(t.source(), args[0]);
case core::Attribute::kColor:
@@ -3111,8 +3113,6 @@
return create<ast::GroupAttribute>(t.source(), args[0]);
case core::Attribute::kId:
return create<ast::IdAttribute>(t.source(), args[0]);
- case core::Attribute::kIndex:
- return create<ast::IndexAttribute>(t.source(), args[0]);
case core::Attribute::kInterpolate:
return create<ast::InterpolateAttribute>(t.source(), args[0],
args.Length() == 2 ? args[1] : nullptr);
diff --git a/src/tint/lang/wgsl/reader/parser/struct_member_attribute_test.cc b/src/tint/lang/wgsl/reader/parser/struct_member_attribute_test.cc
index f4169ac..2c93c6e 100644
--- a/src/tint/lang/wgsl/reader/parser/struct_member_attribute_test.cc
+++ b/src/tint/lang/wgsl/reader/parser/struct_member_attribute_test.cc
@@ -240,8 +240,8 @@
)");
}
-TEST_F(WGSLParserTest, Attribute_Index) {
- auto p = parser("index(1)");
+TEST_F(WGSLParserTest, Attribute_BlendSrc) {
+ auto p = parser("blend_src(1)");
auto attr = p->attribute();
EXPECT_TRUE(attr.matched);
EXPECT_FALSE(attr.errored);
@@ -250,9 +250,9 @@
auto* member_attr = attr.value->As<ast::Attribute>();
ASSERT_NE(member_attr, nullptr);
- ASSERT_TRUE(member_attr->Is<ast::IndexAttribute>());
+ ASSERT_TRUE(member_attr->Is<ast::BlendSrcAttribute>());
- auto* o = member_attr->As<ast::IndexAttribute>();
+ auto* o = member_attr->As<ast::BlendSrcAttribute>();
ASSERT_TRUE(o->expr->Is<ast::IntLiteralExpression>());
EXPECT_EQ(o->expr->As<ast::IntLiteralExpression>()->value, 1);
}
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 417ab1f..7b82086 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
@@ -31,7 +31,7 @@
namespace tint::wgsl::reader {
namespace {
-TEST_F(WGSLParserTest, AttributeList_Parses) {
+TEST_F(WGSLParserTest, VariableAttributeList_Parses) {
auto p = parser(R"(@location(4) @builtin(position))");
auto attrs = p->attribute_list();
ASSERT_FALSE(p->has_error()) << p->error();
@@ -55,7 +55,7 @@
ast::CheckIdentifier(attr_1->As<ast::BuiltinAttribute>()->builtin, "position");
}
-TEST_F(WGSLParserTest, AttributeList_Invalid) {
+TEST_F(WGSLParserTest, VariableAttributeList_Invalid) {
auto p = parser(R"(@invalid)");
auto attrs = p->attribute_list();
EXPECT_TRUE(p->has_error());
@@ -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', 'builtin', 'color', 'compute', 'diagnostic', 'fragment', 'group', 'id', 'index', 'interpolate', 'invariant', 'location', 'must_use', 'size', 'vertex', 'workgroup_size')");
+Possible values: 'align', 'binding', 'blend_src', 'builtin', 'color', 'compute', 'diagnostic', 'fragment', 'group', 'id', 'interpolate', 'invariant', 'location', 'must_use', 'size', 'vertex', 'workgroup_size')");
}
} // namespace
diff --git a/src/tint/lang/wgsl/reader/reader.cc b/src/tint/lang/wgsl/reader/reader.cc
index 3ddc2ae..77289d1 100644
--- a/src/tint/lang/wgsl/reader/reader.cc
+++ b/src/tint/lang/wgsl/reader/reader.cc
@@ -27,6 +27,7 @@
#include "src/tint/lang/wgsl/reader/reader.h"
+#include <limits>
#include <utility>
#include "src/tint/lang/wgsl/reader/lower/lower.h"
@@ -37,6 +38,13 @@
namespace tint::wgsl::reader {
Program Parse(const Source::File* file, const Options& options) {
+ if (TINT_UNLIKELY(file->content.data.size() >
+ static_cast<size_t>(std::numeric_limits<uint32_t>::max()))) {
+ ProgramBuilder b;
+ b.Diagnostics().add_error(tint::diag::System::Reader,
+ "WGSL source must be 0xffffffff bytes or fewer");
+ return Program(std::move(b));
+ }
Parser parser(file);
parser.Parse();
return resolver::Resolve(parser.builder(), options.allowed_features);
diff --git a/src/tint/lang/wgsl/resolver/alias_analysis_test.cc b/src/tint/lang/wgsl/resolver/alias_analysis_test.cc
index 0d9e0bb..e7bd78f 100644
--- a/src/tint/lang/wgsl/resolver/alias_analysis_test.cc
+++ b/src/tint/lang/wgsl/resolver/alias_analysis_test.cc
@@ -50,8 +50,8 @@
// target(&v1, aliased ? &v1 : &v2);
// }
struct TwoPointerConfig {
- core::AddressSpace address_space; // The address space for the pointers.
- bool aliased; // Whether the pointers alias or not.
+ const core::AddressSpace address_space; // The address space for the pointers.
+ const bool aliased; // Whether the pointers alias or not.
};
class TwoPointers : public ResolverTestWithParam<TwoPointerConfig> {
protected:
@@ -179,7 +179,7 @@
// f1(p1);
// f2(p2);
Func("f1",
- Vector<const ast::Parameter*, 4>{
+ Vector{
Param("p1", ty.ptr<i32>(GetParam().address_space)),
},
ty.void_(),
@@ -187,7 +187,7 @@
Assign(Phony(), Deref("p1")),
});
Func("f2",
- Vector<const ast::Parameter*, 4>{
+ Vector{
Param("p2", ty.ptr<i32>(GetParam().address_space)),
},
ty.void_(),
@@ -240,7 +240,7 @@
void Run(Vector<const ast::Statement*, 4>&& body, const char* err = nullptr) {
Func("target",
- Vector<const ast::Parameter*, 4>{
+ Vector{
Param("p1", ty.ptr<i32>(core::AddressSpace::kPrivate)),
},
ty.void_(), std::move(body));
@@ -309,7 +309,7 @@
//
// f1(p1);
Func("f2",
- Vector<const ast::Parameter*, 4>{
+ Vector{
Param("p1", ty.ptr<i32>(core::AddressSpace::kPrivate)),
},
ty.void_(),
@@ -317,7 +317,7 @@
Assign(Deref("p1"), 42_a),
});
Func("f1",
- Vector<const ast::Parameter*, 4>{
+ Vector{
Param("p1", ty.ptr<i32>(core::AddressSpace::kPrivate)),
},
ty.void_(),
@@ -344,7 +344,7 @@
//
// f1(p1);
Func("f2",
- Vector<const ast::Parameter*, 4>{
+ Vector{
Param("p1", ty.ptr<i32>(core::AddressSpace::kPrivate)),
},
ty.void_(),
@@ -353,7 +353,7 @@
Assign(Expr(Source{{56, 78}}, "global_1"), 42_a),
});
Func("f1",
- Vector<const ast::Parameter*, 4>{
+ Vector{
Param("p1", ty.ptr<i32>(core::AddressSpace::kPrivate)),
},
ty.void_(),
@@ -379,7 +379,7 @@
//
// f1(p1);
Func("f2",
- Vector<const ast::Parameter*, 4>{
+ Vector{
Param("p1", ty.ptr<i32>(core::AddressSpace::kPrivate)),
},
ty.void_(),
@@ -387,7 +387,7 @@
Assign(Phony(), Deref("p1")),
});
Func("f1",
- Vector<const ast::Parameter*, 4>{
+ Vector{
Param("p1", ty.ptr<i32>(core::AddressSpace::kPrivate)),
},
ty.void_(),
@@ -939,5 +939,433 @@
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
+////////////////////////////////////////////////////////////////////////////////
+// Atomics
+////////////////////////////////////////////////////////////////////////////////
+class AtomicPointers
+ : public ResolverTestWithParam<
+ std::tuple<wgsl::BuiltinFn, wgsl::BuiltinFn, core::AddressSpace, bool /* aliased */>> {
+ protected:
+ static constexpr std::string_view kPass = "<PASS>";
+
+ ast::Type Ptr() {
+ auto address_space = std::get<2>(GetParam());
+ if (address_space == storage) {
+ return ty.ptr<storage, atomic<i32>, read_write>();
+ } else {
+ return ty.ptr<atomic<i32>>(address_space);
+ }
+ }
+
+ void SetUp() override {
+ auto address_space = std::get<2>(GetParam());
+ if (address_space == storage) {
+ GlobalVar("v1", address_space, read_write, ty.Of<atomic<i32>>(), //
+ Binding(0_a), Group(0_a));
+ GlobalVar("v2", address_space, read_write, ty.Of<atomic<i32>>(), //
+ Binding(1_a), Group(0_a));
+ } else {
+ GlobalVar("v1", address_space, ty.Of<atomic<i32>>());
+ GlobalVar("v2", address_space, ty.Of<atomic<i32>>());
+ }
+ }
+
+ bool IsWrite(wgsl::BuiltinFn fn) const {
+ switch (fn) {
+ case wgsl::BuiltinFn::kAtomicStore:
+ case wgsl::BuiltinFn::kAtomicAdd:
+ case wgsl::BuiltinFn::kAtomicSub:
+ case wgsl::BuiltinFn::kAtomicMax:
+ case wgsl::BuiltinFn::kAtomicMin:
+ case wgsl::BuiltinFn::kAtomicAnd:
+ case wgsl::BuiltinFn::kAtomicOr:
+ case wgsl::BuiltinFn::kAtomicXor:
+ case wgsl::BuiltinFn::kAtomicExchange:
+ case wgsl::BuiltinFn::kAtomicCompareExchangeWeak:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ bool ShouldPass() const {
+ auto [builtin_a, builtin_b, space, aliased] = GetParam();
+ bool fail = aliased && (IsWrite(builtin_a) || IsWrite(builtin_b));
+ return !fail;
+ }
+
+ const ast::Statement* CallBuiltin(wgsl::BuiltinFn fn, std::string_view ptr) {
+ switch (fn) {
+ case wgsl::BuiltinFn::kAtomicLoad:
+ return CallStmt(Call(fn, ptr));
+ case wgsl::BuiltinFn::kAtomicStore:
+ case wgsl::BuiltinFn::kAtomicAdd:
+ case wgsl::BuiltinFn::kAtomicSub:
+ case wgsl::BuiltinFn::kAtomicMax:
+ case wgsl::BuiltinFn::kAtomicMin:
+ case wgsl::BuiltinFn::kAtomicAnd:
+ case wgsl::BuiltinFn::kAtomicOr:
+ case wgsl::BuiltinFn::kAtomicXor:
+ case wgsl::BuiltinFn::kAtomicExchange:
+ return CallStmt(Call(fn, ptr, 42_a));
+ case wgsl::BuiltinFn::kAtomicCompareExchangeWeak:
+ return CallStmt(Call(fn, ptr, 10_a, 42_a));
+ default:
+ TINT_UNIMPLEMENTED() << fn;
+ return nullptr;
+ }
+ }
+
+ std::string Run() {
+ if (r()->Resolve()) {
+ return std::string(kPass);
+ }
+ return r()->error();
+ }
+};
+
+TEST_P(AtomicPointers, CallDirect) {
+ // var<ADDRESS_SPACE> v1 : atomic<i32>;
+ // var<ADDRESS_SPACE> v2 : atomic<i32>;
+ //
+ // fn caller() {
+ // callee(&v1, aliased ? &v1 : &v2);
+ // }
+ //
+ // fn callee(p1 : PTR, p2 : PTR) {
+ // <builtin-a>(p1);
+ // <builtin-b>(p2);
+ // }
+ auto [builtin_a, builtin_b, space, aliased] = GetParam();
+
+ Func("caller", tint::Empty, ty.void_(),
+ Vector{
+ CallStmt(Call("callee", //
+ AddressOf(Source{{12, 34}}, "v1"),
+ AddressOf(Source{{56, 78}}, aliased ? "v1" : "v2"))),
+ });
+
+ Func("callee", Vector{Param("p1", Ptr()), Param("p2", Ptr())}, ty.void_(),
+ Vector{
+ CallBuiltin(builtin_a, "p1"),
+ CallBuiltin(builtin_b, "p2"),
+ });
+
+ EXPECT_EQ(Run(), ShouldPass() ? kPass : R"(56:78 error: invalid aliased pointer argument
+12:34 note: aliases with another argument passed here)");
+}
+
+TEST_P(AtomicPointers, CallThroughChain) {
+ // var<ADDRESS_SPACE> v1 : atomic<i32>;
+ // var<ADDRESS_SPACE> v2 : atomic<i32>;
+ //
+ // fn caller() {
+ // callee(&v1, aliased ? &v1 : &v2);
+ // }
+ //
+ // fn f2(p1 : PTR, p2 : PTR) {
+ // f1(p1, p2);
+ // }
+ //
+ // fn f1(p1 : PTR, p2 : PTR) {
+ // callee(p1, p2);
+ // }
+ //
+ // fn callee(p1 : PTR, p2 : PTR) {
+ // <builtin-a>(p1);
+ // <builtin-b>(p2);
+ // }
+ auto [builtin_a, builtin_b, space, aliased] = GetParam();
+
+ Func("caller", tint::Empty, ty.void_(),
+ Vector{
+ CallStmt(Call("callee", //
+ AddressOf(Source{{12, 34}}, "v1"),
+ AddressOf(Source{{56, 78}}, aliased ? "v1" : "v2"))),
+ });
+
+ Func("f2", Vector{Param("p1", Ptr()), Param("p2", Ptr())}, ty.void_(),
+ Vector{
+ CallStmt(Call("f1", "p1", "p2")),
+ });
+
+ Func("f1", Vector{Param("p1", Ptr()), Param("p2", Ptr())}, ty.void_(),
+ Vector{
+ CallStmt(Call("callee", "p1", "p2")),
+ });
+
+ Func("callee", Vector{Param("p1", Ptr()), Param("p2", Ptr())}, ty.void_(),
+ Vector{
+ CallBuiltin(builtin_a, "p1"),
+ CallBuiltin(builtin_b, "p2"),
+ });
+
+ EXPECT_EQ(Run(), ShouldPass() ? kPass : R"(56:78 error: invalid aliased pointer argument
+12:34 note: aliases with another argument passed here)");
+}
+
+TEST_P(AtomicPointers, ReadWriteAcrossDifferentFunctions) {
+ // var<ADDRESS_SPACE> v1 : atomic<i32>;
+ // var<ADDRESS_SPACE> v2 : atomic<i32>;
+ //
+ // fn caller() {
+ // f(&v1, aliased ? &v1 : &v2);
+ // }
+ //
+ // fn f(p1 : PTR, p2 : PTR) {
+ // f1(p1);
+ // f2(p2);
+ // }
+ //
+ // fn f1(p : PTR) {
+ // <builtin-a>(p);
+ // }
+ //
+ // fn f2(p : PTR) {
+ // <builtin-b>(p);
+ // }
+ auto [builtin_a, builtin_b, space, aliased] = GetParam();
+
+ Func("caller", tint::Empty, ty.void_(),
+ Vector{
+ CallStmt(Call("f", //
+ AddressOf(Source{{12, 34}}, "v1"),
+ AddressOf(Source{{56, 78}}, aliased ? "v1" : "v2"))),
+ });
+
+ Func("f", Vector{Param("p1", Ptr()), Param("p2", Ptr())}, ty.void_(),
+ Vector{
+ CallStmt(Call("f1", "p1")),
+ CallStmt(Call("f2", "p2")),
+ });
+
+ Func("f1", Vector{Param("p", Ptr())}, ty.void_(),
+ Vector{
+ CallBuiltin(builtin_a, "p"),
+ });
+
+ Func("f2", Vector{Param("p", Ptr())}, ty.void_(),
+ Vector{
+ CallBuiltin(builtin_b, "p"),
+ });
+
+ EXPECT_EQ(Run(), ShouldPass() ? kPass : R"(56:78 error: invalid aliased pointer argument
+12:34 note: aliases with another argument passed here)");
+}
+
+std::array kAtomicFns{
+ wgsl::BuiltinFn::kAtomicLoad,
+ wgsl::BuiltinFn::kAtomicStore,
+ wgsl::BuiltinFn::kAtomicAdd,
+ wgsl::BuiltinFn::kAtomicSub,
+ wgsl::BuiltinFn::kAtomicMax,
+ wgsl::BuiltinFn::kAtomicMin,
+ wgsl::BuiltinFn::kAtomicAnd,
+ wgsl::BuiltinFn::kAtomicOr,
+ wgsl::BuiltinFn::kAtomicXor,
+ wgsl::BuiltinFn::kAtomicExchange,
+ wgsl::BuiltinFn::kAtomicCompareExchangeWeak,
+};
+
+INSTANTIATE_TEST_SUITE_P(ResolverAliasAnalysisTest,
+ AtomicPointers,
+ ::testing::Combine(::testing::ValuesIn(kAtomicFns),
+ ::testing::ValuesIn(kAtomicFns),
+ ::testing::Values(core::AddressSpace::kWorkgroup,
+ core::AddressSpace::kStorage),
+ ::testing::Values(true, false)));
+
+////////////////////////////////////////////////////////////////////////////////
+// WorkgroupUniformLoad
+////////////////////////////////////////////////////////////////////////////////
+enum class WorkgroupUniformLoadAction {
+ kRead,
+ kWrite,
+ kWorkgroupUniformLoad,
+};
+
+std::array kWorkgroupUniformLoadActions{
+ WorkgroupUniformLoadAction::kRead,
+ WorkgroupUniformLoadAction::kWrite,
+ WorkgroupUniformLoadAction::kWorkgroupUniformLoad,
+};
+
+class WorkgroupUniformLoad
+ : public ResolverTestWithParam<
+ std::tuple<WorkgroupUniformLoadAction, WorkgroupUniformLoadAction, bool>> {
+ protected:
+ static constexpr std::string_view kPass = "<PASS>";
+
+ void SetUp() override {
+ GlobalVar("v1", workgroup, ty.i32());
+ GlobalVar("v2", workgroup, ty.i32());
+ }
+
+ const ast::Statement* Do(WorkgroupUniformLoadAction action, std::string_view ptr) {
+ switch (action) {
+ case WorkgroupUniformLoadAction::kRead:
+ return Assign(Phony(), Deref(ptr));
+ case WorkgroupUniformLoadAction::kWrite:
+ return Assign(Deref(ptr), 42_a);
+ case WorkgroupUniformLoadAction::kWorkgroupUniformLoad:
+ return Assign(Phony(), Call(wgsl::BuiltinFn::kWorkgroupUniformLoad, ptr));
+ }
+ return nullptr;
+ }
+
+ bool IsWrite(WorkgroupUniformLoadAction action) const {
+ return action == WorkgroupUniformLoadAction::kWrite;
+ }
+
+ bool ShouldPass() const {
+ auto [action_a, action_b, aliased] = GetParam();
+ bool fail = aliased && (IsWrite(action_a) || IsWrite(action_b));
+ return !fail;
+ }
+
+ std::string Run() {
+ if (r()->Resolve()) {
+ return std::string(kPass);
+ }
+ return r()->error();
+ }
+};
+
+TEST_P(WorkgroupUniformLoad, CallDirect) {
+ // var<workgroup> v1 : i32;
+ // var<workgroup> v2 : i32;
+ //
+ // fn caller() {
+ // callee(&v1, aliased ? &v1 : &v2);
+ // }
+ //
+ // fn callee(p1 : PTR, p2 : PTR) {
+ // <action-a>(p1);
+ // <action-b>(p2);
+ // }
+ auto [action_a, action_b, aliased] = GetParam();
+
+ Func("caller", tint::Empty, ty.void_(),
+ Vector{
+ CallStmt(Call("callee", //
+ AddressOf(Source{{12, 34}}, "v1"),
+ AddressOf(Source{{56, 78}}, aliased ? "v1" : "v2"))),
+ });
+
+ Func("callee",
+ Vector{Param("p1", ty.ptr<workgroup, i32>()), Param("p2", ty.ptr<workgroup, i32>())},
+ ty.void_(),
+ Vector{
+ Do(action_a, "p1"),
+ Do(action_b, "p2"),
+ });
+
+ EXPECT_EQ(Run(), ShouldPass() ? kPass : R"(56:78 error: invalid aliased pointer argument
+12:34 note: aliases with another argument passed here)");
+}
+
+TEST_P(WorkgroupUniformLoad, CallThroughChain) {
+ // var<workgroup> v1 : i32;
+ // var<workgroup> v2 : i32;
+ //
+ // fn caller() {
+ // callee(&v1, aliased ? &v1 : &v2);
+ // }
+ //
+ // fn f2(p1 : PTR, p2 : PTR) {
+ // f1(p1, p2);
+ // }
+ //
+ // fn f1(p1 : PTR, p2 : PTR) {
+ // callee(p1, p2);
+ // }
+ //
+ // fn callee(p1 : PTR, p2 : PTR) {
+ // <action-a>(p1);
+ // <action-b>(p2);
+ // }
+ auto [action_a, action_b, aliased] = GetParam();
+
+ Func("caller", tint::Empty, ty.void_(),
+ Vector{
+ CallStmt(Call("callee", //
+ AddressOf(Source{{12, 34}}, "v1"),
+ AddressOf(Source{{56, 78}}, aliased ? "v1" : "v2"))),
+ });
+
+ Func("f2", Vector{Param("p1", ty.ptr<workgroup, i32>()), Param("p2", ty.ptr<workgroup, i32>())},
+ ty.void_(),
+ Vector{
+ CallStmt(Call("f1", "p1", "p2")),
+ });
+
+ Func("f1", Vector{Param("p1", ty.ptr<workgroup, i32>()), Param("p2", ty.ptr<workgroup, i32>())},
+ ty.void_(),
+ Vector{
+ CallStmt(Call("callee", "p1", "p2")),
+ });
+
+ Func("callee",
+ Vector{Param("p1", ty.ptr<workgroup, i32>()), Param("p2", ty.ptr<workgroup, i32>())},
+ ty.void_(),
+ Vector{
+ Do(action_a, "p1"),
+ Do(action_b, "p2"),
+ });
+
+ EXPECT_EQ(Run(), ShouldPass() ? kPass : R"(56:78 error: invalid aliased pointer argument
+12:34 note: aliases with another argument passed here)");
+}
+
+TEST_P(WorkgroupUniformLoad, ReadWriteAcrossDifferentFunctions) {
+ // var<workgroup> v1 : i32;
+ // var<workgroup> v2 : i32;
+ //
+ // fn caller() {
+ // f(&v1, aliased ? &v1 : &v2);
+ // }
+ //
+ // fn f(p1 : PTR, p2 : PTR) {
+ // f1(p1);
+ // f2(p2);
+ // }
+ //
+ // fn f1(p : PTR) {
+ // <action-a>(p);
+ // }
+ //
+ // fn f2(p : PTR) {
+ // <action-b>(p);
+ // }
+ auto [action_a, action_b, aliased] = GetParam();
+
+ Func("caller", tint::Empty, ty.void_(),
+ Vector{
+ CallStmt(Call("f", //
+ AddressOf(Source{{12, 34}}, "v1"),
+ AddressOf(Source{{56, 78}}, aliased ? "v1" : "v2"))),
+ });
+
+ Func("f", Vector{Param("p1", ty.ptr<workgroup, i32>()), Param("p2", ty.ptr<workgroup, i32>())},
+ ty.void_(),
+ Vector{
+ CallStmt(Call("f1", "p1")),
+ CallStmt(Call("f2", "p2")),
+ });
+
+ Func("f1", Vector{Param("p", ty.ptr<workgroup, i32>())}, ty.void_(), Vector{Do(action_a, "p")});
+
+ Func("f2", Vector{Param("p", ty.ptr<workgroup, i32>())}, ty.void_(), Vector{Do(action_b, "p")});
+
+ EXPECT_EQ(Run(), ShouldPass() ? kPass : R"(56:78 error: invalid aliased pointer argument
+12:34 note: aliases with another argument passed here)");
+}
+
+INSTANTIATE_TEST_SUITE_P(ResolverAliasAnalysisTest,
+ WorkgroupUniformLoad,
+ ::testing::Combine(::testing::ValuesIn(kWorkgroupUniformLoadActions),
+ ::testing::ValuesIn(kWorkgroupUniformLoadActions),
+ ::testing::Values(true, false)));
+
} // namespace
} // namespace tint::resolver
diff --git a/src/tint/lang/wgsl/resolver/attribute_validation_test.cc b/src/tint/lang/wgsl/resolver/attribute_validation_test.cc
index c359dd7..33cccae 100644
--- a/src/tint/lang/wgsl/resolver/attribute_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/attribute_validation_test.cc
@@ -59,12 +59,12 @@
enum class AttributeKind {
kAlign,
kBinding,
+ kBlendSrc,
kBuiltinPosition,
kColor,
kDiagnostic,
kGroup,
kId,
- kIndex,
kInterpolate,
kInvariant,
kLocation,
@@ -81,6 +81,8 @@
return o << "@align";
case AttributeKind::kBinding:
return o << "@binding";
+ case AttributeKind::kBlendSrc:
+ return o << "@blend_src";
case AttributeKind::kBuiltinPosition:
return o << "@builtin(position)";
case AttributeKind::kColor:
@@ -91,8 +93,6 @@
return o << "@group";
case AttributeKind::kId:
return o << "@id";
- case AttributeKind::kIndex:
- return o << "@index";
case AttributeKind::kInterpolate:
return o << "@interpolate";
case AttributeKind::kInvariant:
@@ -143,6 +143,10 @@
"1:2 error: @binding is not valid for " + thing,
},
TestParams{
+ {AttributeKind::kBlendSrc},
+ "1:2 error: @blend_src is not valid for " + thing,
+ },
+ TestParams{
{AttributeKind::kBuiltinPosition},
"1:2 error: @builtin is not valid for " + thing,
},
@@ -163,10 +167,6 @@
"1:2 error: @id is not valid for " + thing,
},
TestParams{
- {AttributeKind::kIndex},
- "1:2 error: @index is not valid for " + thing,
- },
- TestParams{
{AttributeKind::kInterpolate},
"1:2 error: @interpolate is not valid for " + thing,
},
@@ -231,8 +231,8 @@
return builder.Group(source, 1_a);
case AttributeKind::kId:
return builder.Id(source, 0_a);
- case AttributeKind::kIndex:
- return builder.Index(source, 0_a);
+ case AttributeKind::kBlendSrc:
+ return builder.BlendSrc(source, 0_a);
case AttributeKind::kInterpolate:
return builder.Interpolate(source, core::InterpolationType::kLinear,
core::InterpolationSampling::kCenter);
@@ -263,7 +263,7 @@
case AttributeKind::kColor:
Enable(wgsl::Extension::kChromiumExperimentalFramebufferFetch);
break;
- case AttributeKind::kIndex:
+ case AttributeKind::kBlendSrc:
Enable(wgsl::Extension::kChromiumInternalDualSourceBlending);
break;
default:
@@ -323,6 +323,10 @@
R"(1:2 error: @binding is not valid for functions)",
},
TestParams{
+ {AttributeKind::kBlendSrc},
+ R"(1:2 error: @blend_src is not valid for functions)",
+ },
+ TestParams{
{AttributeKind::kBuiltinPosition},
R"(1:2 error: @builtin is not valid for functions)",
},
@@ -343,10 +347,6 @@
R"(1:2 error: @id is not valid for functions)",
},
TestParams{
- {AttributeKind::kIndex},
- R"(1:2 error: @index is not valid for functions)",
- },
- TestParams{
{AttributeKind::kInterpolate},
R"(1:2 error: @interpolate is not valid for functions)",
},
@@ -407,6 +407,10 @@
R"(1:2 error: @binding is not valid for functions)",
},
TestParams{
+ {AttributeKind::kBlendSrc},
+ R"(1:2 error: @blend_src is not valid for functions)",
+ },
+ TestParams{
{AttributeKind::kBuiltinPosition},
R"(1:2 error: @builtin is not valid for functions)",
},
@@ -427,10 +431,6 @@
R"(1:2 error: @id is not valid for functions)",
},
TestParams{
- {AttributeKind::kIndex},
- R"(1:2 error: @index is not valid for functions)",
- },
- TestParams{
{AttributeKind::kInterpolate},
R"(1:2 error: @interpolate is not valid for functions)",
},
@@ -498,6 +498,10 @@
R"(1:2 error: @binding is not valid for function parameters)",
},
TestParams{
+ {AttributeKind::kBlendSrc},
+ R"(1:2 error: @blend_src is not valid for function parameters)",
+ },
+ TestParams{
{AttributeKind::kBuiltinPosition},
R"(1:2 error: @builtin is not valid for non-entry point function parameters)",
},
@@ -518,10 +522,6 @@
R"(1:2 error: @id is not valid for function parameters)",
},
TestParams{
- {AttributeKind::kIndex},
- R"(1:2 error: @index is not valid for function parameters)",
- },
- TestParams{
{AttributeKind::kInterpolate},
R"(1:2 error: @interpolate is not valid for non-entry point function parameters)",
},
@@ -583,6 +583,10 @@
R"(1:2 error: @binding is not valid for non-entry point function return types)",
},
TestParams{
+ {AttributeKind::kBlendSrc},
+ R"(1:2 error: @blend_src is not valid for non-entry point function return types)",
+ },
+ TestParams{
{AttributeKind::kBuiltinPosition},
R"(1:2 error: @builtin is not valid for non-entry point function return types)",
},
@@ -603,10 +607,6 @@
R"(1:2 error: @id is not valid for non-entry point function return types)",
},
TestParams{
- {AttributeKind::kIndex},
- R"(1:2 error: @index is not valid for non-entry point function return types)",
- },
- TestParams{
{AttributeKind::kInterpolate},
R"(1:2 error: @interpolate is not valid for non-entry point function return types)",
},
@@ -673,6 +673,10 @@
R"(1:2 error: @binding is not valid for function parameters)",
},
TestParams{
+ {AttributeKind::kBlendSrc},
+ R"(1:2 error: @blend_src is not valid for function parameters)",
+ },
+ TestParams{
{AttributeKind::kBuiltinPosition},
R"(1:2 error: @builtin(position) cannot be used for compute shader input)",
},
@@ -693,10 +697,6 @@
R"(1:2 error: @id is not valid for function parameters)",
},
TestParams{
- {AttributeKind::kIndex},
- R"(1:2 error: @index is not valid for function parameters)",
- },
- TestParams{
{AttributeKind::kInterpolate},
R"(1:2 error: @interpolate cannot be used by compute shaders)",
},
@@ -757,6 +757,10 @@
R"(1:2 error: @binding is not valid for function parameters)",
},
TestParams{
+ {AttributeKind::kBlendSrc},
+ R"(1:2 error: @blend_src is not valid for function parameters)",
+ },
+ TestParams{
{AttributeKind::kBuiltinPosition},
Pass,
},
@@ -782,10 +786,6 @@
R"(1:2 error: @id is not valid for function parameters)",
},
TestParams{
- {AttributeKind::kIndex},
- R"(1:2 error: @index is not valid for function parameters)",
- },
- TestParams{
{AttributeKind::kInterpolate},
R"(9:9 error: missing entry point IO attribute on parameter)",
},
@@ -865,6 +865,10 @@
R"(1:2 error: @binding is not valid for function parameters)",
},
TestParams{
+ {AttributeKind::kBlendSrc},
+ R"(1:2 error: @blend_src is not valid for function parameters)",
+ },
+ TestParams{
{AttributeKind::kBuiltinPosition},
R"(1:2 error: @builtin(position) cannot be used for vertex shader input)",
},
@@ -885,10 +889,6 @@
R"(1:2 error: @id is not valid for function parameters)",
},
TestParams{
- {AttributeKind::kIndex},
- R"(1:2 error: @index is not valid for function parameters)",
- },
- TestParams{
{AttributeKind::kInterpolate},
R"(9:9 error: missing entry point IO attribute on parameter)",
},
@@ -970,6 +970,10 @@
R"(1:2 error: @binding is not valid for entry point return types)",
},
TestParams{
+ {AttributeKind::kBlendSrc},
+ R"(1:2 error: @blend_src can only be used for fragment shader output)",
+ },
+ TestParams{
{AttributeKind::kBuiltinPosition},
R"(1:2 error: @builtin(position) cannot be used for compute shader output)",
},
@@ -990,10 +994,6 @@
R"(1:2 error: @id is not valid for entry point return types)",
},
TestParams{
- {AttributeKind::kIndex},
- R"(1:2 error: @index can only be used for fragment shader output)",
- },
- TestParams{
{AttributeKind::kInterpolate},
R"(1:2 error: @interpolate cannot be used by compute shaders)",
},
@@ -1056,6 +1056,14 @@
R"(1:2 error: @binding is not valid for entry point return types)",
},
TestParams{
+ {AttributeKind::kBlendSrc},
+ R"(9:9 error: missing entry point IO attribute on return type)",
+ },
+ TestParams{
+ {AttributeKind::kBlendSrc, AttributeKind::kLocation},
+ Pass,
+ },
+ TestParams{
{AttributeKind::kBuiltinPosition},
R"(1:2 error: @builtin(position) cannot be used for fragment shader output)",
},
@@ -1076,14 +1084,6 @@
R"(1:2 error: @id is not valid for entry point return types)",
},
TestParams{
- {AttributeKind::kIndex},
- R"(9:9 error: missing entry point IO attribute on return type)",
- },
- TestParams{
- {AttributeKind::kIndex, AttributeKind::kLocation},
- Pass,
- },
- TestParams{
{AttributeKind::kInterpolate},
R"(9:9 error: missing entry point IO attribute on return type)",
},
@@ -1132,7 +1132,7 @@
R"(1:2 error: @binding is not valid for entry point return types)",
},
TestParams{
- {AttributeKind::kIndex, AttributeKind::kLocation},
+ {AttributeKind::kBlendSrc, AttributeKind::kLocation},
Pass,
}));
@@ -1168,6 +1168,10 @@
R"(1:2 error: @binding is not valid for entry point return types)",
},
TestParams{
+ {AttributeKind::kBlendSrc},
+ R"(1:2 error: @blend_src can only be used for fragment shader output)",
+ },
+ TestParams{
{AttributeKind::kBuiltinPosition},
Pass,
},
@@ -1188,10 +1192,6 @@
R"(1:2 error: @id is not valid for entry point return types)",
},
TestParams{
- {AttributeKind::kIndex},
- R"(1:2 error: @index can only be used for fragment shader output)",
- },
- TestParams{
{AttributeKind::kInterpolate},
R"(1:2 error: @interpolate can only be used with @location)",
},
@@ -1293,6 +1293,10 @@
R"(1:2 error: @binding is not valid for struct declarations)",
},
TestParams{
+ {AttributeKind::kBlendSrc},
+ R"(1:2 error: @blend_src is not valid for struct declarations)",
+ },
+ TestParams{
{AttributeKind::kBuiltinPosition},
R"(1:2 error: @builtin is not valid for struct declarations)",
},
@@ -1313,10 +1317,6 @@
R"(1:2 error: @id is not valid for struct declarations)",
},
TestParams{
- {AttributeKind::kIndex},
- R"(1:2 error: @index is not valid for struct declarations)",
- },
- TestParams{
{AttributeKind::kInterpolate},
R"(1:2 error: @interpolate is not valid for struct declarations)",
},
@@ -1376,6 +1376,10 @@
R"(1:2 error: @binding is not valid for struct members)",
},
TestParams{
+ {AttributeKind::kBlendSrc},
+ R"(1:2 error: @blend_src can only be used with @location(0))",
+ },
+ TestParams{
{AttributeKind::kBuiltinPosition},
Pass,
},
@@ -1396,10 +1400,6 @@
R"(1:2 error: @id is not valid for struct members)",
},
TestParams{
- {AttributeKind::kIndex},
- R"(1:2 error: @index can only be used with @location(0))",
- },
- TestParams{
{AttributeKind::kInterpolate},
R"(1:2 error: @interpolate can only be used with @location)",
},
@@ -1648,6 +1648,10 @@
R"(1:2 error: @binding is not valid for array types)",
},
TestParams{
+ {AttributeKind::kBlendSrc},
+ R"(1:2 error: @blend_src is not valid for array types)",
+ },
+ TestParams{
{AttributeKind::kBuiltinPosition},
R"(1:2 error: @builtin is not valid for array types)",
},
@@ -1664,10 +1668,6 @@
R"(1:2 error: @id is not valid for array types)",
},
TestParams{
- {AttributeKind::kIndex},
- R"(1:2 error: @index is not valid for array types)",
- },
- TestParams{
{AttributeKind::kInterpolate},
R"(1:2 error: @interpolate is not valid for array types)",
},
@@ -1739,6 +1739,10 @@
R"(9:9 error: resource variables require @group and @binding attributes)",
},
TestParams{
+ {AttributeKind::kBlendSrc},
+ R"(1:2 error: @blend_src is not valid for module-scope 'var')",
+ },
+ TestParams{
{AttributeKind::kBuiltinPosition},
R"(1:2 error: @builtin is not valid for module-scope 'var')",
},
@@ -1755,10 +1759,6 @@
R"(1:2 error: @id is not valid for module-scope 'var')",
},
TestParams{
- {AttributeKind::kIndex},
- R"(1:2 error: @index is not valid for module-scope 'var')",
- },
- TestParams{
{AttributeKind::kInterpolate},
R"(1:2 error: @interpolate is not valid for module-scope 'var')",
},
@@ -1843,6 +1843,10 @@
R"(1:2 error: @binding is not valid for 'const' declaration)",
},
TestParams{
+ {AttributeKind::kBlendSrc},
+ R"(1:2 error: @blend_src is not valid for 'const' declaration)",
+ },
+ TestParams{
{AttributeKind::kBuiltinPosition},
R"(1:2 error: @builtin is not valid for 'const' declaration)",
},
@@ -1859,10 +1863,6 @@
R"(1:2 error: @id is not valid for 'const' declaration)",
},
TestParams{
- {AttributeKind::kIndex},
- R"(1:2 error: @index is not valid for 'const' declaration)",
- },
- TestParams{
{AttributeKind::kInterpolate},
R"(1:2 error: @interpolate is not valid for 'const' declaration)",
},
@@ -1924,6 +1924,10 @@
R"(1:2 error: @binding is not valid for 'override' declaration)",
},
TestParams{
+ {AttributeKind::kBlendSrc},
+ R"(1:2 error: @blend_src is not valid for 'override' declaration)",
+ },
+ TestParams{
{AttributeKind::kBuiltinPosition},
R"(1:2 error: @builtin is not valid for 'override' declaration)",
},
@@ -1936,10 +1940,6 @@
R"(1:2 error: @group is not valid for 'override' declaration)",
},
TestParams{
- {AttributeKind::kIndex},
- R"(1:2 error: @index is not valid for 'override' declaration)",
- },
- TestParams{
{AttributeKind::kId},
Pass,
},
diff --git a/src/tint/lang/wgsl/resolver/dependency_graph.cc b/src/tint/lang/wgsl/resolver/dependency_graph.cc
index bb07be0..890d024 100644
--- a/src/tint/lang/wgsl/resolver/dependency_graph.cc
+++ b/src/tint/lang/wgsl/resolver/dependency_graph.cc
@@ -36,6 +36,7 @@
#include "src/tint/lang/core/builtin_value.h"
#include "src/tint/lang/wgsl/ast/alias.h"
#include "src/tint/lang/wgsl/ast/assignment_statement.h"
+#include "src/tint/lang/wgsl/ast/blend_src_attribute.h"
#include "src/tint/lang/wgsl/ast/block_statement.h"
#include "src/tint/lang/wgsl/ast/break_if_statement.h"
#include "src/tint/lang/wgsl/ast/break_statement.h"
@@ -51,7 +52,6 @@
#include "src/tint/lang/wgsl/ast/identifier.h"
#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_attribute.h"
#include "src/tint/lang/wgsl/ast/internal_attribute.h"
#include "src/tint/lang/wgsl/ast/interpolate_attribute.h"
#include "src/tint/lang/wgsl/ast/invariant_attribute.h"
@@ -390,7 +390,7 @@
[&](const ast::ColorAttribute* color) { TraverseExpression(color->expr); },
[&](const ast::GroupAttribute* group) { TraverseExpression(group->expr); },
[&](const ast::IdAttribute* id) { TraverseExpression(id->expr); },
- [&](const ast::IndexAttribute* index) { TraverseExpression(index->expr); },
+ [&](const ast::BlendSrcAttribute* index) { TraverseExpression(index->expr); },
[&](const ast::InterpolateAttribute* interpolate) {
TraverseExpression(interpolate->type);
TraverseExpression(interpolate->sampling);
diff --git a/src/tint/lang/wgsl/resolver/dual_source_blending_extension_test.cc b/src/tint/lang/wgsl/resolver/dual_source_blending_extension_test.cc
index 223744a..67a3aab 100644
--- a/src/tint/lang/wgsl/resolver/dual_source_blending_extension_test.cc
+++ b/src/tint/lang/wgsl/resolver/dual_source_blending_extension_test.cc
@@ -39,17 +39,18 @@
using DualSourceBlendingExtensionTest = ResolverTest;
-// Using the @index attribute without chromium_internal_dual_source_blending enabled should fail.
-TEST_F(DualSourceBlendingExtensionTest, UseIndexAttribWithoutExtensionError) {
- Structure("Output",
- Vector{
- Member("a", ty.vec4<f32>(), Vector{Location(0_a), Index(Source{{12, 34}}, 0_a)}),
- });
+// Using the @blend_src attribute without chromium_internal_dual_source_blending enabled should
+// fail.
+TEST_F(DualSourceBlendingExtensionTest, UseBlendSrcAttribWithoutExtensionError) {
+ Structure("Output", Vector{
+ Member("a", ty.vec4<f32>(),
+ Vector{Location(0_a), BlendSrc(Source{{12, 34}}, 0_a)}),
+ });
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(
r()->error(),
- R"(12:34 error: use of @index requires enabling extension 'chromium_internal_dual_source_blending')");
+ R"(12:34 error: use of @blend_src requires enabling extension 'chromium_internal_dual_source_blending')");
}
class DualSourceBlendingExtensionTests : public ResolverTest {
@@ -60,10 +61,10 @@
};
// Using an F32 as an index value should fail.
-TEST_F(DualSourceBlendingExtensionTests, IndexF32Error) {
+TEST_F(DualSourceBlendingExtensionTests, BlendSrcF32Error) {
Structure("Output", Vector{
Member(Source{{12, 34}}, "a", ty.vec4<f32>(),
- Vector{Location(0_a), Index(Source{{12, 34}}, 0_f)}),
+ Vector{Location(0_a), BlendSrc(Source{{12, 34}}, 0_f)}),
});
EXPECT_FALSE(r()->Resolve());
@@ -71,111 +72,111 @@
}
// Using a floating point number as an index value should fail.
-TEST_F(DualSourceBlendingExtensionTests, IndexFloatValueError) {
+TEST_F(DualSourceBlendingExtensionTests, BlendSrcFloatValueError) {
Structure("Output", Vector{
Member(Source{{12, 34}}, "a", ty.vec4<f32>(),
- Vector{Location(0_a), Index(Source{{12, 34}}, 1.0_a)}),
+ Vector{Location(0_a), BlendSrc(Source{{12, 34}}, 1.0_a)}),
});
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(), "12:34 error: @location must be an i32 or u32 value");
}
// Using a number less than zero as an index value should fail.
-TEST_F(DualSourceBlendingExtensionTests, IndexNegativeValue) {
+TEST_F(DualSourceBlendingExtensionTests, BlendSrcNegativeValue) {
Structure("Output", Vector{
Member(Source{{12, 34}}, "a", ty.vec4<f32>(),
- Vector{Location(0_a), Index(Source{{12, 34}}, -1_a)}),
+ Vector{Location(0_a), BlendSrc(Source{{12, 34}}, -1_a)}),
});
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), "12:34 error: @index value must be zero or one");
+ EXPECT_EQ(r()->error(), "12:34 error: @blend_src value must be zero or one");
}
// Using a number greater than one as an index value should fail.
-TEST_F(DualSourceBlendingExtensionTests, IndexValueAboveOne) {
+TEST_F(DualSourceBlendingExtensionTests, BlendSrcValueAboveOne) {
Structure("Output", Vector{
Member(Source{{12, 34}}, "a", ty.vec4<f32>(),
- Vector{Location(0_a), Index(Source{{12, 34}}, 2_a)}),
+ Vector{Location(0_a), BlendSrc(Source{{12, 34}}, 2_a)}),
});
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), "12:34 error: @index value must be zero or one");
+ EXPECT_EQ(r()->error(), "12:34 error: @blend_src value must be zero or one");
}
// Using an index value at the same location multiple times should fail.
-TEST_F(DualSourceBlendingExtensionTests, DuplicateIndexes) {
+TEST_F(DualSourceBlendingExtensionTests, DuplicateBlendSrces) {
Structure("Output", Vector{
- Member("a", ty.vec4<f32>(), Vector{Location(0_a), Index(0_a)}),
+ Member("a", ty.vec4<f32>(), Vector{Location(0_a), BlendSrc(0_a)}),
Member(Source{{12, 34}}, "b", ty.vec4<f32>(),
- Vector{Location(Source{{12, 34}}, 0_a), Index(0_a)}),
+ Vector{Location(Source{{12, 34}}, 0_a), BlendSrc(0_a)}),
});
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), "12:34 error: @location(0) @index(0) appears multiple times");
+ EXPECT_EQ(r()->error(), "12:34 error: @location(0) @blend_src(0) appears multiple times");
}
// Using the index attribute without a location attribute should fail.
-TEST_F(DualSourceBlendingExtensionTests, IndexWithMissingLocationAttribute_Struct) {
+TEST_F(DualSourceBlendingExtensionTests, BlendSrcWithMissingLocationAttribute_Struct) {
Structure("Output", Vector{
Member(Source{{12, 34}}, "a", ty.vec4<f32>(),
- Vector{Index(Source{{12, 34}}, 1_a)}),
+ Vector{BlendSrc(Source{{12, 34}}, 1_a)}),
});
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), "12:34 error: @index can only be used with @location(0)");
+ EXPECT_EQ(r()->error(), "12:34 error: @blend_src can only be used with @location(0)");
}
// Using the index attribute without a location attribute should fail.
-TEST_F(DualSourceBlendingExtensionTests, IndexWithMissingLocationAttribute_ReturnValue) {
+TEST_F(DualSourceBlendingExtensionTests, BlendSrcWithMissingLocationAttribute_ReturnValue) {
Func("F", Empty, ty.vec4<f32>(),
Vector{
Return(Call<vec4<f32>>()),
},
Vector{Stage(ast::PipelineStage::kFragment)},
Vector{
- Index(Source{{12, 34}}, 1_a),
+ BlendSrc(Source{{12, 34}}, 1_a),
Builtin(core::BuiltinValue::kPointSize),
});
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), "12:34 error: @index can only be used with @location(0)");
+ EXPECT_EQ(r()->error(), "12:34 error: @blend_src can only be used with @location(0)");
}
// Using an index attribute on a struct member should pass.
-TEST_F(DualSourceBlendingExtensionTests, StructMemberIndexAttribute) {
- Structure("Output",
- Vector{
- Member("a", ty.vec4<f32>(), Vector{Location(0_a), Index(Source{{12, 34}}, 0_a)}),
- });
+TEST_F(DualSourceBlendingExtensionTests, StructMemberBlendSrcAttribute) {
+ Structure("Output", Vector{
+ Member("a", ty.vec4<f32>(),
+ Vector{Location(0_a), BlendSrc(Source{{12, 34}}, 0_a)}),
+ });
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
// Using an index attribute on a global variable should pass. This is needed internally when using
-// @index with the canonicalize_entry_point transform. This test uses an internal attribute to
+// @blend_src with the canonicalize_entry_point transform. This test uses an internal attribute to
// ignore address space, which is how it is used with the canonicalize_entry_point transform.
-TEST_F(DualSourceBlendingExtensionTests, GlobalVariableIndexAttribute) {
+TEST_F(DualSourceBlendingExtensionTests, GlobalVariableBlendSrcAttribute) {
GlobalVar(
"var", ty.vec4<f32>(),
- Vector{Location(0_a), Index(0_a), Disable(ast::DisabledValidation::kIgnoreAddressSpace)},
+ Vector{Location(0_a), BlendSrc(0_a), Disable(ast::DisabledValidation::kIgnoreAddressSpace)},
core::AddressSpace::kOut);
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
// Using the index attribute with a non-zero location should fail.
-TEST_F(DualSourceBlendingExtensionTests, IndexWithNonZeroLocation_Struct) {
- Structure("Output",
- Vector{
- Member("a", ty.vec4<f32>(), Vector{Location(1_a), Index(Source{{12, 34}}, 0_a)}),
- });
+TEST_F(DualSourceBlendingExtensionTests, BlendSrcWithNonZeroLocation_Struct) {
+ Structure("Output", Vector{
+ Member("a", ty.vec4<f32>(),
+ Vector{Location(1_a), BlendSrc(Source{{12, 34}}, 0_a)}),
+ });
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), "12:34 error: @index can only be used with @location(0)");
+ EXPECT_EQ(r()->error(), "12:34 error: @blend_src can only be used with @location(0)");
}
// Using the index attribute with a non-zero location should fail.
-TEST_F(DualSourceBlendingExtensionTests, IndexWithNonZeroLocation_ReturnValue) {
+TEST_F(DualSourceBlendingExtensionTests, BlendSrcWithNonZeroLocation_ReturnValue) {
Func("F", Empty, ty.vec4<f32>(),
Vector{
Return(Call<vec4<f32>>()),
@@ -183,31 +184,32 @@
Vector{Stage(ast::PipelineStage::kFragment)},
Vector{
Location(1_a),
- Index(Source{{12, 34}}, 1_a),
+ BlendSrc(Source{{12, 34}}, 1_a),
});
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), "12:34 error: @index can only be used with @location(0)");
+ EXPECT_EQ(r()->error(), "12:34 error: @blend_src can only be used with @location(0)");
}
TEST_F(DualSourceBlendingExtensionTests, NoNonZeroCollisionsBetweenInAndOut) {
// struct NonZeroLocation {
// @location(1) a : vec4<f32>,
// };
- // struct NonZeroIndex {
- // @location(0) @index(1) a : vec4<f32>,
+ // struct NonZeroBlendSrc {
+ // @location(0) @blend_src(1) a : vec4<f32>,
// };
- // fn X(in : NonZeroLocation) -> NonZeroIndex { return NonZeroIndex(); }
- // fn Y(in : NonZeroIndex) -> NonZeroLocation { return NonZeroLocation(); }
+ // fn X(in : NonZeroLocation) -> NonZeroBlendSrc { return NonZeroBlendSrc(); }
+ // fn Y(in : NonZeroBlendSrc) -> NonZeroLocation { return NonZeroLocation(); }
Structure("NonZeroLocation", Vector{
Member("a", ty.vec4<f32>(), Vector{Location(1_a)}),
});
- Structure("NonZeroIndex", Vector{
- Member("a", ty.vec4<f32>(), Vector{Location(0_a), Index(1_a)}),
- });
- Func("X", Vector{Param("in", ty("NonZeroLocation"))}, ty("NonZeroIndex"),
- Vector{Return(Call("NonZeroIndex"))}, Vector{Stage(ast::PipelineStage::kFragment)});
- Func("Y", Vector{Param("in", ty("NonZeroIndex"))}, ty("NonZeroLocation"),
+ Structure("NonZeroBlendSrc",
+ Vector{
+ Member("a", ty.vec4<f32>(), Vector{Location(0_a), BlendSrc(1_a)}),
+ });
+ Func("X", Vector{Param("in", ty("NonZeroLocation"))}, ty("NonZeroBlendSrc"),
+ Vector{Return(Call("NonZeroBlendSrc"))}, Vector{Stage(ast::PipelineStage::kFragment)});
+ Func("Y", Vector{Param("in", ty("NonZeroBlendSrc"))}, ty("NonZeroLocation"),
Vector{Return(Call("NonZeroLocation"))}, Vector{Stage(ast::PipelineStage::kFragment)});
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -222,17 +224,17 @@
// Rendering to multiple render targets while using dual source blending should fail.
TEST_P(DualSourceBlendingExtensionTestWithParams,
- MultipleRenderTargetsNotAllowed_IndexThenNonZeroLocation) {
+ MultipleRenderTargetsNotAllowed_BlendSrcThenNonZeroLocation) {
// struct S {
- // @location(0) @index(0) a : vec4<f32>,
- // @location(0) @index(1) b : vec4<f32>,
+ // @location(0) @blend_src(0) a : vec4<f32>,
+ // @location(0) @blend_src(1) b : vec4<f32>,
// @location(n) c : vec4<f32>,
// };
// fn F() -> S { return S(); }
Structure("S",
Vector{
- Member("a", ty.vec4<f32>(), Vector{Location(0_a), Index(0_a)}),
- Member("b", ty.vec4<f32>(), Vector{Location(0_a), Index(Source{{1, 2}}, 1_a)}),
+ Member("a", ty.vec4<f32>(), Vector{Location(0_a), BlendSrc(0_a)}),
+ Member("b", ty.vec4<f32>(), Vector{Location(0_a), BlendSrc(Source{{1, 2}}, 1_a)}),
Member("c", ty.vec4<f32>(), Vector{Location(Source{{3, 4}}, AInt(GetParam()))}),
});
Func("F", Empty, ty("S"), Vector{Return(Call("S"))},
@@ -240,31 +242,31 @@
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- R"(1:2 error: pipeline cannot use both non-zero @index and non-zero @location
+ R"(1:2 error: pipeline cannot use both non-zero @blend_src and non-zero @location
3:4 note: non-zero @location declared here
note: while analyzing entry point 'F')");
}
TEST_P(DualSourceBlendingExtensionTestWithParams,
- MultipleRenderTargetsNotAllowed_NonZeroLocationThenIndex) {
+ MultipleRenderTargetsNotAllowed_NonZeroLocationThenBlendSrc) {
// struct S {
// @location(n) a : vec4<f32>,
- // @location(0) @index(0) b : vec4<f32>,
- // @location(0) @index(1) c : vec4<f32>,
+ // @location(0) @blend_src(0) b : vec4<f32>,
+ // @location(0) @blend_src(1) c : vec4<f32>,
// };
// fn F() -> S { return S(); }
Structure("S",
Vector{
Member("a", ty.vec4<f32>(), Vector{Location(Source{{1, 2}}, AInt(GetParam()))}),
- Member("b", ty.vec4<f32>(), Vector{Location(0_a), Index(0_a)}),
- Member("c", ty.vec4<f32>(), Vector{Location(0_a), Index(Source{{3, 4}}, 1_a)}),
+ Member("b", ty.vec4<f32>(), Vector{Location(0_a), BlendSrc(0_a)}),
+ Member("c", ty.vec4<f32>(), Vector{Location(0_a), BlendSrc(Source{{3, 4}}, 1_a)}),
});
Func(Source{{5, 6}}, "F", Empty, ty("S"), Vector{Return(Call("S"))},
Vector{Stage(ast::PipelineStage::kFragment)});
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
- R"(3:4 error: pipeline cannot use both non-zero @index and non-zero @location
+ R"(3:4 error: pipeline cannot use both non-zero @blend_src and non-zero @location
1:2 note: non-zero @location declared here
5:6 note: while analyzing entry point 'F')");
}
diff --git a/src/tint/lang/wgsl/resolver/resolver.cc b/src/tint/lang/wgsl/resolver/resolver.cc
index 454e928..e8b9bcc 100644
--- a/src/tint/lang/wgsl/resolver/resolver.cc
+++ b/src/tint/lang/wgsl/resolver/resolver.cc
@@ -634,11 +634,11 @@
global->Attributes().location = value.Get();
return kSuccess;
},
- [&](const ast::IndexAttribute* attr) {
+ [&](const ast::BlendSrcAttribute* attr) {
if (!has_io_address_space) {
return kInvalid;
}
- auto value = IndexAttribute(attr);
+ auto value = BlendSrcAttribute(attr);
if (value != Success) {
return kErrored;
}
@@ -1080,8 +1080,8 @@
func->SetReturnLocation(value.Get());
return kSuccess;
},
- [&](const ast::IndexAttribute* attr) {
- auto value = IndexAttribute(attr);
+ [&](const ast::BlendSrcAttribute* attr) {
+ auto value = BlendSrcAttribute(attr);
if (value != Success) {
return kErrored;
}
@@ -1666,13 +1666,25 @@
}
void Resolver::RegisterStore(const sem::ValueExpression* expr) {
- auto& info = alias_analysis_infos_[current_function_];
Switch(
expr->RootIdentifier(),
[&](const sem::GlobalVariable* global) {
- info.module_scope_writes.insert({global, expr});
+ alias_analysis_infos_[current_function_].module_scope_writes.Add(global, expr);
},
- [&](const sem::Parameter* param) { info.parameter_writes.insert(param); });
+ [&](const sem::Parameter* param) {
+ alias_analysis_infos_[current_function_].parameter_writes.Add(param);
+ });
+}
+
+void Resolver::RegisterLoad(const sem::ValueExpression* expr) {
+ Switch(
+ expr->RootIdentifier(),
+ [&](const sem::GlobalVariable* global) {
+ alias_analysis_infos_[current_function_].module_scope_reads.Add(global, expr);
+ },
+ [&](const sem::Parameter* param) {
+ alias_analysis_infos_[current_function_].parameter_reads.Add(param);
+ });
}
bool Resolver::AliasAnalysis(const sem::Call* call) {
@@ -1716,8 +1728,8 @@
// Track the set of root identifiers that are read and written by arguments passed in this
// call.
- std::unordered_map<const sem::Variable*, const sem::ValueExpression*> arg_reads;
- std::unordered_map<const sem::Variable*, const sem::ValueExpression*> arg_writes;
+ Hashmap<const sem::Variable*, const sem::ValueExpression*, 4> arg_reads;
+ Hashmap<const sem::Variable*, const sem::ValueExpression*, 4> arg_writes;
for (size_t i = 0; i < args.Length(); i++) {
auto* arg = args[i];
if (!arg->Type()->Is<core::type::Pointer>()) {
@@ -1725,60 +1737,57 @@
}
auto* root = arg->RootIdentifier();
- if (target_info.parameter_writes.count(target->Parameters()[i])) {
+ if (target_info.parameter_writes.Contains(target->Parameters()[i])) {
// Arguments that are written to can alias with any other argument or module-scope
// variable access.
- if (arg_writes.count(root)) {
- return make_error(arg, {arg_writes.at(root), Alias::Argument, "write"});
+ if (auto write = arg_writes.Get(root)) {
+ return make_error(arg, {*write, Alias::Argument, "write"});
}
- if (arg_reads.count(root)) {
- return make_error(arg, {arg_reads.at(root), Alias::Argument, "read"});
+ if (auto read = arg_reads.Get(root)) {
+ return make_error(arg, {*read, Alias::Argument, "read"});
}
- if (target_info.module_scope_reads.count(root)) {
- return make_error(
- arg, {target_info.module_scope_reads.at(root), Alias::ModuleScope, "read"});
+ if (auto read = target_info.module_scope_reads.Get(root)) {
+ return make_error(arg, {*read, Alias::ModuleScope, "read"});
}
- if (target_info.module_scope_writes.count(root)) {
- return make_error(
- arg, {target_info.module_scope_writes.at(root), Alias::ModuleScope, "write"});
+ if (auto write = target_info.module_scope_writes.Get(root)) {
+ return make_error(arg, {*write, Alias::ModuleScope, "write"});
}
- arg_writes.insert({root, arg});
+ arg_writes.Add(root, arg);
// Propagate the write access to the caller.
Switch(
root,
[&](const sem::GlobalVariable* global) {
- caller_info.module_scope_writes.insert({global, arg});
+ caller_info.module_scope_writes.Add(global, arg);
},
- [&](const sem::Parameter* param) { caller_info.parameter_writes.insert(param); });
- } else if (target_info.parameter_reads.count(target->Parameters()[i])) {
+ [&](const sem::Parameter* param) { caller_info.parameter_writes.Add(param); });
+ } else if (target_info.parameter_reads.Contains(target->Parameters()[i])) {
// Arguments that are read from can alias with arguments or module-scope variables
// that are written to.
- if (arg_writes.count(root)) {
- return make_error(arg, {arg_writes.at(root), Alias::Argument, "write"});
+ if (auto write = arg_writes.Get(root)) {
+ return make_error(arg, {*write, Alias::Argument, "write"});
}
- if (target_info.module_scope_writes.count(root)) {
- return make_error(
- arg, {target_info.module_scope_writes.at(root), Alias::ModuleScope, "write"});
+ if (auto write = target_info.module_scope_writes.Get(root)) {
+ return make_error(arg, {*write, Alias::ModuleScope, "write"});
}
- arg_reads.insert({root, arg});
+ arg_reads.Add(root, arg);
// Propagate the read access to the caller.
Switch(
root,
[&](const sem::GlobalVariable* global) {
- caller_info.module_scope_reads.insert({global, arg});
+ caller_info.module_scope_reads.Add(global, arg);
},
- [&](const sem::Parameter* param) { caller_info.parameter_reads.insert(param); });
+ [&](const sem::Parameter* param) { caller_info.parameter_reads.Add(param); });
}
}
// Propagate module-scope variable uses to the caller.
for (auto read : target_info.module_scope_reads) {
- caller_info.module_scope_reads.insert({read.first, read.second});
+ caller_info.module_scope_reads.Add(read.key, read.value);
}
for (auto write : target_info.module_scope_writes) {
- caller_info.module_scope_writes.insert({write.first, write.second});
+ caller_info.module_scope_writes.Add(write.key, write.value);
}
return true;
@@ -1848,14 +1857,8 @@
load->Behaviors() = expr->Behaviors();
b.Sem().Replace(expr->Declaration(), load);
- // Track the load for the alias analysis.
- auto& alias_info = alias_analysis_infos_[current_function_];
- Switch(
- expr->RootIdentifier(),
- [&](const sem::GlobalVariable* global) {
- alias_info.module_scope_reads.insert({global, expr});
- },
- [&](const sem::Parameter* param) { alias_info.parameter_reads.insert(param); });
+ // Register the load for the alias analysis.
+ RegisterLoad(expr);
return load;
}
@@ -2128,10 +2131,11 @@
// Is this overload a constructor or conversion?
if (match->info->flags.Contains(OverloadFlag::kIsConstructor)) {
// Type constructor
- auto params = Transform(match->parameters, [&](auto& p, size_t i) {
- return b.create<sem::Parameter>(nullptr, static_cast<uint32_t>(i), p.type, p.usage);
- });
target_sem = constructors_.GetOrCreate(match.Get(), [&] {
+ auto params = Transform(match->parameters, [&](auto& p, size_t i) {
+ return b.create<sem::Parameter>(nullptr, static_cast<uint32_t>(i), p.type,
+ p.usage);
+ });
return b.create<sem::ValueConstructor>(match->return_type, std::move(params),
overload_stage);
});
@@ -2474,16 +2478,43 @@
CollectTextureSamplerPairs(target, call->Arguments());
}
- if (fn == wgsl::BuiltinFn::kWorkgroupUniformLoad) {
- if (!validator_.WorkgroupUniformLoad(call)) {
- return nullptr;
- }
- }
+ switch (fn) {
+ case wgsl::BuiltinFn::kWorkgroupUniformLoad:
+ if (!validator_.WorkgroupUniformLoad(call)) {
+ return nullptr;
+ }
+ RegisterLoad(args[0]);
+ break;
- if (fn == wgsl::BuiltinFn::kSubgroupBroadcast) {
- if (!validator_.SubgroupBroadcast(call)) {
- return nullptr;
- }
+ case wgsl::BuiltinFn::kSubgroupBroadcast:
+ if (!validator_.SubgroupBroadcast(call)) {
+ return nullptr;
+ }
+ break;
+
+ case wgsl::BuiltinFn::kAtomicLoad:
+ RegisterLoad(args[0]);
+ break;
+
+ case wgsl::BuiltinFn::kAtomicStore:
+ RegisterStore(args[0]);
+ break;
+
+ case wgsl::BuiltinFn::kAtomicAdd:
+ case wgsl::BuiltinFn::kAtomicSub:
+ case wgsl::BuiltinFn::kAtomicMax:
+ case wgsl::BuiltinFn::kAtomicMin:
+ case wgsl::BuiltinFn::kAtomicAnd:
+ case wgsl::BuiltinFn::kAtomicOr:
+ case wgsl::BuiltinFn::kAtomicXor:
+ case wgsl::BuiltinFn::kAtomicExchange:
+ case wgsl::BuiltinFn::kAtomicCompareExchangeWeak:
+ RegisterLoad(args[0]);
+ RegisterStore(args[0]);
+ break;
+
+ default:
+ break;
}
if (!validator_.BuiltinCall(call)) {
@@ -3496,8 +3527,9 @@
swizzle.Push(3u);
break;
default:
- AddError("invalid vector swizzle character",
- expr->member->source.Begin() + swizzle.Length());
+ AddError(
+ "invalid vector swizzle character",
+ expr->member->source.Begin() + static_cast<uint32_t>(swizzle.Length()));
return nullptr;
}
@@ -3790,8 +3822,8 @@
return static_cast<uint32_t>(value);
}
-tint::Result<uint32_t> Resolver::IndexAttribute(const ast::IndexAttribute* attr) {
- ExprEvalStageConstraint constraint{core::EvaluationStage::kConstant, "@index value"};
+tint::Result<uint32_t> Resolver::BlendSrcAttribute(const ast::BlendSrcAttribute* attr) {
+ ExprEvalStageConstraint constraint{core::EvaluationStage::kConstant, "@blend_src value"};
TINT_SCOPED_ASSIGNMENT(expr_eval_stage_constraint_, constraint);
auto* materialized = Materialize(ValueExpression(attr->expr));
@@ -3807,7 +3839,7 @@
auto const_value = materialized->ConstantValue();
auto value = const_value->ValueAs<AInt>();
if (value != 0 && value != 1) {
- AddError("@index value must be zero or one", attr->source);
+ AddError("@blend_src value must be zero or one", attr->source);
return Failure{};
}
@@ -4416,12 +4448,12 @@
attributes.location = value.Get();
return true;
},
- [&](const ast::IndexAttribute* attr) {
- auto value = IndexAttribute(attr);
+ [&](const ast::BlendSrcAttribute* attr) {
+ auto value = BlendSrcAttribute(attr);
if (value != Success) {
return false;
}
- attributes.index = value.Get();
+ attributes.blend_src = value.Get();
return true;
},
[&](const ast::ColorAttribute* attr) {
@@ -4848,7 +4880,7 @@
ty = const_cast<core::type::Type*>(ty->UnwrapRef());
if (auto* str = ty->As<sem::Struct>()) {
- if (str->AddressSpaceUsage().count(address_space)) {
+ if (str->AddressSpaceUsage().Contains(address_space)) {
return true; // Already applied
}
diff --git a/src/tint/lang/wgsl/resolver/resolver.h b/src/tint/lang/wgsl/resolver/resolver.h
index 344c5af..d51923c 100644
--- a/src/tint/lang/wgsl/resolver/resolver.h
+++ b/src/tint/lang/wgsl/resolver/resolver.h
@@ -314,6 +314,10 @@
/// perform alias analysis.
void RegisterStore(const sem::ValueExpression* expr);
+ /// Register a memory load of an expression, to track accesses to root identifiers in order to
+ /// perform alias analysis.
+ void RegisterLoad(const sem::ValueExpression* expr);
+
/// Perform pointer alias analysis for `call`.
/// @returns true is the call arguments are free from aliasing issues, false otherwise.
bool AliasAnalysis(const sem::Call* call);
@@ -423,9 +427,9 @@
/// @returns the color value on success.
tint::Result<uint32_t> ColorAttribute(const ast::ColorAttribute* attr);
- /// Resolves the `@index` attribute @p attr
- /// @returns the index value on success.
- tint::Result<uint32_t> IndexAttribute(const ast::IndexAttribute* attr);
+ /// Resolves the `@blend_src` attribute @p attr
+ /// @returns the blend_src value on success.
+ tint::Result<uint32_t> BlendSrcAttribute(const ast::BlendSrcAttribute* attr);
/// Resolves the `@binding` attribute @p attr
/// @returns the binding value on success.
@@ -679,13 +683,13 @@
/// of determining if any two arguments alias at any callsite.
struct AliasAnalysisInfo {
/// The set of module-scope variables that are written to, and where that write occurs.
- std::unordered_map<const sem::Variable*, const sem::ValueExpression*> module_scope_writes;
+ Hashmap<const sem::Variable*, const sem::ValueExpression*, 4> module_scope_writes;
/// The set of module-scope variables that are read from, and where that read occurs.
- std::unordered_map<const sem::Variable*, const sem::ValueExpression*> module_scope_reads;
+ Hashmap<const sem::Variable*, const sem::ValueExpression*, 4> module_scope_reads;
/// The set of function parameters that are written to.
- std::unordered_set<const sem::Variable*> parameter_writes;
+ Hashset<const sem::Variable*, 4> parameter_writes;
/// The set of function parameters that are read from.
- std::unordered_set<const sem::Variable*> parameter_reads;
+ Hashset<const sem::Variable*, 4> parameter_reads;
};
ProgramBuilder& b;
diff --git a/src/tint/lang/wgsl/resolver/resolver_test.cc b/src/tint/lang/wgsl/resolver/resolver_test.cc
index f8bcdb4..8eb0457 100644
--- a/src/tint/lang/wgsl/resolver/resolver_test.cc
+++ b/src/tint/lang/wgsl/resolver/resolver_test.cc
@@ -1069,13 +1069,13 @@
auto* foo_sem = Sem().Get(foo);
ASSERT_NE(foo_sem, nullptr);
- ASSERT_EQ(foo_sem->CallSites().size(), 2u);
+ ASSERT_EQ(foo_sem->CallSites().Length(), 2u);
EXPECT_EQ(foo_sem->CallSites()[0]->Declaration(), call_1);
EXPECT_EQ(foo_sem->CallSites()[1]->Declaration(), call_2);
auto* bar_sem = Sem().Get(bar);
ASSERT_NE(bar_sem, nullptr);
- EXPECT_EQ(bar_sem->CallSites().size(), 0u);
+ EXPECT_EQ(bar_sem->CallSites().Length(), 0u);
}
TEST_F(ResolverTest, Function_WorkgroupSize_NotSet) {
@@ -2009,21 +2009,21 @@
EXPECT_EQ(func_c_sem->Parameters().Length(), 0u);
const auto& b_eps = func_b_sem->AncestorEntryPoints();
- ASSERT_EQ(2u, b_eps.size());
+ ASSERT_EQ(2u, b_eps.Length());
EXPECT_EQ(Symbols().Register("ep_1"), b_eps[0]->Declaration()->name->symbol);
EXPECT_EQ(Symbols().Register("ep_2"), b_eps[1]->Declaration()->name->symbol);
const auto& a_eps = func_a_sem->AncestorEntryPoints();
- ASSERT_EQ(1u, a_eps.size());
+ ASSERT_EQ(1u, a_eps.Length());
EXPECT_EQ(Symbols().Register("ep_1"), a_eps[0]->Declaration()->name->symbol);
const auto& c_eps = func_c_sem->AncestorEntryPoints();
- ASSERT_EQ(2u, c_eps.size());
+ ASSERT_EQ(2u, c_eps.Length());
EXPECT_EQ(Symbols().Register("ep_1"), c_eps[0]->Declaration()->name->symbol);
EXPECT_EQ(Symbols().Register("ep_2"), c_eps[1]->Declaration()->name->symbol);
- EXPECT_TRUE(ep_1_sem->AncestorEntryPoints().empty());
- EXPECT_TRUE(ep_2_sem->AncestorEntryPoints().empty());
+ EXPECT_TRUE(ep_1_sem->AncestorEntryPoints().IsEmpty());
+ EXPECT_TRUE(ep_2_sem->AncestorEntryPoints().IsEmpty());
}
// Check for linear-time traversal of functions reachable from entry points.
@@ -2469,7 +2469,7 @@
TEST_F(ResolverTest, ScopeDepth_NestedBlocks) {
const ast::Statement* stmt = Return();
- for (size_t i = 0; i < 150; i++) {
+ for (uint32_t i = 0; i < 150; i++) {
stmt = Block(Source{{i, 1}}, stmt);
}
WrapInFunction(stmt);
@@ -2481,7 +2481,7 @@
TEST_F(ResolverTest, ScopeDepth_NestedIf) {
const ast::Statement* stmt = Return();
- for (size_t i = 0; i < 150; i++) {
+ for (uint32_t i = 0; i < 150; i++) {
stmt = If(Source{{i, 1}}, false, Block(Source{{i, 2}}, stmt));
}
WrapInFunction(stmt);
@@ -2493,7 +2493,7 @@
TEST_F(ResolverTest, ScopeDepth_IfElseChain) {
const ast::Statement* stmt = nullptr;
- for (size_t i = 0; i < 150; i++) {
+ for (uint32_t i = 0; i < 150; i++) {
stmt = If(Source{{i, 1}}, false, Block(Source{{i, 2}}), Else(stmt));
}
WrapInFunction(stmt);
@@ -2545,13 +2545,13 @@
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
-size_t kMaxNestDepthOfCompositeType = 255;
+uint32_t kMaxNestDepthOfCompositeType = 255;
TEST_F(ResolverTest, MaxNestDepthOfCompositeType_Structs_Valid) {
auto* s = Structure("S", Vector{Member("m", ty.i32())});
- size_t depth = 1; // Depth of struct
- size_t iterations = kMaxNestDepthOfCompositeType - depth;
- for (size_t i = 0; i < iterations; ++i) {
+ uint32_t depth = 1; // Depth of struct
+ uint32_t iterations = kMaxNestDepthOfCompositeType - depth;
+ for (uint32_t i = 0; i < iterations; ++i) {
s = Structure("S" + std::to_string(i), Vector{Member("m", ty.Of(s))});
}
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -2559,9 +2559,9 @@
TEST_F(ResolverTest, MaxNestDepthOfCompositeType_Structs_Invalid) {
auto* s = Structure("S", Vector{Member("m", ty.i32())});
- size_t depth = 1; // Depth of struct
- size_t iterations = kMaxNestDepthOfCompositeType - depth + 1;
- for (size_t i = 0; i < iterations; ++i) {
+ uint32_t depth = 1; // Depth of struct
+ uint32_t iterations = kMaxNestDepthOfCompositeType - depth + 1;
+ for (uint32_t i = 0; i < iterations; ++i) {
auto source = i == iterations - 1 ? Source{{12, 34}} : Source{{0, i}};
s = Structure(source, "S" + std::to_string(i), Vector{Member("m", ty.Of(s))});
}
@@ -2571,9 +2571,9 @@
TEST_F(ResolverTest, MaxNestDepthOfCompositeType_StructsWithVector_Valid) {
auto* s = Structure("S", Vector{Member("m", ty.vec3<i32>())});
- size_t depth = 2; // Despth of struct + vector
- size_t iterations = kMaxNestDepthOfCompositeType - depth;
- for (size_t i = 0; i < iterations; ++i) {
+ uint32_t depth = 2; // Despth of struct + vector
+ uint32_t iterations = kMaxNestDepthOfCompositeType - depth;
+ for (uint32_t i = 0; i < iterations; ++i) {
s = Structure("S" + std::to_string(i), Vector{Member("m", ty.Of(s))});
}
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -2581,9 +2581,9 @@
TEST_F(ResolverTest, MaxNestDepthOfCompositeType_StructsWithVector_Invalid) {
auto* s = Structure("S", Vector{Member("m", ty.vec3<i32>())});
- size_t depth = 2; // Despth of struct + vector
- size_t iterations = kMaxNestDepthOfCompositeType - depth + 1;
- for (size_t i = 0; i < iterations; ++i) {
+ uint32_t depth = 2; // Despth of struct + vector
+ uint32_t iterations = kMaxNestDepthOfCompositeType - depth + 1;
+ for (uint32_t i = 0; i < iterations; ++i) {
auto source = i == iterations - 1 ? Source{{12, 34}} : Source{{0, i}};
s = Structure(source, "S" + std::to_string(i), Vector{Member("m", ty.Of(s))});
}
@@ -2593,9 +2593,9 @@
TEST_F(ResolverTest, MaxNestDepthOfCompositeType_StructsWithMatrix_Valid) {
auto* s = Structure("S", Vector{Member("m", ty.mat3x3<f32>())});
- size_t depth = 3; // Depth of struct + matrix
- size_t iterations = kMaxNestDepthOfCompositeType - depth;
- for (size_t i = 0; i < iterations; ++i) {
+ uint32_t depth = 3; // Depth of struct + matrix
+ uint32_t iterations = kMaxNestDepthOfCompositeType - depth;
+ for (uint32_t i = 0; i < iterations; ++i) {
s = Structure("S" + std::to_string(i), Vector{Member("m", ty.Of(s))});
}
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -2603,9 +2603,9 @@
TEST_F(ResolverTest, MaxNestDepthOfCompositeType_StructsWithMatrix_Invalid) {
auto* s = Structure("S", Vector{Member("m", ty.mat3x3<f32>())});
- size_t depth = 3; // Depth of struct + matrix
- size_t iterations = kMaxNestDepthOfCompositeType - depth + 1;
- for (size_t i = 0; i < iterations; ++i) {
+ uint32_t depth = 3; // Depth of struct + matrix
+ uint32_t iterations = kMaxNestDepthOfCompositeType - depth + 1;
+ for (uint32_t i = 0; i < iterations; ++i) {
auto source = i == iterations - 1 ? Source{{12, 34}} : Source{{0, i}};
s = Structure(source, "S" + std::to_string(i), Vector{Member("m", ty.Of(s))});
}
@@ -2615,9 +2615,9 @@
TEST_F(ResolverTest, MaxNestDepthOfCompositeType_Arrays_Valid) {
auto a = ty.array(ty.i32(), 10_u);
- size_t depth = 1; // Depth of array
- size_t iterations = kMaxNestDepthOfCompositeType - depth;
- for (size_t i = 0; i < iterations; ++i) {
+ uint32_t depth = 1; // Depth of array
+ uint32_t iterations = kMaxNestDepthOfCompositeType - depth;
+ for (uint32_t i = 0; i < iterations; ++i) {
a = ty.array(a, 1_u);
}
Alias("a", a);
@@ -2626,9 +2626,9 @@
TEST_F(ResolverTest, MaxNestDepthOfCompositeType_Arrays_Invalid) {
auto a = ty.array(Source{{99, 88}}, ty.i32(), 10_u);
- size_t depth = 1; // Depth of array
- size_t iterations = kMaxNestDepthOfCompositeType - depth + 1;
- for (size_t i = 0; i < iterations; ++i) {
+ uint32_t depth = 1; // Depth of array
+ uint32_t iterations = kMaxNestDepthOfCompositeType - depth + 1;
+ for (uint32_t i = 0; i < iterations; ++i) {
auto source = (i == iterations - 1) ? Source{{12, 34}} : Source{{0, i}};
a = ty.array(source, a, 1_u);
}
@@ -2639,9 +2639,9 @@
TEST_F(ResolverTest, MaxNestDepthOfCompositeType_ArraysOfVector_Valid) {
auto a = ty.array<vec3<i32>, 10>();
- size_t depth = 2; // Depth of array + vector
- size_t iterations = kMaxNestDepthOfCompositeType - depth;
- for (size_t i = 0; i < iterations; ++i) {
+ uint32_t depth = 2; // Depth of array + vector
+ uint32_t iterations = kMaxNestDepthOfCompositeType - depth;
+ for (uint32_t i = 0; i < iterations; ++i) {
a = ty.array(a, 1_u);
}
Alias("a", a);
@@ -2650,9 +2650,9 @@
TEST_F(ResolverTest, MaxNestDepthOfCompositeType_ArraysOfVector_Invalid) {
auto a = ty.array(Source{{99, 88}}, ty.vec3<i32>(), 10_u);
- size_t depth = 2; // Depth of array + vector
- size_t iterations = kMaxNestDepthOfCompositeType - depth + 1;
- for (size_t i = 0; i < iterations; ++i) {
+ uint32_t depth = 2; // Depth of array + vector
+ uint32_t iterations = kMaxNestDepthOfCompositeType - depth + 1;
+ for (uint32_t i = 0; i < iterations; ++i) {
auto source = (i == iterations - 1) ? Source{{12, 34}} : Source{{0, i}};
a = ty.array(source, a, 1_u);
}
@@ -2663,9 +2663,9 @@
TEST_F(ResolverTest, MaxNestDepthOfCompositeType_ArraysOfMatrix_Valid) {
auto a = ty.array(ty.mat3x3<f32>(), 10_u);
- size_t depth = 3; // Depth of array + matrix
- size_t iterations = kMaxNestDepthOfCompositeType - depth;
- for (size_t i = 0; i < iterations; ++i) {
+ uint32_t depth = 3; // Depth of array + matrix
+ uint32_t iterations = kMaxNestDepthOfCompositeType - depth;
+ for (uint32_t i = 0; i < iterations; ++i) {
a = ty.array(a, 1_u);
}
Alias("a", a);
@@ -2674,9 +2674,9 @@
TEST_F(ResolverTest, MaxNestDepthOfCompositeType_ArraysOfMatrix_Invalid) {
auto a = ty.array(ty.mat3x3<f32>(), 10_u);
- size_t depth = 3; // Depth of array + matrix
- size_t iterations = kMaxNestDepthOfCompositeType - depth + 1;
- for (size_t i = 0; i < iterations; ++i) {
+ uint32_t depth = 3; // Depth of array + matrix
+ uint32_t iterations = kMaxNestDepthOfCompositeType - depth + 1;
+ for (uint32_t i = 0; i < iterations; ++i) {
auto source = (i == iterations - 1) ? Source{{12, 34}} : Source{{0, i}};
a = ty.array(source, a, 1_u);
}
@@ -2688,9 +2688,9 @@
TEST_F(ResolverTest, MaxNestDepthOfCompositeType_StructsOfArray_Valid) {
auto a = ty.array(ty.mat3x3<f32>(), 10_u);
auto* s = Structure("S", Vector{Member("m", a)});
- size_t depth = 4; // Depth of struct + array + matrix
- size_t iterations = kMaxNestDepthOfCompositeType - depth;
- for (size_t i = 0; i < iterations; ++i) {
+ uint32_t depth = 4; // Depth of struct + array + matrix
+ uint32_t iterations = kMaxNestDepthOfCompositeType - depth;
+ for (uint32_t i = 0; i < iterations; ++i) {
s = Structure("S" + std::to_string(i), Vector{Member("m", ty.Of(s))});
}
EXPECT_TRUE(r()->Resolve()) << r()->error();
@@ -2699,9 +2699,9 @@
TEST_F(ResolverTest, MaxNestDepthOfCompositeType_StructsOfArray_Invalid) {
auto a = ty.array(ty.mat3x3<f32>(), 10_u);
auto* s = Structure("S", Vector{Member("m", a)});
- size_t depth = 4; // Depth of struct + array + matrix
- size_t iterations = kMaxNestDepthOfCompositeType - depth + 1;
- for (size_t i = 0; i < iterations; ++i) {
+ uint32_t depth = 4; // Depth of struct + array + matrix
+ uint32_t iterations = kMaxNestDepthOfCompositeType - depth + 1;
+ for (uint32_t i = 0; i < iterations; ++i) {
auto source = i == iterations - 1 ? Source{{12, 34}} : Source{{0, i}};
s = Structure(source, "S" + std::to_string(i), Vector{Member("m", ty.Of(s))});
}
@@ -2712,9 +2712,9 @@
TEST_F(ResolverTest, MaxNestDepthOfCompositeType_ArraysOfStruct_Valid) {
auto* s = Structure("S", Vector{Member("m", ty.mat3x3<f32>())});
auto a = ty.array(ty.Of(s), 10_u);
- size_t depth = 4; // Depth of array + struct + matrix
- size_t iterations = kMaxNestDepthOfCompositeType - depth;
- for (size_t i = 0; i < iterations; ++i) {
+ uint32_t depth = 4; // Depth of array + struct + matrix
+ uint32_t iterations = kMaxNestDepthOfCompositeType - depth;
+ for (uint32_t i = 0; i < iterations; ++i) {
a = ty.array(a, 1_u);
}
Alias("a", a);
@@ -2724,9 +2724,9 @@
TEST_F(ResolverTest, MaxNestDepthOfCompositeType_ArraysOfStruct_Invalid) {
auto* s = Structure("S", Vector{Member("m", ty.mat3x3<f32>())});
auto a = ty.array(ty.Of(s), 10_u);
- size_t depth = 4; // Depth of array + struct + matrix
- size_t iterations = kMaxNestDepthOfCompositeType - depth + 1;
- for (size_t i = 0; i < iterations; ++i) {
+ uint32_t depth = 4; // Depth of array + struct + matrix
+ uint32_t iterations = kMaxNestDepthOfCompositeType - depth + 1;
+ for (uint32_t i = 0; i < iterations; ++i) {
auto source = (i == iterations - 1) ? Source{{12, 34}} : Source{{0, i}};
a = ty.array(source, a, 1_u);
}
diff --git a/src/tint/lang/wgsl/resolver/struct_address_space_use_test.cc b/src/tint/lang/wgsl/resolver/struct_address_space_use_test.cc
index bf5f835..5e017fc 100644
--- a/src/tint/lang/wgsl/resolver/struct_address_space_use_test.cc
+++ b/src/tint/lang/wgsl/resolver/struct_address_space_use_test.cc
@@ -47,7 +47,7 @@
auto* sem = TypeOf(s)->As<core::type::Struct>();
ASSERT_NE(sem, nullptr);
- EXPECT_TRUE(sem->AddressSpaceUsage().empty());
+ EXPECT_TRUE(sem->AddressSpaceUsage().IsEmpty());
}
TEST_F(ResolverAddressSpaceUseTest, StructReachableFromParameter) {
diff --git a/src/tint/lang/wgsl/resolver/struct_pipeline_stage_use_test.cc b/src/tint/lang/wgsl/resolver/struct_pipeline_stage_use_test.cc
index d3537db..cb0adab 100644
--- a/src/tint/lang/wgsl/resolver/struct_pipeline_stage_use_test.cc
+++ b/src/tint/lang/wgsl/resolver/struct_pipeline_stage_use_test.cc
@@ -49,7 +49,7 @@
auto* sem = TypeOf(s)->As<core::type::Struct>();
ASSERT_NE(sem, nullptr);
- EXPECT_TRUE(sem->PipelineStageUses().empty());
+ EXPECT_TRUE(sem->PipelineStageUses().IsEmpty());
}
TEST_F(ResolverPipelineStageUseTest, StructUsedAsNonEntryPointParam) {
@@ -61,7 +61,7 @@
auto* sem = TypeOf(s)->As<core::type::Struct>();
ASSERT_NE(sem, nullptr);
- EXPECT_TRUE(sem->PipelineStageUses().empty());
+ EXPECT_TRUE(sem->PipelineStageUses().IsEmpty());
}
TEST_F(ResolverPipelineStageUseTest, StructUsedAsNonEntryPointReturnType) {
@@ -73,7 +73,7 @@
auto* sem = TypeOf(s)->As<core::type::Struct>();
ASSERT_NE(sem, nullptr);
- EXPECT_TRUE(sem->PipelineStageUses().empty());
+ EXPECT_TRUE(sem->PipelineStageUses().IsEmpty());
}
TEST_F(ResolverPipelineStageUseTest, StructUsedAsVertexShaderParam) {
diff --git a/src/tint/lang/wgsl/resolver/validator.cc b/src/tint/lang/wgsl/resolver/validator.cc
index e6f7c31..907a3c4 100644
--- a/src/tint/lang/wgsl/resolver/validator.cc
+++ b/src/tint/lang/wgsl/resolver/validator.cc
@@ -47,6 +47,7 @@
#include "src/tint/lang/wgsl/ast/alias.h"
#include "src/tint/lang/wgsl/ast/assignment_statement.h"
#include "src/tint/lang/wgsl/ast/bitcast_expression.h"
+#include "src/tint/lang/wgsl/ast/blend_src_attribute.h"
#include "src/tint/lang/wgsl/ast/break_statement.h"
#include "src/tint/lang/wgsl/ast/call_statement.h"
#include "src/tint/lang/wgsl/ast/continue_statement.h"
@@ -55,7 +56,6 @@
#include "src/tint/lang/wgsl/ast/for_loop_statement.h"
#include "src/tint/lang/wgsl/ast/id_attribute.h"
#include "src/tint/lang/wgsl/ast/if_statement.h"
-#include "src/tint/lang/wgsl/ast/index_attribute.h"
#include "src/tint/lang/wgsl/ast/internal_attribute.h"
#include "src/tint/lang/wgsl/ast/interpolate_attribute.h"
#include "src/tint/lang/wgsl/ast/loop_statement.h"
@@ -1147,9 +1147,9 @@
// TODO(jrprice): This state could be stored in sem::Function instead, and then passed to
// sem::Function since it would be useful there too.
Hashset<core::BuiltinValue, 4> builtins;
- Hashset<std::pair<uint32_t, uint32_t>, 8> locations_and_indices;
+ Hashset<std::pair<uint32_t, uint32_t>, 8> locations_and_blend_srcs;
const ast::LocationAttribute* first_nonzero_location = nullptr;
- const ast::IndexAttribute* first_nonzero_index = nullptr;
+ const ast::BlendSrcAttribute* first_nonzero_blend_src = nullptr;
Hashset<uint32_t, 4> colors;
enum class ParamOrRetType {
kParameter,
@@ -1162,14 +1162,14 @@
ParamOrRetType param_or_ret,
bool is_struct_member,
std::optional<uint32_t> location,
- std::optional<uint32_t> index,
+ std::optional<uint32_t> blend_src,
std::optional<uint32_t> color) {
// Scan attributes for pipeline IO attributes.
// Check for overlap with attributes that have been seen previously.
const ast::Attribute* pipeline_io_attribute = nullptr;
const ast::LocationAttribute* location_attribute = nullptr;
const ast::ColorAttribute* color_attribute = nullptr;
- const ast::IndexAttribute* index_attribute = nullptr;
+ const ast::BlendSrcAttribute* blend_src_attribute = nullptr;
const ast::InterpolateAttribute* interpolate_attribute = nullptr;
const ast::InvariantAttribute* invariant_attribute = nullptr;
for (auto* attr : attrs) {
@@ -1219,15 +1219,15 @@
return LocationAttribute(loc_attr, ty, stage, source);
},
- [&](const ast::IndexAttribute* index_attr) {
- index_attribute = index_attr;
+ [&](const ast::BlendSrcAttribute* blend_src_attr) {
+ blend_src_attribute = blend_src_attr;
- if (TINT_UNLIKELY(!index.has_value())) {
- TINT_ICE() << "@index has no value";
+ if (TINT_UNLIKELY(!blend_src.has_value())) {
+ TINT_ICE() << "@blend_src has no value";
return false;
}
- return IndexAttribute(index_attr, stage);
+ return BlendSrcAttribute(blend_src_attr, stage);
},
[&](const ast::ColorAttribute* col_attr) {
color_attribute = col_attr;
@@ -1300,12 +1300,13 @@
}
}
- if (index_attribute) {
+ if (blend_src_attribute) {
// Because HLSL specifies dual source blending targets with SV_Target0 and 1, we
- // should restrict targets with @index to location 0 for easy translation
+ // should restrict targets with @blend_src to location 0 for easy translation
// in the backend writers.
if (location.value_or(1) != 0) {
- AddError("@index can only be used with @location(0)", index_attribute->source);
+ AddError("@blend_src can only be used with @location(0)",
+ blend_src_attribute->source);
return false;
}
}
@@ -1314,23 +1315,23 @@
if (!first_nonzero_location && location > 0u) {
first_nonzero_location = location_attribute;
}
- if (!first_nonzero_index && index > 0u) {
- first_nonzero_index = index_attribute;
+ if (!first_nonzero_blend_src && blend_src > 0u) {
+ first_nonzero_blend_src = blend_src_attribute;
}
- if (first_nonzero_location && first_nonzero_index) {
- AddError("pipeline cannot use both non-zero @index and non-zero @location",
- first_nonzero_index->source);
+ if (first_nonzero_location && first_nonzero_blend_src) {
+ AddError("pipeline cannot use both non-zero @blend_src and non-zero @location",
+ first_nonzero_blend_src->source);
AddNote("non-zero @location declared here", first_nonzero_location->source);
return false;
}
- std::pair<uint32_t, uint32_t> location_and_index(location.value(),
- index.value_or(0));
- if (!locations_and_indices.Add(location_and_index)) {
+ std::pair<uint32_t, uint32_t> location_and_blend_src(location.value(),
+ blend_src.value_or(0));
+ if (!locations_and_blend_srcs.Add(location_and_blend_src)) {
StringStream err;
err << "@location(" << location.value() << ") ";
- if (index_attribute) {
- err << "@index(" << index.value() << ") ";
+ if (blend_src_attribute) {
+ err << "@blend_src(" << blend_src.value() << ") ";
}
err << "appears multiple times";
AddError(err.str(), location_attribute->source);
@@ -1389,7 +1390,7 @@
member->Declaration()->attributes, member->Type(),
member->Declaration()->source, param_or_ret,
/*is_struct_member*/ true, member->Attributes().location,
- member->Attributes().index, member->Attributes().color)) {
+ member->Attributes().blend_src, member->Attributes().color)) {
AddNote("while analyzing entry point '" + decl->name->symbol.Name() + "'",
decl->source);
return false;
@@ -1413,9 +1414,9 @@
// Clear IO sets after parameter validation. Builtin and location attributes in return types
// should be validated independently from those used in parameters.
builtins.Clear();
- locations_and_indices.Clear();
+ locations_and_blend_srcs.Clear();
first_nonzero_location = nullptr;
- first_nonzero_index = nullptr;
+ first_nonzero_blend_src = nullptr;
if (!func->ReturnType()->Is<core::type::Void>()) {
if (!validate_entry_point_attributes(decl->return_type_attributes, func->ReturnType(),
@@ -2225,7 +2226,7 @@
return false;
}
- Hashset<std::pair<uint32_t, uint32_t>, 8> locations_and_indices;
+ Hashset<std::pair<uint32_t, uint32_t>, 8> locations_and_blend_srcs;
Hashset<uint32_t, 4> colors;
for (auto* member : str->Members()) {
if (auto* r = member->Type()->As<sem::Array>()) {
@@ -2249,7 +2250,7 @@
}
auto has_position = false;
- const ast::IndexAttribute* index_attribute = nullptr;
+ const ast::BlendSrcAttribute* blend_src_attribute = nullptr;
const ast::LocationAttribute* location_attribute = nullptr;
const ast::ColorAttribute* color_attribute = nullptr;
const ast::InvariantAttribute* invariant_attribute = nullptr;
@@ -2267,9 +2268,9 @@
return LocationAttribute(location, member->Type(), stage,
member->Declaration()->source);
},
- [&](const ast::IndexAttribute* index) {
- index_attribute = index;
- return IndexAttribute(index, stage);
+ [&](const ast::BlendSrcAttribute* blend_src) {
+ blend_src_attribute = blend_src;
+ return BlendSrcAttribute(blend_src, stage);
},
[&](const ast::ColorAttribute* color) {
color_attribute = color;
@@ -2313,12 +2314,13 @@
return false;
}
- if (index_attribute) {
+ if (blend_src_attribute) {
// Because HLSL specifies dual source blending targets with SV_Target0 and 1, we should
// restrict targets with index attributes to location 0 for easy translation in the
// backend writers.
if (member->Attributes().location.value_or(1) != 0) {
- AddError("@index can only be used with @location(0)", index_attribute->source);
+ AddError("@blend_src can only be used with @location(0)",
+ blend_src_attribute->source);
return false;
}
}
@@ -2331,14 +2333,14 @@
// Ensure all locations and index pairs are unique
if (location_attribute) {
uint32_t location = member->Attributes().location.value();
- uint32_t index = member->Attributes().index.value_or(0);
+ uint32_t blend_src = member->Attributes().blend_src.value_or(0);
- std::pair<uint32_t, uint32_t> location_and_index(location, index);
- if (!locations_and_indices.Add(location_and_index)) {
+ std::pair<uint32_t, uint32_t> location_and_blend_src(location, blend_src);
+ if (!locations_and_blend_srcs.Add(location_and_blend_src)) {
StringStream err;
err << "@location(" << location << ") ";
- if (index_attribute) {
- err << "@index(" << index << ") ";
+ if (blend_src_attribute) {
+ err << "@blend_src(" << blend_src << ") ";
}
err << "appears multiple times";
AddError(err.str(), location_attribute->source);
@@ -2414,12 +2416,13 @@
return true;
}
-bool Validator::IndexAttribute(const ast::IndexAttribute* attr,
- ast::PipelineStage stage,
- const std::optional<bool> is_input) const {
+bool Validator::BlendSrcAttribute(const ast::BlendSrcAttribute* attr,
+ ast::PipelineStage stage,
+ const std::optional<bool> is_input) const {
if (!enabled_extensions_.Contains(wgsl::Extension::kChromiumInternalDualSourceBlending)) {
AddError(
- "use of @index requires enabling extension 'chromium_internal_dual_source_blending'",
+ "use of @blend_src requires enabling extension "
+ "'chromium_internal_dual_source_blending'",
attr->source);
return false;
}
diff --git a/src/tint/lang/wgsl/resolver/validator.h b/src/tint/lang/wgsl/resolver/validator.h
index 8bf5af3..4834073 100644
--- a/src/tint/lang/wgsl/resolver/validator.h
+++ b/src/tint/lang/wgsl/resolver/validator.h
@@ -371,14 +371,14 @@
const std::optional<bool> is_input = std::nullopt) const;
/// Validates a index attribute
- /// @param index_attr the index attribute to validate
+ /// @param blend_src_attr the blend_src attribute to validate
/// @param stage the current pipeline stage
/// @param is_input true if is an input variable, false if output variable, std::nullopt is
/// unknown.
/// @returns true on success, false otherwise.
- bool IndexAttribute(const ast::IndexAttribute* index_attr,
- ast::PipelineStage stage,
- const std::optional<bool> is_input = std::nullopt) const;
+ bool BlendSrcAttribute(const ast::BlendSrcAttribute* blend_src_attr,
+ ast::PipelineStage stage,
+ const std::optional<bool> is_input = std::nullopt) const;
/// Validates a loop statement
/// @param stmt the loop statement
diff --git a/src/tint/lang/wgsl/resolver/value_constructor_validation_test.cc b/src/tint/lang/wgsl/resolver/value_constructor_validation_test.cc
index 3f0e1ca..027b471 100644
--- a/src/tint/lang/wgsl/resolver/value_constructor_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/value_constructor_validation_test.cc
@@ -2626,7 +2626,7 @@
}
args_tys << "vec" << param.rows << "<" + element_type_name + ">";
}
- const size_t kInvalidLoc = 2 * (param.columns - 1);
+ const uint32_t kInvalidLoc = 2 * (param.columns - 1);
auto invalid_vec_type = ty.vec(param.create_element_ast_type(*this), param.rows - 1);
args.Push(Call(Source{{12, kInvalidLoc}}, invalid_vec_type));
args_tys << ", vec" << (param.rows - 1) << "<" + element_type_name + ">";
diff --git a/src/tint/lang/wgsl/sem/function.cc b/src/tint/lang/wgsl/sem/function.cc
index 9a56376..311c903 100644
--- a/src/tint/lang/wgsl/sem/function.cc
+++ b/src/tint/lang/wgsl/sem/function.cc
@@ -201,4 +201,8 @@
return ret;
}
+void Function::SetDiagnosticSeverity(wgsl::DiagnosticRule rule, wgsl::DiagnosticSeverity severity) {
+ diagnostic_severities_.Add(rule, severity);
+}
+
} // namespace tint::sem
diff --git a/src/tint/lang/wgsl/sem/function.h b/src/tint/lang/wgsl/sem/function.h
index a2a87ae..88b3c3d 100644
--- a/src/tint/lang/wgsl/sem/function.h
+++ b/src/tint/lang/wgsl/sem/function.h
@@ -155,12 +155,12 @@
/// @returns the list of direct calls to functions / builtins made by this
/// function
- std::vector<const Call*> DirectCalls() const { return direct_calls_; }
+ const Vector<const Call*, 1>& DirectCalls() const { return direct_calls_; }
/// Adds a record of the direct function / builtin calls made by this
/// function
/// @param call the call
- void AddDirectCall(const Call* call) { direct_calls_.emplace_back(call); }
+ void AddDirectCall(const Call* call) { direct_calls_.Push(call); }
/// @param target the target of a call
/// @returns the Call to the given CallTarget, or nullptr the target was not
@@ -175,21 +175,19 @@
}
/// @returns the list of callsites to this function
- std::vector<const Call*> CallSites() const { return callsites_; }
+ const Vector<const Call*, 1>& CallSites() const { return callsites_; }
/// Adds a record of a callsite to this function
/// @param call the callsite
- void AddCallSite(const Call* call) { callsites_.emplace_back(call); }
+ void AddCallSite(const Call* call) { callsites_.Push(call); }
/// @returns the ancestor entry points
- const std::vector<const Function*>& AncestorEntryPoints() const {
- return ancestor_entry_points_;
- }
+ const Vector<const Function*, 1>& AncestorEntryPoints() const { return ancestor_entry_points_; }
/// Adds a record that the given entry point transitively calls this function
/// @param entry_point the entry point that transtively calls this function
void AddAncestorEntryPoint(const sem::Function* entry_point) {
- ancestor_entry_points_.emplace_back(entry_point);
+ ancestor_entry_points_.Push(entry_point);
}
/// Retrieves any referenced location variables
@@ -278,9 +276,7 @@
/// Modifies the severity of a specific diagnostic rule for this function.
/// @param rule the diagnostic rule
/// @param severity the new diagnostic severity
- void SetDiagnosticSeverity(wgsl::DiagnosticRule rule, wgsl::DiagnosticSeverity severity) {
- diagnostic_severities_[rule] = severity;
- }
+ void SetDiagnosticSeverity(wgsl::DiagnosticRule rule, wgsl::DiagnosticSeverity severity);
/// @returns the diagnostic severity modifications applied to this function
const wgsl::DiagnosticRuleSeverities& DiagnosticSeverities() const {
@@ -302,9 +298,9 @@
UniqueVector<const Function*, 8> transitively_called_functions_;
UniqueVector<const BuiltinFn*, 4> directly_called_builtins_;
UniqueVector<VariablePair, 8> texture_sampler_pairs_;
- std::vector<const Call*> direct_calls_;
- std::vector<const Call*> callsites_;
- std::vector<const Function*> ancestor_entry_points_;
+ Vector<const Call*, 1> direct_calls_;
+ Vector<const Call*, 1> callsites_;
+ Vector<const Function*, 1> ancestor_entry_points_;
const Statement* discard_stmt_ = nullptr;
sem::Behaviors behaviors_{sem::Behavior::kNext};
wgsl::DiagnosticRuleSeverities diagnostic_severities_;
diff --git a/src/tint/lang/wgsl/sem/info.cc b/src/tint/lang/wgsl/sem/info.cc
index e9b59be..bfd6c0d 100644
--- a/src/tint/lang/wgsl/sem/info.cc
+++ b/src/tint/lang/wgsl/sem/info.cc
@@ -47,10 +47,8 @@
wgsl::DiagnosticRule rule) const {
// Get the diagnostic severity modification for a node.
auto check = [&](auto* node) {
- auto& severities = node->DiagnosticSeverities();
- auto itr = severities.find(rule);
- if (itr != severities.end()) {
- return itr->second;
+ if (auto severity = node->DiagnosticSeverities().Get(rule)) {
+ return *severity;
}
return wgsl::DiagnosticSeverity::kUndefined;
};
diff --git a/src/tint/lang/wgsl/sem/info.h b/src/tint/lang/wgsl/sem/info.h
index f63fa1c..bd2daf4 100644
--- a/src/tint/lang/wgsl/sem/info.h
+++ b/src/tint/lang/wgsl/sem/info.h
@@ -80,7 +80,7 @@
/// @param highest_node_id the last allocated (numerically highest) AST node identifier.
void Reserve(ast::NodeID highest_node_id) {
- nodes_.resize(std::max(highest_node_id.value + 1, nodes_.size()));
+ nodes_.Resize(std::max(highest_node_id.value + 1, static_cast<uint32_t>(nodes_.Length())));
}
/// Get looks up the semantic information for the AST node `ast_node`.
@@ -93,7 +93,7 @@
static_assert(std::is_same_v<SEM, InferFromAST> ||
!tint::traits::IsTypeOrDerived<SemanticNodeTypeFor<AST>, SEM>,
"explicit template argument is unnecessary");
- if (ast_node && ast_node->node_id.value < nodes_.size()) {
+ if (ast_node && ast_node->node_id.value < nodes_.Length()) {
return As<RESULT>(nodes_[ast_node->node_id.value]);
}
return nullptr;
@@ -157,7 +157,7 @@
private:
// AST node index to semantic node
- std::vector<const CastableBase*> nodes_;
+ tint::Vector<const CastableBase*, 0> nodes_;
// The semantic module
sem::Module* module_ = nullptr;
};
diff --git a/src/tint/lang/wgsl/sem/module.cc b/src/tint/lang/wgsl/sem/module.cc
index 6e04901..178d662 100644
--- a/src/tint/lang/wgsl/sem/module.cc
+++ b/src/tint/lang/wgsl/sem/module.cc
@@ -39,4 +39,8 @@
Module::~Module() = default;
+void Module::SetDiagnosticSeverity(wgsl::DiagnosticRule rule, wgsl::DiagnosticSeverity severity) {
+ diagnostic_severities_.Add(rule, severity);
+}
+
} // namespace tint::sem
diff --git a/src/tint/lang/wgsl/sem/module.h b/src/tint/lang/wgsl/sem/module.h
index c95798e..98c1022 100644
--- a/src/tint/lang/wgsl/sem/module.h
+++ b/src/tint/lang/wgsl/sem/module.h
@@ -61,9 +61,7 @@
/// Modifies the severity of a specific diagnostic rule for this module.
/// @param rule the diagnostic rule
/// @param severity the new diagnostic severity
- void SetDiagnosticSeverity(wgsl::DiagnosticRule rule, wgsl::DiagnosticSeverity severity) {
- diagnostic_severities_[rule] = severity;
- }
+ void SetDiagnosticSeverity(wgsl::DiagnosticRule rule, wgsl::DiagnosticSeverity severity);
/// @returns the diagnostic severity modifications applied to this module
const wgsl::DiagnosticRuleSeverities& DiagnosticSeverities() const {
diff --git a/src/tint/lang/wgsl/sem/statement.cc b/src/tint/lang/wgsl/sem/statement.cc
index 8497bb4..0e1a8c7 100644
--- a/src/tint/lang/wgsl/sem/statement.cc
+++ b/src/tint/lang/wgsl/sem/statement.cc
@@ -52,6 +52,11 @@
return FindFirstParent<BlockStatement>();
}
+void Statement::SetDiagnosticSeverity(wgsl::DiagnosticRule rule,
+ wgsl::DiagnosticSeverity severity) {
+ diagnostic_severities_.Add(rule, severity);
+}
+
CompoundStatement::CompoundStatement(const ast::Statement* declaration,
const CompoundStatement* parent,
const sem::Function* function)
diff --git a/src/tint/lang/wgsl/sem/statement.h b/src/tint/lang/wgsl/sem/statement.h
index 88e1685..2e023fc 100644
--- a/src/tint/lang/wgsl/sem/statement.h
+++ b/src/tint/lang/wgsl/sem/statement.h
@@ -126,9 +126,7 @@
/// Modifies the severity of a specific diagnostic rule for this statement.
/// @param rule the diagnostic rule
/// @param severity the new diagnostic severity
- void SetDiagnosticSeverity(wgsl::DiagnosticRule rule, wgsl::DiagnosticSeverity severity) {
- diagnostic_severities_[rule] = severity;
- }
+ void SetDiagnosticSeverity(wgsl::DiagnosticRule rule, wgsl::DiagnosticSeverity severity);
/// @returns the diagnostic severity modifications applied to this statement
const wgsl::DiagnosticRuleSeverities& DiagnosticSeverities() const {
diff --git a/src/tint/lang/wgsl/writer/ast_printer/ast_printer.cc b/src/tint/lang/wgsl/writer/ast_printer/ast_printer.cc
index 2f51a4c..517ea6d 100644
--- a/src/tint/lang/wgsl/writer/ast_printer/ast_printer.cc
+++ b/src/tint/lang/wgsl/writer/ast_printer/ast_printer.cc
@@ -35,6 +35,7 @@
#include "src/tint/lang/wgsl/ast/assignment_statement.h"
#include "src/tint/lang/wgsl/ast/binary_expression.h"
#include "src/tint/lang/wgsl/ast/bitcast_expression.h"
+#include "src/tint/lang/wgsl/ast/blend_src_attribute.h"
#include "src/tint/lang/wgsl/ast/bool_literal_expression.h"
#include "src/tint/lang/wgsl/ast/break_if_statement.h"
#include "src/tint/lang/wgsl/ast/break_statement.h"
@@ -55,7 +56,6 @@
#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/index_attribute.h"
#include "src/tint/lang/wgsl/ast/int_literal_expression.h"
#include "src/tint/lang/wgsl/ast/internal_attribute.h"
#include "src/tint/lang/wgsl/ast/interpolate_attribute.h"
@@ -511,8 +511,8 @@
EmitExpression(out, color->expr);
out << ")";
},
- [&](const ast::IndexAttribute* index) {
- out << "index(";
+ [&](const ast::BlendSrcAttribute* index) {
+ out << "blend_src(";
EmitExpression(out, index->expr);
out << ")";
},
diff --git a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
index 712fab3..c6498a1 100644
--- a/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
+++ b/src/tint/lang/wgsl/writer/ir_to_program/ir_to_program.cc
@@ -1078,9 +1078,9 @@
if (auto location = ir_attrs.location) {
ast_attrs.Push(b.Location(u32(*location)));
}
- if (auto index = ir_attrs.index) {
+ if (auto blend_src = ir_attrs.blend_src) {
Enable(wgsl::Extension::kChromiumInternalDualSourceBlending);
- ast_attrs.Push(b.Index(u32(*index)));
+ ast_attrs.Push(b.BlendSrc(u32(*blend_src)));
}
if (auto builtin = ir_attrs.builtin) {
if (RequiresSubgroups(*builtin)) {
diff --git a/src/tint/lang/wgsl/writer/syntax_tree_printer/syntax_tree_printer.cc b/src/tint/lang/wgsl/writer/syntax_tree_printer/syntax_tree_printer.cc
index 529f9c2..6c0b0b4 100644
--- a/src/tint/lang/wgsl/writer/syntax_tree_printer/syntax_tree_printer.cc
+++ b/src/tint/lang/wgsl/writer/syntax_tree_printer/syntax_tree_printer.cc
@@ -32,6 +32,7 @@
#include "src/tint/lang/wgsl/ast/assignment_statement.h"
#include "src/tint/lang/wgsl/ast/binary_expression.h"
#include "src/tint/lang/wgsl/ast/bitcast_expression.h"
+#include "src/tint/lang/wgsl/ast/blend_src_attribute.h"
#include "src/tint/lang/wgsl/ast/bool_literal_expression.h"
#include "src/tint/lang/wgsl/ast/break_if_statement.h"
#include "src/tint/lang/wgsl/ast/break_statement.h"
@@ -51,7 +52,6 @@
#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/index_attribute.h"
#include "src/tint/lang/wgsl/ast/int_literal_expression.h"
#include "src/tint/lang/wgsl/ast/internal_attribute.h"
#include "src/tint/lang/wgsl/ast/interpolate_attribute.h"
@@ -563,8 +563,8 @@
}
Line() << "]";
},
- [&](const ast::IndexAttribute* index) {
- Line() << "IndexAttribute [";
+ [&](const ast::BlendSrcAttribute* index) {
+ Line() << "BlendSrcAttribute [";
{
ScopedIndent idx(this);
EmitExpression(index->expr);
diff --git a/src/tint/utils/containers/hashmap_base.h b/src/tint/utils/containers/hashmap_base.h
index b665891..81141ba 100644
--- a/src/tint/utils/containers/hashmap_base.h
+++ b/src/tint/utils/containers/hashmap_base.h
@@ -639,7 +639,7 @@
size_t Wrap(size_t index) const { return index % slots_.Length(); }
/// The vector of slots. The vector length is equal to its capacity.
- Vector<Slot, kNumFixedSlots> slots_;
+ Vector<Slot, kMinSlots> slots_;
/// The number of entries in the map.
size_t count_ = 0;
diff --git a/src/tint/utils/diagnostic/source.h b/src/tint/utils/diagnostic/source.h
index 4c2fc9a..8400921 100644
--- a/src/tint/utils/diagnostic/source.h
+++ b/src/tint/utils/diagnostic/source.h
@@ -89,10 +89,10 @@
class Location {
public:
/// the 1-based line number. 0 represents no line information.
- size_t line = 0;
+ uint32_t line = 0;
/// the 1-based column number in utf8-code units (bytes).
/// 0 represents no column information.
- size_t column = 0;
+ uint32_t column = 0;
/// Returns true if `this` location is lexicographically less than `rhs`
/// @param rhs location to compare against
@@ -132,7 +132,7 @@
/// Return a column-shifted Range
/// @param n the number of characters to shift by
/// @returns a Range with a #begin and #end column shifted by `n`
- inline Range operator+(size_t n) const {
+ inline Range operator+(uint32_t n) const {
return Range{{begin.line, begin.column + n}, {end.line, end.column + n}};
}
@@ -179,7 +179,7 @@
/// Return a column-shifted Source
/// @param n the number of characters to shift by
/// @returns a Source with the range's columns shifted by `n`
- inline Source operator+(size_t n) const { return Source(range + n, file); }
+ inline Source operator+(uint32_t n) const { return Source(range + n, file); }
/// Returns true of `this` Source is lexicographically less than `rhs`
/// @param rhs source to compare against