[spirv-reader][ir] Support `WorkgroupSize` annotation.
Adds support for creating computer shader workgroup size information
from a `WorkgroupSize` annotated variable.
Bug: 42250952
Change-Id: I54d3112b658a4b9c62c3334bf8ced143aedb6482
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/245995
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: James Price <jrprice@google.com>
diff --git a/src/tint/lang/spirv/reader/parser/function_test.cc b/src/tint/lang/spirv/reader/parser/function_test.cc
index 2b53807..98a2aea 100644
--- a/src/tint/lang/spirv/reader/parser/function_test.cc
+++ b/src/tint/lang/spirv/reader/parser/function_test.cc
@@ -74,6 +74,101 @@
)");
}
+TEST_F(SpirvParserTest, WorkgroupSize_Constant) {
+ EXPECT_IR(R"(
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main"
+ OpDecorate %gl_WorkGroupSize BuiltIn WorkgroupSize
+ %void = OpTypeVoid
+ %uint = OpTypeInt 32 0
+ %v3uint = OpTypeVector %uint 3
+ %uint_3 = OpConstant %uint 3
+ %uint_5 = OpConstant %uint 5
+ %uint_7 = OpConstant %uint 7
+%gl_WorkGroupSize = OpConstantComposite %v3uint %uint_3 %uint_5 %uint_7
+ %ep_type = OpTypeFunction %void
+ %main = OpFunction %void None %ep_type
+ %main_start = OpLabel
+ OpReturn
+ OpFunctionEnd
+)",
+ R"(
+%main = @compute @workgroup_size(3u, 5u, 7u) func():void {
+ $B1: {
+ ret
+ }
+}
+)");
+}
+
+TEST_F(SpirvParserTest, WorkgroupSize_SpecConstant_Mixed) {
+ EXPECT_IR(R"(
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main"
+ OpDecorate %gl_WorkGroupSize BuiltIn WorkgroupSize
+ %void = OpTypeVoid
+ %uint = OpTypeInt 32 0
+ %v3uint = OpTypeVector %uint 3
+ %uint_3 = OpSpecConstant %uint 3
+ %uint_5 = OpConstant %uint 5
+ %uint_7 = OpSpecConstant %uint 7
+%gl_WorkGroupSize = OpSpecConstantComposite %v3uint %uint_3 %uint_5 %uint_7
+ %ep_type = OpTypeFunction %void
+ %main = OpFunction %void None %ep_type
+ %main_start = OpLabel
+ OpReturn
+ OpFunctionEnd
+)",
+ R"(
+$B1: { # root
+ %1:u32 = override 3u
+ %2:u32 = override 7u
+}
+
+%main = @compute @workgroup_size(%1, 5u, %2) func():void {
+ $B2: {
+ ret
+ }
+}
+)");
+}
+
+TEST_F(SpirvParserTest, WorkgroupSize_SpecConstant) {
+ EXPECT_IR(R"(
+ OpCapability Shader
+ OpMemoryModel Logical GLSL450
+ OpEntryPoint GLCompute %main "main"
+ OpDecorate %gl_WorkGroupSize BuiltIn WorkgroupSize
+ %void = OpTypeVoid
+ %uint = OpTypeInt 32 0
+ %v3uint = OpTypeVector %uint 3
+ %uint_3 = OpSpecConstant %uint 3
+ %uint_5 = OpSpecConstant %uint 5
+ %uint_7 = OpSpecConstant %uint 7
+%gl_WorkGroupSize = OpSpecConstantComposite %v3uint %uint_3 %uint_5 %uint_7
+ %ep_type = OpTypeFunction %void
+ %main = OpFunction %void None %ep_type
+ %main_start = OpLabel
+ OpReturn
+ OpFunctionEnd
+)",
+ R"(
+$B1: { # root
+ %1:u32 = override 3u
+ %2:u32 = override 5u
+ %3:u32 = override 7u
+}
+
+%main = @compute @workgroup_size(%1, %2, %3) func():void {
+ $B2: {
+ ret
+ }
+}
+)");
+}
+
TEST_F(SpirvParserTest, FragmentShader) {
EXPECT_IR(R"(
OpCapability Shader
diff --git a/src/tint/lang/spirv/reader/parser/parser.cc b/src/tint/lang/spirv/reader/parser/parser.cc
index b7c6cb2..6a82af2 100644
--- a/src/tint/lang/spirv/reader/parser/parser.cc
+++ b/src/tint/lang/spirv/reader/parser/parser.cc
@@ -1183,6 +1183,39 @@
// first one found.
break;
}
+ } else if (func->IsCompute()) {
+ // Search for `WorkgroupSize` decorated Ids
+ for (const spvtools::opt::Instruction& inst :
+ spirv_context_->module()->annotations()) {
+ if (inst.opcode() != spv::Op::OpDecorate ||
+ inst.GetSingleWordInOperand(1) != uint32_t(spv::Decoration::BuiltIn) ||
+ inst.GetSingleWordInOperand(2) != uint32_t(spv::BuiltIn::WorkgroupSize)) {
+ continue;
+ }
+ uint32_t id = inst.GetSingleWordInOperand(0);
+
+ Vector<core::ir::Value*, 3> args;
+ if (auto* c = SpvConstant(id)) {
+ auto* vals = c->AsVectorConstant();
+ TINT_ASSERT(vals);
+
+ for (auto& el : vals->GetComponents()) {
+ args.Push(b_.Constant(Constant(el)));
+ }
+ } else {
+ TINT_ASSERT(spec_composites_.contains(id));
+
+ auto info = spec_composites_[id];
+ TINT_ASSERT(info.args.Length() == 3);
+
+ for (auto arg : info.args) {
+ args.Push(Value(arg));
+ }
+ }
+ func->SetWorkgroupSize(args[0], args[1], args[2]);
+
+ break;
+ }
}
}