[hlsl] Add `discard`
This CL add support for emitting `discard` and `TerminateInvocation`
instructions.
Bug: 42251045
Change-Id: Iab7971da453ae3aa52166e8999fe94b52179084b
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/195474
Reviewed-by: James Price <jrprice@google.com>
Commit-Queue: dan sinclair <dsinclair@chromium.org>
diff --git a/src/tint/lang/hlsl/writer/function_test.cc b/src/tint/lang/hlsl/writer/function_test.cc
index 436116a..e2b8660 100644
--- a/src/tint/lang/hlsl/writer/function_test.cc
+++ b/src/tint/lang/hlsl/writer/function_test.cc
@@ -822,7 +822,7 @@
)");
}
-TEST_F(HlslWriterTest, DISABLED_FunctionWithDiscardAndVoidReturn) {
+TEST_F(HlslWriterTest, FunctionWithDiscardAndVoidReturn) {
// fn my_func(a: i32) {
// if (a == 0) {
// discard;
@@ -835,16 +835,19 @@
b.Append(func->Block(), [&] {
auto* i = b.If(b.Equal(ty.bool_(), p, 0_i));
- b.Append(i->True(), [&] { b.Discard(); });
+ b.Append(i->True(), [&] {
+ b.Discard();
+ b.ExitIf(i);
+ });
b.Return(func);
});
ASSERT_TRUE(Generate()) << err_ << output_.hlsl;
- EXPECT_EQ(output_.hlsl, R"(void my_func(int a) {
+ EXPECT_EQ(output_.hlsl, R"(
+void my_func(int a) {
if ((a == 0)) {
discard;
}
- return;
}
[numthreads(1, 1, 1)]
@@ -854,6 +857,7 @@
)");
}
+// TODO(dsinclair): Needs transform to handle discard properly
TEST_F(HlslWriterTest, DISABLED_FunctionWithDiscardAndNonVoidReturn) {
// fn my_func(a: i32) -> i32 {
// if (a == 0) {
@@ -863,17 +867,21 @@
// }
auto* func = b.Function("my_func", ty.i32());
- auto* p = b.FunctionParam("a", ty.i32());
- func->SetParams({p});
+ auto* a = b.FunctionParam("a", ty.i32());
+ func->SetParams({a});
b.Append(func->Block(), [&] {
- auto* i = b.If(b.Equal(ty.bool_(), p, 0_i));
- b.Append(i->True(), [&] { b.Discard(); });
+ auto* i = b.If(b.Equal(ty.bool_(), a, 0_i));
+ b.Append(i->True(), [&] {
+ b.Discard();
+ b.ExitIf(i);
+ });
b.Return(func, 42_i);
});
ASSERT_TRUE(Generate()) << err_ << output_.hlsl;
- EXPECT_EQ(output_.hlsl, R"(int my_func(int a) {
+ EXPECT_EQ(output_.hlsl, R"(
+int my_func(int a) {
if (true) {
if ((a == 0)) {
discard;
@@ -939,7 +947,8 @@
}
ASSERT_TRUE(Generate()) << err_ << output_.hlsl;
- EXPECT_EQ(output_.hlsl, R"(RWByteAddressBuffer data : register(u0);
+ EXPECT_EQ(output_.hlsl, R"(
+RWByteAddressBuffer data : register(u0);
[numthreads(1, 1, 1)]
void a() {
diff --git a/src/tint/lang/hlsl/writer/printer/printer.cc b/src/tint/lang/hlsl/writer/printer/printer.cc
index bbbb103..6b3fa75 100644
--- a/src/tint/lang/hlsl/writer/printer/printer.cc
+++ b/src/tint/lang/hlsl/writer/printer/printer.cc
@@ -57,6 +57,7 @@
#include "src/tint/lang/core/ir/core_binary.h"
#include "src/tint/lang/core/ir/core_builtin_call.h"
#include "src/tint/lang/core/ir/core_unary.h"
+#include "src/tint/lang/core/ir/discard.h"
#include "src/tint/lang/core/ir/exit_if.h"
#include "src/tint/lang/core/ir/exit_loop.h"
#include "src/tint/lang/core/ir/exit_switch.h"
@@ -74,6 +75,7 @@
#include "src/tint/lang/core/ir/store_vector_element.h"
#include "src/tint/lang/core/ir/switch.h"
#include "src/tint/lang/core/ir/swizzle.h"
+#include "src/tint/lang/core/ir/terminate_invocation.h"
#include "src/tint/lang/core/ir/unreachable.h"
#include "src/tint/lang/core/ir/user_call.h"
#include "src/tint/lang/core/ir/validator.h"
@@ -282,7 +284,11 @@
for (auto* inst : *block) {
Switch(
- inst, //
+ inst,
+ // Discard and TerminateInvocation must come before Call.
+ [&](const core::ir::Discard*) { EmitDiscard(); }, //
+ [&](const core::ir::TerminateInvocation*) { EmitDiscard(); }, //
+
[&](const core::ir::BreakIf* i) { EmitBreakIf(i); }, //
[&](const core::ir::Call* i) { EmitCallStmt(i); }, //
[&](const core::ir::Continue*) { EmitContinue(); }, //
@@ -313,6 +319,8 @@
}
}
+ void EmitDiscard() { Line() << "discard;"; }
+
void EmitStoreVectorElement(const core::ir::StoreVectorElement* l) {
auto out = Line();