[spirv-writer] Start emitting types
This CL starts the emitting of SPIR-V types. This CL adds code to emit the `AliasType`, `BoolType`, `F32Type`, `I32Type`, `MatrixType`, `U32Type`, `VectorType` and `VoidType`. Bug: tint:5 Change-Id: Ic13026ca9006fc0a253d019b1a6dd984ae992fba Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/17561 Reviewed-by: David Neto <dneto@google.com>
This commit is contained in:
parent
7c6e8ded7d
commit
7a480f4313
|
@ -404,6 +404,7 @@ if(${TINT_BUILD_SPV_WRITER})
|
||||||
list(APPEND TINT_TEST_SRCS
|
list(APPEND TINT_TEST_SRCS
|
||||||
writer/spirv/binary_writer_test.cc
|
writer/spirv/binary_writer_test.cc
|
||||||
writer/spirv/builder_test.cc
|
writer/spirv/builder_test.cc
|
||||||
|
writer/spirv/builder_type_test.cc
|
||||||
writer/spirv/builder_entry_point_test.cc
|
writer/spirv/builder_entry_point_test.cc
|
||||||
writer/spirv/instruction_test.cc
|
writer/spirv/instruction_test.cc
|
||||||
writer/spirv/operand_test.cc
|
writer/spirv/operand_test.cc
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace tint {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
namespace type {
|
namespace type {
|
||||||
|
|
||||||
MatrixType::MatrixType(Type* subtype, size_t rows, size_t columns)
|
MatrixType::MatrixType(Type* subtype, uint32_t rows, uint32_t columns)
|
||||||
: subtype_(subtype), rows_(rows), columns_(columns) {
|
: subtype_(subtype), rows_(rows), columns_(columns) {
|
||||||
assert(rows > 1);
|
assert(rows > 1);
|
||||||
assert(rows < 5);
|
assert(rows < 5);
|
||||||
|
|
|
@ -30,7 +30,7 @@ class MatrixType : public Type {
|
||||||
/// @param subtype type matrix type
|
/// @param subtype type matrix type
|
||||||
/// @param rows the number of rows in the matrix
|
/// @param rows the number of rows in the matrix
|
||||||
/// @param columns the number of columns in the matrix
|
/// @param columns the number of columns in the matrix
|
||||||
MatrixType(Type* subtype, size_t rows, size_t columns);
|
MatrixType(Type* subtype, uint32_t rows, uint32_t columns);
|
||||||
/// Move constructor
|
/// Move constructor
|
||||||
MatrixType(MatrixType&&) = default;
|
MatrixType(MatrixType&&) = default;
|
||||||
~MatrixType() override;
|
~MatrixType() override;
|
||||||
|
@ -41,9 +41,9 @@ class MatrixType : public Type {
|
||||||
/// @returns the type of the matrix
|
/// @returns the type of the matrix
|
||||||
Type* type() const { return subtype_; }
|
Type* type() const { return subtype_; }
|
||||||
/// @returns the number of rows in the matrix
|
/// @returns the number of rows in the matrix
|
||||||
size_t rows() const { return rows_; }
|
uint32_t rows() const { return rows_; }
|
||||||
/// @returns the number of columns in the matrix
|
/// @returns the number of columns in the matrix
|
||||||
size_t columns() const { return columns_; }
|
uint32_t columns() const { return columns_; }
|
||||||
|
|
||||||
/// @returns the name for this type
|
/// @returns the name for this type
|
||||||
std::string type_name() const override {
|
std::string type_name() const override {
|
||||||
|
@ -53,8 +53,8 @@ class MatrixType : public Type {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type* subtype_ = nullptr;
|
Type* subtype_ = nullptr;
|
||||||
size_t rows_ = 2;
|
uint32_t rows_ = 2;
|
||||||
size_t columns_ = 2;
|
uint32_t columns_ = 2;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace type
|
} // namespace type
|
||||||
|
|
|
@ -63,7 +63,7 @@ class Type {
|
||||||
/// @returns true if the type is a void type
|
/// @returns true if the type is a void type
|
||||||
virtual bool IsVoid() const { return false; }
|
virtual bool IsVoid() const { return false; }
|
||||||
|
|
||||||
/// @returns the name for this type
|
/// @returns the name for this type. The |type_name| is unique over all types.
|
||||||
virtual std::string type_name() const = 0;
|
virtual std::string type_name() const = 0;
|
||||||
|
|
||||||
/// @returns the type as an alias type
|
/// @returns the type as an alias type
|
||||||
|
|
|
@ -20,7 +20,7 @@ namespace tint {
|
||||||
namespace ast {
|
namespace ast {
|
||||||
namespace type {
|
namespace type {
|
||||||
|
|
||||||
VectorType::VectorType(Type* subtype, size_t size)
|
VectorType::VectorType(Type* subtype, uint32_t size)
|
||||||
: subtype_(subtype), size_(size) {
|
: subtype_(subtype), size_(size) {
|
||||||
assert(size_ > 1);
|
assert(size_ > 1);
|
||||||
assert(size_ < 5);
|
assert(size_ < 5);
|
||||||
|
|
|
@ -29,7 +29,7 @@ class VectorType : public Type {
|
||||||
/// Constructor
|
/// Constructor
|
||||||
/// @param subtype the vector element type
|
/// @param subtype the vector element type
|
||||||
/// @param size the number of elements in the vector
|
/// @param size the number of elements in the vector
|
||||||
VectorType(Type* subtype, size_t size);
|
VectorType(Type* subtype, uint32_t size);
|
||||||
/// Move constructor
|
/// Move constructor
|
||||||
VectorType(VectorType&&) = default;
|
VectorType(VectorType&&) = default;
|
||||||
~VectorType() override;
|
~VectorType() override;
|
||||||
|
@ -40,7 +40,7 @@ class VectorType : public Type {
|
||||||
/// @returns the type of the vector elements
|
/// @returns the type of the vector elements
|
||||||
Type* type() const { return subtype_; }
|
Type* type() const { return subtype_; }
|
||||||
/// @returns the size of the vector
|
/// @returns the size of the vector
|
||||||
size_t size() const { return size_; }
|
uint32_t size() const { return size_; }
|
||||||
|
|
||||||
/// @returns the name for th type
|
/// @returns the name for th type
|
||||||
std::string type_name() const override {
|
std::string type_name() const override {
|
||||||
|
@ -49,7 +49,7 @@ class VectorType : public Type {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type* subtype_ = nullptr;
|
Type* subtype_ = nullptr;
|
||||||
size_t size_ = 2;
|
uint32_t size_ = 2;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace type
|
} // namespace type
|
||||||
|
|
|
@ -15,6 +15,8 @@
|
||||||
#include "src/writer/spirv/builder.h"
|
#include "src/writer/spirv/builder.h"
|
||||||
|
|
||||||
#include "spirv/unified1/spirv.h"
|
#include "spirv/unified1/spirv.h"
|
||||||
|
#include "src/ast/type/matrix_type.h"
|
||||||
|
#include "src/ast/type/vector_type.h"
|
||||||
|
|
||||||
namespace tint {
|
namespace tint {
|
||||||
namespace writer {
|
namespace writer {
|
||||||
|
@ -137,14 +139,65 @@ bool Builder::GenerateEntryPoint(ast::EntryPoint* ep) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Builder::GenerateImport(ast::Import* imp) {
|
void Builder::GenerateImport(ast::Import* imp) {
|
||||||
auto op = result_op();
|
auto result = result_op();
|
||||||
auto id = op.to_i();
|
auto id = result.to_i();
|
||||||
|
|
||||||
push_preamble(spv::Op::OpExtInstImport, {op, Operand::String(imp->path())});
|
push_preamble(spv::Op::OpExtInstImport,
|
||||||
|
{result, Operand::String(imp->path())});
|
||||||
|
|
||||||
import_name_to_id_[imp->name()] = id;
|
import_name_to_id_[imp->name()] = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t Builder::GenerateTypeIfNeeded(ast::type::Type* type) {
|
||||||
|
if (type->IsAlias()) {
|
||||||
|
return GenerateTypeIfNeeded(type->AsAlias()->type());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto val = type_name_to_id_.find(type->type_name());
|
||||||
|
if (val != type_name_to_id_.end()) {
|
||||||
|
return val->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto result = result_op();
|
||||||
|
auto id = result.to_i();
|
||||||
|
|
||||||
|
if (type->IsBool()) {
|
||||||
|
push_type(spv::Op::OpTypeBool, {result});
|
||||||
|
} else if (type->IsF32()) {
|
||||||
|
push_type(spv::Op::OpTypeFloat, {result, Operand::Int(32)});
|
||||||
|
} else if (type->IsI32()) {
|
||||||
|
push_type(spv::Op::OpTypeInt, {result, Operand::Int(32), Operand::Int(1)});
|
||||||
|
} else if (type->IsMatrix()) {
|
||||||
|
auto mat = type->AsMatrix();
|
||||||
|
ast::type::VectorType col_type(mat->type(), mat->rows());
|
||||||
|
auto type_id = GenerateTypeIfNeeded(&col_type);
|
||||||
|
if (has_error()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
push_type(spv::Op::OpTypeMatrix,
|
||||||
|
{result, Operand::Int(type_id), Operand::Int(mat->columns())});
|
||||||
|
} else if (type->IsU32()) {
|
||||||
|
push_type(spv::Op::OpTypeInt, {result, Operand::Int(32), Operand::Int(0)});
|
||||||
|
} else if (type->IsVector()) {
|
||||||
|
auto vec = type->AsVector();
|
||||||
|
auto col_type_id = GenerateTypeIfNeeded(vec->type());
|
||||||
|
if (has_error()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
push_type(spv::Op::OpTypeVector,
|
||||||
|
{result, Operand::Int(col_type_id), Operand::Int(vec->size())});
|
||||||
|
} else if (type->IsVoid()) {
|
||||||
|
push_type(spv::Op::OpTypeVoid, {result});
|
||||||
|
} else {
|
||||||
|
error_ = "unable to convert type: " + type->type_name();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
type_name_to_id_[type->type_name()] = id;
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace spirv
|
} // namespace spirv
|
||||||
} // namespace writer
|
} // namespace writer
|
||||||
} // namespace tint
|
} // namespace tint
|
||||||
|
|
|
@ -41,6 +41,8 @@ class Builder {
|
||||||
|
|
||||||
/// @returns the error string or blank if no error was reported.
|
/// @returns the error string or blank if no error was reported.
|
||||||
const std::string& error() const { return error_; }
|
const std::string& error() const { return error_; }
|
||||||
|
/// @returns true if the builder encountered an error
|
||||||
|
bool has_error() const { return !error_.empty(); }
|
||||||
|
|
||||||
/// @returns the number of uint32_t's needed to make up the results
|
/// @returns the number of uint32_t's needed to make up the results
|
||||||
uint32_t total_size() const;
|
uint32_t total_size() const;
|
||||||
|
@ -99,7 +101,7 @@ class Builder {
|
||||||
types_.push_back(Instruction{op, operands});
|
types_.push_back(Instruction{op, operands});
|
||||||
}
|
}
|
||||||
/// @returns the type instructions
|
/// @returns the type instructions
|
||||||
const std::vector<Instruction>& type() const { return types_; }
|
const std::vector<Instruction>& types() const { return types_; }
|
||||||
/// Adds an instruction to the instruction list
|
/// Adds an instruction to the instruction list
|
||||||
/// @param op the op to set
|
/// @param op the op to set
|
||||||
/// @param operands the operands for the instruction
|
/// @param operands the operands for the instruction
|
||||||
|
@ -124,8 +126,14 @@ class Builder {
|
||||||
/// Generates an import instruction
|
/// Generates an import instruction
|
||||||
/// @param imp the import
|
/// @param imp the import
|
||||||
void GenerateImport(ast::Import* imp);
|
void GenerateImport(ast::Import* imp);
|
||||||
|
/// Generates a type if not already created
|
||||||
|
/// @param type the type to create
|
||||||
|
/// @returns the ID to use for the given type. Returns 0 on unknown type.
|
||||||
|
uint32_t GenerateTypeIfNeeded(ast::type::Type* type);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/// @returns an Operand with a new result ID in it. Increments the next_id_
|
||||||
|
/// automatically.
|
||||||
Operand result_op();
|
Operand result_op();
|
||||||
|
|
||||||
std::string error_;
|
std::string error_;
|
||||||
|
@ -138,6 +146,7 @@ class Builder {
|
||||||
|
|
||||||
std::unordered_map<std::string, uint32_t> import_name_to_id_;
|
std::unordered_map<std::string, uint32_t> import_name_to_id_;
|
||||||
std::unordered_map<std::string, uint32_t> func_name_to_id_;
|
std::unordered_map<std::string, uint32_t> func_name_to_id_;
|
||||||
|
std::unordered_map<std::string, uint32_t> type_name_to_id_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace spirv
|
} // namespace spirv
|
||||||
|
|
|
@ -0,0 +1,256 @@
|
||||||
|
// 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 <memory>
|
||||||
|
|
||||||
|
#include "gtest/gtest.h"
|
||||||
|
#include "src/ast/type/alias_type.h"
|
||||||
|
#include "src/ast/type/array_type.h"
|
||||||
|
#include "src/ast/type/bool_type.h"
|
||||||
|
#include "src/ast/type/f32_type.h"
|
||||||
|
#include "src/ast/type/i32_type.h"
|
||||||
|
#include "src/ast/type/matrix_type.h"
|
||||||
|
#include "src/ast/type/pointer_type.h"
|
||||||
|
#include "src/ast/type/u32_type.h"
|
||||||
|
#include "src/ast/type/vector_type.h"
|
||||||
|
#include "src/ast/type/void_type.h"
|
||||||
|
#include "src/writer/spirv/builder.h"
|
||||||
|
#include "src/writer/spirv/spv_dump.h"
|
||||||
|
|
||||||
|
namespace tint {
|
||||||
|
namespace writer {
|
||||||
|
namespace spirv {
|
||||||
|
|
||||||
|
using BuilderTest_Type = testing::Test;
|
||||||
|
|
||||||
|
TEST_F(BuilderTest_Type, GenerateAlias) {
|
||||||
|
ast::type::F32Type f32;
|
||||||
|
ast::type::AliasType alias_type("my_type", &f32);
|
||||||
|
|
||||||
|
Builder b;
|
||||||
|
auto id = b.GenerateTypeIfNeeded(&alias_type);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
EXPECT_EQ(id, 1);
|
||||||
|
|
||||||
|
EXPECT_EQ(b.types().size(), 1);
|
||||||
|
EXPECT_EQ(DumpInstructions(b.types()), R"(%1 = OpTypeFloat 32
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(BuilderTest_Type, ReturnsGeneratedAlias) {
|
||||||
|
ast::type::I32Type i32;
|
||||||
|
ast::type::F32Type f32;
|
||||||
|
ast::type::AliasType alias_type("my_type", &f32);
|
||||||
|
|
||||||
|
Builder b;
|
||||||
|
EXPECT_EQ(b.GenerateTypeIfNeeded(&alias_type), 1);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
EXPECT_EQ(b.GenerateTypeIfNeeded(&i32), 2);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
EXPECT_EQ(b.GenerateTypeIfNeeded(&alias_type), 1);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
EXPECT_EQ(b.GenerateTypeIfNeeded(&f32), 1);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(BuilderTest_Type, GenerateBool) {
|
||||||
|
ast::type::BoolType bool_type;
|
||||||
|
|
||||||
|
Builder b;
|
||||||
|
auto id = b.GenerateTypeIfNeeded(&bool_type);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
EXPECT_EQ(id, 1);
|
||||||
|
|
||||||
|
ASSERT_EQ(b.types().size(), 1);
|
||||||
|
EXPECT_EQ(DumpInstruction(b.types()[0]), R"(%1 = OpTypeBool
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(BuilderTest_Type, ReturnsGeneratedBool) {
|
||||||
|
ast::type::I32Type i32;
|
||||||
|
ast::type::BoolType bool_type;
|
||||||
|
|
||||||
|
Builder b;
|
||||||
|
EXPECT_EQ(b.GenerateTypeIfNeeded(&bool_type), 1);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
EXPECT_EQ(b.GenerateTypeIfNeeded(&i32), 2);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
EXPECT_EQ(b.GenerateTypeIfNeeded(&bool_type), 1);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(BuilderTest_Type, GenerateF32) {
|
||||||
|
ast::type::F32Type f32;
|
||||||
|
|
||||||
|
Builder b;
|
||||||
|
auto id = b.GenerateTypeIfNeeded(&f32);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
EXPECT_EQ(id, 1);
|
||||||
|
|
||||||
|
ASSERT_EQ(b.types().size(), 1);
|
||||||
|
EXPECT_EQ(DumpInstruction(b.types()[0]), R"(%1 = OpTypeFloat 32
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(BuilderTest_Type, ReturnsGeneratedF32) {
|
||||||
|
ast::type::I32Type i32;
|
||||||
|
ast::type::F32Type f32;
|
||||||
|
|
||||||
|
Builder b;
|
||||||
|
EXPECT_EQ(b.GenerateTypeIfNeeded(&f32), 1);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
EXPECT_EQ(b.GenerateTypeIfNeeded(&i32), 2);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
EXPECT_EQ(b.GenerateTypeIfNeeded(&f32), 1);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(BuilderTest_Type, GenerateI32) {
|
||||||
|
ast::type::I32Type i32;
|
||||||
|
|
||||||
|
Builder b;
|
||||||
|
auto id = b.GenerateTypeIfNeeded(&i32);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
EXPECT_EQ(id, 1);
|
||||||
|
|
||||||
|
ASSERT_EQ(b.types().size(), 1);
|
||||||
|
EXPECT_EQ(DumpInstruction(b.types()[0]), R"(%1 = OpTypeInt 32 1
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(BuilderTest_Type, ReturnsGeneratedI32) {
|
||||||
|
ast::type::I32Type i32;
|
||||||
|
ast::type::F32Type f32;
|
||||||
|
|
||||||
|
Builder b;
|
||||||
|
EXPECT_EQ(b.GenerateTypeIfNeeded(&i32), 1);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
EXPECT_EQ(b.GenerateTypeIfNeeded(&f32), 2);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
EXPECT_EQ(b.GenerateTypeIfNeeded(&i32), 1);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(BuilderTest_Type, GenerateMatrix) {
|
||||||
|
ast::type::F32Type f32;
|
||||||
|
ast::type::MatrixType mat_type(&f32, 3, 2);
|
||||||
|
|
||||||
|
Builder b;
|
||||||
|
auto id = b.GenerateTypeIfNeeded(&mat_type);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
EXPECT_EQ(id, 1);
|
||||||
|
|
||||||
|
EXPECT_EQ(b.types().size(), 3);
|
||||||
|
EXPECT_EQ(DumpInstructions(b.types()), R"(%3 = OpTypeFloat 32
|
||||||
|
%2 = OpTypeVector %3 3
|
||||||
|
%1 = OpTypeMatrix %2 2
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(BuilderTest_Type, ReturnsGeneratedMatrix) {
|
||||||
|
ast::type::I32Type i32;
|
||||||
|
ast::type::MatrixType mat_type(&i32, 3, 4);
|
||||||
|
|
||||||
|
Builder b;
|
||||||
|
EXPECT_EQ(b.GenerateTypeIfNeeded(&mat_type), 1);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
EXPECT_EQ(b.GenerateTypeIfNeeded(&i32), 3);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
EXPECT_EQ(b.GenerateTypeIfNeeded(&mat_type), 1);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(BuilderTest_Type, GenerateU32) {
|
||||||
|
ast::type::U32Type u32;
|
||||||
|
|
||||||
|
Builder b;
|
||||||
|
auto id = b.GenerateTypeIfNeeded(&u32);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
EXPECT_EQ(id, 1);
|
||||||
|
|
||||||
|
ASSERT_EQ(b.types().size(), 1);
|
||||||
|
EXPECT_EQ(DumpInstruction(b.types()[0]), R"(%1 = OpTypeInt 32 0
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(BuilderTest_Type, ReturnsGeneratedU32) {
|
||||||
|
ast::type::U32Type u32;
|
||||||
|
ast::type::F32Type f32;
|
||||||
|
|
||||||
|
Builder b;
|
||||||
|
EXPECT_EQ(b.GenerateTypeIfNeeded(&u32), 1);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
EXPECT_EQ(b.GenerateTypeIfNeeded(&f32), 2);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
EXPECT_EQ(b.GenerateTypeIfNeeded(&u32), 1);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(BuilderTest_Type, GenerateVector) {
|
||||||
|
ast::type::F32Type f32;
|
||||||
|
ast::type::VectorType vec_type(&f32, 3);
|
||||||
|
|
||||||
|
Builder b;
|
||||||
|
auto id = b.GenerateTypeIfNeeded(&vec_type);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
EXPECT_EQ(id, 1);
|
||||||
|
|
||||||
|
EXPECT_EQ(b.types().size(), 2);
|
||||||
|
EXPECT_EQ(DumpInstructions(b.types()), R"(%2 = OpTypeFloat 32
|
||||||
|
%1 = OpTypeVector %2 3
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(BuilderTest_Type, ReturnsGeneratedVector) {
|
||||||
|
ast::type::I32Type i32;
|
||||||
|
ast::type::VectorType vec_type(&i32, 3);
|
||||||
|
|
||||||
|
Builder b;
|
||||||
|
EXPECT_EQ(b.GenerateTypeIfNeeded(&vec_type), 1);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
EXPECT_EQ(b.GenerateTypeIfNeeded(&i32), 2);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
EXPECT_EQ(b.GenerateTypeIfNeeded(&vec_type), 1);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(BuilderTest_Type, GenerateVoid) {
|
||||||
|
ast::type::VoidType void_type;
|
||||||
|
|
||||||
|
Builder b;
|
||||||
|
auto id = b.GenerateTypeIfNeeded(&void_type);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
EXPECT_EQ(id, 1);
|
||||||
|
|
||||||
|
ASSERT_EQ(b.types().size(), 1);
|
||||||
|
EXPECT_EQ(DumpInstruction(b.types()[0]), R"(%1 = OpTypeVoid
|
||||||
|
)");
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(BuilderTest_Type, ReturnsGeneratedVoid) {
|
||||||
|
ast::type::I32Type i32;
|
||||||
|
ast::type::VoidType void_type;
|
||||||
|
|
||||||
|
Builder b;
|
||||||
|
EXPECT_EQ(b.GenerateTypeIfNeeded(&void_type), 1);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
EXPECT_EQ(b.GenerateTypeIfNeeded(&i32), 2);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
EXPECT_EQ(b.GenerateTypeIfNeeded(&void_type), 1);
|
||||||
|
ASSERT_FALSE(b.has_error()) << b.error();
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace spirv
|
||||||
|
} // namespace writer
|
||||||
|
} // namespace tint
|
|
@ -53,9 +53,7 @@ std::string Disassemble(const std::vector<uint32_t>& data) {
|
||||||
tools.SetMessageConsumer(msg_consumer);
|
tools.SetMessageConsumer(msg_consumer);
|
||||||
|
|
||||||
std::string result;
|
std::string result;
|
||||||
if (!tools.Disassemble(data, &result,
|
if (!tools.Disassemble(data, &result, SPV_BINARY_TO_TEXT_OPTION_NO_HEADER)) {
|
||||||
SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES |
|
|
||||||
SPV_BINARY_TO_TEXT_OPTION_NO_HEADER)) {
|
|
||||||
printf("%s\n", spv_errors.c_str());
|
printf("%s\n", spv_errors.c_str());
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
@ -77,6 +75,15 @@ std::string DumpInstruction(const Instruction& inst) {
|
||||||
return Disassemble(writer.result());
|
return Disassemble(writer.result());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string DumpInstructions(const std::vector<Instruction>& insts) {
|
||||||
|
BinaryWriter writer;
|
||||||
|
writer.WriteHeader(kDefaultMaxIdBound);
|
||||||
|
for (const auto& inst : insts) {
|
||||||
|
writer.WriteInstruction(inst);
|
||||||
|
}
|
||||||
|
return Disassemble(writer.result());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace spirv
|
} // namespace spirv
|
||||||
} // namespace writer
|
} // namespace writer
|
||||||
} // namespace tint
|
} // namespace tint
|
||||||
|
|
|
@ -34,6 +34,11 @@ std::string DumpBuilder(const Builder& builder);
|
||||||
/// @returns the instruction as a SPIR-V disassembly string
|
/// @returns the instruction as a SPIR-V disassembly string
|
||||||
std::string DumpInstruction(const Instruction& inst);
|
std::string DumpInstruction(const Instruction& inst);
|
||||||
|
|
||||||
|
/// Dumps the given instructions to a SPIR-V disassembly string
|
||||||
|
/// @param insts the instructions to dump
|
||||||
|
/// @returns the instruction as a SPIR-V disassembly string
|
||||||
|
std::string DumpInstructions(const std::vector<Instruction>& insts);
|
||||||
|
|
||||||
} // namespace spirv
|
} // namespace spirv
|
||||||
} // namespace writer
|
} // namespace writer
|
||||||
} // namespace tint
|
} // namespace tint
|
||||||
|
|
Loading…
Reference in New Issue