Skip to content

Commit

Permalink
[glsl][ir] Emit Loop and supporting instructions
Browse files Browse the repository at this point in the history
This Cl adds `Loop`, `Continue`, `BreakIf` and `ExitLoop` support to the
GLSL IR backend.

Bug: 42251044
Change-Id: Id94471a4218725a0dc8ad4c84f734ee98c3a5507
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/204815
Commit-Queue: dan sinclair <[email protected]>
Reviewed-by: James Price <[email protected]>
  • Loading branch information
dj2 authored and Dawn LUCI CQ committed Sep 3, 2024
1 parent 0330f50 commit 7206591
Show file tree
Hide file tree
Showing 150 changed files with 1,700 additions and 1,537 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 @@ -95,6 +95,7 @@ cc_library(
"constant_test.cc",
"function_test.cc",
"if_test.cc",
"loop_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 @@ -109,6 +109,7 @@ tint_add_target(tint_lang_glsl_writer_test test
lang/glsl/writer/constant_test.cc
lang/glsl/writer/function_test.cc
lang/glsl/writer/if_test.cc
lang/glsl/writer/loop_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 @@ -99,6 +99,7 @@ if (tint_build_unittests) {
"constant_test.cc",
"function_test.cc",
"if_test.cc",
"loop_test.cc",
"switch_test.cc",
"type_test.cc",
"unary_test.cc",
Expand Down
153 changes: 153 additions & 0 deletions src/tint/lang/glsl/writer/loop_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
// 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::fluent_types; // NOLINT
using namespace tint::core::number_suffixes; // NOLINT

namespace tint::glsl::writer {
namespace {

TEST_F(GlslWriterTest, Loop) {
auto* func = b.Function("a", ty.void_(), core::ir::Function::PipelineStage::kCompute);
func->SetWorkgroupSize(1, 1, 1);

b.Append(func->Block(), [&] {
auto* l = b.Loop();
b.Append(l->Body(), [&] { b.ExitLoop(l); });
b.Append(l->Continuing(), [&] { b.NextIteration(l); });
b.Return(func);
});

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

TEST_F(GlslWriterTest, LoopContinueAndBreakIf) {
auto* func = b.Function("a", ty.void_(), core::ir::Function::PipelineStage::kCompute);
func->SetWorkgroupSize(1, 1, 1);

b.Append(func->Block(), [&] {
auto* l = b.Loop();
b.Append(l->Body(), [&] { b.Continue(l); });
b.Append(l->Continuing(), [&] { b.BreakIf(l, true); });
b.Return(func);
});

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

TEST_F(GlslWriterTest, LoopBodyVarInContinue) {
auto* func = b.Function("a", ty.void_(), core::ir::Function::PipelineStage::kCompute);
func->SetWorkgroupSize(1, 1, 1);

b.Append(func->Block(), [&] {
auto* l = b.Loop();
b.Append(l->Body(), [&] {
auto* v = b.Var("v", true);
b.Continue(l);

b.Append(l->Continuing(), [&] { b.BreakIf(l, v); });
});
b.Return(func);
});

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

TEST_F(GlslWriterTest, LoopInitializer) {
auto* func = b.Function("a", ty.void_(), core::ir::Function::PipelineStage::kCompute);
func->SetWorkgroupSize(1, 1, 1);

b.Append(func->Block(), [&] {
auto* l = b.Loop();
b.Append(l->Initializer(), [&] {
auto* v = b.Var("v", true);
b.NextIteration(l);

b.Append(l->Body(), [&] { b.Continue(l); });
b.Append(l->Continuing(), [&] { b.BreakIf(l, v); });
});
b.Return(func);
});

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

} // namespace
} // namespace tint::glsl::writer
64 changes: 64 additions & 0 deletions src/tint/lang/glsl/writer/printer/printer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,18 +34,23 @@
#include "src/tint/lang/core/constant/splat.h"
#include "src/tint/lang/core/ir/access.h"
#include "src/tint/lang/core/ir/bitcast.h"
#include "src/tint/lang/core/ir/break_if.h"
#include "src/tint/lang/core/ir/construct.h"
#include "src/tint/lang/core/ir/continue.h"
#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/exit_if.h"
#include "src/tint/lang/core/ir/exit_loop.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"
#include "src/tint/lang/core/ir/loop.h"
#include "src/tint/lang/core/ir/module.h"
#include "src/tint/lang/core/ir/multi_in_block.h"
#include "src/tint/lang/core/ir/next_iteration.h"
#include "src/tint/lang/core/ir/return.h"
#include "src/tint/lang/core/ir/store.h"
Expand Down Expand Up @@ -148,6 +153,9 @@ class Printer : public tint::TextGenerator {
// The set of emitted structs
Hashset<const core::type::Struct*, 4> emitted_structs_;

/// Block to emit for a continuing
std::function<void()> emit_continuing_;

/// @returns the name of the given value, creating a new unique name if the value is unnamed in
/// the module.
std::string NameOf(const core::ir::Value* value) {
Expand Down Expand Up @@ -251,11 +259,15 @@ class Printer : public tint::TextGenerator {
for (auto* inst : *block) {
tint::Switch(
inst, //
[&](const core::ir::BreakIf* i) { EmitBreakIf(i); }, //
[&](const core::ir::Call* i) { EmitCallStmt(i); }, //
[&](const core::ir::Continue*) { EmitContinue(); }, //
[&](const core::ir::ExitIf*) { /* do nothing handled by transform */ }, //
[&](const core::ir::ExitLoop*) { EmitExitLoop(); }, //
[&](const core::ir::ExitSwitch*) { EmitExitSwitch(); }, //
[&](const core::ir::If* i) { EmitIf(i); }, //
[&](const core::ir::Let* i) { EmitLet(i); }, //
[&](const core::ir::Loop* l) { EmitLoop(l); }, //
[&](const core::ir::Return* r) { EmitReturn(r); }, //
[&](const core::ir::Store* s) { EmitStore(s); }, //
[&](const core::ir::Switch* i) { EmitSwitch(i); }, //
Expand All @@ -277,6 +289,51 @@ class Printer : public tint::TextGenerator {
}
}

void EmitContinue() {
if (emit_continuing_) {
emit_continuing_();
}
Line() << "continue;";
}

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

void EmitLoop(const core::ir::Loop* l) {
// Note, we can't just emit the continuing inside a conditional at the top of the loop
// because any variable declared in the block must be visible to the continuing.
//
// loop {
// var a = 3;
// continue {
// let y = a;
// }
// }

auto emit_continuing = [&] {
Line() << "{";
{
const ScopedIndent si(current_buffer_);
EmitBlock(l->Continuing());
}
Line() << "}";
};
TINT_SCOPED_ASSIGNMENT(emit_continuing_, emit_continuing);

Line() << "{";
{
ScopedIndent init(current_buffer_);
EmitBlock(l->Initializer());

Line() << "while(true) {";
{
ScopedIndent si(current_buffer_);
EmitBlock(l->Body());
}
Line() << "}";
}
Line() << "}";
}

/// Emit an if instruction
/// @param if_ the if instruction
void EmitIf(const core::ir::If* if_) {
Expand All @@ -302,6 +359,13 @@ class Printer : public tint::TextGenerator {
Line() << "}";
}

void EmitBreakIf(const core::ir::BreakIf* b) {
auto out = Line();
out << "if (";
EmitValue(out, b->Condition());
out << ") { break; }";
}

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

void EmitSwitch(const core::ir::Switch* s) {
Expand Down
91 changes: 82 additions & 9 deletions test/tint/array/strides.spvasm.expected.ir.glsl
Original file line number Diff line number Diff line change
@@ -1,11 +1,84 @@
SKIP: FAILED
#version 310 es

<dawn>/src/tint/lang/glsl/writer/printer/printer.cc:482 internal compiler error: Switch() matched no cases. Type: tint::core::ir::Load
********************************************************************
* 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. *
********************************************************************
struct strided_arr {
float el;
};

tint executable returned error: signal: illegal instruction
struct strided_arr_1 {
strided_arr el[3][2];
};

struct S {
strided_arr_1 a[4];
};

S s;
void tint_store_and_preserve_padding_4(inout strided_arr target, strided_arr value_param) {
target.el = value_param.el;
}
void tint_store_and_preserve_padding_3(inout strided_arr target[2], strided_arr value_param[2]) {
{
uint v = 0u;
v = 0u;
while(true) {
uint v_1 = v;
if ((v_1 >= 2u)) {
break;
}
tint_store_and_preserve_padding_4(target[v_1], value_param[v_1]);
{
v = (v_1 + 1u);
}
continue;
}
}
}
void tint_store_and_preserve_padding_2(inout strided_arr target[3][2], strided_arr value_param[3][2]) {
{
uint v_2 = 0u;
v_2 = 0u;
while(true) {
uint v_3 = v_2;
if ((v_3 >= 3u)) {
break;
}
tint_store_and_preserve_padding_3(target[v_3], value_param[v_3]);
{
v_2 = (v_3 + 1u);
}
continue;
}
}
}
void tint_store_and_preserve_padding_1(inout strided_arr_1 target, strided_arr_1 value_param) {
tint_store_and_preserve_padding_2(target.el, value_param.el);
}
void tint_store_and_preserve_padding(inout strided_arr_1 target[4], strided_arr_1 value_param[4]) {
{
uint v_4 = 0u;
v_4 = 0u;
while(true) {
uint v_5 = v_4;
if ((v_5 >= 4u)) {
break;
}
tint_store_and_preserve_padding_1(target[v_5], value_param[v_5]);
{
v_4 = (v_5 + 1u);
}
continue;
}
}
}
void f_1() {
strided_arr_1 x_19[4] = s.a;
strided_arr x_24[3][2] = s.a[3].el;
strided_arr x_28[2] = s.a[3].el[2];
float x_32 = s.a[3].el[2][1].el;
tint_store_and_preserve_padding(s.a, strided_arr_1[4](strided_arr_1(strided_arr[3][2](strided_arr[2](strided_arr(0.0f), strided_arr(0.0f)), strided_arr[2](strided_arr(0.0f), strided_arr(0.0f)), strided_arr[2](strided_arr(0.0f), strided_arr(0.0f)))), strided_arr_1(strided_arr[3][2](strided_arr[2](strided_arr(0.0f), strided_arr(0.0f)), strided_arr[2](strided_arr(0.0f), strided_arr(0.0f)), strided_arr[2](strided_arr(0.0f), strided_arr(0.0f)))), strided_arr_1(strided_arr[3][2](strided_arr[2](strided_arr(0.0f), strided_arr(0.0f)), strided_arr[2](strided_arr(0.0f), strided_arr(0.0f)), strided_arr[2](strided_arr(0.0f), strided_arr(0.0f)))), strided_arr_1(strided_arr[3][2](strided_arr[2](strided_arr(0.0f), strided_arr(0.0f)), strided_arr[2](strided_arr(0.0f), strided_arr(0.0f)), strided_arr[2](strided_arr(0.0f), strided_arr(0.0f))))));
s.a[3].el[2][1].el = 5.0f;
}
layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
void main() {
f_1();
}
Loading

0 comments on commit 7206591

Please sign in to comment.