[tint][ir][val] Add basic const checks for @workgroup_size
This checks that the value for params are in range if they are
constant values, and rejects non-constant value params if
kAllowsOverrides is not set.
It does not do the look-up to determine if more complex cases are
override-expression yet, since there is still implementation side work
needed for overrides.
Issue: 376624999
Change-Id: I370c982d503e32e6db03f5b0ef91dee5bfe2eb75
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/214095
Reviewed-by: dan sinclair <dsinclair@chromium.org>
Commit-Queue: Ryan Harrison <rharrison@chromium.org>
Auto-Submit: Ryan Harrison <rharrison@chromium.org>
diff --git a/src/tint/lang/core/ir/validator.cc b/src/tint/lang/core/ir/validator.cc
index 2221117..e467b07 100644
--- a/src/tint/lang/core/ir/validator.cc
+++ b/src/tint/lang/core/ir/validator.cc
@@ -2015,7 +2015,33 @@
return;
}
- // TODO(376624999): Implement enforcing rules around override and constant expressions
+ if (auto* c = size->As<ir::Constant>()) {
+ if (c->Value()->ValueAs<int64_t>() <= 0) {
+ AddError(func) << "@workgroup_size params must be greater than 0";
+ return;
+ }
+ continue;
+ }
+
+ if (!capabilities_.Contains(Capability::kAllowOverrides)) {
+ AddError(func) << "@workgroup_size param is not a constant value, and IR capability "
+ "'kAllowOverrides' is not set";
+ return;
+ }
+
+ if (auto* r = size->As<ir::InstructionResult>()) {
+ if (r->Instruction() && r->Instruction()->Is<core::ir::Override>()) {
+ continue;
+ }
+
+ // TODO(376624999): Finish implementing checking that this is a override/constant
+ // expression, i.e. calculated from only appropriate values/operations, once override
+ // implementation is complete
+ // for each value/operation used to calculate param:
+ // if not constant expression && not override expression:
+ // fail
+ // pass
+ }
}
}
diff --git a/src/tint/lang/core/ir/validator_test.cc b/src/tint/lang/core/ir/validator_test.cc
index b2fccba..01b25b8 100644
--- a/src/tint/lang/core/ir/validator_test.cc
+++ b/src/tint/lang/core/ir/validator_test.cc
@@ -1054,6 +1054,52 @@
)");
}
+TEST_F(IR_ValidatorTest, Function_WorkgroupSize_ParamsTooSmall) {
+ auto* f = ComputeEntryPoint();
+ f->SetWorkgroupSize({b.Constant(-1_i), b.Constant(2_i), b.Constant(3_i)});
+
+ b.Append(f->Block(), [&] { b.Unreachable(); });
+
+ auto res = ir::Validate(mod);
+ ASSERT_NE(res, Success);
+ EXPECT_EQ(res.Failure().reason.Str(),
+ R"(:1:1 error: @workgroup_size params must be greater than 0
+%f = @compute @workgroup_size(-1i, 2i, 3i) func():void {
+^^
+
+note: # Disassembly
+%f = @compute @workgroup_size(-1i, 2i, 3i) func():void {
+ $B1: {
+ unreachable
+ }
+}
+)");
+}
+
+TEST_F(IR_ValidatorTest, Function_WorkgroupSize_OverrideWithoutAllowOverrides) {
+ auto* o = b.Override(ty.u32());
+ auto* f = ComputeEntryPoint();
+ f->SetWorkgroupSize({o->Result(0), o->Result(0), o->Result(0)});
+
+ b.Append(f->Block(), [&] { b.Unreachable(); });
+
+ auto res = ir::Validate(mod);
+ ASSERT_NE(res, Success);
+ EXPECT_EQ(
+ res.Failure().reason.Str(),
+ R"(:1:1 error: @workgroup_size param is not a constant value, and IR capability 'kAllowOverrides' is not set
+%f = @compute @workgroup_size(%2, %2, %2) func():void {
+^^
+
+note: # Disassembly
+%f = @compute @workgroup_size(%2, %2, %2) func():void {
+ $B1: {
+ unreachable
+ }
+}
+)");
+}
+
TEST_F(IR_ValidatorTest, Function_Vertex_BasicPosition) {
auto* f = b.Function("my_func", ty.vec4<f32>(), Function::PipelineStage::kVertex);
f->SetReturnBuiltin(BuiltinValue::kPosition);