spirv-reader: support OpVectorInsertDynamic
Change-Id: I30b9ad14faf921c3ec0bf47729480d4f7d37f561 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/39161 Commit-Queue: David Neto <dneto@google.com> Auto-Submit: David Neto <dneto@google.com> Reviewed-by: dan sinclair <dsinclair@chromium.org>
This commit is contained in:
parent
3335254c1c
commit
45f1832f11
|
@ -3021,6 +3021,10 @@ bool FunctionEmitter::EmitStatement(const spvtools::opt::Instruction& inst) {
|
||||||
// Synthesize an outer product expression in its own statement.
|
// Synthesize an outer product expression in its own statement.
|
||||||
return EmitConstDefOrWriteToHoistedVar(inst, MakeOuterProduct(inst));
|
return EmitConstDefOrWriteToHoistedVar(inst, MakeOuterProduct(inst));
|
||||||
|
|
||||||
|
case SpvOpVectorInsertDynamic:
|
||||||
|
// Synthesize a vector insertion in its own statements.
|
||||||
|
return MakeVectorInsertDynamic(inst);
|
||||||
|
|
||||||
case SpvOpFunctionCall:
|
case SpvOpFunctionCall:
|
||||||
return EmitFunctionCall(inst);
|
return EmitFunctionCall(inst);
|
||||||
|
|
||||||
|
@ -3171,7 +3175,6 @@ TypedExpression FunctionEmitter::MaybeEmitCombinatorialValue(
|
||||||
// OpGenericCastToPtrExplicit // Not in Vulkan
|
// OpGenericCastToPtrExplicit // Not in Vulkan
|
||||||
//
|
//
|
||||||
// OpArrayLength
|
// OpArrayLength
|
||||||
// OpVectorInsertDynamic
|
|
||||||
// OpCompositeInsert
|
// OpCompositeInsert
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
|
@ -4646,6 +4649,47 @@ TypedExpression FunctionEmitter::MakeOuterProduct(
|
||||||
result_columns)};
|
result_columns)};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FunctionEmitter::MakeVectorInsertDynamic(
|
||||||
|
const spvtools::opt::Instruction& inst) {
|
||||||
|
// For
|
||||||
|
// %result = OpVectorInsertDynamic %type %src_vector %component %index
|
||||||
|
// generate statements like this:
|
||||||
|
//
|
||||||
|
// var temp : type = src_vector;
|
||||||
|
// temp[index] = component;
|
||||||
|
// const result : type = temp;
|
||||||
|
//
|
||||||
|
// Then use result everywhere the original SPIR-V id is used. Using a const
|
||||||
|
// like this avoids constantly reloading the value many times.
|
||||||
|
|
||||||
|
auto* ast_type = parser_impl_.ConvertType(inst.type_id());
|
||||||
|
auto src_vector = MakeOperand(inst, 0);
|
||||||
|
auto component = MakeOperand(inst, 1);
|
||||||
|
auto index = MakeOperand(inst, 2);
|
||||||
|
|
||||||
|
// Synthesize the temporary variable.
|
||||||
|
// It doesn't correspond to a SPIR-V ID, so we don't use the ordinary
|
||||||
|
// API in parser_impl_.
|
||||||
|
auto result_name = namer_.Name(inst.result_id());
|
||||||
|
auto temp_name = namer_.MakeDerivedName(result_name);
|
||||||
|
auto registered_temp_name = builder_.Symbols().Register(temp_name);
|
||||||
|
|
||||||
|
auto* temp_var = create<ast::Variable>(
|
||||||
|
Source{}, registered_temp_name, ast::StorageClass::kFunction, ast_type,
|
||||||
|
false, src_vector.expr, ast::VariableDecorationList{});
|
||||||
|
AddStatement(create<ast::VariableDeclStatement>(Source{}, temp_var));
|
||||||
|
|
||||||
|
auto* lhs = create<ast::ArrayAccessorExpression>(
|
||||||
|
Source{}, create<ast::IdentifierExpression>(registered_temp_name),
|
||||||
|
index.expr);
|
||||||
|
|
||||||
|
AddStatement(create<ast::AssignmentStatement>(Source{}, lhs, component.expr));
|
||||||
|
|
||||||
|
return EmitConstDefinition(
|
||||||
|
inst,
|
||||||
|
{ast_type, create<ast::IdentifierExpression>(registered_temp_name)});
|
||||||
|
}
|
||||||
|
|
||||||
FunctionEmitter::FunctionDeclaration::FunctionDeclaration() = default;
|
FunctionEmitter::FunctionDeclaration::FunctionDeclaration() = default;
|
||||||
FunctionEmitter::FunctionDeclaration::~FunctionDeclaration() = default;
|
FunctionEmitter::FunctionDeclaration::~FunctionDeclaration() = default;
|
||||||
|
|
||||||
|
|
|
@ -860,6 +860,12 @@ class FunctionEmitter {
|
||||||
/// @returns an expression
|
/// @returns an expression
|
||||||
TypedExpression MakeOuterProduct(const spvtools::opt::Instruction& inst);
|
TypedExpression MakeOuterProduct(const spvtools::opt::Instruction& inst);
|
||||||
|
|
||||||
|
/// Generates statements for a SPIR-V OpVectorInsertDynamic instruction.
|
||||||
|
/// Registers a const declaration for the result.
|
||||||
|
/// @param inst the SPIR-V instruction
|
||||||
|
/// @returns an expression
|
||||||
|
bool MakeVectorInsertDynamic(const spvtools::opt::Instruction& inst);
|
||||||
|
|
||||||
/// Get the SPIR-V instruction for the image memory object declaration for
|
/// Get the SPIR-V instruction for the image memory object declaration for
|
||||||
/// the image operand to the given instruction.
|
/// the image operand to the given instruction.
|
||||||
/// @param inst the SPIR-V instruction
|
/// @param inst the SPIR-V instruction
|
||||||
|
|
|
@ -32,6 +32,11 @@ using ::testing::HasSubstr;
|
||||||
|
|
||||||
std::string Preamble() {
|
std::string Preamble() {
|
||||||
return R"(
|
return R"(
|
||||||
|
OpCapability Shader
|
||||||
|
OpMemoryModel Logical Simple
|
||||||
|
OpEntryPoint GLCompute %100 "main"
|
||||||
|
OpExecutionMode %100 LocalSize 1 1 1
|
||||||
|
|
||||||
%void = OpTypeVoid
|
%void = OpTypeVoid
|
||||||
%voidfn = OpTypeFunction %void
|
%voidfn = OpTypeFunction %void
|
||||||
|
|
||||||
|
@ -864,6 +869,56 @@ TEST_F(SpvParserTest_VectorExtractDynamic, UnsignedIndex) {
|
||||||
})")) << got;
|
})")) << got;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
using SpvParserTest_VectorInsertDynamic = SpvParserTest;
|
||||||
|
|
||||||
|
TEST_F(SpvParserTest_VectorExtractDynamic, Sample) {
|
||||||
|
const auto assembly = Preamble() + R"(
|
||||||
|
%100 = OpFunction %void None %voidfn
|
||||||
|
%entry = OpLabel
|
||||||
|
%1 = OpCopyObject %v2uint %v2uint_3_4
|
||||||
|
%2 = OpCopyObject %uint %uint_3
|
||||||
|
%3 = OpCopyObject %int %int_1
|
||||||
|
%10 = OpVectorInsertDynamic %v2uint %1 %2 %3
|
||||||
|
OpReturn
|
||||||
|
OpFunctionEnd
|
||||||
|
)";
|
||||||
|
|
||||||
|
auto p = parser(test::Assemble(assembly));
|
||||||
|
ASSERT_TRUE(p->BuildAndParseInternalModuleExceptFunctions()) << assembly;
|
||||||
|
FunctionEmitter fe(p.get(), *spirv_function(p.get(), 100));
|
||||||
|
EXPECT_TRUE(fe.EmitBody()) << p->error();
|
||||||
|
const auto got = ToString(p->builder(), fe.ast_body());
|
||||||
|
EXPECT_THAT(got, HasSubstr(R"(
|
||||||
|
VariableDeclStatement{
|
||||||
|
Variable{
|
||||||
|
x_10_1
|
||||||
|
function
|
||||||
|
__vec_2__u32
|
||||||
|
{
|
||||||
|
Identifier[not set]{x_1}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Assignment{
|
||||||
|
ArrayAccessor[not set]{
|
||||||
|
Identifier[not set]{x_10_1}
|
||||||
|
Identifier[not set]{x_3}
|
||||||
|
}
|
||||||
|
Identifier[not set]{x_2}
|
||||||
|
}
|
||||||
|
VariableDeclStatement{
|
||||||
|
VariableConst{
|
||||||
|
x_10
|
||||||
|
none
|
||||||
|
__vec_2__u32
|
||||||
|
{
|
||||||
|
Identifier[not set]{x_10_1}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})")) << got
|
||||||
|
<< assembly;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace spirv
|
} // namespace spirv
|
||||||
} // namespace reader
|
} // namespace reader
|
||||||
|
|
Loading…
Reference in New Issue