Add support for multisampled textures. This Cl adds the AST, WGSL-Reader and SPIRV-Writer support for the `texture_multisampled_2d` type. Bug: tint:237 Change-Id: Ib3eb831227b49f32162801f1e1b4e474774c78b3 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/28480 Commit-Queue: dan sinclair <dsinclair@chromium.org> Reviewed-by: David Neto <dneto@google.com>
diff --git a/src/reader/wgsl/lexer.cc b/src/reader/wgsl/lexer.cc index 66a2dc2..37bfeb5 100644 --- a/src/reader/wgsl/lexer.cc +++ b/src/reader/wgsl/lexer.cc
@@ -657,6 +657,10 @@ return {Token::Type::kTextureDepthCubeArray, source, "texture_depth_cube_array"}; } + if (str == "texture_multisampled_2d") { + return {Token::Type::kTextureMultisampled2d, source, + "texture_multisampled_2d"}; + } if (str == "texture_ro_1d") return {Token::Type::kTextureStorageReadonly1d, source, "texture_ro_1d"}; if (str == "texture_ro_1d_array") @@ -681,12 +685,6 @@ 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")
diff --git a/src/reader/wgsl/lexer_test.cc b/src/reader/wgsl/lexer_test.cc index 4806cb6..d21f3b6 100644 --- a/src/reader/wgsl/lexer_test.cc +++ b/src/reader/wgsl/lexer_test.cc
@@ -401,7 +401,7 @@ Lexer l(params.input); auto t = l.next(); - EXPECT_TRUE(t.Is(params.type)); + EXPECT_TRUE(t.Is(params.type)) << params.input; EXPECT_EQ(1u, t.line()); EXPECT_EQ(1u, t.column()); @@ -505,6 +505,8 @@ TokenData{"texture_depth_cube", Token::Type::kTextureDepthCube}, TokenData{"texture_depth_cube_array", Token::Type::kTextureDepthCubeArray}, + TokenData{"texture_multisampled_2d", + Token::Type::kTextureMultisampled2d}, TokenData{"texture_ro_1d", Token::Type::kTextureStorageReadonly1d}, TokenData{"texture_ro_1d_array", Token::Type::kTextureStorageReadonly1dArray}, @@ -518,9 +520,6 @@ 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",
diff --git a/src/reader/wgsl/parser_impl.cc b/src/reader/wgsl/parser_impl.cc index 82af4cc..a85f7c7 100644 --- a/src/reader/wgsl/parser_impl.cc +++ b/src/reader/wgsl/parser_impl.cc
@@ -50,6 +50,7 @@ #include "src/ast/type/f32_type.h" #include "src/ast/type/i32_type.h" #include "src/ast/type/matrix_type.h" +#include "src/ast/type/multisampled_texture_type.h" #include "src/ast/type/pointer_type.h" #include "src/ast/type/sampled_texture_type.h" #include "src/ast/type/sampler_type.h" @@ -582,7 +583,7 @@ // : sampler_type // | depth_texture_type // | sampled_texture_type LESS_THAN type_decl GREATER_THAN -// | TODO: multisampled_texture_type LESS_THAN type_decl GREATER_THAN +// | multisampled_texture_type LESS_THAN type_decl GREATER_THAN // | storage_texture_type LESS_THAN image_storage_type GREATER_THAN ast::type::Type* ParserImpl::texture_sampler_types() { auto* type = sampler_type(); @@ -595,8 +596,8 @@ return type; } - auto sampled_dim = sampled_texture_type(); - if (sampled_dim != ast::type::TextureDimension::kNone) { + 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"); @@ -618,7 +619,33 @@ } return ctx_.type_mgr().Get( - std::make_unique<ast::type::SampledTextureType>(sampled_dim, subtype)); + std::make_unique<ast::type::SampledTextureType>(dim, subtype)); + } + + dim = multisampled_texture_type(); + if (dim != ast::type::TextureDimension::kNone) { + auto t = next(); + if (!t.IsLessThan()) { + set_error(peek(), "missing '<' for multisampled texture type"); + return nullptr; + } + + auto* subtype = type_decl(); + if (has_error()) + return nullptr; + if (subtype == nullptr) { + set_error(peek(), "invalid subtype for multisampled texture type"); + return nullptr; + } + + t = next(); + if (!t.IsGreaterThan()) { + set_error(peek(), "missing '>' for multisampled texture type"); + return nullptr; + } + + return ctx_.type_mgr().Get( + std::make_unique<ast::type::MultisampledTextureType>(dim, subtype)); } ast::type::TextureDimension storage_dim; @@ -675,8 +702,6 @@ // | 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 @@ -698,14 +723,6 @@ 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; @@ -721,6 +738,17 @@ return ast::type::TextureDimension::kNone; } +// multisampled_texture_type +// : TEXTURE_MULTISAMPLED_2D +ast::type::TextureDimension ParserImpl::multisampled_texture_type() { + auto t = peek(); + if (t.IsTextureMultisampled2d()) { + next(); // Consume the peek + return ast::type::TextureDimension::k2d; + } + return ast::type::TextureDimension::kNone; +} + // storage_texture_type // : TEXTURE_RO_1D // | TEXTURE_RO_1D_ARRAY
diff --git a/src/reader/wgsl/parser_impl.h b/src/reader/wgsl/parser_impl.h index eb35b3d..6da84df 100644 --- a/src/reader/wgsl/parser_impl.h +++ b/src/reader/wgsl/parser_impl.h
@@ -188,6 +188,10 @@ /// Parses a `sampler_type` grammar element /// @returns the parsed Type or nullptr if none matched. ast::type::Type* sampler_type(); + /// Parses a `multisampled_texture_type` grammar element + /// @returns returns the multisample texture dimension or kNone if none + /// matched. + ast::type::TextureDimension multisampled_texture_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();
diff --git a/src/reader/wgsl/parser_impl_sampled_texture_type_test.cc b/src/reader/wgsl/parser_impl_sampled_texture_type_test.cc index da9a461..6e838a2 100644 --- a/src/reader/wgsl/parser_impl_sampled_texture_type_test.cc +++ b/src/reader/wgsl/parser_impl_sampled_texture_type_test.cc
@@ -57,20 +57,6 @@ 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();
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 3174004..649920f 100644 --- a/src/reader/wgsl/parser_impl_texture_sampler_types_test.cc +++ b/src/reader/wgsl/parser_impl_texture_sampler_types_test.cc
@@ -13,6 +13,7 @@ // limitations under the License. #include "gtest/gtest.h" +#include "src/ast/type/multisampled_texture_type.h" #include "src/ast/type/sampled_texture_type.h" #include "src/ast/type/sampler_type.h" #include "src/reader/wgsl/parser_impl.h" @@ -33,67 +34,68 @@ TEST_F(ParserImplTest, TextureSamplerTypes_Sampler) { auto* p = parser("sampler"); auto* t = p->texture_sampler_types(); + ASSERT_FALSE(p->has_error()) << p->error(); ASSERT_NE(t, nullptr); ASSERT_TRUE(t->IsSampler()); ASSERT_FALSE(t->AsSampler()->IsComparison()); - EXPECT_FALSE(p->has_error()); } TEST_F(ParserImplTest, TextureSamplerTypes_SamplerComparison) { auto* p = parser("sampler_comparison"); auto* t = p->texture_sampler_types(); + ASSERT_FALSE(p->has_error()) << p->error(); 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(); + ASSERT_FALSE(p->has_error()) << p->error(); ASSERT_NE(t, nullptr); ASSERT_TRUE(t->IsTexture()); ASSERT_TRUE(t->AsTexture()->IsDepth()); EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k2d); - EXPECT_FALSE(p->has_error()); } TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_F32) { auto* p = parser("texture_sampled_1d<f32>"); auto* t = p->texture_sampler_types(); + ASSERT_FALSE(p->has_error()) << p->error(); 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<i32>"); auto* t = p->texture_sampler_types(); + ASSERT_FALSE(p->has_error()) << p->error(); 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<u32>"); auto* t = p->texture_sampler_types(); + ASSERT_FALSE(p->has_error()) << p->error(); 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<abc>"); auto* t = p->texture_sampler_types(); + ASSERT_TRUE(p->has_error()); EXPECT_EQ(t, nullptr); EXPECT_EQ(p->error(), "1:20: unknown type alias 'abc'"); } @@ -101,6 +103,7 @@ TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_MissingType) { auto* p = parser("texture_sampled_1d<>"); auto* t = p->texture_sampler_types(); + ASSERT_TRUE(p->has_error()); EXPECT_EQ(t, nullptr); EXPECT_EQ(p->error(), "1:20: invalid subtype for sampled texture type"); } @@ -108,6 +111,7 @@ TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_MissingLessThan) { auto* p = parser("texture_sampled_1d"); auto* t = p->texture_sampler_types(); + ASSERT_TRUE(p->has_error()); EXPECT_EQ(t, nullptr); EXPECT_EQ(p->error(), "1:19: missing '<' for sampled texture type"); } @@ -115,13 +119,58 @@ TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_MissingGreaterThan) { auto* p = parser("texture_sampled_1d<u32"); auto* t = p->texture_sampler_types(); + ASSERT_TRUE(p->has_error()); EXPECT_EQ(t, nullptr); EXPECT_EQ(p->error(), "1:23: missing '>' for sampled texture type"); } +TEST_F(ParserImplTest, TextureSamplerTypes_MultisampledTexture_I32) { + auto* p = parser("texture_multisampled_2d<i32>"); + auto* t = p->texture_sampler_types(); + ASSERT_FALSE(p->has_error()) << p->error(); + ASSERT_NE(t, nullptr); + ASSERT_TRUE(t->IsTexture()); + ASSERT_TRUE(t->AsTexture()->IsMultisampled()); + ASSERT_TRUE(t->AsTexture()->AsMultisampled()->type()->IsI32()); + EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k2d); +} + +TEST_F(ParserImplTest, TextureSamplerTypes_MultisampledTexture_Invalid) { + auto* p = parser("texture_multisampled_2d<abc>"); + auto* t = p->texture_sampler_types(); + ASSERT_TRUE(p->has_error()); + EXPECT_EQ(t, nullptr); + EXPECT_EQ(p->error(), "1:25: unknown type alias 'abc'"); +} + +TEST_F(ParserImplTest, TextureSamplerTypes_MultisampledTexture_MissingType) { + auto* p = parser("texture_multisampled_2d<>"); + auto* t = p->texture_sampler_types(); + ASSERT_TRUE(p->has_error()); + EXPECT_EQ(t, nullptr); + EXPECT_EQ(p->error(), "1:25: invalid subtype for multisampled texture type"); +} + +TEST_F(ParserImplTest, + TextureSamplerTypes_MultisampledTexture_MissingLessThan) { + auto* p = parser("texture_multisampled_2d"); + auto* t = p->texture_sampler_types(); + EXPECT_EQ(t, nullptr); + EXPECT_EQ(p->error(), "1:24: missing '<' for multisampled texture type"); +} + +TEST_F(ParserImplTest, + TextureSamplerTypes_MultisampledTexture_MissingGreaterThan) { + auto* p = parser("texture_multisampled_2d<u32"); + auto* t = p->texture_sampler_types(); + EXPECT_EQ(t, nullptr); + EXPECT_EQ(p->error(), "1:28: missing '>' for multisampled texture type"); +} + TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_Readonly1dR8Unorm) { auto* p = parser("texture_ro_1d<r8unorm>"); auto* t = p->texture_sampler_types(); + ASSERT_FALSE(p->has_error()) << p->error(); ASSERT_NE(t, nullptr); ASSERT_TRUE(t->IsTexture()); ASSERT_TRUE(t->AsTexture()->IsStorage()); @@ -130,12 +179,12 @@ EXPECT_EQ(t->AsTexture()->AsStorage()->access(), ast::type::StorageAccess::kRead); EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k1d); - EXPECT_FALSE(p->has_error()); } TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_Writeonly2dR16Float) { auto* p = parser("texture_wo_2d<r16float>"); auto* t = p->texture_sampler_types(); + ASSERT_FALSE(p->has_error()) << p->error(); ASSERT_NE(t, nullptr); ASSERT_TRUE(t->IsTexture()); ASSERT_TRUE(t->AsTexture()->IsStorage()); @@ -144,7 +193,6 @@ EXPECT_EQ(t->AsTexture()->AsStorage()->access(), ast::type::StorageAccess::kWrite); EXPECT_EQ(t->AsTexture()->dim(), ast::type::TextureDimension::k2d); - EXPECT_FALSE(p->has_error()); } TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_InvalidType) {
diff --git a/src/reader/wgsl/token.cc b/src/reader/wgsl/token.cc index 58d60f4..dd1ad3e 100644 --- a/src/reader/wgsl/token.cc +++ b/src/reader/wgsl/token.cc
@@ -289,6 +289,8 @@ return "texture_depth_cube"; case Token::Type::kTextureDepthCubeArray: return "texture_depth_cube_array"; + case Token::Type::kTextureMultisampled2d: + return "texture_multisampled_2d"; case Token::Type::kTextureStorageReadonly1d: return "texture_ro_1d"; case Token::Type::kTextureStorageReadonly1dArray: @@ -307,10 +309,6 @@ 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:
diff --git a/src/reader/wgsl/token.h b/src/reader/wgsl/token.h index 2e9f2da..da18df3 100644 --- a/src/reader/wgsl/token.h +++ b/src/reader/wgsl/token.h
@@ -300,6 +300,8 @@ kTextureDepthCube, /// A 'texture_depth_cube_array' kTextureDepthCubeArray, + /// A 'texture_multisampled_2d' + kTextureMultisampled2d, /// A 'texture_ro_1d' kTextureStorageReadonly1d, /// A 'texture_ro_2d_array' @@ -318,10 +320,6 @@ 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' @@ -689,6 +687,10 @@ bool IsTextureDepthCubeArray() const { return type_ == Type::kTextureDepthCubeArray; } + /// @returns true if the token is a 'texture_multisample_2d' + bool IsTextureMultisampled2d() const { + return type_ == Type::kTextureMultisampled2d; + } /// @returns true if token is a 'texture_ro_1d' bool IsTextureStorageReadonly1d() const { return type_ == Type::kTextureStorageReadonly1d; @@ -721,14 +723,6 @@ 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'