validation: compute shader must include 'workgroup_size' in its attributes

Bug: tint:884
Change-Id: If96c6df3247fee142a779117fa26d006afd4f7ef
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/55680
Kokoro: Kokoro <noreply+kokoro@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
Sarah
2021-06-29 18:39:44 +00:00
committed by Sarah Mashayekhi
parent d18f2e0d6e
commit e6cb51e715
1840 changed files with 2070 additions and 2018 deletions

View File

@@ -273,7 +273,7 @@ TEST_F(ResolverBuiltinsValidationTest, VertexBuiltin_Pass) {
}
TEST_F(ResolverBuiltinsValidationTest, ComputeBuiltin_Pass) {
// [[stage(compute)]]
// [[stage(compute), workgroup_size(1)]]
// fn main(
// [[builtin(local_invocationId)]] li_id: vec3<u32>,
// [[builtin(local_invocationIndex)]] li_index: u32,

View File

@@ -271,7 +271,7 @@ TEST_P(EntryPointReturnTypeDecorationTest, IsValid) {
Func("main", ast::VariableList{}, ty.vec4<f32>(),
{Return(Construct(ty.vec4<f32>(), 1.f))},
{Stage(ast::PipelineStage::kCompute)},
{Stage(ast::PipelineStage::kCompute), WorkgroupSize(1)},
createDecorations({}, *this, params.kind));
if (params.should_pass) {
@@ -933,6 +933,24 @@ namespace WorkgroupDecorationTests {
namespace {
using WorkgroupDecoration = ResolverTest;
TEST_F(WorkgroupDecoration, ComputeShaderPass) {
Func("main", {}, ty.void_(), {},
{Stage(ast::PipelineStage::kCompute),
create<ast::WorkgroupDecoration>(Source{{12, 34}}, Expr(1))});
EXPECT_TRUE(r()->Resolve()) << r()->error();
}
TEST_F(WorkgroupDecoration, Missing) {
Func(Source{{12, 34}}, "main", {}, ty.void_(), {},
{Stage(ast::PipelineStage::kCompute)});
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(
r()->error(),
"12:34 error: a compute shader must include 'workgroup_size' in its "
"attributes");
}
TEST_F(WorkgroupDecoration, NotAnEntryPoint) {
Func("main", {}, ty.void_(), {},

View File

@@ -49,12 +49,12 @@ using IntrinsicType = sem::IntrinsicType;
using ResolverIntrinsicValidationTest = ResolverTest;
TEST_F(ResolverIntrinsicValidationTest, InvalidPipelineStageDirect) {
// [[stage(compute)]] fn func { return dpdx(1.0); }
// [[stage(compute), workgroup_size(1)]] fn func { return dpdx(1.0); }
auto* dpdx = create<ast::CallExpression>(Source{{3, 4}}, Expr("dpdx"),
ast::ExpressionList{Expr(1.0f)});
Func(Source{{1, 2}}, "func", ast::VariableList{}, ty.void_(), {Ignore(dpdx)},
{Stage(ast::PipelineStage::kCompute)});
{Stage(ast::PipelineStage::kCompute), WorkgroupSize(1)});
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),
@@ -65,7 +65,7 @@ TEST_F(ResolverIntrinsicValidationTest, InvalidPipelineStageIndirect) {
// fn f0 { return dpdx(1.0); }
// fn f1 { f0(); }
// fn f2 { f1(); }
// [[stage(compute)]] fn main { return f2(); }
// [[stage(compute), workgroup_size(1)]] fn main { return f2(); }
auto* dpdx = create<ast::CallExpression>(Source{{3, 4}}, Expr("dpdx"),
ast::ExpressionList{Expr(1.0f)});
@@ -78,7 +78,8 @@ TEST_F(ResolverIntrinsicValidationTest, InvalidPipelineStageIndirect) {
{Ignore(Call("f1"))});
Func(Source{{7, 8}}, "main", ast::VariableList{}, ty.void_(),
{Ignore(Call("f2"))}, {Stage(ast::PipelineStage::kCompute)});
{Ignore(Call("f2"))},
{Stage(ast::PipelineStage::kCompute), WorkgroupSize(1)});
EXPECT_FALSE(r()->Resolve());
EXPECT_EQ(r()->error(),

View File

@@ -1365,6 +1365,16 @@ bool Resolver::ValidateEntryPoint(const ast::Function* func,
}
}
if (func->pipeline_stage() == ast::PipelineStage::kCompute) {
if (!ast::HasDecoration<ast::WorkgroupDecoration>(func->decorations())) {
AddError(
"a compute shader must include 'workgroup_size' in its "
"attributes",
func->source());
return false;
}
}
// Validate there are no resource variable binding collisions
std::unordered_map<sem::BindingPoint, const ast::Variable*> binding_points;
for (auto* var_info : info->referenced_module_vars) {

View File

@@ -1107,7 +1107,7 @@ TEST_F(ResolverTest, Function_ReturnStatements) {
}
TEST_F(ResolverTest, Function_WorkgroupSize_NotSet) {
// [[stage(compute)]]
// [[stage(compute), workgroup_size(1)]]
// fn main() {}
auto* func = Func("main", ast::VariableList{}, ty.void_(), {}, {});
@@ -2067,17 +2067,15 @@ TEST_F(ResolverTest, Function_EntryPoints_StageDecoration) {
Assign("call_a", Call("a")),
Assign("call_b", Call("b")),
},
ast::DecorationList{
Stage(ast::PipelineStage::kCompute),
});
ast::DecorationList{Stage(ast::PipelineStage::kCompute),
WorkgroupSize(1)});
auto* ep_2 = Func("ep_2", params, ty.void_(),
{
Assign("call_c", Call("c")),
},
ast::DecorationList{
Stage(ast::PipelineStage::kCompute),
});
ast::DecorationList{Stage(ast::PipelineStage::kCompute),
WorkgroupSize(1)});
ASSERT_TRUE(r()->Resolve()) << r()->error();
@@ -2154,9 +2152,7 @@ TEST_F(ResolverTest, Function_EntryPoints_LinearTime) {
create<ast::CallStatement>(Call(fn_a(0))),
create<ast::CallStatement>(Call(fn_b(0))),
},
{
Stage(ast::PipelineStage::kCompute),
});
{Stage(ast::PipelineStage::kCompute), WorkgroupSize(1)});
ASSERT_TRUE(r()->Resolve()) << r()->error();
}

View File

@@ -126,7 +126,7 @@ TEST_F(ResolverPipelineStageUseTest, StructUsedAsComputeShaderParam) {
{Member("a", ty.u32(), {Builtin(ast::Builtin::kLocalInvocationIndex)})});
Func("main", {Param("param", ty.Of(s))}, ty.void_(), {},
{Stage(ast::PipelineStage::kCompute)});
{Stage(ast::PipelineStage::kCompute), WorkgroupSize(1)});
ASSERT_TRUE(r()->Resolve()) << r()->error();