[spirv-writer] Allow emitting an array stride.

This CL adds the ability to attach a stride to an array type and have it
emitted during SPIR-V generation.

Bug: tint:5
Change-Id: I9c0f0a6afef6ae6662b64f4da2c150ba3f8da29f
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/23223
Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
dan sinclair 2020-06-15 20:58:28 +00:00
parent 7be237aa8f
commit 6941c5354c
6 changed files with 62 additions and 0 deletions

View File

@ -37,6 +37,8 @@ std::string ArrayType::type_name() const {
std::string type_name = "__array" + subtype_->type_name(); std::string type_name = "__array" + subtype_->type_name();
if (!IsRuntimeArray()) if (!IsRuntimeArray())
type_name += "_" + std::to_string(size_); type_name += "_" + std::to_string(size_);
if (has_array_stride())
type_name += "_" + std::to_string(array_stride_);
return type_name; return type_name;
} }

View File

@ -45,6 +45,14 @@ class ArrayType : public Type {
/// i.e. the size is determined at runtime /// i.e. the size is determined at runtime
bool IsRuntimeArray() const { return size_ == 0; } 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; }
/// @returns the array stride or 0 if none set.
uint32_t array_stride() const { return array_stride_; }
/// @returns true if the array has a stride set
bool has_array_stride() const { return array_stride_ != 0; }
/// @returns the array type /// @returns the array type
Type* type() const { return subtype_; } Type* type() const { return subtype_; }
/// @returns the array size. Size is 0 for a runtime array /// @returns the array size. Size is 0 for a runtime array
@ -56,6 +64,7 @@ class ArrayType : public Type {
private: private:
Type* subtype_ = nullptr; Type* subtype_ = nullptr;
uint32_t size_ = 0; uint32_t size_ = 0;
uint32_t array_stride_ = 0;
}; };
} // namespace type } // namespace type

View File

@ -60,11 +60,24 @@ TEST_F(ArrayTypeTest, Is) {
} }
TEST_F(ArrayTypeTest, TypeName) { TEST_F(ArrayTypeTest, TypeName) {
I32Type i32;
ArrayType arr{&i32};
EXPECT_EQ(arr.type_name(), "__array__i32");
}
TEST_F(ArrayTypeTest, TypeName_RuntimeArray) {
I32Type i32; I32Type i32;
ArrayType arr{&i32, 3}; ArrayType arr{&i32, 3};
EXPECT_EQ(arr.type_name(), "__array__i32_3"); EXPECT_EQ(arr.type_name(), "__array__i32_3");
} }
TEST_F(ArrayTypeTest, TypeName_WithStride) {
I32Type i32;
ArrayType arr{&i32, 3};
arr.set_array_stride(16);
EXPECT_EQ(arr.type_name(), "__array__i32_3_16");
}
} // namespace } // namespace
} // namespace type } // namespace type
} // namespace ast } // namespace ast

View File

@ -41,6 +41,11 @@ class StructType : public Type {
/// @returns the struct name /// @returns the struct name
const std::string& name() const { return name_; } const std::string& name() const { return name_; }
/// @returns true if the struct has a block decoration
bool IsBlockDecorated() const {
return struct_->decoration() == StructDecoration::kBlock;
}
/// @returns true if the type is a struct type /// @returns true if the type is a struct type
bool IsStruct() const override; bool IsStruct() const override;

View File

@ -1681,6 +1681,7 @@ bool Builder::GenerateArrayType(ast::type::ArrayType* ary,
return false; return false;
} }
auto result_id = result.to_i();
if (ary->IsRuntimeArray()) { if (ary->IsRuntimeArray()) {
push_type(spv::Op::OpTypeRuntimeArray, {result, Operand::Int(elem_type)}); push_type(spv::Op::OpTypeRuntimeArray, {result, Operand::Int(elem_type)});
} else { } else {
@ -1692,6 +1693,17 @@ bool Builder::GenerateArrayType(ast::type::ArrayType* ary,
push_type(spv::Op::OpTypeArray, push_type(spv::Op::OpTypeArray,
{result, Operand::Int(elem_type), Operand::Int(len_id)}); {result, Operand::Int(elem_type), Operand::Int(len_id)});
} }
// SPIR-V explicitly requires no array stride if the array contains a struct
// which has a Block decoration.
if (ary->type()->IsStruct() && ary->type()->AsStruct()->IsBlockDecorated()) {
return true;
}
if (ary->has_array_stride()) {
push_annot(spv::Op::OpDecorate,
{Operand::Int(result_id), Operand::Int(SpvDecorationArrayStride),
Operand::Int(ary->array_stride())});
}
return true; return true;
} }

View File

@ -118,6 +118,27 @@ TEST_F(BuilderTest_Type, GenerateArray) {
)"); )");
} }
TEST_F(BuilderTest_Type, GenerateArray_WithStride) {
ast::type::I32Type i32;
ast::type::ArrayType ary(&i32, 4);
ary.set_array_stride(16u);
ast::Module mod;
Builder b(&mod);
auto id = b.GenerateTypeIfNeeded(&ary);
ASSERT_FALSE(b.has_error()) << b.error();
EXPECT_EQ(1u, id);
EXPECT_EQ(DumpInstructions(b.annots()), R"(OpDecorate %1 ArrayStride 16
)");
EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeInt 32 1
%3 = OpTypeInt 32 0
%4 = OpConstant %3 4
%1 = OpTypeArray %2 %4
)");
}
TEST_F(BuilderTest_Type, ReturnsGeneratedArray) { TEST_F(BuilderTest_Type, ReturnsGeneratedArray) {
ast::type::I32Type i32; ast::type::I32Type i32;
ast::type::ArrayType ary(&i32, 4); ast::type::ArrayType ary(&i32, 4);