spirv-reader: support OpArrayLength
Fixed: tint:431 Change-Id: I727ca8200118e0b93b42c5f7d9e97bc4afd97830 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/36460 Commit-Queue: David Neto <dneto@google.com> Commit-Queue: Ben Clayton <bclayton@google.com> Auto-Submit: David Neto <dneto@google.com> Reviewed-by: Ben Clayton <bclayton@google.com>
This commit is contained in:
parent
9894867678
commit
6cad63c2ad
|
@ -3143,6 +3143,10 @@ TypedExpression FunctionEmitter::MaybeEmitCombinatorialValue(
|
||||||
return MakeSimpleSelect(inst);
|
return MakeSimpleSelect(inst);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opcode == SpvOpArrayLength) {
|
||||||
|
return MakeArrayLength(inst);
|
||||||
|
}
|
||||||
|
|
||||||
// builtin readonly function
|
// builtin readonly function
|
||||||
// glsl.std.450 readonly function
|
// glsl.std.450 readonly function
|
||||||
|
|
||||||
|
@ -4490,6 +4494,45 @@ TypedExpression FunctionEmitter::ToSignedIfUnsigned(TypedExpression value) {
|
||||||
return ToI32(value);
|
return ToI32(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TypedExpression FunctionEmitter::MakeArrayLength(
|
||||||
|
const spvtools::opt::Instruction& inst) {
|
||||||
|
if (inst.NumInOperands() != 2) {
|
||||||
|
// Binary parsing will fail on this anyway.
|
||||||
|
Fail() << "invalid array length: requires 2 operands: "
|
||||||
|
<< inst.PrettyPrint();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
const auto struct_ptr_id = inst.GetSingleWordInOperand(0);
|
||||||
|
const auto field_index = inst.GetSingleWordInOperand(1);
|
||||||
|
const auto struct_ptr_type_id =
|
||||||
|
def_use_mgr_->GetDef(struct_ptr_id)->type_id();
|
||||||
|
// Trace through the pointer type to get to the struct type.
|
||||||
|
const auto struct_type_id =
|
||||||
|
def_use_mgr_->GetDef(struct_ptr_type_id)->GetSingleWordInOperand(1);
|
||||||
|
const auto field_name = namer_.GetMemberName(struct_type_id, field_index);
|
||||||
|
if (field_name.empty()) {
|
||||||
|
Fail() << "struct index out of bounds for array length: "
|
||||||
|
<< inst.PrettyPrint();
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* member_ident = create<ast::IdentifierExpression>(
|
||||||
|
Source{}, ast_module_.RegisterSymbol(field_name), field_name);
|
||||||
|
auto* member_access = create<ast::MemberAccessorExpression>(
|
||||||
|
Source{}, MakeExpression(struct_ptr_id).expr, member_ident);
|
||||||
|
|
||||||
|
// Generate the intrinsic function call.
|
||||||
|
std::string call_ident_str = "arrayLength";
|
||||||
|
auto* call_ident = create<ast::IdentifierExpression>(
|
||||||
|
Source{}, ast_module_.RegisterSymbol(call_ident_str), call_ident_str);
|
||||||
|
call_ident->set_intrinsic(ast::Intrinsic::kArrayLength);
|
||||||
|
|
||||||
|
ast::ExpressionList params{member_access};
|
||||||
|
auto* call_expr =
|
||||||
|
create<ast::CallExpression>(Source{}, call_ident, std::move(params));
|
||||||
|
|
||||||
|
return {parser_impl_.ConvertType(inst.type_id()), call_expr};
|
||||||
|
}
|
||||||
|
|
||||||
FunctionEmitter::FunctionDeclaration::FunctionDeclaration() = default;
|
FunctionEmitter::FunctionDeclaration::FunctionDeclaration() = default;
|
||||||
FunctionEmitter::FunctionDeclaration::~FunctionDeclaration() = default;
|
FunctionEmitter::FunctionDeclaration::~FunctionDeclaration() = default;
|
||||||
|
|
||||||
|
|
|
@ -834,6 +834,11 @@ class FunctionEmitter {
|
||||||
/// @returns an expression
|
/// @returns an expression
|
||||||
TypedExpression MakeIntrinsicCall(const spvtools::opt::Instruction& inst);
|
TypedExpression MakeIntrinsicCall(const spvtools::opt::Instruction& inst);
|
||||||
|
|
||||||
|
/// Returns an expression for a SPIR-V OpArrayLength instruction.
|
||||||
|
/// @param inst the SPIR-V instruction
|
||||||
|
/// @returns an expression
|
||||||
|
TypedExpression MakeArrayLength(const spvtools::opt::Instruction& inst);
|
||||||
|
|
||||||
/// Emits a texture builtin function call for a SPIR-V instruction that
|
/// Emits a texture builtin function call for a SPIR-V instruction that
|
||||||
/// accesses an image or sampled image.
|
/// accesses an image or sampled image.
|
||||||
/// @param inst the SPIR-V instruction
|
/// @param inst the SPIR-V instruction
|
||||||
|
|
|
@ -1011,6 +1011,69 @@ TEST_F(SpvParserTest, DISABLED_RemapStorageBuffer_ThroughFunctionParameter) {
|
||||||
// TODO(dneto): Blocked on OpFunctionCall support.
|
// TODO(dneto): Blocked on OpFunctionCall support.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string RuntimeArrayPreamble() {
|
||||||
|
return R"(
|
||||||
|
OpName %myvar "myvar"
|
||||||
|
OpMemberName %struct 0 "first"
|
||||||
|
OpMemberName %struct 1 "rtarr"
|
||||||
|
|
||||||
|
OpDecorate %struct Block
|
||||||
|
OpMemberDecorate %struct 0 Offset 0
|
||||||
|
OpMemberDecorate %struct 1 Offset 4
|
||||||
|
OpDecorate %arr ArrayStride 4
|
||||||
|
|
||||||
|
%void = OpTypeVoid
|
||||||
|
%voidfn = OpTypeFunction %void
|
||||||
|
%uint = OpTypeInt 32 0
|
||||||
|
|
||||||
|
%uint_0 = OpConstant %uint 0
|
||||||
|
%uint_1 = OpConstant %uint 1
|
||||||
|
|
||||||
|
%arr = OpTypeRuntimeArray %uint
|
||||||
|
%struct = OpTypeStruct %uint %arr
|
||||||
|
%ptr_struct = OpTypePointer StorageBuffer %struct
|
||||||
|
%ptr_uint = OpTypePointer StorageBuffer %uint
|
||||||
|
|
||||||
|
%myvar = OpVariable %ptr_struct StorageBuffer
|
||||||
|
)";
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest, ArrayLength) {
|
||||||
|
const auto assembly = RuntimeArrayPreamble() + R"(
|
||||||
|
|
||||||
|
%100 = OpFunction %void None %voidfn
|
||||||
|
|
||||||
|
%entry = OpLabel
|
||||||
|
%1 = OpArrayLength %uint %myvar 1
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
auto p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModule()) << assembly << p->error();
|
||||||
|
FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
|
||||||
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
||||||
|
const auto body_str = ToString(p->get_module(), fe.ast_body());
|
||||||
|
EXPECT_THAT(body_str, HasSubstr(R"(VariableDeclStatement{
|
||||||
|
VariableConst{
|
||||||
|
x_1
|
||||||
|
none
|
||||||
|
__u32
|
||||||
|
{
|
||||||
|
Call[not set]{
|
||||||
|
Identifier[not set]{arrayLength}
|
||||||
|
(
|
||||||
|
MemberAccessor[not set]{
|
||||||
|
Identifier[not set]{myvar}
|
||||||
|
Identifier[not set]{rtarr}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)")) << body_str;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace spirv
|
} // namespace spirv
|
||||||
} // namespace reader
|
} // namespace reader
|
||||||
|
|
|
@ -78,7 +78,7 @@ class Namer {
|
||||||
/// Gets the registered name for a struct member. If no name has
|
/// Gets the registered name for a struct member. If no name has
|
||||||
/// been registered for this member, then returns the empty string.
|
/// been registered for this member, then returns the empty string.
|
||||||
/// member index is in bounds.
|
/// member index is in bounds.
|
||||||
/// @param id the SPIR-V ID of the struct
|
/// @param id the SPIR-V ID of the struct type
|
||||||
/// @param member_index the index of the member, counting from 0
|
/// @param member_index the index of the member, counting from 0
|
||||||
/// @returns the registered name for the ID, or an empty string if
|
/// @returns the registered name for the ID, or an empty string if
|
||||||
/// nothing has been registered.
|
/// nothing has been registered.
|
||||||
|
|
Loading…
Reference in New Issue