[spirv] Fail for functions with >255 parameters Some IR transforms add new parameters to existing functions, which can cause a valid input shader to exceed SPIR-V limit of 255 parameters. We can't easily fix this, so just fail gracefully and class it as a spurious failure as per the WGSL spec. Fixed: 354748060 Change-Id: I31b1d1eddc2b75e237e3f01f967f4bb3e3488cee Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/200014 Reviewed-by: David Neto <dneto@google.com> Auto-Submit: James Price <jrprice@google.com> Commit-Queue: David Neto <dneto@google.com> (cherry picked from commit 3f657b9e679dc3a9f35f4a9f880f5da02ae86478) Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/200275 Reviewed-by: Ken Russell <kbr@google.com>
diff --git a/src/tint/lang/spirv/writer/printer/printer.cc b/src/tint/lang/spirv/writer/printer/printer.cc index 8a7ccc1..82c3b15 100644 --- a/src/tint/lang/spirv/writer/printer/printer.cc +++ b/src/tint/lang/spirv/writer/printer/printer.cc
@@ -307,7 +307,10 @@ // Emit functions. for (core::ir::Function* func : ir_.functions) { - EmitFunction(func); + auto res = EmitFunction(func); + if (res != Success) { + return res; + } } return Success; @@ -694,7 +697,17 @@ /// Emit a function. /// @param func the function to emit - void EmitFunction(core::ir::Function* func) { + Result<SuccessType> EmitFunction(core::ir::Function* func) { + if (func->Params().Length() > 255) { + // Tint transforms may add additional function parameters which can cause a valid input + // shader to exceed SPIR-V's function parameter limit. There isn't much we can do about + // this, so just fail gracefully instead of a generating invalid SPIR-V. + StringStream ss; + ss << "Function '" << ir_.NameOf(func).Name() + << "' has more than 255 parameters after running Tint transforms"; + return Failure{ss.str()}; + } + auto id = Value(func); // Emit the function name. @@ -748,6 +761,8 @@ // Add the function to the module. module_.PushFunction(current_function_); + + return Success; } /// Emit entry point declarations for a function.
diff --git a/src/tint/lang/spirv/writer/writer_test.cc b/src/tint/lang/spirv/writer/writer_test.cc index b64c0ef..c00563f 100644 --- a/src/tint/lang/spirv/writer/writer_test.cc +++ b/src/tint/lang/spirv/writer/writer_test.cc
@@ -86,5 +86,24 @@ )"); } +// Test that we fail gracefully when a function has too many parameters. +// See crbug.com/354748060. +TEST_F(SpirvWriterTest, TooManyFunctionParameters) { + Vector<core::ir::FunctionParam*, 256> params; + for (uint32_t i = 0; i < 256; i++) { + params.Push(b.FunctionParam(ty.i32())); + } + auto* func = b.Function("foo", ty.void_()); + func->SetParams(std::move(params)); + b.Append(func->Block(), [&] { // + b.Return(func); + }); + + EXPECT_FALSE(Generate()); + EXPECT_THAT(Error(), + testing::HasSubstr( + "Function 'foo' has more than 255 parameters after running Tint transforms")); +} + } // namespace } // namespace tint::spirv::writer