reader/wgsl: Add support for interpolate attribute

Bug: tint:746
Change-Id: I43486c0244a893a73b734e888fc8811c8e954ab6
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/56242
Kokoro: Kokoro <noreply+kokoro@google.com>
Auto-Submit: James Price <jrprice@google.com>
Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
James Price 2021-06-28 23:04:43 +00:00
parent 989a8e4d62
commit 03a7522276
2 changed files with 163 additions and 3 deletions

View File

@ -110,6 +110,7 @@ const char kBindingDecoration[] = "binding";
const char kBlockDecoration[] = "block";
const char kBuiltinDecoration[] = "builtin";
const char kGroupDecoration[] = "group";
const char kInterpolateDecoration[] = "interpolate";
const char kLocationDecoration[] = "location";
const char kOverrideDecoration[] = "override";
const char kSizeDecoration[] = "size";
@ -126,9 +127,9 @@ bool is_decoration(Token t) {
auto s = t.to_str();
return s == kAlignDecoration || s == kBindingDecoration ||
s == kBlockDecoration || s == kBuiltinDecoration ||
s == kGroupDecoration || s == kLocationDecoration ||
s == kOverrideDecoration || s == kSetDecoration ||
s == kSizeDecoration || s == kStageDecoration ||
s == kGroupDecoration || s == kInterpolateDecoration ||
s == kLocationDecoration || s == kOverrideDecoration ||
s == kSetDecoration || s == kSizeDecoration || s == kStageDecoration ||
s == kStrideDecoration || s == kWorkgroupSizeDecoration;
}
@ -2995,6 +2996,41 @@ Maybe<ast::Decoration*> ParserImpl::decoration() {
});
}
if (s == kInterpolateDecoration) {
return expect_paren_block("interpolate decoration", [&]() -> Result {
ast::InterpolationType type;
ast::InterpolationSampling sampling = ast::InterpolationSampling::kNone;
auto type_tok = next();
auto type_str = type_tok.to_str();
if (type_str == "perspective") {
type = ast::InterpolationType::kPerspective;
} else if (type_str == "linear") {
type = ast::InterpolationType::kLinear;
} else if (type_str == "flat") {
type = ast::InterpolationType::kFlat;
} else {
return add_error(type_tok, "invalid interpolation type");
}
if (match(Token::Type::kComma)) {
auto sampling_tok = next();
auto sampling_str = sampling_tok.to_str();
if (sampling_str == "center") {
sampling = ast::InterpolationSampling::kCenter;
} else if (sampling_str == "centroid") {
sampling = ast::InterpolationSampling::kCentroid;
} else if (sampling_str == "sample") {
sampling = ast::InterpolationSampling::kSample;
} else {
return add_error(sampling_tok, "invalid interpolation sampling");
}
}
return create<ast::InterpolateDecoration>(t.source(), type, sampling);
});
}
if (s == kBuiltinDecoration) {
return expect_paren_block("builtin decoration", [&]() -> Result {
auto builtin = expect_builtin();

View File

@ -174,6 +174,130 @@ TEST_F(ParserImplTest, Decoration_Builtin_MissingInvalid) {
EXPECT_EQ(p->error(), "1:9: expected identifier for builtin");
}
TEST_F(ParserImplTest, Decoration_Interpolate_Flat) {
auto p = parser("interpolate(flat)");
auto deco = p->decoration();
EXPECT_TRUE(deco.matched);
EXPECT_FALSE(deco.errored);
ASSERT_NE(deco.value, nullptr);
auto* var_deco = deco.value->As<ast::Decoration>();
ASSERT_NE(var_deco, nullptr);
ASSERT_FALSE(p->has_error());
ASSERT_TRUE(var_deco->Is<ast::InterpolateDecoration>());
auto* interp = var_deco->As<ast::InterpolateDecoration>();
EXPECT_EQ(interp->type(), ast::InterpolationType::kFlat);
EXPECT_EQ(interp->sampling(), ast::InterpolationSampling::kNone);
}
TEST_F(ParserImplTest, Decoration_Interpolate_Perspective_Center) {
auto p = parser("interpolate(perspective, center)");
auto deco = p->decoration();
EXPECT_TRUE(deco.matched);
EXPECT_FALSE(deco.errored);
ASSERT_NE(deco.value, nullptr);
auto* var_deco = deco.value->As<ast::Decoration>();
ASSERT_NE(var_deco, nullptr);
ASSERT_FALSE(p->has_error());
ASSERT_TRUE(var_deco->Is<ast::InterpolateDecoration>());
auto* interp = var_deco->As<ast::InterpolateDecoration>();
EXPECT_EQ(interp->type(), ast::InterpolationType::kPerspective);
EXPECT_EQ(interp->sampling(), ast::InterpolationSampling::kCenter);
}
TEST_F(ParserImplTest, Decoration_Interpolate_Perspective_Centroid) {
auto p = parser("interpolate(perspective, centroid)");
auto deco = p->decoration();
EXPECT_TRUE(deco.matched);
EXPECT_FALSE(deco.errored);
ASSERT_NE(deco.value, nullptr);
auto* var_deco = deco.value->As<ast::Decoration>();
ASSERT_NE(var_deco, nullptr);
ASSERT_FALSE(p->has_error());
ASSERT_TRUE(var_deco->Is<ast::InterpolateDecoration>());
auto* interp = var_deco->As<ast::InterpolateDecoration>();
EXPECT_EQ(interp->type(), ast::InterpolationType::kPerspective);
EXPECT_EQ(interp->sampling(), ast::InterpolationSampling::kCentroid);
}
TEST_F(ParserImplTest, Decoration_Interpolate_Linear_Sample) {
auto p = parser("interpolate(linear, sample)");
auto deco = p->decoration();
EXPECT_TRUE(deco.matched);
EXPECT_FALSE(deco.errored);
ASSERT_NE(deco.value, nullptr);
auto* var_deco = deco.value->As<ast::Decoration>();
ASSERT_NE(var_deco, nullptr);
ASSERT_FALSE(p->has_error());
ASSERT_TRUE(var_deco->Is<ast::InterpolateDecoration>());
auto* interp = var_deco->As<ast::InterpolateDecoration>();
EXPECT_EQ(interp->type(), ast::InterpolationType::kLinear);
EXPECT_EQ(interp->sampling(), ast::InterpolationSampling::kSample);
}
TEST_F(ParserImplTest, Decoration_Interpolate_MissingLeftParen) {
auto p = parser("interpolate flat)");
auto deco = p->decoration();
EXPECT_FALSE(deco.matched);
EXPECT_TRUE(deco.errored);
EXPECT_EQ(deco.value, nullptr);
EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:13: expected '(' for interpolate decoration");
}
TEST_F(ParserImplTest, Decoration_Interpolate_MissingRightParen) {
auto p = parser("interpolate(flat");
auto deco = p->decoration();
EXPECT_FALSE(deco.matched);
EXPECT_TRUE(deco.errored);
EXPECT_EQ(deco.value, nullptr);
EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:17: expected ')' for interpolate decoration");
}
TEST_F(ParserImplTest, Decoration_Interpolate_MissingFirstValue) {
auto p = parser("interpolate()");
auto deco = p->decoration();
EXPECT_FALSE(deco.matched);
EXPECT_TRUE(deco.errored);
EXPECT_EQ(deco.value, nullptr);
EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:13: invalid interpolation type");
}
TEST_F(ParserImplTest, Decoration_Interpolate_InvalidFirstValue) {
auto p = parser("interpolate(other_thingy)");
auto deco = p->decoration();
EXPECT_FALSE(deco.matched);
EXPECT_TRUE(deco.errored);
EXPECT_EQ(deco.value, nullptr);
EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:13: invalid interpolation type");
}
TEST_F(ParserImplTest, Decoration_Interpolate_MissingSecondValue) {
auto p = parser("interpolate(perspective,)");
auto deco = p->decoration();
EXPECT_FALSE(deco.matched);
EXPECT_TRUE(deco.errored);
EXPECT_EQ(deco.value, nullptr);
EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:25: invalid interpolation sampling");
}
TEST_F(ParserImplTest, Decoration_Interpolate_InvalidSecondValue) {
auto p = parser("interpolate(perspective, nope)");
auto deco = p->decoration();
EXPECT_FALSE(deco.matched);
EXPECT_TRUE(deco.errored);
EXPECT_EQ(deco.value, nullptr);
EXPECT_TRUE(p->has_error());
EXPECT_EQ(p->error(), "1:26: invalid interpolation sampling");
}
TEST_F(ParserImplTest, Decoration_Binding) {
auto p = parser("binding(4)");
auto deco = p->decoration();