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>
This commit is contained in:
parent
c66b5e6922
commit
1131d31761
|
@ -301,7 +301,6 @@ libtint_source_set("libtint_syntax_tree_src") {
|
|||
"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 @@ libtint_source_set("libtint_ast_src") {
|
|||
"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 @@ if (tint_build_unittests) {
|
|||
}
|
||||
}
|
||||
|
||||
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 @@ if (tint_build_unittests) {
|
|||
"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 @@ if (tint_build_unittests) {
|
|||
"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 @@ if (tint_build_unittests) {
|
|||
":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 @@ if (tint_build_unittests) {
|
|||
|
||||
deps = [
|
||||
":libtint_base_src",
|
||||
":libtint_unittests_ast_helper",
|
||||
":libtint_wgsl_reader_src",
|
||||
]
|
||||
}
|
||||
|
@ -1993,6 +2001,7 @@ if (tint_build_unittests) {
|
|||
|
||||
deps = [
|
||||
":libtint_base_src",
|
||||
":libtint_unittests_ast_helper",
|
||||
":tint_unittests_ast_src",
|
||||
]
|
||||
}
|
||||
|
|
|
@ -201,8 +201,6 @@ list(APPEND TINT_LIB_SRCS
|
|||
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 @@ if(TINT_BUILD_TESTS)
|
|||
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
|
||||
|
|
|
@ -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 @@ TEST_F(AstMultisampledTextureTest, IsTexture) {
|
|||
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) {
|
||||
|
|
|
@ -24,7 +24,6 @@ using AstSampledTextureTest = TestHelper;
|
|||
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) {
|
||||
|
|
|
@ -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
|
|
@ -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_
|
|
@ -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
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -176,6 +176,11 @@ enum builtin_type {
|
|||
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
|
||||
}
|
||||
|
|
|
@ -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 @@ class ProgramBuilder {
|
|||
/// @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,
|
||||
/// @returns the storage texture typename
|
||||
const ast::TypeName* 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);
|
||||
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,
|
||||
/// @returns the storage texture typename
|
||||
const ast::TypeName* 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);
|
||||
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
|
||||
|
|
|
@ -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"
|
||||
|
||||
|
|
|
@ -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 @@ TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_Readonly1dRg32Float) {
|
|||
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 @@ TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_Writeonly2dR32Uint) {
|
|||
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}}));
|
||||
}
|
||||
|
||||
|
|
|
@ -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,23 +337,35 @@ class DependencyScanner {
|
|||
}
|
||||
}
|
||||
|
||||
/// 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) {
|
||||
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* ident) {
|
||||
AddDependency(ident->identifier, ident->identifier->symbol, "identifier",
|
||||
[&](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);
|
||||
|
@ -364,6 +375,7 @@ class DependencyScanner {
|
|||
return ast::TraverseAction::Descend;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Traverses the type node, performing symbol resolution and determining
|
||||
/// global dependencies.
|
||||
|
@ -388,6 +400,11 @@ class DependencyScanner {
|
|||
},
|
||||
[&](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 @@ class DependencyScanner {
|
|||
[&](const ast::MultisampledTexture* tex) { //
|
||||
TraverseType(tex->type);
|
||||
},
|
||||
[&](const ast::StorageTexture* tex) { //
|
||||
TraverseType(tex->type);
|
||||
},
|
||||
[&](Default) { UnhandledNode(diagnostics_, ty); });
|
||||
}
|
||||
|
||||
|
|
|
@ -121,7 +121,7 @@ TEST_P(ResolverExpressionKindTest, Test) {
|
|||
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 @@ TEST_P(ResolverExpressionKindTest, Test) {
|
|||
|
||||
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 @@ TEST_P(ResolverExpressionKindTest, Test) {
|
|||
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 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
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 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
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 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
{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 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
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 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
{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 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
{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 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
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 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
{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 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
{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 @@ INSTANTIATE_TEST_SUITE_P(
|
|||
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},
|
||||
}));
|
||||
|
||||
|
|
|
@ -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 @@ type::Type* Resolver::Type(const ast::Type* ty) {
|
|||
}
|
||||
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 @@ type::Type* Resolver::Type(const ast::Type* ty) {
|
|||
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 @@ sem::Call* Resolver::BuiltinCall(const ast::CallExpression* expr,
|
|||
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 @@ type::Type* Resolver::BuiltinType(type::Builtin builtin_ty, const ast::Identifie
|
|||
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 @@ void Resolver::ErrorMismatchedResolvedIdentifier(const Source& source,
|
|||
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);
|
||||
});
|
||||
}
|
||||
|
|
|
@ -432,6 +432,11 @@ class Resolver {
|
|||
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 @@ class Resolver {
|
|||
|
||||
/// @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.
|
||||
|
|
|
@ -37,30 +37,40 @@ type::Type* SemHelper::TypeOf(const ast::Expression* expr) const {
|
|||
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 {
|
|||
});
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -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 @@ class SemHelper {
|
|||
}
|
||||
|
||||
/// @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 {
|
||||
/// @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->template As<sem::ValueExpression>(); TINT_LIKELY(val)) {
|
||||
if (auto* val = expr->As<sem::ValueExpression>(); TINT_LIKELY(val)) {
|
||||
return val;
|
||||
}
|
||||
ErrorExpectedValueExpr(expr);
|
||||
}
|
||||
return static_cast<sem::ValueExpression*>(nullptr);
|
||||
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 @@ class SemHelper {
|
|||
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;
|
||||
|
||||
|
|
|
@ -1064,26 +1064,26 @@ INSTANTIATE_TEST_SUITE_P(ResolverTypeValidationTest,
|
|||
|
||||
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 @@ TEST_P(StorageTextureDimensionTest, All) {
|
|||
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 @@ INSTANTIATE_TEST_SUITE_P(ResolverTypeValidationTest,
|
|||
|
||||
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, RWAccess_Fail) {
|
|||
|
||||
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, ReadOnlyAccess_Fail) {
|
|||
|
||||
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 @@ INSTANTIATE_TEST_SUITE_P(ResolverTypeValidationTest,
|
|||
|
||||
} // 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
|
||||
|
|
|
@ -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 @@ bool Validator::Pointer(const ast::Pointer* a, const type::Pointer* s) const {
|
|||
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;
|
||||
|
|
|
@ -372,8 +372,9 @@ class Validator {
|
|||
|
||||
/// 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
|
||||
|
|
|
@ -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,14 +1067,18 @@ Transform::ApplyResult BuiltinPolyfill::Apply(const Program* src,
|
|||
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);
|
||||
[&](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;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -83,7 +83,8 @@ struct Texture1DTo2D::State {
|
|||
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 @@ struct Texture1DTo2D::State {
|
|||
},
|
||||
[&](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;
|
||||
|
|
|
@ -163,8 +163,7 @@ const ast::Type* Transform::CreateASTTypeFor(CloneContext& ctx, const type::Type
|
|||
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());
|
||||
|
|
|
@ -118,6 +118,18 @@ Builtin ParseBuiltin(std::string_view str) {
|
|||
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 @@ std::ostream& operator<<(std::ostream& out, Builtin value) {
|
|||
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:
|
||||
|
|
|
@ -60,6 +60,10 @@ enum class Builtin {
|
|||
kTextureDepthCubeArray,
|
||||
kTextureDepthMultisampled2D,
|
||||
kTextureExternal,
|
||||
kTextureStorage1D,
|
||||
kTextureStorage2D,
|
||||
kTextureStorage2DArray,
|
||||
kTextureStorage3D,
|
||||
kU32,
|
||||
kVec2F,
|
||||
kVec2H,
|
||||
|
@ -116,6 +120,10 @@ constexpr const char* kBuiltinStrings[] = {
|
|||
"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",
|
||||
|
|
|
@ -241,97 +241,125 @@ void BuiltinParser(::benchmark::State& state) {
|
|||
"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) {
|
||||
|
|
|
@ -73,6 +73,10 @@ static constexpr Case kValidCases[] = {
|
|||
{"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 @@ static constexpr Case kInvalidCases[] = {
|
|||
{"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>;
|
||||
|
|
|
@ -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::EmitLiteral(std::ostream& out, const ast::LiteralExpression*
|
|||
}
|
||||
|
||||
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 @@ bool GeneratorImpl::EmitType(std::ostream& out, const ast::Type* ty) {
|
|||
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 @@ bool GeneratorImpl::EmitType(std::ostream& out, const ast::Type* ty) {
|
|||
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 @@ bool GeneratorImpl::EmitType(std::ostream& out, const ast::Type* ty) {
|
|||
}
|
||||
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));
|
||||
|
|
|
@ -142,6 +142,11 @@ class GeneratorImpl : public TextGenerator {
|
|||
/// @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
|
||||
|
|
Loading…
Reference in New Issue