[wgsl-reader] Allow array decorations to have multiple blocks.

This CL updates the WGSL parser to allow array decorations to accept
multiple blocks. The stride decoration on arrays was turned into a
proper decoration object instead of just storing the stride directly.

Bug: tint:240
Change-Id: I6cdc7400d8847e3e043b846ea5c9f86cb795cf86
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/29780
Commit-Queue: dan sinclair <dsinclair@chromium.org>
Reviewed-by: Sarah Mashayekhi <sarahmashay@google.com>
Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
dan sinclair 2020-10-08 19:34:25 +00:00 committed by Commit Bot service account
parent 71d69e5ed3
commit eb5d3e147d
20 changed files with 431 additions and 65 deletions

View File

@ -219,6 +219,8 @@ source_set("libtint_core_src") {
sources = [
"src/ast/array_accessor_expression.cc",
"src/ast/array_accessor_expression.h",
"src/ast/array_decoration.cc",
"src/ast/array_decoration.h",
"src/ast/assignment_statement.cc",
"src/ast/assignment_statement.h",
"src/ast/binary_expression.cc",
@ -303,6 +305,8 @@ source_set("libtint_core_src") {
"src/ast/statement.h",
"src/ast/storage_class.cc",
"src/ast/storage_class.h",
"src/ast/stride_decoration.cc",
"src/ast/stride_decoration.h",
"src/ast/struct.cc",
"src/ast/struct.h",
"src/ast/struct_decoration.cc",
@ -727,6 +731,7 @@ source_set("tint_unittests_core_src") {
"src/ast/set_decoration_test.cc",
"src/ast/sint_literal_test.cc",
"src/ast/stage_decoration_test.cc",
"src/ast/stride_decoration_test.cc",
"src/ast/struct_member_offset_decoration_test.cc",
"src/ast/struct_member_test.cc",
"src/ast/struct_test.cc",

View File

@ -40,6 +40,8 @@ set(TINT_LIB_SRCS
../include/tint/tint.h
ast/array_accessor_expression.cc
ast/array_accessor_expression.h
ast/array_decoration.cc
ast/array_decoration.h
ast/assignment_statement.cc
ast/assignment_statement.h
ast/binary_expression.cc
@ -124,10 +126,12 @@ set(TINT_LIB_SRCS
ast/statement.h
ast/storage_class.cc
ast/storage_class.h
ast/struct_decoration.cc
ast/struct_decoration.h
ast/stride_decoration.cc
ast/stride_decoration.h
ast/struct.cc
ast/struct.h
ast/struct_decoration.cc
ast/struct_decoration.h
ast/struct_member.cc
ast/struct_member.h
ast/struct_member_decoration.cc
@ -337,6 +341,7 @@ set(TINT_TEST_SRCS
ast/set_decoration_test.cc
ast/sint_literal_test.cc
ast/stage_decoration_test.cc
ast/stride_decoration_test.cc
ast/struct_member_test.cc
ast/struct_member_offset_decoration_test.cc
ast/struct_test.cc

View File

@ -0,0 +1,38 @@
// Copyright 2020 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "src/ast/array_decoration.h"
#include <assert.h>
#include "src/ast/stride_decoration.h"
namespace tint {
namespace ast {
ArrayDecoration::ArrayDecoration() = default;
ArrayDecoration::~ArrayDecoration() = default;
bool ArrayDecoration::IsStride() const {
return false;
}
StrideDecoration* ArrayDecoration::AsStride() {
assert(IsStride());
return static_cast<StrideDecoration*>(this);
}
} // namespace ast
} // namespace tint

View File

@ -0,0 +1,51 @@
// Copyright 2020 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef SRC_AST_ARRAY_DECORATION_H_
#define SRC_AST_ARRAY_DECORATION_H_
#include <memory>
#include <string>
#include <vector>
namespace tint {
namespace ast {
class StrideDecoration;
/// A decoration attached to an array
class ArrayDecoration {
public:
virtual ~ArrayDecoration();
/// @returns true if this is a stride decoration
virtual bool IsStride() const;
/// @returns the decoration as a stride decoration
StrideDecoration* AsStride();
/// @returns the decoration as a string
virtual std::string to_str() const = 0;
protected:
ArrayDecoration();
};
/// A list of unique array decorations
using ArrayDecorationList = std::vector<std::unique_ptr<ArrayDecoration>>;
} // namespace ast
} // namespace tint
#endif // SRC_AST_ARRAY_DECORATION_H_

View File

@ -0,0 +1,33 @@
// Copyright 2020 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "src/ast/stride_decoration.h"
namespace tint {
namespace ast {
StrideDecoration::StrideDecoration(uint32_t stride) : stride_(stride) {}
bool StrideDecoration::IsStride() const {
return true;
}
StrideDecoration::~StrideDecoration() = default;
std::string StrideDecoration::to_str() const {
return "stride " + std::to_string(stride_);
}
} // namespace ast
} // namespace tint

View File

@ -0,0 +1,51 @@
// Copyright 2020 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef SRC_AST_STRIDE_DECORATION_H_
#define SRC_AST_STRIDE_DECORATION_H_
#include <stddef.h>
#include <string>
#include "src/ast/array_decoration.h"
namespace tint {
namespace ast {
/// A stride decoration
class StrideDecoration : public ArrayDecoration {
public:
/// constructor
/// @param stride the stride value
explicit StrideDecoration(uint32_t stride);
~StrideDecoration() override;
/// @returns true if this is a stride decoration
bool IsStride() const override;
/// @returns the stride value
uint32_t stride() const { return stride_; }
/// @returns the decoration as a string
std::string to_str() const override;
private:
uint32_t stride_;
};
} // namespace ast
} // namespace tint
#endif // SRC_AST_STRIDE_DECORATION_H_

View File

@ -0,0 +1,37 @@
// Copyright 2020 The Tint Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#include "src/ast/stride_decoration.h"
#include "gtest/gtest.h"
namespace tint {
namespace ast {
namespace {
using StrideDecorationTest = testing::Test;
TEST_F(StrideDecorationTest, Creation) {
StrideDecoration d{2};
EXPECT_EQ(2u, d.stride());
}
TEST_F(StrideDecorationTest, Is) {
StrideDecoration d{2};
EXPECT_TRUE(d.IsStride());
}
} // namespace
} // namespace ast
} // namespace tint

View File

@ -16,6 +16,7 @@
#define SRC_AST_STRUCT_DECORATION_H_
#include <ostream>
#include <vector>
namespace tint {
namespace ast {

View File

@ -14,6 +14,8 @@
#include "src/ast/type/array_type.h"
#include "src/ast/stride_decoration.h"
namespace tint {
namespace ast {
namespace type {
@ -31,6 +33,24 @@ bool ArrayType::IsArray() const {
return true;
}
uint32_t ArrayType::array_stride() const {
for (const auto& deco : decos_) {
if (deco->IsStride()) {
return deco->AsStride()->stride();
}
}
return 0;
}
bool ArrayType::has_array_stride() const {
for (const auto& deco : decos_) {
if (deco->IsStride()) {
return true;
}
}
return false;
}
std::string ArrayType::type_name() const {
assert(subtype_);
@ -38,7 +58,7 @@ std::string ArrayType::type_name() const {
if (!IsRuntimeArray())
type_name += "_" + std::to_string(size_);
if (has_array_stride())
type_name += "_stride_" + std::to_string(array_stride_);
type_name += "_stride_" + std::to_string(array_stride());
return type_name;
}

View File

@ -19,6 +19,7 @@
#include <string>
#include "src/ast/array_decoration.h"
#include "src/ast/type/type.h"
namespace tint {
@ -45,13 +46,18 @@ class ArrayType : public Type {
/// i.e. the size is determined at runtime
bool IsRuntimeArray() const { return size_ == 0; }
/// Sets the array stride
/// @param stride the stride to set
void set_array_stride(uint32_t stride) { array_stride_ = stride; }
/// Sets the array decorations
/// @param decos the decorations to set
void set_decorations(ast::ArrayDecorationList decos) {
decos_ = std::move(decos);
}
/// @returns the array decorations
const ArrayDecorationList& decorations() const { return decos_; }
/// @returns the array stride or 0 if none set.
uint32_t array_stride() const { return array_stride_; }
uint32_t array_stride() const;
/// @returns true if the array has a stride set
bool has_array_stride() const { return array_stride_ != 0; }
bool has_array_stride() const;
/// @returns the array type
Type* type() const { return subtype_; }
@ -64,7 +70,7 @@ class ArrayType : public Type {
private:
Type* subtype_ = nullptr;
uint32_t size_ = 0;
uint32_t array_stride_ = 0;
ast::ArrayDecorationList decos_;
};
} // namespace type

View File

@ -15,6 +15,7 @@
#include "src/ast/type/array_type.h"
#include "gtest/gtest.h"
#include "src/ast/stride_decoration.h"
#include "src/ast/type/i32_type.h"
#include "src/ast/type/u32_type.h"
@ -75,8 +76,11 @@ TEST_F(ArrayTypeTest, TypeName_RuntimeArray) {
TEST_F(ArrayTypeTest, TypeName_WithStride) {
I32Type i32;
ArrayDecorationList decos;
decos.push_back(std::make_unique<StrideDecoration>(16));
ArrayType arr{&i32, 3};
arr.set_array_stride(16);
arr.set_decorations(std::move(decos));
EXPECT_EQ(arr.type_name(), "__array__i32_3_stride_16");
}

View File

@ -45,6 +45,7 @@
#include "src/ast/scalar_constructor_expression.h"
#include "src/ast/set_decoration.h"
#include "src/ast/sint_literal.h"
#include "src/ast/stride_decoration.h"
#include "src/ast/struct.h"
#include "src/ast/struct_decoration.h"
#include "src/ast/struct_member.h"
@ -772,7 +773,9 @@ bool ParserImpl::ApplyArrayDecorations(
return Fail() << "invalid array type ID " << type_id
<< ": multiple ArrayStride decorations";
}
ast_type->set_array_stride(stride);
ast::ArrayDecorationList decos;
decos.push_back(std::make_unique<ast::StrideDecoration>(stride));
ast_type->set_decorations(std::move(decos));
} else {
return Fail() << "invalid array type ID " << type_id
<< ": unknown decoration "

View File

@ -41,6 +41,7 @@
#include "src/ast/set_decoration.h"
#include "src/ast/sint_literal.h"
#include "src/ast/stage_decoration.h"
#include "src/ast/stride_decoration.h"
#include "src/ast/struct_member_offset_decoration.h"
#include "src/ast/switch_statement.h"
#include "src/ast/type/alias_type.h"
@ -1105,9 +1106,9 @@ ast::type::AliasType* ParserImpl::type_alias() {
// | VEC3 LESS_THAN type_decl GREATER_THAN
// | VEC4 LESS_THAN type_decl GREATER_THAN
// | PTR LESS_THAN storage_class, type_decl GREATER_THAN
// | array_decoration_list? ARRAY LESS_THAN type_decl COMMA
// | array_decoration_list* ARRAY LESS_THAN type_decl COMMA
// INT_LITERAL GREATER_THAN
// | array_decoration_list? ARRAY LESS_THAN type_decl
// | array_decoration_list* ARRAY LESS_THAN type_decl
// GREATER_THAN
// | MAT2x2 LESS_THAN type_decl GREATER_THAN
// | MAT2x3 LESS_THAN type_decl GREATER_THAN
@ -1153,19 +1154,28 @@ ast::type::Type* ParserImpl::type_decl() {
return type_decl_pointer(t);
}
auto deco = array_decoration_list();
ast::ArrayDecorationList decos;
for (;;) {
size_t s = decos.size();
if (!array_decoration_list(decos)) {
return nullptr;
}
if (decos.size() == s) {
break;
}
}
if (has_error()) {
return nullptr;
}
if (deco != 0) {
if (!decos.empty()) {
t = peek();
}
if (deco != 0 && !t.IsArray()) {
if (!decos.empty() && !t.IsArray()) {
set_error(t, "found array decoration but no array");
return nullptr;
}
if (t.IsArray()) {
return type_decl_array(t, deco);
return type_decl_array(t, std::move(decos));
}
if (t.IsMat2x2() || t.IsMat2x3() || t.IsMat2x4() || t.IsMat3x2() ||
t.IsMat3x3() || t.IsMat3x4() || t.IsMat4x2() || t.IsMat4x3() ||
@ -1258,7 +1268,8 @@ ast::type::Type* ParserImpl::type_decl_vector(Token t) {
std::make_unique<ast::type::VectorType>(subtype, count));
}
ast::type::Type* ParserImpl::type_decl_array(Token t, uint32_t stride) {
ast::type::Type* ParserImpl::type_decl_array(Token t,
ast::ArrayDecorationList decos) {
next(); // Consume the peek
t = next();
@ -1296,9 +1307,7 @@ ast::type::Type* ParserImpl::type_decl_array(Token t, uint32_t stride) {
}
auto ty = std::make_unique<ast::type::ArrayType>(subtype, size);
if (stride != 0) {
ty->set_array_stride(stride);
}
ty->set_decorations(std::move(decos));
return ctx_.type_mgr().Get(std::move(ty));
}
@ -1309,48 +1318,62 @@ ast::type::Type* ParserImpl::type_decl_array(Token t, uint32_t stride) {
//
// As there is currently only one decoration I'm combining these for now.
// we can split apart later if needed.
uint32_t ParserImpl::array_decoration_list() {
bool ParserImpl::array_decoration_list(ast::ArrayDecorationList& decos) {
auto t = peek();
if (!t.IsAttrLeft()) {
return 0;
return true;
}
t = peek(1);
if (!t.IsStride()) {
return 0;
return true;
}
next(); // consume the peek of [[
next(); // consume the peek of stride
t = next();
if (!t.IsParenLeft()) {
set_error(t, "missing ( for stride attribute");
return 0;
}
for (;;) {
t = next();
if (!t.IsStride()) {
set_error(t, "unknown array decoration");
return false;
}
t = next();
if (!t.IsSintLiteral()) {
set_error(t, "missing value for stride decoration");
return 0;
}
if (t.to_i32() < 0) {
set_error(t, "invalid stride value: " + t.to_str());
return 0;
}
uint32_t stride = static_cast<uint32_t>(t.to_i32());
t = next();
if (!t.IsParenLeft()) {
set_error(t, "missing ( for stride attribute");
return false;
}
t = next();
if (!t.IsParenRight()) {
set_error(t, "missing ) for stride attribute");
return 0;
t = next();
if (!t.IsSintLiteral()) {
set_error(t, "missing value for stride decoration");
return false;
}
if (t.to_i32() < 0) {
set_error(t, "invalid stride value: " + t.to_str());
return false;
}
uint32_t stride = static_cast<uint32_t>(t.to_i32());
decos.push_back(std::make_unique<ast::StrideDecoration>(stride));
t = next();
if (!t.IsParenRight()) {
set_error(t, "missing ) for stride attribute");
return false;
}
t = peek();
if (!t.IsComma()) {
break;
}
next(); // Consume the peek
}
t = next();
if (!t.IsAttrRight()) {
set_error(t, "missing ]] for array decoration");
return 0;
return false;
}
return stride;
return true;
}
ast::type::Type* ParserImpl::type_decl_matrix(Token t) {

View File

@ -21,6 +21,7 @@
#include <unordered_map>
#include <utility>
#include "src/ast/array_decoration.h"
#include "src/ast/assignment_statement.h"
#include "src/ast/builtin.h"
#include "src/ast/call_statement.h"
@ -172,8 +173,8 @@ class ParserImpl {
std::unique_ptr<ast::StructMember> struct_member();
/// Parses a `struct_member_decoration_decl` grammar element, appending newly
/// parsed decorations to the end of |decos|.
/// @params decos the decoration list
/// @returns the list of decorations
/// @param decos the decoration list
/// @returns true if parsing was successful.
bool struct_member_decoration_decl(ast::StructMemberDecorationList& decos);
/// Parses a `struct_member_decoration` grammar element
/// @returns the decoration or nullptr if none found
@ -395,8 +396,8 @@ class ParserImpl {
private:
ast::type::Type* type_decl_pointer(Token t);
ast::type::Type* type_decl_vector(Token t);
ast::type::Type* type_decl_array(Token t, uint32_t stride);
uint32_t array_decoration_list();
ast::type::Type* type_decl_array(Token t, ast::ArrayDecorationList decos);
bool array_decoration_list(ast::ArrayDecorationList& decos);
ast::type::Type* type_decl_matrix(Token t);
std::unique_ptr<ast::ConstructorExpression> const_expr_internal(

View File

@ -13,6 +13,7 @@
// limitations under the License.
#include "gtest/gtest.h"
#include "src/ast/stride_decoration.h"
#include "src/ast/type/alias_type.h"
#include "src/ast/type/array_type.h"
#include "src/ast/type/bool_type.h"
@ -423,6 +424,44 @@ TEST_F(ParserImplTest, TypeDecl_Array_Runtime_Stride) {
EXPECT_EQ(a->array_stride(), 16u);
}
TEST_F(ParserImplTest, TypeDecl_Array_MultipleDecorations_OneBlock) {
auto* p = parser("[[stride(16), stride(32)]] array<f32>");
auto* t = p->type_decl();
ASSERT_NE(t, nullptr) << p->error();
ASSERT_FALSE(p->has_error());
ASSERT_TRUE(t->IsArray());
auto* a = t->AsArray();
ASSERT_TRUE(a->IsRuntimeArray());
ASSERT_TRUE(a->type()->IsF32());
auto& decos = a->decorations();
ASSERT_EQ(decos.size(), 2u);
EXPECT_TRUE(decos[0]->IsStride());
EXPECT_EQ(decos[0]->AsStride()->stride(), 16u);
EXPECT_TRUE(decos[1]->IsStride());
EXPECT_EQ(decos[1]->AsStride()->stride(), 32u);
}
TEST_F(ParserImplTest, TypeDecl_Array_MultipleDecorations_MultipleBlocks) {
auto* p = parser("[[stride(16)]] [[stride(32)]] array<f32>");
auto* t = p->type_decl();
ASSERT_NE(t, nullptr) << p->error();
ASSERT_FALSE(p->has_error());
ASSERT_TRUE(t->IsArray());
auto* a = t->AsArray();
ASSERT_TRUE(a->IsRuntimeArray());
ASSERT_TRUE(a->type()->IsF32());
auto& decos = a->decorations();
ASSERT_EQ(decos.size(), 2u);
EXPECT_TRUE(decos[0]->IsStride());
EXPECT_EQ(decos[0]->AsStride()->stride(), 16u);
EXPECT_TRUE(decos[1]->IsStride());
EXPECT_EQ(decos[1]->AsStride()->stride(), 32u);
}
TEST_F(ParserImplTest, TypeDecl_Array_Decoration_MissingArray) {
auto* p = parser("[[stride(16)]] f32");
auto* t = p->type_decl();

View File

@ -21,6 +21,7 @@
#include "src/ast/decorated_variable.h"
#include "src/ast/member_accessor_expression.h"
#include "src/ast/scalar_constructor_expression.h"
#include "src/ast/stride_decoration.h"
#include "src/ast/struct.h"
#include "src/ast/struct_decoration.h"
#include "src/ast/struct_member.h"
@ -215,7 +216,10 @@ void VertexPullingTransform::AddVertexStorageBuffers() {
// TODO(idanr): Make this readonly https://github.com/gpuweb/gpuweb/issues/935
// The array inside the struct definition
auto internal_array = std::make_unique<ast::type::ArrayType>(GetU32Type());
internal_array->set_array_stride(4u);
ast::ArrayDecorationList ary_decos;
ary_decos.push_back(std::make_unique<ast::StrideDecoration>(4u));
internal_array->set_decorations(std::move(ary_decos));
auto* internal_array_type = ctx_->type_mgr().Get(std::move(internal_array));
// Creating the struct type

View File

@ -24,6 +24,7 @@
#include "src/ast/module.h"
#include "src/ast/scalar_constructor_expression.h"
#include "src/ast/sint_literal.h"
#include "src/ast/stride_decoration.h"
#include "src/ast/struct.h"
#include "src/ast/struct_member.h"
#include "src/ast/struct_member_offset_decoration.h"
@ -525,7 +526,9 @@ TEST_F(HlslGeneratorImplTest_MemberAccessor,
ast::type::F32Type f32;
ast::type::I32Type i32;
ast::type::ArrayType ary(&i32, 5);
ary.set_array_stride(4);
ast::ArrayDecorationList decos;
decos.push_back(std::make_unique<ast::StrideDecoration>(4));
ary.set_decorations(std::move(decos));
ast::StructMemberList members;
ast::StructMemberDecorationList a_deco;
@ -573,7 +576,9 @@ TEST_F(HlslGeneratorImplTest_MemberAccessor,
ast::type::F32Type f32;
ast::type::I32Type i32;
ast::type::ArrayType ary(&i32, 5);
ary.set_array_stride(4);
ast::ArrayDecorationList decos;
decos.push_back(std::make_unique<ast::StrideDecoration>(4));
ary.set_decorations(std::move(decos));
ast::StructMemberList members;
ast::StructMemberDecorationList a_deco;
@ -684,7 +689,9 @@ TEST_F(HlslGeneratorImplTest_MemberAccessor,
ast::type::F32Type f32;
ast::type::I32Type i32;
ast::type::ArrayType ary(&i32, 5);
ary.set_array_stride(4);
ast::ArrayDecorationList decos;
decos.push_back(std::make_unique<ast::StrideDecoration>(4));
ary.set_decorations(std::move(decos));
ast::StructMemberList members;
ast::StructMemberDecorationList a_deco;
@ -937,7 +944,9 @@ TEST_F(HlslGeneratorImplTest_MemberAccessor,
data.set_name("Data");
ast::type::ArrayType ary(&data, 4);
ary.set_array_stride(32);
ast::ArrayDecorationList decos;
decos.push_back(std::make_unique<ast::StrideDecoration>(32));
ary.set_decorations(std::move(decos));
deco.push_back(std::make_unique<ast::StructMemberOffsetDecoration>(0));
members.push_back(
@ -1010,7 +1019,9 @@ TEST_F(HlslGeneratorImplTest_MemberAccessor,
data.set_name("Data");
ast::type::ArrayType ary(&data, 4);
ary.set_array_stride(32);
ast::ArrayDecorationList decos;
decos.push_back(std::make_unique<ast::StrideDecoration>(32));
ary.set_decorations(std::move(decos));
deco.push_back(std::make_unique<ast::StructMemberOffsetDecoration>(0));
members.push_back(
@ -1086,7 +1097,9 @@ TEST_F(
data.set_name("Data");
ast::type::ArrayType ary(&data, 4);
ary.set_array_stride(32);
ast::ArrayDecorationList decos;
decos.push_back(std::make_unique<ast::StrideDecoration>(32));
ary.set_decorations(std::move(decos));
deco.push_back(std::make_unique<ast::StructMemberOffsetDecoration>(0));
members.push_back(
@ -1161,7 +1174,9 @@ TEST_F(HlslGeneratorImplTest_MemberAccessor,
data.set_name("Data");
ast::type::ArrayType ary(&data, 4);
ary.set_array_stride(32);
ast::ArrayDecorationList decos;
decos.push_back(std::make_unique<ast::StrideDecoration>(32));
ary.set_decorations(std::move(decos));
deco.push_back(std::make_unique<ast::StructMemberOffsetDecoration>(0));
members.push_back(
@ -1237,7 +1252,9 @@ TEST_F(HlslGeneratorImplTest_MemberAccessor,
data.set_name("Data");
ast::type::ArrayType ary(&data, 4);
ary.set_array_stride(32);
ast::ArrayDecorationList decos;
decos.push_back(std::make_unique<ast::StrideDecoration>(32));
ary.set_decorations(std::move(decos));
deco.push_back(std::make_unique<ast::StructMemberOffsetDecoration>(0));
members.push_back(
@ -1329,7 +1346,9 @@ TEST_F(HlslGeneratorImplTest_MemberAccessor,
data.set_name("Data");
ast::type::ArrayType ary(&data, 4);
ary.set_array_stride(32);
ast::ArrayDecorationList decos;
decos.push_back(std::make_unique<ast::StrideDecoration>(32));
ary.set_decorations(std::move(decos));
deco.push_back(std::make_unique<ast::StructMemberOffsetDecoration>(0));
members.push_back(

View File

@ -16,6 +16,7 @@
#include "gtest/gtest.h"
#include "src/ast/identifier_expression.h"
#include "src/ast/stride_decoration.h"
#include "src/ast/struct.h"
#include "src/ast/struct_member.h"
#include "src/ast/struct_member_offset_decoration.h"
@ -128,8 +129,12 @@ TEST_F(BuilderTest_Type, GenerateArray) {
TEST_F(BuilderTest_Type, GenerateArray_WithStride) {
ast::type::I32Type i32;
ast::ArrayDecorationList decos;
decos.push_back(std::make_unique<ast::StrideDecoration>(16u));
ast::type::ArrayType ary(&i32, 4);
ary.set_array_stride(16u);
ary.set_decorations(std::move(decos));
ast::Module mod;
Builder b(&mod);

View File

@ -46,6 +46,7 @@
#include "src/ast/sint_literal.h"
#include "src/ast/stage_decoration.h"
#include "src/ast/statement.h"
#include "src/ast/stride_decoration.h"
#include "src/ast/struct.h"
#include "src/ast/struct_member.h"
#include "src/ast/struct_member_offset_decoration.h"
@ -395,8 +396,10 @@ bool GeneratorImpl::EmitType(ast::type::Type* type) {
} else if (type->IsArray()) {
auto* ary = type->AsArray();
if (ary->has_array_stride()) {
out_ << "[[stride(" << ary->array_stride() << ")]] ";
for (const auto& deco : ary->decorations()) {
if (deco->IsStride()) {
out_ << "[[stride(" << deco->AsStride()->stride() << ")]] ";
}
}
out_ << "array<";

View File

@ -13,6 +13,7 @@
// limitations under the License.
#include "gtest/gtest.h"
#include "src/ast/stride_decoration.h"
#include "src/ast/struct.h"
#include "src/ast/struct_decoration.h"
#include "src/ast/struct_member.h"
@ -60,16 +61,33 @@ TEST_F(WgslGeneratorImplTest, EmitType_Array) {
EXPECT_EQ(g.result(), "array<bool, 4>");
}
TEST_F(WgslGeneratorImplTest, EmitType_Array_WithStride) {
TEST_F(WgslGeneratorImplTest, EmitType_Array_Decoration) {
ast::type::BoolType b;
ast::ArrayDecorationList decos;
decos.push_back(std::make_unique<ast::StrideDecoration>(16u));
ast::type::ArrayType a(&b, 4);
a.set_array_stride(16);
a.set_decorations(std::move(decos));
GeneratorImpl g;
ASSERT_TRUE(g.EmitType(&a)) << g.error();
EXPECT_EQ(g.result(), "[[stride(16)]] array<bool, 4>");
}
TEST_F(WgslGeneratorImplTest, EmitType_Array_MultipleDecorations) {
ast::type::BoolType b;
ast::ArrayDecorationList decos;
decos.push_back(std::make_unique<ast::StrideDecoration>(16u));
decos.push_back(std::make_unique<ast::StrideDecoration>(32u));
ast::type::ArrayType a(&b, 4);
a.set_decorations(std::move(decos));
GeneratorImpl g;
ASSERT_TRUE(g.EmitType(&a)) << g.error();
EXPECT_EQ(g.result(), "[[stride(16)]] [[stride(32)]] array<bool, 4>");
}
TEST_F(WgslGeneratorImplTest, EmitType_RuntimeArray) {
ast::type::BoolType b;
ast::type::ArrayType a(&b);