tint/ast: Remove ast::StorageTexture
Instead use ast::TypeName.
Also improve the validation and diagnostics around providing template
arguments to types that do not accept them.
Bug: tint:1810
Change-Id: I4241d50ce0425ab721157686889e918993482876
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/119284
Reviewed-by: Dan Sinclair <dsinclair@chromium.org>
Reviewed-by: James Price <jrprice@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
Commit-Queue: Ben Clayton <bclayton@chromium.org>
diff --git a/src/tint/BUILD.gn b/src/tint/BUILD.gn
index 99d7c91..4c851e1 100644
--- a/src/tint/BUILD.gn
+++ b/src/tint/BUILD.gn
@@ -301,7 +301,6 @@
"ast/sampled_texture.h",
"ast/stage_attribute.h",
"ast/statement.h",
- "ast/storage_texture.h",
"ast/stride_attribute.h",
"ast/struct.h",
"ast/struct_member.h",
@@ -665,8 +664,6 @@
"ast/stage_attribute.h",
"ast/statement.cc",
"ast/statement.h",
- "ast/storage_texture.cc",
- "ast/storage_texture.h",
"ast/stride_attribute.cc",
"ast/stride_attribute.h",
"ast/struct.cc",
@@ -1279,6 +1276,18 @@
}
}
+ tint_unittests_source_set("libtint_unittests_ast_helper") {
+ sources = [
+ "ast/test_helper.h",
+ "ast/test_helper_test.cc",
+ ]
+ deps = [
+ ":libtint_ast_src",
+ ":libtint_base_src",
+ ":libtint_syntax_tree_src",
+ ]
+ }
+
tint_unittests_source_set("tint_unittests_ast_src") {
sources = [
"ast/alias_test.cc",
@@ -1333,7 +1342,6 @@
"ast/return_statement_test.cc",
"ast/sampled_texture_test.cc",
"ast/stage_attribute_test.cc",
- "ast/storage_texture_test.cc",
"ast/stride_attribute_test.cc",
"ast/struct_member_align_attribute_test.cc",
"ast/struct_member_offset_attribute_test.cc",
@@ -1342,8 +1350,6 @@
"ast/struct_test.cc",
"ast/switch_statement_test.cc",
"ast/templated_identifier_test.cc",
- "ast/test_helper.h",
- "ast/test_helper_test.cc",
"ast/texture_test.cc",
"ast/traverse_expressions_test.cc",
"ast/type_name_test.cc",
@@ -1358,6 +1364,7 @@
":libtint_ast_src",
":libtint_base_src",
":libtint_transform_src",
+ ":libtint_unittests_ast_helper",
]
if (tint_build_wgsl_reader && tint_build_wgsl_writer) {
@@ -1797,6 +1804,7 @@
deps = [
":libtint_base_src",
+ ":libtint_unittests_ast_helper",
":libtint_wgsl_reader_src",
]
}
@@ -1993,6 +2001,7 @@
deps = [
":libtint_base_src",
+ ":libtint_unittests_ast_helper",
":tint_unittests_ast_src",
]
}
diff --git a/src/tint/CMakeLists.txt b/src/tint/CMakeLists.txt
index d3d3097..e80e1f8 100644
--- a/src/tint/CMakeLists.txt
+++ b/src/tint/CMakeLists.txt
@@ -201,8 +201,6 @@
ast/stage_attribute.h
ast/statement.cc
ast/statement.h
- ast/storage_texture.cc
- ast/storage_texture.h
ast/stride_attribute.cc
ast/stride_attribute.h
ast/struct_member_align_attribute.cc
@@ -856,7 +854,6 @@
ast/return_statement_test.cc
ast/sampled_texture_test.cc
ast/stage_attribute_test.cc
- ast/storage_texture_test.cc
ast/stride_attribute_test.cc
ast/struct_member_align_attribute_test.cc
ast/struct_member_offset_attribute_test.cc
diff --git a/src/tint/ast/multisampled_texture_test.cc b/src/tint/ast/multisampled_texture_test.cc
index 2b81a0a..6b8125c 100644
--- a/src/tint/ast/multisampled_texture_test.cc
+++ b/src/tint/ast/multisampled_texture_test.cc
@@ -19,7 +19,6 @@
#include "src/tint/ast/matrix.h"
#include "src/tint/ast/pointer.h"
#include "src/tint/ast/sampled_texture.h"
-#include "src/tint/ast/storage_texture.h"
#include "src/tint/ast/struct.h"
#include "src/tint/ast/test_helper.h"
#include "src/tint/ast/texture.h"
@@ -35,7 +34,6 @@
Texture* t = create<MultisampledTexture>(type::TextureDimension::kCube, ty.f32());
EXPECT_TRUE(t->Is<MultisampledTexture>());
EXPECT_FALSE(t->Is<SampledTexture>());
- EXPECT_FALSE(t->Is<StorageTexture>());
}
TEST_F(AstMultisampledTextureTest, Dim) {
diff --git a/src/tint/ast/sampled_texture_test.cc b/src/tint/ast/sampled_texture_test.cc
index 506b259..01d7b65 100644
--- a/src/tint/ast/sampled_texture_test.cc
+++ b/src/tint/ast/sampled_texture_test.cc
@@ -24,7 +24,6 @@
TEST_F(AstSampledTextureTest, IsTexture) {
Texture* t = create<SampledTexture>(type::TextureDimension::kCube, ty.f32());
EXPECT_TRUE(t->Is<SampledTexture>());
- EXPECT_FALSE(t->Is<StorageTexture>());
}
TEST_F(AstSampledTextureTest, Dim) {
diff --git a/src/tint/ast/storage_texture.cc b/src/tint/ast/storage_texture.cc
deleted file mode 100644
index cb2cee7..0000000
--- a/src/tint/ast/storage_texture.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-// 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/tint/ast/storage_texture.h"
-
-#include "src/tint/program_builder.h"
-
-TINT_INSTANTIATE_TYPEINFO(tint::ast::StorageTexture);
-
-namespace tint::ast {
-
-StorageTexture::StorageTexture(ProgramID pid,
- NodeID nid,
- const Source& src,
- type::TextureDimension d,
- type::TexelFormat fmt,
- const Type* subtype,
- type::Access ac)
- : Base(pid, nid, src, d), format(fmt), type(subtype), access(ac) {}
-
-StorageTexture::StorageTexture(StorageTexture&&) = default;
-
-StorageTexture::~StorageTexture() = default;
-
-std::string StorageTexture::FriendlyName(const SymbolTable&) const {
- std::ostringstream out;
- out << "texture_storage_" << dim << "<" << format << ", " << access << ">";
- return out.str();
-}
-
-const StorageTexture* StorageTexture::Clone(CloneContext* ctx) const {
- // Clone arguments outside of create() call to have deterministic ordering
- auto src = ctx->Clone(source);
- auto* ty = ctx->Clone(type);
- return ctx->dst->create<StorageTexture>(src, dim, format, ty, access);
-}
-
-const Type* StorageTexture::SubtypeFor(type::TexelFormat format, ProgramBuilder& builder) {
- switch (format) {
- case type::TexelFormat::kR32Uint:
- case type::TexelFormat::kRgba8Uint:
- case type::TexelFormat::kRg32Uint:
- case type::TexelFormat::kRgba16Uint:
- case type::TexelFormat::kRgba32Uint: {
- return builder.ty.u32();
- }
-
- case type::TexelFormat::kR32Sint:
- case type::TexelFormat::kRgba8Sint:
- case type::TexelFormat::kRg32Sint:
- case type::TexelFormat::kRgba16Sint:
- case type::TexelFormat::kRgba32Sint: {
- return builder.ty.i32();
- }
-
- case type::TexelFormat::kBgra8Unorm:
- case type::TexelFormat::kRgba8Unorm:
- case type::TexelFormat::kRgba8Snorm:
- case type::TexelFormat::kR32Float:
- case type::TexelFormat::kRg32Float:
- case type::TexelFormat::kRgba16Float:
- case type::TexelFormat::kRgba32Float: {
- return builder.ty.f32();
- }
-
- case type::TexelFormat::kUndefined:
- break;
- }
-
- return nullptr;
-}
-
-} // namespace tint::ast
diff --git a/src/tint/ast/storage_texture.h b/src/tint/ast/storage_texture.h
deleted file mode 100644
index 646bca0..0000000
--- a/src/tint/ast/storage_texture.h
+++ /dev/null
@@ -1,77 +0,0 @@
-// 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_TINT_AST_STORAGE_TEXTURE_H_
-#define SRC_TINT_AST_STORAGE_TEXTURE_H_
-
-#include <string>
-
-#include "src/tint/ast/texture.h"
-#include "src/tint/type/access.h"
-#include "src/tint/type/texel_format.h"
-#include "src/tint/type/texture_dimension.h"
-
-namespace tint::ast {
-
-/// A storage texture type.
-class StorageTexture final : public Castable<StorageTexture, Texture> {
- public:
- /// Constructor
- /// @param pid the identifier of the program that owns this node
- /// @param nid the unique node identifier
- /// @param src the source of this node
- /// @param dim the dimensionality of the texture
- /// @param format the image format of the texture
- /// @param subtype the storage subtype. Use SubtypeFor() to calculate this.
- /// @param access_control the access control for the texture.
- StorageTexture(ProgramID pid,
- NodeID nid,
- const Source& src,
- type::TextureDimension dim,
- type::TexelFormat format,
- const Type* subtype,
- type::Access access_control);
-
- /// Move constructor
- StorageTexture(StorageTexture&&);
- ~StorageTexture() override;
-
- /// @param symbols the program's symbol table
- /// @returns the name for this type that closely resembles how it would be
- /// declared in WGSL.
- std::string FriendlyName(const SymbolTable& symbols) const override;
-
- /// Clones this type and all transitive types using the `CloneContext` `ctx`.
- /// @param ctx the clone context
- /// @return the newly cloned type
- const StorageTexture* Clone(CloneContext* ctx) const override;
-
- /// @param format the storage texture image format
- /// @param builder the ProgramBuilder used to build the returned type
- /// @returns the storage texture subtype for the given TexelFormat
- static const Type* SubtypeFor(type::TexelFormat format, ProgramBuilder& builder);
-
- /// The image format
- const type::TexelFormat format;
-
- /// The storage subtype
- const Type* const type;
-
- /// The access control
- const type::Access access;
-};
-
-} // namespace tint::ast
-
-#endif // SRC_TINT_AST_STORAGE_TEXTURE_H_
diff --git a/src/tint/ast/storage_texture_test.cc b/src/tint/ast/storage_texture_test.cc
deleted file mode 100644
index e03c4b3..0000000
--- a/src/tint/ast/storage_texture_test.cc
+++ /dev/null
@@ -1,91 +0,0 @@
-// 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/tint/ast/storage_texture.h"
-
-#include "src/tint/ast/test_helper.h"
-
-namespace tint::ast {
-namespace {
-
-using AstStorageTextureTest = TestHelper;
-
-TEST_F(AstStorageTextureTest, IsTexture) {
- auto* subtype = StorageTexture::SubtypeFor(type::TexelFormat::kRgba32Float, *this);
- Texture* ty =
- create<StorageTexture>(type::TextureDimension::k2dArray, type::TexelFormat::kRgba32Float,
- subtype, type::Access::kRead);
- EXPECT_FALSE(ty->Is<SampledTexture>());
- EXPECT_TRUE(ty->Is<StorageTexture>());
-}
-
-TEST_F(AstStorageTextureTest, Dim) {
- auto* subtype = StorageTexture::SubtypeFor(type::TexelFormat::kRgba32Float, *this);
- auto* s = create<StorageTexture>(type::TextureDimension::k2dArray,
- type::TexelFormat::kRgba32Float, subtype, type::Access::kRead);
- EXPECT_EQ(s->dim, type::TextureDimension::k2dArray);
-}
-
-TEST_F(AstStorageTextureTest, Format) {
- auto* subtype = StorageTexture::SubtypeFor(type::TexelFormat::kRgba32Float, *this);
- auto* s = create<StorageTexture>(type::TextureDimension::k2dArray,
- type::TexelFormat::kRgba32Float, subtype, type::Access::kRead);
- EXPECT_EQ(s->format, type::TexelFormat::kRgba32Float);
-}
-
-TEST_F(AstStorageTextureTest, FriendlyName) {
- auto* subtype = StorageTexture::SubtypeFor(type::TexelFormat::kRgba32Float, *this);
- auto* s = create<StorageTexture>(type::TextureDimension::k2dArray,
- type::TexelFormat::kRgba32Float, subtype, type::Access::kRead);
- EXPECT_EQ(s->FriendlyName(Symbols()), "texture_storage_2d_array<rgba32float, read>");
-}
-
-TEST_F(AstStorageTextureTest, F32) {
- auto* subtype = StorageTexture::SubtypeFor(type::TexelFormat::kRgba32Float, *this);
- Type* s = create<StorageTexture>(type::TextureDimension::k2dArray,
- type::TexelFormat::kRgba32Float, subtype, type::Access::kRead);
-
- ASSERT_TRUE(s->Is<Texture>());
- ASSERT_TRUE(s->Is<StorageTexture>());
- ASSERT_TRUE(s->As<StorageTexture>()->type->Is<ast::TypeName>());
- EXPECT_EQ(Symbols().NameFor(s->As<StorageTexture>()->type->As<ast::TypeName>()->name->symbol),
- "f32");
-}
-
-TEST_F(AstStorageTextureTest, U32) {
- auto* subtype = StorageTexture::SubtypeFor(type::TexelFormat::kRg32Uint, *this);
- Type* s = create<StorageTexture>(type::TextureDimension::k2dArray, type::TexelFormat::kRg32Uint,
- subtype, type::Access::kRead);
-
- ASSERT_TRUE(s->Is<Texture>());
- ASSERT_TRUE(s->Is<StorageTexture>());
- ASSERT_TRUE(s->As<StorageTexture>()->type->Is<ast::TypeName>());
- EXPECT_EQ(Symbols().NameFor(s->As<StorageTexture>()->type->As<ast::TypeName>()->name->symbol),
- "u32");
-}
-
-TEST_F(AstStorageTextureTest, I32) {
- auto* subtype = StorageTexture::SubtypeFor(type::TexelFormat::kRgba32Sint, *this);
- Type* s = create<StorageTexture>(type::TextureDimension::k2dArray,
- type::TexelFormat::kRgba32Sint, subtype, type::Access::kRead);
-
- ASSERT_TRUE(s->Is<Texture>());
- ASSERT_TRUE(s->Is<StorageTexture>());
- ASSERT_TRUE(s->As<StorageTexture>()->type->Is<ast::TypeName>());
- EXPECT_EQ(Symbols().NameFor(s->As<StorageTexture>()->type->As<ast::TypeName>()->name->symbol),
- "i32");
-}
-
-} // namespace
-} // namespace tint::ast
diff --git a/src/tint/inspector/resource_binding.h b/src/tint/inspector/resource_binding.h
index d968604..4c1e0c7 100644
--- a/src/tint/inspector/resource_binding.h
+++ b/src/tint/inspector/resource_binding.h
@@ -17,7 +17,7 @@
#include <cstdint>
-#include "src/tint/ast/storage_texture.h"
+#include "src/tint/type/texel_format.h"
#include "src/tint/type/texture_dimension.h"
#include "src/tint/type/type.h"
diff --git a/src/tint/intrinsics.def b/src/tint/intrinsics.def
index db589a1..c490482 100644
--- a/src/tint/intrinsics.def
+++ b/src/tint/intrinsics.def
@@ -176,6 +176,11 @@
texture_depth_cube
texture_depth_cube_array
texture_depth_multisampled_2d
+ // https://www.w3.org/TR/WGSL/#texture-storage
+ texture_storage_1d
+ texture_storage_2d
+ texture_storage_2d_array
+ texture_storage_3d
// https://www.w3.org/TR/WGSL/#external-texture-type
texture_external
}
diff --git a/src/tint/program_builder.h b/src/tint/program_builder.h
index c24dc25..0541511 100644
--- a/src/tint/program_builder.h
+++ b/src/tint/program_builder.h
@@ -68,7 +68,6 @@
#include "src/tint/ast/return_statement.h"
#include "src/tint/ast/sampled_texture.h"
#include "src/tint/ast/stage_attribute.h"
-#include "src/tint/ast/storage_texture.h"
#include "src/tint/ast/stride_attribute.h"
#include "src/tint/ast/struct_member_align_attribute.h"
#include "src/tint/ast/struct_member_offset_attribute.h"
@@ -1063,25 +1062,41 @@
/// @param dims the dimensionality of the texture
/// @param format the texel format of the texture
/// @param access the access control of the texture
- /// @returns the storage texture
- const ast::StorageTexture* storage_texture(type::TextureDimension dims,
- type::TexelFormat format,
- type::Access access) const {
- auto* subtype = ast::StorageTexture::SubtypeFor(format, *builder);
- return builder->create<ast::StorageTexture>(dims, format, subtype, access);
+ /// @returns the storage texture typename
+ const ast::TypeName* storage_texture(type::TextureDimension dims,
+ type::TexelFormat format,
+ type::Access access) const {
+ return storage_texture(builder->source_, dims, format, access);
}
/// @param source the Source of the node
/// @param dims the dimensionality of the texture
/// @param format the texel format of the texture
/// @param access the access control of the texture
- /// @returns the storage texture
- const ast::StorageTexture* storage_texture(const Source& source,
- type::TextureDimension dims,
- type::TexelFormat format,
- type::Access access) const {
- auto* subtype = ast::StorageTexture::SubtypeFor(format, *builder);
- return builder->create<ast::StorageTexture>(source, dims, format, subtype, access);
+ /// @returns the storage texture typename
+ const ast::TypeName* storage_texture(const Source& source,
+ type::TextureDimension dims,
+ type::TexelFormat format,
+ type::Access access) const {
+ switch (dims) {
+ case type::TextureDimension::k1d:
+ return (*this)(source, "texture_storage_1d", utils::ToString(format),
+ utils::ToString(access));
+ case type::TextureDimension::k2d:
+ return (*this)(source, "texture_storage_2d", utils::ToString(format),
+ utils::ToString(access));
+ case type::TextureDimension::k2dArray:
+ return (*this)(source, "texture_storage_2d_array", utils::ToString(format),
+ utils::ToString(access));
+ case type::TextureDimension::k3d:
+ return (*this)(source, "texture_storage_3d", utils::ToString(format),
+ utils::ToString(access));
+ default:
+ break;
+ }
+ TINT_ICE(ProgramBuilder, builder->Diagnostics())
+ << "invalid sampled_texture dimensions: " << dims;
+ return nullptr;
}
/// @returns the external texture
diff --git a/src/tint/reader/spirv/parser_type.h b/src/tint/reader/spirv/parser_type.h
index 33f7e05..04c8c67 100644
--- a/src/tint/reader/spirv/parser_type.h
+++ b/src/tint/reader/spirv/parser_type.h
@@ -19,11 +19,12 @@
#include <string>
#include <vector>
-#include "src/tint/ast/storage_texture.h"
#include "src/tint/castable.h"
+#include "src/tint/symbol.h"
#include "src/tint/type/access.h"
#include "src/tint/type/address_space.h"
#include "src/tint/type/sampler_kind.h"
+#include "src/tint/type/texel_format.h"
#include "src/tint/type/texture_dimension.h"
#include "src/tint/utils/block_allocator.h"
diff --git a/src/tint/reader/wgsl/parser_impl_texture_sampler_test.cc b/src/tint/reader/wgsl/parser_impl_texture_sampler_test.cc
index 29d62c5..37dbd97 100644
--- a/src/tint/reader/wgsl/parser_impl_texture_sampler_test.cc
+++ b/src/tint/reader/wgsl/parser_impl_texture_sampler_test.cc
@@ -12,6 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
+#include "src/tint/ast/test_helper.h"
#include "src/tint/reader/wgsl/parser_impl_test_helper.h"
#include "src/tint/type/depth_texture.h"
#include "src/tint/type/multisampled_texture.h"
@@ -195,11 +196,8 @@
EXPECT_FALSE(t.errored);
ASSERT_NE(t.value, nullptr);
- ASSERT_TRUE(t->Is<ast::Texture>());
- ASSERT_TRUE(t->Is<ast::StorageTexture>());
- EXPECT_EQ(t->As<ast::StorageTexture>()->format, type::TexelFormat::kRg32Float);
- EXPECT_EQ(t->As<ast::StorageTexture>()->access, type::Access::kRead);
- EXPECT_EQ(t->As<ast::Texture>()->dim, type::TextureDimension::k1d);
+ ast::CheckIdentifier(p->builder().Symbols(), t->As<ast::TypeName>()->name,
+ ast::Template("texture_storage_1d", "rg32float", "read"));
EXPECT_EQ(t->source.range, (Source::Range{{1u, 1u}, {1u, 36u}}));
}
@@ -211,11 +209,8 @@
EXPECT_FALSE(t.errored);
ASSERT_NE(t.value, nullptr);
- ASSERT_TRUE(t->Is<ast::Texture>());
- ASSERT_TRUE(t->Is<ast::StorageTexture>());
- EXPECT_EQ(t->As<ast::StorageTexture>()->format, type::TexelFormat::kR32Uint);
- EXPECT_EQ(t->As<ast::StorageTexture>()->access, type::Access::kWrite);
- EXPECT_EQ(t->As<ast::Texture>()->dim, type::TextureDimension::k2d);
+ ast::CheckIdentifier(p->builder().Symbols(), t->As<ast::TypeName>()->name,
+ ast::Template("texture_storage_2d", "r32uint", "write"));
EXPECT_EQ(t->source.range, (Source::Range{{1u, 1u}, {1u, 35u}}));
}
diff --git a/src/tint/resolver/dependency_graph.cc b/src/tint/resolver/dependency_graph.cc
index 9358335..e581b9a 100644
--- a/src/tint/resolver/dependency_graph.cc
+++ b/src/tint/resolver/dependency_graph.cc
@@ -48,7 +48,6 @@
#include "src/tint/ast/return_statement.h"
#include "src/tint/ast/sampled_texture.h"
#include "src/tint/ast/stage_attribute.h"
-#include "src/tint/ast/storage_texture.h"
#include "src/tint/ast/stride_attribute.h"
#include "src/tint/ast/struct.h"
#include "src/tint/ast/struct_member_align_attribute.h"
@@ -338,31 +337,44 @@
}
}
- /// Traverses the expression, performing symbol resolution and determining
- /// global dependencies.
+ /// Traverses the expression, performing symbol resolution and determining global dependencies.
void TraverseExpression(const ast::Expression* root) {
if (!root) {
return;
}
- ast::TraverseExpressions(root, diagnostics_, [&](const ast::Expression* expr) {
- Switch(
- expr,
- [&](const ast::IdentifierExpression* ident) {
- AddDependency(ident->identifier, ident->identifier->symbol, "identifier",
- "references");
- },
- [&](const ast::CallExpression* call) {
- if (call->target.name) {
- AddDependency(call->target.name, call->target.name->symbol, "function",
- "calls");
- }
- if (call->target.type) {
- TraverseType(call->target.type);
- }
- },
- [&](const ast::BitcastExpression* cast) { TraverseType(cast->type); });
- return ast::TraverseAction::Descend;
- });
+ utils::Vector<const ast::Expression*, 8> pending{root};
+ while (!pending.IsEmpty()) {
+ ast::TraverseExpressions(pending.Pop(), diagnostics_, [&](const ast::Expression* expr) {
+ Switch(
+ expr,
+ [&](const ast::IdentifierExpression* e) {
+ AddDependency(e->identifier, e->identifier->symbol, "identifier",
+ "references");
+ if (auto* tmpl_ident = e->identifier->As<ast::TemplatedIdentifier>()) {
+ for (auto* arg : tmpl_ident->arguments) {
+ pending.Push(arg);
+ }
+ }
+ },
+ [&](const ast::CallExpression* call) {
+ if (call->target.name) {
+ AddDependency(call->target.name, call->target.name->symbol, "function",
+ "calls");
+ if (auto* tmpl_ident =
+ call->target.name->As<ast::TemplatedIdentifier>()) {
+ for (auto* arg : tmpl_ident->arguments) {
+ pending.Push(arg);
+ }
+ }
+ }
+ if (call->target.type) {
+ TraverseType(call->target.type);
+ }
+ },
+ [&](const ast::BitcastExpression* cast) { TraverseType(cast->type); });
+ return ast::TraverseAction::Descend;
+ });
+ }
}
/// Traverses the type node, performing symbol resolution and determining
@@ -388,6 +400,11 @@
},
[&](const ast::TypeName* tn) { //
AddDependency(tn->name, tn->name->symbol, "type", "references");
+ if (auto* tmpl_ident = tn->name->As<ast::TemplatedIdentifier>()) {
+ for (auto* arg : tmpl_ident->arguments) {
+ TraverseExpression(arg);
+ }
+ }
},
[&](const ast::Vector* vec) { //
TraverseType(vec->type);
@@ -398,9 +415,6 @@
[&](const ast::MultisampledTexture* tex) { //
TraverseType(tex->type);
},
- [&](const ast::StorageTexture* tex) { //
- TraverseType(tex->type);
- },
[&](Default) { UnhandledNode(diagnostics_, ty); });
}
diff --git a/src/tint/resolver/expression_kind_test.cc b/src/tint/resolver/expression_kind_test.cc
index 8581560..7737654 100644
--- a/src/tint/resolver/expression_kind_test.cc
+++ b/src/tint/resolver/expression_kind_test.cc
@@ -121,7 +121,7 @@
Symbol sym;
switch (GetParam().def) {
case Def::kAccess:
- sym = Sym("read_write");
+ sym = Sym("write");
break;
case Def::kAddressSpace:
sym = Sym("workgroup");
@@ -155,7 +155,8 @@
switch (GetParam().use) {
case Use::kAccess:
- return; // TODO(crbug.com/tint/1810)
+ GlobalVar("v", ty("texture_storage_2d", "rgba8unorm", sym), Group(0_u), Binding(0_u));
+ break;
case Use::kAddressSpace:
return; // TODO(crbug.com/tint/1810)
case Use::kCallExpr:
@@ -174,7 +175,8 @@
Structure("s", utils::Vector{Member("m", ty(kUseSource, sym))});
break;
case Use::kTexelFormat:
- return; // TODO(crbug.com/tint/1810)
+ GlobalVar("v", ty("texture_storage_2d", sym, "write"), Group(0_u), Binding(0_u));
+ break;
case Use::kValueExpression:
GlobalVar("v", type::AddressSpace::kPrivate, Expr(kUseSource, sym));
break;
@@ -201,21 +203,18 @@
testing::ValuesIn(std::vector<Case>{
{Def::kAccess, Use::kAccess, kPass},
{Def::kAccess, Use::kAddressSpace, R"(TODO(crbug.com/tint/1810))"},
- {Def::kAccess, Use::kBinaryOp, R"(5:6 error: cannot use access 'read_write' as value)"},
- {Def::kAccess, Use::kCallExpr,
- R"(5:6 error: cannot use access 'read_write' as call target)"},
- {Def::kAccess, Use::kCallStmt,
- R"(5:6 error: cannot use access 'read_write' as call target)"},
- {Def::kAccess, Use::kFunctionReturnType,
- R"(5:6 error: cannot use access 'read_write' as type)"},
- {Def::kAccess, Use::kMemberType, R"(5:6 error: cannot use access 'read_write' as type)"},
- {Def::kAccess, Use::kTexelFormat, R"(TODO(crbug.com/tint/1810))"},
- {Def::kAccess, Use::kValueExpression,
- R"(5:6 error: cannot use access 'read_write' as value)"},
- {Def::kAccess, Use::kVariableType, R"(5:6 error: cannot use access 'read_write' as type)"},
- {Def::kAccess, Use::kUnaryOp, R"(5:6 error: cannot use access 'read_write' as value)"},
+ {Def::kAccess, Use::kBinaryOp, R"(5:6 error: cannot use access 'write' as value)"},
+ {Def::kAccess, Use::kCallExpr, R"(5:6 error: cannot use access 'write' as call target)"},
+ {Def::kAccess, Use::kCallStmt, R"(5:6 error: cannot use access 'write' as call target)"},
+ {Def::kAccess, Use::kFunctionReturnType, R"(5:6 error: cannot use access 'write' as type)"},
+ {Def::kAccess, Use::kMemberType, R"(5:6 error: cannot use access 'write' as type)"},
+ {Def::kAccess, Use::kTexelFormat, R"(error: cannot use access 'write' as texel format)"},
+ {Def::kAccess, Use::kValueExpression, R"(5:6 error: cannot use access 'write' as value)"},
+ {Def::kAccess, Use::kVariableType, R"(5:6 error: cannot use access 'write' as type)"},
+ {Def::kAccess, Use::kUnaryOp, R"(5:6 error: cannot use access 'write' as value)"},
- {Def::kAddressSpace, Use::kAccess, R"(TODO(crbug.com/tint/1810))"},
+ {Def::kAddressSpace, Use::kAccess,
+ R"(error: cannot use address space 'workgroup' as access)"},
{Def::kAddressSpace, Use::kAddressSpace, kPass},
{Def::kAddressSpace, Use::kBinaryOp,
R"(5:6 error: cannot use address space 'workgroup' as value)"},
@@ -227,7 +226,8 @@
R"(5:6 error: cannot use address space 'workgroup' as type)"},
{Def::kAddressSpace, Use::kMemberType,
R"(5:6 error: cannot use address space 'workgroup' as type)"},
- {Def::kAddressSpace, Use::kTexelFormat, R"(TODO(crbug.com/tint/1810))"},
+ {Def::kAddressSpace, Use::kTexelFormat,
+ R"(error: cannot use address space 'workgroup' as texel format)"},
{Def::kAddressSpace, Use::kValueExpression,
R"(5:6 error: cannot use address space 'workgroup' as value)"},
{Def::kAddressSpace, Use::kVariableType,
@@ -235,7 +235,7 @@
{Def::kAddressSpace, Use::kUnaryOp,
R"(5:6 error: cannot use address space 'workgroup' as value)"},
- {Def::kBuiltinFunction, Use::kAccess, R"(TODO(crbug.com/tint/1810))"},
+ {Def::kBuiltinFunction, Use::kAccess, R"(error: missing '(' for builtin function call)"},
{Def::kBuiltinFunction, Use::kAddressSpace, R"(TODO(crbug.com/tint/1810))"},
{Def::kBuiltinFunction, Use::kBinaryOp,
R"(7:8 error: missing '(' for builtin function call)"},
@@ -244,7 +244,8 @@
R"(5:6 error: cannot use builtin function 'workgroupBarrier' as type)"},
{Def::kBuiltinFunction, Use::kMemberType,
R"(5:6 error: cannot use builtin function 'workgroupBarrier' as type)"},
- {Def::kBuiltinFunction, Use::kTexelFormat, R"(TODO(crbug.com/tint/1810))"},
+ {Def::kBuiltinFunction, Use::kTexelFormat,
+ R"(error: missing '(' for builtin function call)"},
{Def::kBuiltinFunction, Use::kValueExpression,
R"(7:8 error: missing '(' for builtin function call)"},
{Def::kBuiltinFunction, Use::kVariableType,
@@ -252,7 +253,7 @@
{Def::kBuiltinFunction, Use::kUnaryOp,
R"(7:8 error: missing '(' for builtin function call)"},
- {Def::kBuiltinType, Use::kAccess, kPass},
+ {Def::kBuiltinType, Use::kAccess, R"(error: cannot use type 'vec4<f32>' as access)"},
{Def::kBuiltinType, Use::kAddressSpace, kPass},
{Def::kBuiltinType, Use::kBinaryOp,
R"(5:6 error: cannot use type 'vec4<f32>' as value
@@ -260,7 +261,8 @@
{Def::kBuiltinType, Use::kCallExpr, kPass},
{Def::kBuiltinType, Use::kFunctionReturnType, kPass},
{Def::kBuiltinType, Use::kMemberType, kPass},
- {Def::kBuiltinType, Use::kTexelFormat, R"(TODO(crbug.com/tint/1810))"},
+ {Def::kBuiltinType, Use::kTexelFormat,
+ R"(error: cannot use type 'vec4<f32>' as texel format)"},
{Def::kBuiltinType, Use::kValueExpression,
R"(5:6 error: cannot use type 'vec4<f32>' as value
7:8 note: are you missing '()' for type initializer?)"},
@@ -269,43 +271,44 @@
R"(5:6 error: cannot use type 'vec4<f32>' as value
7:8 note: are you missing '()' for type initializer?)"},
- {Def::kFunction, Use::kAccess, R"(TODO(crbug.com/tint/1810))"},
+ {Def::kFunction, Use::kAccess, R"(error: missing '(' for function call)"},
{Def::kFunction, Use::kAddressSpace, R"(TODO(crbug.com/tint/1810))"},
{Def::kFunction, Use::kBinaryOp, R"(7:8 error: missing '(' for function call)"},
{Def::kFunction, Use::kCallExpr, kPass},
{Def::kFunction, Use::kCallStmt, kPass},
{Def::kFunction, Use::kFunctionReturnType,
R"(5:6 error: cannot use function 'FUNCTION' as type
-1:2 note: 'FUNCTION' declared here)"},
+1:2 note: function 'FUNCTION' declared here)"},
{Def::kFunction, Use::kMemberType,
R"(5:6 error: cannot use function 'FUNCTION' as type
-1:2 note: 'FUNCTION' declared here)"},
- {Def::kFunction, Use::kTexelFormat, R"(TODO(crbug.com/tint/1810))"},
+1:2 note: function 'FUNCTION' declared here)"},
+ {Def::kFunction, Use::kTexelFormat, R"(error: missing '(' for function call)"},
{Def::kFunction, Use::kValueExpression, R"(7:8 error: missing '(' for function call)"},
{Def::kFunction, Use::kVariableType,
R"(5:6 error: cannot use function 'FUNCTION' as type
-1:2 note: 'FUNCTION' declared here)"},
+1:2 note: function 'FUNCTION' declared here)"},
{Def::kFunction, Use::kUnaryOp, R"(7:8 error: missing '(' for function call)"},
- {Def::kStruct, Use::kAccess, R"(TODO(crbug.com/tint/1810))"},
+ {Def::kStruct, Use::kAccess, R"(error: cannot use type 'STRUCT' as access)"},
{Def::kStruct, Use::kAddressSpace, R"(TODO(crbug.com/tint/1810))"},
{Def::kStruct, Use::kBinaryOp, R"(5:6 error: cannot use type 'STRUCT' as value
7:8 note: are you missing '()' for type initializer?
-1:2 note: 'STRUCT' declared here)"},
+1:2 note: struct 'STRUCT' declared here)"},
{Def::kStruct, Use::kFunctionReturnType, kPass},
{Def::kStruct, Use::kMemberType, kPass},
- {Def::kStruct, Use::kTexelFormat, R"(TODO(crbug.com/tint/1810))"},
+ {Def::kStruct, Use::kTexelFormat, R"(error: cannot use type 'STRUCT' as texel format)"},
{Def::kStruct, Use::kValueExpression,
R"(5:6 error: cannot use type 'STRUCT' as value
7:8 note: are you missing '()' for type initializer?
-1:2 note: 'STRUCT' declared here)"},
+1:2 note: struct 'STRUCT' declared here)"},
{Def::kStruct, Use::kVariableType, kPass},
{Def::kStruct, Use::kUnaryOp,
R"(5:6 error: cannot use type 'STRUCT' as value
7:8 note: are you missing '()' for type initializer?
-1:2 note: 'STRUCT' declared here)"},
+1:2 note: struct 'STRUCT' declared here)"},
- {Def::kTexelFormat, Use::kAccess, R"(TODO(crbug.com/tint/1810))"},
+ {Def::kTexelFormat, Use::kAccess,
+ R"(error: cannot use texel format 'rgba8unorm' as access)"},
{Def::kTexelFormat, Use::kAddressSpace, R"(TODO(crbug.com/tint/1810))"},
{Def::kTexelFormat, Use::kBinaryOp,
R"(5:6 error: cannot use texel format 'rgba8unorm' as value)"},
@@ -325,7 +328,7 @@
{Def::kTexelFormat, Use::kUnaryOp,
R"(5:6 error: cannot use texel format 'rgba8unorm' as value)"},
- {Def::kTypeAlias, Use::kAccess, R"(TODO(crbug.com/tint/1810))"},
+ {Def::kTypeAlias, Use::kAccess, R"(error: cannot use type 'i32' as access)"},
{Def::kTypeAlias, Use::kAddressSpace, R"(TODO(crbug.com/tint/1810))"},
{Def::kTypeAlias, Use::kBinaryOp,
R"(5:6 error: cannot use type 'i32' as value
@@ -333,7 +336,7 @@
{Def::kTypeAlias, Use::kCallExpr, kPass},
{Def::kTypeAlias, Use::kFunctionReturnType, kPass},
{Def::kTypeAlias, Use::kMemberType, kPass},
- {Def::kTypeAlias, Use::kTexelFormat, R"(TODO(crbug.com/tint/1810))"},
+ {Def::kTypeAlias, Use::kTexelFormat, R"(error: cannot use type 'i32' as texel format)"},
{Def::kTypeAlias, Use::kValueExpression,
R"(5:6 error: cannot use type 'i32' as value
7:8 note: are you missing '()' for type initializer?)"},
@@ -342,26 +345,27 @@
R"(5:6 error: cannot use type 'i32' as value
7:8 note: are you missing '()' for type initializer?)"},
- {Def::kVariable, Use::kAccess, R"(TODO(crbug.com/tint/1810))"},
+ {Def::kVariable, Use::kAccess, R"(error: cannot use 'VARIABLE' of type 'i32' as access)"},
{Def::kVariable, Use::kAddressSpace, R"(TODO(crbug.com/tint/1810))"},
{Def::kVariable, Use::kBinaryOp, kPass},
{Def::kVariable, Use::kCallStmt,
R"(5:6 error: cannot use const 'VARIABLE' as call target
-1:2 note: 'VARIABLE' declared here)"},
+1:2 note: const 'VARIABLE' declared here)"},
{Def::kVariable, Use::kCallExpr,
R"(5:6 error: cannot use const 'VARIABLE' as call target
-1:2 note: 'VARIABLE' declared here)"},
+1:2 note: const 'VARIABLE' declared here)"},
{Def::kVariable, Use::kFunctionReturnType,
R"(5:6 error: cannot use const 'VARIABLE' as type
-1:2 note: 'VARIABLE' declared here)"},
+1:2 note: const 'VARIABLE' declared here)"},
{Def::kVariable, Use::kMemberType,
R"(5:6 error: cannot use const 'VARIABLE' as type
-1:2 note: 'VARIABLE' declared here)"},
- {Def::kVariable, Use::kTexelFormat, R"(TODO(crbug.com/tint/1810))"},
+1:2 note: const 'VARIABLE' declared here)"},
+ {Def::kVariable, Use::kTexelFormat,
+ R"(error: cannot use 'VARIABLE' of type 'i32' as texel format)"},
{Def::kVariable, Use::kValueExpression, kPass},
{Def::kVariable, Use::kVariableType,
R"(5:6 error: cannot use const 'VARIABLE' as type
-1:2 note: 'VARIABLE' declared here)"},
+1:2 note: const 'VARIABLE' declared here)"},
{Def::kVariable, Use::kUnaryOp, kPass},
}));
diff --git a/src/tint/resolver/resolver.cc b/src/tint/resolver/resolver.cc
index 06b0c18..ab1970a 100644
--- a/src/tint/resolver/resolver.cc
+++ b/src/tint/resolver/resolver.cc
@@ -40,7 +40,6 @@
#include "src/tint/ast/pointer.h"
#include "src/tint/ast/return_statement.h"
#include "src/tint/ast/sampled_texture.h"
-#include "src/tint/ast/storage_texture.h"
#include "src/tint/ast/switch_statement.h"
#include "src/tint/ast/traverse_expressions.h"
#include "src/tint/ast/type_name.h"
@@ -308,22 +307,9 @@
}
return nullptr;
},
- [&](const ast::StorageTexture* t) -> type::StorageTexture* {
- if (auto* el = Type(t->type)) {
- if (!validator_.StorageTexture(t)) {
- return nullptr;
- }
- return builder_->create<type::StorageTexture>(t->dim, t->format, t->access, el);
- }
- return nullptr;
- },
[&](const ast::TypeName* t) -> type::Type* {
Mark(t->name);
- if (t->name->Is<ast::TemplatedIdentifier>()) {
- TINT_UNREACHABLE(Resolver, diagnostics_) << "TODO(crbug.com/tint/1810)";
- }
-
auto resolved = dependencies_.resolved_identifiers.Get(t->name);
if (!resolved) {
TINT_ICE(Resolver, diagnostics_)
@@ -338,6 +324,15 @@
ErrorMismatchedResolvedIdentifier(t->source, *resolved, "type");
return nullptr;
}
+
+ if (TINT_UNLIKELY(t->name->Is<ast::TemplatedIdentifier>())) {
+ AddError("type '" + builder_->Symbols().NameFor(t->name->symbol) +
+ "' does not take template arguments",
+ t->source);
+ NoteDeclarationSource(ast_node);
+ return nullptr;
+ }
+
return type;
}
if (auto b = resolved->BuiltinType(); b != type::Builtin::kUndefined) {
@@ -2431,9 +2426,18 @@
return call;
}
-type::Type* Resolver::BuiltinType(type::Builtin builtin_ty, const ast::Identifier* ident) const {
+type::Type* Resolver::BuiltinType(type::Builtin builtin_ty, const ast::Identifier* ident) {
auto& b = *builder_;
+ auto check_no_tmpl_args = [&](type::Type* ty) -> type::Type* {
+ if (TINT_UNLIKELY(ident->Is<ast::TemplatedIdentifier>())) {
+ AddError("type '" + b.Symbols().NameFor(ident->symbol) +
+ "' does not take template arguments",
+ ident->source);
+ return nullptr;
+ }
+ return ty;
+ };
auto f32 = [&] { return b.create<type::F32>(); };
auto i32 = [&] { return b.create<type::I32>(); };
auto u32 = [&] { return b.create<type::U32>(); };
@@ -2446,94 +2450,143 @@
auto mat = [&](type::Type* el, uint32_t num_columns, uint32_t num_rows) {
return el ? b.create<type::Matrix>(vec(el, num_rows), num_columns) : nullptr;
};
+ auto templated_identifier = [&](size_t num_args) -> const ast::TemplatedIdentifier* {
+ auto* tmpl_ident = ident->As<ast::TemplatedIdentifier>();
+ if (TINT_UNLIKELY(!tmpl_ident)) {
+ AddError("expected '<' for '" + b.Symbols().NameFor(ident->symbol) + "'",
+ Source{ident->source.range.end});
+ return nullptr;
+ }
+ if (TINT_UNLIKELY(tmpl_ident->arguments.Length() != num_args)) {
+ AddError("'" + b.Symbols().NameFor(ident->symbol) + "' requires " +
+ std::to_string(num_args) + " template arguments",
+ ident->source);
+ return nullptr;
+ }
+ return tmpl_ident;
+ };
+ auto storage_texture = [&](type::TextureDimension dim) -> type::StorageTexture* {
+ auto* tmpl_ident = templated_identifier(2);
+ if (TINT_UNLIKELY(!tmpl_ident)) {
+ return nullptr;
+ }
+ auto* format = sem_.AsTexelFormat(Expression(tmpl_ident->arguments[0]));
+ if (TINT_UNLIKELY(!format)) {
+ return nullptr;
+ }
+ auto* access = sem_.AsAccess(Expression(tmpl_ident->arguments[1]));
+ if (TINT_UNLIKELY(!access)) {
+ return nullptr;
+ }
+ auto* subtype = type::StorageTexture::SubtypeFor(format->Value(), builder_->Types());
+ auto* tex = b.create<type::StorageTexture>(dim, format->Value(), access->Value(), subtype);
+ if (!validator_.StorageTexture(tex, ident->source)) {
+ return nullptr;
+ }
+ return tex;
+ };
switch (builtin_ty) {
case type::Builtin::kBool:
- return b.create<type::Bool>();
+ return check_no_tmpl_args(b.create<type::Bool>());
case type::Builtin::kI32:
- return i32();
+ return check_no_tmpl_args(i32());
case type::Builtin::kU32:
- return u32();
+ return check_no_tmpl_args(u32());
case type::Builtin::kF16:
- return f16();
+ return check_no_tmpl_args(f16());
case type::Builtin::kF32:
- return b.create<type::F32>();
+ return check_no_tmpl_args(b.create<type::F32>());
case type::Builtin::kMat2X2F:
- return mat(f32(), 2u, 2u);
+ return check_no_tmpl_args(mat(f32(), 2u, 2u));
case type::Builtin::kMat2X3F:
- return mat(f32(), 2u, 3u);
+ return check_no_tmpl_args(mat(f32(), 2u, 3u));
case type::Builtin::kMat2X4F:
- return mat(f32(), 2u, 4u);
+ return check_no_tmpl_args(mat(f32(), 2u, 4u));
case type::Builtin::kMat3X2F:
- return mat(f32(), 3u, 2u);
+ return check_no_tmpl_args(mat(f32(), 3u, 2u));
case type::Builtin::kMat3X3F:
- return mat(f32(), 3u, 3u);
+ return check_no_tmpl_args(mat(f32(), 3u, 3u));
case type::Builtin::kMat3X4F:
- return mat(f32(), 3u, 4u);
+ return check_no_tmpl_args(mat(f32(), 3u, 4u));
case type::Builtin::kMat4X2F:
- return mat(f32(), 4u, 2u);
+ return check_no_tmpl_args(mat(f32(), 4u, 2u));
case type::Builtin::kMat4X3F:
- return mat(f32(), 4u, 3u);
+ return check_no_tmpl_args(mat(f32(), 4u, 3u));
case type::Builtin::kMat4X4F:
- return mat(f32(), 4u, 4u);
+ return check_no_tmpl_args(mat(f32(), 4u, 4u));
case type::Builtin::kMat2X2H:
- return mat(f16(), 2u, 2u);
+ return check_no_tmpl_args(mat(f16(), 2u, 2u));
case type::Builtin::kMat2X3H:
- return mat(f16(), 2u, 3u);
+ return check_no_tmpl_args(mat(f16(), 2u, 3u));
case type::Builtin::kMat2X4H:
- return mat(f16(), 2u, 4u);
+ return check_no_tmpl_args(mat(f16(), 2u, 4u));
case type::Builtin::kMat3X2H:
- return mat(f16(), 3u, 2u);
+ return check_no_tmpl_args(mat(f16(), 3u, 2u));
case type::Builtin::kMat3X3H:
- return mat(f16(), 3u, 3u);
+ return check_no_tmpl_args(mat(f16(), 3u, 3u));
case type::Builtin::kMat3X4H:
- return mat(f16(), 3u, 4u);
+ return check_no_tmpl_args(mat(f16(), 3u, 4u));
case type::Builtin::kMat4X2H:
- return mat(f16(), 4u, 2u);
+ return check_no_tmpl_args(mat(f16(), 4u, 2u));
case type::Builtin::kMat4X3H:
- return mat(f16(), 4u, 3u);
+ return check_no_tmpl_args(mat(f16(), 4u, 3u));
case type::Builtin::kMat4X4H:
- return mat(f16(), 4u, 4u);
+ return check_no_tmpl_args(mat(f16(), 4u, 4u));
case type::Builtin::kVec2F:
- return vec(f32(), 2u);
+ return check_no_tmpl_args(vec(f32(), 2u));
case type::Builtin::kVec3F:
- return vec(f32(), 3u);
+ return check_no_tmpl_args(vec(f32(), 3u));
case type::Builtin::kVec4F:
- return vec(f32(), 4u);
+ return check_no_tmpl_args(vec(f32(), 4u));
case type::Builtin::kVec2H:
- return vec(f16(), 2u);
+ return check_no_tmpl_args(vec(f16(), 2u));
case type::Builtin::kVec3H:
- return vec(f16(), 3u);
+ return check_no_tmpl_args(vec(f16(), 3u));
case type::Builtin::kVec4H:
- return vec(f16(), 4u);
+ return check_no_tmpl_args(vec(f16(), 4u));
case type::Builtin::kVec2I:
- return vec(i32(), 2u);
+ return check_no_tmpl_args(vec(i32(), 2u));
case type::Builtin::kVec3I:
- return vec(i32(), 3u);
+ return check_no_tmpl_args(vec(i32(), 3u));
case type::Builtin::kVec4I:
- return vec(i32(), 4u);
+ return check_no_tmpl_args(vec(i32(), 4u));
case type::Builtin::kVec2U:
- return vec(u32(), 2u);
+ return check_no_tmpl_args(vec(u32(), 2u));
case type::Builtin::kVec3U:
- return vec(u32(), 3u);
+ return check_no_tmpl_args(vec(u32(), 3u));
case type::Builtin::kVec4U:
- return vec(u32(), 4u);
+ return check_no_tmpl_args(vec(u32(), 4u));
case type::Builtin::kSampler:
- return builder_->create<type::Sampler>(type::SamplerKind::kSampler);
+ return check_no_tmpl_args(builder_->create<type::Sampler>(type::SamplerKind::kSampler));
case type::Builtin::kSamplerComparison:
- return builder_->create<type::Sampler>(type::SamplerKind::kComparisonSampler);
+ return check_no_tmpl_args(
+ builder_->create<type::Sampler>(type::SamplerKind::kComparisonSampler));
case type::Builtin::kTextureDepth2D:
- return builder_->create<type::DepthTexture>(type::TextureDimension::k2d);
+ return check_no_tmpl_args(
+ builder_->create<type::DepthTexture>(type::TextureDimension::k2d));
case type::Builtin::kTextureDepth2DArray:
- return builder_->create<type::DepthTexture>(type::TextureDimension::k2dArray);
+ return check_no_tmpl_args(
+ builder_->create<type::DepthTexture>(type::TextureDimension::k2dArray));
case type::Builtin::kTextureDepthCube:
- return builder_->create<type::DepthTexture>(type::TextureDimension::kCube);
+ return check_no_tmpl_args(
+ builder_->create<type::DepthTexture>(type::TextureDimension::kCube));
case type::Builtin::kTextureDepthCubeArray:
- return builder_->create<type::DepthTexture>(type::TextureDimension::kCubeArray);
+ return check_no_tmpl_args(
+ builder_->create<type::DepthTexture>(type::TextureDimension::kCubeArray));
case type::Builtin::kTextureDepthMultisampled2D:
- return builder_->create<type::DepthMultisampledTexture>(type::TextureDimension::k2d);
+ return check_no_tmpl_args(
+ builder_->create<type::DepthMultisampledTexture>(type::TextureDimension::k2d));
case type::Builtin::kTextureExternal:
- return builder_->create<type::ExternalTexture>();
+ return check_no_tmpl_args(builder_->create<type::ExternalTexture>());
+ case type::Builtin::kTextureStorage1D:
+ return storage_texture(type::TextureDimension::k1d);
+ case type::Builtin::kTextureStorage2D:
+ return storage_texture(type::TextureDimension::k2d);
+ case type::Builtin::kTextureStorage2DArray:
+ return storage_texture(type::TextureDimension::k2dArray);
+ case type::Builtin::kTextureStorage3D:
+ return storage_texture(type::TextureDimension::k3d);
case type::Builtin::kUndefined:
break;
}
@@ -4021,19 +4074,43 @@
AddError("cannot use " + resolved.String(builder_->Symbols(), diagnostics_) + " as " +
std::string(wanted),
source);
+ NoteDeclarationSource(resolved.Node());
+}
+void Resolver::NoteDeclarationSource(const ast::Node* node) {
Switch(
- resolved.Node(),
- [&](const ast::TypeDecl* n) {
- AddNote("'" + builder_->Symbols().NameFor(n->name->symbol) + "' declared here",
+ node,
+ [&](const ast::Struct* n) {
+ AddNote("struct '" + builder_->Symbols().NameFor(n->name->symbol) + "' declared here",
n->source);
},
- [&](const ast::Variable* n) {
- AddNote("'" + builder_->Symbols().NameFor(n->name->symbol) + "' declared here",
+ [&](const ast::Alias* n) {
+ AddNote("alias '" + builder_->Symbols().NameFor(n->name->symbol) + "' declared here",
n->source);
},
+ [&](const ast::Var* n) {
+ AddNote("var '" + builder_->Symbols().NameFor(n->name->symbol) + "' declared here",
+ n->source);
+ },
+ [&](const ast::Let* n) {
+ AddNote("let '" + builder_->Symbols().NameFor(n->name->symbol) + "' declared here",
+ n->source);
+ },
+ [&](const ast::Override* n) {
+ AddNote("override '" + builder_->Symbols().NameFor(n->name->symbol) + "' declared here",
+ n->source);
+ },
+ [&](const ast::Const* n) {
+ AddNote("const '" + builder_->Symbols().NameFor(n->name->symbol) + "' declared here",
+ n->source);
+ },
+ [&](const ast::Parameter* n) {
+ AddNote(
+ "parameter '" + builder_->Symbols().NameFor(n->name->symbol) + "' declared here",
+ n->source);
+ },
[&](const ast::Function* n) {
- AddNote("'" + builder_->Symbols().NameFor(n->name->symbol) + "' declared here",
+ AddNote("function '" + builder_->Symbols().NameFor(n->name->symbol) + "' declared here",
n->source);
});
}
diff --git a/src/tint/resolver/resolver.h b/src/tint/resolver/resolver.h
index 0d3c879..bc8821a 100644
--- a/src/tint/resolver/resolver.h
+++ b/src/tint/resolver/resolver.h
@@ -432,6 +432,11 @@
const ResolvedIdentifier& resolved,
std::string_view wanted);
+ /// If @p node is a module-scope type, variable or function declaration, then appends a note
+ /// diagnostic where this declaration was declared, otherwise the function does nothing.
+ /// @param node the AST node.
+ void NoteDeclarationSource(const ast::Node* node);
+
/// Adds the given error message to the diagnostics
void AddError(const std::string& msg, const Source& source) const;
@@ -443,7 +448,7 @@
/// @returns the type::Type for the builtin type @p builtin_ty with the identifier @p ident
/// @note: Will raise an ICE if @p symbol is not a builtin type.
- type::Type* BuiltinType(type::Builtin builtin_ty, const ast::Identifier* ident) const;
+ type::Type* BuiltinType(type::Builtin builtin_ty, const ast::Identifier* ident);
// ArrayInitializerSig represents a unique array initializer signature.
// It is a tuple of the array type, number of arguments provided and earliest evaluation stage.
diff --git a/src/tint/resolver/sem_helper.cc b/src/tint/resolver/sem_helper.cc
index bb769ab..e288707 100644
--- a/src/tint/resolver/sem_helper.cc
+++ b/src/tint/resolver/sem_helper.cc
@@ -37,30 +37,40 @@
return sem ? const_cast<type::Type*>(sem->Type()) : nullptr;
}
-void SemHelper::ErrorExpectedValueExpr(const sem::Expression* expr) const {
+void SemHelper::ErrorUnexpectedExprKind(const sem::Expression* expr,
+ std::string_view wanted) const {
Switch(
expr, //
+ [&](const sem::VariableUser* var_expr) {
+ auto name =
+ builder_->Symbols().NameFor(var_expr->Variable()->Declaration()->name->symbol);
+ auto type = var_expr->Type()->FriendlyName(builder_->Symbols());
+ AddError("cannot use '" + name + "' of type '" + type + "' as " + std::string(wanted),
+ var_expr->Declaration()->source);
+ },
+ [&](const sem::ValueExpression* val_expr) {
+ auto type = val_expr->Type()->FriendlyName(builder_->Symbols());
+ AddError("cannot use expression of type '" + type + "' as " + std::string(wanted),
+ val_expr->Declaration()->source);
+ },
[&](const sem::TypeExpression* ty_expr) {
auto name = ty_expr->Type()->FriendlyName(builder_->Symbols());
- AddError("cannot use type '" + name + "' as value", ty_expr->Declaration()->source);
- if (auto* ident = ty_expr->Declaration()->As<ast::IdentifierExpression>()) {
- AddNote("are you missing '()' for type initializer?",
- Source{{ident->source.range.end}});
- }
- if (auto* str = ty_expr->Type()->As<type::Struct>()) {
- AddNote("'" + name + "' declared here", str->Source());
- }
+ AddError("cannot use type '" + name + "' as " + std::string(wanted),
+ ty_expr->Declaration()->source);
},
[&](const sem::BuiltinEnumExpression<type::Access>* access) {
- AddError("cannot use access '" + utils::ToString(access->Value()) + "' as value",
+ AddError("cannot use access '" + utils::ToString(access->Value()) + "' as " +
+ std::string(wanted),
access->Declaration()->source);
},
[&](const sem::BuiltinEnumExpression<type::AddressSpace>* addr) {
- AddError("cannot use address space '" + utils::ToString(addr->Value()) + "' as value",
+ AddError("cannot use address space '" + utils::ToString(addr->Value()) + "' as " +
+ std::string(wanted),
addr->Declaration()->source);
},
[&](const sem::BuiltinEnumExpression<type::TexelFormat>* fmt) {
- AddError("cannot use texel format '" + utils::ToString(fmt->Value()) + "' as value",
+ AddError("cannot use texel format '" + utils::ToString(fmt->Value()) + "' as " +
+ std::string(wanted),
fmt->Declaration()->source);
},
[&](Default) {
@@ -69,6 +79,20 @@
});
}
+void SemHelper::ErrorExpectedValueExpr(const sem::Expression* expr) const {
+ ErrorUnexpectedExprKind(expr, "value");
+ if (auto* ty_expr = expr->As<sem::TypeExpression>()) {
+ if (auto* ident = ty_expr->Declaration()->As<ast::IdentifierExpression>()) {
+ AddNote("are you missing '()' for type initializer?",
+ Source{{ident->source.range.end}});
+ }
+ if (auto* str = ty_expr->Type()->As<type::Struct>()) {
+ AddNote("struct '" + str->FriendlyName(builder_->Symbols()) + "' declared here",
+ str->Source());
+ }
+ }
+}
+
void SemHelper::AddError(const std::string& msg, const Source& source) const {
builder_->Diagnostics().add_error(diag::System::Resolver, msg, source);
}
diff --git a/src/tint/resolver/sem_helper.h b/src/tint/resolver/sem_helper.h
index 9c918cd..db3eda4 100644
--- a/src/tint/resolver/sem_helper.h
+++ b/src/tint/resolver/sem_helper.h
@@ -20,6 +20,7 @@
#include "src/tint/diagnostic/diagnostic.h"
#include "src/tint/program_builder.h"
#include "src/tint/resolver/dependency_graph.h"
+#include "src/tint/sem/builtin_enum_expression.h"
#include "src/tint/utils/map.h"
namespace tint::resolver {
@@ -61,25 +62,46 @@
}
/// @param expr the semantic node
- /// @returns one of:
- /// * nullptr if @p expr is nullptr
- /// * @p expr if the static pointer type already derives from sem::ValueExpression
- /// * @p expr cast to sem::ValueExpression if the cast is successful
- /// * nullptr if @p expr is not a sem::ValueExpression. In this case an error diagnostic is
- /// raised.
- template <typename EXPR>
- auto* AsValue(EXPR* expr) const {
- if constexpr (traits::IsTypeOrDerived<EXPR, sem::ValueExpression>) {
- return expr;
- } else {
- if (TINT_LIKELY(expr)) {
- if (auto* val = expr->template As<sem::ValueExpression>(); TINT_LIKELY(val)) {
- return val;
- }
- ErrorExpectedValueExpr(expr);
+ /// @returns nullptr if @p expr is nullptr, or @p expr cast to sem::ValueExpression if the cast
+ /// is successful, otherwise an error diagnostic is raised.
+ sem::ValueExpression* AsValue(sem::Expression* expr) const {
+ if (TINT_LIKELY(expr)) {
+ if (auto* val = expr->As<sem::ValueExpression>(); TINT_LIKELY(val)) {
+ return val;
}
- return static_cast<sem::ValueExpression*>(nullptr);
+ ErrorExpectedValueExpr(expr);
}
+ return nullptr;
+ }
+
+ /// @param expr the semantic node
+ /// @returns nullptr if @p expr is nullptr, or @p expr cast to
+ /// sem::BuiltinEnumExpression<type::TexelFormat> if the cast is successful, otherwise an error
+ /// diagnostic is raised.
+ sem::BuiltinEnumExpression<type::TexelFormat>* AsTexelFormat(sem::Expression* expr) const {
+ if (TINT_LIKELY(expr)) {
+ if (auto* val = expr->As<sem::BuiltinEnumExpression<type::TexelFormat>>();
+ TINT_LIKELY(val)) {
+ return val;
+ }
+ ErrorUnexpectedExprKind(expr, "texel format");
+ }
+ return nullptr;
+ }
+
+ /// @param expr the semantic node
+ /// @returns nullptr if @p expr is nullptr, or @p expr cast to
+ /// sem::BuiltinEnumExpression<type::Access> if the cast is successful, otherwise an error
+ /// diagnostic is raised.
+ sem::BuiltinEnumExpression<type::Access>* AsAccess(sem::Expression* expr) const {
+ if (TINT_LIKELY(expr)) {
+ if (auto* val = expr->As<sem::BuiltinEnumExpression<type::Access>>();
+ TINT_LIKELY(val)) {
+ return val;
+ }
+ ErrorUnexpectedExprKind(expr, "access");
+ }
+ return nullptr;
}
/// @returns the resolved type of the ast::Expression @p expr
@@ -100,6 +122,10 @@
void ErrorExpectedValueExpr(const sem::Expression* expr) const;
private:
+ /// Raises an error diagnostic that the expression @p got was not of the kind @p wanted.
+ /// @param expr the expression
+ void ErrorUnexpectedExprKind(const sem::Expression* expr, std::string_view wanted) const;
+
/// Adds the given error message to the diagnostics
void AddError(const std::string& msg, const Source& source) const;
diff --git a/src/tint/resolver/type_validation_test.cc b/src/tint/resolver/type_validation_test.cc
index b28cecf..70b3837 100644
--- a/src/tint/resolver/type_validation_test.cc
+++ b/src/tint/resolver/type_validation_test.cc
@@ -1064,26 +1064,26 @@
namespace StorageTextureTests {
struct DimensionParams {
- type::TextureDimension dim;
+ const char* name;
bool is_valid;
};
static constexpr DimensionParams Dimension_cases[] = {
- DimensionParams{type::TextureDimension::k1d, true},
- DimensionParams{type::TextureDimension::k2d, true},
- DimensionParams{type::TextureDimension::k2dArray, true},
- DimensionParams{type::TextureDimension::k3d, true},
- DimensionParams{type::TextureDimension::kCube, false},
- DimensionParams{type::TextureDimension::kCubeArray, false}};
+ DimensionParams{"texture_storage_1d", true},
+ DimensionParams{"texture_storage_2d", true},
+ DimensionParams{"texture_storage_2d_array", true},
+ DimensionParams{"texture_storage_3d", true},
+ DimensionParams{"texture_storage_cube", false},
+ DimensionParams{"texture_storage_cube_array", false}};
using StorageTextureDimensionTest = ResolverTestWithParam<DimensionParams>;
TEST_P(StorageTextureDimensionTest, All) {
// @group(0) @binding(0)
- // var a : texture_storage_*<ru32int, write>;
+ // var a : texture_storage_*<r32uint, write>;
auto& params = GetParam();
- auto* st = ty.storage_texture(Source{{12, 34}}, params.dim, type::TexelFormat::kR32Uint,
- type::Access::kWrite);
+ auto* st = ty(Source{{12, 34}}, params.name, utils::ToString(type::TexelFormat::kR32Uint),
+ utils::ToString(type::Access::kWrite));
GlobalVar("a", st, Group(0_a), Binding(0_a));
@@ -1091,8 +1091,7 @@
EXPECT_TRUE(r()->Resolve()) << r()->error();
} else {
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(),
- "12:34 error: cube dimensions for storage textures are not supported");
+ EXPECT_EQ(r()->error(), "12:34 error: unknown type: '" + std::string(params.name) + "'");
}
}
INSTANTIATE_TEST_SUITE_P(ResolverTypeValidationTest,
@@ -1165,22 +1164,33 @@
using StorageTextureAccessTest = ResolverTest;
-TEST_F(StorageTextureAccessTest, MissingAccess_Fail) {
+TEST_F(StorageTextureAccessTest, MissingTemplates) {
// @group(0) @binding(0)
- // var a : texture_storage_1d<ru32int>;
+ // var a : texture_storage_1d<r32uint>;
- auto* st = ty.storage_texture(Source{{12, 34}}, type::TextureDimension::k1d,
- type::TexelFormat::kR32Uint, type::Access::kUndefined);
+ auto* st = ty(Source{{12, 34}}, "texture_storage_1d");
GlobalVar("a", st, Group(0_a), Binding(0_a));
EXPECT_FALSE(r()->Resolve());
- EXPECT_EQ(r()->error(), "12:34 error: storage texture missing access control");
+ EXPECT_EQ(r()->error(), "12:34 error: expected '<' for 'texture_storage_1d'");
+}
+
+TEST_F(StorageTextureAccessTest, MissingAccess_Fail) {
+ // @group(0) @binding(0)
+ // var a : texture_storage_1d<r32uint>;
+
+ auto* st = ty(Source{{12, 34}}, "texture_storage_1d", "r32uint");
+
+ GlobalVar("a", st, Group(0_a), Binding(0_a));
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(), R"(12:34 error: 'texture_storage_1d' requires 2 template arguments)");
}
TEST_F(StorageTextureAccessTest, RWAccess_Fail) {
// @group(0) @binding(0)
- // var a : texture_storage_1d<ru32int, read_write>;
+ // var a : texture_storage_1d<r32uint, read_write>;
auto* st = ty.storage_texture(Source{{12, 34}}, type::TextureDimension::k1d,
type::TexelFormat::kR32Uint, type::Access::kReadWrite);
@@ -1194,7 +1204,7 @@
TEST_F(StorageTextureAccessTest, ReadOnlyAccess_Fail) {
// @group(0) @binding(0)
- // var a : texture_storage_1d<ru32int, read>;
+ // var a : texture_storage_1d<r32uint, read>;
auto* st = ty.storage_texture(Source{{12, 34}}, type::TextureDimension::k1d,
type::TexelFormat::kR32Uint, type::Access::kRead);
@@ -1208,7 +1218,7 @@
TEST_F(StorageTextureAccessTest, WriteOnlyAccess_Pass) {
// @group(0) @binding(0)
- // var a : texture_storage_1d<ru32int, write>;
+ // var a : texture_storage_1d<r32uint, write>;
auto* st = ty.storage_texture(type::TextureDimension::k1d, type::TexelFormat::kR32Uint,
type::Access::kWrite);
@@ -1445,5 +1455,91 @@
} // namespace BuiltinTypeAliasTests
+namespace TypeDoesNotTakeTemplateArgs {
+
+using ResolverUntemplatedTypeUsedWithTemplateArgs = ResolverTestWithParam<const char*>;
+
+TEST_P(ResolverUntemplatedTypeUsedWithTemplateArgs, Builtin_UseWithTemplateArgs) {
+ // enable f16;
+ // var<private> v : f32<true>;
+
+ Enable(ast::Extension::kF16);
+ GlobalVar("v", type::AddressSpace::kPrivate, ty(Source{{12, 34}}, GetParam(), true));
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(), "12:34 error: type '" + std::string(GetParam()) +
+ "' does not take template arguments");
+}
+
+TEST_P(ResolverUntemplatedTypeUsedWithTemplateArgs, BuiltinAlias_UseWithTemplateArgs) {
+ // enable f16;
+ // alias A = f32;
+ // var<private> v : S<true>;
+
+ Enable(ast::Extension::kF16);
+ Alias(Source{{56, 78}}, "A", ty(GetParam()));
+ GlobalVar("v", type::AddressSpace::kPrivate, ty(Source{{12, 34}}, "A", true));
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(),
+ R"(12:34 error: type 'A' does not take template arguments
+56:78 note: alias 'A' declared here)");
+}
+
+INSTANTIATE_TEST_SUITE_P(BuiltinTypes,
+ ResolverUntemplatedTypeUsedWithTemplateArgs,
+ testing::Values("bool",
+ "f16",
+ "f32",
+ "i32",
+ "u32",
+ "mat2x2f",
+ "mat2x2h",
+ "mat2x3f",
+ "mat2x3h",
+ "mat2x4f",
+ "mat2x4h",
+ "mat3x2f",
+ "mat3x2h",
+ "mat3x3f",
+ "mat3x3h",
+ "mat3x4f",
+ "mat3x4h",
+ "mat4x2f",
+ "mat4x2h",
+ "mat4x3f",
+ "mat4x3h",
+ "mat4x4f",
+ "mat4x4h",
+ "vec2f",
+ "vec2h",
+ "vec2i",
+ "vec2u",
+ "vec3f",
+ "vec3h",
+ "vec3i",
+ "vec3u",
+ "vec4f",
+ "vec4h",
+ "vec4i",
+ "vec4u"));
+
+TEST_F(ResolverUntemplatedTypeUsedWithTemplateArgs, Struct_UseWithTemplateArgs) {
+ // struct S {
+ // i: i32;
+ // };
+ // var<private> v : S<true>;
+
+ Structure(Source{{56, 78}}, "S", utils::Vector{Member("i", ty.i32())});
+ GlobalVar("v", type::AddressSpace::kPrivate, ty(Source{{12, 34}}, "S", true));
+
+ EXPECT_FALSE(r()->Resolve());
+ EXPECT_EQ(r()->error(),
+ R"(12:34 error: type 'S' does not take template arguments
+56:78 note: struct 'S' declared here)");
+}
+
+} // namespace TypeDoesNotTakeTemplateArgs
+
} // namespace
} // namespace tint::resolver
diff --git a/src/tint/resolver/validator.cc b/src/tint/resolver/validator.cc
index 24a2bd7..71e39af 100644
--- a/src/tint/resolver/validator.cc
+++ b/src/tint/resolver/validator.cc
@@ -37,7 +37,6 @@
#include "src/tint/ast/pointer.h"
#include "src/tint/ast/return_statement.h"
#include "src/tint/ast/sampled_texture.h"
-#include "src/tint/ast/storage_texture.h"
#include "src/tint/ast/switch_statement.h"
#include "src/tint/ast/traverse_expressions.h"
#include "src/tint/ast/type_name.h"
@@ -316,28 +315,28 @@
a->source);
}
-bool Validator::StorageTexture(const ast::StorageTexture* t) const {
- switch (t->access) {
+bool Validator::StorageTexture(const type::StorageTexture* t, const Source& source) const {
+ switch (t->access()) {
case type::Access::kWrite:
break;
case type::Access::kUndefined:
- AddError("storage texture missing access control", t->source);
+ AddError("storage texture missing access control", source);
return false;
default:
- AddError("storage textures currently only support 'write' access control", t->source);
+ AddError("storage textures currently only support 'write' access control", source);
return false;
}
- if (!IsValidStorageTextureDimension(t->dim)) {
- AddError("cube dimensions for storage textures are not supported", t->source);
+ if (!IsValidStorageTextureDimension(t->dim())) {
+ AddError("cube dimensions for storage textures are not supported", source);
return false;
}
- if (!IsValidStorageTextureTexelFormat(t->format)) {
+ if (!IsValidStorageTextureTexelFormat(t->texel_format())) {
AddError(
"image format must be one of the texel formats specified for storage "
"textues in https://gpuweb.github.io/gpuweb/wgsl/#texel-formats",
- t->source);
+ source);
return false;
}
return true;
diff --git a/src/tint/resolver/validator.h b/src/tint/resolver/validator.h
index 55625d3..9e11f50 100644
--- a/src/tint/resolver/validator.h
+++ b/src/tint/resolver/validator.h
@@ -372,8 +372,9 @@
/// Validates a storage texture
/// @param t the texture to validate
+ /// @param source the source of the texture
/// @returns true on success, false otherwise
- bool StorageTexture(const ast::StorageTexture* t) const;
+ bool StorageTexture(const type::StorageTexture* t, const Source& source) const;
/// Validates a sampled texture
/// @param t the texture to validate
diff --git a/src/tint/transform/builtin_polyfill.cc b/src/tint/transform/builtin_polyfill.cc
index 9924da3..3d647a7 100644
--- a/src/tint/transform/builtin_polyfill.cc
+++ b/src/tint/transform/builtin_polyfill.cc
@@ -22,6 +22,8 @@
#include "src/tint/program_builder.h"
#include "src/tint/sem/builtin.h"
#include "src/tint/sem/call.h"
+#include "src/tint/sem/type_expression.h"
+#include "src/tint/type/storage_texture.h"
#include "src/tint/type/texture_dimension.h"
#include "src/tint/utils/map.h"
@@ -1065,13 +1067,17 @@
break;
}
},
- [&](const ast::StorageTexture* tex) {
- if (polyfill.bgra8unorm && tex->format == type::TexelFormat::kBgra8Unorm) {
- ctx.Replace(tex, [&ctx, tex] {
- return ctx.dst->ty.storage_texture(tex->dim, type::TexelFormat::kRgba8Unorm,
- tex->access);
- });
- made_changes = true;
+ [&](const ast::TypeName* type_name) {
+ if (polyfill.bgra8unorm) {
+ if (auto* tex = src->Sem().Get<type::StorageTexture>(type_name)) {
+ if (tex->texel_format() == type::TexelFormat::kBgra8Unorm) {
+ ctx.Replace(type_name, [&ctx, tex] {
+ return ctx.dst->ty.storage_texture(
+ tex->dim(), type::TexelFormat::kRgba8Unorm, tex->access());
+ });
+ made_changes = true;
+ }
+ }
}
});
}
diff --git a/src/tint/transform/texture_1d_to_2d.cc b/src/tint/transform/texture_1d_to_2d.cc
index 4561814..84d480a 100644
--- a/src/tint/transform/texture_1d_to_2d.cc
+++ b/src/tint/transform/texture_1d_to_2d.cc
@@ -83,7 +83,8 @@
return SkipTransform;
}
- auto create_var = [&](const ast::Variable* v, ast::Type* type) -> const ast::Variable* {
+ auto create_var = [&](const ast::Variable* v,
+ const ast::Type* type) -> const ast::Variable* {
if (v->As<ast::Parameter>()) {
return ctx.dst->Param(ctx.Clone(v->name->symbol), type, ctx.Clone(v->attributes));
} else {
@@ -105,9 +106,9 @@
},
[&](const type::StorageTexture* storage_tex) -> const ast::Variable* {
if (storage_tex->dim() == type::TextureDimension::k1d) {
- auto* type = ctx.dst->create<ast::StorageTexture>(
- type::TextureDimension::k2d, storage_tex->texel_format(),
- CreateASTTypeFor(ctx, storage_tex->type()), storage_tex->access());
+ auto* type = ctx.dst->ty.storage_texture(type::TextureDimension::k2d,
+ storage_tex->texel_format(),
+ storage_tex->access());
return create_var(v, type);
} else {
return nullptr;
diff --git a/src/tint/transform/transform.cc b/src/tint/transform/transform.cc
index 1b5b345..a2ae237 100644
--- a/src/tint/transform/transform.cc
+++ b/src/tint/transform/transform.cc
@@ -163,8 +163,7 @@
return ctx.dst->create<ast::SampledTexture>(t->dim(), CreateASTTypeFor(ctx, t->type()));
}
if (auto* t = ty->As<type::StorageTexture>()) {
- return ctx.dst->create<ast::StorageTexture>(t->dim(), t->texel_format(),
- CreateASTTypeFor(ctx, t->type()), t->access());
+ return ctx.dst->ty.storage_texture(t->dim(), t->texel_format(), t->access());
}
if (auto* s = ty->As<type::Sampler>()) {
return ctx.dst->ty.sampler(s->kind());
diff --git a/src/tint/type/builtin.cc b/src/tint/type/builtin.cc
index e8bf467..b400ccb 100644
--- a/src/tint/type/builtin.cc
+++ b/src/tint/type/builtin.cc
@@ -118,6 +118,18 @@
if (str == "texture_external") {
return Builtin::kTextureExternal;
}
+ if (str == "texture_storage_1d") {
+ return Builtin::kTextureStorage1D;
+ }
+ if (str == "texture_storage_2d") {
+ return Builtin::kTextureStorage2D;
+ }
+ if (str == "texture_storage_2d_array") {
+ return Builtin::kTextureStorage2DArray;
+ }
+ if (str == "texture_storage_3d") {
+ return Builtin::kTextureStorage3D;
+ }
if (str == "u32") {
return Builtin::kU32;
}
@@ -224,6 +236,14 @@
return out << "texture_depth_multisampled_2d";
case Builtin::kTextureExternal:
return out << "texture_external";
+ case Builtin::kTextureStorage1D:
+ return out << "texture_storage_1d";
+ case Builtin::kTextureStorage2D:
+ return out << "texture_storage_2d";
+ case Builtin::kTextureStorage2DArray:
+ return out << "texture_storage_2d_array";
+ case Builtin::kTextureStorage3D:
+ return out << "texture_storage_3d";
case Builtin::kU32:
return out << "u32";
case Builtin::kVec2F:
diff --git a/src/tint/type/builtin.h b/src/tint/type/builtin.h
index 8b73461..3b57489 100644
--- a/src/tint/type/builtin.h
+++ b/src/tint/type/builtin.h
@@ -60,6 +60,10 @@
kTextureDepthCubeArray,
kTextureDepthMultisampled2D,
kTextureExternal,
+ kTextureStorage1D,
+ kTextureStorage2D,
+ kTextureStorage2DArray,
+ kTextureStorage3D,
kU32,
kVec2F,
kVec2H,
@@ -116,6 +120,10 @@
"texture_depth_cube_array",
"texture_depth_multisampled_2d",
"texture_external",
+ "texture_storage_1d",
+ "texture_storage_2d",
+ "texture_storage_2d_array",
+ "texture_storage_3d",
"u32",
"vec2f",
"vec2h",
diff --git a/src/tint/type/builtin_bench.cc b/src/tint/type/builtin_bench.cc
index 31fa29a..aea57f5 100644
--- a/src/tint/type/builtin_bench.cc
+++ b/src/tint/type/builtin_bench.cc
@@ -241,97 +241,125 @@
"textuXe_ZZxtJJrnal",
"textuPPe_eternal",
"texturc_external",
- "ull62",
- "93yy",
- "u3KK",
+ "tllxture_storage_P6d",
+ "tex99ure_yytorag_1d",
+ "textuKKe_storage_1d",
+ "texture_storage_1d",
+ "texture__xorage_d",
+ "yxKur_storage_1d",
+ "textureVstorkge_1z",
+ "texKure_Storqge_2d",
+ "texture_storage_d",
+ "teture_storage_VVd",
+ "texture_storage_2d",
+ "textureIstoraAUe_2d",
+ "jextre_storaR_2d",
+ "extue44storYYge_2",
+ "textre_storage_2d_array",
+ "tex9ur_stor11ge_d_xxrray",
+ "tmmxture_storJe_2d_arrcc",
+ "texture_storage_2d_array",
+ "tJJxture_storage_2_array",
+ "DDCCltufe_storaUe_2d_array",
+ "tegture_storage_2d_array",
+ "exture_srageCC3d",
+ "txture_storage_3d",
+ "textuIe_sto__age_3d",
+ "texture_storage_3d",
+ "texttte_PPorage_3d",
+ "texture_stora3de_3d",
+ "exture_Ktoragyy_3d",
+ "",
+ "03nn",
+ "uCnuu",
"u32",
- "x_",
- "K",
- "kVz",
- "veKSf",
- "vc2f",
- "ec2VV",
- "vec2f",
- "IAAc2f",
- "jbR",
- "veY4",
- "ec2h",
- "vc911",
- "mmcch",
- "vec2h",
- "vJJch",
- "lDDcUfC",
- "vec2g",
- "CCe",
- "ec2i",
- "vIc__i",
- "vec2i",
- "ePPtt",
- "v3dc2i",
- "vcyyi",
- "u2",
- "v03nnu",
- "Cuuecnv",
- "vec2u",
- "vX2ll",
- "vocppu",
- "vwwc2",
+ "3Xl",
+ "pp3o",
+ "uww",
"veuug",
"vaac",
"TRZcccf",
- "vec3f",
- "vTc3O8",
- "vem03f",
- "meBB3f",
- "Mpp3",
- "OOe3h",
- "veG3G",
- "vec3h",
- "11eHH3h",
+ "vec2f",
+ "vTc2O8",
+ "vem02f",
+ "meBB2f",
+ "Mpp2",
+ "OOe2h",
+ "veG2G",
+ "vec2h",
+ "11eHH2h",
"veFFe6",
- "ve3",
- "vKii3l",
- "ec3i",
- "v993IIv",
- "vec3i",
+ "ve2",
+ "vKii2l",
+ "ec2i",
+ "v992IIv",
+ "vec2i",
"veci",
"vechi",
"vczllPi",
"u",
- "vffqq3",
- "vJdd3u",
- "vec3u",
+ "vffqq2",
+ "vJdd2u",
+ "vec2u",
"vecXX",
- "ve32",
- "Nyyc3u",
- "vO4",
+ "ve22",
+ "Nyyc2u",
+ "vO3",
"PEruZ",
"vlc2edd",
- "vec4f",
+ "vec3f",
"ec9f",
"ve1II",
- "veb4f",
+ "veb3f",
"vi7",
- "oec4ii",
- "ec4",
- "vec4h",
+ "oec3ii",
+ "ec3",
+ "vec3h",
"veci",
"22ec",
- "vGc4C",
- "ffec48",
- "c4i",
+ "vGc3C",
+ "ffec38",
+ "c3i",
"JJecSSi",
- "vec4i",
- "94i",
- "vbbJJ4TT",
+ "vec3i",
+ "93i",
+ "vbbJJ3TT",
"e66i",
- "u664u",
- "vW4u",
- "v4u",
- "vec4u",
+ "u663u",
+ "vW3u",
+ "v3u",
+ "vec3u",
"vecu",
- "rec4u",
- "2ec4B",
+ "rec3u",
+ "2ec3B",
+ "vcBBf",
+ "vRc4f",
+ "v4LL0",
+ "vec4f",
+ "vKOOf",
+ "vgwcf",
+ "vLphf",
+ "eiiEh",
+ "ec4h",
+ "UU884",
+ "vec4h",
+ "rrecvvh",
+ "ecmm",
+ "vec4j",
+ "vec4X",
+ "vec48",
+ "vecvEE",
+ "vec4i",
+ "z99ci",
+ "GGeJJA4i",
+ "vess4i",
+ "vPcKu",
+ "tpc4u",
+ "vec",
+ "vec4u",
+ "MMec4u",
+ "vJJc40",
+ "8c",
};
for (auto _ : state) {
for (auto* str : kStrings) {
diff --git a/src/tint/type/builtin_test.cc b/src/tint/type/builtin_test.cc
index 97f3164..ebd2cea 100644
--- a/src/tint/type/builtin_test.cc
+++ b/src/tint/type/builtin_test.cc
@@ -73,6 +73,10 @@
{"texture_depth_cube_array", Builtin::kTextureDepthCubeArray},
{"texture_depth_multisampled_2d", Builtin::kTextureDepthMultisampled2D},
{"texture_external", Builtin::kTextureExternal},
+ {"texture_storage_1d", Builtin::kTextureStorage1D},
+ {"texture_storage_2d", Builtin::kTextureStorage2D},
+ {"texture_storage_2d_array", Builtin::kTextureStorage2DArray},
+ {"texture_storage_3d", Builtin::kTextureStorage3D},
{"u32", Builtin::kU32},
{"vec2f", Builtin::kVec2F},
{"vec2h", Builtin::kVec2H},
@@ -179,45 +183,57 @@
{"texture_exernss77", Builtin::kUndefined},
{"texture_bbxternRRl", Builtin::kUndefined},
{"textureXXexternal", Builtin::kUndefined},
- {"qOOO2", Builtin::kUndefined},
- {"us", Builtin::kUndefined},
- {"u3X", Builtin::kUndefined},
- {"ve2f", Builtin::kUndefined},
- {"qq2", Builtin::kUndefined},
- {"vec222", Builtin::kUndefined},
- {"vezzXy", Builtin::kUndefined},
- {"ieVVP", Builtin::kUndefined},
- {"venCh", Builtin::kUndefined},
- {"vHc2Aq", Builtin::kUndefined},
- {"ve2i", Builtin::kUndefined},
- {"vefK", Builtin::kUndefined},
- {"vgg2", Builtin::kUndefined},
- {"vecu", Builtin::kUndefined},
- {"4TNc2u", Builtin::kUndefined},
+ {"CCextOOre_stoage_qOd", Builtin::kUndefined},
+ {"txtsre_sturage_1L", Builtin::kUndefined},
+ {"texture_stoXage_1d", Builtin::kUndefined},
+ {"textue_storage_2d", Builtin::kUndefined},
+ {"teuresOorageqq2d", Builtin::kUndefined},
+ {"texture_sto22age_2d", Builtin::kUndefined},
+ {"exture_syora0e_2d_Xzzrray", Builtin::kUndefined},
+ {"texiVVr_storageP2d_array", Builtin::kUndefined},
+ {"texturestorage_2nn_arCay", Builtin::kUndefined},
+ {"texturHHstorAAe_qqd", Builtin::kUndefined},
+ {"textur_storage_3d", Builtin::kUndefined},
+ {"texure_sfKorage3d", Builtin::kUndefined},
+ {"gg", Builtin::kUndefined},
+ {"u3", Builtin::kUndefined},
+ {"NT42", Builtin::kUndefined},
{"ppec7l", Builtin::kUndefined},
- {"zNe3f", Builtin::kUndefined},
- {"uXXb3f", Builtin::kUndefined},
- {"vec3", Builtin::kUndefined},
- {"883K", Builtin::kUndefined},
+ {"zNe2f", Builtin::kUndefined},
+ {"uXXb2f", Builtin::kUndefined},
+ {"vec2", Builtin::kUndefined},
+ {"882K", Builtin::kUndefined},
{"vq9h", Builtin::kUndefined},
- {"vec311", Builtin::kUndefined},
+ {"vec211", Builtin::kUndefined},
{"22ciii", Builtin::kUndefined},
{"ec77i", Builtin::kUndefined},
- {"NN23u", Builtin::kUndefined},
- {"vVVc3u", Builtin::kUndefined},
- {"WW11w3u", Builtin::kUndefined},
+ {"NN22u", Builtin::kUndefined},
+ {"vVVc2u", Builtin::kUndefined},
+ {"WW11w2u", Builtin::kUndefined},
{"vcwwf", Builtin::kUndefined},
- {"vDc4f", Builtin::kUndefined},
+ {"vDc3f", Builtin::kUndefined},
{"vecK", Builtin::kUndefined},
- {"f11r4PP", Builtin::kUndefined},
- {"ve4h", Builtin::kUndefined},
- {"vec4YY", Builtin::kUndefined},
+ {"f11r3PP", Builtin::kUndefined},
+ {"ve3h", Builtin::kUndefined},
+ {"vec3YY", Builtin::kUndefined},
{"vkktHH", Builtin::kUndefined},
- {"rrec4i", Builtin::kUndefined},
+ {"rrec3i", Builtin::kUndefined},
{"vWWssi", Builtin::kUndefined},
{"veYu", Builtin::kUndefined},
- {"eq4f", Builtin::kUndefined},
- {"u22ec4u", Builtin::kUndefined},
+ {"eq3f", Builtin::kUndefined},
+ {"u22ec3u", Builtin::kUndefined},
+ {"c4f", Builtin::kUndefined},
+ {"vec4", Builtin::kUndefined},
+ {"vYyc47E", Builtin::kUndefined},
+ {"veMoh", Builtin::kUndefined},
+ {"ve4MM", Builtin::kUndefined},
+ {"55ec4h", Builtin::kUndefined},
+ {"N4i", Builtin::kUndefined},
+ {"ve33i", Builtin::kUndefined},
+ {"3ec4i", Builtin::kUndefined},
+ {"mecI", Builtin::kUndefined},
+ {"vrnK4u", Builtin::kUndefined},
+ {"v4", Builtin::kUndefined},
};
using BuiltinParseTest = testing::TestWithParam<Case>;
diff --git a/src/tint/writer/wgsl/generator_impl.cc b/src/tint/writer/wgsl/generator_impl.cc
index d99ecde..19345d0 100644
--- a/src/tint/writer/wgsl/generator_impl.cc
+++ b/src/tint/writer/wgsl/generator_impl.cc
@@ -32,7 +32,6 @@
#include "src/tint/ast/pointer.h"
#include "src/tint/ast/sampled_texture.h"
#include "src/tint/ast/stage_attribute.h"
-#include "src/tint/ast/storage_texture.h"
#include "src/tint/ast/stride_attribute.h"
#include "src/tint/ast/struct_member_align_attribute.h"
#include "src/tint/ast/struct_member_offset_attribute.h"
@@ -290,7 +289,23 @@
}
bool GeneratorImpl::EmitIdentifier(std::ostream& out, const ast::IdentifierExpression* expr) {
- out << program_->Symbols().NameFor(expr->identifier->symbol);
+ return EmitIdentifier(out, expr->identifier);
+}
+
+bool GeneratorImpl::EmitIdentifier(std::ostream& out, const ast::Identifier* ident) {
+ out << program_->Symbols().NameFor(ident->symbol);
+ if (auto* tmpl_ident = ident->As<ast::TemplatedIdentifier>()) {
+ out << "<";
+ TINT_DEFER(out << ">");
+ for (auto* expr : tmpl_ident->arguments) {
+ if (expr != tmpl_ident->arguments.Front()) {
+ out << ", ";
+ }
+ if (!EmitExpression(out, expr)) {
+ return false;
+ }
+ }
+ }
return true;
}
@@ -462,10 +477,6 @@
out << "multisampled_";
return true;
},
- [&](const ast::StorageTexture*) { //
- out << "storage_";
- return true;
- },
[&](Default) { //
diagnostics_.add_error(diag::System::Writer, "unknown texture type");
return false;
@@ -516,18 +527,6 @@
out << ">";
return true;
},
- [&](const ast::StorageTexture* storage) { //
- out << "<";
- if (!EmitImageFormat(out, storage->format)) {
- return false;
- }
- out << ", ";
- if (!EmitAccess(out, storage->access)) {
- return false;
- }
- out << ">";
- return true;
- },
[&](Default) { //
return true;
});
@@ -543,10 +542,7 @@
}
return true;
},
- [&](const ast::TypeName* tn) {
- out << program_->Symbols().NameFor(tn->name->symbol);
- return true;
- },
+ [&](const ast::TypeName* tn) { return EmitIdentifier(out, tn->name); },
[&](Default) {
diagnostics_.add_error(diag::System::Writer,
"unknown type in EmitType: " + std::string(ty->TypeInfo().name));
diff --git a/src/tint/writer/wgsl/generator_impl.h b/src/tint/writer/wgsl/generator_impl.h
index c6c74f7..cf5d270 100644
--- a/src/tint/writer/wgsl/generator_impl.h
+++ b/src/tint/writer/wgsl/generator_impl.h
@@ -142,6 +142,11 @@
/// @param expr the identifier expression
/// @returns true if the identifier was emitted
bool EmitIdentifier(std::ostream& out, const ast::IdentifierExpression* expr);
+ /// Handles generating an identifier
+ /// @param out the output of the expression stream
+ /// @param ident the identifier
+ /// @returns true if the identifier was emitted
+ bool EmitIdentifier(std::ostream& out, const ast::Identifier* ident);
/// Handles an if statement
/// @param stmt the statement to emit
/// @returns true if the statement was successfully emitted