[ast][spirv-writer][hlsl-writer][wgsl-writer] Add workgroup_size decoration
This CL adds the workgroup_size decoration to functions and emits as needed from the various backends. Change-Id: Ifffde239e68047f6419c6980eca70c4efa9822c0 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/28662 Reviewed-by: Sarah Mashayekhi <sarahmashay@google.com> Commit-Queue: dan sinclair <dsinclair@chromium.org>
This commit is contained in:
parent
35552f2a48
commit
643827967e
3
BUILD.gn
3
BUILD.gn
|
@ -369,6 +369,8 @@ source_set("libtint_core_src") {
|
||||||
"src/ast/variable_decl_statement.h",
|
"src/ast/variable_decl_statement.h",
|
||||||
"src/ast/variable_decoration.cc",
|
"src/ast/variable_decoration.cc",
|
||||||
"src/ast/variable_decoration.h",
|
"src/ast/variable_decoration.h",
|
||||||
|
"src/ast/workgroup_decoration.cc",
|
||||||
|
"src/ast/workgroup_decoration.h",
|
||||||
"src/context.cc",
|
"src/context.cc",
|
||||||
"src/context.h",
|
"src/context.h",
|
||||||
"src/reader/reader.cc",
|
"src/reader/reader.cc",
|
||||||
|
@ -744,6 +746,7 @@ source_set("tint_unittests_core_src") {
|
||||||
"src/ast/unary_op_expression_test.cc",
|
"src/ast/unary_op_expression_test.cc",
|
||||||
"src/ast/variable_decl_statement_test.cc",
|
"src/ast/variable_decl_statement_test.cc",
|
||||||
"src/ast/variable_test.cc",
|
"src/ast/variable_test.cc",
|
||||||
|
"src/ast/workgroup_decoration_test.cc",
|
||||||
"src/scope_stack_test.cc",
|
"src/scope_stack_test.cc",
|
||||||
"src/type_determiner_test.cc",
|
"src/type_determiner_test.cc",
|
||||||
"src/type_manager_test.cc",
|
"src/type_manager_test.cc",
|
||||||
|
|
|
@ -190,6 +190,8 @@ set(TINT_LIB_SRCS
|
||||||
ast/variable_decoration.h
|
ast/variable_decoration.h
|
||||||
ast/variable_decl_statement.cc
|
ast/variable_decl_statement.cc
|
||||||
ast/variable_decl_statement.h
|
ast/variable_decl_statement.h
|
||||||
|
ast/workgroup_decoration.cc
|
||||||
|
ast/workgroup_decoration.h
|
||||||
context.h
|
context.h
|
||||||
context.cc
|
context.cc
|
||||||
reader/reader.cc
|
reader/reader.cc
|
||||||
|
@ -354,6 +356,7 @@ set(TINT_TEST_SRCS
|
||||||
ast/unary_op_expression_test.cc
|
ast/unary_op_expression_test.cc
|
||||||
ast/variable_decl_statement_test.cc
|
ast/variable_decl_statement_test.cc
|
||||||
ast/variable_test.cc
|
ast/variable_test.cc
|
||||||
|
ast/workgroup_decoration_test.cc
|
||||||
scope_stack_test.cc
|
scope_stack_test.cc
|
||||||
type_determiner_test.cc
|
type_determiner_test.cc
|
||||||
type_manager_test.cc
|
type_manager_test.cc
|
||||||
|
|
|
@ -17,6 +17,7 @@
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
#include "src/ast/decorated_variable.h"
|
#include "src/ast/decorated_variable.h"
|
||||||
|
#include "src/ast/workgroup_decoration.h"
|
||||||
|
|
||||||
namespace tint {
|
namespace tint {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
|
@ -46,6 +47,15 @@ Function::Function(Function&&) = default;
|
||||||
|
|
||||||
Function::~Function() = default;
|
Function::~Function() = default;
|
||||||
|
|
||||||
|
std::tuple<uint32_t, uint32_t, uint32_t> Function::workgroup_size() const {
|
||||||
|
for (const auto& deco : decorations_) {
|
||||||
|
if (deco->IsWorkgroup()) {
|
||||||
|
return deco->AsWorkgroup()->values();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {1, 1, 1};
|
||||||
|
}
|
||||||
|
|
||||||
void Function::add_referenced_module_variable(Variable* var) {
|
void Function::add_referenced_module_variable(Variable* var) {
|
||||||
for (const auto* v : referenced_module_vars_) {
|
for (const auto* v : referenced_module_vars_) {
|
||||||
if (v->name() == var->name()) {
|
if (v->name() == var->name()) {
|
||||||
|
|
|
@ -90,6 +90,10 @@ class Function : public Node {
|
||||||
/// @returns the decorations attached to this function
|
/// @returns the decorations attached to this function
|
||||||
const FunctionDecorationList& decorations() const { return decorations_; }
|
const FunctionDecorationList& decorations() const { return decorations_; }
|
||||||
|
|
||||||
|
/// @returns the workgroup size {x, y, z} for the function. {1, 1, 1} will be
|
||||||
|
/// return if no workgroup size was set.
|
||||||
|
std::tuple<uint32_t, uint32_t, uint32_t> workgroup_size() const;
|
||||||
|
|
||||||
/// Adds the given variable to the list of referenced module variables if it
|
/// Adds the given variable to the list of referenced module variables if it
|
||||||
/// is not already included.
|
/// is not already included.
|
||||||
/// @param var the module variable to add
|
/// @param var the module variable to add
|
||||||
|
|
|
@ -14,6 +14,10 @@
|
||||||
|
|
||||||
#include "src/ast/function_decoration.h"
|
#include "src/ast/function_decoration.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
#include "src/ast/workgroup_decoration.h"
|
||||||
|
|
||||||
namespace tint {
|
namespace tint {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
|
|
||||||
|
@ -21,5 +25,14 @@ FunctionDecoration::FunctionDecoration() = default;
|
||||||
|
|
||||||
FunctionDecoration::~FunctionDecoration() = default;
|
FunctionDecoration::~FunctionDecoration() = default;
|
||||||
|
|
||||||
|
bool FunctionDecoration::IsWorkgroup() const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
const WorkgroupDecoration* FunctionDecoration::AsWorkgroup() const {
|
||||||
|
assert(IsWorkgroup());
|
||||||
|
return static_cast<const WorkgroupDecoration*>(this);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace ast
|
} // namespace ast
|
||||||
} // namespace tint
|
} // namespace tint
|
||||||
|
|
|
@ -22,11 +22,19 @@
|
||||||
namespace tint {
|
namespace tint {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
|
|
||||||
|
class WorkgroupDecoration;
|
||||||
|
|
||||||
/// A decoration attached to a function
|
/// A decoration attached to a function
|
||||||
class FunctionDecoration {
|
class FunctionDecoration {
|
||||||
public:
|
public:
|
||||||
virtual ~FunctionDecoration();
|
virtual ~FunctionDecoration();
|
||||||
|
|
||||||
|
/// @returns true if this is a workgroup decoration
|
||||||
|
virtual bool IsWorkgroup() const;
|
||||||
|
|
||||||
|
/// @returns the decoration as a workgroup decoration
|
||||||
|
const WorkgroupDecoration* AsWorkgroup() const;
|
||||||
|
|
||||||
/// Outputs the function decoration to the given stream
|
/// Outputs the function decoration to the given stream
|
||||||
/// @param out the stream to output too
|
/// @param out the stream to output too
|
||||||
virtual void to_str(std::ostream& out) const = 0;
|
virtual void to_str(std::ostream& out) const = 0;
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
#include "src/ast/type/i32_type.h"
|
#include "src/ast/type/i32_type.h"
|
||||||
#include "src/ast/type/void_type.h"
|
#include "src/ast/type/void_type.h"
|
||||||
#include "src/ast/variable.h"
|
#include "src/ast/variable.h"
|
||||||
// #include "src/ast/workgroup_decoration.h"
|
#include "src/ast/workgroup_decoration.h"
|
||||||
|
|
||||||
namespace tint {
|
namespace tint {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
|
@ -298,27 +298,27 @@ TEST_F(FunctionTest, ToStr) {
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
// TEST_F(FunctionTest, ToStr_WithDecoration) {
|
TEST_F(FunctionTest, ToStr_WithDecoration) {
|
||||||
// type::VoidType void_type;
|
type::VoidType void_type;
|
||||||
// type::I32Type i32;
|
type::I32Type i32;
|
||||||
|
|
||||||
// auto block = std::make_unique<ast::BlockStatement>();
|
auto block = std::make_unique<ast::BlockStatement>();
|
||||||
// block->append(std::make_unique<DiscardStatement>());
|
block->append(std::make_unique<DiscardStatement>());
|
||||||
|
|
||||||
// Function f("func", {}, &void_type);
|
Function f("func", {}, &void_type);
|
||||||
// f.set_body(std::move(block));
|
f.set_body(std::move(block));
|
||||||
// f.add_decoration(std::make_unique<WorkgroupDecoration>(2, 4, 6));
|
f.add_decoration(std::make_unique<WorkgroupDecoration>(2, 4, 6));
|
||||||
|
|
||||||
// std::ostringstream out;
|
std::ostringstream out;
|
||||||
// f.to_str(out, 2);
|
f.to_str(out, 2);
|
||||||
// EXPECT_EQ(out.str(), R"( Function func -> __void
|
EXPECT_EQ(out.str(), R"( Function func -> __void
|
||||||
// workgroup_size 2 4 6
|
WorkgroupDecoration{2 4 6}
|
||||||
// ()
|
()
|
||||||
// {
|
{
|
||||||
// Discard{}
|
Discard{}
|
||||||
// }
|
}
|
||||||
// )");
|
)");
|
||||||
// }
|
}
|
||||||
|
|
||||||
TEST_F(FunctionTest, ToStr_WithParams) {
|
TEST_F(FunctionTest, ToStr_WithParams) {
|
||||||
type::VoidType void_type;
|
type::VoidType void_type;
|
||||||
|
@ -396,6 +396,33 @@ TEST_F(FunctionTest, GetLastStatement_nullptr) {
|
||||||
|
|
||||||
EXPECT_EQ(f.get_last_statement(), nullptr);
|
EXPECT_EQ(f.get_last_statement(), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(FunctionTest, WorkgroupSize_NoneSet) {
|
||||||
|
type::VoidType void_type;
|
||||||
|
Function f("f", {}, &void_type);
|
||||||
|
uint32_t x = 0;
|
||||||
|
uint32_t y = 0;
|
||||||
|
uint32_t z = 0;
|
||||||
|
std::tie(x, y, z) = f.workgroup_size();
|
||||||
|
EXPECT_EQ(x, 1u);
|
||||||
|
EXPECT_EQ(y, 1u);
|
||||||
|
EXPECT_EQ(z, 1u);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(FunctionTest, WorkgroupSize) {
|
||||||
|
type::VoidType void_type;
|
||||||
|
Function f("f", {}, &void_type);
|
||||||
|
f.add_decoration(std::make_unique<WorkgroupDecoration>(2u, 4u, 6u));
|
||||||
|
|
||||||
|
uint32_t x = 0;
|
||||||
|
uint32_t y = 0;
|
||||||
|
uint32_t z = 0;
|
||||||
|
std::tie(x, y, z) = f.workgroup_size();
|
||||||
|
EXPECT_EQ(x, 2u);
|
||||||
|
EXPECT_EQ(y, 4u);
|
||||||
|
EXPECT_EQ(z, 6u);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace ast
|
} // namespace ast
|
||||||
} // namespace tint
|
} // namespace tint
|
||||||
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
// 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 "src/ast/workgroup_decoration.h"
|
||||||
|
|
||||||
|
namespace tint {
|
||||||
|
namespace ast {
|
||||||
|
|
||||||
|
WorkgroupDecoration::WorkgroupDecoration(uint32_t x) : x_(x) {}
|
||||||
|
|
||||||
|
WorkgroupDecoration::WorkgroupDecoration(uint32_t x, uint32_t y)
|
||||||
|
: x_(x), y_(y) {}
|
||||||
|
|
||||||
|
WorkgroupDecoration::WorkgroupDecoration(uint32_t x, uint32_t y, uint32_t z)
|
||||||
|
: x_(x), y_(y), z_(z) {}
|
||||||
|
|
||||||
|
WorkgroupDecoration::~WorkgroupDecoration() = default;
|
||||||
|
|
||||||
|
bool WorkgroupDecoration::IsWorkgroup() const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorkgroupDecoration::to_str(std::ostream& out) const {
|
||||||
|
out << "WorkgroupDecoration{" << x_ << " " << y_ << " " << z_ << "}"
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace ast
|
||||||
|
} // namespace tint
|
|
@ -0,0 +1,65 @@
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
#ifndef SRC_AST_WORKGROUP_DECORATION_H_
|
||||||
|
#define SRC_AST_WORKGROUP_DECORATION_H_
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
#include "src/ast/function_decoration.h"
|
||||||
|
|
||||||
|
namespace tint {
|
||||||
|
namespace ast {
|
||||||
|
|
||||||
|
/// A workgroup decoration
|
||||||
|
class WorkgroupDecoration : public FunctionDecoration {
|
||||||
|
public:
|
||||||
|
/// constructor
|
||||||
|
/// @param x the workgroup x dimension size
|
||||||
|
explicit WorkgroupDecoration(uint32_t x);
|
||||||
|
/// constructor
|
||||||
|
/// @param x the workgroup x dimension size
|
||||||
|
/// @param y the workgroup x dimension size
|
||||||
|
WorkgroupDecoration(uint32_t x, uint32_t y);
|
||||||
|
/// constructor
|
||||||
|
/// @param x the workgroup x dimension size
|
||||||
|
/// @param y the workgroup x dimension size
|
||||||
|
/// @param z the workgroup x dimension size
|
||||||
|
WorkgroupDecoration(uint32_t x, uint32_t y, uint32_t z);
|
||||||
|
~WorkgroupDecoration() override;
|
||||||
|
|
||||||
|
/// @returns true if this is a workgroup decoration
|
||||||
|
bool IsWorkgroup() const override;
|
||||||
|
|
||||||
|
/// @returns the workgroup dimensions
|
||||||
|
std::tuple<uint32_t, uint32_t, uint32_t> values() const {
|
||||||
|
return {x_, y_, z_};
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Outputs the decoration to the given stream
|
||||||
|
/// @param out the stream to output too
|
||||||
|
void to_str(std::ostream& out) const override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
uint32_t x_ = 1;
|
||||||
|
uint32_t y_ = 1;
|
||||||
|
uint32_t z_ = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace ast
|
||||||
|
} // namespace tint
|
||||||
|
|
||||||
|
#endif // SRC_AST_WORKGROUP_DECORATION_H_
|
|
@ -0,0 +1,74 @@
|
||||||
|
// 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 "src/ast/workgroup_decoration.h"
|
||||||
|
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
|
||||||
|
namespace tint {
|
||||||
|
namespace ast {
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
using WorkgroupDecorationTest = testing::Test;
|
||||||
|
|
||||||
|
TEST_F(WorkgroupDecorationTest, Creation_1param) {
|
||||||
|
WorkgroupDecoration d{2};
|
||||||
|
uint32_t x = 0;
|
||||||
|
uint32_t y = 0;
|
||||||
|
uint32_t z = 0;
|
||||||
|
std::tie(x, y, z) = d.values();
|
||||||
|
EXPECT_EQ(x, 2u);
|
||||||
|
EXPECT_EQ(y, 1u);
|
||||||
|
EXPECT_EQ(z, 1u);
|
||||||
|
}
|
||||||
|
TEST_F(WorkgroupDecorationTest, Creation_2param) {
|
||||||
|
WorkgroupDecoration d{2, 4};
|
||||||
|
uint32_t x = 0;
|
||||||
|
uint32_t y = 0;
|
||||||
|
uint32_t z = 0;
|
||||||
|
std::tie(x, y, z) = d.values();
|
||||||
|
EXPECT_EQ(x, 2u);
|
||||||
|
EXPECT_EQ(y, 4u);
|
||||||
|
EXPECT_EQ(z, 1u);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(WorkgroupDecorationTest, Creation_3param) {
|
||||||
|
WorkgroupDecoration d{2, 4, 6};
|
||||||
|
uint32_t x = 0;
|
||||||
|
uint32_t y = 0;
|
||||||
|
uint32_t z = 0;
|
||||||
|
std::tie(x, y, z) = d.values();
|
||||||
|
EXPECT_EQ(x, 2u);
|
||||||
|
EXPECT_EQ(y, 4u);
|
||||||
|
EXPECT_EQ(z, 6u);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(WorkgroupDecorationTest, Is) {
|
||||||
|
WorkgroupDecoration d{2, 4, 6};
|
||||||
|
EXPECT_TRUE(d.IsWorkgroup());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(WorkgroupDecorationTest, ToStr) {
|
||||||
|
WorkgroupDecoration d{2, 4, 6};
|
||||||
|
std::ostringstream out;
|
||||||
|
d.to_str(out);
|
||||||
|
EXPECT_EQ(out.str(), R"(WorkgroupDecoration{2 4 6}
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
} // namespace ast
|
||||||
|
} // namespace tint
|
|
@ -1428,9 +1428,12 @@ bool GeneratorImpl::EmitEntryPointFunction(std::ostream& out,
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ep->stage() == ast::PipelineStage::kCompute) {
|
if (ep->stage() == ast::PipelineStage::kCompute) {
|
||||||
// TODO(dsinclair): When we have a way to set the thread group size this
|
uint32_t x = 0;
|
||||||
// should be updated.
|
uint32_t y = 0;
|
||||||
out << "[numthreads(1, 1, 1)]" << std::endl;
|
uint32_t z = 0;
|
||||||
|
std::tie(x, y, z) = func->workgroup_size();
|
||||||
|
out << "[numthreads(" << std::to_string(x) << ", " << std::to_string(y)
|
||||||
|
<< ", " << std::to_string(z) << ")]" << std::endl;
|
||||||
make_indent(out);
|
make_indent(out);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
#include "src/ast/type/void_type.h"
|
#include "src/ast/type/void_type.h"
|
||||||
#include "src/ast/variable.h"
|
#include "src/ast/variable.h"
|
||||||
#include "src/ast/variable_decl_statement.h"
|
#include "src/ast/variable_decl_statement.h"
|
||||||
|
#include "src/ast/workgroup_decoration.h"
|
||||||
#include "src/context.h"
|
#include "src/context.h"
|
||||||
#include "src/type_determiner.h"
|
#include "src/type_determiner.h"
|
||||||
#include "src/writer/hlsl/test_helper.h"
|
#include "src/writer/hlsl/test_helper.h"
|
||||||
|
@ -1223,6 +1224,35 @@ void main() {
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(HlslGeneratorImplTest_Function,
|
||||||
|
Emit_Function_EntryPoint_Compute_WithWorkgroup) {
|
||||||
|
ast::type::VoidType void_type;
|
||||||
|
|
||||||
|
ast::VariableList params;
|
||||||
|
auto func = std::make_unique<ast::Function>("comp_main", std::move(params),
|
||||||
|
&void_type);
|
||||||
|
func->add_decoration(std::make_unique<ast::WorkgroupDecoration>(2u, 4u, 6u));
|
||||||
|
|
||||||
|
auto body = std::make_unique<ast::BlockStatement>();
|
||||||
|
body->append(std::make_unique<ast::ReturnStatement>());
|
||||||
|
func->set_body(std::move(body));
|
||||||
|
|
||||||
|
mod()->AddFunction(std::move(func));
|
||||||
|
|
||||||
|
auto ep = std::make_unique<ast::EntryPoint>(ast::PipelineStage::kCompute,
|
||||||
|
"main", "comp_main");
|
||||||
|
mod()->AddEntryPoint(std::move(ep));
|
||||||
|
|
||||||
|
ASSERT_TRUE(td().Determine()) << td().error();
|
||||||
|
ASSERT_TRUE(gen().Generate(out())) << gen().error();
|
||||||
|
EXPECT_EQ(result(), R"([numthreads(2, 4, 6)]
|
||||||
|
void main() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(HlslGeneratorImplTest_Function, Emit_Function_WithArrayParams) {
|
TEST_F(HlslGeneratorImplTest_Function, Emit_Function_WithArrayParams) {
|
||||||
ast::type::F32Type f32;
|
ast::type::F32Type f32;
|
||||||
ast::type::ArrayType ary(&f32, 5);
|
ast::type::ArrayType ary(&f32, 5);
|
||||||
|
|
|
@ -359,10 +359,15 @@ bool Builder::GenerateExecutionModes(ast::EntryPoint* ep) {
|
||||||
spv::Op::OpExecutionMode,
|
spv::Op::OpExecutionMode,
|
||||||
{Operand::Int(id), Operand::Int(SpvExecutionModeOriginUpperLeft)});
|
{Operand::Int(id), Operand::Int(SpvExecutionModeOriginUpperLeft)});
|
||||||
} else if (ep->stage() == ast::PipelineStage::kCompute) {
|
} else if (ep->stage() == ast::PipelineStage::kCompute) {
|
||||||
// TODO(dsinclair): Support LocalSize other then (1, 1, 1)
|
auto* func = func_name_to_func_[ep->function_name()];
|
||||||
|
|
||||||
|
uint32_t x = 0;
|
||||||
|
uint32_t y = 0;
|
||||||
|
uint32_t z = 0;
|
||||||
|
std::tie(x, y, z) = func->workgroup_size();
|
||||||
push_preamble(spv::Op::OpExecutionMode,
|
push_preamble(spv::Op::OpExecutionMode,
|
||||||
{Operand::Int(id), Operand::Int(SpvExecutionModeLocalSize),
|
{Operand::Int(id), Operand::Int(SpvExecutionModeLocalSize),
|
||||||
Operand::Int(1), Operand::Int(1), Operand::Int(1)});
|
Operand::Int(x), Operand::Int(y), Operand::Int(z)});
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "src/ast/type/f32_type.h"
|
#include "src/ast/type/f32_type.h"
|
||||||
#include "src/ast/type/void_type.h"
|
#include "src/ast/type/void_type.h"
|
||||||
#include "src/ast/variable.h"
|
#include "src/ast/variable.h"
|
||||||
|
#include "src/ast/workgroup_decoration.h"
|
||||||
#include "src/context.h"
|
#include "src/context.h"
|
||||||
#include "src/type_determiner.h"
|
#include "src/type_determiner.h"
|
||||||
#include "src/writer/spirv/builder.h"
|
#include "src/writer/spirv/builder.h"
|
||||||
|
@ -264,6 +265,23 @@ TEST_F(BuilderTest, ExecutionModel_Compute_LocalSize) {
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(BuilderTest, ExecutionModel_Compute_LocalSize_WithWorkgroup) {
|
||||||
|
ast::type::VoidType void_type;
|
||||||
|
|
||||||
|
ast::Function func("main", {}, &void_type);
|
||||||
|
func.add_decoration(std::make_unique<ast::WorkgroupDecoration>(2u, 4u, 6u));
|
||||||
|
ast::EntryPoint ep(ast::PipelineStage::kCompute, "main", "main");
|
||||||
|
|
||||||
|
ast::Module mod;
|
||||||
|
Builder b(&mod);
|
||||||
|
ASSERT_TRUE(b.GenerateFunction(&func)) << b.error();
|
||||||
|
ASSERT_TRUE(b.GenerateExecutionModes(&ep));
|
||||||
|
|
||||||
|
EXPECT_EQ(DumpInstructions(b.preamble()),
|
||||||
|
R"(OpExecutionMode %3 LocalSize 2 4 6
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace spirv
|
} // namespace spirv
|
||||||
} // namespace writer
|
} // namespace writer
|
||||||
|
|
|
@ -63,6 +63,7 @@
|
||||||
#include "src/ast/uint_literal.h"
|
#include "src/ast/uint_literal.h"
|
||||||
#include "src/ast/unary_op_expression.h"
|
#include "src/ast/unary_op_expression.h"
|
||||||
#include "src/ast/variable_decl_statement.h"
|
#include "src/ast/variable_decl_statement.h"
|
||||||
|
#include "src/ast/workgroup_decoration.h"
|
||||||
|
|
||||||
namespace tint {
|
namespace tint {
|
||||||
namespace writer {
|
namespace writer {
|
||||||
|
@ -422,8 +423,21 @@ bool GeneratorImpl::EmitImport(const ast::Import* import) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GeneratorImpl::EmitFunction(ast::Function* func) {
|
bool GeneratorImpl::EmitFunction(ast::Function* func) {
|
||||||
|
for (auto& deco : func->decorations()) {
|
||||||
make_indent();
|
make_indent();
|
||||||
|
out_ << "[[";
|
||||||
|
if (deco->IsWorkgroup()) {
|
||||||
|
uint32_t x = 0;
|
||||||
|
uint32_t y = 0;
|
||||||
|
uint32_t z = 0;
|
||||||
|
std::tie(x, y, z) = deco->AsWorkgroup()->values();
|
||||||
|
out_ << "workgroup_size(" << std::to_string(x) << ", "
|
||||||
|
<< std::to_string(y) << ", " << std::to_string(z) << ")";
|
||||||
|
}
|
||||||
|
out_ << "]]" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
make_indent();
|
||||||
out_ << "fn " << func->name() << "(";
|
out_ << "fn " << func->name() << "(";
|
||||||
|
|
||||||
bool first = true;
|
bool first = true;
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "src/ast/type/i32_type.h"
|
#include "src/ast/type/i32_type.h"
|
||||||
#include "src/ast/type/void_type.h"
|
#include "src/ast/type/void_type.h"
|
||||||
#include "src/ast/variable.h"
|
#include "src/ast/variable.h"
|
||||||
|
#include "src/ast/workgroup_decoration.h"
|
||||||
#include "src/writer/wgsl/generator_impl.h"
|
#include "src/writer/wgsl/generator_impl.h"
|
||||||
|
|
||||||
namespace tint {
|
namespace tint {
|
||||||
|
@ -77,6 +78,28 @@ TEST_F(WgslGeneratorImplTest, Emit_Function_WithParams) {
|
||||||
)");
|
)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(WgslGeneratorImplTest, Emit_Function_WithDecorations) {
|
||||||
|
auto body = std::make_unique<ast::BlockStatement>();
|
||||||
|
body->append(std::make_unique<ast::DiscardStatement>());
|
||||||
|
body->append(std::make_unique<ast::ReturnStatement>());
|
||||||
|
|
||||||
|
ast::type::VoidType void_type;
|
||||||
|
ast::Function func("my_func", {}, &void_type);
|
||||||
|
func.add_decoration(std::make_unique<ast::WorkgroupDecoration>(2u, 4u, 6u));
|
||||||
|
func.set_body(std::move(body));
|
||||||
|
|
||||||
|
GeneratorImpl g;
|
||||||
|
g.increment_indent();
|
||||||
|
|
||||||
|
ASSERT_TRUE(g.EmitFunction(&func));
|
||||||
|
EXPECT_EQ(g.result(), R"( [[workgroup_size(2, 4, 6)]]
|
||||||
|
fn my_func() -> void {
|
||||||
|
discard;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace wgsl
|
} // namespace wgsl
|
||||||
} // namespace writer
|
} // namespace writer
|
||||||
|
|
Loading…
Reference in New Issue