spirv-writer: Emit the DepthReplacing execution mode

... if the kFragDepth builtin is referenced.

Bug: dawn:399
Change-Id: I17a4a50d7aa03fd341dec4787a93566c61b59320
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/35500
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: David Neto <dneto@google.com>
diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc
index 2143b57..e1cc57b 100644
--- a/src/writer/spirv/builder.cc
+++ b/src/writer/spirv/builder.cc
@@ -477,6 +477,14 @@
          Operand::Int(x), Operand::Int(y), Operand::Int(z)});
   }
 
+  for (auto builtin : func->referenced_builtin_variables()) {
+    if (builtin.second->value() == ast::Builtin::kFragDepth) {
+      push_execution_mode(
+          spv::Op::OpExecutionMode,
+          {Operand::Int(id), Operand::Int(SpvExecutionModeDepthReplacing)});
+    }
+  }
+
   return true;
 }
 
diff --git a/src/writer/spirv/builder_function_decoration_test.cc b/src/writer/spirv/builder_function_decoration_test.cc
index fe8fc51..4f28dc5 100644
--- a/src/writer/spirv/builder_function_decoration_test.cc
+++ b/src/writer/spirv/builder_function_decoration_test.cc
@@ -271,7 +271,7 @@
 )");
 }
 
-TEST_F(BuilderTest, FunctionDecoration_WorkgroupSize_Default) {
+TEST_F(BuilderTest, FunctionDecoration_ExecutionMode_WorkgroupSize_Default) {
   ast::type::Void void_type;
 
   ast::Function func(
@@ -287,7 +287,7 @@
 )");
 }
 
-TEST_F(BuilderTest, FunctionDecoration_WorkgroupSize) {
+TEST_F(BuilderTest, FunctionDecoration_ExecutionMode_WorkgroupSize) {
   ast::type::Void void_type;
 
   ast::Function func(
@@ -343,6 +343,31 @@
 )");
 }
 
+TEST_F(BuilderTest, FunctionDecoration_ExecutionMode_FragDepth) {
+  auto* fragdepth =
+      Var("fragdepth", ast::StorageClass::kOutput, create<ast::type::F32>(),
+          nullptr,
+          ast::VariableDecorationList{
+              create<ast::BuiltinDecoration>(ast::Builtin::kFragDepth),
+          });
+  mod->AddGlobalVariable(fragdepth);
+
+  auto* body = create<ast::BlockStatement>(ast::StatementList{
+      create<ast::AssignmentStatement>(Expr("fragdepth"), Expr(1.f)),
+  });
+
+  auto* func = create<ast::Function>(
+      Source{}, mod->RegisterSymbol("main"), "main", ast::VariableList{},
+      create<ast::type::Void>(), body, ast::FunctionDecorationList{});
+
+  func->add_referenced_module_variable(fragdepth);
+
+  ASSERT_TRUE(b.GenerateExecutionModes(func, 3)) << b.error();
+  EXPECT_EQ(DumpInstructions(b.execution_modes()),
+            R"(OpExecutionMode %3 DepthReplacing
+)");
+}
+
 }  // namespace
 }  // namespace spirv
 }  // namespace writer