diff --git a/BUILD.gn b/BUILD.gn index c31ebffd9a..fa52285d71 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -803,6 +803,7 @@ source_set("tint_unittests_spv_writer_src") { "src/writer/spirv/builder_call_test.cc", "src/writer/spirv/builder_cast_expression_test.cc", "src/writer/spirv/builder_constructor_expression_test.cc", + "src/writer/spirv/builder_discard_test.cc", "src/writer/spirv/builder_entry_point_test.cc", "src/writer/spirv/builder_function_test.cc", "src/writer/spirv/builder_function_variable_test.cc", diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index d2807b9bf3..4f35b61f7b 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -457,6 +457,7 @@ if(${TINT_BUILD_SPV_WRITER}) writer/spirv/builder_call_test.cc writer/spirv/builder_cast_expression_test.cc writer/spirv/builder_constructor_expression_test.cc + writer/spirv/builder_discard_test.cc writer/spirv/builder_entry_point_test.cc writer/spirv/builder_function_test.cc writer/spirv/builder_function_variable_test.cc diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc index d5c956f5c4..c21288ff1d 100644 --- a/src/writer/spirv/builder.cc +++ b/src/writer/spirv/builder.cc @@ -105,8 +105,8 @@ bool LastIsTerminator(const ast::StatementList& stmts) { } auto* last = stmts.back().get(); - return last->IsBreak() || last->IsContinue() || last->IsReturn() || - last->IsKill() || last->IsFallthrough(); + return last->IsBreak() || last->IsContinue() || last->IsDiscard() || + last->IsReturn() || last->IsKill() || last->IsFallthrough(); } uint32_t IndexFromName(char name) { @@ -273,6 +273,14 @@ bool Builder::GenerateContinueStatement(ast::ContinueStatement*) { return true; } +// TODO(dsinclair): This is generating an OpKill but the semantics of kill +// haven't been defined for WGSL yet. So, this may need to change. +// https://github.com/gpuweb/gpuweb/issues/676 +bool Builder::GenerateDiscardStatement(ast::DiscardStatement*) { + push_function_inst(spv::Op::OpKill, {}); + return true; +} + // TODO(dsinclair): This is generating an OpKill but the semantics of kill // haven't been defined for WGSL yet. So, this may need to change. // https://github.com/gpuweb/gpuweb/issues/676 @@ -1816,6 +1824,9 @@ bool Builder::GenerateStatement(ast::Statement* stmt) { if (stmt->IsContinue()) { return GenerateContinueStatement(stmt->AsContinue()); } + if (stmt->IsDiscard()) { + return GenerateDiscardStatement(stmt->AsDiscard()); + } if (stmt->IsFallthrough()) { // Do nothing here, the fallthrough gets handled by the switch code. return true; diff --git a/src/writer/spirv/builder.h b/src/writer/spirv/builder.h index 91505e82a0..28f893aa2e 100644 --- a/src/writer/spirv/builder.h +++ b/src/writer/spirv/builder.h @@ -175,6 +175,10 @@ class Builder { /// @param stmt the statement to generate /// @returns true if the statement was successfully generated bool GenerateContinueStatement(ast::ContinueStatement* stmt); + /// Generates a discard statement + /// @param stmt the statement to generate + /// @returns true if the statement was successfully generated + bool GenerateDiscardStatement(ast::DiscardStatement* stmt); /// Generates a kill statement /// @param stmt the statement to generate /// @returns true if the statement was successfully generated diff --git a/src/writer/spirv/builder_discard_test.cc b/src/writer/spirv/builder_discard_test.cc new file mode 100644 index 0000000000..596a24c210 --- /dev/null +++ b/src/writer/spirv/builder_discard_test.cc @@ -0,0 +1,43 @@ +// Copyright 2020 The Tint Authors. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "gtest/gtest.h" +#include "src/ast/discard_statement.h" +#include "src/context.h" +#include "src/type_determiner.h" +#include "src/writer/spirv/builder.h" +#include "src/writer/spirv/spv_dump.h" + +namespace tint { +namespace writer { +namespace spirv { +namespace { + +using BuilderTest = testing::Test; + +TEST_F(BuilderTest, Discard) { + ast::DiscardStatement expr; + + ast::Module mod; + Builder b(&mod); + b.push_function(Function{}); + EXPECT_EQ(b.GenerateStatement(&expr), 1u) << b.error(); + EXPECT_EQ(DumpInstructions(b.functions()[0].instructions()), R"(OpKill +)"); +} + +} // namespace +} // namespace spirv +} // namespace writer +} // namespace tint