diff --git a/BUILD.gn b/BUILD.gn index dc3b08597c..67cd7b81c8 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -331,6 +331,8 @@ source_set("libtint_core_src") { "src/ast/type/i32_type.h", "src/ast/type/matrix_type.cc", "src/ast/type/matrix_type.h", + "src/ast/type/multisampled_texture_type.cc", + "src/ast/type/multisampled_texture_type.h", "src/ast/type/pointer_type.cc", "src/ast/type/pointer_type.h", "src/ast/type/sampled_texture_type.cc", @@ -727,6 +729,7 @@ source_set("tint_unittests_core_src") { "src/ast/type/f32_type_test.cc", "src/ast/type/i32_type_test.cc", "src/ast/type/matrix_type_test.cc", + "src/ast/type/multisampled_texture_type_test.cc", "src/ast/type/pointer_type_test.cc", "src/ast/type/sampled_texture_type_test.cc", "src/ast/type/sampler_type_test.cc", diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index fc5fc111ff..33cd00633f 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -154,6 +154,8 @@ set(TINT_LIB_SRCS ast/type/i32_type.h ast/type/matrix_type.cc ast/type/matrix_type.h + ast/type/multisampled_texture_type.cc + ast/type/multisampled_texture_type.h ast/type/pointer_type.cc ast/type/pointer_type.h ast/type/sampled_texture_type.cc @@ -337,6 +339,7 @@ set(TINT_TEST_SRCS ast/type/f32_type_test.cc ast/type/i32_type_test.cc ast/type/matrix_type_test.cc + ast/type/multisampled_texture_type_test.cc ast/type/pointer_type_test.cc ast/type/sampled_texture_type_test.cc ast/type/sampler_type_test.cc diff --git a/src/ast/type/multisampled_texture_type.cc b/src/ast/type/multisampled_texture_type.cc new file mode 100644 index 0000000000..7bfc885e20 --- /dev/null +++ b/src/ast/type/multisampled_texture_type.cc @@ -0,0 +1,47 @@ +// 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 "src/ast/type/multisampled_texture_type.h" + +#include +#include + +namespace tint { +namespace ast { +namespace type { + +MultisampledTextureType::MultisampledTextureType(TextureDimension dim, + Type* type) + : TextureType(dim), type_(type) { + assert(type_); +} + +MultisampledTextureType::MultisampledTextureType(MultisampledTextureType&&) = + default; + +MultisampledTextureType::~MultisampledTextureType() = default; + +bool MultisampledTextureType::IsMultisampled() const { + return true; +} + +std::string MultisampledTextureType::type_name() const { + std::ostringstream out; + out << "__multisampled_texture_" << dim() << type_->type_name(); + return out.str(); +} + +} // namespace type +} // namespace ast +} // namespace tint diff --git a/src/ast/type/multisampled_texture_type.h b/src/ast/type/multisampled_texture_type.h new file mode 100644 index 0000000000..ae8f38efaf --- /dev/null +++ b/src/ast/type/multisampled_texture_type.h @@ -0,0 +1,54 @@ +// 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. + +#ifndef SRC_AST_TYPE_MULTISAMPLED_TEXTURE_TYPE_H_ +#define SRC_AST_TYPE_MULTISAMPLED_TEXTURE_TYPE_H_ + +#include + +#include "src/ast/type/texture_type.h" + +namespace tint { +namespace ast { +namespace type { + +/// A multisampled texture type. +class MultisampledTextureType : public TextureType { + public: + /// Constructor + /// @param dim the dimensionality of the texture + /// @param type the data type of the multisampled texture + MultisampledTextureType(TextureDimension dim, Type* type); + /// Move constructor + MultisampledTextureType(MultisampledTextureType&&); + ~MultisampledTextureType() override; + + /// @returns true if the type is a sampled texture type + bool IsMultisampled() const override; + + /// @returns the subtype of the sampled texture + Type* type() const { return type_; } + + /// @returns the name for this type + std::string type_name() const override; + + private: + Type* type_ = nullptr; +}; + +} // namespace type +} // namespace ast +} // namespace tint + +#endif // SRC_AST_TYPE_MULTISAMPLED_TEXTURE_TYPE_H_ diff --git a/src/ast/type/multisampled_texture_type_test.cc b/src/ast/type/multisampled_texture_type_test.cc new file mode 100644 index 0000000000..c50cef9cbf --- /dev/null +++ b/src/ast/type/multisampled_texture_type_test.cc @@ -0,0 +1,74 @@ +// 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 "src/ast/type/multisampled_texture_type.h" + +#include "gtest/gtest.h" +#include "src/ast/type/f32_type.h" + +namespace tint { +namespace ast { +namespace type { +namespace { + +using MultisampledTextureTypeTest = testing::Test; + +TEST_F(MultisampledTextureTypeTest, Is) { + F32Type f32; + MultisampledTextureType s(TextureDimension::kCube, &f32); + EXPECT_FALSE(s.IsAlias()); + EXPECT_FALSE(s.IsArray()); + EXPECT_FALSE(s.IsBool()); + EXPECT_FALSE(s.IsF32()); + EXPECT_FALSE(s.IsI32()); + EXPECT_FALSE(s.IsMatrix()); + EXPECT_FALSE(s.IsPointer()); + EXPECT_FALSE(s.IsSampler()); + EXPECT_FALSE(s.IsStruct()); + EXPECT_TRUE(s.IsTexture()); + EXPECT_FALSE(s.IsU32()); + EXPECT_FALSE(s.IsVector()); +} + +TEST_F(MultisampledTextureTypeTest, IsTextureType) { + F32Type f32; + MultisampledTextureType s(TextureDimension::kCube, &f32); + EXPECT_FALSE(s.IsDepth()); + EXPECT_TRUE(s.IsMultisampled()); + EXPECT_FALSE(s.IsSampled()); + EXPECT_FALSE(s.IsStorage()); +} + +TEST_F(MultisampledTextureTypeTest, Dim) { + F32Type f32; + MultisampledTextureType s(TextureDimension::k3d, &f32); + EXPECT_EQ(s.dim(), TextureDimension::k3d); +} + +TEST_F(MultisampledTextureTypeTest, Type) { + F32Type f32; + MultisampledTextureType s(TextureDimension::k3d, &f32); + EXPECT_EQ(s.type(), &f32); +} + +TEST_F(MultisampledTextureTypeTest, TypeName) { + F32Type f32; + MultisampledTextureType s(TextureDimension::k3d, &f32); + EXPECT_EQ(s.type_name(), "__multisampled_texture_3d__f32"); +} + +} // namespace +} // namespace type +} // namespace ast +} // namespace tint diff --git a/src/ast/type/texture_type.cc b/src/ast/type/texture_type.cc index 690a514b67..ab4e54f96a 100644 --- a/src/ast/type/texture_type.cc +++ b/src/ast/type/texture_type.cc @@ -17,6 +17,7 @@ #include #include "src/ast/type/depth_texture_type.h" +#include "src/ast/type/multisampled_texture_type.h" #include "src/ast/type/sampled_texture_type.h" #include "src/ast/type/storage_texture_type.h" @@ -41,12 +42,6 @@ std::ostream& operator<<(std::ostream& out, TextureDimension dim) { case TextureDimension::k2dArray: out << "2d_array"; break; - case TextureDimension::k2dMs: - out << "2d_ms"; - break; - case TextureDimension::k2dMsArray: - out << "2d_ms_array"; - break; case TextureDimension::k3d: out << "3d"; break; @@ -73,6 +68,9 @@ bool TextureType::IsTexture() const { bool TextureType::IsDepth() const { return false; } +bool TextureType::IsMultisampled() const { + return false; +} bool TextureType::IsStorage() const { return false; } @@ -85,6 +83,11 @@ const DepthTextureType* TextureType::AsDepth() const { return static_cast(this); } +const MultisampledTextureType* TextureType::AsMultisampled() const { + assert(IsMultisampled()); + return static_cast(this); +} + const SampledTextureType* TextureType::AsSampled() const { assert(IsSampled()); return static_cast(this); @@ -100,6 +103,11 @@ DepthTextureType* TextureType::AsDepth() { return static_cast(this); } +MultisampledTextureType* TextureType::AsMultisampled() { + assert(IsMultisampled()); + return static_cast(this); +} + SampledTextureType* TextureType::AsSampled() { assert(IsSampled()); return static_cast(this); diff --git a/src/ast/type/texture_type.h b/src/ast/type/texture_type.h index e0f44fac5b..14cac19b05 100644 --- a/src/ast/type/texture_type.h +++ b/src/ast/type/texture_type.h @@ -25,6 +25,7 @@ namespace ast { namespace type { class DepthTextureType; +class MultisampledTextureType; class SampledTextureType; class StorageTextureType; @@ -40,10 +41,6 @@ enum class TextureDimension { k2d, /// 2 dimensional array texture k2dArray, - /// 2 dimensional multi-sampled texture - k2dMs, - /// 2 dimensional multi-sampled array texture - k2dMsArray, /// 3 dimensional texture k3d, /// cube texture @@ -71,6 +68,8 @@ class TextureType : public Type { /// @returns true if this is a depth texture virtual bool IsDepth() const; + /// @returns ture if this is a multisampled texture + virtual bool IsMultisampled() const; /// @returns true if this is a storage texture virtual bool IsStorage() const; /// @returns true if this is a sampled texture @@ -78,6 +77,8 @@ class TextureType : public Type { /// @returns the texture as a depth texture const DepthTextureType* AsDepth() const; + /// @returns the texture as a multisampled texture + const MultisampledTextureType* AsMultisampled() const; /// @returns the texture as a sampled texture const SampledTextureType* AsSampled() const; /// @returns the texture as a storage texture @@ -85,6 +86,8 @@ class TextureType : public Type { /// @returns the texture as a depth texture DepthTextureType* AsDepth(); + /// @returns the texture as a multisampled texture + MultisampledTextureType* AsMultisampled(); /// @returns the texture as a sampled texture SampledTextureType* AsSampled(); /// @returns the texture as a storage texture diff --git a/src/reader/wgsl/lexer.cc b/src/reader/wgsl/lexer.cc index 66a2dc23d0..37bfeb5238 100644 --- a/src/reader/wgsl/lexer.cc +++ b/src/reader/wgsl/lexer.cc @@ -657,6 +657,10 @@ Token Lexer::check_keyword(const Source& source, const std::string& str) { 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 @@ Token Lexer::check_keyword(const Source& source, const std::string& str) { 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 4806cb6751..d21f3b66e3 100644 --- a/src/reader/wgsl/lexer_test.cc +++ b/src/reader/wgsl/lexer_test.cc @@ -401,7 +401,7 @@ TEST_P(KeywordTest, Parses) { 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 @@ INSTANTIATE_TEST_SUITE_P( 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 @@ INSTANTIATE_TEST_SUITE_P( 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 82af4ccd41..a85f7c7331 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 @@ std::unique_ptr ParserImpl::variable_decl() { // : 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 @@ ast::type::Type* ParserImpl::texture_sampler_types() { 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 @@ ast::type::Type* ParserImpl::texture_sampler_types() { } return ctx_.type_mgr().Get( - std::make_unique(sampled_dim, subtype)); + std::make_unique(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(dim, subtype)); } ast::type::TextureDimension storage_dim; @@ -675,8 +702,6 @@ ast::type::Type* ParserImpl::sampler_type() { // | 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 @@ ast::type::TextureDimension ParserImpl::sampled_texture_type() { 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 @@ ast::type::TextureDimension ParserImpl::sampled_texture_type() { 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 eb35b3d465..6da84df4a9 100644 --- a/src/reader/wgsl/parser_impl.h +++ b/src/reader/wgsl/parser_impl.h @@ -188,6 +188,10 @@ class ParserImpl { /// 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 da9a461453..6e838a2da2 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 @@ TEST_F(ParserImplTest, SampledTextureType_2dArray) { 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 3174004075..649920f889 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_Invalid) { 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"); 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"); 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"); 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"); 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_Invalid) { 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_MissingType) { 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_MissingLessThan) { TEST_F(ParserImplTest, TextureSamplerTypes_SampledTexture_MissingGreaterThan) { auto* p = parser("texture_sampled_1dtexture_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"); + 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"); + 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_2dtexture_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"); 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 @@ TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_Readonly1dR8Unorm) { 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"); 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 @@ TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_Writeonly2dR16Float) { 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 58d60f4340..dd1ad3ee30 100644 --- a/src/reader/wgsl/token.cc +++ b/src/reader/wgsl/token.cc @@ -289,6 +289,8 @@ std::string Token::TypeToName(Type type) { 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 @@ std::string Token::TypeToName(Type type) { 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 2e9f2daa05..da18df348e 100644 --- a/src/reader/wgsl/token.h +++ b/src/reader/wgsl/token.h @@ -300,6 +300,8 @@ class Token { 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 @@ class Token { 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 @@ class Token { 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 @@ class Token { 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' diff --git a/src/type_determiner_test.cc b/src/type_determiner_test.cc index 926fbde061..512e0b2ef6 100644 --- a/src/type_determiner_test.cc +++ b/src/type_determiner_test.cc @@ -1870,8 +1870,7 @@ class Intrinsic_TextureOperation return std::make_unique(); } } else if (dim == ast::type::TextureDimension::k1dArray || - dim == ast::type::TextureDimension::k2d || - dim == ast::type::TextureDimension::k2dMs) { + dim == ast::type::TextureDimension::k2d) { return std::make_unique(type, 2); } else if (dim == ast::type::TextureDimension::kCubeArray) { return std::make_unique(type, 4); @@ -2144,18 +2143,6 @@ INSTANTIATE_TEST_SUITE_P( TextureType::kI32}, TextureTestParams{ast::type::TextureDimension::k2dArray, TextureType::kU32}, - TextureTestParams{ast::type::TextureDimension::k2dMs, - TextureType::kF32}, - TextureTestParams{ast::type::TextureDimension::k2dMs, - TextureType::kI32}, - TextureTestParams{ast::type::TextureDimension::k2dMs, - TextureType::kU32}, - TextureTestParams{ast::type::TextureDimension::k2dMsArray, - TextureType::kF32}, - TextureTestParams{ast::type::TextureDimension::k2dMsArray, - TextureType::kI32}, - TextureTestParams{ast::type::TextureDimension::k2dMsArray, - TextureType::kU32}, TextureTestParams{ast::type::TextureDimension::k3d, TextureType::kF32}, TextureTestParams{ast::type::TextureDimension::k3d, TextureType::kI32}, TextureTestParams{ast::type::TextureDimension::k3d, TextureType::kU32}, diff --git a/src/writer/spirv/builder.cc b/src/writer/spirv/builder.cc index bce9333d6a..9754fb2c77 100644 --- a/src/writer/spirv/builder.cc +++ b/src/writer/spirv/builder.cc @@ -54,6 +54,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/storage_texture_type.h" @@ -2039,7 +2040,6 @@ bool Builder::GenerateTextureType(ast::type::TextureType* texture, auto dim = texture->dim(); if (dim == ast::type::TextureDimension::k1dArray || dim == ast::type::TextureDimension::k2dArray || - dim == ast::type::TextureDimension::k2dMsArray || dim == ast::type::TextureDimension::kCubeArray) { array_literal = 1u; } @@ -2058,8 +2058,7 @@ bool Builder::GenerateTextureType(ast::type::TextureType* texture, } uint32_t ms_literal = 0u; - if (dim == ast::type::TextureDimension::k2dMs || - dim == ast::type::TextureDimension::k2dMsArray) { + if (texture->IsMultisampled()) { ms_literal = 1u; } @@ -2069,7 +2068,7 @@ bool Builder::GenerateTextureType(ast::type::TextureType* texture, } uint32_t sampled_literal = 2u; - if (texture->IsSampled() || texture->IsDepth()) { + if (texture->IsMultisampled() || texture->IsSampled() || texture->IsDepth()) { sampled_literal = 1u; } @@ -2079,6 +2078,8 @@ bool Builder::GenerateTextureType(ast::type::TextureType* texture, type_id = GenerateTypeIfNeeded(&f32); } else if (texture->IsSampled()) { type_id = GenerateTypeIfNeeded(texture->AsSampled()->type()); + } else if (texture->IsMultisampled()) { + type_id = GenerateTypeIfNeeded(texture->AsMultisampled()->type()); } else if (texture->IsStorage()) { if (texture->AsStorage()->access() == ast::type::StorageAccess::kWrite) { ast::type::VoidType void_type; diff --git a/src/writer/spirv/builder_intrinsic_test.cc b/src/writer/spirv/builder_intrinsic_test.cc index 1adfbb1c2e..e950da416f 100644 --- a/src/writer/spirv/builder_intrinsic_test.cc +++ b/src/writer/spirv/builder_intrinsic_test.cc @@ -458,8 +458,7 @@ class Builder_TextureOperation return std::make_unique(); } } else if (dim == ast::type::TextureDimension::k1dArray || - dim == ast::type::TextureDimension::k2d || - dim == ast::type::TextureDimension::k2dMs) { + dim == ast::type::TextureDimension::k2d) { return std::make_unique(type, 2); } else if (dim == ast::type::TextureDimension::kCubeArray) { return std::make_unique(type, 4); @@ -523,20 +522,13 @@ class Builder_TextureOperation if (dim == ast::type::TextureDimension::k1dArray || dim == ast::type::TextureDimension::k2dArray || - dim == ast::type::TextureDimension::k2dMsArray || dim == ast::type::TextureDimension::kCubeArray) { res += "1 "; } else { res += "0 "; } - if (dim == ast::type::TextureDimension::k2dMs || - dim == ast::type::TextureDimension::k2dMsArray) { - res += "1 "; - } else { - res += "0 "; - } - + res += "0 "; res += std::to_string(sampled_literal) + " "; if (unknown_format) { diff --git a/src/writer/spirv/builder_type_test.cc b/src/writer/spirv/builder_type_test.cc index 48a5652ea6..351b1cfdc7 100644 --- a/src/writer/spirv/builder_type_test.cc +++ b/src/writer/spirv/builder_type_test.cc @@ -26,6 +26,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" @@ -771,6 +772,53 @@ inline std::ostream& operator<<(std::ostream& out, TextureType data) { return out; } +class MultisampledTextureTypeTest : public testing::TestWithParam { + public: + std::unique_ptr get_type(TextureType param) { + if (param == TextureType::kF32) { + return std::make_unique(); + } + if (param == TextureType::kI32) { + return std::make_unique(); + } + return std::make_unique(); + } + + std::string get_type_line(TextureType param) { + if (param == TextureType::kI32) { + return "%2 = OpTypeInt 32 1\n"; + } + if (param == TextureType::kU32) { + return "%2 = OpTypeInt 32 0\n"; + } + return "%2 = OpTypeFloat 32\n"; + } +}; + +TEST_P(MultisampledTextureTypeTest, Generate_2d) { + auto param = GetParam(); + auto type = get_type(param); + + ast::type::MultisampledTextureType two_d(ast::type::TextureDimension::k2d, + type.get()); + + ast::Module mod; + Builder b(&mod); + + auto id_two_d = b.GenerateTypeIfNeeded(&two_d); + ASSERT_FALSE(b.has_error()) << b.error(); + EXPECT_EQ(1u, id_two_d); + + EXPECT_EQ(DumpInstructions(b.types()), + get_type_line(param) + "%1 = OpTypeImage %2 2D 0 0 1 1 Unknown\n"); +} + +INSTANTIATE_TEST_SUITE_P(BuilderTest_Type, + MultisampledTextureTypeTest, + testing::Values(TextureType::kU32, + TextureType::kI32, + TextureType::kF32)); + class SampledTextureTypeTest : public testing::TestWithParam { public: std::unique_ptr get_type(TextureType param) { diff --git a/src/writer/wgsl/generator_impl.cc b/src/writer/wgsl/generator_impl.cc index ec38eb978b..c64a1b35a9 100644 --- a/src/writer/wgsl/generator_impl.cc +++ b/src/writer/wgsl/generator_impl.cc @@ -52,6 +52,7 @@ #include "src/ast/type/array_type.h" #include "src/ast/type/depth_texture_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" @@ -655,6 +656,8 @@ bool GeneratorImpl::EmitType(ast::type::Type* type) { out_ << "depth_"; } else if (texture->IsSampled()) { out_ << "sampled_"; + } else if (texture->IsMultisampled()) { + out_ << "multisampled_"; } else if (texture->IsStorage()) { auto* storage = texture->AsStorage(); @@ -684,12 +687,6 @@ bool GeneratorImpl::EmitType(ast::type::Type* type) { case ast::type::TextureDimension::k2dArray: out_ << "2d_array"; break; - case ast::type::TextureDimension::k2dMs: - out_ << "2d_ms"; - break; - case ast::type::TextureDimension::k2dMsArray: - out_ << "2d_ms_array"; - break; case ast::type::TextureDimension::k3d: out_ << "3d"; break; @@ -707,6 +704,14 @@ bool GeneratorImpl::EmitType(ast::type::Type* type) { if (texture->IsSampled()) { auto* sampled = texture->AsSampled(); + out_ << "<"; + if (!EmitType(sampled->type())) { + return false; + } + out_ << ">"; + } else if (texture->IsMultisampled()) { + auto* sampled = texture->AsMultisampled(); + out_ << "<"; if (!EmitType(sampled->type())) { return false; diff --git a/src/writer/wgsl/generator_impl_type_test.cc b/src/writer/wgsl/generator_impl_type_test.cc index 46e06fc18f..fe099253ab 100644 --- a/src/writer/wgsl/generator_impl_type_test.cc +++ b/src/writer/wgsl/generator_impl_type_test.cc @@ -24,6 +24,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" @@ -276,6 +277,46 @@ INSTANTIATE_TEST_SUITE_P( TextureData{ast::type::TextureDimension::kCubeArray, "texture_sampled_cube_array"})); +using WgslGenerator_MultiampledTextureTest = + testing::TestWithParam; +TEST_P(WgslGenerator_MultiampledTextureTest, EmitType_MultisampledTexture_F32) { + auto param = GetParam(); + + ast::type::F32Type f32; + ast::type::MultisampledTextureType t(param.dim, &f32); + + GeneratorImpl g; + ASSERT_TRUE(g.EmitType(&t)) << g.error(); + EXPECT_EQ(g.result(), std::string(param.name) + ""); +} + +TEST_P(WgslGenerator_MultiampledTextureTest, EmitType_MultisampledTexture_I32) { + auto param = GetParam(); + + ast::type::I32Type i32; + ast::type::MultisampledTextureType t(param.dim, &i32); + + GeneratorImpl g; + ASSERT_TRUE(g.EmitType(&t)) << g.error(); + EXPECT_EQ(g.result(), std::string(param.name) + ""); +} + +TEST_P(WgslGenerator_MultiampledTextureTest, EmitType_MultisampledTexture_U32) { + auto param = GetParam(); + + ast::type::U32Type u32; + ast::type::MultisampledTextureType t(param.dim, &u32); + + GeneratorImpl g; + ASSERT_TRUE(g.EmitType(&t)) << g.error(); + EXPECT_EQ(g.result(), std::string(param.name) + ""); +} +INSTANTIATE_TEST_SUITE_P(WgslGeneratorImplTest, + WgslGenerator_MultiampledTextureTest, + testing::Values(TextureData{ + ast::type::TextureDimension::k2d, + "texture_multisampled_2d"})); + struct StorageTextureData { ast::type::ImageFormat fmt; ast::type::TextureDimension dim;