[tint] Early evaluation errors for subgroup and quad broadcast
Bug: 380862306
Change-Id: I41e1a6bd8afd7d41313b79f143824f604268670c
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/216956
Commit-Queue: Peter McNeeley <petermcneeley@google.com>
Reviewed-by: dan sinclair <dsinclair@chromium.org>
diff --git a/src/tint/lang/wgsl/resolver/builtin_validation_test.cc b/src/tint/lang/wgsl/resolver/builtin_validation_test.cc
index 7c6e138..ade78ee 100644
--- a/src/tint/lang/wgsl/resolver/builtin_validation_test.cc
+++ b/src/tint/lang/wgsl/resolver/builtin_validation_test.cc
@@ -1084,6 +1084,30 @@
R"(12:34 error: the sourceLaneIndex argument of subgroupBroadcast must be greater than or equal to zero)");
}
+TEST_F(ResolverBuiltinValidationTest, SubgroupBroadcastLaneArgMustLessThan128Signed) {
+ Enable(wgsl::Extension::kSubgroups);
+ Func("func", tint::Empty, ty.u32(),
+ Vector{
+ Return(Call("subgroupBroadcast", 1_u, Expr(Source{{12, 34}}, 128_i))),
+ });
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(
+ r()->error(),
+ R"(12:34 error: the sourceLaneIndex argument of subgroupBroadcast must be less than 128)");
+}
+
+TEST_F(ResolverBuiltinValidationTest, SubgroupBroadcastLaneArgMustLessThan128) {
+ Enable(wgsl::Extension::kSubgroups);
+ Func("func", tint::Empty, ty.u32(),
+ Vector{
+ Return(Call("subgroupBroadcast", 1_u, Expr(Source{{12, 34}}, 128_u))),
+ });
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(
+ r()->error(),
+ R"(12:34 error: the sourceLaneIndex argument of subgroupBroadcast must be less than 128)");
+}
+
TEST_F(ResolverBuiltinValidationTest, QuadBroadcastIdArgMustBeNonNeg) {
Enable(wgsl::Extension::kSubgroups);
Func("func", tint::Empty, ty.u32(),
@@ -1096,6 +1120,38 @@
R"(12:34 error: the id argument of quadBroadcast must be greater than or equal to zero)");
}
+TEST_F(ResolverBuiltinValidationTest, QuadBroadcastIdArgMustBeNonNeg4) {
+ Enable(wgsl::Extension::kSubgroups);
+ Func("func", tint::Empty, ty.u32(),
+ Vector{
+ Return(Call("quadBroadcast", 1_u, Expr(Source{{12, 34}}, -4_i))),
+ });
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(
+ r()->error(),
+ R"(12:34 error: the id argument of quadBroadcast must be greater than or equal to zero)");
+}
+
+TEST_F(ResolverBuiltinValidationTest, QuadBroadcastIdArgMustLessThan4Signed) {
+ Enable(wgsl::Extension::kSubgroups);
+ Func("func", tint::Empty, ty.u32(),
+ Vector{
+ Return(Call("quadBroadcast", 1_u, Expr(Source{{12, 34}}, 4_i))),
+ });
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(), R"(12:34 error: the id argument of quadBroadcast must be less than 4)");
+}
+
+TEST_F(ResolverBuiltinValidationTest, QuadBroadcastIdArgMustLessThan4) {
+ Enable(wgsl::Extension::kSubgroups);
+ Func("func", tint::Empty, ty.u32(),
+ Vector{
+ Return(Call("quadBroadcast", 1_u, Expr(Source{{12, 34}}, 4_u))),
+ });
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(), R"(12:34 error: the id argument of quadBroadcast must be less than 4)");
+}
+
TEST_F(ResolverBuiltinValidationTest, TextureBarrier) {
// fn func { textureBarrier(); }
Func("func", tint::Empty, ty.void_(),
diff --git a/src/tint/lang/wgsl/resolver/validator.cc b/src/tint/lang/wgsl/resolver/validator.cc
index f7031e5..8cf0c3d 100644
--- a/src/tint/lang/wgsl/resolver/validator.cc
+++ b/src/tint/lang/wgsl/resolver/validator.cc
@@ -1974,9 +1974,27 @@
return false;
}
- if (id->Type()->IsSignedIntegerScalar() && constant_value->ValueAs<i32>() < 0) {
+ if (id->Type()->IsSignedIntegerScalar()) {
+ if (constant_value->ValueAs<i32>() < 0) {
+ AddError(id->Declaration()->source)
+ << "the sourceLaneIndex argument of subgroupBroadcast "
+ "must be greater than or equal to zero";
+ return false;
+ }
+ if (constant_value->ValueAs<i32>() >= tint::internal_limits::kMaxSubgroupSize) {
+ AddError(id->Declaration()->source)
+ << "the sourceLaneIndex argument of subgroupBroadcast "
+ "must be less than "
+ << tint::internal_limits::kMaxSubgroupSize;
+ return false;
+ }
+ }
+
+ if (id->Type()->IsUnsignedIntegerScalar() &&
+ constant_value->ValueAs<u32>() >= tint::internal_limits::kMaxSubgroupSize) {
AddError(id->Declaration()->source) << "the sourceLaneIndex argument of subgroupBroadcast "
- "must be greater than or equal to zero";
+ "must be less than "
+ << tint::internal_limits::kMaxSubgroupSize;
return false;
}
@@ -1999,9 +2017,24 @@
return false;
}
- if (id->Type()->IsSignedIntegerScalar() && constant_value->ValueAs<i32>() < 0) {
- AddError(id->Declaration()->source)
- << "the id argument of quadBroadcast must be greater than or equal to zero";
+ if (id->Type()->IsSignedIntegerScalar()) {
+ if (constant_value->ValueAs<i32>() < 0) {
+ AddError(id->Declaration()->source)
+ << "the id argument of quadBroadcast must be greater than or equal to zero";
+ return false;
+ }
+ if (constant_value->ValueAs<i32>() >= tint::internal_limits::kQuadSize) {
+ AddError(id->Declaration()->source)
+ << "the id argument of quadBroadcast must be less than "
+ << tint::internal_limits::kQuadSize;
+ return false;
+ }
+ }
+
+ if (id->Type()->IsUnsignedIntegerScalar() &&
+ constant_value->ValueAs<u32>() >= tint::internal_limits::kQuadSize) {
+ AddError(id->Declaration()->source) << "the id argument of quadBroadcast must be less than "
+ << tint::internal_limits::kQuadSize;
return false;
}
diff --git a/src/tint/utils/internal_limits.h b/src/tint/utils/internal_limits.h
index 59f2e1a..a405e71 100644
--- a/src/tint/utils/internal_limits.h
+++ b/src/tint/utils/internal_limits.h
@@ -44,6 +44,12 @@
// Limits the number of elements in an array type
constexpr int64_t kMaxArrayElementCount = 65536;
+// The max subgroup size supported. Used in validation.
+constexpr int64_t kMaxSubgroupSize = 128;
+
+// A quad (fragment) is composed of four invocations.
+constexpr int64_t kQuadSize = 4;
+
} // namespace tint::internal_limits
#endif // SRC_TINT_UTILS_INTERNAL_LIMITS_H_