[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
|
||||
writer/spirv/binary_writer_test.cc
|
||||
writer/spirv/builder_test.cc
|
||||
writer/spirv/builder_type_test.cc
|
||||
writer/spirv/builder_entry_point_test.cc
|
||||
writer/spirv/instruction_test.cc
|
||||
writer/spirv/operand_test.cc
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace tint {
|
|||
namespace ast {
|
||||
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) {
|
||||
assert(rows > 1);
|
||||
assert(rows < 5);
|
||||
|
|
|
@ -30,7 +30,7 @@ class MatrixType : public Type {
|
|||
/// @param subtype type matrix type
|
||||
/// @param rows the number of rows 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
|
||||
MatrixType(MatrixType&&) = default;
|
||||
~MatrixType() override;
|
||||
|
@ -41,9 +41,9 @@ class MatrixType : public Type {
|
|||
/// @returns the type of the matrix
|
||||
Type* type() const { return subtype_; }
|
||||
/// @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
|
||||
size_t columns() const { return columns_; }
|
||||
uint32_t columns() const { return columns_; }
|
||||
|
||||
/// @returns the name for this type
|
||||
std::string type_name() const override {
|
||||
|
@ -53,8 +53,8 @@ class MatrixType : public Type {
|
|||
|
||||
private:
|
||||
Type* subtype_ = nullptr;
|
||||
size_t rows_ = 2;
|
||||
size_t columns_ = 2;
|
||||
uint32_t rows_ = 2;
|
||||
uint32_t columns_ = 2;
|
||||
};
|
||||
|
||||
} // namespace type
|
||||
|
|
|
@ -63,7 +63,7 @@ class Type {
|
|||
/// @returns true if the type is a void type
|
||||
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;
|
||||
|
||||
/// @returns the type as an alias type
|
||||
|
|
|
@ -20,7 +20,7 @@ namespace tint {
|
|||
namespace ast {
|
||||
namespace type {
|
||||
|
||||
VectorType::VectorType(Type* subtype, size_t size)
|
||||
VectorType::VectorType(Type* subtype, uint32_t size)
|
||||
: subtype_(subtype), size_(size) {
|
||||
assert(size_ > 1);
|
||||
assert(size_ < 5);
|
||||
|
|
|
@ -29,7 +29,7 @@ class VectorType : public Type {
|
|||
/// Constructor
|
||||
/// @param subtype the vector element type
|
||||
/// @param size the number of elements in the vector
|
||||
VectorType(Type* subtype, size_t size);
|
||||
VectorType(Type* subtype, uint32_t size);
|
||||
/// Move constructor
|
||||
VectorType(VectorType&&) = default;
|
||||
~VectorType() override;
|
||||
|
@ -40,7 +40,7 @@ class VectorType : public Type {
|
|||
/// @returns the type of the vector elements
|
||||
Type* type() const { return subtype_; }
|
||||
/// @returns the size of the vector
|
||||
size_t size() const { return size_; }
|
||||
uint32_t size() const { return size_; }
|
||||
|
||||
/// @returns the name for th type
|
||||
std::string type_name() const override {
|
||||
|
@ -49,7 +49,7 @@ class VectorType : public Type {
|
|||
|
||||
private:
|
||||
Type* subtype_ = nullptr;
|
||||
size_t size_ = 2;
|
||||
uint32_t size_ = 2;
|
||||
};
|
||||
|
||||
} // namespace type
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
#include "src/writer/spirv/builder.h"
|
||||
|
||||
#include "spirv/unified1/spirv.h"
|
||||
#include "src/ast/type/matrix_type.h"
|
||||
#include "src/ast/type/vector_type.h"
|
||||
|
||||
namespace tint {
|
||||
namespace writer {
|
||||
|
@ -137,14 +139,65 @@ bool Builder::GenerateEntryPoint(ast::EntryPoint* ep) {
|
|||
}
|
||||
|
||||
void Builder::GenerateImport(ast::Import* imp) {
|
||||
auto op = result_op();
|
||||
auto id = op.to_i();
|
||||
auto result = result_op();
|
||||
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;
|
||||
}
|
||||
|
||||
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 writer
|
||||
} // namespace tint
|
||||
|
|
|
@ -41,6 +41,8 @@ class Builder {
|
|||
|
||||
/// @returns the error string or blank if no error was reported.
|
||||
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
|
||||
uint32_t total_size() const;
|
||||
|
@ -99,7 +101,7 @@ class Builder {
|
|||
types_.push_back(Instruction{op, operands});
|
||||
}
|
||||
/// @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
|
||||
/// @param op the op to set
|
||||
/// @param operands the operands for the instruction
|
||||
|
@ -124,8 +126,14 @@ class Builder {
|
|||
/// Generates an import instruction
|
||||
/// @param imp the import
|
||||
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:
|
||||
/// @returns an Operand with a new result ID in it. Increments the next_id_
|
||||
/// automatically.
|
||||
Operand result_op();
|
||||
|
||||
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> func_name_to_id_;
|
||||
std::unordered_map<std::string, uint32_t> type_name_to_id_;
|
||||
};
|
||||
|
||||
} // 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);
|
||||
|
||||
std::string result;
|
||||
if (!tools.Disassemble(data, &result,
|
||||
SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES |
|
||||
SPV_BINARY_TO_TEXT_OPTION_NO_HEADER)) {
|
||||
if (!tools.Disassemble(data, &result, SPV_BINARY_TO_TEXT_OPTION_NO_HEADER)) {
|
||||
printf("%s\n", spv_errors.c_str());
|
||||
}
|
||||
return result;
|
||||
|
@ -77,6 +75,15 @@ std::string DumpInstruction(const Instruction& inst) {
|
|||
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 writer
|
||||
} // namespace tint
|
||||
|
|
|
@ -34,6 +34,11 @@ std::string DumpBuilder(const Builder& builder);
|
|||
/// @returns the instruction as a SPIR-V disassembly string
|
||||
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 writer
|
||||
} // namespace tint
|
||||
|
|
Loading…
Reference in New Issue