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/sampled_texture.h",
|
||||||
"ast/stage_attribute.h",
|
"ast/stage_attribute.h",
|
||||||
"ast/statement.h",
|
"ast/statement.h",
|
||||||
"ast/storage_texture.h",
|
|
||||||
"ast/stride_attribute.h",
|
"ast/stride_attribute.h",
|
||||||
"ast/struct.h",
|
"ast/struct.h",
|
||||||
"ast/struct_member.h",
|
"ast/struct_member.h",
|
||||||
|
@ -665,8 +664,6 @@ libtint_source_set("libtint_ast_src") {
|
||||||
"ast/stage_attribute.h",
|
"ast/stage_attribute.h",
|
||||||
"ast/statement.cc",
|
"ast/statement.cc",
|
||||||
"ast/statement.h",
|
"ast/statement.h",
|
||||||
"ast/storage_texture.cc",
|
|
||||||
"ast/storage_texture.h",
|
|
||||||
"ast/stride_attribute.cc",
|
"ast/stride_attribute.cc",
|
||||||
"ast/stride_attribute.h",
|
"ast/stride_attribute.h",
|
||||||
"ast/struct.cc",
|
"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") {
|
tint_unittests_source_set("tint_unittests_ast_src") {
|
||||||
sources = [
|
sources = [
|
||||||
"ast/alias_test.cc",
|
"ast/alias_test.cc",
|
||||||
|
@ -1333,7 +1342,6 @@ if (tint_build_unittests) {
|
||||||
"ast/return_statement_test.cc",
|
"ast/return_statement_test.cc",
|
||||||
"ast/sampled_texture_test.cc",
|
"ast/sampled_texture_test.cc",
|
||||||
"ast/stage_attribute_test.cc",
|
"ast/stage_attribute_test.cc",
|
||||||
"ast/storage_texture_test.cc",
|
|
||||||
"ast/stride_attribute_test.cc",
|
"ast/stride_attribute_test.cc",
|
||||||
"ast/struct_member_align_attribute_test.cc",
|
"ast/struct_member_align_attribute_test.cc",
|
||||||
"ast/struct_member_offset_attribute_test.cc",
|
"ast/struct_member_offset_attribute_test.cc",
|
||||||
|
@ -1342,8 +1350,6 @@ if (tint_build_unittests) {
|
||||||
"ast/struct_test.cc",
|
"ast/struct_test.cc",
|
||||||
"ast/switch_statement_test.cc",
|
"ast/switch_statement_test.cc",
|
||||||
"ast/templated_identifier_test.cc",
|
"ast/templated_identifier_test.cc",
|
||||||
"ast/test_helper.h",
|
|
||||||
"ast/test_helper_test.cc",
|
|
||||||
"ast/texture_test.cc",
|
"ast/texture_test.cc",
|
||||||
"ast/traverse_expressions_test.cc",
|
"ast/traverse_expressions_test.cc",
|
||||||
"ast/type_name_test.cc",
|
"ast/type_name_test.cc",
|
||||||
|
@ -1358,6 +1364,7 @@ if (tint_build_unittests) {
|
||||||
":libtint_ast_src",
|
":libtint_ast_src",
|
||||||
":libtint_base_src",
|
":libtint_base_src",
|
||||||
":libtint_transform_src",
|
":libtint_transform_src",
|
||||||
|
":libtint_unittests_ast_helper",
|
||||||
]
|
]
|
||||||
|
|
||||||
if (tint_build_wgsl_reader && tint_build_wgsl_writer) {
|
if (tint_build_wgsl_reader && tint_build_wgsl_writer) {
|
||||||
|
@ -1797,6 +1804,7 @@ if (tint_build_unittests) {
|
||||||
|
|
||||||
deps = [
|
deps = [
|
||||||
":libtint_base_src",
|
":libtint_base_src",
|
||||||
|
":libtint_unittests_ast_helper",
|
||||||
":libtint_wgsl_reader_src",
|
":libtint_wgsl_reader_src",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
@ -1993,6 +2001,7 @@ if (tint_build_unittests) {
|
||||||
|
|
||||||
deps = [
|
deps = [
|
||||||
":libtint_base_src",
|
":libtint_base_src",
|
||||||
|
":libtint_unittests_ast_helper",
|
||||||
":tint_unittests_ast_src",
|
":tint_unittests_ast_src",
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -201,8 +201,6 @@ list(APPEND TINT_LIB_SRCS
|
||||||
ast/stage_attribute.h
|
ast/stage_attribute.h
|
||||||
ast/statement.cc
|
ast/statement.cc
|
||||||
ast/statement.h
|
ast/statement.h
|
||||||
ast/storage_texture.cc
|
|
||||||
ast/storage_texture.h
|
|
||||||
ast/stride_attribute.cc
|
ast/stride_attribute.cc
|
||||||
ast/stride_attribute.h
|
ast/stride_attribute.h
|
||||||
ast/struct_member_align_attribute.cc
|
ast/struct_member_align_attribute.cc
|
||||||
|
@ -856,7 +854,6 @@ if(TINT_BUILD_TESTS)
|
||||||
ast/return_statement_test.cc
|
ast/return_statement_test.cc
|
||||||
ast/sampled_texture_test.cc
|
ast/sampled_texture_test.cc
|
||||||
ast/stage_attribute_test.cc
|
ast/stage_attribute_test.cc
|
||||||
ast/storage_texture_test.cc
|
|
||||||
ast/stride_attribute_test.cc
|
ast/stride_attribute_test.cc
|
||||||
ast/struct_member_align_attribute_test.cc
|
ast/struct_member_align_attribute_test.cc
|
||||||
ast/struct_member_offset_attribute_test.cc
|
ast/struct_member_offset_attribute_test.cc
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
#include "src/tint/ast/matrix.h"
|
#include "src/tint/ast/matrix.h"
|
||||||
#include "src/tint/ast/pointer.h"
|
#include "src/tint/ast/pointer.h"
|
||||||
#include "src/tint/ast/sampled_texture.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/struct.h"
|
||||||
#include "src/tint/ast/test_helper.h"
|
#include "src/tint/ast/test_helper.h"
|
||||||
#include "src/tint/ast/texture.h"
|
#include "src/tint/ast/texture.h"
|
||||||
|
@ -35,7 +34,6 @@ TEST_F(AstMultisampledTextureTest, IsTexture) {
|
||||||
Texture* t = create<MultisampledTexture>(type::TextureDimension::kCube, ty.f32());
|
Texture* t = create<MultisampledTexture>(type::TextureDimension::kCube, ty.f32());
|
||||||
EXPECT_TRUE(t->Is<MultisampledTexture>());
|
EXPECT_TRUE(t->Is<MultisampledTexture>());
|
||||||
EXPECT_FALSE(t->Is<SampledTexture>());
|
EXPECT_FALSE(t->Is<SampledTexture>());
|
||||||
EXPECT_FALSE(t->Is<StorageTexture>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(AstMultisampledTextureTest, Dim) {
|
TEST_F(AstMultisampledTextureTest, Dim) {
|
||||||
|
|
|
@ -24,7 +24,6 @@ using AstSampledTextureTest = TestHelper;
|
||||||
TEST_F(AstSampledTextureTest, IsTexture) {
|
TEST_F(AstSampledTextureTest, IsTexture) {
|
||||||
Texture* t = create<SampledTexture>(type::TextureDimension::kCube, ty.f32());
|
Texture* t = create<SampledTexture>(type::TextureDimension::kCube, ty.f32());
|
||||||
EXPECT_TRUE(t->Is<SampledTexture>());
|
EXPECT_TRUE(t->Is<SampledTexture>());
|
||||||
EXPECT_FALSE(t->Is<StorageTexture>());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(AstSampledTextureTest, Dim) {
|
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 <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/texture_dimension.h"
|
||||||
#include "src/tint/type/type.h"
|
#include "src/tint/type/type.h"
|
||||||
|
|
||||||
|
|
|
@ -176,6 +176,11 @@ enum builtin_type {
|
||||||
texture_depth_cube
|
texture_depth_cube
|
||||||
texture_depth_cube_array
|
texture_depth_cube_array
|
||||||
texture_depth_multisampled_2d
|
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
|
// https://www.w3.org/TR/WGSL/#external-texture-type
|
||||||
texture_external
|
texture_external
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,7 +68,6 @@
|
||||||
#include "src/tint/ast/return_statement.h"
|
#include "src/tint/ast/return_statement.h"
|
||||||
#include "src/tint/ast/sampled_texture.h"
|
#include "src/tint/ast/sampled_texture.h"
|
||||||
#include "src/tint/ast/stage_attribute.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/stride_attribute.h"
|
||||||
#include "src/tint/ast/struct_member_align_attribute.h"
|
#include "src/tint/ast/struct_member_align_attribute.h"
|
||||||
#include "src/tint/ast/struct_member_offset_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 dims the dimensionality of the texture
|
||||||
/// @param format the texel format of the texture
|
/// @param format the texel format of the texture
|
||||||
/// @param access the access control of the texture
|
/// @param access the access control of the texture
|
||||||
/// @returns the storage texture
|
/// @returns the storage texture typename
|
||||||
const ast::StorageTexture* storage_texture(type::TextureDimension dims,
|
const ast::TypeName* storage_texture(type::TextureDimension dims,
|
||||||
type::TexelFormat format,
|
type::TexelFormat format,
|
||||||
type::Access access) const {
|
type::Access access) const {
|
||||||
auto* subtype = ast::StorageTexture::SubtypeFor(format, *builder);
|
return storage_texture(builder->source_, dims, format, access);
|
||||||
return builder->create<ast::StorageTexture>(dims, format, subtype, access);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @param source the Source of the node
|
/// @param source the Source of the node
|
||||||
/// @param dims the dimensionality of the texture
|
/// @param dims the dimensionality of the texture
|
||||||
/// @param format the texel format of the texture
|
/// @param format the texel format of the texture
|
||||||
/// @param access the access control of the texture
|
/// @param access the access control of the texture
|
||||||
/// @returns the storage texture
|
/// @returns the storage texture typename
|
||||||
const ast::StorageTexture* storage_texture(const Source& source,
|
const ast::TypeName* storage_texture(const Source& source,
|
||||||
type::TextureDimension dims,
|
type::TextureDimension dims,
|
||||||
type::TexelFormat format,
|
type::TexelFormat format,
|
||||||
type::Access access) const {
|
type::Access access) const {
|
||||||
auto* subtype = ast::StorageTexture::SubtypeFor(format, *builder);
|
switch (dims) {
|
||||||
return builder->create<ast::StorageTexture>(source, dims, format, subtype, access);
|
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
|
/// @returns the external texture
|
||||||
|
|
|
@ -19,11 +19,12 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "src/tint/ast/storage_texture.h"
|
|
||||||
#include "src/tint/castable.h"
|
#include "src/tint/castable.h"
|
||||||
|
#include "src/tint/symbol.h"
|
||||||
#include "src/tint/type/access.h"
|
#include "src/tint/type/access.h"
|
||||||
#include "src/tint/type/address_space.h"
|
#include "src/tint/type/address_space.h"
|
||||||
#include "src/tint/type/sampler_kind.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/type/texture_dimension.h"
|
||||||
#include "src/tint/utils/block_allocator.h"
|
#include "src/tint/utils/block_allocator.h"
|
||||||
|
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include "src/tint/ast/test_helper.h"
|
||||||
#include "src/tint/reader/wgsl/parser_impl_test_helper.h"
|
#include "src/tint/reader/wgsl/parser_impl_test_helper.h"
|
||||||
#include "src/tint/type/depth_texture.h"
|
#include "src/tint/type/depth_texture.h"
|
||||||
#include "src/tint/type/multisampled_texture.h"
|
#include "src/tint/type/multisampled_texture.h"
|
||||||
|
@ -195,11 +196,8 @@ TEST_F(ParserImplTest, TextureSamplerTypes_StorageTexture_Readonly1dRg32Float) {
|
||||||
EXPECT_FALSE(t.errored);
|
EXPECT_FALSE(t.errored);
|
||||||
ASSERT_NE(t.value, nullptr);
|
ASSERT_NE(t.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(t->Is<ast::Texture>());
|
ast::CheckIdentifier(p->builder().Symbols(), t->As<ast::TypeName>()->name,
|
||||||
ASSERT_TRUE(t->Is<ast::StorageTexture>());
|
ast::Template("texture_storage_1d", "rg32float", "read"));
|
||||||
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);
|
|
||||||
EXPECT_EQ(t->source.range, (Source::Range{{1u, 1u}, {1u, 36u}}));
|
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);
|
EXPECT_FALSE(t.errored);
|
||||||
ASSERT_NE(t.value, nullptr);
|
ASSERT_NE(t.value, nullptr);
|
||||||
|
|
||||||
ASSERT_TRUE(t->Is<ast::Texture>());
|
ast::CheckIdentifier(p->builder().Symbols(), t->As<ast::TypeName>()->name,
|
||||||
ASSERT_TRUE(t->Is<ast::StorageTexture>());
|
ast::Template("texture_storage_2d", "r32uint", "write"));
|
||||||
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);
|
|
||||||
EXPECT_EQ(t->source.range, (Source::Range{{1u, 1u}, {1u, 35u}}));
|
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/return_statement.h"
|
||||||
#include "src/tint/ast/sampled_texture.h"
|
#include "src/tint/ast/sampled_texture.h"
|
||||||
#include "src/tint/ast/stage_attribute.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/stride_attribute.h"
|
||||||
#include "src/tint/ast/struct.h"
|
#include "src/tint/ast/struct.h"
|
||||||
#include "src/tint/ast/struct_member_align_attribute.h"
|
#include "src/tint/ast/struct_member_align_attribute.h"
|
||||||
|
@ -338,31 +337,44 @@ class DependencyScanner {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Traverses the expression, performing symbol resolution and determining
|
/// Traverses the expression, performing symbol resolution and determining global dependencies.
|
||||||
/// global dependencies.
|
|
||||||
void TraverseExpression(const ast::Expression* root) {
|
void TraverseExpression(const ast::Expression* root) {
|
||||||
if (!root) {
|
if (!root) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ast::TraverseExpressions(root, diagnostics_, [&](const ast::Expression* expr) {
|
utils::Vector<const ast::Expression*, 8> pending{root};
|
||||||
Switch(
|
while (!pending.IsEmpty()) {
|
||||||
expr,
|
ast::TraverseExpressions(pending.Pop(), diagnostics_, [&](const ast::Expression* expr) {
|
||||||
[&](const ast::IdentifierExpression* ident) {
|
Switch(
|
||||||
AddDependency(ident->identifier, ident->identifier->symbol, "identifier",
|
expr,
|
||||||
"references");
|
[&](const ast::IdentifierExpression* e) {
|
||||||
},
|
AddDependency(e->identifier, e->identifier->symbol, "identifier",
|
||||||
[&](const ast::CallExpression* call) {
|
"references");
|
||||||
if (call->target.name) {
|
if (auto* tmpl_ident = e->identifier->As<ast::TemplatedIdentifier>()) {
|
||||||
AddDependency(call->target.name, call->target.name->symbol, "function",
|
for (auto* arg : tmpl_ident->arguments) {
|
||||||
"calls");
|
pending.Push(arg);
|
||||||
}
|
}
|
||||||
if (call->target.type) {
|
}
|
||||||
TraverseType(call->target.type);
|
},
|
||||||
}
|
[&](const ast::CallExpression* call) {
|
||||||
},
|
if (call->target.name) {
|
||||||
[&](const ast::BitcastExpression* cast) { TraverseType(cast->type); });
|
AddDependency(call->target.name, call->target.name->symbol, "function",
|
||||||
return ast::TraverseAction::Descend;
|
"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
|
/// Traverses the type node, performing symbol resolution and determining
|
||||||
|
@ -388,6 +400,11 @@ class DependencyScanner {
|
||||||
},
|
},
|
||||||
[&](const ast::TypeName* tn) { //
|
[&](const ast::TypeName* tn) { //
|
||||||
AddDependency(tn->name, tn->name->symbol, "type", "references");
|
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) { //
|
[&](const ast::Vector* vec) { //
|
||||||
TraverseType(vec->type);
|
TraverseType(vec->type);
|
||||||
|
@ -398,9 +415,6 @@ class DependencyScanner {
|
||||||
[&](const ast::MultisampledTexture* tex) { //
|
[&](const ast::MultisampledTexture* tex) { //
|
||||||
TraverseType(tex->type);
|
TraverseType(tex->type);
|
||||||
},
|
},
|
||||||
[&](const ast::StorageTexture* tex) { //
|
|
||||||
TraverseType(tex->type);
|
|
||||||
},
|
|
||||||
[&](Default) { UnhandledNode(diagnostics_, ty); });
|
[&](Default) { UnhandledNode(diagnostics_, ty); });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -121,7 +121,7 @@ TEST_P(ResolverExpressionKindTest, Test) {
|
||||||
Symbol sym;
|
Symbol sym;
|
||||||
switch (GetParam().def) {
|
switch (GetParam().def) {
|
||||||
case Def::kAccess:
|
case Def::kAccess:
|
||||||
sym = Sym("read_write");
|
sym = Sym("write");
|
||||||
break;
|
break;
|
||||||
case Def::kAddressSpace:
|
case Def::kAddressSpace:
|
||||||
sym = Sym("workgroup");
|
sym = Sym("workgroup");
|
||||||
|
@ -155,7 +155,8 @@ TEST_P(ResolverExpressionKindTest, Test) {
|
||||||
|
|
||||||
switch (GetParam().use) {
|
switch (GetParam().use) {
|
||||||
case Use::kAccess:
|
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:
|
case Use::kAddressSpace:
|
||||||
return; // TODO(crbug.com/tint/1810)
|
return; // TODO(crbug.com/tint/1810)
|
||||||
case Use::kCallExpr:
|
case Use::kCallExpr:
|
||||||
|
@ -174,7 +175,8 @@ TEST_P(ResolverExpressionKindTest, Test) {
|
||||||
Structure("s", utils::Vector{Member("m", ty(kUseSource, sym))});
|
Structure("s", utils::Vector{Member("m", ty(kUseSource, sym))});
|
||||||
break;
|
break;
|
||||||
case Use::kTexelFormat:
|
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:
|
case Use::kValueExpression:
|
||||||
GlobalVar("v", type::AddressSpace::kPrivate, Expr(kUseSource, sym));
|
GlobalVar("v", type::AddressSpace::kPrivate, Expr(kUseSource, sym));
|
||||||
break;
|
break;
|
||||||
|
@ -201,21 +203,18 @@ INSTANTIATE_TEST_SUITE_P(
|
||||||
testing::ValuesIn(std::vector<Case>{
|
testing::ValuesIn(std::vector<Case>{
|
||||||
{Def::kAccess, Use::kAccess, kPass},
|
{Def::kAccess, Use::kAccess, kPass},
|
||||||
{Def::kAccess, Use::kAddressSpace, R"(TODO(crbug.com/tint/1810))"},
|
{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::kBinaryOp, R"(5:6 error: cannot use access 'write' as value)"},
|
||||||
{Def::kAccess, Use::kCallExpr,
|
{Def::kAccess, Use::kCallExpr, R"(5:6 error: cannot use access 'write' as call target)"},
|
||||||
R"(5:6 error: cannot use access 'read_write' as call target)"},
|
{Def::kAccess, Use::kCallStmt, R"(5:6 error: cannot use access 'write' as call target)"},
|
||||||
{Def::kAccess, Use::kCallStmt,
|
{Def::kAccess, Use::kFunctionReturnType, R"(5:6 error: cannot use access 'write' as type)"},
|
||||||
R"(5:6 error: cannot use access 'read_write' as call target)"},
|
{Def::kAccess, Use::kMemberType, R"(5:6 error: cannot use access 'write' as type)"},
|
||||||
{Def::kAccess, Use::kFunctionReturnType,
|
{Def::kAccess, Use::kTexelFormat, R"(error: cannot use access 'write' as texel format)"},
|
||||||
R"(5:6 error: cannot use access 'read_write' as type)"},
|
{Def::kAccess, Use::kValueExpression, R"(5:6 error: cannot use access 'write' as value)"},
|
||||||
{Def::kAccess, Use::kMemberType, R"(5:6 error: cannot use access 'read_write' as type)"},
|
{Def::kAccess, Use::kVariableType, R"(5:6 error: cannot use access 'write' as type)"},
|
||||||
{Def::kAccess, Use::kTexelFormat, R"(TODO(crbug.com/tint/1810))"},
|
{Def::kAccess, Use::kUnaryOp, R"(5:6 error: cannot use access 'write' as value)"},
|
||||||
{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::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::kAddressSpace, kPass},
|
||||||
{Def::kAddressSpace, Use::kBinaryOp,
|
{Def::kAddressSpace, Use::kBinaryOp,
|
||||||
R"(5:6 error: cannot use address space 'workgroup' as value)"},
|
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)"},
|
R"(5:6 error: cannot use address space 'workgroup' as type)"},
|
||||||
{Def::kAddressSpace, Use::kMemberType,
|
{Def::kAddressSpace, Use::kMemberType,
|
||||||
R"(5:6 error: cannot use address space 'workgroup' as type)"},
|
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,
|
{Def::kAddressSpace, Use::kValueExpression,
|
||||||
R"(5:6 error: cannot use address space 'workgroup' as value)"},
|
R"(5:6 error: cannot use address space 'workgroup' as value)"},
|
||||||
{Def::kAddressSpace, Use::kVariableType,
|
{Def::kAddressSpace, Use::kVariableType,
|
||||||
|
@ -235,7 +235,7 @@ INSTANTIATE_TEST_SUITE_P(
|
||||||
{Def::kAddressSpace, Use::kUnaryOp,
|
{Def::kAddressSpace, Use::kUnaryOp,
|
||||||
R"(5:6 error: cannot use address space 'workgroup' as value)"},
|
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::kAddressSpace, R"(TODO(crbug.com/tint/1810))"},
|
||||||
{Def::kBuiltinFunction, Use::kBinaryOp,
|
{Def::kBuiltinFunction, Use::kBinaryOp,
|
||||||
R"(7:8 error: missing '(' for builtin function call)"},
|
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)"},
|
R"(5:6 error: cannot use builtin function 'workgroupBarrier' as type)"},
|
||||||
{Def::kBuiltinFunction, Use::kMemberType,
|
{Def::kBuiltinFunction, Use::kMemberType,
|
||||||
R"(5:6 error: cannot use builtin function 'workgroupBarrier' as type)"},
|
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,
|
{Def::kBuiltinFunction, Use::kValueExpression,
|
||||||
R"(7:8 error: missing '(' for builtin function call)"},
|
R"(7:8 error: missing '(' for builtin function call)"},
|
||||||
{Def::kBuiltinFunction, Use::kVariableType,
|
{Def::kBuiltinFunction, Use::kVariableType,
|
||||||
|
@ -252,7 +253,7 @@ INSTANTIATE_TEST_SUITE_P(
|
||||||
{Def::kBuiltinFunction, Use::kUnaryOp,
|
{Def::kBuiltinFunction, Use::kUnaryOp,
|
||||||
R"(7:8 error: missing '(' for builtin function call)"},
|
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::kAddressSpace, kPass},
|
||||||
{Def::kBuiltinType, Use::kBinaryOp,
|
{Def::kBuiltinType, Use::kBinaryOp,
|
||||||
R"(5:6 error: cannot use type 'vec4<f32>' as value
|
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::kCallExpr, kPass},
|
||||||
{Def::kBuiltinType, Use::kFunctionReturnType, kPass},
|
{Def::kBuiltinType, Use::kFunctionReturnType, kPass},
|
||||||
{Def::kBuiltinType, Use::kMemberType, 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,
|
{Def::kBuiltinType, Use::kValueExpression,
|
||||||
R"(5:6 error: cannot use type 'vec4<f32>' as value
|
R"(5:6 error: cannot use type 'vec4<f32>' as value
|
||||||
7:8 note: are you missing '()' for type initializer?)"},
|
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
|
R"(5:6 error: cannot use type 'vec4<f32>' as value
|
||||||
7:8 note: are you missing '()' for type initializer?)"},
|
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::kAddressSpace, R"(TODO(crbug.com/tint/1810))"},
|
||||||
{Def::kFunction, Use::kBinaryOp, R"(7:8 error: missing '(' for function call)"},
|
{Def::kFunction, Use::kBinaryOp, R"(7:8 error: missing '(' for function call)"},
|
||||||
{Def::kFunction, Use::kCallExpr, kPass},
|
{Def::kFunction, Use::kCallExpr, kPass},
|
||||||
{Def::kFunction, Use::kCallStmt, kPass},
|
{Def::kFunction, Use::kCallStmt, kPass},
|
||||||
{Def::kFunction, Use::kFunctionReturnType,
|
{Def::kFunction, Use::kFunctionReturnType,
|
||||||
R"(5:6 error: cannot use function 'FUNCTION' as type
|
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,
|
{Def::kFunction, Use::kMemberType,
|
||||||
R"(5:6 error: cannot use function 'FUNCTION' as type
|
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::kTexelFormat, R"(TODO(crbug.com/tint/1810))"},
|
{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::kValueExpression, R"(7:8 error: missing '(' for function call)"},
|
||||||
{Def::kFunction, Use::kVariableType,
|
{Def::kFunction, Use::kVariableType,
|
||||||
R"(5:6 error: cannot use function 'FUNCTION' as type
|
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::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::kAddressSpace, R"(TODO(crbug.com/tint/1810))"},
|
||||||
{Def::kStruct, Use::kBinaryOp, R"(5:6 error: cannot use type 'STRUCT' as value
|
{Def::kStruct, Use::kBinaryOp, R"(5:6 error: cannot use type 'STRUCT' as value
|
||||||
7:8 note: are you missing '()' for type initializer?
|
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::kFunctionReturnType, kPass},
|
||||||
{Def::kStruct, Use::kMemberType, 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,
|
{Def::kStruct, Use::kValueExpression,
|
||||||
R"(5:6 error: cannot use type 'STRUCT' as value
|
R"(5:6 error: cannot use type 'STRUCT' as value
|
||||||
7:8 note: are you missing '()' for type initializer?
|
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::kVariableType, kPass},
|
||||||
{Def::kStruct, Use::kUnaryOp,
|
{Def::kStruct, Use::kUnaryOp,
|
||||||
R"(5:6 error: cannot use type 'STRUCT' as value
|
R"(5:6 error: cannot use type 'STRUCT' as value
|
||||||
7:8 note: are you missing '()' for type initializer?
|
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::kAddressSpace, R"(TODO(crbug.com/tint/1810))"},
|
||||||
{Def::kTexelFormat, Use::kBinaryOp,
|
{Def::kTexelFormat, Use::kBinaryOp,
|
||||||
R"(5:6 error: cannot use texel format 'rgba8unorm' as value)"},
|
R"(5:6 error: cannot use texel format 'rgba8unorm' as value)"},
|
||||||
|
@ -325,7 +328,7 @@ INSTANTIATE_TEST_SUITE_P(
|
||||||
{Def::kTexelFormat, Use::kUnaryOp,
|
{Def::kTexelFormat, Use::kUnaryOp,
|
||||||
R"(5:6 error: cannot use texel format 'rgba8unorm' as value)"},
|
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::kAddressSpace, R"(TODO(crbug.com/tint/1810))"},
|
||||||
{Def::kTypeAlias, Use::kBinaryOp,
|
{Def::kTypeAlias, Use::kBinaryOp,
|
||||||
R"(5:6 error: cannot use type 'i32' as value
|
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::kCallExpr, kPass},
|
||||||
{Def::kTypeAlias, Use::kFunctionReturnType, kPass},
|
{Def::kTypeAlias, Use::kFunctionReturnType, kPass},
|
||||||
{Def::kTypeAlias, Use::kMemberType, 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,
|
{Def::kTypeAlias, Use::kValueExpression,
|
||||||
R"(5:6 error: cannot use type 'i32' as value
|
R"(5:6 error: cannot use type 'i32' as value
|
||||||
7:8 note: are you missing '()' for type initializer?)"},
|
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
|
R"(5:6 error: cannot use type 'i32' as value
|
||||||
7:8 note: are you missing '()' for type initializer?)"},
|
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::kAddressSpace, R"(TODO(crbug.com/tint/1810))"},
|
||||||
{Def::kVariable, Use::kBinaryOp, kPass},
|
{Def::kVariable, Use::kBinaryOp, kPass},
|
||||||
{Def::kVariable, Use::kCallStmt,
|
{Def::kVariable, Use::kCallStmt,
|
||||||
R"(5:6 error: cannot use const 'VARIABLE' as call target
|
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,
|
{Def::kVariable, Use::kCallExpr,
|
||||||
R"(5:6 error: cannot use const 'VARIABLE' as call target
|
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,
|
{Def::kVariable, Use::kFunctionReturnType,
|
||||||
R"(5:6 error: cannot use const 'VARIABLE' as type
|
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,
|
{Def::kVariable, Use::kMemberType,
|
||||||
R"(5:6 error: cannot use const 'VARIABLE' as type
|
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::kTexelFormat, R"(TODO(crbug.com/tint/1810))"},
|
{Def::kVariable, Use::kTexelFormat,
|
||||||
|
R"(error: cannot use 'VARIABLE' of type 'i32' as texel format)"},
|
||||||
{Def::kVariable, Use::kValueExpression, kPass},
|
{Def::kVariable, Use::kValueExpression, kPass},
|
||||||
{Def::kVariable, Use::kVariableType,
|
{Def::kVariable, Use::kVariableType,
|
||||||
R"(5:6 error: cannot use const 'VARIABLE' as type
|
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},
|
{Def::kVariable, Use::kUnaryOp, kPass},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,6 @@
|
||||||
#include "src/tint/ast/pointer.h"
|
#include "src/tint/ast/pointer.h"
|
||||||
#include "src/tint/ast/return_statement.h"
|
#include "src/tint/ast/return_statement.h"
|
||||||
#include "src/tint/ast/sampled_texture.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/switch_statement.h"
|
||||||
#include "src/tint/ast/traverse_expressions.h"
|
#include "src/tint/ast/traverse_expressions.h"
|
||||||
#include "src/tint/ast/type_name.h"
|
#include "src/tint/ast/type_name.h"
|
||||||
|
@ -308,22 +307,9 @@ type::Type* Resolver::Type(const ast::Type* ty) {
|
||||||
}
|
}
|
||||||
return nullptr;
|
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* {
|
[&](const ast::TypeName* t) -> type::Type* {
|
||||||
Mark(t->name);
|
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);
|
auto resolved = dependencies_.resolved_identifiers.Get(t->name);
|
||||||
if (!resolved) {
|
if (!resolved) {
|
||||||
TINT_ICE(Resolver, diagnostics_)
|
TINT_ICE(Resolver, diagnostics_)
|
||||||
|
@ -338,6 +324,15 @@ type::Type* Resolver::Type(const ast::Type* ty) {
|
||||||
ErrorMismatchedResolvedIdentifier(t->source, *resolved, "type");
|
ErrorMismatchedResolvedIdentifier(t->source, *resolved, "type");
|
||||||
return nullptr;
|
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;
|
return type;
|
||||||
}
|
}
|
||||||
if (auto b = resolved->BuiltinType(); b != type::Builtin::kUndefined) {
|
if (auto b = resolved->BuiltinType(); b != type::Builtin::kUndefined) {
|
||||||
|
@ -2431,9 +2426,18 @@ sem::Call* Resolver::BuiltinCall(const ast::CallExpression* expr,
|
||||||
return call;
|
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& 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 f32 = [&] { return b.create<type::F32>(); };
|
||||||
auto i32 = [&] { return b.create<type::I32>(); };
|
auto i32 = [&] { return b.create<type::I32>(); };
|
||||||
auto u32 = [&] { return b.create<type::U32>(); };
|
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) {
|
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;
|
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) {
|
switch (builtin_ty) {
|
||||||
case type::Builtin::kBool:
|
case type::Builtin::kBool:
|
||||||
return b.create<type::Bool>();
|
return check_no_tmpl_args(b.create<type::Bool>());
|
||||||
case type::Builtin::kI32:
|
case type::Builtin::kI32:
|
||||||
return i32();
|
return check_no_tmpl_args(i32());
|
||||||
case type::Builtin::kU32:
|
case type::Builtin::kU32:
|
||||||
return u32();
|
return check_no_tmpl_args(u32());
|
||||||
case type::Builtin::kF16:
|
case type::Builtin::kF16:
|
||||||
return f16();
|
return check_no_tmpl_args(f16());
|
||||||
case type::Builtin::kF32:
|
case type::Builtin::kF32:
|
||||||
return b.create<type::F32>();
|
return check_no_tmpl_args(b.create<type::F32>());
|
||||||
case type::Builtin::kMat2X2F:
|
case type::Builtin::kMat2X2F:
|
||||||
return mat(f32(), 2u, 2u);
|
return check_no_tmpl_args(mat(f32(), 2u, 2u));
|
||||||
case type::Builtin::kMat2X3F:
|
case type::Builtin::kMat2X3F:
|
||||||
return mat(f32(), 2u, 3u);
|
return check_no_tmpl_args(mat(f32(), 2u, 3u));
|
||||||
case type::Builtin::kMat2X4F:
|
case type::Builtin::kMat2X4F:
|
||||||
return mat(f32(), 2u, 4u);
|
return check_no_tmpl_args(mat(f32(), 2u, 4u));
|
||||||
case type::Builtin::kMat3X2F:
|
case type::Builtin::kMat3X2F:
|
||||||
return mat(f32(), 3u, 2u);
|
return check_no_tmpl_args(mat(f32(), 3u, 2u));
|
||||||
case type::Builtin::kMat3X3F:
|
case type::Builtin::kMat3X3F:
|
||||||
return mat(f32(), 3u, 3u);
|
return check_no_tmpl_args(mat(f32(), 3u, 3u));
|
||||||
case type::Builtin::kMat3X4F:
|
case type::Builtin::kMat3X4F:
|
||||||
return mat(f32(), 3u, 4u);
|
return check_no_tmpl_args(mat(f32(), 3u, 4u));
|
||||||
case type::Builtin::kMat4X2F:
|
case type::Builtin::kMat4X2F:
|
||||||
return mat(f32(), 4u, 2u);
|
return check_no_tmpl_args(mat(f32(), 4u, 2u));
|
||||||
case type::Builtin::kMat4X3F:
|
case type::Builtin::kMat4X3F:
|
||||||
return mat(f32(), 4u, 3u);
|
return check_no_tmpl_args(mat(f32(), 4u, 3u));
|
||||||
case type::Builtin::kMat4X4F:
|
case type::Builtin::kMat4X4F:
|
||||||
return mat(f32(), 4u, 4u);
|
return check_no_tmpl_args(mat(f32(), 4u, 4u));
|
||||||
case type::Builtin::kMat2X2H:
|
case type::Builtin::kMat2X2H:
|
||||||
return mat(f16(), 2u, 2u);
|
return check_no_tmpl_args(mat(f16(), 2u, 2u));
|
||||||
case type::Builtin::kMat2X3H:
|
case type::Builtin::kMat2X3H:
|
||||||
return mat(f16(), 2u, 3u);
|
return check_no_tmpl_args(mat(f16(), 2u, 3u));
|
||||||
case type::Builtin::kMat2X4H:
|
case type::Builtin::kMat2X4H:
|
||||||
return mat(f16(), 2u, 4u);
|
return check_no_tmpl_args(mat(f16(), 2u, 4u));
|
||||||
case type::Builtin::kMat3X2H:
|
case type::Builtin::kMat3X2H:
|
||||||
return mat(f16(), 3u, 2u);
|
return check_no_tmpl_args(mat(f16(), 3u, 2u));
|
||||||
case type::Builtin::kMat3X3H:
|
case type::Builtin::kMat3X3H:
|
||||||
return mat(f16(), 3u, 3u);
|
return check_no_tmpl_args(mat(f16(), 3u, 3u));
|
||||||
case type::Builtin::kMat3X4H:
|
case type::Builtin::kMat3X4H:
|
||||||
return mat(f16(), 3u, 4u);
|
return check_no_tmpl_args(mat(f16(), 3u, 4u));
|
||||||
case type::Builtin::kMat4X2H:
|
case type::Builtin::kMat4X2H:
|
||||||
return mat(f16(), 4u, 2u);
|
return check_no_tmpl_args(mat(f16(), 4u, 2u));
|
||||||
case type::Builtin::kMat4X3H:
|
case type::Builtin::kMat4X3H:
|
||||||
return mat(f16(), 4u, 3u);
|
return check_no_tmpl_args(mat(f16(), 4u, 3u));
|
||||||
case type::Builtin::kMat4X4H:
|
case type::Builtin::kMat4X4H:
|
||||||
return mat(f16(), 4u, 4u);
|
return check_no_tmpl_args(mat(f16(), 4u, 4u));
|
||||||
case type::Builtin::kVec2F:
|
case type::Builtin::kVec2F:
|
||||||
return vec(f32(), 2u);
|
return check_no_tmpl_args(vec(f32(), 2u));
|
||||||
case type::Builtin::kVec3F:
|
case type::Builtin::kVec3F:
|
||||||
return vec(f32(), 3u);
|
return check_no_tmpl_args(vec(f32(), 3u));
|
||||||
case type::Builtin::kVec4F:
|
case type::Builtin::kVec4F:
|
||||||
return vec(f32(), 4u);
|
return check_no_tmpl_args(vec(f32(), 4u));
|
||||||
case type::Builtin::kVec2H:
|
case type::Builtin::kVec2H:
|
||||||
return vec(f16(), 2u);
|
return check_no_tmpl_args(vec(f16(), 2u));
|
||||||
case type::Builtin::kVec3H:
|
case type::Builtin::kVec3H:
|
||||||
return vec(f16(), 3u);
|
return check_no_tmpl_args(vec(f16(), 3u));
|
||||||
case type::Builtin::kVec4H:
|
case type::Builtin::kVec4H:
|
||||||
return vec(f16(), 4u);
|
return check_no_tmpl_args(vec(f16(), 4u));
|
||||||
case type::Builtin::kVec2I:
|
case type::Builtin::kVec2I:
|
||||||
return vec(i32(), 2u);
|
return check_no_tmpl_args(vec(i32(), 2u));
|
||||||
case type::Builtin::kVec3I:
|
case type::Builtin::kVec3I:
|
||||||
return vec(i32(), 3u);
|
return check_no_tmpl_args(vec(i32(), 3u));
|
||||||
case type::Builtin::kVec4I:
|
case type::Builtin::kVec4I:
|
||||||
return vec(i32(), 4u);
|
return check_no_tmpl_args(vec(i32(), 4u));
|
||||||
case type::Builtin::kVec2U:
|
case type::Builtin::kVec2U:
|
||||||
return vec(u32(), 2u);
|
return check_no_tmpl_args(vec(u32(), 2u));
|
||||||
case type::Builtin::kVec3U:
|
case type::Builtin::kVec3U:
|
||||||
return vec(u32(), 3u);
|
return check_no_tmpl_args(vec(u32(), 3u));
|
||||||
case type::Builtin::kVec4U:
|
case type::Builtin::kVec4U:
|
||||||
return vec(u32(), 4u);
|
return check_no_tmpl_args(vec(u32(), 4u));
|
||||||
case type::Builtin::kSampler:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
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:
|
case type::Builtin::kUndefined:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -4021,19 +4074,43 @@ void Resolver::ErrorMismatchedResolvedIdentifier(const Source& source,
|
||||||
AddError("cannot use " + resolved.String(builder_->Symbols(), diagnostics_) + " as " +
|
AddError("cannot use " + resolved.String(builder_->Symbols(), diagnostics_) + " as " +
|
||||||
std::string(wanted),
|
std::string(wanted),
|
||||||
source);
|
source);
|
||||||
|
NoteDeclarationSource(resolved.Node());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Resolver::NoteDeclarationSource(const ast::Node* node) {
|
||||||
Switch(
|
Switch(
|
||||||
resolved.Node(),
|
node,
|
||||||
[&](const ast::TypeDecl* n) {
|
[&](const ast::Struct* n) {
|
||||||
AddNote("'" + builder_->Symbols().NameFor(n->name->symbol) + "' declared here",
|
AddNote("struct '" + builder_->Symbols().NameFor(n->name->symbol) + "' declared here",
|
||||||
n->source);
|
n->source);
|
||||||
},
|
},
|
||||||
[&](const ast::Variable* n) {
|
[&](const ast::Alias* n) {
|
||||||
AddNote("'" + builder_->Symbols().NameFor(n->name->symbol) + "' declared here",
|
AddNote("alias '" + builder_->Symbols().NameFor(n->name->symbol) + "' declared here",
|
||||||
n->source);
|
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) {
|
[&](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);
|
n->source);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -432,6 +432,11 @@ class Resolver {
|
||||||
const ResolvedIdentifier& resolved,
|
const ResolvedIdentifier& resolved,
|
||||||
std::string_view wanted);
|
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
|
/// Adds the given error message to the diagnostics
|
||||||
void AddError(const std::string& msg, const Source& source) const;
|
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
|
/// @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.
|
/// @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.
|
// ArrayInitializerSig represents a unique array initializer signature.
|
||||||
// It is a tuple of the array type, number of arguments provided and earliest evaluation stage.
|
// 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;
|
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(
|
Switch(
|
||||||
expr, //
|
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) {
|
[&](const sem::TypeExpression* ty_expr) {
|
||||||
auto name = ty_expr->Type()->FriendlyName(builder_->Symbols());
|
auto name = ty_expr->Type()->FriendlyName(builder_->Symbols());
|
||||||
AddError("cannot use type '" + name + "' as value", ty_expr->Declaration()->source);
|
AddError("cannot use type '" + name + "' as " + std::string(wanted),
|
||||||
if (auto* ident = ty_expr->Declaration()->As<ast::IdentifierExpression>()) {
|
ty_expr->Declaration()->source);
|
||||||
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());
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
[&](const sem::BuiltinEnumExpression<type::Access>* access) {
|
[&](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);
|
access->Declaration()->source);
|
||||||
},
|
},
|
||||||
[&](const sem::BuiltinEnumExpression<type::AddressSpace>* addr) {
|
[&](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);
|
addr->Declaration()->source);
|
||||||
},
|
},
|
||||||
[&](const sem::BuiltinEnumExpression<type::TexelFormat>* fmt) {
|
[&](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);
|
fmt->Declaration()->source);
|
||||||
},
|
},
|
||||||
[&](Default) {
|
[&](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 {
|
void SemHelper::AddError(const std::string& msg, const Source& source) const {
|
||||||
builder_->Diagnostics().add_error(diag::System::Resolver, msg, source);
|
builder_->Diagnostics().add_error(diag::System::Resolver, msg, source);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "src/tint/diagnostic/diagnostic.h"
|
#include "src/tint/diagnostic/diagnostic.h"
|
||||||
#include "src/tint/program_builder.h"
|
#include "src/tint/program_builder.h"
|
||||||
#include "src/tint/resolver/dependency_graph.h"
|
#include "src/tint/resolver/dependency_graph.h"
|
||||||
|
#include "src/tint/sem/builtin_enum_expression.h"
|
||||||
#include "src/tint/utils/map.h"
|
#include "src/tint/utils/map.h"
|
||||||
|
|
||||||
namespace tint::resolver {
|
namespace tint::resolver {
|
||||||
|
@ -61,25 +62,46 @@ class SemHelper {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @param expr the semantic node
|
/// @param expr the semantic node
|
||||||
/// @returns one of:
|
/// @returns nullptr if @p expr is nullptr, or @p expr cast to sem::ValueExpression if the cast
|
||||||
/// * nullptr if @p expr is nullptr
|
/// is successful, otherwise an error diagnostic is raised.
|
||||||
/// * @p expr if the static pointer type already derives from sem::ValueExpression
|
sem::ValueExpression* AsValue(sem::Expression* expr) const {
|
||||||
/// * @p expr cast to sem::ValueExpression if the cast is successful
|
if (TINT_LIKELY(expr)) {
|
||||||
/// * nullptr if @p expr is not a sem::ValueExpression. In this case an error diagnostic is
|
if (auto* val = expr->As<sem::ValueExpression>(); TINT_LIKELY(val)) {
|
||||||
/// raised.
|
return val;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
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
|
/// @returns the resolved type of the ast::Expression @p expr
|
||||||
|
@ -100,6 +122,10 @@ class SemHelper {
|
||||||
void ErrorExpectedValueExpr(const sem::Expression* expr) const;
|
void ErrorExpectedValueExpr(const sem::Expression* expr) const;
|
||||||
|
|
||||||
private:
|
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
|
/// Adds the given error message to the diagnostics
|
||||||
void AddError(const std::string& msg, const Source& source) const;
|
void AddError(const std::string& msg, const Source& source) const;
|
||||||
|
|
||||||
|
|
|
@ -1064,26 +1064,26 @@ INSTANTIATE_TEST_SUITE_P(ResolverTypeValidationTest,
|
||||||
|
|
||||||
namespace StorageTextureTests {
|
namespace StorageTextureTests {
|
||||||
struct DimensionParams {
|
struct DimensionParams {
|
||||||
type::TextureDimension dim;
|
const char* name;
|
||||||
bool is_valid;
|
bool is_valid;
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr DimensionParams Dimension_cases[] = {
|
static constexpr DimensionParams Dimension_cases[] = {
|
||||||
DimensionParams{type::TextureDimension::k1d, true},
|
DimensionParams{"texture_storage_1d", true},
|
||||||
DimensionParams{type::TextureDimension::k2d, true},
|
DimensionParams{"texture_storage_2d", true},
|
||||||
DimensionParams{type::TextureDimension::k2dArray, true},
|
DimensionParams{"texture_storage_2d_array", true},
|
||||||
DimensionParams{type::TextureDimension::k3d, true},
|
DimensionParams{"texture_storage_3d", true},
|
||||||
DimensionParams{type::TextureDimension::kCube, false},
|
DimensionParams{"texture_storage_cube", false},
|
||||||
DimensionParams{type::TextureDimension::kCubeArray, false}};
|
DimensionParams{"texture_storage_cube_array", false}};
|
||||||
|
|
||||||
using StorageTextureDimensionTest = ResolverTestWithParam<DimensionParams>;
|
using StorageTextureDimensionTest = ResolverTestWithParam<DimensionParams>;
|
||||||
TEST_P(StorageTextureDimensionTest, All) {
|
TEST_P(StorageTextureDimensionTest, All) {
|
||||||
// @group(0) @binding(0)
|
// @group(0) @binding(0)
|
||||||
// var a : texture_storage_*<ru32int, write>;
|
// var a : texture_storage_*<r32uint, write>;
|
||||||
auto& params = GetParam();
|
auto& params = GetParam();
|
||||||
|
|
||||||
auto* st = ty.storage_texture(Source{{12, 34}}, params.dim, type::TexelFormat::kR32Uint,
|
auto* st = ty(Source{{12, 34}}, params.name, utils::ToString(type::TexelFormat::kR32Uint),
|
||||||
type::Access::kWrite);
|
utils::ToString(type::Access::kWrite));
|
||||||
|
|
||||||
GlobalVar("a", st, Group(0_a), Binding(0_a));
|
GlobalVar("a", st, Group(0_a), Binding(0_a));
|
||||||
|
|
||||||
|
@ -1091,8 +1091,7 @@ TEST_P(StorageTextureDimensionTest, All) {
|
||||||
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
EXPECT_TRUE(r()->Resolve()) << r()->error();
|
||||||
} else {
|
} else {
|
||||||
EXPECT_FALSE(r()->Resolve());
|
EXPECT_FALSE(r()->Resolve());
|
||||||
EXPECT_EQ(r()->error(),
|
EXPECT_EQ(r()->error(), "12:34 error: unknown type: '" + std::string(params.name) + "'");
|
||||||
"12:34 error: cube dimensions for storage textures are not supported");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
INSTANTIATE_TEST_SUITE_P(ResolverTypeValidationTest,
|
INSTANTIATE_TEST_SUITE_P(ResolverTypeValidationTest,
|
||||||
|
@ -1165,22 +1164,33 @@ INSTANTIATE_TEST_SUITE_P(ResolverTypeValidationTest,
|
||||||
|
|
||||||
using StorageTextureAccessTest = ResolverTest;
|
using StorageTextureAccessTest = ResolverTest;
|
||||||
|
|
||||||
TEST_F(StorageTextureAccessTest, MissingAccess_Fail) {
|
TEST_F(StorageTextureAccessTest, MissingTemplates) {
|
||||||
// @group(0) @binding(0)
|
// @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,
|
auto* st = ty(Source{{12, 34}}, "texture_storage_1d");
|
||||||
type::TexelFormat::kR32Uint, type::Access::kUndefined);
|
|
||||||
|
|
||||||
GlobalVar("a", st, Group(0_a), Binding(0_a));
|
GlobalVar("a", st, Group(0_a), Binding(0_a));
|
||||||
|
|
||||||
EXPECT_FALSE(r()->Resolve());
|
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) {
|
TEST_F(StorageTextureAccessTest, RWAccess_Fail) {
|
||||||
// @group(0) @binding(0)
|
// @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,
|
auto* st = ty.storage_texture(Source{{12, 34}}, type::TextureDimension::k1d,
|
||||||
type::TexelFormat::kR32Uint, type::Access::kReadWrite);
|
type::TexelFormat::kR32Uint, type::Access::kReadWrite);
|
||||||
|
@ -1194,7 +1204,7 @@ TEST_F(StorageTextureAccessTest, RWAccess_Fail) {
|
||||||
|
|
||||||
TEST_F(StorageTextureAccessTest, ReadOnlyAccess_Fail) {
|
TEST_F(StorageTextureAccessTest, ReadOnlyAccess_Fail) {
|
||||||
// @group(0) @binding(0)
|
// @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,
|
auto* st = ty.storage_texture(Source{{12, 34}}, type::TextureDimension::k1d,
|
||||||
type::TexelFormat::kR32Uint, type::Access::kRead);
|
type::TexelFormat::kR32Uint, type::Access::kRead);
|
||||||
|
@ -1208,7 +1218,7 @@ TEST_F(StorageTextureAccessTest, ReadOnlyAccess_Fail) {
|
||||||
|
|
||||||
TEST_F(StorageTextureAccessTest, WriteOnlyAccess_Pass) {
|
TEST_F(StorageTextureAccessTest, WriteOnlyAccess_Pass) {
|
||||||
// @group(0) @binding(0)
|
// @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,
|
auto* st = ty.storage_texture(type::TextureDimension::k1d, type::TexelFormat::kR32Uint,
|
||||||
type::Access::kWrite);
|
type::Access::kWrite);
|
||||||
|
@ -1445,5 +1455,91 @@ INSTANTIATE_TEST_SUITE_P(ResolverTypeValidationTest,
|
||||||
|
|
||||||
} // namespace BuiltinTypeAliasTests
|
} // 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
|
||||||
} // namespace tint::resolver
|
} // namespace tint::resolver
|
||||||
|
|
|
@ -37,7 +37,6 @@
|
||||||
#include "src/tint/ast/pointer.h"
|
#include "src/tint/ast/pointer.h"
|
||||||
#include "src/tint/ast/return_statement.h"
|
#include "src/tint/ast/return_statement.h"
|
||||||
#include "src/tint/ast/sampled_texture.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/switch_statement.h"
|
||||||
#include "src/tint/ast/traverse_expressions.h"
|
#include "src/tint/ast/traverse_expressions.h"
|
||||||
#include "src/tint/ast/type_name.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);
|
a->source);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Validator::StorageTexture(const ast::StorageTexture* t) const {
|
bool Validator::StorageTexture(const type::StorageTexture* t, const Source& source) const {
|
||||||
switch (t->access) {
|
switch (t->access()) {
|
||||||
case type::Access::kWrite:
|
case type::Access::kWrite:
|
||||||
break;
|
break;
|
||||||
case type::Access::kUndefined:
|
case type::Access::kUndefined:
|
||||||
AddError("storage texture missing access control", t->source);
|
AddError("storage texture missing access control", source);
|
||||||
return false;
|
return false;
|
||||||
default:
|
default:
|
||||||
AddError("storage textures currently only support 'write' access control", t->source);
|
AddError("storage textures currently only support 'write' access control", source);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsValidStorageTextureDimension(t->dim)) {
|
if (!IsValidStorageTextureDimension(t->dim())) {
|
||||||
AddError("cube dimensions for storage textures are not supported", t->source);
|
AddError("cube dimensions for storage textures are not supported", source);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!IsValidStorageTextureTexelFormat(t->format)) {
|
if (!IsValidStorageTextureTexelFormat(t->texel_format())) {
|
||||||
AddError(
|
AddError(
|
||||||
"image format must be one of the texel formats specified for storage "
|
"image format must be one of the texel formats specified for storage "
|
||||||
"textues in https://gpuweb.github.io/gpuweb/wgsl/#texel-formats",
|
"textues in https://gpuweb.github.io/gpuweb/wgsl/#texel-formats",
|
||||||
t->source);
|
source);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -372,8 +372,9 @@ class Validator {
|
||||||
|
|
||||||
/// Validates a storage texture
|
/// Validates a storage texture
|
||||||
/// @param t the texture to validate
|
/// @param t the texture to validate
|
||||||
|
/// @param source the source of the texture
|
||||||
/// @returns true on success, false otherwise
|
/// @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
|
/// Validates a sampled texture
|
||||||
/// @param t the texture to validate
|
/// @param t the texture to validate
|
||||||
|
|
|
@ -22,6 +22,8 @@
|
||||||
#include "src/tint/program_builder.h"
|
#include "src/tint/program_builder.h"
|
||||||
#include "src/tint/sem/builtin.h"
|
#include "src/tint/sem/builtin.h"
|
||||||
#include "src/tint/sem/call.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/type/texture_dimension.h"
|
||||||
#include "src/tint/utils/map.h"
|
#include "src/tint/utils/map.h"
|
||||||
|
|
||||||
|
@ -1065,13 +1067,17 @@ Transform::ApplyResult BuiltinPolyfill::Apply(const Program* src,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[&](const ast::StorageTexture* tex) {
|
[&](const ast::TypeName* type_name) {
|
||||||
if (polyfill.bgra8unorm && tex->format == type::TexelFormat::kBgra8Unorm) {
|
if (polyfill.bgra8unorm) {
|
||||||
ctx.Replace(tex, [&ctx, tex] {
|
if (auto* tex = src->Sem().Get<type::StorageTexture>(type_name)) {
|
||||||
return ctx.dst->ty.storage_texture(tex->dim, type::TexelFormat::kRgba8Unorm,
|
if (tex->texel_format() == type::TexelFormat::kBgra8Unorm) {
|
||||||
tex->access);
|
ctx.Replace(type_name, [&ctx, tex] {
|
||||||
});
|
return ctx.dst->ty.storage_texture(
|
||||||
made_changes = true;
|
tex->dim(), type::TexelFormat::kRgba8Unorm, tex->access());
|
||||||
|
});
|
||||||
|
made_changes = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -83,7 +83,8 @@ struct Texture1DTo2D::State {
|
||||||
return SkipTransform;
|
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>()) {
|
if (v->As<ast::Parameter>()) {
|
||||||
return ctx.dst->Param(ctx.Clone(v->name->symbol), type, ctx.Clone(v->attributes));
|
return ctx.dst->Param(ctx.Clone(v->name->symbol), type, ctx.Clone(v->attributes));
|
||||||
} else {
|
} else {
|
||||||
|
@ -105,9 +106,9 @@ struct Texture1DTo2D::State {
|
||||||
},
|
},
|
||||||
[&](const type::StorageTexture* storage_tex) -> const ast::Variable* {
|
[&](const type::StorageTexture* storage_tex) -> const ast::Variable* {
|
||||||
if (storage_tex->dim() == type::TextureDimension::k1d) {
|
if (storage_tex->dim() == type::TextureDimension::k1d) {
|
||||||
auto* type = ctx.dst->create<ast::StorageTexture>(
|
auto* type = ctx.dst->ty.storage_texture(type::TextureDimension::k2d,
|
||||||
type::TextureDimension::k2d, storage_tex->texel_format(),
|
storage_tex->texel_format(),
|
||||||
CreateASTTypeFor(ctx, storage_tex->type()), storage_tex->access());
|
storage_tex->access());
|
||||||
return create_var(v, type);
|
return create_var(v, type);
|
||||||
} else {
|
} else {
|
||||||
return nullptr;
|
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()));
|
return ctx.dst->create<ast::SampledTexture>(t->dim(), CreateASTTypeFor(ctx, t->type()));
|
||||||
}
|
}
|
||||||
if (auto* t = ty->As<type::StorageTexture>()) {
|
if (auto* t = ty->As<type::StorageTexture>()) {
|
||||||
return ctx.dst->create<ast::StorageTexture>(t->dim(), t->texel_format(),
|
return ctx.dst->ty.storage_texture(t->dim(), t->texel_format(), t->access());
|
||||||
CreateASTTypeFor(ctx, t->type()), t->access());
|
|
||||||
}
|
}
|
||||||
if (auto* s = ty->As<type::Sampler>()) {
|
if (auto* s = ty->As<type::Sampler>()) {
|
||||||
return ctx.dst->ty.sampler(s->kind());
|
return ctx.dst->ty.sampler(s->kind());
|
||||||
|
|
|
@ -118,6 +118,18 @@ Builtin ParseBuiltin(std::string_view str) {
|
||||||
if (str == "texture_external") {
|
if (str == "texture_external") {
|
||||||
return Builtin::kTextureExternal;
|
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") {
|
if (str == "u32") {
|
||||||
return Builtin::kU32;
|
return Builtin::kU32;
|
||||||
}
|
}
|
||||||
|
@ -224,6 +236,14 @@ std::ostream& operator<<(std::ostream& out, Builtin value) {
|
||||||
return out << "texture_depth_multisampled_2d";
|
return out << "texture_depth_multisampled_2d";
|
||||||
case Builtin::kTextureExternal:
|
case Builtin::kTextureExternal:
|
||||||
return out << "texture_external";
|
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:
|
case Builtin::kU32:
|
||||||
return out << "u32";
|
return out << "u32";
|
||||||
case Builtin::kVec2F:
|
case Builtin::kVec2F:
|
||||||
|
|
|
@ -60,6 +60,10 @@ enum class Builtin {
|
||||||
kTextureDepthCubeArray,
|
kTextureDepthCubeArray,
|
||||||
kTextureDepthMultisampled2D,
|
kTextureDepthMultisampled2D,
|
||||||
kTextureExternal,
|
kTextureExternal,
|
||||||
|
kTextureStorage1D,
|
||||||
|
kTextureStorage2D,
|
||||||
|
kTextureStorage2DArray,
|
||||||
|
kTextureStorage3D,
|
||||||
kU32,
|
kU32,
|
||||||
kVec2F,
|
kVec2F,
|
||||||
kVec2H,
|
kVec2H,
|
||||||
|
@ -116,6 +120,10 @@ constexpr const char* kBuiltinStrings[] = {
|
||||||
"texture_depth_cube_array",
|
"texture_depth_cube_array",
|
||||||
"texture_depth_multisampled_2d",
|
"texture_depth_multisampled_2d",
|
||||||
"texture_external",
|
"texture_external",
|
||||||
|
"texture_storage_1d",
|
||||||
|
"texture_storage_2d",
|
||||||
|
"texture_storage_2d_array",
|
||||||
|
"texture_storage_3d",
|
||||||
"u32",
|
"u32",
|
||||||
"vec2f",
|
"vec2f",
|
||||||
"vec2h",
|
"vec2h",
|
||||||
|
|
|
@ -241,97 +241,125 @@ void BuiltinParser(::benchmark::State& state) {
|
||||||
"textuXe_ZZxtJJrnal",
|
"textuXe_ZZxtJJrnal",
|
||||||
"textuPPe_eternal",
|
"textuPPe_eternal",
|
||||||
"texturc_external",
|
"texturc_external",
|
||||||
"ull62",
|
"tllxture_storage_P6d",
|
||||||
"93yy",
|
"tex99ure_yytorag_1d",
|
||||||
"u3KK",
|
"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",
|
"u32",
|
||||||
"x_",
|
"3Xl",
|
||||||
"K",
|
"pp3o",
|
||||||
"kVz",
|
"uww",
|
||||||
"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",
|
|
||||||
"veuug",
|
"veuug",
|
||||||
"vaac",
|
"vaac",
|
||||||
"TRZcccf",
|
"TRZcccf",
|
||||||
"vec3f",
|
"vec2f",
|
||||||
"vTc3O8",
|
"vTc2O8",
|
||||||
"vem03f",
|
"vem02f",
|
||||||
"meBB3f",
|
"meBB2f",
|
||||||
"Mpp3",
|
"Mpp2",
|
||||||
"OOe3h",
|
"OOe2h",
|
||||||
"veG3G",
|
"veG2G",
|
||||||
"vec3h",
|
"vec2h",
|
||||||
"11eHH3h",
|
"11eHH2h",
|
||||||
"veFFe6",
|
"veFFe6",
|
||||||
"ve3",
|
"ve2",
|
||||||
"vKii3l",
|
"vKii2l",
|
||||||
"ec3i",
|
"ec2i",
|
||||||
"v993IIv",
|
"v992IIv",
|
||||||
"vec3i",
|
"vec2i",
|
||||||
"veci",
|
"veci",
|
||||||
"vechi",
|
"vechi",
|
||||||
"vczllPi",
|
"vczllPi",
|
||||||
"u",
|
"u",
|
||||||
"vffqq3",
|
"vffqq2",
|
||||||
"vJdd3u",
|
"vJdd2u",
|
||||||
"vec3u",
|
"vec2u",
|
||||||
"vecXX",
|
"vecXX",
|
||||||
"ve32",
|
"ve22",
|
||||||
"Nyyc3u",
|
"Nyyc2u",
|
||||||
"vO4",
|
"vO3",
|
||||||
"PEruZ",
|
"PEruZ",
|
||||||
"vlc2edd",
|
"vlc2edd",
|
||||||
"vec4f",
|
"vec3f",
|
||||||
"ec9f",
|
"ec9f",
|
||||||
"ve1II",
|
"ve1II",
|
||||||
"veb4f",
|
"veb3f",
|
||||||
"vi7",
|
"vi7",
|
||||||
"oec4ii",
|
"oec3ii",
|
||||||
"ec4",
|
"ec3",
|
||||||
"vec4h",
|
"vec3h",
|
||||||
"veci",
|
"veci",
|
||||||
"22ec",
|
"22ec",
|
||||||
"vGc4C",
|
"vGc3C",
|
||||||
"ffec48",
|
"ffec38",
|
||||||
"c4i",
|
"c3i",
|
||||||
"JJecSSi",
|
"JJecSSi",
|
||||||
"vec4i",
|
"vec3i",
|
||||||
"94i",
|
"93i",
|
||||||
"vbbJJ4TT",
|
"vbbJJ3TT",
|
||||||
"e66i",
|
"e66i",
|
||||||
"u664u",
|
"u663u",
|
||||||
"vW4u",
|
"vW3u",
|
||||||
"v4u",
|
"v3u",
|
||||||
"vec4u",
|
"vec3u",
|
||||||
"vecu",
|
"vecu",
|
||||||
"rec4u",
|
"rec3u",
|
||||||
"2ec4B",
|
"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 _ : state) {
|
||||||
for (auto* str : kStrings) {
|
for (auto* str : kStrings) {
|
||||||
|
|
|
@ -73,6 +73,10 @@ static constexpr Case kValidCases[] = {
|
||||||
{"texture_depth_cube_array", Builtin::kTextureDepthCubeArray},
|
{"texture_depth_cube_array", Builtin::kTextureDepthCubeArray},
|
||||||
{"texture_depth_multisampled_2d", Builtin::kTextureDepthMultisampled2D},
|
{"texture_depth_multisampled_2d", Builtin::kTextureDepthMultisampled2D},
|
||||||
{"texture_external", Builtin::kTextureExternal},
|
{"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},
|
{"u32", Builtin::kU32},
|
||||||
{"vec2f", Builtin::kVec2F},
|
{"vec2f", Builtin::kVec2F},
|
||||||
{"vec2h", Builtin::kVec2H},
|
{"vec2h", Builtin::kVec2H},
|
||||||
|
@ -179,45 +183,57 @@ static constexpr Case kInvalidCases[] = {
|
||||||
{"texture_exernss77", Builtin::kUndefined},
|
{"texture_exernss77", Builtin::kUndefined},
|
||||||
{"texture_bbxternRRl", Builtin::kUndefined},
|
{"texture_bbxternRRl", Builtin::kUndefined},
|
||||||
{"textureXXexternal", Builtin::kUndefined},
|
{"textureXXexternal", Builtin::kUndefined},
|
||||||
{"qOOO2", Builtin::kUndefined},
|
{"CCextOOre_stoage_qOd", Builtin::kUndefined},
|
||||||
{"us", Builtin::kUndefined},
|
{"txtsre_sturage_1L", Builtin::kUndefined},
|
||||||
{"u3X", Builtin::kUndefined},
|
{"texture_stoXage_1d", Builtin::kUndefined},
|
||||||
{"ve2f", Builtin::kUndefined},
|
{"textue_storage_2d", Builtin::kUndefined},
|
||||||
{"qq2", Builtin::kUndefined},
|
{"teuresOorageqq2d", Builtin::kUndefined},
|
||||||
{"vec222", Builtin::kUndefined},
|
{"texture_sto22age_2d", Builtin::kUndefined},
|
||||||
{"vezzXy", Builtin::kUndefined},
|
{"exture_syora0e_2d_Xzzrray", Builtin::kUndefined},
|
||||||
{"ieVVP", Builtin::kUndefined},
|
{"texiVVr_storageP2d_array", Builtin::kUndefined},
|
||||||
{"venCh", Builtin::kUndefined},
|
{"texturestorage_2nn_arCay", Builtin::kUndefined},
|
||||||
{"vHc2Aq", Builtin::kUndefined},
|
{"texturHHstorAAe_qqd", Builtin::kUndefined},
|
||||||
{"ve2i", Builtin::kUndefined},
|
{"textur_storage_3d", Builtin::kUndefined},
|
||||||
{"vefK", Builtin::kUndefined},
|
{"texure_sfKorage3d", Builtin::kUndefined},
|
||||||
{"vgg2", Builtin::kUndefined},
|
{"gg", Builtin::kUndefined},
|
||||||
{"vecu", Builtin::kUndefined},
|
{"u3", Builtin::kUndefined},
|
||||||
{"4TNc2u", Builtin::kUndefined},
|
{"NT42", Builtin::kUndefined},
|
||||||
{"ppec7l", Builtin::kUndefined},
|
{"ppec7l", Builtin::kUndefined},
|
||||||
{"zNe3f", Builtin::kUndefined},
|
{"zNe2f", Builtin::kUndefined},
|
||||||
{"uXXb3f", Builtin::kUndefined},
|
{"uXXb2f", Builtin::kUndefined},
|
||||||
{"vec3", Builtin::kUndefined},
|
{"vec2", Builtin::kUndefined},
|
||||||
{"883K", Builtin::kUndefined},
|
{"882K", Builtin::kUndefined},
|
||||||
{"vq9h", Builtin::kUndefined},
|
{"vq9h", Builtin::kUndefined},
|
||||||
{"vec311", Builtin::kUndefined},
|
{"vec211", Builtin::kUndefined},
|
||||||
{"22ciii", Builtin::kUndefined},
|
{"22ciii", Builtin::kUndefined},
|
||||||
{"ec77i", Builtin::kUndefined},
|
{"ec77i", Builtin::kUndefined},
|
||||||
{"NN23u", Builtin::kUndefined},
|
{"NN22u", Builtin::kUndefined},
|
||||||
{"vVVc3u", Builtin::kUndefined},
|
{"vVVc2u", Builtin::kUndefined},
|
||||||
{"WW11w3u", Builtin::kUndefined},
|
{"WW11w2u", Builtin::kUndefined},
|
||||||
{"vcwwf", Builtin::kUndefined},
|
{"vcwwf", Builtin::kUndefined},
|
||||||
{"vDc4f", Builtin::kUndefined},
|
{"vDc3f", Builtin::kUndefined},
|
||||||
{"vecK", Builtin::kUndefined},
|
{"vecK", Builtin::kUndefined},
|
||||||
{"f11r4PP", Builtin::kUndefined},
|
{"f11r3PP", Builtin::kUndefined},
|
||||||
{"ve4h", Builtin::kUndefined},
|
{"ve3h", Builtin::kUndefined},
|
||||||
{"vec4YY", Builtin::kUndefined},
|
{"vec3YY", Builtin::kUndefined},
|
||||||
{"vkktHH", Builtin::kUndefined},
|
{"vkktHH", Builtin::kUndefined},
|
||||||
{"rrec4i", Builtin::kUndefined},
|
{"rrec3i", Builtin::kUndefined},
|
||||||
{"vWWssi", Builtin::kUndefined},
|
{"vWWssi", Builtin::kUndefined},
|
||||||
{"veYu", Builtin::kUndefined},
|
{"veYu", Builtin::kUndefined},
|
||||||
{"eq4f", Builtin::kUndefined},
|
{"eq3f", Builtin::kUndefined},
|
||||||
{"u22ec4u", 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>;
|
using BuiltinParseTest = testing::TestWithParam<Case>;
|
||||||
|
|
|
@ -32,7 +32,6 @@
|
||||||
#include "src/tint/ast/pointer.h"
|
#include "src/tint/ast/pointer.h"
|
||||||
#include "src/tint/ast/sampled_texture.h"
|
#include "src/tint/ast/sampled_texture.h"
|
||||||
#include "src/tint/ast/stage_attribute.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/stride_attribute.h"
|
||||||
#include "src/tint/ast/struct_member_align_attribute.h"
|
#include "src/tint/ast/struct_member_align_attribute.h"
|
||||||
#include "src/tint/ast/struct_member_offset_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) {
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -462,10 +477,6 @@ bool GeneratorImpl::EmitType(std::ostream& out, const ast::Type* ty) {
|
||||||
out << "multisampled_";
|
out << "multisampled_";
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
[&](const ast::StorageTexture*) { //
|
|
||||||
out << "storage_";
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
[&](Default) { //
|
[&](Default) { //
|
||||||
diagnostics_.add_error(diag::System::Writer, "unknown texture type");
|
diagnostics_.add_error(diag::System::Writer, "unknown texture type");
|
||||||
return false;
|
return false;
|
||||||
|
@ -516,18 +527,6 @@ bool GeneratorImpl::EmitType(std::ostream& out, const ast::Type* ty) {
|
||||||
out << ">";
|
out << ">";
|
||||||
return true;
|
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) { //
|
[&](Default) { //
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
|
@ -543,10 +542,7 @@ bool GeneratorImpl::EmitType(std::ostream& out, const ast::Type* ty) {
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
},
|
},
|
||||||
[&](const ast::TypeName* tn) {
|
[&](const ast::TypeName* tn) { return EmitIdentifier(out, tn->name); },
|
||||||
out << program_->Symbols().NameFor(tn->name->symbol);
|
|
||||||
return true;
|
|
||||||
},
|
|
||||||
[&](Default) {
|
[&](Default) {
|
||||||
diagnostics_.add_error(diag::System::Writer,
|
diagnostics_.add_error(diag::System::Writer,
|
||||||
"unknown type in EmitType: " + std::string(ty->TypeInfo().name));
|
"unknown type in EmitType: " + std::string(ty->TypeInfo().name));
|
||||||
|
|
|
@ -142,6 +142,11 @@ class GeneratorImpl : public TextGenerator {
|
||||||
/// @param expr the identifier expression
|
/// @param expr the identifier expression
|
||||||
/// @returns true if the identifier was emitted
|
/// @returns true if the identifier was emitted
|
||||||
bool EmitIdentifier(std::ostream& out, const ast::IdentifierExpression* expr);
|
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
|
/// Handles an if statement
|
||||||
/// @param stmt the statement to emit
|
/// @param stmt the statement to emit
|
||||||
/// @returns true if the statement was successfully emitted
|
/// @returns true if the statement was successfully emitted
|
||||||
|
|
Loading…
Reference in New Issue