mirror of
https://github.com/encounter/dawn-cmake.git
synced 2025-07-30 00:45:52 +00:00
[spir-reader] Emit alias types (named types)
Bug: tint:3 Change-Id: I4882160d9fe533d956f29ca15e65bf99eb80f5df Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/18360 Reviewed-by: dan sinclair <dsinclair@google.com>
This commit is contained in:
parent
4493d13d49
commit
a7640d6d4c
@ -327,6 +327,7 @@ if(${TINT_BUILD_SPV_READER})
|
||||
reader/spirv/parser_impl_entry_point_test.cc
|
||||
reader/spirv/parser_impl_get_decorations_test.cc
|
||||
reader/spirv/parser_impl_import_test.cc
|
||||
reader/spirv/parser_impl_named_types_test.cc
|
||||
reader/spirv/parser_impl_user_name_test.cc
|
||||
reader/spirv/parser_impl_test.cc
|
||||
reader/spirv/parser_test.cc
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "src/ast/struct_member.h"
|
||||
#include "src/ast/struct_member_decoration.h"
|
||||
#include "src/ast/struct_member_offset_decoration.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"
|
||||
@ -77,7 +78,6 @@ ParserImpl::ParserImpl(Context* ctx, const std::vector<uint32_t>& spv_binary)
|
||||
// For binary validation errors, we only have the instruction
|
||||
// number. It's not text, so there is no column number.
|
||||
this->Fail() << "line:" << position.index << ": " << message;
|
||||
this->Fail() << "error: line " << position.index << ": " << message;
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -85,23 +85,27 @@ ParserImpl::ParserImpl(Context* ctx, const std::vector<uint32_t>& spv_binary)
|
||||
ParserImpl::~ParserImpl() = default;
|
||||
|
||||
bool ParserImpl::Parse() {
|
||||
// Set up use of SPIRV-Tools utilities.
|
||||
spvtools::SpirvTools spv_tools(kTargetEnv);
|
||||
|
||||
// Error messages from SPIRV-Tools are forwarded as failures, including
|
||||
// setting |success_| to false.
|
||||
spv_tools.SetMessageConsumer(message_consumer_);
|
||||
|
||||
if (!success_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Set up use of SPIRV-Tools utilities.
|
||||
spvtools::SpirvTools spv_tools(kTargetEnv);
|
||||
|
||||
// Error messages from SPIRV-Tools are forwarded as failures.
|
||||
spv_tools.SetMessageConsumer(message_consumer_);
|
||||
|
||||
// Only consider valid modules.
|
||||
if (success_) {
|
||||
success_ = spv_tools.Validate(spv_binary_);
|
||||
// Only consider valid modules. On failure, the message consumer
|
||||
// will set the error status.
|
||||
if (!spv_tools.Validate(spv_binary_)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (success_) {
|
||||
success_ = BuildInternalModule();
|
||||
if (!BuildInternalModule()) {
|
||||
return false;
|
||||
}
|
||||
if (!ParseInternalModule()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return success_;
|
||||
@ -160,6 +164,11 @@ ast::type::Type* ParserImpl::ConvertType(uint32_t type_id) {
|
||||
return save(ConvertType(spirv_type->AsArray()));
|
||||
case spvtools::opt::analysis::Type::kStruct:
|
||||
return save(ConvertType(spirv_type->AsStruct()));
|
||||
case spvtools::opt::analysis::Type::kFunction:
|
||||
case spvtools::opt::analysis::Type::kPointer:
|
||||
// For now, just return null without erroring out.
|
||||
// TODO(dneto)
|
||||
return nullptr;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -228,6 +237,9 @@ ParserImpl::ConvertMemberDecoration(const Decoration& decoration) {
|
||||
}
|
||||
|
||||
bool ParserImpl::BuildInternalModule() {
|
||||
if (!success_) {
|
||||
return false;
|
||||
}
|
||||
tools_.SetMessageConsumer(message_consumer_);
|
||||
|
||||
const spv_context& context = tools_context_.CContext();
|
||||
@ -243,7 +255,7 @@ bool ParserImpl::BuildInternalModule() {
|
||||
type_mgr_ = ir_context_->get_type_mgr();
|
||||
deco_mgr_ = ir_context_->get_decoration_mgr();
|
||||
|
||||
return true;
|
||||
return success_;
|
||||
}
|
||||
|
||||
void ParserImpl::ResetInternalModule() {
|
||||
@ -265,12 +277,18 @@ bool ParserImpl::ParseInternalModule() {
|
||||
if (!RegisterExtendedInstructionImports()) {
|
||||
return false;
|
||||
}
|
||||
if (!RegisterUserNames()) {
|
||||
if (!RegisterUserAndStructMemberNames()) {
|
||||
return false;
|
||||
}
|
||||
if (!EmitEntryPoints()) {
|
||||
return false;
|
||||
}
|
||||
if (!RegisterTypes()) {
|
||||
return false;
|
||||
}
|
||||
if (!EmitAliasTypes()) {
|
||||
return false;
|
||||
}
|
||||
// TODO(dneto): fill in the rest
|
||||
return true;
|
||||
}
|
||||
@ -297,7 +315,10 @@ bool ParserImpl::RegisterExtendedInstructionImports() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParserImpl::RegisterUserNames() {
|
||||
bool ParserImpl::RegisterUserAndStructMemberNames() {
|
||||
if (!success_) {
|
||||
return false;
|
||||
}
|
||||
// Register entry point names. An entry point name is the point of contact
|
||||
// between the API and the shader. It has the highest priority for
|
||||
// preservation, so register it first.
|
||||
@ -490,14 +511,77 @@ ast::type::Type* ParserImpl::ConvertType(
|
||||
// Now make the struct.
|
||||
auto ast_struct = std::make_unique<ast::Struct>(ast_struct_decoration,
|
||||
std::move(ast_members));
|
||||
// The struct type will be assigned a name during EmitAliasTypes.
|
||||
auto ast_struct_type =
|
||||
std::make_unique<ast::type::StructType>(std::move(ast_struct));
|
||||
// The struct might not have a name yet. Suggest one.
|
||||
// Set the struct name before registering it.
|
||||
namer_.SuggestSanitizedName(type_id, "S");
|
||||
ast_struct_type->set_name(namer_.GetName(type_id));
|
||||
return ctx_.type_mgr().Get(std::move(ast_struct_type));
|
||||
}
|
||||
|
||||
bool ParserImpl::RegisterTypes() {
|
||||
if (!success_) {
|
||||
return false;
|
||||
}
|
||||
for (auto& type_or_const : module_->types_values()) {
|
||||
const auto* type = type_mgr_->GetType(type_or_const.result_id());
|
||||
if (type == nullptr) {
|
||||
continue;
|
||||
}
|
||||
ConvertType(type_or_const.result_id());
|
||||
}
|
||||
return success_;
|
||||
}
|
||||
|
||||
bool ParserImpl::EmitAliasTypes() {
|
||||
if (!success_) {
|
||||
return false;
|
||||
}
|
||||
// The algorithm here emits type definitions in the order presented in
|
||||
// the SPIR-V module. This is valid because:
|
||||
//
|
||||
// - There are no back-references. OpTypeForwarddPointer is not supported
|
||||
// by the WebGPU shader programming model.
|
||||
// - Arrays are always sized by an OpConstant of scalar integral type.
|
||||
// WGSL currently doesn't have specialization constants.
|
||||
// crbug.com/32 tracks implementation in case they are added.
|
||||
for (auto& type_or_const : module_->types_values()) {
|
||||
const auto type_id = type_or_const.result_id();
|
||||
// We only care about struct, arrays, and runtime arrays.
|
||||
switch (type_or_const.opcode()) {
|
||||
case SpvOpTypeStruct:
|
||||
// The struct already got a name when the type was first registered.
|
||||
break;
|
||||
case SpvOpTypeRuntimeArray:
|
||||
// Runtime arrays are always decorated with ArrayStride so always get a
|
||||
// type alias.
|
||||
namer_.SuggestSanitizedName(type_id, "RTArr");
|
||||
break;
|
||||
case SpvOpTypeArray:
|
||||
// Only make a type aliase for arrays with decorations.
|
||||
if (GetDecorationsFor(type_id).empty()) {
|
||||
continue;
|
||||
}
|
||||
namer_.SuggestSanitizedName(type_id, "Arr");
|
||||
break;
|
||||
default:
|
||||
// Ignore constants, and any other types.
|
||||
continue;
|
||||
}
|
||||
auto* ast_underlying_type = id_to_type_[type_id];
|
||||
if (ast_underlying_type == nullptr) {
|
||||
Fail() << "internal error: no type registered for SPIR-V ID: " << type_id;
|
||||
return false;
|
||||
}
|
||||
const auto name = namer_.GetName(type_id);
|
||||
auto* ast_type = ctx_.type_mgr().Get(
|
||||
std::make_unique<ast::type::AliasType>(name, ast_underlying_type));
|
||||
ast_module_.AddAliasType(ast_type->AsAlias());
|
||||
}
|
||||
return success_;
|
||||
}
|
||||
|
||||
} // namespace spirv
|
||||
} // namespace reader
|
||||
} // namespace tint
|
||||
|
@ -126,33 +126,54 @@ class ParserImpl : Reader {
|
||||
std::unique_ptr<ast::StructMemberDecoration> ConvertMemberDecoration(
|
||||
const Decoration& decoration);
|
||||
|
||||
private:
|
||||
/// Builds the internal representation of the SPIR-V module.
|
||||
/// Assumes the module is somewhat well-formed. Normally you
|
||||
/// would want to validate the SPIR-V module before attempting
|
||||
/// to build this internal representation.
|
||||
/// @returns true if successful.
|
||||
/// This is a no-op if the parser has already failed.
|
||||
/// @returns true if the parser is still successful.
|
||||
bool BuildInternalModule();
|
||||
|
||||
/// Walks the internal representation of the module to populate
|
||||
/// the AST form of the module.
|
||||
/// @returns true on success
|
||||
/// This is a no-op if the parser has already failed.
|
||||
/// @returns true if the parser is still successful.
|
||||
bool ParseInternalModule();
|
||||
|
||||
/// Destroys the internal representation of the SPIR-V module.
|
||||
void ResetInternalModule();
|
||||
|
||||
/// Registers extended instruction imports. Only "GLSL.std.450" is supported.
|
||||
/// This is a no-op if the parser has already failed.
|
||||
/// @returns true if parser is still successful.
|
||||
bool RegisterExtendedInstructionImports();
|
||||
|
||||
/// Registers user names for SPIR-V objects, from OpName, and OpMemberName.
|
||||
/// Also synthesizes struct field names. Ensures uniqueness for names for
|
||||
/// SPIR-V IDs, and uniqueness of names of fields within any single struct.
|
||||
bool RegisterUserNames();
|
||||
/// This is a no-op if the parser has already failed.
|
||||
/// @returns true if parser is still successful.
|
||||
bool RegisterUserAndStructMemberNames();
|
||||
|
||||
/// Emit entry point AST nodes.
|
||||
/// This is a no-op if the parser has already failed.
|
||||
/// @returns true if parser is still successful.
|
||||
bool EmitEntryPoints();
|
||||
|
||||
/// Register Tint AST types for SPIR-V types.
|
||||
/// This is a no-op if the parser has already failed.
|
||||
/// @returns true if parser is still successful.
|
||||
bool RegisterTypes();
|
||||
|
||||
/// Emit type alias declarations for types requiring user-specified names:
|
||||
/// - struct types
|
||||
/// - decorated arrays and runtime arrays
|
||||
/// TODO(dneto): I expect images and samplers to require names as well.
|
||||
/// This is a no-op if the parser has already failed.
|
||||
/// @returns true if parser is still successful.
|
||||
bool EmitAliasTypes();
|
||||
|
||||
private:
|
||||
/// Converts a specific SPIR-V type to a Tint type. Integer case
|
||||
ast::type::Type* ConvertType(const spvtools::opt::analysis::Integer* int_ty);
|
||||
/// Converts a specific SPIR-V type to a Tint type. Float case
|
||||
|
@ -53,7 +53,7 @@ TEST_F(SpvParserTest, ConvertType_RequiresInternalRepresntation) {
|
||||
|
||||
TEST_F(SpvParserTest, ConvertType_NotAnId) {
|
||||
auto p = parser(test::Assemble("%1 = OpExtInstImport \"GLSL.std.450\""));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule()) << p->error();
|
||||
EXPECT_TRUE(p->BuildInternalModule());
|
||||
|
||||
auto* type = p->ConvertType(10);
|
||||
EXPECT_EQ(type, nullptr);
|
||||
@ -63,7 +63,7 @@ TEST_F(SpvParserTest, ConvertType_NotAnId) {
|
||||
|
||||
TEST_F(SpvParserTest, ConvertType_IdExistsButIsNotAType) {
|
||||
auto p = parser(test::Assemble("%1 = OpExtInstImport \"GLSL.std.450\""));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->BuildInternalModule());
|
||||
|
||||
auto* type = p->ConvertType(1);
|
||||
EXPECT_EQ(nullptr, type);
|
||||
@ -73,7 +73,7 @@ TEST_F(SpvParserTest, ConvertType_IdExistsButIsNotAType) {
|
||||
TEST_F(SpvParserTest, ConvertType_UnhandledType) {
|
||||
// Pipes are an OpenCL type. Tint doesn't support them.
|
||||
auto p = parser(test::Assemble("%70 = OpTypePipe WriteOnly"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->BuildInternalModule());
|
||||
|
||||
auto* type = p->ConvertType(70);
|
||||
EXPECT_EQ(nullptr, type);
|
||||
@ -82,7 +82,7 @@ TEST_F(SpvParserTest, ConvertType_UnhandledType) {
|
||||
|
||||
TEST_F(SpvParserTest, ConvertType_Void) {
|
||||
auto p = parser(test::Assemble("%1 = OpTypeVoid"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->BuildInternalModule());
|
||||
|
||||
auto* type = p->ConvertType(1);
|
||||
EXPECT_TRUE(type->IsVoid());
|
||||
@ -91,7 +91,7 @@ TEST_F(SpvParserTest, ConvertType_Void) {
|
||||
|
||||
TEST_F(SpvParserTest, ConvertType_Bool) {
|
||||
auto p = parser(test::Assemble("%100 = OpTypeBool"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->BuildInternalModule());
|
||||
|
||||
auto* type = p->ConvertType(100);
|
||||
EXPECT_TRUE(type->IsBool());
|
||||
@ -100,7 +100,7 @@ TEST_F(SpvParserTest, ConvertType_Bool) {
|
||||
|
||||
TEST_F(SpvParserTest, ConvertType_I32) {
|
||||
auto p = parser(test::Assemble("%2 = OpTypeInt 32 1"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->BuildInternalModule());
|
||||
|
||||
auto* type = p->ConvertType(2);
|
||||
EXPECT_TRUE(type->IsI32());
|
||||
@ -109,7 +109,7 @@ TEST_F(SpvParserTest, ConvertType_I32) {
|
||||
|
||||
TEST_F(SpvParserTest, ConvertType_U32) {
|
||||
auto p = parser(test::Assemble("%3 = OpTypeInt 32 0"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->BuildInternalModule());
|
||||
|
||||
auto* type = p->ConvertType(3);
|
||||
EXPECT_TRUE(type->IsU32());
|
||||
@ -118,7 +118,7 @@ TEST_F(SpvParserTest, ConvertType_U32) {
|
||||
|
||||
TEST_F(SpvParserTest, ConvertType_F32) {
|
||||
auto p = parser(test::Assemble("%4 = OpTypeFloat 32"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->BuildInternalModule());
|
||||
|
||||
auto* type = p->ConvertType(4);
|
||||
EXPECT_TRUE(type->IsF32());
|
||||
@ -127,7 +127,7 @@ TEST_F(SpvParserTest, ConvertType_F32) {
|
||||
|
||||
TEST_F(SpvParserTest, ConvertType_BadIntWidth) {
|
||||
auto p = parser(test::Assemble("%5 = OpTypeInt 17 1"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->BuildInternalModule());
|
||||
|
||||
auto* type = p->ConvertType(5);
|
||||
EXPECT_EQ(type, nullptr);
|
||||
@ -136,7 +136,7 @@ TEST_F(SpvParserTest, ConvertType_BadIntWidth) {
|
||||
|
||||
TEST_F(SpvParserTest, ConvertType_BadFloatWidth) {
|
||||
auto p = parser(test::Assemble("%6 = OpTypeFloat 19"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->BuildInternalModule());
|
||||
|
||||
auto* type = p->ConvertType(6);
|
||||
EXPECT_EQ(type, nullptr);
|
||||
@ -148,7 +148,7 @@ TEST_F(SpvParserTest, DISABLED_ConvertType_InvalidVectorElement) {
|
||||
%5 = OpTypePipe ReadOnly
|
||||
%20 = OpTypeVector %5 2
|
||||
)"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->BuildInternalModule());
|
||||
|
||||
auto* type = p->ConvertType(20);
|
||||
EXPECT_EQ(type, nullptr);
|
||||
@ -162,7 +162,7 @@ TEST_F(SpvParserTest, ConvertType_VecOverF32) {
|
||||
%30 = OpTypeVector %float 3
|
||||
%40 = OpTypeVector %float 4
|
||||
)"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->BuildInternalModule());
|
||||
|
||||
auto* v2xf32 = p->ConvertType(20);
|
||||
EXPECT_TRUE(v2xf32->IsVector());
|
||||
@ -189,7 +189,7 @@ TEST_F(SpvParserTest, ConvertType_VecOverI32) {
|
||||
%30 = OpTypeVector %int 3
|
||||
%40 = OpTypeVector %int 4
|
||||
)"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->BuildInternalModule());
|
||||
|
||||
auto* v2xi32 = p->ConvertType(20);
|
||||
EXPECT_TRUE(v2xi32->IsVector());
|
||||
@ -216,7 +216,7 @@ TEST_F(SpvParserTest, ConvertType_VecOverU32) {
|
||||
%30 = OpTypeVector %uint 3
|
||||
%40 = OpTypeVector %uint 4
|
||||
)"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->BuildInternalModule());
|
||||
|
||||
auto* v2xu32 = p->ConvertType(20);
|
||||
EXPECT_TRUE(v2xu32->IsVector());
|
||||
@ -242,7 +242,7 @@ TEST_F(SpvParserTest, DISABLED_ConvertType_InvalidMatrixElement) {
|
||||
%10 = OpTypeVector %5 2
|
||||
%20 = OpTypeMatrix %10 2
|
||||
)"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->BuildInternalModule());
|
||||
|
||||
auto* type = p->ConvertType(20);
|
||||
EXPECT_EQ(type, nullptr);
|
||||
@ -268,7 +268,7 @@ TEST_F(SpvParserTest, ConvertType_MatrixOverF32) {
|
||||
%43 = OpTypeMatrix %v4 3
|
||||
%44 = OpTypeMatrix %v4 4
|
||||
)"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->BuildInternalModule());
|
||||
|
||||
auto* m22 = p->ConvertType(22);
|
||||
EXPECT_TRUE(m22->IsMatrix());
|
||||
@ -332,7 +332,7 @@ TEST_F(SpvParserTest, ConvertType_RuntimeArray) {
|
||||
%uint = OpTypeInt 32 0
|
||||
%10 = OpTypeRuntimeArray %uint
|
||||
)"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->BuildInternalModule());
|
||||
|
||||
auto* type = p->ConvertType(10);
|
||||
ASSERT_NE(type, nullptr);
|
||||
@ -353,7 +353,7 @@ TEST_F(SpvParserTest, ConvertType_Array) {
|
||||
%uint_42 = OpConstant %uint 42
|
||||
%10 = OpTypeArray %uint %uint_42
|
||||
)"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->BuildInternalModule());
|
||||
|
||||
auto* type = p->ConvertType(10);
|
||||
ASSERT_NE(type, nullptr);
|
||||
@ -375,7 +375,7 @@ TEST_F(SpvParserTest, ConvertType_ArrayBadLengthIsSpecConstantValue) {
|
||||
%uint_42 = OpSpecConstant %uint 42
|
||||
%10 = OpTypeArray %uint %uint_42
|
||||
)"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->BuildInternalModule());
|
||||
|
||||
auto* type = p->ConvertType(10);
|
||||
ASSERT_EQ(type, nullptr);
|
||||
@ -390,7 +390,7 @@ TEST_F(SpvParserTest, ConvertType_ArrayBadLengthIsSpecConstantExpr) {
|
||||
%sum = OpSpecConstantOp %uint IAdd %uint_42 %uint_42
|
||||
%10 = OpTypeArray %uint %sum
|
||||
)"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->BuildInternalModule());
|
||||
|
||||
auto* type = p->ConvertType(10);
|
||||
ASSERT_EQ(type, nullptr);
|
||||
@ -408,7 +408,7 @@ TEST_F(SpvParserTest, ConvertType_ArrayBadTooBig) {
|
||||
%uint64_big = OpConstant %uint64 5000000000
|
||||
%10 = OpTypeArray %uint64 %uint64_big
|
||||
)"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->BuildInternalModule());
|
||||
|
||||
auto* type = p->ConvertType(10);
|
||||
ASSERT_EQ(type, nullptr);
|
||||
@ -423,10 +423,11 @@ TEST_F(SpvParserTest, ConvertType_StructTwoMembers) {
|
||||
%float = OpTypeFloat 32
|
||||
%10 = OpTypeStruct %uint %float
|
||||
)"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->BuildInternalModule());
|
||||
EXPECT_TRUE(p->RegisterUserAndStructMemberNames());
|
||||
|
||||
auto* type = p->ConvertType(10);
|
||||
ASSERT_NE(type, nullptr) << p->error();
|
||||
ASSERT_NE(type, nullptr);
|
||||
EXPECT_TRUE(type->IsStruct());
|
||||
std::stringstream ss;
|
||||
type->AsStruct()->impl()->to_str(ss, 0);
|
||||
@ -443,7 +444,8 @@ TEST_F(SpvParserTest, ConvertType_StructWithBlockDecoration) {
|
||||
%uint = OpTypeInt 32 0
|
||||
%10 = OpTypeStruct %uint
|
||||
)"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->BuildInternalModule());
|
||||
EXPECT_TRUE(p->RegisterUserAndStructMemberNames());
|
||||
|
||||
auto* type = p->ConvertType(10);
|
||||
ASSERT_NE(type, nullptr);
|
||||
@ -466,10 +468,11 @@ TEST_F(SpvParserTest, ConvertType_StructWithMemberDecorations) {
|
||||
%mat = OpTypeMatrix %vec 2
|
||||
%10 = OpTypeStruct %float %vec %mat
|
||||
)"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->BuildInternalModule());
|
||||
EXPECT_TRUE(p->RegisterUserAndStructMemberNames());
|
||||
|
||||
auto* type = p->ConvertType(10);
|
||||
ASSERT_NE(type, nullptr) << p->error();
|
||||
ASSERT_NE(type, nullptr);
|
||||
EXPECT_TRUE(type->IsStruct());
|
||||
std::stringstream ss;
|
||||
type->AsStruct()->impl()->to_str(ss, 0);
|
||||
|
@ -97,7 +97,8 @@ TEST_F(SpvParserTest, GetDecorationsForMember_MemberWithoutDecoration) {
|
||||
EXPECT_TRUE(p->error().empty());
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest, GetDecorationsForMember_OneDecoration) {
|
||||
// TODO(dneto): Enable when ArrayStride is handled
|
||||
TEST_F(SpvParserTest, DISABLED_GetDecorationsForMember_OneDecoration) {
|
||||
auto p = parser(test::Assemble(R"(
|
||||
OpMemberDecorate %10 1 ArrayStride 12
|
||||
%uint = OpTypeInt 32 0
|
||||
@ -105,14 +106,17 @@ TEST_F(SpvParserTest, GetDecorationsForMember_OneDecoration) {
|
||||
%arr = OpTypeArray %uint %uint_2
|
||||
%10 = OpTypeStruct %uint %arr
|
||||
)"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule()) << p->error();
|
||||
auto decorations = p->GetDecorationsForMember(10, 1);
|
||||
EXPECT_THAT(decorations,
|
||||
UnorderedElementsAre(Decoration{SpvDecorationArrayStride, 12}));
|
||||
EXPECT_TRUE(p->error().empty());
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest, GetDecorationsForMember_MultiDecoration) {
|
||||
// TODO(dneto): Enable when ArrayStride, MatrixStride, ColMajor are handled
|
||||
// crbug.com/tint/30 for ArrayStride
|
||||
// crbug.com/tint/31 for matrix layout
|
||||
TEST_F(SpvParserTest, DISABLED_GetDecorationsForMember_MultiDecoration) {
|
||||
auto p = parser(test::Assemble(R"(
|
||||
OpMemberDecorate %50 1 RelaxedPrecision
|
||||
OpMemberDecorate %50 2 ArrayStride 16
|
||||
@ -126,7 +130,7 @@ TEST_F(SpvParserTest, GetDecorationsForMember_MultiDecoration) {
|
||||
%arr = OpTypeArray %mat %uint_2
|
||||
%50 = OpTypeStruct %uint %float %arr
|
||||
)"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule()) << p->error();
|
||||
|
||||
EXPECT_TRUE(p->GetDecorationsForMember(50, 0).empty());
|
||||
EXPECT_THAT(p->GetDecorationsForMember(50, 1),
|
||||
|
96
src/reader/spirv/parser_impl_named_types_test.cc
Normal file
96
src/reader/spirv/parser_impl_named_types_test.cc
Normal file
@ -0,0 +1,96 @@
|
||||
// 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 <cstdint>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "gmock/gmock.h"
|
||||
#include "src/ast/struct.h"
|
||||
#include "src/ast/type/array_type.h"
|
||||
#include "src/ast/type/matrix_type.h"
|
||||
#include "src/ast/type/struct_type.h"
|
||||
#include "src/ast/type/vector_type.h"
|
||||
#include "src/reader/spirv/parser_impl.h"
|
||||
#include "src/reader/spirv/parser_impl_test_helper.h"
|
||||
#include "src/reader/spirv/spirv_tools_helpers_test.h"
|
||||
#include "src/type_manager.h"
|
||||
|
||||
namespace tint {
|
||||
namespace reader {
|
||||
namespace spirv {
|
||||
namespace {
|
||||
|
||||
using ::testing::HasSubstr;
|
||||
|
||||
TEST_F(SpvParserTest, NamedTypes_AnonStruct) {
|
||||
auto p = parser(test::Assemble(R"(
|
||||
%uint = OpTypeInt 32 0
|
||||
%s = OpTypeStruct %uint %uint
|
||||
)"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_THAT(p->module().to_str(), HasSubstr("S -> __struct_"));
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest, NamedTypes_NamedStruct) {
|
||||
auto p = parser(test::Assemble(R"(
|
||||
OpName %s "mystruct"
|
||||
%uint = OpTypeInt 32 0
|
||||
%s = OpTypeStruct %uint %uint
|
||||
)"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_THAT(p->module().to_str(), HasSubstr("mystruct -> __struct_"));
|
||||
}
|
||||
|
||||
// TODO(dneto): Enable this when array types can have ArrayStride
|
||||
TEST_F(SpvParserTest, DISABLED_NamedTypes_AnonArrayWithDecoration) {
|
||||
auto p = parser(test::Assemble(R"(
|
||||
OpDecorate %arr ArrayStride 16
|
||||
%uint = OpTypeInt 32 0
|
||||
%uint_3 = OpConstant %uint 3
|
||||
%arr = OpTypeArray %uint %uint_3
|
||||
)"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_THAT(p->module().to_str(), HasSubstr("Arr -> __array__u32"));
|
||||
}
|
||||
|
||||
// TODO(dneto): Should we make an alias for an un-decoratrd array with
|
||||
// an OpName?
|
||||
|
||||
TEST_F(SpvParserTest, NamedTypes_AnonRTArray) {
|
||||
auto p = parser(test::Assemble(R"(
|
||||
%uint = OpTypeInt 32 0
|
||||
%arr = OpTypeRuntimeArray %uint
|
||||
)"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_THAT(p->module().to_str(), HasSubstr("RTArr -> __array__u32"));
|
||||
}
|
||||
|
||||
TEST_F(SpvParserTest, NamedTypes_NamedRTArray) {
|
||||
auto p = parser(test::Assemble(R"(
|
||||
OpName %arr "myrtarr"
|
||||
%uint = OpTypeInt 32 0
|
||||
%arr = OpTypeRuntimeArray %uint
|
||||
)"));
|
||||
EXPECT_TRUE(p->BuildAndParseInternalModule());
|
||||
EXPECT_THAT(p->module().to_str(), HasSubstr("myrtarr -> __array__u32"));
|
||||
}
|
||||
|
||||
// TODO(dneto): Handle arrays sized by a spec constant.
|
||||
// Blocked by crbug.com/tint/32
|
||||
|
||||
} // namespace
|
||||
} // namespace spirv
|
||||
} // namespace reader
|
||||
} // namespace tint
|
Loading…
x
Reference in New Issue
Block a user