[tint] Check uniformity for subgroup matrix variable declarations
Add a new type of node to represent a subgroup matrix variable
declaration, and special-case the diagnostic generation code.
Fixed: 403611388
Change-Id: I380832dda61499abb23debdf39422638088ff079
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/235657
Commit-Queue: David Neto <dneto@google.com>
Reviewed-by: David Neto <dneto@google.com>
diff --git a/src/tint/lang/wgsl/resolver/uniformity.cc b/src/tint/lang/wgsl/resolver/uniformity.cc
index 2bb5cdc..6570272 100644
--- a/src/tint/lang/wgsl/resolver/uniformity.cc
+++ b/src/tint/lang/wgsl/resolver/uniformity.cc
@@ -131,6 +131,7 @@
kFunctionCallPointerArgumentResult,
kFunctionCallReturnValue,
kFunctionPointerParameterContents,
+ kSubgroupMatrixVariableDeclaration,
};
/// The type of the node.
@@ -1238,6 +1239,19 @@
}
} else {
node = cf;
+
+ // Subgroup matrix variables cannot be declared in non-uniform control flow.
+ if (ContainsSubgroupMatrix(sem_var->Type()->UnwrapRef())) {
+ auto severity = sem_.DiagnosticSeverity(
+ decl, wgsl::ChromiumDiagnosticRule::kSubgroupMatrixUniformity);
+ if (severity != wgsl::DiagnosticSeverity::kOff) {
+ // Create an extra node so that we can produce good diagnostics.
+ node = CreateNode({NameFor(sem_var), "_decl"}, decl);
+ node->type = Node::kSubgroupMatrixVariableDeclaration;
+ node->AddEdge(cf);
+ current_function_->RequiredToBeUniform(severity)->AddEdge(node);
+ }
+ }
}
current_function_->variables.Set(sem_var, node);
@@ -2101,6 +2115,19 @@
return node->visited_from == function.RequiredToBeUniform(severity);
});
+ // Special-case error for subgroup-matrix variable declarations, which are the only source
+ // of uniformity requirements that do not involve function calls.
+ if (cause->type == Node::kSubgroupMatrixVariableDeclaration) {
+ report(cause->ast->source,
+ "variables that contain subgroup matrix types cannot be declared in non-uniform "
+ "control flow",
+ /* note */ false);
+
+ // Show the point at which control-flow depends on a non-uniform value.
+ ShowControlFlowDivergence(function, cause, source_node);
+ return;
+ }
+
// The node will always have a corresponding call expression.
auto* call = cause->ast->As<ast::CallExpression>();
TINT_ASSERT(call);
diff --git a/src/tint/lang/wgsl/resolver/uniformity_test.cc b/src/tint/lang/wgsl/resolver/uniformity_test.cc
index 500dfda..0ffa2a6 100644
--- a/src/tint/lang/wgsl/resolver/uniformity_test.cc
+++ b/src/tint/lang/wgsl/resolver/uniformity_test.cc
@@ -907,6 +907,128 @@
}
////////////////////////////////////////////////////////////////////////////////
+/// Test subgroup matrix variable declarations.
+////////////////////////////////////////////////////////////////////////////////
+
+TEST_F(UniformityAnalysisTest, SubgroupMatrixVarDecl_Pass) {
+ std::string src = R"(
+enable chromium_experimental_subgroup_matrix;
+
+@group(0) @binding(0) var<storage, read> ro : i32;
+
+fn foo() {
+ if (ro == 0) {
+ var sm : subgroup_matrix_result<f32, 8, 8>;
+ }
+}
+)";
+
+ RunTest(src, true);
+}
+
+TEST_F(UniformityAnalysisTest, SubgroupMatrixVarDecl_Fail) {
+ std::string src = R"(
+enable chromium_experimental_subgroup_matrix;
+
+@group(0) @binding(0) var<storage, read_write> rw : i32;
+
+fn foo() {
+ if (rw == 0) {
+ var sm : subgroup_matrix_result<f32, 8, 8>;
+ }
+}
+)";
+
+ RunTest(src, false);
+ EXPECT_EQ(
+ error_,
+ R"(test:8:5 error: variables that contain subgroup matrix types cannot be declared in non-uniform control flow
+ var sm : subgroup_matrix_result<f32, 8, 8>;
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+test:7:3 note: control flow depends on possibly non-uniform value
+ if (rw == 0) {
+ ^^
+
+test:7:7 note: reading from read_write storage buffer 'rw' may result in a non-uniform value
+ if (rw == 0) {
+ ^^
+)");
+}
+
+TEST_F(UniformityAnalysisTest, SubgroupMatrixVarDecl_InStruct_Fail) {
+ std::string src = R"(
+enable chromium_experimental_subgroup_matrix;
+
+struct Inner {
+ u : u32,
+ sm : subgroup_matrix_result<f32, 8, 8>,
+}
+
+struct S {
+ u : u32,
+ inner : Inner,
+}
+
+@group(0) @binding(0) var<storage, read_write> rw : i32;
+
+fn foo() {
+ if (rw == 0) {
+ var sm : S;
+ }
+}
+)";
+
+ RunTest(src, false);
+ EXPECT_EQ(
+ error_,
+ R"(test:18:5 error: variables that contain subgroup matrix types cannot be declared in non-uniform control flow
+ var sm : S;
+ ^^^^^^^^^^
+
+test:17:3 note: control flow depends on possibly non-uniform value
+ if (rw == 0) {
+ ^^
+
+test:17:7 note: reading from read_write storage buffer 'rw' may result in a non-uniform value
+ if (rw == 0) {
+ ^^
+)");
+}
+
+TEST_F(UniformityAnalysisTest, SubgroupMatrixVarDecl_InArray_Fail) {
+ std::string src = R"(
+enable chromium_experimental_subgroup_matrix;
+
+alias ArrayType = array<array<subgroup_matrix_result<f32, 8, 8>, 4>, 4>;
+
+@group(0) @binding(0) var<storage, read_write> rw : i32;
+
+fn foo() {
+ if (rw == 0) {
+ var sm : ArrayType;
+ }
+}
+)";
+
+ RunTest(src, false);
+ EXPECT_EQ(
+ error_,
+ R"(test:10:5 error: variables that contain subgroup matrix types cannot be declared in non-uniform control flow
+ var sm : ArrayType;
+ ^^^^^^^^^^^^^^^^^^
+
+test:9:3 note: control flow depends on possibly non-uniform value
+ if (rw == 0) {
+ ^^
+
+test:9:7 note: reading from read_write storage buffer 'rw' may result in a non-uniform value
+ if (rw == 0) {
+ ^^
+)");
+}
+
+////////////////////////////////////////////////////////////////////////////////
/// Test loop conditions and conditional break/continue statements.
////////////////////////////////////////////////////////////////////////////////
@@ -10048,6 +10170,33 @@
}
}
+TEST_P(UniformityAnalysisDiagnosticFilterTest, Directive_SubgroupMatrixUniformity_VarDecl) {
+ auto& param = GetParam();
+ StringStream ss;
+ ss << "enable chromium_experimental_subgroup_matrix;\n"
+ << "diagnostic(" << param << ", chromium.subgroup_matrix_uniformity);" << R"(
+@group(0) @binding(0) var<storage, read_write> non_uniform : i32;
+
+@group(0) @binding(1) var<storage, read_write> data : array<f32>;
+
+fn foo() {
+ if (non_uniform == 42) {
+ var sm : subgroup_matrix_left<f32, 8, 8>;
+ }
+}
+)";
+
+ RunTest(ss.str(), param != wgsl::DiagnosticSeverity::kError);
+
+ if (param == wgsl::DiagnosticSeverity::kOff) {
+ EXPECT_TRUE(error_.empty());
+ } else {
+ StringStream err;
+ err << ToStr(param) << ": variables that contain subgroup matrix types";
+ EXPECT_THAT(error_, ::testing::HasSubstr(err.str()));
+ }
+}
+
TEST_P(UniformityAnalysisDiagnosticFilterTest, AttributeOnFunction_DerivativeUniformity) {
auto& param = GetParam();
StringStream ss;