Skip to content

Commit

Permalink
[glsl][ir] Emit If and ExitIf
Browse files Browse the repository at this point in the history
This Cl adds `If` and `ExitIf` support to the GLSL IR backend.

Bug: 42251044
Change-Id: I62741fb732add708ab860a44f9681a8d72e1ce98
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/204814
Reviewed-by: James Price <[email protected]>
Commit-Queue: dan sinclair <[email protected]>
  • Loading branch information
dj2 authored and Dawn LUCI CQ committed Sep 3, 2024
1 parent 7112f39 commit 0330f50
Show file tree
Hide file tree
Showing 99 changed files with 890 additions and 1,013 deletions.
1 change: 1 addition & 0 deletions src/tint/lang/glsl/writer/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ cc_library(
"call_test.cc",
"constant_test.cc",
"function_test.cc",
"if_test.cc",
"switch_test.cc",
"type_test.cc",
"unary_test.cc",
Expand Down
1 change: 1 addition & 0 deletions src/tint/lang/glsl/writer/BUILD.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ tint_add_target(tint_lang_glsl_writer_test test
lang/glsl/writer/call_test.cc
lang/glsl/writer/constant_test.cc
lang/glsl/writer/function_test.cc
lang/glsl/writer/if_test.cc
lang/glsl/writer/switch_test.cc
lang/glsl/writer/type_test.cc
lang/glsl/writer/unary_test.cc
Expand Down
1 change: 1 addition & 0 deletions src/tint/lang/glsl/writer/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ if (tint_build_unittests) {
"call_test.cc",
"constant_test.cc",
"function_test.cc",
"if_test.cc",
"switch_test.cc",
"type_test.cc",
"unary_test.cc",
Expand Down
263 changes: 263 additions & 0 deletions src/tint/lang/glsl/writer/if_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,263 @@
// Copyright 2024 The Dawn & Tint Authors
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice, this
// list of conditions and the following disclaimer.
//
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// 3. Neither the name of the copyright holder nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
// FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
// CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

#include "src/tint/lang/glsl/writer/helper_test.h"

using namespace tint::core::number_suffixes; // NOLINT

namespace tint::glsl::writer {
namespace {

TEST_F(GlslWriterTest, If) {
auto* func = b.Function("foo", ty.void_());
b.Append(func->Block(), [&] {
auto* if_ = b.If(true);
b.Append(if_->True(), [&] { b.ExitIf(if_); });
b.Return(func);
});

ASSERT_TRUE(Generate()) << err_ << output_.glsl;
EXPECT_EQ(output_.glsl, GlslHeader() + R"(
void foo() {
if (true) {
}
}
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
void main() {
}
)");
}

TEST_F(GlslWriterTest, IfWithElseIf) {
auto* func = b.Function("foo", ty.void_());
b.Append(func->Block(), [&] {
auto* if_ = b.If(true);
b.Append(if_->True(), [&] { b.ExitIf(if_); });
b.Append(if_->False(), [&] {
auto* false_ = b.If(false);
b.Append(false_->True(), [&] { b.ExitIf(false_); });
b.ExitIf(if_);
});
b.Return(func);
});

ASSERT_TRUE(Generate()) << err_ << output_.glsl;
EXPECT_EQ(output_.glsl, GlslHeader() + R"(
void foo() {
if (true) {
} else {
if (false) {
}
}
}
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
void main() {
}
)");
}

TEST_F(GlslWriterTest, IfWithElse) {
auto* func = b.Function("foo", ty.void_());
b.Append(func->Block(), [&] {
auto* if_ = b.If(true);
b.Append(if_->True(), [&] { b.ExitIf(if_); });
b.Append(if_->False(), [&] { b.Return(func); });
b.Return(func);
});

ASSERT_TRUE(Generate()) << err_ << output_.glsl;
EXPECT_EQ(output_.glsl, GlslHeader() + R"(
void foo() {
if (true) {
} else {
return;
}
}
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
void main() {
}
)");
}

TEST_F(GlslWriterTest, IfBothBranchesReturn) {
auto* func = b.Function("foo", ty.void_());
b.Append(func->Block(), [&] {
auto* if_ = b.If(true);
b.Append(if_->True(), [&] { b.Return(func); });
b.Append(if_->False(), [&] { b.Return(func); });
b.Unreachable();
});

ASSERT_TRUE(Generate()) << err_ << output_.glsl;
EXPECT_EQ(output_.glsl, GlslHeader() + R"(
void foo() {
if (true) {
return;
} else {
return;
}
/* unreachable */
}
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
void main() {
}
)");
}

TEST_F(GlslWriterTest, IfWithSinglePhi) {
auto* func = b.Function("foo", ty.void_());
b.Append(func->Block(), [&] {
auto* i = b.If(true);
i->SetResults(b.InstructionResult(ty.i32()));
b.Append(i->True(), [&] { //
b.ExitIf(i, 10_i);
});
b.Append(i->False(), [&] { //
b.ExitIf(i, 20_i);
});
b.Return(func);
});

ASSERT_TRUE(Generate()) << err_ << output_.glsl;
EXPECT_EQ(output_.glsl, GlslHeader() + R"(
void foo() {
int v = 0;
if (true) {
v = 10;
} else {
v = 20;
}
}
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
void main() {
}
)");
}

TEST_F(GlslWriterTest, IfWithMultiPhi) {
auto* func = b.Function("foo", ty.void_());
b.Append(func->Block(), [&] {
auto* i = b.If(true);
i->SetResults(b.InstructionResult(ty.i32()), b.InstructionResult(ty.bool_()));
b.Append(i->True(), [&] { //
b.ExitIf(i, 10_i, true);
});
b.Append(i->False(), [&] { //
b.ExitIf(i, 20_i, false);
});
b.Return(func);
});

ASSERT_TRUE(Generate()) << err_ << output_.glsl;
EXPECT_EQ(output_.glsl, GlslHeader() + R"(
void foo() {
int v = 0;
bool v_1 = false;
if (true) {
v = 10;
v_1 = true;
} else {
v = 20;
v_1 = false;
}
}
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
void main() {
}
)");
}

TEST_F(GlslWriterTest, IfWithMultiPhiReturn1) {
auto* func = b.Function("foo", ty.i32());
b.Append(func->Block(), [&] {
auto* i = b.If(true);
i->SetResults(b.InstructionResult(ty.i32()), b.InstructionResult(ty.bool_()));
b.Append(i->True(), [&] { //
b.ExitIf(i, 10_i, true);
});
b.Append(i->False(), [&] { //
b.ExitIf(i, 20_i, false);
});
b.Return(func, i->Result(0));
});

ASSERT_TRUE(Generate()) << err_ << output_.glsl;
EXPECT_EQ(output_.glsl, GlslHeader() + R"(
int foo() {
int v = 0;
bool v_1 = false;
if (true) {
v = 10;
v_1 = true;
} else {
v = 20;
v_1 = false;
}
return v;
}
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
void main() {
}
)");
}

TEST_F(GlslWriterTest, IfWithMultiPhiReturn2) {
auto* func = b.Function("foo", ty.bool_());
b.Append(func->Block(), [&] {
auto* i = b.If(true);
i->SetResults(b.InstructionResult(ty.i32()), b.InstructionResult(ty.bool_()));
b.Append(i->True(), [&] { //
b.ExitIf(i, 10_i, true);
});
b.Append(i->False(), [&] { //
b.ExitIf(i, 20_i, false);
});
b.Return(func, i->Result(1));
});

ASSERT_TRUE(Generate()) << err_ << output_.glsl;
EXPECT_EQ(output_.glsl, GlslHeader() + R"(
bool foo() {
int v = 0;
bool v_1 = false;
if (true) {
v = 10;
v_1 = true;
} else {
v = 20;
v_1 = false;
}
return v_1;
}
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
void main() {
}
)");
}

} // namespace
} // namespace tint::glsl::writer
46 changes: 37 additions & 9 deletions src/tint/lang/glsl/writer/printer/printer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
#include "src/tint/lang/core/ir/exit_if.h"
#include "src/tint/lang/core/ir/exit_switch.h"
#include "src/tint/lang/core/ir/function.h"
#include "src/tint/lang/core/ir/if.h"
#include "src/tint/lang/core/ir/let.h"
#include "src/tint/lang/core/ir/load.h"
#include "src/tint/lang/core/ir/load_vector_element.h"
Expand Down Expand Up @@ -249,15 +250,17 @@ class Printer : public tint::TextGenerator {

for (auto* inst : *block) {
tint::Switch(
inst, //
[&](const core::ir::Call* i) { EmitCallStmt(i); }, //
[&](const core::ir::ExitSwitch*) { EmitExitSwitch(); }, //
[&](const core::ir::Let* i) { EmitLet(i); }, //
[&](const core::ir::Return* r) { EmitReturn(r); }, //
[&](const core::ir::Store* s) { EmitStore(s); }, //
[&](const core::ir::Switch* i) { EmitSwitch(i); }, //
[&](const core::ir::Unreachable*) { EmitUnreachable(); }, //
[&](const core::ir::Var* v) { EmitVar(Line(), v); }, //
inst, //
[&](const core::ir::Call* i) { EmitCallStmt(i); }, //
[&](const core::ir::ExitIf*) { /* do nothing handled by transform */ }, //
[&](const core::ir::ExitSwitch*) { EmitExitSwitch(); }, //
[&](const core::ir::If* i) { EmitIf(i); }, //
[&](const core::ir::Let* i) { EmitLet(i); }, //
[&](const core::ir::Return* r) { EmitReturn(r); }, //
[&](const core::ir::Store* s) { EmitStore(s); }, //
[&](const core::ir::Switch* i) { EmitSwitch(i); }, //
[&](const core::ir::Unreachable*) { EmitUnreachable(); }, //
[&](const core::ir::Var* v) { EmitVar(Line(), v); }, //

[&](const core::ir::NextIteration*) { /* do nothing */ }, //
[&](const core::ir::ExitIf*) { /* do nothing handled by transform */ }, //
Expand All @@ -274,6 +277,31 @@ class Printer : public tint::TextGenerator {
}
}

/// Emit an if instruction
/// @param if_ the if instruction
void EmitIf(const core::ir::If* if_) {
{
auto out = Line();
out << "if (";
EmitValue(out, if_->Condition());
out << ") {";
}

{
const ScopedIndent si(current_buffer_);
EmitBlock(if_->True());
}

if (if_->False() && !if_->False()->IsEmpty()) {
Line() << "} else {";

const ScopedIndent si(current_buffer_);
EmitBlock(if_->False());
}

Line() << "}";
}

void EmitExitSwitch() { Line() << "break;"; }

void EmitSwitch(const core::ir::Switch* s) {
Expand Down
19 changes: 9 additions & 10 deletions test/tint/bug/chromium/341124493.wgsl.expected.ir.glsl
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
SKIP: FAILED
#version 310 es

<dawn>/src/tint/lang/glsl/writer/printer/printer.cc:252 internal compiler error: Switch() matched no cases. Type: tint::core::ir::If
********************************************************************
* The tint shader compiler has encountered an unexpected error. *
* *
* Please help us fix this issue by submitting a bug report at *
* crbug.com/tint with the source program that triggered the bug. *
********************************************************************

tint executable returned error: signal: illegal instruction
void F() {
bool b = false;
if (false) {
}
}
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
void main() {
}
Loading

0 comments on commit 0330f50

Please sign in to comment.