mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-12-10 05:57:51 +00:00
tint/resolver: Allow texture 'offset' to be const-expr
This allows the value to be declared in a `const` expression, and to use arithmetic. Fixed: tint:1636 Change-Id: Ie641a9d4183429c79c91605cd4df78f569be3579 Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/105623 Kokoro: Kokoro <noreply+kokoro@google.com> Reviewed-by: Dan Sinclair <dsinclair@chromium.org> Commit-Queue: Ben Clayton <bclayton@google.com>
This commit is contained in:
committed by
Dawn LUCI CQ
parent
d5139b4463
commit
559a248233
@@ -260,8 +260,7 @@ TEST_P(BuiltinTextureConstExprArgValidationTest, Immediate) {
|
||||
// a vector constructor.
|
||||
bool is_vector = arg_to_replace->Is<ast::CallExpression>();
|
||||
|
||||
// Make the expression to be replaced, reachable. This keeps the resolver
|
||||
// happy.
|
||||
// Make the expression to be replaced, reachable. This keeps the resolver happy.
|
||||
WrapInFunction(arg_to_replace);
|
||||
|
||||
arg_to_replace = expr(Source{{12, 34}}, *this);
|
||||
@@ -310,13 +309,65 @@ TEST_P(BuiltinTextureConstExprArgValidationTest, GlobalConst) {
|
||||
auto args = overload.args(this);
|
||||
auto*& arg_to_replace = (param.position == Position::kFirst) ? args.Front() : args.Back();
|
||||
|
||||
// Make the expression to be replaced, reachable. This keeps the resolver
|
||||
// happy.
|
||||
// BuildTextureVariable() uses a Literal for scalars, and a CallExpression for
|
||||
// a vector constructor.
|
||||
bool is_vector = arg_to_replace->Is<ast::CallExpression>();
|
||||
|
||||
// Make the expression to be replaced, reachable. This keeps the resolver happy.
|
||||
WrapInFunction(arg_to_replace);
|
||||
|
||||
arg_to_replace = Expr(Source{{12, 34}}, "G");
|
||||
|
||||
// Call the builtin with the constexpr argument replaced
|
||||
// Call the builtin with the constant-expression argument replaced
|
||||
Func("func", utils::Empty, ty.void_(),
|
||||
utils::Vector{
|
||||
CallStmt(Call(overload.function, args)),
|
||||
},
|
||||
utils::Vector{
|
||||
Stage(ast::PipelineStage::kFragment),
|
||||
});
|
||||
|
||||
if (expr.invalid_index == Constexpr::kValid) {
|
||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||
} else {
|
||||
EXPECT_FALSE(r()->Resolve());
|
||||
std::stringstream err;
|
||||
if (is_vector) {
|
||||
err << "12:34 error: each component of the " << param.name
|
||||
<< " argument must be at least " << param.min << " and at most " << param.max
|
||||
<< ". " << param.name << " component " << expr.invalid_index << " is "
|
||||
<< std::to_string(expr.values[static_cast<size_t>(expr.invalid_index)]);
|
||||
} else {
|
||||
err << "12:34 error: the " << param.name << " argument must be at least " << param.min
|
||||
<< " and at most " << param.max << ". " << param.name << " is "
|
||||
<< std::to_string(expr.values[static_cast<size_t>(expr.invalid_index)]);
|
||||
}
|
||||
EXPECT_EQ(r()->error(), err.str());
|
||||
}
|
||||
}
|
||||
|
||||
TEST_P(BuiltinTextureConstExprArgValidationTest, GlobalVar) {
|
||||
auto& p = GetParam();
|
||||
auto overload = std::get<0>(p);
|
||||
auto param = std::get<1>(p);
|
||||
auto expr = std::get<2>(p);
|
||||
|
||||
// Build the global texture and sampler variables
|
||||
overload.BuildTextureVariable(this);
|
||||
overload.BuildSamplerVariable(this);
|
||||
|
||||
// Build the module-scope var 'G' with the offset value
|
||||
GlobalVar("G", expr({}, *this), ast::AddressSpace::kPrivate);
|
||||
|
||||
auto args = overload.args(this);
|
||||
auto*& arg_to_replace = (param.position == Position::kFirst) ? args.Front() : args.Back();
|
||||
|
||||
// Make the expression to be replaced, reachable. This keeps the resolver happy.
|
||||
WrapInFunction(arg_to_replace);
|
||||
|
||||
arg_to_replace = Expr(Source{{12, 34}}, "G");
|
||||
|
||||
// Call the builtin with the constant-expression argument replaced
|
||||
Func("func", utils::Empty, ty.void_(),
|
||||
utils::Vector{
|
||||
CallStmt(Call(overload.function, args)),
|
||||
|
||||
@@ -1663,50 +1663,29 @@ bool Validator::TextureBuiltinFunction(const sem::Call* call) const {
|
||||
std::string name = sem::str(usage);
|
||||
auto* arg = call->Arguments()[index];
|
||||
if (auto values = arg->ConstantValue()) {
|
||||
// Assert that the constant values are of the expected type.
|
||||
if (!values->Type()->is_integer_scalar_or_vector()) {
|
||||
TINT_ICE(Resolver, diagnostics_)
|
||||
<< "failed to resolve '" + func_name + "' " << name << " parameter type";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Currently const_expr is restricted to literals and type constructors.
|
||||
// Check that that's all we have for the parameter.
|
||||
bool is_const_expr = true;
|
||||
ast::TraverseExpressions(
|
||||
arg->Declaration(), diagnostics_, [&](const ast::Expression* e) {
|
||||
if (e->IsAnyOf<ast::LiteralExpression, ast::CallExpression>()) {
|
||||
return ast::TraverseAction::Descend;
|
||||
}
|
||||
is_const_expr = false;
|
||||
return ast::TraverseAction::Stop;
|
||||
});
|
||||
if (is_const_expr) {
|
||||
if (auto* vector = builtin->Parameters()[index]->Type()->As<sem::Vector>()) {
|
||||
for (size_t i = 0; i < vector->Width(); i++) {
|
||||
auto value = values->Index(i)->As<AInt>();
|
||||
if (value < min || value > max) {
|
||||
AddError("each component of the " + name +
|
||||
" argument must be at least " + std::to_string(min) +
|
||||
" and at most " + std::to_string(max) + ". " + name +
|
||||
" component " + std::to_string(i) + " is " +
|
||||
std::to_string(value),
|
||||
arg->Declaration()->source);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
auto value = values->As<AInt>();
|
||||
if (auto* vector = values->Type()->As<sem::Vector>()) {
|
||||
for (size_t i = 0; i < vector->Width(); i++) {
|
||||
auto value = values->Index(i)->As<AInt>();
|
||||
if (value < min || value > max) {
|
||||
AddError("the " + name + " argument must be at least " +
|
||||
AddError("each component of the " + name + " argument must be at least " +
|
||||
std::to_string(min) + " and at most " + std::to_string(max) +
|
||||
". " + name + " is " + std::to_string(value),
|
||||
". " + name + " component " + std::to_string(i) + " is " +
|
||||
std::to_string(value),
|
||||
arg->Declaration()->source);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
auto value = values->As<AInt>();
|
||||
if (value < min || value > max) {
|
||||
AddError("the " + name + " argument must be at least " + std::to_string(min) +
|
||||
" and at most " + std::to_string(max) + ". " + name + " is " +
|
||||
std::to_string(value),
|
||||
arg->Declaration()->source);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
AddError("the " + name + " argument must be a const-expression",
|
||||
arg->Declaration()->source);
|
||||
|
||||
Reference in New Issue
Block a user