[Tint] Validate subgroup builtins as input only
Validate that subgroup_size and subgroup_invocation_id are input only.
Bug: 352540632
Change-Id: Iaeab5781f9022cf085177664711ab0a2a93fd5ac
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/198574
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Commit-Queue: Natalie Chouinard <chouinard@google.com>
diff --git a/src/tint/lang/wgsl/resolver/subgroups_extension_test.cc b/src/tint/lang/wgsl/resolver/subgroups_extension_test.cc
index 5e6a8b1..c93edfc 100644
--- a/src/tint/lang/wgsl/resolver/subgroups_extension_test.cc
+++ b/src/tint/lang/wgsl/resolver/subgroups_extension_test.cc
@@ -30,6 +30,7 @@
#include "gmock/gmock.h"
+using namespace tint::core::fluent_types; // NOLINT
using namespace tint::core::number_suffixes; // NOLINT
namespace tint::resolver {
@@ -165,6 +166,47 @@
"error: '@builtin(subgroup_size)' is only valid as a compute shader input");
}
+TEST_F(ResolverSubgroupsExtensionTest, SubgroupSizeComputeShaderOutput) {
+ Enable(wgsl::Extension::kSubgroups);
+
+ Func("main", tint::Empty, ty.u32(),
+ Vector{
+ Return(Call<u32>()),
+ },
+ Vector{
+ Stage(ast::PipelineStage::kCompute),
+ WorkgroupSize(1_i),
+ },
+ Vector{Builtin(Source{{1, 2}}, core::BuiltinValue::kSubgroupSize)});
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(),
+ "1:2 error: '@builtin(subgroup_size)' is only valid as a compute shader input");
+}
+
+TEST_F(ResolverSubgroupsExtensionTest, SubgroupSizeComputeShaderStructOutput) {
+ Enable(wgsl::Extension::kSubgroups);
+
+ auto* s = Structure(
+ "Output", Vector{
+ Member("a", ty.u32(), Vector{Builtin(core::BuiltinValue::kSubgroupSize)}),
+ });
+
+ Func("main", tint::Empty, ty.Of(s),
+ Vector{
+ Return(Call(ty.Of(s), Call<u32>())),
+ },
+ Vector{
+ Stage(ast::PipelineStage::kCompute),
+ WorkgroupSize(1_i),
+ });
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(),
+ R"(error: '@builtin(subgroup_size)' is only valid as a compute shader input
+note: while analyzing entry point 'main')");
+}
+
// Using builtin(subgroup_invocation_id) for anything other than a compute shader input should fail.
TEST_F(ResolverSubgroupsExtensionTest, SubgroupInvocationIdFragmentShader) {
Enable(wgsl::Extension::kSubgroups);
@@ -177,5 +219,24 @@
"error: '@builtin(subgroup_invocation_id)' is only valid as a compute shader input");
}
+TEST_F(ResolverSubgroupsExtensionTest, SubgroupInvocationIdComputeShaderOutput) {
+ Enable(wgsl::Extension::kSubgroups);
+
+ Func("main", tint::Empty, ty.u32(),
+ Vector{
+ Return(Call<u32>()),
+ },
+ Vector{
+ Stage(ast::PipelineStage::kCompute),
+ WorkgroupSize(1_i),
+ },
+ Vector{Builtin(Source{{1, 2}}, core::BuiltinValue::kSubgroupInvocationId)});
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(
+ r()->error(),
+ "1:2 error: '@builtin(subgroup_invocation_id)' is only valid as a compute shader input");
+}
+
} // namespace
} // namespace tint::resolver
diff --git a/src/tint/lang/wgsl/resolver/validator.cc b/src/tint/lang/wgsl/resolver/validator.cc
index 964ebea..32d158d 100644
--- a/src/tint/lang/wgsl/resolver/validator.cc
+++ b/src/tint/lang/wgsl/resolver/validator.cc
@@ -1109,7 +1109,8 @@
err_builtin_type("u32");
return false;
}
- if (stage != ast::PipelineStage::kNone && stage != ast::PipelineStage::kCompute) {
+ if (stage != ast::PipelineStage::kNone &&
+ !(stage == ast::PipelineStage::kCompute && is_input)) {
AddError(attr->source)
<< style::Attribute("@builtin") << style::Code("(", style::Enum(builtin), ")")
<< " is only valid as a compute shader input";