From 45f1832f111c5c831aac736224184c92c8f29eea Mon Sep 17 00:00:00 2001 From: David Neto Date: Fri, 29 Jan 2021 21:32:11 +0000 Subject: [PATCH] spirv-reader: support OpVectorInsertDynamic Change-Id: I30b9ad14faf921c3ec0bf47729480d4f7d37f561 Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/39161 Commit-Queue: David Neto Auto-Submit: David Neto Reviewed-by: dan sinclair --- src/reader/spirv/function.cc | 46 ++++++++++++++++- src/reader/spirv/function.h | 6 +++ src/reader/spirv/function_composite_test.cc | 55 +++++++++++++++++++++ 3 files changed, 106 insertions(+), 1 deletion(-) diff --git a/src/reader/spirv/function.cc b/src/reader/spirv/function.cc index fd3aff38b9..e5ede5fdfa 100644 --- a/src/reader/spirv/function.cc +++ b/src/reader/spirv/function.cc @@ -3021,6 +3021,10 @@ bool FunctionEmitter::EmitStatement(const spvtools::opt::Instruction& inst) { // Synthesize an outer product expression in its own statement. return EmitConstDefOrWriteToHoistedVar(inst, MakeOuterProduct(inst)); + case SpvOpVectorInsertDynamic: + // Synthesize a vector insertion in its own statements. + return MakeVectorInsertDynamic(inst); + case SpvOpFunctionCall: return EmitFunctionCall(inst); @@ -3171,7 +3175,6 @@ TypedExpression FunctionEmitter::MaybeEmitCombinatorialValue( // OpGenericCastToPtrExplicit // Not in Vulkan // // OpArrayLength - // OpVectorInsertDynamic // OpCompositeInsert return {}; @@ -4646,6 +4649,47 @@ TypedExpression FunctionEmitter::MakeOuterProduct( 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( + Source{}, registered_temp_name, ast::StorageClass::kFunction, ast_type, + false, src_vector.expr, ast::VariableDecorationList{}); + AddStatement(create(Source{}, temp_var)); + + auto* lhs = create( + Source{}, create(registered_temp_name), + index.expr); + + AddStatement(create(Source{}, lhs, component.expr)); + + return EmitConstDefinition( + inst, + {ast_type, create(registered_temp_name)}); +} + FunctionEmitter::FunctionDeclaration::FunctionDeclaration() = default; FunctionEmitter::FunctionDeclaration::~FunctionDeclaration() = default; diff --git a/src/reader/spirv/function.h b/src/reader/spirv/function.h index eaafa6852f..5eff0dfbf3 100644 --- a/src/reader/spirv/function.h +++ b/src/reader/spirv/function.h @@ -860,6 +860,12 @@ class FunctionEmitter { /// @returns an expression 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 /// the image operand to the given instruction. /// @param inst the SPIR-V instruction diff --git a/src/reader/spirv/function_composite_test.cc b/src/reader/spirv/function_composite_test.cc index e5ff9b499d..adff130cce 100644 --- a/src/reader/spirv/function_composite_test.cc +++ b/src/reader/spirv/function_composite_test.cc @@ -32,6 +32,11 @@ using ::testing::HasSubstr; std::string Preamble() { return R"( + OpCapability Shader + OpMemoryModel Logical Simple + OpEntryPoint GLCompute %100 "main" + OpExecutionMode %100 LocalSize 1 1 1 + %void = OpTypeVoid %voidfn = OpTypeFunction %void @@ -864,6 +869,56 @@ TEST_F(SpvParserTest_VectorExtractDynamic, UnsignedIndex) { })")) << 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 spirv } // namespace reader