resolver: Track global uses in function decorations
Fixed: tint:1320 Change-Id: Ib92c37d4de0641d11e508be4d8e05d641e808be9 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/70662 Reviewed-by: James Price <jrprice@google.com> Reviewed-by: David Neto <dneto@google.com> Kokoro: Kokoro <noreply+kokoro@google.com> Commit-Queue: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
b05e185a36
commit
d1f0a14563
|
@ -16,6 +16,10 @@
|
||||||
* The `dot()` builtin now supports integer vector types.
|
* The `dot()` builtin now supports integer vector types.
|
||||||
* Identifiers can now start with a single leading underscore. [tint:1292](https://crbug.com/tint/1292)
|
* Identifiers can now start with a single leading underscore. [tint:1292](https://crbug.com/tint/1292)
|
||||||
|
|
||||||
|
### Fixes
|
||||||
|
|
||||||
|
* Fixed an issue where using a module-scoped `let` in a `workgroup_size` may result in a compilation error. [tint:1320](https://crbug.com/tint/1320)
|
||||||
|
|
||||||
## Changes for M97
|
## Changes for M97
|
||||||
|
|
||||||
### Breaking Changes
|
### Breaking Changes
|
||||||
|
|
|
@ -427,15 +427,26 @@ TEST_F(ResolverFunctionValidationTest, FunctionParamsConst) {
|
||||||
TEST_F(ResolverFunctionValidationTest, WorkgroupSize_GoodType_ConstU32) {
|
TEST_F(ResolverFunctionValidationTest, WorkgroupSize_GoodType_ConstU32) {
|
||||||
// let x = 4u;
|
// let x = 4u;
|
||||||
// let x = 8u;
|
// let x = 8u;
|
||||||
// [[stage(compute), workgroup_size(x, y, 16u]
|
// [[stage(compute), workgroup_size(x, y, 16u)]]
|
||||||
// fn main() {}
|
// fn main() {}
|
||||||
GlobalConst("x", ty.u32(), Expr(4u));
|
auto* x = GlobalConst("x", ty.u32(), Expr(4u));
|
||||||
GlobalConst("y", ty.u32(), Expr(8u));
|
auto* y = GlobalConst("y", ty.u32(), Expr(8u));
|
||||||
Func("main", {}, ty.void_(), {},
|
auto* func = Func("main", {}, ty.void_(), {},
|
||||||
{Stage(ast::PipelineStage::kCompute),
|
{Stage(ast::PipelineStage::kCompute),
|
||||||
WorkgroupSize(Expr("x"), Expr("y"), Expr(16u))});
|
WorkgroupSize(Expr("x"), Expr("y"), Expr(16u))});
|
||||||
|
|
||||||
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
ASSERT_TRUE(r()->Resolve()) << r()->error();
|
||||||
|
|
||||||
|
auto* sem_func = Sem().Get(func);
|
||||||
|
auto* sem_x = Sem().Get<sem::GlobalVariable>(x);
|
||||||
|
auto* sem_y = Sem().Get<sem::GlobalVariable>(y);
|
||||||
|
|
||||||
|
ASSERT_NE(sem_func, nullptr);
|
||||||
|
ASSERT_NE(sem_x, nullptr);
|
||||||
|
ASSERT_NE(sem_y, nullptr);
|
||||||
|
|
||||||
|
EXPECT_TRUE(sem_func->DirectlyReferencedGlobals().contains(sem_x));
|
||||||
|
EXPECT_TRUE(sem_func->DirectlyReferencedGlobals().contains(sem_y));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(ResolverFunctionValidationTest, WorkgroupSize_GoodType_U32) {
|
TEST_F(ResolverFunctionValidationTest, WorkgroupSize_GoodType_U32) {
|
||||||
|
|
|
@ -634,21 +634,19 @@ sem::Function* Resolver::Function(const ast::Function* decl) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sem::WorkgroupSize ws{};
|
auto* func = builder_->create<sem::Function>(decl, return_type, parameters);
|
||||||
if (!WorkgroupSizeFor(decl, ws)) {
|
builder_->Sem().Add(decl, func);
|
||||||
|
|
||||||
|
TINT_SCOPED_ASSIGNMENT(current_function_, func);
|
||||||
|
|
||||||
|
if (!WorkgroupSize(decl)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto* func =
|
|
||||||
builder_->create<sem::Function>(decl, return_type, parameters, ws);
|
|
||||||
builder_->Sem().Add(decl, func);
|
|
||||||
|
|
||||||
if (decl->IsEntryPoint()) {
|
if (decl->IsEntryPoint()) {
|
||||||
entry_points_.emplace_back(func);
|
entry_points_.emplace_back(func);
|
||||||
}
|
}
|
||||||
|
|
||||||
TINT_SCOPED_ASSIGNMENT(current_function_, func);
|
|
||||||
|
|
||||||
if (decl->body) {
|
if (decl->body) {
|
||||||
Mark(decl->body);
|
Mark(decl->body);
|
||||||
if (current_compound_statement_) {
|
if (current_compound_statement_) {
|
||||||
|
@ -692,9 +690,9 @@ sem::Function* Resolver::Function(const ast::Function* decl) {
|
||||||
return func;
|
return func;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Resolver::WorkgroupSizeFor(const ast::Function* func,
|
bool Resolver::WorkgroupSize(const ast::Function* func) {
|
||||||
sem::WorkgroupSize& ws) {
|
|
||||||
// Set work-group size defaults.
|
// Set work-group size defaults.
|
||||||
|
sem::WorkgroupSize ws;
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
ws[i].value = 1;
|
ws[i].value = 1;
|
||||||
ws[i].overridable_const = nullptr;
|
ws[i].overridable_const = nullptr;
|
||||||
|
@ -790,6 +788,8 @@ bool Resolver::WorkgroupSizeFor(const ast::Function* func,
|
||||||
ws[i].value = is_i32 ? static_cast<uint32_t>(value.Elements()[0].i32)
|
ws[i].value = is_i32 ? static_cast<uint32_t>(value.Elements()[0].i32)
|
||||||
: value.Elements()[0].u32;
|
: value.Elements()[0].u32;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
current_function_->SetWorkgroupSize(std::move(ws));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -282,8 +282,9 @@ class Resolver {
|
||||||
bool IsValidationEnabled(const ast::DecorationList& decorations,
|
bool IsValidationEnabled(const ast::DecorationList& decorations,
|
||||||
ast::DisabledValidation validation) const;
|
ast::DisabledValidation validation) const;
|
||||||
|
|
||||||
/// Resolves the WorkgroupSize for the given function
|
/// Resolves the WorkgroupSize for the given function, assigning it to
|
||||||
bool WorkgroupSizeFor(const ast::Function*, sem::WorkgroupSize& ws);
|
/// current_function_
|
||||||
|
bool WorkgroupSize(const ast::Function*);
|
||||||
|
|
||||||
/// @returns the sem::Type for the ast::Type `ty`, building it if it
|
/// @returns the sem::Type for the ast::Type `ty`, building it if it
|
||||||
/// hasn't been constructed already. If an error is raised, nullptr is
|
/// hasn't been constructed already. If an error is raised, nullptr is
|
||||||
|
|
|
@ -30,11 +30,11 @@ namespace sem {
|
||||||
|
|
||||||
Function::Function(const ast::Function* declaration,
|
Function::Function(const ast::Function* declaration,
|
||||||
Type* return_type,
|
Type* return_type,
|
||||||
std::vector<Parameter*> parameters,
|
std::vector<Parameter*> parameters)
|
||||||
sem::WorkgroupSize workgroup_size)
|
|
||||||
: Base(return_type, utils::ToConstPtrVec(parameters)),
|
: Base(return_type, utils::ToConstPtrVec(parameters)),
|
||||||
declaration_(declaration),
|
declaration_(declaration),
|
||||||
workgroup_size_(std::move(workgroup_size)) {
|
workgroup_size_{WorkgroupDimension{1}, WorkgroupDimension{1},
|
||||||
|
WorkgroupDimension{1}} {
|
||||||
for (auto* parameter : parameters) {
|
for (auto* parameter : parameters) {
|
||||||
parameter->SetOwner(this);
|
parameter->SetOwner(this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,11 +62,9 @@ class Function : public Castable<Function, CallTarget> {
|
||||||
/// @param declaration the ast::Function
|
/// @param declaration the ast::Function
|
||||||
/// @param return_type the return type of the function
|
/// @param return_type the return type of the function
|
||||||
/// @param parameters the parameters to the function
|
/// @param parameters the parameters to the function
|
||||||
/// @param workgroup_size the workgroup size
|
|
||||||
Function(const ast::Function* declaration,
|
Function(const ast::Function* declaration,
|
||||||
Type* return_type,
|
Type* return_type,
|
||||||
std::vector<Parameter*> parameters,
|
std::vector<Parameter*> parameters);
|
||||||
sem::WorkgroupSize workgroup_size);
|
|
||||||
|
|
||||||
/// Destructor
|
/// Destructor
|
||||||
~Function() override;
|
~Function() override;
|
||||||
|
@ -77,6 +75,12 @@ class Function : public Castable<Function, CallTarget> {
|
||||||
/// @returns the workgroup size {x, y, z} for the function.
|
/// @returns the workgroup size {x, y, z} for the function.
|
||||||
const sem::WorkgroupSize& WorkgroupSize() const { return workgroup_size_; }
|
const sem::WorkgroupSize& WorkgroupSize() const { return workgroup_size_; }
|
||||||
|
|
||||||
|
/// Sets the workgroup size {x, y, z} for the function.
|
||||||
|
/// @param workgroup_size the new workgroup size of the function
|
||||||
|
void SetWorkgroupSize(sem::WorkgroupSize workgroup_size) {
|
||||||
|
workgroup_size_ = std::move(workgroup_size);
|
||||||
|
}
|
||||||
|
|
||||||
/// @returns all directly referenced global variables
|
/// @returns all directly referenced global variables
|
||||||
const utils::UniqueVector<const GlobalVariable*>& DirectlyReferencedGlobals()
|
const utils::UniqueVector<const GlobalVariable*>& DirectlyReferencedGlobals()
|
||||||
const {
|
const {
|
||||||
|
@ -243,8 +247,8 @@ class Function : public Castable<Function, CallTarget> {
|
||||||
bool multisampled) const;
|
bool multisampled) const;
|
||||||
|
|
||||||
const ast::Function* const declaration_;
|
const ast::Function* const declaration_;
|
||||||
const sem::WorkgroupSize workgroup_size_;
|
|
||||||
|
|
||||||
|
sem::WorkgroupSize workgroup_size_;
|
||||||
utils::UniqueVector<const GlobalVariable*> directly_referenced_globals_;
|
utils::UniqueVector<const GlobalVariable*> directly_referenced_globals_;
|
||||||
utils::UniqueVector<const GlobalVariable*> transitively_referenced_globals_;
|
utils::UniqueVector<const GlobalVariable*> transitively_referenced_globals_;
|
||||||
utils::UniqueVector<const Function*> transitively_called_functions_;
|
utils::UniqueVector<const Function*> transitively_called_functions_;
|
||||||
|
|
|
@ -236,6 +236,26 @@ fn comp_main1() {
|
||||||
EXPECT_EQ(expect, str(got));
|
EXPECT_EQ(expect, str(got));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(SingleEntryPointTest, WorkgroupSizeLetPreserved) {
|
||||||
|
auto* src = R"(
|
||||||
|
let size : i32 = 1;
|
||||||
|
|
||||||
|
[[stage(compute), workgroup_size(size)]]
|
||||||
|
fn main() {
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
auto* expect = src;
|
||||||
|
|
||||||
|
SingleEntryPoint::Config cfg("main");
|
||||||
|
|
||||||
|
DataMap data;
|
||||||
|
data.Add<SingleEntryPoint::Config>(cfg);
|
||||||
|
auto got = Run<SingleEntryPoint>(src, data);
|
||||||
|
|
||||||
|
EXPECT_EQ(expect, str(got));
|
||||||
|
}
|
||||||
|
|
||||||
TEST_F(SingleEntryPointTest, OverridableConstants) {
|
TEST_F(SingleEntryPointTest, OverridableConstants) {
|
||||||
auto* src = R"(
|
auto* src = R"(
|
||||||
[[override(1001)]] let c1 : u32 = 1u;
|
[[override(1001)]] let c1 : u32 = 1u;
|
||||||
|
|
Loading…
Reference in New Issue