From fd3ca9ee47df480673485fd32fa14e90c84da56f Mon Sep 17 00:00:00 2001 From: Tomek Ponitka Date: Wed, 2 Sep 2020 15:52:15 +0000 Subject: [PATCH] [wgsl-reader] Parsing sampled texture type Bug: tint:147 Change-Id: I21c864dd63c2003797c78758358ab4134cd8ff31 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/28002 Commit-Queue: dan sinclair Reviewed-by: dan sinclair --- BUILD.gn | 1 + src/CMakeLists.txt | 1 + src/ast/type/texture_type.cc | 3 + src/ast/type/texture_type.h | 2 + src/reader/wgsl/lexer.cc | 26 +++++ src/reader/wgsl/lexer_test.cc | 13 +++ src/reader/wgsl/parser_impl.cc | 80 ++++++++++++++- src/reader/wgsl/parser_impl.h | 4 + .../parser_impl_sampled_texture_type_test.cc | 98 +++++++++++++++++++ .../parser_impl_texture_sampler_types_test.cc | 70 +++++++++++++ src/reader/wgsl/token.cc | 18 ++++ src/reader/wgsl/token.h | 48 +++++++++ 12 files changed, 363 insertions(+), 1 deletion(-) create mode 100644 src/reader/wgsl/parser_impl_sampled_texture_type_test.cc diff --git a/BUILD.gn b/BUILD.gn index 6add641aeb..7462befd29 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -909,6 +909,7 @@ source_set("tint_unittests_wgsl_reader_src") { "src/reader/wgsl/parser_impl_postfix_expression_test.cc", "src/reader/wgsl/parser_impl_primary_expression_test.cc", "src/reader/wgsl/parser_impl_relational_expression_test.cc", + "src/reader/wgsl/parser_impl_sampled_texture_type_test.cc", "src/reader/wgsl/parser_impl_sampler_type_test.cc", "src/reader/wgsl/parser_impl_shift_expression_test.cc", "src/reader/wgsl/parser_impl_statement_test.cc", diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index c735b0d440..3d82ef66b9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -440,6 +440,7 @@ if(${TINT_BUILD_WGSL_READER}) reader/wgsl/parser_impl_postfix_expression_test.cc reader/wgsl/parser_impl_primary_expression_test.cc reader/wgsl/parser_impl_relational_expression_test.cc + reader/wgsl/parser_impl_sampled_texture_type_test.cc reader/wgsl/parser_impl_sampler_type_test.cc reader/wgsl/parser_impl_shift_expression_test.cc reader/wgsl/parser_impl_statement_test.cc diff --git a/src/ast/type/texture_type.cc b/src/ast/type/texture_type.cc index a5a4e1e4a1..690a514b67 100644 --- a/src/ast/type/texture_type.cc +++ b/src/ast/type/texture_type.cc @@ -26,6 +26,9 @@ namespace type { std::ostream& operator<<(std::ostream& out, TextureDimension dim) { switch (dim) { + case TextureDimension::kNone: + out << "None"; + break; case TextureDimension::k1d: out << "1d"; break; diff --git a/src/ast/type/texture_type.h b/src/ast/type/texture_type.h index 37ca7e1fcf..e0f44fac5b 100644 --- a/src/ast/type/texture_type.h +++ b/src/ast/type/texture_type.h @@ -30,6 +30,8 @@ class StorageTextureType; /// The dimensionality of the texture enum class TextureDimension { + /// Invalid texture + kNone = -1, /// 1 dimensional texture k1d, /// 1 dimenstional array texture diff --git a/src/reader/wgsl/lexer.cc b/src/reader/wgsl/lexer.cc index c2126a8ca1..eacd7ab837 100644 --- a/src/reader/wgsl/lexer.cc +++ b/src/reader/wgsl/lexer.cc @@ -587,6 +587,32 @@ Token Lexer::check_keyword(const Source& source, const std::string& str) { return {Token::Type::kTextureDepthCubeArray, source, "texture_depth_cube_array"}; } + if (str == "texture_sampled_1d") + return {Token::Type::kTextureSampled1d, source, "texture_sampled_1d"}; + if (str == "texture_sampled_1d_array") { + return {Token::Type::kTextureSampled1dArray, source, + "texture_sampled_1d_array"}; + } + if (str == "texture_sampled_2d") + return {Token::Type::kTextureSampled2d, source, "texture_sampled_2d"}; + if (str == "texture_sampled_2d_array") { + return {Token::Type::kTextureSampled2dArray, source, + "texture_sampled_2d_array"}; + } + if (str == "texture_sampled_2d_ms") + return {Token::Type::kTextureSampled2dMs, source, "texture_sampled_2d_ms"}; + if (str == "texture_sampled_2d_ms_array") { + return {Token::Type::kTextureSampled2dMsArray, source, + "texture_sampled_2d_ms_array"}; + } + if (str == "texture_sampled_3d") + return {Token::Type::kTextureSampled3d, source, "texture_sampled_3d"}; + if (str == "texture_sampled_cube") + return {Token::Type::kTextureSampledCube, source, "texture_sampled_cube"}; + if (str == "texture_sampled_cube_array") { + return {Token::Type::kTextureSampledCubeArray, source, + "texture_sampled_cube_array"}; + } if (str == "true") return {Token::Type::kTrue, source, "true"}; if (str == "type") diff --git a/src/reader/wgsl/lexer_test.cc b/src/reader/wgsl/lexer_test.cc index a2169cfa84..0dc5bfa388 100644 --- a/src/reader/wgsl/lexer_test.cc +++ b/src/reader/wgsl/lexer_test.cc @@ -470,6 +470,19 @@ INSTANTIATE_TEST_SUITE_P( TokenData{"texture_depth_cube", Token::Type::kTextureDepthCube}, TokenData{"texture_depth_cube_array", Token::Type::kTextureDepthCubeArray}, + TokenData{"texture_sampled_1d", Token::Type::kTextureSampled1d}, + TokenData{"texture_sampled_1d_array", + Token::Type::kTextureSampled1dArray}, + TokenData{"texture_sampled_2d", Token::Type::kTextureSampled2d}, + TokenData{"texture_sampled_2d_array", + Token::Type::kTextureSampled2dArray}, + TokenData{"texture_sampled_2d_ms", Token::Type::kTextureSampled2dMs}, + TokenData{"texture_sampled_2d_ms_array", + Token::Type::kTextureSampled2dMsArray}, + TokenData{"texture_sampled_3d", Token::Type::kTextureSampled3d}, + TokenData{"texture_sampled_cube", Token::Type::kTextureSampledCube}, + TokenData{"texture_sampled_cube_array", + Token::Type::kTextureSampledCubeArray}, TokenData{"true", Token::Type::kTrue}, TokenData{"type", Token::Type::kType}, TokenData{"u32", Token::Type::kU32}, diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc index e7a748b94c..43169305c8 100644 --- a/src/reader/wgsl/parser_impl.cc +++ b/src/reader/wgsl/parser_impl.cc @@ -51,6 +51,7 @@ #include "src/ast/type/i32_type.h" #include "src/ast/type/matrix_type.h" #include "src/ast/type/pointer_type.h" +#include "src/ast/type/sampled_texture_type.h" #include "src/ast/type/sampler_type.h" #include "src/ast/type/struct_type.h" #include "src/ast/type/u32_type.h" @@ -580,7 +581,7 @@ std::unique_ptr ParserImpl::variable_decl() { // texture_sampler_types // : sampler_type // | depth_texture_type -// | TODO: sampled_texture_type LESS_THAN type_decl GREATER_THAN +// | sampled_texture_type LESS_THAN type_decl GREATER_THAN // | TODO: multisampled_texture_type LESS_THAN type_decl GREATER_THAN // | TODO: storage_texture_type LESS_THAN image_storage_type GREATER_THAN ast::type::Type* ParserImpl::texture_sampler_types() { @@ -594,6 +595,32 @@ ast::type::Type* ParserImpl::texture_sampler_types() { return type; } + auto dim = sampled_texture_type(); + if (dim != ast::type::TextureDimension::kNone) { + auto t = next(); + if (!t.IsLessThan()) { + set_error(peek(), "missing '<' for sampled texture type"); + return nullptr; + } + + auto* subtype = type_decl(); + if (has_error()) + return nullptr; + if (subtype == nullptr) { + set_error(peek(), "invalid subtype for sampled texture type"); + return nullptr; + } + + t = next(); + if (!t.IsGreaterThan()) { + set_error(peek(), "missing '>' for sampled texture type"); + return nullptr; + } + + return ctx_.type_mgr().Get( + std::make_unique(dim, subtype)); + } + return nullptr; } @@ -615,6 +642,57 @@ ast::type::Type* ParserImpl::sampler_type() { return nullptr; } +// sampled_texture_type +// : TEXTURE_SAMPLED_1D +// | TEXTURE_SAMPLED_1D_ARRAY +// | TEXTURE_SAMPLED_2D +// | TEXTURE_SAMPLED_2D_ARRAY +// | TEXTURE_SAMPLED_2D_MS +// | TEXTURE_SAMPLED_2D_MS_ARRAY +// | TEXTURE_SAMPLED_3D +// | TEXTURE_SAMPLED_CUBE +// | TEXTURE_SAMPLED_CUBE_ARRAY +ast::type::TextureDimension ParserImpl::sampled_texture_type() { + auto t = peek(); + if (t.IsTextureSampled1d()) { + next(); // Consume the peek + return ast::type::TextureDimension::k1d; + } + if (t.IsTextureSampled1dArray()) { + next(); // Consume the peek + return ast::type::TextureDimension::k1dArray; + } + if (t.IsTextureSampled2d()) { + next(); // Consume the peek + return ast::type::TextureDimension::k2d; + } + if (t.IsTextureSampled2dArray()) { + next(); // Consume the peek + return ast::type::TextureDimension::k2dArray; + } + if (t.IsTextureSampled2dMs()) { + next(); // Consume the peek + return ast::type::TextureDimension::k2dMs; + } + if (t.IsTextureSampled2dMsArray()) { + next(); // Consume the peek + return ast::type::TextureDimension::k2dMsArray; + } + if (t.IsTextureSampled3d()) { + next(); // Consume the peek + return ast::type::TextureDimension::k3d; + } + if (t.IsTextureSampledCube()) { + next(); // Consume the peek + return ast::type::TextureDimension::kCube; + } + if (t.IsTextureSampledCubeArray()) { + next(); // Consume the peek + return ast::type::TextureDimension::kCubeArray; + } + return ast::type::TextureDimension::kNone; +} + // depth_texture_type // : TEXTURE_DEPTH_2D // | TEXTURE_DEPTH_2D_ARRAY diff --git a/src/reader/wgsl/parser_impl.h b/src/reader/wgsl/parser_impl.h index d4924384a6..3f3073f6b6 100644 --- a/src/reader/wgsl/parser_impl.h +++ b/src/reader/wgsl/parser_impl.h @@ -40,6 +40,7 @@ #include "src/ast/struct_decoration.h" #include "src/ast/struct_member.h" #include "src/ast/struct_member_decoration.h" +#include "src/ast/type/texture_type.h" #include "src/ast/type/type.h" #include "src/ast/variable.h" #include "src/ast/variable_decoration.h" @@ -186,6 +187,9 @@ class ParserImpl { /// Parses a `sampler_type` grammar element /// @returns the parsed Type or nullptr if none matched. ast::type::Type* sampler_type(); + /// Parses a `sampled_texture_type` grammar element + /// @returns returns the sample texture dimension or kNone if none matched. + ast::type::TextureDimension sampled_texture_type(); /// Parses a `depth_texture_type` grammar element /// @returns the parsed Type or nullptr if none matched. ast::type::Type* depth_texture_type(); diff --git a/src/reader/wgsl/parser_impl_sampled_texture_type_test.cc b/src/reader/wgsl/parser_impl_sampled_texture_type_test.cc new file mode 100644 index 0000000000..da9a461453 --- /dev/null +++ b/src/reader/wgsl/parser_impl_sampled_texture_type_test.cc @@ -0,0 +1,98 @@ +// 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/type/texture_type.h" +#include "src/reader/wgsl/parser_impl.h" +#include "src/reader/wgsl/parser_impl_test_helper.h" + +namespace tint { +namespace reader { +namespace wgsl { +namespace { + +TEST_F(ParserImplTest, SampledTextureType_Invalid) { + auto* p = parser("1234"); + auto t = p->sampled_texture_type(); + EXPECT_EQ(t, ast::type::TextureDimension::kNone); + EXPECT_FALSE(p->has_error()); +} + +TEST_F(ParserImplTest, SampledTextureType_1d) { + auto* p = parser("texture_sampled_1d"); + auto t = p->sampled_texture_type(); + EXPECT_EQ(t, ast::type::TextureDimension::k1d); + EXPECT_FALSE(p->has_error()); +} + +TEST_F(ParserImplTest, SampledTextureType_1dArray) { + auto* p = parser("texture_sampled_1d_array"); + auto t = p->sampled_texture_type(); + EXPECT_EQ(t, ast::type::TextureDimension::k1dArray); + EXPECT_FALSE(p->has_error()); +} + +TEST_F(ParserImplTest, SampledTextureType_2d) { + auto* p = parser("texture_sampled_2d"); + auto t = p->sampled_texture_type(); + EXPECT_EQ(t, ast::type::TextureDimension::k2d); + EXPECT_FALSE(p->has_error()); +} + +TEST_F(ParserImplTest, SampledTextureType_2dArray) { + auto* p = parser("texture_sampled_2d_array"); + auto t = p->sampled_texture_type(); + EXPECT_EQ(t, ast::type::TextureDimension::k2dArray); + EXPECT_FALSE(p->has_error()); +} + +TEST_F(ParserImplTest, SampledTextureType_2dMs) { + auto* p = parser("texture_sampled_2d_ms"); + auto t = p->sampled_texture_type(); + EXPECT_EQ(t, ast::type::TextureDimension::k2dMs); + EXPECT_FALSE(p->has_error()); +} + +TEST_F(ParserImplTest, SampledTextureType_2dMsArray) { + auto* p = parser("texture_sampled_2d_ms_array"); + auto t = p->sampled_texture_type(); + EXPECT_EQ(t, ast::type::TextureDimension::k2dMsArray); + EXPECT_FALSE(p->has_error()); +} + +TEST_F(ParserImplTest, SampledTextureType_3d) { + auto* p = parser("texture_sampled_3d"); + auto t = p->sampled_texture_type(); + EXPECT_EQ(t, ast::type::TextureDimension::k3d); + EXPECT_FALSE(p->has_error()); +} + +TEST_F(ParserImplTest, SampledTextureType_Cube) { + auto* p = parser("texture_sampled_cube"); + auto t = p->sampled_texture_type(); + EXPECT_EQ(t, ast::type::TextureDimension::kCube); + EXPECT_FALSE(p->has_error()); +} + +TEST_F(ParserImplTest, SampledTextureType_kCubeArray) { + auto* p = parser("texture_sampled_cube_array"); + auto t = p->sampled_texture_type(); + EXPECT_EQ(t, ast::type::TextureDimension::kCubeArray); + EXPECT_FALSE(p->has_error()); +} + +} // namespace +} // namespace wgsl +} // namespace reader +} // namespace tint diff --git a/src/reader/wgsl/parser_impl_texture_sampler_types_test.cc b/src/reader/wgsl/parser_impl_texture_sampler_types_test.cc index a1580e6052..262dca976f 100644 --- a/src/reader/wgsl/parser_impl_texture_sampler_types_test.cc +++ b/src/reader/wgsl/parser_impl_texture_sampler_types_test.cc @@ -39,6 +39,15 @@ TEST_F(ParserImplTest, TextureSamplerTypes_Sampler) { EXPECT_FALSE(p->has_error()); } +TEST_F(ParserImplTest, TextureSamplerTypes_SamplerComparison) { + auto* p = parser("sampler_comparison"); + auto* t = p->texture_sampler_types(); + ASSERT_NE(t, nullptr); + ASSERT_TRUE(t->IsSampler()); + ASSERT_TRUE(t->AsSampler()->IsComparison()); + EXPECT_FALSE(p->has_error()); +} + TEST_F(ParserImplTest, TextureSamplerTypes_DepthTexture) { auto* p = parser("texture_depth_2d"); auto* t = p->texture_sampler_types(); @@ -49,6 +58,67 @@ TEST_F(ParserImplTest, TextureSamplerTypes_DepthTexture) { EXPECT_FALSE(p->has_error()); } +TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_F32) { + auto* p = parser("texture_sampled_1d"); + auto* t = p->texture_sampler_types(); + ASSERT_NE(t, nullptr); + ASSERT_TRUE(t->IsTexture()); + ASSERT_TRUE(t->AsTexture()->IsSampled()); + ASSERT_TRUE(t->AsTexture()->AsSampled()->type()->IsF32()); + EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k1d); + EXPECT_FALSE(p->has_error()); +} + +TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_I32) { + auto* p = parser("texture_sampled_2d"); + auto* t = p->texture_sampler_types(); + ASSERT_NE(t, nullptr); + ASSERT_TRUE(t->IsTexture()); + ASSERT_TRUE(t->AsTexture()->IsSampled()); + ASSERT_TRUE(t->AsTexture()->AsSampled()->type()->IsI32()); + EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k2d); + EXPECT_FALSE(p->has_error()); +} + +TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_U32) { + auto* p = parser("texture_sampled_3d"); + auto* t = p->texture_sampler_types(); + ASSERT_NE(t, nullptr); + ASSERT_TRUE(t->IsTexture()); + ASSERT_TRUE(t->AsTexture()->IsSampled()); + ASSERT_TRUE(t->AsTexture()->AsSampled()->type()->IsU32()); + EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k3d); + EXPECT_FALSE(p->has_error()); +} + +TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_Invalid) { + auto* p = parser("texture_sampled_1d"); + auto* t = p->texture_sampler_types(); + EXPECT_EQ(t, nullptr); + EXPECT_EQ(p->error(), "1:20: unknown type alias 'abc'"); +} + +TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_MissingType) { + auto* p = parser("texture_sampled_1d<>"); + auto* t = p->texture_sampler_types(); + EXPECT_EQ(t, nullptr); + EXPECT_EQ(p->error(), "1:20: invalid subtype for sampled texture type"); +} + +TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_MissingLessThan) { + auto* p = parser("texture_sampled_1d"); + auto* t = p->texture_sampler_types(); + EXPECT_EQ(t, nullptr); + EXPECT_EQ(p->error(), "1:19: missing '<' for sampled texture type"); +} + +TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_MissingGreaterThan) { + auto* p = parser("texture_sampled_1dtexture_sampler_types(); + EXPECT_EQ(t, nullptr); + EXPECT_EQ(p->error(), "1:23: missing '>' for sampled texture type"); +} + } // namespace } // namespace wgsl } // namespace reader diff --git a/src/reader/wgsl/token.cc b/src/reader/wgsl/token.cc index 9ca01c97da..be6f752963 100644 --- a/src/reader/wgsl/token.cc +++ b/src/reader/wgsl/token.cc @@ -219,6 +219,24 @@ std::string Token::TypeToName(Type type) { return "texture_depth_cube"; case Token::Type::kTextureDepthCubeArray: return "texture_depth_cube_array"; + case Token::Type::kTextureSampled1d: + return "texture_sampled_1d"; + case Token::Type::kTextureSampled1dArray: + return "texture_sampled_1d_array"; + case Token::Type::kTextureSampled2d: + return "texture_sampled_2d"; + case Token::Type::kTextureSampled2dArray: + return "texture_sampled_2d_array"; + case Token::Type::kTextureSampled2dMs: + return "texture_sampled_2d_ms"; + case Token::Type::kTextureSampled2dMsArray: + return "texture_sampled_2d_ms_array"; + case Token::Type::kTextureSampled3d: + return "texture_sampled_3d"; + case Token::Type::kTextureSampledCube: + return "texture_sampled_cube"; + case Token::Type::kTextureSampledCubeArray: + return "texture_sampled_cube_array"; case Token::Type::kTrue: return "true"; case Token::Type::kType: diff --git a/src/reader/wgsl/token.h b/src/reader/wgsl/token.h index 3740b799d7..1b8d5f7ab0 100644 --- a/src/reader/wgsl/token.h +++ b/src/reader/wgsl/token.h @@ -230,6 +230,24 @@ class Token { kTextureDepthCube, /// A 'texture_depth_cube_array' kTextureDepthCubeArray, + /// A 'texture_sampled_1d' + kTextureSampled1d, + /// A 'texture_sampled_1d_array' + kTextureSampled1dArray, + /// A 'texture_sampled_2d' + kTextureSampled2d, + /// A 'texture_sampled_2d_array' + kTextureSampled2dArray, + /// A 'texture_sampled_2d_ms' + kTextureSampled2dMs, + /// A 'texture_sampled_2d_ms_array' + kTextureSampled2dMsArray, + /// A 'texture_sampled_3d' + kTextureSampled3d, + /// A 'texture_sampled_cube' + kTextureSampledCube, + /// A 'texture_sampled_cube_array' + kTextureSampledCubeArray, /// A 'true' kTrue, /// A 'type' @@ -503,6 +521,36 @@ class Token { bool IsTextureDepthCubeArray() const { return type_ == Type::kTextureDepthCubeArray; } + /// @returns true if token is a 'texture_sampled_1d' + bool IsTextureSampled1d() const { return type_ == Type::kTextureSampled1d; } + /// @returns true if token is a 'texture_sampled_1d_array' + bool IsTextureSampled1dArray() const { + return type_ == Type::kTextureSampled1dArray; + } + /// @returns true if token is a 'texture_sampled_2d' + bool IsTextureSampled2d() const { return type_ == Type::kTextureSampled2d; } + /// @returns true if token is a 'texture_sampled_2d_array' + bool IsTextureSampled2dArray() const { + return type_ == Type::kTextureSampled2dArray; + } + /// @returns true if token is a 'texture_sampled_2d_ms' + bool IsTextureSampled2dMs() const { + return type_ == Type::kTextureSampled2dMs; + } + /// @returns true if token is a 'texture_sampled_2d_ms_array' + bool IsTextureSampled2dMsArray() const { + return type_ == Type::kTextureSampled2dMsArray; + } + /// @returns true if token is a 'texture_sampled_3d' + bool IsTextureSampled3d() const { return type_ == Type::kTextureSampled3d; } + /// @returns true if token is a 'texture_sampled_cube' + bool IsTextureSampledCube() const { + return type_ == Type::kTextureSampledCube; + } + /// @returns true if token is a 'texture_sampled_cube_array' + bool IsTextureSampledCubeArray() const { + return type_ == Type::kTextureSampledCubeArray; + } /// @returns true if token is a 'true' bool IsTrue() const { return type_ == Type::kTrue; } /// @returns true if token is a 'type'