tint: Resolve @interpolate() args as expressions
This CL makes the builtin argument resolve as a shadowable enumerator
expression.
Bug: tint:1841
Bug: tint:1845
Change-Id: I5000ea91771fabb460c80c164bc7708fbbb0288c
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/120722
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/tint/resolver/attribute_validation_test.cc b/src/tint/resolver/attribute_validation_test.cc
index 100c239..e0c47d0 100644
--- a/src/tint/resolver/attribute_validation_test.cc
+++ b/src/tint/resolver/attribute_validation_test.cc
@@ -1649,8 +1649,7 @@
Param("a", ty.vec4<f32>(),
utils::Vector{
Builtin(builtin::BuiltinValue::kPosition),
- Interpolate(Source{{12, 34}}, builtin::InterpolationType::kFlat,
- builtin::InterpolationSampling::kUndefined),
+ Interpolate(Source{{12, 34}}, builtin::InterpolationType::kFlat),
}),
},
ty.void_(), utils::Empty,
@@ -1673,8 +1672,7 @@
},
utils::Vector{
Builtin(builtin::BuiltinValue::kPosition),
- Interpolate(Source{{12, 34}}, builtin::InterpolationType::kFlat,
- builtin::InterpolationSampling::kUndefined),
+ Interpolate(Source{{12, 34}}, builtin::InterpolationType::kFlat),
});
EXPECT_FALSE(r()->Resolve());
@@ -1687,8 +1685,7 @@
"S",
utils::Vector{
Member("a", ty.f32(),
- utils::Vector{Interpolate(Source{{12, 34}}, builtin::InterpolationType::kFlat,
- builtin::InterpolationSampling::kUndefined)}),
+ utils::Vector{Interpolate(Source{{12, 34}}, builtin::InterpolationType::kFlat)}),
});
EXPECT_FALSE(r()->Resolve());
diff --git a/src/tint/resolver/dependency_graph.cc b/src/tint/resolver/dependency_graph.cc
index a764596..e913789 100644
--- a/src/tint/resolver/dependency_graph.cc
+++ b/src/tint/resolver/dependency_graph.cc
@@ -438,6 +438,11 @@
TraverseValueExpression(id->expr);
return true;
},
+ [&](const ast::InterpolateAttribute* interpolate) {
+ TraverseExpression(interpolate->type, "interpolation type", "references");
+ TraverseExpression(interpolate->sampling, "interpolation sampling", "references");
+ return true;
+ },
[&](const ast::LocationAttribute* loc) {
TraverseValueExpression(loc->expr);
return true;
@@ -505,6 +510,16 @@
graph_.resolved_identifiers.Add(from, ResolvedIdentifier(access));
return;
}
+ if (auto i_type = builtin::ParseInterpolationType(s);
+ i_type != builtin::InterpolationType::kUndefined) {
+ graph_.resolved_identifiers.Add(from, ResolvedIdentifier(i_type));
+ return;
+ }
+ if (auto i_smpl = builtin::ParseInterpolationSampling(s);
+ i_smpl != builtin::InterpolationSampling::kUndefined) {
+ graph_.resolved_identifiers.Add(from, ResolvedIdentifier(i_smpl));
+ return;
+ }
UnknownSymbol(to, from->source, use);
return;
@@ -884,6 +899,12 @@
if (auto addr = AddressSpace(); addr != builtin::AddressSpace::kUndefined) {
return "address space '" + utils::ToString(addr) + "'";
}
+ if (auto type = InterpolationType(); type != builtin::InterpolationType::kUndefined) {
+ return "interpolation type '" + utils::ToString(type) + "'";
+ }
+ if (auto smpl = InterpolationSampling(); smpl != builtin::InterpolationSampling::kUndefined) {
+ return "interpolation sampling '" + utils::ToString(smpl) + "'";
+ }
if (auto fmt = TexelFormat(); fmt != builtin::TexelFormat::kUndefined) {
return "texel format '" + utils::ToString(fmt) + "'";
}
diff --git a/src/tint/resolver/dependency_graph.h b/src/tint/resolver/dependency_graph.h
index 382514f..da25383 100644
--- a/src/tint/resolver/dependency_graph.h
+++ b/src/tint/resolver/dependency_graph.h
@@ -22,6 +22,8 @@
#include "src/tint/builtin/access.h"
#include "src/tint/builtin/builtin.h"
#include "src/tint/builtin/builtin_value.h"
+#include "src/tint/builtin/interpolation_sampling.h"
+#include "src/tint/builtin/interpolation_type.h"
#include "src/tint/builtin/texel_format.h"
#include "src/tint/diagnostic/diagnostic.h"
#include "src/tint/sem/builtin_type.h"
@@ -40,6 +42,8 @@
/// - builtin::AddressSpace
/// - builtin::Builtin
/// - builtin::BuiltinValue
+/// - builtin::InterpolationSampling
+/// - builtin::InterpolationType
/// - builtin::TexelFormat
class ResolvedIdentifier {
public:
@@ -106,6 +110,24 @@
return builtin::BuiltinValue::kUndefined;
}
+ /// @return the texel format if the ResolvedIdentifier holds type::InterpolationSampling,
+ /// otherwise type::InterpolationSampling::kUndefined
+ builtin::InterpolationSampling InterpolationSampling() const {
+ if (auto n = std::get_if<builtin::InterpolationSampling>(&value_)) {
+ return *n;
+ }
+ return builtin::InterpolationSampling::kUndefined;
+ }
+
+ /// @return the texel format if the ResolvedIdentifier holds type::InterpolationType,
+ /// otherwise type::InterpolationType::kUndefined
+ builtin::InterpolationType InterpolationType() const {
+ if (auto n = std::get_if<builtin::InterpolationType>(&value_)) {
+ return *n;
+ }
+ return builtin::InterpolationType::kUndefined;
+ }
+
/// @return the texel format if the ResolvedIdentifier holds type::TexelFormat, otherwise
/// type::TexelFormat::kUndefined
builtin::TexelFormat TexelFormat() const {
@@ -145,6 +167,8 @@
builtin::AddressSpace,
builtin::Builtin,
builtin::BuiltinValue,
+ builtin::InterpolationSampling,
+ builtin::InterpolationType,
builtin::TexelFormat>
value_;
};
diff --git a/src/tint/resolver/dependency_graph_test.cc b/src/tint/resolver/dependency_graph_test.cc
index d8ec08b..8c1f0bd 100644
--- a/src/tint/resolver/dependency_graph_test.cc
+++ b/src/tint/resolver/dependency_graph_test.cc
@@ -21,6 +21,7 @@
#include "src/tint/resolver/dependency_graph.h"
#include "src/tint/resolver/resolver_test_helper.h"
#include "src/tint/type/texture_dimension.h"
+#include "src/tint/utils/transform.h"
using namespace tint::number_suffixes; // NOLINT
@@ -139,6 +140,40 @@
WorkgroupSizeValue,
};
+static constexpr SymbolUseKind kAllUseKinds[] = {
+ SymbolUseKind::GlobalVarType,
+ SymbolUseKind::GlobalVarArrayElemType,
+ SymbolUseKind::GlobalVarArraySizeValue,
+ SymbolUseKind::GlobalVarVectorElemType,
+ SymbolUseKind::GlobalVarMatrixElemType,
+ SymbolUseKind::GlobalVarSampledTexElemType,
+ SymbolUseKind::GlobalVarMultisampledTexElemType,
+ SymbolUseKind::GlobalVarValue,
+ SymbolUseKind::GlobalConstType,
+ SymbolUseKind::GlobalConstArrayElemType,
+ SymbolUseKind::GlobalConstArraySizeValue,
+ SymbolUseKind::GlobalConstVectorElemType,
+ SymbolUseKind::GlobalConstMatrixElemType,
+ SymbolUseKind::GlobalConstValue,
+ SymbolUseKind::AliasType,
+ SymbolUseKind::StructMemberType,
+ SymbolUseKind::CallFunction,
+ SymbolUseKind::ParameterType,
+ SymbolUseKind::LocalVarType,
+ SymbolUseKind::LocalVarArrayElemType,
+ SymbolUseKind::LocalVarArraySizeValue,
+ SymbolUseKind::LocalVarVectorElemType,
+ SymbolUseKind::LocalVarMatrixElemType,
+ SymbolUseKind::LocalVarValue,
+ SymbolUseKind::LocalLetType,
+ SymbolUseKind::LocalLetValue,
+ SymbolUseKind::NestedLocalVarType,
+ SymbolUseKind::NestedLocalVarValue,
+ SymbolUseKind::NestedLocalLetType,
+ SymbolUseKind::NestedLocalLetValue,
+ SymbolUseKind::WorkgroupSizeValue,
+};
+
static constexpr SymbolUseKind kTypeUseKinds[] = {
SymbolUseKind::GlobalVarType,
SymbolUseKind::GlobalVarArrayElemType,
@@ -1178,51 +1213,6 @@
EXPECT_EQ(resolved->BuiltinFunction(), builtin) << resolved->String(Symbols(), Diagnostics());
}
-TEST_P(ResolverDependencyGraphResolveToBuiltinFunc, ShadowedByGlobalVar) {
- const auto use = std::get<0>(GetParam());
- const auto builtin = std::get<1>(GetParam());
- const auto symbol = Symbols().New(utils::ToString(builtin));
-
- SymbolTestHelper helper(this);
- auto* decl = helper.Add(SymbolDeclKind::GlobalVar, symbol);
- auto* ident = helper.Add(use, symbol);
- helper.Build();
-
- auto resolved = Build().resolved_identifiers.Get(ident);
- ASSERT_TRUE(resolved);
- EXPECT_EQ(resolved->Node(), decl) << resolved->String(Symbols(), Diagnostics());
-}
-
-TEST_P(ResolverDependencyGraphResolveToBuiltinFunc, ShadowedByStruct) {
- const auto use = std::get<0>(GetParam());
- const auto builtin = std::get<1>(GetParam());
- const auto symbol = Symbols().New(utils::ToString(builtin));
-
- SymbolTestHelper helper(this);
- auto* decl = helper.Add(SymbolDeclKind::Struct, symbol);
- auto* ident = helper.Add(use, symbol);
- helper.Build();
-
- auto resolved = Build().resolved_identifiers.Get(ident);
- ASSERT_TRUE(resolved);
- EXPECT_EQ(resolved->Node(), decl) << resolved->String(Symbols(), Diagnostics());
-}
-
-TEST_P(ResolverDependencyGraphResolveToBuiltinFunc, ShadowedByFunc) {
- const auto use = std::get<0>(GetParam());
- const auto builtin = std::get<1>(GetParam());
- const auto symbol = Symbols().New(utils::ToString(builtin));
-
- SymbolTestHelper helper(this);
- auto* decl = helper.Add(SymbolDeclKind::Function, symbol);
- auto* ident = helper.Add(use, symbol);
- helper.Build();
-
- auto resolved = Build().resolved_identifiers.Get(ident);
- ASSERT_TRUE(resolved);
- EXPECT_EQ(resolved->Node(), decl) << resolved->String(Symbols(), Diagnostics());
-}
-
INSTANTIATE_TEST_SUITE_P(Types,
ResolverDependencyGraphResolveToBuiltinFunc,
testing::Combine(testing::ValuesIn(kTypeUseKinds),
@@ -1263,56 +1253,6 @@
<< resolved->String(Symbols(), Diagnostics());
}
-TEST_P(ResolverDependencyGraphResolveToBuiltinType, ShadowedByGlobalVar) {
- const auto use = std::get<0>(GetParam());
- const std::string name = std::get<1>(GetParam());
- const auto symbol = Symbols().New(name);
-
- auto* decl =
- GlobalVar(symbol, name == "i32" ? ty.u32() : ty.i32(), builtin::AddressSpace::kPrivate);
-
- SymbolTestHelper helper(this);
- auto* ident = helper.Add(use, symbol);
- helper.Build();
-
- auto resolved = Build().resolved_identifiers.Get(ident);
- ASSERT_TRUE(resolved);
- EXPECT_EQ(resolved->Node(), decl) << resolved->String(Symbols(), Diagnostics());
-}
-
-TEST_P(ResolverDependencyGraphResolveToBuiltinType, ShadowedByStruct) {
- const auto use = std::get<0>(GetParam());
- const std::string name = std::get<1>(GetParam());
- const auto symbol = Symbols().New(name);
-
- auto* decl = Structure(symbol, utils::Vector{
- Member("m", name == "i32" ? ty.u32() : ty.i32()),
- });
-
- SymbolTestHelper helper(this);
- auto* ident = helper.Add(use, symbol);
- helper.Build();
-
- auto resolved = Build().resolved_identifiers.Get(ident);
- ASSERT_TRUE(resolved);
- EXPECT_EQ(resolved->Node(), decl) << resolved->String(Symbols(), Diagnostics());
-}
-
-TEST_P(ResolverDependencyGraphResolveToBuiltinType, ShadowedByFunc) {
- const auto use = std::get<0>(GetParam());
- const auto name = std::get<1>(GetParam());
- const auto symbol = Symbols().New(name);
-
- SymbolTestHelper helper(this);
- auto* decl = helper.Add(SymbolDeclKind::Function, symbol);
- auto* ident = helper.Add(use, symbol);
- helper.Build();
-
- auto resolved = Build().resolved_identifiers.Get(ident);
- ASSERT_TRUE(resolved);
- EXPECT_EQ(resolved->Node(), decl) << resolved->String(Symbols(), Diagnostics());
-}
-
INSTANTIATE_TEST_SUITE_P(Types,
ResolverDependencyGraphResolveToBuiltinType,
testing::Combine(testing::ValuesIn(kTypeUseKinds),
@@ -1353,51 +1293,6 @@
<< resolved->String(Symbols(), Diagnostics());
}
-TEST_P(ResolverDependencyGraphResolveToAccess, ShadowedByGlobalVar) {
- const auto use = std::get<0>(GetParam());
- const auto builtin = std::get<1>(GetParam());
- const auto symbol = Symbols().New(utils::ToString(builtin));
-
- SymbolTestHelper helper(this);
- auto* decl = helper.Add(SymbolDeclKind::GlobalVar, symbol);
- auto* ident = helper.Add(use, symbol);
- helper.Build();
-
- auto resolved = Build().resolved_identifiers.Get(ident);
- ASSERT_TRUE(resolved);
- EXPECT_EQ(resolved->Node(), decl) << resolved->String(Symbols(), Diagnostics());
-}
-
-TEST_P(ResolverDependencyGraphResolveToAccess, ShadowedByStruct) {
- const auto use = std::get<0>(GetParam());
- const auto builtin = std::get<1>(GetParam());
- const auto symbol = Symbols().New(utils::ToString(builtin));
-
- SymbolTestHelper helper(this);
- auto* decl = helper.Add(SymbolDeclKind::Struct, symbol);
- auto* ident = helper.Add(use, symbol);
- helper.Build();
-
- auto resolved = Build().resolved_identifiers.Get(ident);
- ASSERT_TRUE(resolved);
- EXPECT_EQ(resolved->Node(), decl) << resolved->String(Symbols(), Diagnostics());
-}
-
-TEST_P(ResolverDependencyGraphResolveToAccess, ShadowedByFunc) {
- const auto use = std::get<0>(GetParam());
- const auto builtin = std::get<1>(GetParam());
- const auto symbol = Symbols().New(utils::ToString(builtin));
-
- SymbolTestHelper helper(this);
- auto* decl = helper.Add(SymbolDeclKind::Function, symbol);
- auto* ident = helper.Add(use, symbol);
- helper.Build();
-
- auto resolved = Build().resolved_identifiers.Get(ident);
- ASSERT_TRUE(resolved);
- EXPECT_EQ(resolved->Node(), decl) << resolved->String(Symbols(), Diagnostics());
-}
-
INSTANTIATE_TEST_SUITE_P(Types,
ResolverDependencyGraphResolveToAccess,
testing::Combine(testing::ValuesIn(kTypeUseKinds),
@@ -1438,51 +1333,6 @@
<< resolved->String(Symbols(), Diagnostics());
}
-TEST_P(ResolverDependencyGraphResolveToAddressSpace, ShadowedByGlobalConst) {
- const auto use = std::get<0>(GetParam());
- const auto builtin = std::get<1>(GetParam());
- const auto symbol = Symbols().New(utils::ToString(builtin));
-
- SymbolTestHelper helper(this);
- auto* decl = helper.Add(SymbolDeclKind::GlobalConst, symbol);
- auto* ident = helper.Add(use, symbol);
- helper.Build();
-
- auto resolved = Build().resolved_identifiers.Get(ident);
- ASSERT_TRUE(resolved);
- EXPECT_EQ(resolved->Node(), decl) << resolved->String(Symbols(), Diagnostics());
-}
-
-TEST_P(ResolverDependencyGraphResolveToAddressSpace, ShadowedByStruct) {
- const auto use = std::get<0>(GetParam());
- const auto builtin = std::get<1>(GetParam());
- const auto symbol = Symbols().New(utils::ToString(builtin));
-
- SymbolTestHelper helper(this);
- auto* decl = helper.Add(SymbolDeclKind::Struct, symbol);
- auto* ident = helper.Add(use, symbol);
- helper.Build();
-
- auto resolved = Build().resolved_identifiers.Get(ident);
- ASSERT_TRUE(resolved);
- EXPECT_EQ(resolved->Node(), decl) << resolved->String(Symbols(), Diagnostics());
-}
-
-TEST_P(ResolverDependencyGraphResolveToAddressSpace, ShadowedByFunc) {
- const auto use = std::get<0>(GetParam());
- const auto builtin = std::get<1>(GetParam());
- const auto symbol = Symbols().New(utils::ToString(builtin));
-
- SymbolTestHelper helper(this);
- auto* decl = helper.Add(SymbolDeclKind::Function, symbol);
- auto* ident = helper.Add(use, symbol);
- helper.Build();
-
- auto resolved = Build().resolved_identifiers.Get(ident);
- ASSERT_TRUE(resolved);
- EXPECT_EQ(resolved->Node(), decl) << resolved->String(Symbols(), Diagnostics());
-}
-
INSTANTIATE_TEST_SUITE_P(Types,
ResolverDependencyGraphResolveToAddressSpace,
testing::Combine(testing::ValuesIn(kTypeUseKinds),
@@ -1523,51 +1373,6 @@
<< resolved->String(Symbols(), Diagnostics());
}
-TEST_P(ResolverDependencyGraphResolveToBuiltinValue, ShadowedByGlobalConst) {
- const auto use = std::get<0>(GetParam());
- const auto builtin = std::get<1>(GetParam());
- const auto symbol = Symbols().New(utils::ToString(builtin));
-
- SymbolTestHelper helper(this);
- auto* decl = helper.Add(SymbolDeclKind::GlobalConst, symbol);
- auto* ident = helper.Add(use, symbol);
- helper.Build();
-
- auto resolved = Build().resolved_identifiers.Get(ident);
- ASSERT_TRUE(resolved);
- EXPECT_EQ(resolved->Node(), decl) << resolved->String(Symbols(), Diagnostics());
-}
-
-TEST_P(ResolverDependencyGraphResolveToBuiltinValue, ShadowedByStruct) {
- const auto use = std::get<0>(GetParam());
- const auto builtin = std::get<1>(GetParam());
- const auto symbol = Symbols().New(utils::ToString(builtin));
-
- SymbolTestHelper helper(this);
- auto* decl = helper.Add(SymbolDeclKind::Struct, symbol);
- auto* ident = helper.Add(use, symbol);
- helper.Build();
-
- auto resolved = Build().resolved_identifiers.Get(ident);
- ASSERT_TRUE(resolved);
- EXPECT_EQ(resolved->Node(), decl) << resolved->String(Symbols(), Diagnostics());
-}
-
-TEST_P(ResolverDependencyGraphResolveToBuiltinValue, ShadowedByFunc) {
- const auto use = std::get<0>(GetParam());
- const auto builtin = std::get<1>(GetParam());
- const auto symbol = Symbols().New(utils::ToString(builtin));
-
- SymbolTestHelper helper(this);
- auto* decl = helper.Add(SymbolDeclKind::Function, symbol);
- auto* ident = helper.Add(use, symbol);
- helper.Build();
-
- auto resolved = Build().resolved_identifiers.Get(ident);
- ASSERT_TRUE(resolved);
- EXPECT_EQ(resolved->Node(), decl) << resolved->String(Symbols(), Diagnostics());
-}
-
INSTANTIATE_TEST_SUITE_P(Types,
ResolverDependencyGraphResolveToBuiltinValue,
testing::Combine(testing::ValuesIn(kTypeUseKinds),
@@ -1586,6 +1391,89 @@
} // namespace resolve_to_builtin_value
////////////////////////////////////////////////////////////////////////////////
+// Resolve to builtin::InterpolationSampling tests
+////////////////////////////////////////////////////////////////////////////////
+namespace resolve_to_interpolation_sampling {
+
+using ResolverDependencyGraphResolveToInterpolationSampling =
+ ResolverDependencyGraphTestWithParam<std::tuple<SymbolUseKind, const char*>>;
+
+TEST_P(ResolverDependencyGraphResolveToInterpolationSampling, Resolve) {
+ const auto use = std::get<0>(GetParam());
+ const auto name = std::get<1>(GetParam());
+ const auto symbol = Symbols().New(name);
+
+ SymbolTestHelper helper(this);
+ auto* ident = helper.Add(use, symbol);
+ helper.Build();
+
+ auto resolved = Build().resolved_identifiers.Get(ident);
+ ASSERT_TRUE(resolved);
+ EXPECT_EQ(resolved->InterpolationSampling(), builtin::ParseInterpolationSampling(name))
+ << resolved->String(Symbols(), Diagnostics());
+}
+
+INSTANTIATE_TEST_SUITE_P(Types,
+ ResolverDependencyGraphResolveToInterpolationSampling,
+ testing::Combine(testing::ValuesIn(kTypeUseKinds),
+ testing::ValuesIn(builtin::kInterpolationTypeStrings)));
+
+INSTANTIATE_TEST_SUITE_P(Values,
+ ResolverDependencyGraphResolveToInterpolationSampling,
+ testing::Combine(testing::ValuesIn(kValueUseKinds),
+ testing::ValuesIn(builtin::kInterpolationTypeStrings)));
+
+INSTANTIATE_TEST_SUITE_P(Functions,
+ ResolverDependencyGraphResolveToInterpolationSampling,
+ testing::Combine(testing::ValuesIn(kFuncUseKinds),
+ testing::ValuesIn(builtin::kInterpolationTypeStrings)));
+
+} // namespace resolve_to_interpolation_sampling
+
+////////////////////////////////////////////////////////////////////////////////
+// Resolve to builtin::InterpolationType tests
+////////////////////////////////////////////////////////////////////////////////
+namespace resolve_to_interpolation_sampling {
+
+using ResolverDependencyGraphResolveToInterpolationType =
+ ResolverDependencyGraphTestWithParam<std::tuple<SymbolUseKind, const char*>>;
+
+TEST_P(ResolverDependencyGraphResolveToInterpolationType, Resolve) {
+ const auto use = std::get<0>(GetParam());
+ const auto name = std::get<1>(GetParam());
+ const auto symbol = Symbols().New(name);
+
+ SymbolTestHelper helper(this);
+ auto* ident = helper.Add(use, symbol);
+ helper.Build();
+
+ auto resolved = Build().resolved_identifiers.Get(ident);
+ ASSERT_TRUE(resolved);
+ EXPECT_EQ(resolved->InterpolationType(), builtin::ParseInterpolationType(name))
+ << resolved->String(Symbols(), Diagnostics());
+}
+
+INSTANTIATE_TEST_SUITE_P(
+ Types,
+ ResolverDependencyGraphResolveToInterpolationType,
+ testing::Combine(testing::ValuesIn(kTypeUseKinds),
+ testing::ValuesIn(builtin::kInterpolationSamplingStrings)));
+
+INSTANTIATE_TEST_SUITE_P(
+ Values,
+ ResolverDependencyGraphResolveToInterpolationType,
+ testing::Combine(testing::ValuesIn(kValueUseKinds),
+ testing::ValuesIn(builtin::kInterpolationSamplingStrings)));
+
+INSTANTIATE_TEST_SUITE_P(
+ Functions,
+ ResolverDependencyGraphResolveToInterpolationType,
+ testing::Combine(testing::ValuesIn(kFuncUseKinds),
+ testing::ValuesIn(builtin::kInterpolationSamplingStrings)));
+
+} // namespace resolve_to_interpolation_sampling
+
+////////////////////////////////////////////////////////////////////////////////
// Resolve to builtin::TexelFormat tests
////////////////////////////////////////////////////////////////////////////////
namespace resolve_to_texel_format {
@@ -1608,51 +1496,6 @@
<< resolved->String(Symbols(), Diagnostics());
}
-TEST_P(ResolverDependencyGraphResolveToTexelFormat, ShadowedByGlobalVar) {
- const auto use = std::get<0>(GetParam());
- const auto builtin = std::get<1>(GetParam());
- const auto symbol = Symbols().New(utils::ToString(builtin));
-
- SymbolTestHelper helper(this);
- auto* decl = helper.Add(SymbolDeclKind::GlobalVar, symbol);
- auto* ident = helper.Add(use, symbol);
- helper.Build();
-
- auto resolved = Build().resolved_identifiers.Get(ident);
- ASSERT_TRUE(resolved);
- EXPECT_EQ(resolved->Node(), decl) << resolved->String(Symbols(), Diagnostics());
-}
-
-TEST_P(ResolverDependencyGraphResolveToTexelFormat, ShadowedByStruct) {
- const auto use = std::get<0>(GetParam());
- const auto builtin = std::get<1>(GetParam());
- const auto symbol = Symbols().New(utils::ToString(builtin));
-
- SymbolTestHelper helper(this);
- auto* decl = helper.Add(SymbolDeclKind::Struct, symbol);
- auto* ident = helper.Add(use, symbol);
- helper.Build();
-
- auto resolved = Build().resolved_identifiers.Get(ident);
- ASSERT_TRUE(resolved);
- EXPECT_EQ(resolved->Node(), decl) << resolved->String(Symbols(), Diagnostics());
-}
-
-TEST_P(ResolverDependencyGraphResolveToTexelFormat, ShadowedByFunc) {
- const auto use = std::get<0>(GetParam());
- const auto builtin = std::get<1>(GetParam());
- const auto symbol = Symbols().New(utils::ToString(builtin));
-
- SymbolTestHelper helper(this);
- auto* decl = helper.Add(SymbolDeclKind::Function, symbol);
- auto* ident = helper.Add(use, symbol);
- helper.Build();
-
- auto resolved = Build().resolved_identifiers.Get(ident);
- ASSERT_TRUE(resolved);
- EXPECT_EQ(resolved->Node(), decl) << resolved->String(Symbols(), Diagnostics());
-}
-
INSTANTIATE_TEST_SUITE_P(Types,
ResolverDependencyGraphResolveToTexelFormat,
testing::Combine(testing::ValuesIn(kTypeUseKinds),
@@ -1675,10 +1518,10 @@
////////////////////////////////////////////////////////////////////////////////
namespace shadowing {
-using ResolverDependencyGraphShadowTest =
+using ResolverDependencyGraphShadowScopeTest =
ResolverDependencyGraphTestWithParam<std::tuple<SymbolDeclKind, SymbolDeclKind>>;
-TEST_P(ResolverDependencyGraphShadowTest, Test) {
+TEST_P(ResolverDependencyGraphShadowScopeTest, Test) {
const Symbol symbol = Sym("SYMBOL");
const auto outer_kind = std::get<0>(GetParam());
const auto inner_kind = std::get<1>(GetParam());
@@ -1701,18 +1544,107 @@
}
INSTANTIATE_TEST_SUITE_P(LocalShadowGlobal,
- ResolverDependencyGraphShadowTest,
+ ResolverDependencyGraphShadowScopeTest,
testing::Combine(testing::ValuesIn(kGlobalDeclKinds),
testing::ValuesIn(kLocalDeclKinds)));
INSTANTIATE_TEST_SUITE_P(NestedLocalShadowLocal,
- ResolverDependencyGraphShadowTest,
+ ResolverDependencyGraphShadowScopeTest,
testing::Combine(testing::Values(SymbolDeclKind::Parameter,
SymbolDeclKind::LocalVar,
SymbolDeclKind::LocalLet),
testing::Values(SymbolDeclKind::NestedLocalVar,
SymbolDeclKind::NestedLocalLet)));
+using ResolverDependencyGraphShadowKindTest =
+ ResolverDependencyGraphTestWithParam<std::tuple<SymbolUseKind, const char*>>;
+
+TEST_P(ResolverDependencyGraphShadowKindTest, ShadowedByGlobalVar) {
+ const auto use = std::get<0>(GetParam());
+ const std::string_view name = std::get<1>(GetParam());
+ const auto symbol = Symbols().New(utils::ToString(name));
+
+ SymbolTestHelper helper(this);
+ auto* decl = GlobalVar(
+ symbol, //
+ name == "i32" ? ty.u32() : ty.i32(),
+ name == "private" ? builtin::AddressSpace::kWorkgroup : builtin::AddressSpace::kPrivate);
+ auto* ident = helper.Add(use, symbol);
+ helper.Build();
+
+ auto resolved = Build().resolved_identifiers.Get(ident);
+ ASSERT_TRUE(resolved);
+ EXPECT_EQ(resolved->Node(), decl) << resolved->String(Symbols(), Diagnostics());
+}
+
+TEST_P(ResolverDependencyGraphShadowKindTest, ShadowedByStruct) {
+ const auto use = std::get<0>(GetParam());
+ const std::string_view name = std::get<1>(GetParam());
+ const auto symbol = Symbols().New(utils::ToString(name));
+
+ SymbolTestHelper helper(this);
+ auto* decl = Structure(symbol, utils::Vector{
+ Member("m", name == "i32" ? ty.u32() : ty.i32()),
+ });
+ auto* ident = helper.Add(use, symbol);
+ helper.Build();
+
+ auto resolved = Build().resolved_identifiers.Get(ident);
+ ASSERT_TRUE(resolved);
+ EXPECT_EQ(resolved->Node(), decl) << resolved->String(Symbols(), Diagnostics());
+}
+
+TEST_P(ResolverDependencyGraphShadowKindTest, ShadowedByFunc) {
+ const auto use = std::get<0>(GetParam());
+ const auto name = std::get<1>(GetParam());
+ const auto symbol = Symbols().New(utils::ToString(name));
+
+ SymbolTestHelper helper(this);
+ auto* decl = helper.Add(SymbolDeclKind::Function, symbol);
+ auto* ident = helper.Add(use, symbol);
+ helper.Build();
+
+ auto resolved = Build().resolved_identifiers.Get(ident);
+ ASSERT_TRUE(resolved);
+ EXPECT_EQ(resolved->Node(), decl) << resolved->String(Symbols(), Diagnostics());
+}
+
+INSTANTIATE_TEST_SUITE_P(Access,
+ ResolverDependencyGraphShadowKindTest,
+ testing::Combine(testing::ValuesIn(kAllUseKinds),
+ testing::ValuesIn(builtin::kAccessStrings)));
+
+INSTANTIATE_TEST_SUITE_P(AddressSpace,
+ ResolverDependencyGraphShadowKindTest,
+ testing::Combine(testing::ValuesIn(kAllUseKinds),
+ testing::ValuesIn(builtin::kAddressSpaceStrings)));
+
+INSTANTIATE_TEST_SUITE_P(BuiltinType,
+ ResolverDependencyGraphShadowKindTest,
+ testing::Combine(testing::ValuesIn(kAllUseKinds),
+ testing::ValuesIn(builtin::kBuiltinStrings)));
+
+INSTANTIATE_TEST_SUITE_P(BuiltinFunction,
+ ResolverDependencyGraphShadowKindTest,
+ testing::Combine(testing::ValuesIn(kAllUseKinds),
+ testing::ValuesIn(builtin::kBuiltinStrings)));
+
+INSTANTIATE_TEST_SUITE_P(
+ InterpolationSampling,
+ ResolverDependencyGraphShadowKindTest,
+ testing::Combine(testing::ValuesIn(kAllUseKinds),
+ testing::ValuesIn(builtin::kInterpolationSamplingStrings)));
+
+INSTANTIATE_TEST_SUITE_P(InterpolationType,
+ ResolverDependencyGraphShadowKindTest,
+ testing::Combine(testing::ValuesIn(kAllUseKinds),
+ testing::ValuesIn(builtin::kInterpolationTypeStrings)));
+
+INSTANTIATE_TEST_SUITE_P(TexelFormat,
+ ResolverDependencyGraphShadowKindTest,
+ testing::Combine(testing::ValuesIn(kAllUseKinds),
+ testing::ValuesIn(builtin::kTexelFormatStrings)));
+
} // namespace shadowing
////////////////////////////////////////////////////////////////////////////////
@@ -1753,6 +1685,7 @@
std::string(__FILE__) + ":" + std::to_string(line) + ": " + kind});
return use;
};
+
#define V add_use(value_decl, Expr(value_sym), __LINE__, "V()")
#define T add_use(type_decl, ty(type_sym), __LINE__, "T()")
#define F add_use(func_decl, Ident(func_sym), __LINE__, "F()")
@@ -1772,6 +1705,8 @@
utils::Vector{
Location(V), // Parameter attributes
Builtin(V),
+ Interpolate(V),
+ Interpolate(V, V),
}),
},
T, // Return type
diff --git a/src/tint/resolver/expression_kind_test.cc b/src/tint/resolver/expression_kind_test.cc
index 8761055..01248b3 100644
--- a/src/tint/resolver/expression_kind_test.cc
+++ b/src/tint/resolver/expression_kind_test.cc
@@ -29,6 +29,8 @@
kBuiltinType,
kBuiltinValue,
kFunction,
+ kInterpolationSampling,
+ kInterpolationType,
kStruct,
kTexelFormat,
kTypeAlias,
@@ -49,6 +51,10 @@
return out << "Def::kBuiltinValue";
case Def::kFunction:
return out << "Def::kFunction";
+ case Def::kInterpolationSampling:
+ return out << "Def::kInterpolationSampling";
+ case Def::kInterpolationType:
+ return out << "Def::kInterpolationType";
case Def::kStruct:
return out << "Def::kStruct";
case Def::kTexelFormat:
@@ -69,6 +75,8 @@
kCallExpr,
kCallStmt,
kFunctionReturnType,
+ kInterpolationSampling,
+ kInterpolationType,
kMemberType,
kTexelFormat,
kValueExpression,
@@ -92,6 +100,10 @@
return out << "Use::kCallStmt";
case Use::kFunctionReturnType:
return out << "Use::kFunctionReturnType";
+ case Use::kInterpolationSampling:
+ return out << "Use::kInterpolationSampling";
+ case Use::kInterpolationType:
+ return out << "Use::kInterpolationType";
case Use::kMemberType:
return out << "Use::kMemberType";
case Use::kTexelFormat:
@@ -183,6 +195,28 @@
};
break;
}
+ case Def::kInterpolationSampling: {
+ sym = Sym("center");
+ check_expr = [](const sem::Expression* expr) {
+ ASSERT_NE(expr, nullptr);
+ auto* enum_expr =
+ expr->As<sem::BuiltinEnumExpression<builtin::InterpolationSampling>>();
+ ASSERT_NE(enum_expr, nullptr);
+ EXPECT_EQ(enum_expr->Value(), builtin::InterpolationSampling::kCenter);
+ };
+ break;
+ }
+ case Def::kInterpolationType: {
+ sym = Sym("linear");
+ check_expr = [](const sem::Expression* expr) {
+ ASSERT_NE(expr, nullptr);
+ auto* enum_expr =
+ expr->As<sem::BuiltinEnumExpression<builtin::InterpolationType>>();
+ ASSERT_NE(enum_expr, nullptr);
+ EXPECT_EQ(enum_expr->Value(), builtin::InterpolationType::kLinear);
+ };
+ break;
+ }
case Def::kStruct: {
auto* s = Structure(kDefSource, "STRUCT", utils::Vector{Member("m", ty.i32())});
sym = Sym("STRUCT");
@@ -256,6 +290,26 @@
case Use::kFunctionReturnType:
Func("f", utils::Empty, ty(expr), Return(Call(sym)));
break;
+ case Use::kInterpolationSampling: {
+ Func("f",
+ utils::Vector{Param("p", ty.vec4<f32>(),
+ utils::Vector{
+ Location(0_a),
+ Interpolate(builtin::InterpolationType::kLinear, expr),
+ })},
+ ty.void_(), utils::Empty, utils::Vector{Stage(ast::PipelineStage::kFragment)});
+ break;
+ }
+ case Use::kInterpolationType: {
+ Func("f",
+ utils::Vector{Param("p", ty.vec4<f32>(),
+ utils::Vector{
+ Location(0_a),
+ Interpolate(expr, builtin::InterpolationSampling::kCenter),
+ })},
+ ty.void_(), utils::Empty, utils::Vector{Stage(ast::PipelineStage::kFragment)});
+ break;
+ }
case Use::kMemberType:
Structure("s", utils::Vector{Member("m", ty(expr))});
break;
@@ -296,6 +350,10 @@
{Def::kAccess, Use::kCallExpr, R"(5:6 error: cannot use access 'write' as call target)"},
{Def::kAccess, Use::kCallStmt, R"(5:6 error: cannot use access 'write' as call target)"},
{Def::kAccess, Use::kFunctionReturnType, R"(5:6 error: cannot use access 'write' as type)"},
+ {Def::kAccess, Use::kInterpolationSampling,
+ R"(5:6 error: cannot use access 'write' as interpolation sampling)"},
+ {Def::kAccess, Use::kInterpolationType,
+ R"(5:6 error: cannot use access 'write' as interpolation type)"},
{Def::kAccess, Use::kMemberType, R"(5:6 error: cannot use access 'write' as type)"},
{Def::kAccess, Use::kTexelFormat,
R"(5:6 error: cannot use access 'write' as texel format)"},
@@ -316,6 +374,10 @@
R"(5:6 error: cannot use address space 'workgroup' as call target)"},
{Def::kAddressSpace, Use::kFunctionReturnType,
R"(5:6 error: cannot use address space 'workgroup' as type)"},
+ {Def::kAddressSpace, Use::kInterpolationSampling,
+ R"(5:6 error: cannot use address space 'workgroup' as interpolation sampling)"},
+ {Def::kAddressSpace, Use::kInterpolationType,
+ R"(5:6 error: cannot use address space 'workgroup' as interpolation type)"},
{Def::kAddressSpace, Use::kMemberType,
R"(5:6 error: cannot use address space 'workgroup' as type)"},
{Def::kAddressSpace, Use::kTexelFormat,
@@ -338,6 +400,10 @@
{Def::kBuiltinFunction, Use::kCallStmt, kPass},
{Def::kBuiltinFunction, Use::kFunctionReturnType,
R"(7:8 error: missing '(' for builtin function call)"},
+ {Def::kBuiltinFunction, Use::kInterpolationSampling,
+ R"(7:8 error: missing '(' for builtin function call)"},
+ {Def::kBuiltinFunction, Use::kInterpolationType,
+ R"(7:8 error: missing '(' for builtin function call)"},
{Def::kBuiltinFunction, Use::kMemberType,
R"(7:8 error: missing '(' for builtin function call)"},
{Def::kBuiltinFunction, Use::kTexelFormat,
@@ -359,6 +425,10 @@
R"(5:6 error: cannot use type 'vec4<f32>' as builtin value)"},
{Def::kBuiltinType, Use::kCallExpr, kPass},
{Def::kBuiltinType, Use::kFunctionReturnType, kPass},
+ {Def::kBuiltinType, Use::kInterpolationSampling,
+ R"(5:6 error: cannot use type 'vec4<f32>' as interpolation sampling)"},
+ {Def::kBuiltinType, Use::kInterpolationType,
+ R"(5:6 error: cannot use type 'vec4<f32>' as interpolation type)"},
{Def::kBuiltinType, Use::kMemberType, kPass},
{Def::kBuiltinType, Use::kTexelFormat,
R"(5:6 error: cannot use type 'vec4<f32>' as texel format)"},
@@ -383,6 +453,10 @@
R"(5:6 error: cannot use builtin value 'position' as call target)"},
{Def::kBuiltinValue, Use::kFunctionReturnType,
R"(5:6 error: cannot use builtin value 'position' as type)"},
+ {Def::kBuiltinValue, Use::kInterpolationSampling,
+ R"(5:6 error: cannot use builtin value 'position' as interpolation sampling)"},
+ {Def::kBuiltinValue, Use::kInterpolationType,
+ R"(5:6 error: cannot use builtin value 'position' as interpolation type)"},
{Def::kBuiltinValue, Use::kMemberType,
R"(5:6 error: cannot use builtin value 'position' as type)"},
{Def::kBuiltinValue, Use::kTexelFormat,
@@ -409,6 +483,12 @@
{Def::kFunction, Use::kFunctionReturnType,
R"(5:6 error: cannot use function 'FUNCTION' as type
1:2 note: function 'FUNCTION' declared here)"},
+ {Def::kFunction, Use::kInterpolationSampling,
+ R"(5:6 error: cannot use function 'FUNCTION' as interpolation sampling
+1:2 note: function 'FUNCTION' declared here)"},
+ {Def::kFunction, Use::kInterpolationType,
+ R"(5:6 error: cannot use function 'FUNCTION' as interpolation type
+1:2 note: function 'FUNCTION' declared here)"},
{Def::kFunction, Use::kMemberType,
R"(5:6 error: cannot use function 'FUNCTION' as type
1:2 note: function 'FUNCTION' declared here)"},
@@ -424,6 +504,62 @@
{Def::kFunction, Use::kUnaryOp, R"(5:6 error: cannot use function 'FUNCTION' as value
1:2 note: function 'FUNCTION' declared here)"},
+ {Def::kInterpolationSampling, Use::kAccess,
+ R"(5:6 error: cannot use interpolation sampling 'center' as access)"},
+ {Def::kInterpolationSampling, Use::kAddressSpace,
+ R"(5:6 error: cannot use interpolation sampling 'center' as address space)"},
+ {Def::kInterpolationSampling, Use::kBinaryOp,
+ R"(5:6 error: cannot use interpolation sampling 'center' as value)"},
+ {Def::kInterpolationSampling, Use::kBuiltinValue,
+ R"(5:6 error: cannot use interpolation sampling 'center' as builtin value)"},
+ {Def::kInterpolationSampling, Use::kCallStmt,
+ R"(5:6 error: cannot use interpolation sampling 'center' as call target)"},
+ {Def::kInterpolationSampling, Use::kCallExpr,
+ R"(5:6 error: cannot use interpolation sampling 'center' as call target)"},
+ {Def::kInterpolationSampling, Use::kFunctionReturnType,
+ R"(5:6 error: cannot use interpolation sampling 'center' as type)"},
+ {Def::kInterpolationSampling, Use::kInterpolationSampling, kPass},
+ {Def::kInterpolationSampling, Use::kInterpolationType,
+ R"(5:6 error: cannot use interpolation sampling 'center' as interpolation type)"},
+ {Def::kInterpolationSampling, Use::kMemberType,
+ R"(5:6 error: cannot use interpolation sampling 'center' as type)"},
+ {Def::kInterpolationSampling, Use::kTexelFormat,
+ R"(5:6 error: cannot use interpolation sampling 'center' as texel format)"},
+ {Def::kInterpolationSampling, Use::kValueExpression,
+ R"(5:6 error: cannot use interpolation sampling 'center' as value)"},
+ {Def::kInterpolationSampling, Use::kVariableType,
+ R"(5:6 error: cannot use interpolation sampling 'center' as type)"},
+ {Def::kInterpolationSampling, Use::kUnaryOp,
+ R"(5:6 error: cannot use interpolation sampling 'center' as value)"},
+
+ {Def::kInterpolationType, Use::kAccess,
+ R"(5:6 error: cannot use interpolation type 'linear' as access)"},
+ {Def::kInterpolationType, Use::kAddressSpace,
+ R"(5:6 error: cannot use interpolation type 'linear' as address space)"},
+ {Def::kInterpolationType, Use::kBinaryOp,
+ R"(5:6 error: cannot use interpolation type 'linear' as value)"},
+ {Def::kInterpolationType, Use::kBuiltinValue,
+ R"(5:6 error: cannot use interpolation type 'linear' as builtin value)"},
+ {Def::kInterpolationType, Use::kCallStmt,
+ R"(5:6 error: cannot use interpolation type 'linear' as call target)"},
+ {Def::kInterpolationType, Use::kCallExpr,
+ R"(5:6 error: cannot use interpolation type 'linear' as call target)"},
+ {Def::kInterpolationType, Use::kFunctionReturnType,
+ R"(5:6 error: cannot use interpolation type 'linear' as type)"},
+ {Def::kInterpolationType, Use::kInterpolationSampling,
+ R"(5:6 error: cannot use interpolation type 'linear' as interpolation sampling)"},
+ {Def::kInterpolationType, Use::kInterpolationType, kPass},
+ {Def::kInterpolationType, Use::kMemberType,
+ R"(5:6 error: cannot use interpolation type 'linear' as type)"},
+ {Def::kInterpolationType, Use::kTexelFormat,
+ R"(5:6 error: cannot use interpolation type 'linear' as texel format)"},
+ {Def::kInterpolationType, Use::kValueExpression,
+ R"(5:6 error: cannot use interpolation type 'linear' as value)"},
+ {Def::kInterpolationType, Use::kVariableType,
+ R"(5:6 error: cannot use interpolation type 'linear' as type)"},
+ {Def::kInterpolationType, Use::kUnaryOp,
+ R"(5:6 error: cannot use interpolation type 'linear' as value)"},
+
{Def::kStruct, Use::kAccess, R"(5:6 error: cannot use type 'STRUCT' as access)"},
{Def::kStruct, Use::kAddressSpace,
R"(5:6 error: cannot use type 'STRUCT' as address space)"},
@@ -433,6 +569,10 @@
{Def::kStruct, Use::kBuiltinValue,
R"(5:6 error: cannot use type 'STRUCT' as builtin value)"},
{Def::kStruct, Use::kFunctionReturnType, kPass},
+ {Def::kStruct, Use::kInterpolationSampling,
+ R"(5:6 error: cannot use type 'STRUCT' as interpolation sampling)"},
+ {Def::kStruct, Use::kInterpolationType,
+ R"(5:6 error: cannot use type 'STRUCT' as interpolation type)"},
{Def::kStruct, Use::kMemberType, kPass},
{Def::kStruct, Use::kTexelFormat, R"(5:6 error: cannot use type 'STRUCT' as texel format)"},
{Def::kStruct, Use::kValueExpression,
@@ -459,6 +599,10 @@
R"(5:6 error: cannot use texel format 'rgba8unorm' as call target)"},
{Def::kTexelFormat, Use::kFunctionReturnType,
R"(5:6 error: cannot use texel format 'rgba8unorm' as type)"},
+ {Def::kTexelFormat, Use::kInterpolationSampling,
+ R"(5:6 error: cannot use texel format 'rgba8unorm' as interpolation sampling)"},
+ {Def::kTexelFormat, Use::kInterpolationType,
+ R"(5:6 error: cannot use texel format 'rgba8unorm' as interpolation type)"},
{Def::kTexelFormat, Use::kMemberType,
R"(5:6 error: cannot use texel format 'rgba8unorm' as type)"},
{Def::kTexelFormat, Use::kTexelFormat, kPass},
@@ -479,6 +623,10 @@
R"(5:6 error: cannot use type 'i32' as builtin value)"},
{Def::kTypeAlias, Use::kCallExpr, kPass},
{Def::kTypeAlias, Use::kFunctionReturnType, kPass},
+ {Def::kTypeAlias, Use::kInterpolationSampling,
+ R"(5:6 error: cannot use type 'i32' as interpolation sampling)"},
+ {Def::kTypeAlias, Use::kInterpolationType,
+ R"(5:6 error: cannot use type 'i32' as interpolation type)"},
{Def::kTypeAlias, Use::kMemberType, kPass},
{Def::kTypeAlias, Use::kTexelFormat, R"(5:6 error: cannot use type 'i32' as texel format)"},
{Def::kTypeAlias, Use::kValueExpression,
@@ -507,6 +655,12 @@
{Def::kVariable, Use::kFunctionReturnType,
R"(5:6 error: cannot use const 'VARIABLE' as type
1:2 note: const 'VARIABLE' declared here)"},
+ {Def::kVariable, Use::kInterpolationSampling,
+ R"(5:6 error: cannot use const 'VARIABLE' as interpolation sampling
+1:2 note: const 'VARIABLE' declared here)"},
+ {Def::kVariable, Use::kInterpolationType,
+ R"(5:6 error: cannot use const 'VARIABLE' as interpolation type
+1:2 note: const 'VARIABLE' declared here)"},
{Def::kVariable, Use::kMemberType,
R"(5:6 error: cannot use const 'VARIABLE' as type
1:2 note: const 'VARIABLE' declared here)"},
diff --git a/src/tint/resolver/resolver.cc b/src/tint/resolver/resolver.cc
index 3d0b539..ca5c46f 100644
--- a/src/tint/resolver/resolver.cc
+++ b/src/tint/resolver/resolver.cc
@@ -90,6 +90,8 @@
TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression<tint::builtin::Access>);
TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression<tint::builtin::AddressSpace>);
TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression<tint::builtin::BuiltinValue>);
+TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression<tint::builtin::InterpolationSampling>);
+TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression<tint::builtin::InterpolationType>);
TINT_INSTANTIATE_TYPEINFO(tint::sem::BuiltinEnumExpression<tint::builtin::TexelFormat>);
namespace tint::resolver {
@@ -1521,6 +1523,16 @@
return sem_.AsAccess(Expression(expr));
}
+sem::BuiltinEnumExpression<builtin::InterpolationSampling>* Resolver::InterpolationSampling(
+ const ast::Expression* expr) {
+ return sem_.AsInterpolationSampling(Expression(expr));
+}
+
+sem::BuiltinEnumExpression<builtin::InterpolationType>* Resolver::InterpolationType(
+ const ast::Expression* expr) {
+ return sem_.AsInterpolationType(Expression(expr));
+}
+
void Resolver::RegisterStore(const sem::ValueExpression* expr) {
auto& info = alias_analysis_infos_[current_function_];
Switch(
@@ -3001,6 +3013,18 @@
expr, current_statement_, builtin);
}
+ if (auto i_smpl = resolved->InterpolationSampling();
+ i_smpl != builtin::InterpolationSampling::kUndefined) {
+ return builder_->create<sem::BuiltinEnumExpression<builtin::InterpolationSampling>>(
+ expr, current_statement_, i_smpl);
+ }
+
+ if (auto i_type = resolved->InterpolationType();
+ i_type != builtin::InterpolationType::kUndefined) {
+ return builder_->create<sem::BuiltinEnumExpression<builtin::InterpolationType>>(
+ expr, current_statement_, i_type);
+ }
+
if (auto fmt = resolved->TexelFormat(); fmt != builtin::TexelFormat::kUndefined) {
return builder_->create<sem::BuiltinEnumExpression<builtin::TexelFormat>>(
expr, current_statement_, fmt);
@@ -3326,7 +3350,8 @@
return Switch(
attr, //
[&](const ast::BuiltinAttribute* b) { return BuiltinAttribute(b); },
- [&](const ast::DiagnosticAttribute* dc) { return DiagnosticControl(dc->control); },
+ [&](const ast::DiagnosticAttribute* d) { return DiagnosticControl(d->control); },
+ [&](const ast::InterpolateAttribute* i) { return InterpolateAttribute(i); },
[&](Default) { return true; });
}
@@ -3341,6 +3366,16 @@
return true;
}
+bool Resolver::InterpolateAttribute(const ast::InterpolateAttribute* attr) {
+ if (!InterpolationType(attr->type)) {
+ return false;
+ }
+ if (attr->sampling && !InterpolationSampling(attr->sampling)) {
+ return false;
+ }
+ return true;
+}
+
bool Resolver::DiagnosticControl(const ast::DiagnosticControl& control) {
Mark(control.rule_name);
diff --git a/src/tint/resolver/resolver.h b/src/tint/resolver/resolver.h
index 2a04a2a..bbde9e9 100644
--- a/src/tint/resolver/resolver.h
+++ b/src/tint/resolver/resolver.h
@@ -163,6 +163,20 @@
/// diagnostic is raised and nullptr is returned.
sem::BuiltinEnumExpression<builtin::Access>* AccessExpression(const ast::Expression* expr);
+ /// @returns the call of Expression() cast to a
+ /// sem::BuiltinEnumExpression<builtin::InterpolationSampling>*. If the sem::Expression is not a
+ /// sem::BuiltinEnumExpression<builtin::InterpolationSampling>*, then an error diagnostic is
+ /// raised and nullptr is returned.
+ sem::BuiltinEnumExpression<builtin::InterpolationSampling>* InterpolationSampling(
+ const ast::Expression* expr);
+
+ /// @returns the call of Expression() cast to a
+ /// sem::BuiltinEnumExpression<builtin::InterpolationType>*. If the sem::Expression is not a
+ /// sem::BuiltinEnumExpression<builtin::InterpolationType>*, then an error diagnostic is raised
+ /// and nullptr is returned.
+ sem::BuiltinEnumExpression<builtin::InterpolationType>* InterpolationType(
+ const ast::Expression* expr);
+
/// Expression traverses the graph of expressions starting at `expr`, building a post-ordered
/// list (leaf-first) of all the expression nodes. Each of the expressions are then resolved by
/// dispatching to the appropriate expression handlers below.
@@ -304,6 +318,10 @@
/// @returns true on success, false on failure
bool BuiltinAttribute(const ast::BuiltinAttribute* attr);
+ /// Resolves the `@interpolate` attribute @p attr
+ /// @returns true on success, false on failure
+ bool InterpolateAttribute(const ast::InterpolateAttribute* attr);
+
/// @param control the diagnostic control
/// @returns true on success, false on failure
bool DiagnosticControl(const ast::DiagnosticControl& control);
diff --git a/src/tint/resolver/sem_helper.cc b/src/tint/resolver/sem_helper.cc
index b8c328c..0a9bc1b 100644
--- a/src/tint/resolver/sem_helper.cc
+++ b/src/tint/resolver/sem_helper.cc
@@ -89,6 +89,16 @@
std::string(wanted),
builtin->Declaration()->source);
},
+ [&](const sem::BuiltinEnumExpression<builtin::InterpolationSampling>* fmt) {
+ AddError("cannot use interpolation sampling '" + utils::ToString(fmt->Value()) +
+ "' as " + std::string(wanted),
+ fmt->Declaration()->source);
+ },
+ [&](const sem::BuiltinEnumExpression<builtin::InterpolationType>* fmt) {
+ AddError("cannot use interpolation type '" + utils::ToString(fmt->Value()) + "' as " +
+ std::string(wanted),
+ fmt->Declaration()->source);
+ },
[&](const sem::BuiltinEnumExpression<builtin::TexelFormat>* fmt) {
AddError("cannot use texel format '" + utils::ToString(fmt->Value()) + "' as " +
std::string(wanted),
diff --git a/src/tint/resolver/sem_helper.h b/src/tint/resolver/sem_helper.h
index a7c37b1..2ba8502 100644
--- a/src/tint/resolver/sem_helper.h
+++ b/src/tint/resolver/sem_helper.h
@@ -18,6 +18,8 @@
#include <string>
#include "src/tint/builtin/builtin_value.h"
+#include "src/tint/builtin/interpolation_sampling.h"
+#include "src/tint/builtin/interpolation_type.h"
#include "src/tint/diagnostic/diagnostic.h"
#include "src/tint/program_builder.h"
#include "src/tint/resolver/dependency_graph.h"
@@ -164,6 +166,39 @@
return nullptr;
}
+ /// @param expr the semantic node
+ /// @returns nullptr if @p expr is nullptr, or @p expr cast to
+ /// sem::BuiltinEnumExpression<builtin::InterpolationSampling> if the cast is successful,
+ /// otherwise an error diagnostic is raised.
+ sem::BuiltinEnumExpression<builtin::InterpolationSampling>* AsInterpolationSampling(
+ sem::Expression* expr) const {
+ if (TINT_LIKELY(expr)) {
+ auto* enum_expr =
+ expr->As<sem::BuiltinEnumExpression<builtin::InterpolationSampling>>();
+ if (TINT_LIKELY(enum_expr)) {
+ return enum_expr;
+ }
+ ErrorUnexpectedExprKind(expr, "interpolation sampling");
+ }
+ return nullptr;
+ }
+
+ /// @param expr the semantic node
+ /// @returns nullptr if @p expr is nullptr, or @p expr cast to
+ /// sem::BuiltinEnumExpression<builtin::InterpolationType> if the cast is successful, otherwise
+ /// an error diagnostic is raised.
+ sem::BuiltinEnumExpression<builtin::InterpolationType>* AsInterpolationType(
+ sem::Expression* expr) const {
+ if (TINT_LIKELY(expr)) {
+ auto* enum_expr = expr->As<sem::BuiltinEnumExpression<builtin::InterpolationType>>();
+ if (TINT_LIKELY(enum_expr)) {
+ return enum_expr;
+ }
+ ErrorUnexpectedExprKind(expr, "interpolation type");
+ }
+ return nullptr;
+ }
+
/// @returns the resolved type of the ast::Expression @p expr
/// @param expr the expression
type::Type* TypeOf(const ast::Expression* expr) const;
diff --git a/src/tint/resolver/validator.cc b/src/tint/resolver/validator.cc
index 5e64d98..4db6c1a 100644
--- a/src/tint/resolver/validator.cc
+++ b/src/tint/resolver/validator.cc
@@ -985,14 +985,19 @@
const type::Type* storage_ty) const {
auto* type = storage_ty->UnwrapRef();
- if (type->is_integer_scalar_or_vector() && attr->type != builtin::InterpolationType::kFlat) {
+ auto i_type = sem_.AsInterpolationType(sem_.Get(attr->type));
+ if (TINT_UNLIKELY(!i_type)) {
+ return false;
+ }
+
+ if (type->is_integer_scalar_or_vector() &&
+ i_type->Value() != builtin::InterpolationType::kFlat) {
AddError("interpolation type must be 'flat' for integral user-defined IO types",
attr->source);
return false;
}
- if (attr->type == builtin::InterpolationType::kFlat &&
- attr->sampling != builtin::InterpolationSampling::kUndefined) {
+ if (attr->sampling && i_type->Value() == builtin::InterpolationType::kFlat) {
AddError("flat interpolation attribute must not have a sampling parameter", attr->source);
return false;
}