Browse Source

Updated spirv-tools.

Бранимир Караџић 2 years ago
parent
commit
3d390308dc

+ 1 - 1
3rdparty/spirv-tools/include/generated/build-version.inc

@@ -1 +1 @@
-"v2022.5-dev", "SPIRV-Tools v2022.5-dev 466c6a4e95f6c2ebd61040d6fe2f6418e45b7e20"
+"v2023.2-dev", "SPIRV-Tools v2023.2-dev v2022.4-89-g4ee97c03"

+ 1 - 2
3rdparty/spirv-tools/include/generated/core.insts-unified1.inc

@@ -95,7 +95,6 @@ static const spvtools::Extension pygen_variable_exts_SPV_KHR_ray_query[] = {spvt
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_ray_tracing[] = {spvtools::Extension::kSPV_KHR_ray_tracing};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_ray_tracingSPV_KHR_ray_query[] = {spvtools::Extension::kSPV_KHR_ray_tracing, spvtools::Extension::kSPV_KHR_ray_query};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_shader_ballot[] = {spvtools::Extension::kSPV_KHR_shader_ballot};
-static const spvtools::Extension pygen_variable_exts_SPV_KHR_shader_clock[] = {spvtools::Extension::kSPV_KHR_shader_clock};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_subgroup_vote[] = {spvtools::Extension::kSPV_KHR_subgroup_vote};
 static const spvtools::Extension pygen_variable_exts_SPV_KHR_terminate_invocation[] = {spvtools::Extension::kSPV_KHR_terminate_invocation};
 static const spvtools::Extension pygen_variable_exts_SPV_NV_cooperative_matrix[] = {spvtools::Extension::kSPV_NV_cooperative_matrix};
@@ -494,7 +493,7 @@ static const spv_opcode_desc_t kOpcodeTableEntries[] = {
   {"GroupSMaxNonUniformAMD", spv::Op::OpGroupSMaxNonUniformAMD, 1, pygen_variable_caps_Groups, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID, SPV_OPERAND_TYPE_GROUP_OPERATION, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_AMD_shader_ballot, 0xffffffffu, 0xffffffffu},
   {"FragmentMaskFetchAMD", spv::Op::OpFragmentMaskFetchAMD, 1, pygen_variable_caps_FragmentMaskAMD, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_AMD_shader_fragment_mask, 0xffffffffu, 0xffffffffu},
   {"FragmentFetchAMD", spv::Op::OpFragmentFetchAMD, 1, pygen_variable_caps_FragmentMaskAMD, 5, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_AMD_shader_fragment_mask, 0xffffffffu, 0xffffffffu},
-  {"ReadClockKHR", spv::Op::OpReadClockKHR, 1, pygen_variable_caps_ShaderClockKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_KHR_shader_clock, 0xffffffffu, 0xffffffffu},
+  {"ReadClockKHR", spv::Op::OpReadClockKHR, 1, pygen_variable_caps_ShaderClockKHR, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_SCOPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
   {"HitObjectRecordHitMotionNV", spv::Op::OpHitObjectRecordHitMotionNV, 2, pygen_variable_caps_ShaderInvocationReorderNVRayTracingMotionBlurNV, 14, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 0, nullptr, 0xffffffffu, 0xffffffffu},
   {"HitObjectRecordHitWithIndexMotionNV", spv::Op::OpHitObjectRecordHitWithIndexMotionNV, 2, pygen_variable_caps_ShaderInvocationReorderNVRayTracingMotionBlurNV, 13, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 0, nullptr, 0xffffffffu, 0xffffffffu},
   {"HitObjectRecordMissMotionNV", spv::Op::OpHitObjectRecordMissMotionNV, 2, pygen_variable_caps_ShaderInvocationReorderNVRayTracingMotionBlurNV, 7, {SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 0, 0, 0, nullptr, 0xffffffffu, 0xffffffffu},

File diff suppressed because it is too large
+ 2 - 0
3rdparty/spirv-tools/include/generated/enum_string_mapping.inc


+ 1 - 0
3rdparty/spirv-tools/include/generated/extension_enum.inc

@@ -35,6 +35,7 @@ kSPV_INTEL_debug_module,
 kSPV_INTEL_device_side_avc_motion_estimation,
 kSPV_INTEL_float_controls2,
 kSPV_INTEL_fp_fast_math_mode,
+kSPV_INTEL_fpga_argument_interfaces,
 kSPV_INTEL_fpga_buffer_location,
 kSPV_INTEL_fpga_cluster_attributes,
 kSPV_INTEL_fpga_dsp_control,

+ 14 - 2
3rdparty/spirv-tools/include/generated/operand.kinds-unified1.inc

@@ -15,6 +15,7 @@ static const spv::Capability pygen_variable_caps_DeviceGroup[] = {spv::Capabilit
 static const spv::Capability pygen_variable_caps_DrawParameters[] = {spv::Capability::DrawParameters};
 static const spv::Capability pygen_variable_caps_DrawParametersMeshShadingNVMeshShadingEXT[] = {spv::Capability::DrawParameters, spv::Capability::MeshShadingNV, spv::Capability::MeshShadingEXT};
 static const spv::Capability pygen_variable_caps_FPFastMathModeINTEL[] = {spv::Capability::FPFastMathModeINTEL};
+static const spv::Capability pygen_variable_caps_FPGAArgumentInterfacesINTEL[] = {spv::Capability::FPGAArgumentInterfacesINTEL};
 static const spv::Capability pygen_variable_caps_FPGABufferLocationINTEL[] = {spv::Capability::FPGABufferLocationINTEL};
 static const spv::Capability pygen_variable_caps_FPGAClusterAttributesINTEL[] = {spv::Capability::FPGAClusterAttributesINTEL};
 static const spv::Capability pygen_variable_caps_FPGADSPControlINTEL[] = {spv::Capability::FPGADSPControlINTEL};
@@ -164,6 +165,7 @@ static const spvtools::Extension pygen_variable_exts_SPV_INTEL_debug_module[] =
 static const spvtools::Extension pygen_variable_exts_SPV_INTEL_device_side_avc_motion_estimation[] = {spvtools::Extension::kSPV_INTEL_device_side_avc_motion_estimation};
 static const spvtools::Extension pygen_variable_exts_SPV_INTEL_float_controls2[] = {spvtools::Extension::kSPV_INTEL_float_controls2};
 static const spvtools::Extension pygen_variable_exts_SPV_INTEL_fp_fast_math_mode[] = {spvtools::Extension::kSPV_INTEL_fp_fast_math_mode};
+static const spvtools::Extension pygen_variable_exts_SPV_INTEL_fpga_argument_interfaces[] = {spvtools::Extension::kSPV_INTEL_fpga_argument_interfaces};
 static const spvtools::Extension pygen_variable_exts_SPV_INTEL_fpga_buffer_location[] = {spvtools::Extension::kSPV_INTEL_fpga_buffer_location};
 static const spvtools::Extension pygen_variable_exts_SPV_INTEL_fpga_cluster_attributes[] = {spvtools::Extension::kSPV_INTEL_fpga_cluster_attributes};
 static const spvtools::Extension pygen_variable_exts_SPV_INTEL_fpga_dsp_control[] = {spvtools::Extension::kSPV_INTEL_fpga_dsp_control};
@@ -831,7 +833,16 @@ static const spv_operand_desc_t pygen_variable_DecorationEntries[] = {
   {"FunctionFloatingPointModeINTEL", 6080, 1, pygen_variable_caps_FunctionFloatControlINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER, SPV_OPERAND_TYPE_FPOPERATION_MODE}, 0xffffffffu, 0xffffffffu},
   {"SingleElementVectorINTEL", 6085, 1, pygen_variable_caps_VectorComputeINTEL, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
   {"VectorComputeCallableFunctionINTEL", 6087, 1, pygen_variable_caps_VectorComputeINTEL, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
-  {"MediaBlockIOINTEL", 6140, 1, pygen_variable_caps_VectorComputeINTEL, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}
+  {"MediaBlockIOINTEL", 6140, 1, pygen_variable_caps_VectorComputeINTEL, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
+  {"ConduitKernelArgumentINTEL", 6175, 1, pygen_variable_caps_FPGAArgumentInterfacesINTEL, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
+  {"RegisterMapKernelArgumentINTEL", 6176, 1, pygen_variable_caps_FPGAArgumentInterfacesINTEL, 0, nullptr, {}, 0xffffffffu, 0xffffffffu},
+  {"MMHostInterfaceAddressWidthINTEL", 6177, 1, pygen_variable_caps_FPGAArgumentInterfacesINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
+  {"MMHostInterfaceDataWidthINTEL", 6178, 1, pygen_variable_caps_FPGAArgumentInterfacesINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
+  {"MMHostInterfaceLatencyINTEL", 6179, 1, pygen_variable_caps_FPGAArgumentInterfacesINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
+  {"MMHostInterfaceReadWriteModeINTEL", 6180, 1, pygen_variable_caps_FPGAArgumentInterfacesINTEL, 0, nullptr, {SPV_OPERAND_TYPE_ACCESS_QUALIFIER}, 0xffffffffu, 0xffffffffu},
+  {"MMHostInterfaceMaxBurstINTEL", 6181, 1, pygen_variable_caps_FPGAArgumentInterfacesINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
+  {"MMHostInterfaceWaitRequestINTEL", 6182, 1, pygen_variable_caps_FPGAArgumentInterfacesINTEL, 0, nullptr, {SPV_OPERAND_TYPE_LITERAL_INTEGER}, 0xffffffffu, 0xffffffffu},
+  {"StableKernelArgumentINTEL", 6183, 1, pygen_variable_caps_FPGAArgumentInterfacesINTEL, 0, nullptr, {}, 0xffffffffu, 0xffffffffu}
 };
 
 static const spv_operand_desc_t pygen_variable_BuiltInEntries[] = {
@@ -1104,7 +1115,7 @@ static const spv_operand_desc_t pygen_variable_CapabilityEntries[] = {
   {"StencilExportEXT", 5013, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_EXT_shader_stencil_export, {}, 0xffffffffu, 0xffffffffu},
   {"ImageReadWriteLodAMD", 5015, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_AMD_shader_image_load_store_lod, {}, 0xffffffffu, 0xffffffffu},
   {"Int64ImageEXT", 5016, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_EXT_shader_image_int64, {}, 0xffffffffu, 0xffffffffu},
-  {"ShaderClockKHR", 5055, 1, pygen_variable_caps_Shader, 1, pygen_variable_exts_SPV_KHR_shader_clock, {}, 0xffffffffu, 0xffffffffu},
+  {"ShaderClockKHR", 5055, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_shader_clock, {}, 0xffffffffu, 0xffffffffu},
   {"SampleMaskOverrideCoverageNV", 5249, 1, pygen_variable_caps_SampleRateShading, 1, pygen_variable_exts_SPV_NV_sample_mask_override_coverage, {}, 0xffffffffu, 0xffffffffu},
   {"GeometryShaderPassthroughNV", 5251, 1, pygen_variable_caps_Geometry, 1, pygen_variable_exts_SPV_NV_geometry_shader_passthrough, {}, 0xffffffffu, 0xffffffffu},
   {"ShaderViewportIndexLayerEXT", 5254, 1, pygen_variable_caps_MultiViewport, 2, pygen_variable_exts_SPV_EXT_shader_viewport_index_layerSPV_NV_viewport_array2, {}, 0xffffffffu, 0xffffffffu},
@@ -1226,6 +1237,7 @@ static const spv_operand_desc_t pygen_variable_CapabilityEntries[] = {
   {"AtomicFloat16AddEXT", 6095, 0, nullptr, 1, pygen_variable_exts_SPV_EXT_shader_atomic_float16_add, {}, 0xffffffffu, 0xffffffffu},
   {"DebugInfoModuleINTEL", 6114, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_debug_module, {}, 0xffffffffu, 0xffffffffu},
   {"SplitBarrierINTEL", 6141, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_split_barrier, {}, 0xffffffffu, 0xffffffffu},
+  {"FPGAArgumentInterfacesINTEL", 6174, 0, nullptr, 1, pygen_variable_exts_SPV_INTEL_fpga_argument_interfaces, {}, 0xffffffffu, 0xffffffffu},
   {"GroupUniformArithmeticKHR", 6400, 0, nullptr, 1, pygen_variable_exts_SPV_KHR_uniform_group_instructions, {}, 0xffffffffu, 0xffffffffu}
 };
 

+ 59 - 0
3rdparty/spirv-tools/include/spirv-tools/libspirv.h

@@ -442,6 +442,8 @@ typedef struct spv_reducer_options_t spv_reducer_options_t;
 
 typedef struct spv_fuzzer_options_t spv_fuzzer_options_t;
 
+typedef struct spv_optimizer_t spv_optimizer_t;
+
 // Type Definitions
 
 typedef spv_const_binary_t* spv_const_binary;
@@ -901,6 +903,63 @@ SPIRV_TOOLS_EXPORT spv_result_t spvBinaryParse(
     const size_t num_words, spv_parsed_header_fn_t parse_header,
     spv_parsed_instruction_fn_t parse_instruction, spv_diagnostic* diagnostic);
 
+// The optimizer interface.
+
+// A pointer to a function that accepts a log message from an optimizer.
+typedef void (*spv_message_consumer)(
+    spv_message_level_t, const char*, const spv_position_t*, const char*);
+
+// Creates and returns an optimizer object.  This object must be passed to
+// optimizer APIs below and is valid until passed to spvOptimizerDestroy.
+SPIRV_TOOLS_EXPORT spv_optimizer_t* spvOptimizerCreate(spv_target_env env);
+
+// Destroys the given optimizer object.
+SPIRV_TOOLS_EXPORT void spvOptimizerDestroy(spv_optimizer_t* optimizer);
+
+// Sets an spv_message_consumer on an optimizer object.
+SPIRV_TOOLS_EXPORT void spvOptimizerSetMessageConsumer(
+    spv_optimizer_t* optimizer, spv_message_consumer consumer);
+
+// Registers passes that attempt to legalize the generated code.
+SPIRV_TOOLS_EXPORT void spvOptimizerRegisterLegalizationPasses(
+    spv_optimizer_t* optimizer);
+
+// Registers passes that attempt to improve performance of generated code.
+SPIRV_TOOLS_EXPORT void spvOptimizerRegisterPerformancePasses(
+    spv_optimizer_t* optimizer);
+
+// Registers passes that attempt to improve the size of generated code.
+SPIRV_TOOLS_EXPORT void spvOptimizerRegisterSizePasses(
+    spv_optimizer_t* optimizer);
+
+// Registers a pass specified by a flag in an optimizer object.
+SPIRV_TOOLS_EXPORT bool spvOptimizerRegisterPassFromFlag(
+    spv_optimizer_t* optimizer, const char* flag);
+
+// Registers passes specified by length number of flags in an optimizer object.
+SPIRV_TOOLS_EXPORT bool spvOptimizerRegisterPassesFromFlags(
+    spv_optimizer_t* optimizer, const char** flags, const size_t flag_count);
+
+// Optimizes the SPIR-V code of size |word_count| pointed to by |binary| and
+// returns an optimized spv_binary in |optimized_binary|.
+//
+// Returns SPV_SUCCESS on successful optimization, whether or not the module is
+// modified.  Returns an SPV_ERROR_* if the module fails to validate or if
+// errors occur when processing using any of the registered passes.  In that
+// case, no further passes are executed and the |optimized_binary| contents may
+// be invalid.
+//
+// By default, the binary is validated before any transforms are performed,
+// and optionally after each transform.  Validation uses SPIR-V spec rules
+// for the SPIR-V version named in the binary's header (at word offset 1).
+// Additionally, if the target environment is a client API (such as
+// Vulkan 1.1), then validate for that client API version, to the extent
+// that it is verifiable from data in the binary itself, or from the
+// validator options set on the optimizer options.
+SPIRV_TOOLS_EXPORT spv_result_t spvOptimizerRun(
+    spv_optimizer_t* optimizer, const uint32_t* binary, const size_t word_count,
+    spv_binary* optimized_binary, const spv_optimizer_options options);
+
 #ifdef __cplusplus
 }
 #endif

+ 21 - 16
3rdparty/spirv-tools/source/opt/inst_bindless_check_pass.cpp

@@ -497,8 +497,8 @@ uint32_t InstBindlessCheckPass::GenLastByteIdx(RefAnalysis* ref,
     if (sum_id == 0)
       sum_id = curr_offset_id;
     else {
-      Instruction* sum_inst = builder->AddBinaryOp(GetUintId(), spv::Op::OpIAdd,
-                                                   sum_id, curr_offset_id);
+      Instruction* sum_inst =
+          builder->AddIAdd(GetUintId(), sum_id, curr_offset_id);
       sum_id = sum_inst->result_id();
     }
     ++ac_in_idx;
@@ -507,8 +507,7 @@ uint32_t InstBindlessCheckPass::GenLastByteIdx(RefAnalysis* ref,
   uint32_t bsize = ByteSize(curr_ty_id, matrix_stride, col_major, in_matrix);
   uint32_t last = bsize - 1;
   uint32_t last_id = builder->GetUintConstantId(last);
-  Instruction* sum_inst =
-      builder->AddBinaryOp(GetUintId(), spv::Op::OpIAdd, sum_id, last_id);
+  Instruction* sum_inst = builder->AddIAdd(GetUintId(), sum_id, last_id);
   return sum_inst->result_id();
 }
 
@@ -536,6 +535,8 @@ void InstBindlessCheckPass::GenCheckCode(
       new BasicBlock(std::move(valid_label)));
   builder.SetInsertPoint(&*new_blk_ptr);
   uint32_t new_ref_id = CloneOriginalReference(ref, &builder);
+  uint32_t null_id = 0;
+  uint32_t ref_type_id = ref->ref_inst->type_id();
   (void)builder.AddBranch(merge_blk_id);
   new_blocks->push_back(std::move(new_blk_ptr));
   // Gen invalid block
@@ -563,10 +564,23 @@ void InstBindlessCheckPass::GenCheckCode(
     GenDebugStreamWrite(uid2offset_[ref->ref_inst->unique_id()], stage_idx,
                         {error_id, u_index_id, u_length_id}, &builder);
   }
+  // Generate a ConstantNull, converting to uint64 if the type cannot be a null.
+  if (new_ref_id != 0) {
+    analysis::TypeManager* type_mgr = context()->get_type_mgr();
+    analysis::Type* ref_type = type_mgr->GetType(ref_type_id);
+    if (ref_type->AsPointer() != nullptr) {
+      context()->AddCapability(spv::Capability::Int64);
+      uint32_t null_u64_id = GetNullId(GetUint64Id());
+      Instruction* null_ptr_inst = builder.AddUnaryOp(
+          ref_type_id, spv::Op::OpConvertUToPtr, null_u64_id);
+      null_id = null_ptr_inst->result_id();
+    } else {
+      null_id = GetNullId(ref_type_id);
+    }
+  }
   // Remember last invalid block id
   uint32_t last_invalid_blk_id = new_blk_ptr->GetLabelInst()->result_id();
   // Gen zero for invalid  reference
-  uint32_t ref_type_id = ref->ref_inst->type_id();
   (void)builder.AddBranch(merge_blk_id);
   new_blocks->push_back(std::move(new_blk_ptr));
   // Gen merge block
@@ -577,8 +591,7 @@ void InstBindlessCheckPass::GenCheckCode(
   // reference.
   if (new_ref_id != 0) {
     Instruction* phi_inst = builder.AddPhi(
-        ref_type_id, {new_ref_id, valid_blk_id, GetNullId(ref_type_id),
-                      last_invalid_blk_id});
+        ref_type_id, {new_ref_id, valid_blk_id, null_id, last_invalid_blk_id});
     context()->ReplaceAllUsesWith(ref->ref_inst->result_id(),
                                   phi_inst->result_id());
   }
@@ -734,15 +747,7 @@ void InstBindlessCheckPass::GenTexBuffCheckCode(
   if (image_ty_inst->GetSingleWordInOperand(kSpvTypeImageArrayed) != 0) return;
   if (image_ty_inst->GetSingleWordInOperand(kSpvTypeImageMS) != 0) return;
   // Enable ImageQuery Capability if not yet enabled
-  if (!get_feature_mgr()->HasCapability(spv::Capability::ImageQuery)) {
-    std::unique_ptr<Instruction> cap_image_query_inst(
-        new Instruction(context(), spv::Op::OpCapability, 0, 0,
-                        std::initializer_list<Operand>{
-                            {SPV_OPERAND_TYPE_CAPABILITY,
-                             {uint32_t(spv::Capability::ImageQuery)}}}));
-    get_def_use_mgr()->AnalyzeInstDefUse(&*cap_image_query_inst);
-    context()->AddCapability(std::move(cap_image_query_inst));
-  }
+  context()->AddCapability(spv::Capability::ImageQuery);
   // Move original block's preceding instructions into first new block
   std::unique_ptr<BasicBlock> new_blk_ptr;
   MovePreludeCode(ref_inst_itr, ref_block_itr, &new_blk_ptr);

+ 9 - 29
3rdparty/spirv-tools/source/opt/inst_buff_addr_check_pass.cpp

@@ -257,9 +257,7 @@ uint32_t InstBuffAddrCheckPass::GetSearchAndTestFuncId() {
     uint32_t hdr_blk_id = TakeNextId();
     // Branch to search loop header
     std::unique_ptr<Instruction> hdr_blk_label(NewLabel(hdr_blk_id));
-    (void)builder.AddInstruction(MakeUnique<Instruction>(
-        context(), spv::Op::OpBranch, 0, 0,
-        std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {hdr_blk_id}}}));
+    (void)builder.AddBranch(hdr_blk_id);
     input_func->AddBasicBlock(std::move(first_blk_ptr));
     // Linear search loop header block
     // TODO(greg-lunarg): Implement binary search
@@ -293,17 +291,10 @@ uint32_t InstBuffAddrCheckPass::GetSearchAndTestFuncId() {
     uint32_t bound_test_blk_id = TakeNextId();
     std::unique_ptr<Instruction> bound_test_blk_label(
         NewLabel(bound_test_blk_id));
-    (void)builder.AddInstruction(MakeUnique<Instruction>(
-        context(), spv::Op::OpLoopMerge, 0, 0,
-        std::initializer_list<Operand>{
-            {SPV_OPERAND_TYPE_ID, {bound_test_blk_id}},
-            {SPV_OPERAND_TYPE_ID, {cont_blk_id}},
-            {SPV_OPERAND_TYPE_LITERAL_INTEGER,
-             {uint32_t(spv::LoopControlMask::MaskNone)}}}));
+    (void)builder.AddLoopMerge(bound_test_blk_id, cont_blk_id,
+                               uint32_t(spv::LoopControlMask::MaskNone));
     // Branch to continue/work block
-    (void)builder.AddInstruction(MakeUnique<Instruction>(
-        context(), spv::Op::OpBranch, 0, 0,
-        std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {cont_blk_id}}}));
+    (void)builder.AddBranch(cont_blk_id);
     input_func->AddBasicBlock(std::move(hdr_blk_ptr));
     // Continue/Work Block. Read next buffer pointer and break if greater
     // than ref_ptr arg.
@@ -386,10 +377,8 @@ uint32_t InstBuffAddrCheckPass::GetSearchAndTestFuncId() {
         GetBoolId(), spv::Op::OpULessThanEqual, ref_end_inst->result_id(),
         len_load_inst->result_id());
     // Return test result
-    (void)builder.AddInstruction(MakeUnique<Instruction>(
-        context(), spv::Op::OpReturnValue, 0, 0,
-        std::initializer_list<Operand>{
-            {SPV_OPERAND_TYPE_ID, {len_test_inst->result_id()}}}));
+    (void)builder.AddUnaryOp(0, spv::Op::OpReturnValue,
+                             len_test_inst->result_id());
     // Close block
     input_func->AddBasicBlock(std::move(bound_test_blk_ptr));
     // Close function and add function to module
@@ -408,14 +397,7 @@ uint32_t InstBuffAddrCheckPass::GenSearchAndTest(Instruction* ref_inst,
                                                  InstructionBuilder* builder,
                                                  uint32_t* ref_uptr_id) {
   // Enable Int64 if necessary
-  if (!get_feature_mgr()->HasCapability(spv::Capability::Int64)) {
-    std::unique_ptr<Instruction> cap_int64_inst(new Instruction(
-        context(), spv::Op::OpCapability, 0, 0,
-        std::initializer_list<Operand>{{SPV_OPERAND_TYPE_CAPABILITY,
-                                        {uint32_t(spv::Capability::Int64)}}}));
-    get_def_use_mgr()->AnalyzeInstDefUse(&*cap_int64_inst);
-    context()->AddCapability(std::move(cap_int64_inst));
-  }
+  context()->AddCapability(spv::Capability::Int64);
   // Convert reference pointer to uint64
   uint32_t ref_ptr_id = ref_inst->GetSingleWordInOperand(0);
   Instruction* ref_uptr_inst =
@@ -429,10 +411,8 @@ uint32_t InstBuffAddrCheckPass::GenSearchAndTest(Instruction* ref_inst,
   uint32_t ref_len = GetTypeLength(ref_ptr_ty_inst->GetSingleWordInOperand(1));
   uint32_t ref_len_id = builder->GetUintConstantId(ref_len);
   // Gen call to search and test function
-  const std::vector<uint32_t> args = {GetSearchAndTestFuncId(), *ref_uptr_id,
-                                      ref_len_id};
-  Instruction* call_inst =
-      builder->AddNaryOp(GetBoolId(), spv::Op::OpFunctionCall, args);
+  Instruction* call_inst = builder->AddFunctionCall(
+      GetBoolId(), GetSearchAndTestFuncId(), {*ref_uptr_id, ref_len_id});
   uint32_t retval = call_inst->result_id();
   return retval;
 }

+ 4 - 5
3rdparty/spirv-tools/source/opt/inst_debug_printf_pass.cpp

@@ -34,8 +34,8 @@ void InstDebugPrintfPass::GenOutputValues(Instruction* val_inst,
       const analysis::Type* c_ty = v_ty->element_type();
       uint32_t c_ty_id = type_mgr->GetId(c_ty);
       for (uint32_t c = 0; c < v_ty->element_count(); ++c) {
-        Instruction* c_inst = builder->AddIdLiteralOp(
-            c_ty_id, spv::Op::OpCompositeExtract, val_inst->result_id(), c);
+        Instruction* c_inst =
+            builder->AddCompositeExtract(c_ty_id, val_inst->result_id(), {c});
         GenOutputValues(c_inst, val_ids, builder);
       }
       return;
@@ -44,9 +44,8 @@ void InstDebugPrintfPass::GenOutputValues(Instruction* val_inst,
       // Select between uint32 zero or one
       uint32_t zero_id = builder->GetUintConstantId(0);
       uint32_t one_id = builder->GetUintConstantId(1);
-      Instruction* sel_inst =
-          builder->AddTernaryOp(GetUintId(), spv::Op::OpSelect,
-                                val_inst->result_id(), one_id, zero_id);
+      Instruction* sel_inst = builder->AddSelect(
+          GetUintId(), val_inst->result_id(), one_id, zero_id);
       val_ids->push_back(sel_inst->result_id());
       return;
     }

+ 186 - 171
3rdparty/spirv-tools/source/opt/instrument_pass.cpp

@@ -54,7 +54,6 @@ void InstrumentPass::MovePreludeCode(
 
 void InstrumentPass::MovePostludeCode(
     UptrVectorIterator<BasicBlock> ref_block_itr, BasicBlock* new_blk_ptr) {
-  // new_blk_ptr->reset(new BasicBlock(NewLabel(ref_block_itr->id())));
   // Move contents of original ref block.
   for (auto cii = ref_block_itr->begin(); cii != ref_block_itr->end();
        cii = ref_block_itr->begin()) {
@@ -77,21 +76,62 @@ void InstrumentPass::MovePostludeCode(
 }
 
 std::unique_ptr<Instruction> InstrumentPass::NewLabel(uint32_t label_id) {
-  std::unique_ptr<Instruction> newLabel(
-      new Instruction(context(), spv::Op::OpLabel, 0, label_id, {}));
-  get_def_use_mgr()->AnalyzeInstDefUse(&*newLabel);
-  return newLabel;
+  auto new_label =
+      MakeUnique<Instruction>(context(), spv::Op::OpLabel, 0, label_id,
+                              std::initializer_list<Operand>{});
+  get_def_use_mgr()->AnalyzeInstDefUse(&*new_label);
+  return new_label;
+}
+
+std::unique_ptr<Function> InstrumentPass::StartFunction(
+    uint32_t func_id, const analysis::Type* return_type,
+    const std::vector<const analysis::Type*>& param_types) {
+  analysis::TypeManager* type_mgr = context()->get_type_mgr();
+  analysis::Function* func_type = GetFunction(return_type, param_types);
+
+  const std::vector<Operand> operands{
+      {spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
+       {uint32_t(spv::FunctionControlMask::MaskNone)}},
+      {spv_operand_type_t::SPV_OPERAND_TYPE_ID, {type_mgr->GetId(func_type)}},
+  };
+  auto func_inst =
+      MakeUnique<Instruction>(context(), spv::Op::OpFunction,
+                              type_mgr->GetId(return_type), func_id, operands);
+  get_def_use_mgr()->AnalyzeInstDefUse(&*func_inst);
+  return MakeUnique<Function>(std::move(func_inst));
+}
+
+std::unique_ptr<Instruction> InstrumentPass::EndFunction() {
+  auto end = MakeUnique<Instruction>(context(), spv::Op::OpFunctionEnd, 0, 0,
+                                     std::initializer_list<Operand>{});
+  get_def_use_mgr()->AnalyzeInstDefUse(end.get());
+  return end;
+}
+
+std::vector<uint32_t> InstrumentPass::AddParameters(
+    Function& func, const std::vector<const analysis::Type*>& param_types) {
+  std::vector<uint32_t> param_ids;
+  param_ids.reserve(param_types.size());
+  for (const analysis::Type* param : param_types) {
+    uint32_t pid = TakeNextId();
+    param_ids.push_back(pid);
+    auto param_inst =
+        MakeUnique<Instruction>(context(), spv::Op::OpFunctionParameter,
+                                context()->get_type_mgr()->GetId(param), pid,
+                                std::initializer_list<Operand>{});
+    get_def_use_mgr()->AnalyzeInstDefUse(param_inst.get());
+    func.AddParameter(std::move(param_inst));
+  }
+  return param_ids;
 }
 
 std::unique_ptr<Instruction> InstrumentPass::NewName(
     uint32_t id, const std::string& name_str) {
-  std::unique_ptr<Instruction> new_name(new Instruction(
+  return MakeUnique<Instruction>(
       context(), spv::Op::OpName, 0, 0,
       std::initializer_list<Operand>{
           {SPV_OPERAND_TYPE_ID, {id}},
-          {SPV_OPERAND_TYPE_LITERAL_STRING, utils::MakeVector(name_str)}}));
-
-  return new_name;
+          {SPV_OPERAND_TYPE_LITERAL_STRING, utils::MakeVector(name_str)}});
 }
 
 std::unique_ptr<Instruction> InstrumentPass::NewGlobalName(
@@ -118,14 +158,12 @@ std::unique_ptr<Instruction> InstrumentPass::NewGlobalName(
 
 std::unique_ptr<Instruction> InstrumentPass::NewMemberName(
     uint32_t id, uint32_t member_index, const std::string& name_str) {
-  std::unique_ptr<Instruction> new_name(new Instruction(
+  return MakeUnique<Instruction>(
       context(), spv::Op::OpMemberName, 0, 0,
       std::initializer_list<Operand>{
           {SPV_OPERAND_TYPE_ID, {id}},
           {SPV_OPERAND_TYPE_LITERAL_INTEGER, {member_index}},
-          {SPV_OPERAND_TYPE_LITERAL_STRING, utils::MakeVector(name_str)}}));
-
-  return new_name;
+          {SPV_OPERAND_TYPE_LITERAL_STRING, utils::MakeVector(name_str)}});
 }
 
 uint32_t InstrumentPass::Gen32BitCvtCode(uint32_t val_id,
@@ -167,17 +205,15 @@ void InstrumentPass::GenDebugOutputFieldCode(uint32_t base_offset_id,
   // Cast value to 32-bit unsigned if necessary
   uint32_t val_id = GenUintCastCode(field_value_id, builder);
   // Store value
-  Instruction* data_idx_inst =
-      builder->AddBinaryOp(GetUintId(), spv::Op::OpIAdd, base_offset_id,
-                           builder->GetUintConstantId(field_offset));
+  Instruction* data_idx_inst = builder->AddIAdd(
+      GetUintId(), base_offset_id, builder->GetUintConstantId(field_offset));
   uint32_t buf_id = GetOutputBufferId();
   uint32_t buf_uint_ptr_id = GetOutputBufferPtrId();
-  Instruction* achain_inst =
-      builder->AddTernaryOp(buf_uint_ptr_id, spv::Op::OpAccessChain, buf_id,
-                            builder->GetUintConstantId(kDebugOutputDataOffset),
-                            data_idx_inst->result_id());
-  (void)builder->AddBinaryOp(0, spv::Op::OpStore, achain_inst->result_id(),
-                             val_id);
+  Instruction* achain_inst = builder->AddAccessChain(
+      buf_uint_ptr_id, buf_id,
+      {builder->GetUintConstantId(kDebugOutputDataOffset),
+       data_idx_inst->result_id()});
+  (void)builder->AddStore(achain_inst->result_id(), val_id);
 }
 
 void InstrumentPass::GenCommonStreamWriteCode(uint32_t record_sz,
@@ -202,8 +238,8 @@ void InstrumentPass::GenCommonStreamWriteCode(uint32_t record_sz,
 void InstrumentPass::GenFragCoordEltDebugOutputCode(
     uint32_t base_offset_id, uint32_t uint_frag_coord_id, uint32_t element,
     InstructionBuilder* builder) {
-  Instruction* element_val_inst = builder->AddIdLiteralOp(
-      GetUintId(), spv::Op::OpCompositeExtract, uint_frag_coord_id, element);
+  Instruction* element_val_inst =
+      builder->AddCompositeExtract(GetUintId(), uint_frag_coord_id, {element});
   GenDebugOutputFieldCode(base_offset_id, kInstFragOutFragCoordX + element,
                           element_val_inst->result_id(), builder);
 }
@@ -212,8 +248,7 @@ uint32_t InstrumentPass::GenVarLoad(uint32_t var_id,
                                     InstructionBuilder* builder) {
   Instruction* var_inst = get_def_use_mgr()->GetDef(var_id);
   uint32_t type_id = GetPointeeTypeId(var_inst);
-  Instruction* load_inst =
-      builder->AddUnaryOp(type_id, spv::Op::OpLoad, var_id);
+  Instruction* load_inst = builder->AddLoad(type_id, var_id);
   return load_inst->result_id();
 }
 
@@ -249,12 +284,12 @@ void InstrumentPass::GenStageStreamWriteCode(uint32_t stage_idx,
       uint32_t load_id = GenVarLoad(context()->GetBuiltinInputVarId(uint32_t(
                                         spv::BuiltIn::GlobalInvocationId)),
                                     builder);
-      Instruction* x_inst = builder->AddIdLiteralOp(
-          GetUintId(), spv::Op::OpCompositeExtract, load_id, 0);
-      Instruction* y_inst = builder->AddIdLiteralOp(
-          GetUintId(), spv::Op::OpCompositeExtract, load_id, 1);
-      Instruction* z_inst = builder->AddIdLiteralOp(
-          GetUintId(), spv::Op::OpCompositeExtract, load_id, 2);
+      Instruction* x_inst =
+          builder->AddCompositeExtract(GetUintId(), load_id, {0});
+      Instruction* y_inst =
+          builder->AddCompositeExtract(GetUintId(), load_id, {1});
+      Instruction* z_inst =
+          builder->AddCompositeExtract(GetUintId(), load_id, {2});
       GenDebugOutputFieldCode(base_offset_id, kInstCompOutGlobalInvocationIdX,
                               x_inst->result_id(), builder);
       GenDebugOutputFieldCode(base_offset_id, kInstCompOutGlobalInvocationIdY,
@@ -291,10 +326,10 @@ void InstrumentPass::GenStageStreamWriteCode(uint32_t stage_idx,
       Instruction* uvec3_cast_inst =
           builder->AddUnaryOp(GetVec3UintId(), spv::Op::OpBitcast, load_id);
       uint32_t uvec3_cast_id = uvec3_cast_inst->result_id();
-      Instruction* u_inst = builder->AddIdLiteralOp(
-          GetUintId(), spv::Op::OpCompositeExtract, uvec3_cast_id, 0);
-      Instruction* v_inst = builder->AddIdLiteralOp(
-          GetUintId(), spv::Op::OpCompositeExtract, uvec3_cast_id, 1);
+      Instruction* u_inst =
+          builder->AddCompositeExtract(GetUintId(), uvec3_cast_id, {0});
+      Instruction* v_inst =
+          builder->AddCompositeExtract(GetUintId(), uvec3_cast_id, {1});
       GenDebugOutputFieldCode(base_offset_id, kInstTessEvalOutTessCoordU,
                               u_inst->result_id(), builder);
       GenDebugOutputFieldCode(base_offset_id, kInstTessEvalOutTessCoordV,
@@ -302,8 +337,8 @@ void InstrumentPass::GenStageStreamWriteCode(uint32_t stage_idx,
     } break;
     case spv::ExecutionModel::Fragment: {
       // Load FragCoord and convert to Uint
-      Instruction* frag_coord_inst = builder->AddUnaryOp(
-          GetVec4FloatId(), spv::Op::OpLoad,
+      Instruction* frag_coord_inst = builder->AddLoad(
+          GetVec4FloatId(),
           context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::FragCoord)));
       Instruction* uint_frag_coord_inst = builder->AddUnaryOp(
           GetVec4UintId(), spv::Op::OpBitcast, frag_coord_inst->result_id());
@@ -321,12 +356,12 @@ void InstrumentPass::GenStageStreamWriteCode(uint32_t stage_idx,
       uint32_t launch_id = GenVarLoad(
           context()->GetBuiltinInputVarId(uint32_t(spv::BuiltIn::LaunchIdNV)),
           builder);
-      Instruction* x_launch_inst = builder->AddIdLiteralOp(
-          GetUintId(), spv::Op::OpCompositeExtract, launch_id, 0);
-      Instruction* y_launch_inst = builder->AddIdLiteralOp(
-          GetUintId(), spv::Op::OpCompositeExtract, launch_id, 1);
-      Instruction* z_launch_inst = builder->AddIdLiteralOp(
-          GetUintId(), spv::Op::OpCompositeExtract, launch_id, 2);
+      Instruction* x_launch_inst =
+          builder->AddCompositeExtract(GetUintId(), launch_id, {0});
+      Instruction* y_launch_inst =
+          builder->AddCompositeExtract(GetUintId(), launch_id, {1});
+      Instruction* z_launch_inst =
+          builder->AddCompositeExtract(GetUintId(), launch_id, {2});
       GenDebugOutputFieldCode(base_offset_id, kInstRayTracingOutLaunchIdX,
                               x_launch_inst->result_id(), builder);
       GenDebugOutputFieldCode(base_offset_id, kInstRayTracingOutLaunchIdY,
@@ -344,11 +379,10 @@ void InstrumentPass::GenDebugStreamWrite(
   // Call debug output function. Pass func_idx, instruction_idx and
   // validation ids as args.
   uint32_t val_id_cnt = static_cast<uint32_t>(validation_ids.size());
-  uint32_t output_func_id = GetStreamWriteFunctionId(stage_idx, val_id_cnt);
-  std::vector<uint32_t> args = {output_func_id,
-                                builder->GetUintConstantId(instruction_idx)};
+  std::vector<uint32_t> args = {builder->GetUintConstantId(instruction_idx)};
   (void)args.insert(args.end(), validation_ids.begin(), validation_ids.end());
-  (void)builder->AddNaryOp(GetVoidId(), spv::Op::OpFunctionCall, args);
+  (void)builder->AddFunctionCall(
+      GetVoidId(), GetStreamWriteFunctionId(stage_idx, val_id_cnt), args);
 }
 
 bool InstrumentPass::AllConstant(const std::vector<uint32_t>& ids) {
@@ -360,33 +394,38 @@ bool InstrumentPass::AllConstant(const std::vector<uint32_t>& ids) {
 }
 
 uint32_t InstrumentPass::GenDebugDirectRead(
-    const std::vector<uint32_t>& offset_ids, InstructionBuilder* ref_builder) {
+    const std::vector<uint32_t>& offset_ids, InstructionBuilder* builder) {
   // Call debug input function. Pass func_idx and offset ids as args.
-  uint32_t off_id_cnt = static_cast<uint32_t>(offset_ids.size());
-  uint32_t input_func_id = GetDirectReadFunctionId(off_id_cnt);
-  std::vector<uint32_t> args = {input_func_id};
-  (void)args.insert(args.end(), offset_ids.begin(), offset_ids.end());
+  const uint32_t off_id_cnt = static_cast<uint32_t>(offset_ids.size());
+  const uint32_t input_func_id = GetDirectReadFunctionId(off_id_cnt);
+  return GenReadFunctionCall(input_func_id, offset_ids, builder);
+}
+
+uint32_t InstrumentPass::GenReadFunctionCall(
+    uint32_t func_id, const std::vector<uint32_t>& func_call_args,
+    InstructionBuilder* ref_builder) {
   // If optimizing direct reads and the call has already been generated,
   // use its result
   if (opt_direct_reads_) {
-    uint32_t res_id = call2id_[args];
+    uint32_t res_id = call2id_[func_call_args];
     if (res_id != 0) return res_id;
   }
-  // If the offsets are all constants, the call can be moved to the first block
-  // of the function where its result can be reused. One example where this is
-  // profitable is for uniform buffer references, of which there are often many.
+  // If the function arguments are all constants, the call can be moved to the
+  // first block of the function where its result can be reused. One example
+  // where this is profitable is for uniform buffer references, of which there
+  // are often many.
   InstructionBuilder builder(ref_builder->GetContext(),
                              &*ref_builder->GetInsertPoint(),
                              ref_builder->GetPreservedAnalysis());
-  bool insert_in_first_block = opt_direct_reads_ && AllConstant(offset_ids);
+  bool insert_in_first_block = opt_direct_reads_ && AllConstant(func_call_args);
   if (insert_in_first_block) {
     Instruction* insert_before = &*curr_func_->begin()->tail();
     builder.SetInsertPoint(insert_before);
   }
   uint32_t res_id =
-      builder.AddNaryOp(GetUintId(), spv::Op::OpFunctionCall, args)
+      builder.AddFunctionCall(GetUintId(), func_id, func_call_args)
           ->result_id();
-  if (insert_in_first_block) call2id_[args] = res_id;
+  if (insert_in_first_block) call2id_[func_call_args] = res_id;
   return res_id;
 }
 
@@ -502,32 +541,61 @@ uint32_t InstrumentPass::GetInputBufferBinding() {
   return 0;
 }
 
-analysis::Type* InstrumentPass::GetUintXRuntimeArrayType(
-    uint32_t width, analysis::Type** rarr_ty) {
+analysis::Integer* InstrumentPass::GetInteger(uint32_t width, bool is_signed) {
+  analysis::Integer i(width, is_signed);
+  analysis::Type* type = context()->get_type_mgr()->GetRegisteredType(&i);
+  assert(type && type->AsInteger());
+  return type->AsInteger();
+}
+
+analysis::Struct* InstrumentPass::GetStruct(
+    const std::vector<const analysis::Type*>& fields) {
+  analysis::Struct s(fields);
+  analysis::Type* type = context()->get_type_mgr()->GetRegisteredType(&s);
+  assert(type && type->AsStruct());
+  return type->AsStruct();
+}
+
+analysis::RuntimeArray* InstrumentPass::GetRuntimeArray(
+    const analysis::Type* element) {
+  analysis::RuntimeArray r(element);
+  analysis::Type* type = context()->get_type_mgr()->GetRegisteredType(&r);
+  assert(type && type->AsRuntimeArray());
+  return type->AsRuntimeArray();
+}
+
+analysis::Function* InstrumentPass::GetFunction(
+    const analysis::Type* return_val,
+    const std::vector<const analysis::Type*>& args) {
+  analysis::Function func(return_val, args);
+  analysis::Type* type = context()->get_type_mgr()->GetRegisteredType(&func);
+  assert(type && type->AsFunction());
+  return type->AsFunction();
+}
+
+analysis::RuntimeArray* InstrumentPass::GetUintXRuntimeArrayType(
+    uint32_t width, analysis::RuntimeArray** rarr_ty) {
   if (*rarr_ty == nullptr) {
-    analysis::DecorationManager* deco_mgr = get_decoration_mgr();
-    analysis::TypeManager* type_mgr = context()->get_type_mgr();
-    analysis::Integer uint_ty(width, false);
-    analysis::Type* reg_uint_ty = type_mgr->GetRegisteredType(&uint_ty);
-    analysis::RuntimeArray uint_rarr_ty_tmp(reg_uint_ty);
-    *rarr_ty = type_mgr->GetRegisteredType(&uint_rarr_ty_tmp);
-    uint32_t uint_arr_ty_id = type_mgr->GetTypeInstruction(*rarr_ty);
+    *rarr_ty = GetRuntimeArray(GetInteger(width, false));
+    uint32_t uint_arr_ty_id =
+        context()->get_type_mgr()->GetTypeInstruction(*rarr_ty);
     // By the Vulkan spec, a pre-existing RuntimeArray of uint must be part of
     // a block, and will therefore be decorated with an ArrayStride. Therefore
     // the undecorated type returned here will not be pre-existing and can
     // safely be decorated. Since this type is now decorated, it is out of
     // sync with the TypeManager and therefore the TypeManager must be
     // invalidated after this pass.
-    assert(context()->get_def_use_mgr()->NumUses(uint_arr_ty_id) == 0 &&
+    assert(get_def_use_mgr()->NumUses(uint_arr_ty_id) == 0 &&
            "used RuntimeArray type returned");
-    deco_mgr->AddDecorationVal(
+    get_decoration_mgr()->AddDecorationVal(
         uint_arr_ty_id, uint32_t(spv::Decoration::ArrayStride), width / 8u);
   }
   return *rarr_ty;
 }
 
-analysis::Type* InstrumentPass::GetUintRuntimeArrayType(uint32_t width) {
-  analysis::Type** rarr_ty =
+analysis::RuntimeArray* InstrumentPass::GetUintRuntimeArrayType(
+    uint32_t width) {
+  analysis::RuntimeArray** rarr_ty =
       (width == 64) ? &uint64_rarr_ty_ : &uint32_rarr_ty_;
   return GetUintXRuntimeArrayType(width, rarr_ty);
 }
@@ -546,11 +614,10 @@ uint32_t InstrumentPass::GetOutputBufferId() {
     // If not created yet, create one
     analysis::DecorationManager* deco_mgr = get_decoration_mgr();
     analysis::TypeManager* type_mgr = context()->get_type_mgr();
-    analysis::Type* reg_uint_rarr_ty = GetUintRuntimeArrayType(32);
-    analysis::Integer uint_ty(32, false);
-    analysis::Type* reg_uint_ty = type_mgr->GetRegisteredType(&uint_ty);
-    analysis::Struct buf_ty({reg_uint_ty, reg_uint_ty, reg_uint_rarr_ty});
-    analysis::Type* reg_buf_ty = type_mgr->GetRegisteredType(&buf_ty);
+    analysis::RuntimeArray* reg_uint_rarr_ty = GetUintRuntimeArrayType(32);
+    analysis::Integer* reg_uint_ty = GetInteger(32, false);
+    analysis::Type* reg_buf_ty =
+        GetStruct({reg_uint_ty, reg_uint_ty, reg_uint_rarr_ty});
     uint32_t obufTyId = type_mgr->GetTypeInstruction(reg_buf_ty);
     // By the Vulkan spec, a pre-existing struct containing a RuntimeArray
     // must be a block, and will therefore be decorated with Block. Therefore
@@ -604,8 +671,7 @@ uint32_t InstrumentPass::GetInputBufferId() {
     analysis::TypeManager* type_mgr = context()->get_type_mgr();
     uint32_t width = (validation_id_ == kInstValidationIdBuffAddr) ? 64u : 32u;
     analysis::Type* reg_uint_rarr_ty = GetUintRuntimeArrayType(width);
-    analysis::Struct buf_ty({reg_uint_rarr_ty});
-    analysis::Type* reg_buf_ty = type_mgr->GetRegisteredType(&buf_ty);
+    analysis::Struct* reg_buf_ty = GetStruct({reg_uint_rarr_ty});
     uint32_t ibufTyId = type_mgr->GetTypeInstruction(reg_buf_ty);
     // By the Vulkan spec, a pre-existing struct containing a RuntimeArray
     // must be a block, and will therefore be decorated with Block. Therefore
@@ -747,37 +813,17 @@ uint32_t InstrumentPass::GetStreamWriteFunctionId(uint32_t stage_idx,
     // Create function
     param2output_func_id_[param_cnt] = TakeNextId();
     analysis::TypeManager* type_mgr = context()->get_type_mgr();
-    std::vector<const analysis::Type*> param_types;
-    for (uint32_t c = 0; c < param_cnt; ++c)
-      param_types.push_back(type_mgr->GetType(GetUintId()));
-    analysis::Function func_ty(type_mgr->GetType(GetVoidId()), param_types);
-    analysis::Type* reg_func_ty = type_mgr->GetRegisteredType(&func_ty);
-    std::unique_ptr<Instruction> func_inst(
-        new Instruction(get_module()->context(), spv::Op::OpFunction,
-                        GetVoidId(), param2output_func_id_[param_cnt],
-                        {{spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
-                          {uint32_t(spv::FunctionControlMask::MaskNone)}},
-                         {spv_operand_type_t::SPV_OPERAND_TYPE_ID,
-                          {type_mgr->GetTypeInstruction(reg_func_ty)}}}));
-    get_def_use_mgr()->AnalyzeInstDefUse(&*func_inst);
-    std::unique_ptr<Function> output_func =
-        MakeUnique<Function>(std::move(func_inst));
-    // Add parameters
-    std::vector<uint32_t> param_vec;
-    for (uint32_t c = 0; c < param_cnt; ++c) {
-      uint32_t pid = TakeNextId();
-      param_vec.push_back(pid);
-      std::unique_ptr<Instruction> param_inst(
-          new Instruction(get_module()->context(), spv::Op::OpFunctionParameter,
-                          GetUintId(), pid, {}));
-      get_def_use_mgr()->AnalyzeInstDefUse(&*param_inst);
-      output_func->AddParameter(std::move(param_inst));
-    }
+
+    const std::vector<const analysis::Type*> param_types(param_cnt,
+                                                         GetInteger(32, false));
+    std::unique_ptr<Function> output_func = StartFunction(
+        param2output_func_id_[param_cnt], type_mgr->GetVoidType(), param_types);
+
+    std::vector<uint32_t> param_ids = AddParameters(*output_func, param_types);
+
     // Create first block
-    uint32_t test_blk_id = TakeNextId();
-    std::unique_ptr<Instruction> test_label(NewLabel(test_blk_id));
-    std::unique_ptr<BasicBlock> new_blk_ptr =
-        MakeUnique<BasicBlock>(std::move(test_label));
+    auto new_blk_ptr = MakeUnique<BasicBlock>(NewLabel(TakeNextId()));
+
     InstructionBuilder builder(
         context(), &*new_blk_ptr,
         IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
@@ -786,9 +832,9 @@ uint32_t InstrumentPass::GetStreamWriteFunctionId(uint32_t stage_idx,
     uint32_t obuf_record_sz = val_spec_offset + val_spec_param_cnt;
     uint32_t buf_id = GetOutputBufferId();
     uint32_t buf_uint_ptr_id = GetOutputBufferPtrId();
-    Instruction* obuf_curr_sz_ac_inst =
-        builder.AddBinaryOp(buf_uint_ptr_id, spv::Op::OpAccessChain, buf_id,
-                            builder.GetUintConstantId(kDebugOutputSizeOffset));
+    Instruction* obuf_curr_sz_ac_inst = builder.AddAccessChain(
+        buf_uint_ptr_id, buf_id,
+        {builder.GetUintConstantId(kDebugOutputSizeOffset)});
     // Fetch the current debug buffer written size atomically, adding the
     // size of the record to be written.
     uint32_t obuf_record_sz_id = builder.GetUintConstantId(obuf_record_sz);
@@ -802,8 +848,8 @@ uint32_t InstrumentPass::GetStreamWriteFunctionId(uint32_t stage_idx,
     uint32_t obuf_curr_sz_id = obuf_curr_sz_inst->result_id();
     // Compute new written size
     Instruction* obuf_new_sz_inst =
-        builder.AddBinaryOp(GetUintId(), spv::Op::OpIAdd, obuf_curr_sz_id,
-                            builder.GetUintConstantId(obuf_record_sz));
+        builder.AddIAdd(GetUintId(), obuf_curr_sz_id,
+                        builder.GetUintConstantId(obuf_record_sz));
     // Fetch the data bound
     Instruction* obuf_bnd_inst =
         builder.AddIdLiteralOp(GetUintId(), spv::Op::OpArrayLength,
@@ -825,13 +871,13 @@ uint32_t InstrumentPass::GetStreamWriteFunctionId(uint32_t stage_idx,
     new_blk_ptr = MakeUnique<BasicBlock>(std::move(write_label));
     builder.SetInsertPoint(&*new_blk_ptr);
     // Generate common and stage-specific debug record members
-    GenCommonStreamWriteCode(obuf_record_sz, param_vec[kInstCommonParamInstIdx],
+    GenCommonStreamWriteCode(obuf_record_sz, param_ids[kInstCommonParamInstIdx],
                              stage_idx, obuf_curr_sz_id, &builder);
     GenStageStreamWriteCode(stage_idx, obuf_curr_sz_id, &builder);
     // Gen writes of validation specific data
     for (uint32_t i = 0; i < val_spec_param_cnt; ++i) {
       GenDebugOutputFieldCode(obuf_curr_sz_id, val_spec_offset + i,
-                              param_vec[kInstCommonParamCnt + i], &builder);
+                              param_ids[kInstCommonParamCnt + i], &builder);
     }
     // Close write block and gen merge block
     (void)builder.AddBranch(merge_blk_id);
@@ -840,11 +886,9 @@ uint32_t InstrumentPass::GetStreamWriteFunctionId(uint32_t stage_idx,
     builder.SetInsertPoint(&*new_blk_ptr);
     // Close merge block and function and add function to module
     (void)builder.AddNullaryOp(0, spv::Op::OpReturn);
+
     output_func->AddBasicBlock(std::move(new_blk_ptr));
-    std::unique_ptr<Instruction> func_end_inst(new Instruction(
-        get_module()->context(), spv::Op::OpFunctionEnd, 0, 0, {}));
-    get_def_use_mgr()->AnalyzeInstDefUse(&*func_end_inst);
-    output_func->SetFunctionEnd(std::move(func_end_inst));
+    output_func->SetFunctionEnd(EndFunction());
     context()->AddFunction(std::move(output_func));
 
     std::string name("stream_write_");
@@ -861,77 +905,48 @@ uint32_t InstrumentPass::GetDirectReadFunctionId(uint32_t param_cnt) {
   if (func_id != 0) return func_id;
   // Create input function for param_cnt.
   func_id = TakeNextId();
-  analysis::TypeManager* type_mgr = context()->get_type_mgr();
-  std::vector<const analysis::Type*> param_types;
-  for (uint32_t c = 0; c < param_cnt; ++c)
-    param_types.push_back(type_mgr->GetType(GetUintId()));
-  uint32_t ibuf_type_id = GetInputBufferTypeId();
-  analysis::Function func_ty(type_mgr->GetType(ibuf_type_id), param_types);
-  analysis::Type* reg_func_ty = type_mgr->GetRegisteredType(&func_ty);
-  std::unique_ptr<Instruction> func_inst(new Instruction(
-      get_module()->context(), spv::Op::OpFunction, ibuf_type_id, func_id,
-      {{spv_operand_type_t::SPV_OPERAND_TYPE_LITERAL_INTEGER,
-        {uint32_t(spv::FunctionControlMask::MaskNone)}},
-       {spv_operand_type_t::SPV_OPERAND_TYPE_ID,
-        {type_mgr->GetTypeInstruction(reg_func_ty)}}}));
-  get_def_use_mgr()->AnalyzeInstDefUse(&*func_inst);
+  analysis::Integer* uint_type = GetInteger(32, false);
+  std::vector<const analysis::Type*> param_types(param_cnt, uint_type);
+
   std::unique_ptr<Function> input_func =
-      MakeUnique<Function>(std::move(func_inst));
-  // Add parameters
-  std::vector<uint32_t> param_vec;
-  for (uint32_t c = 0; c < param_cnt; ++c) {
-    uint32_t pid = TakeNextId();
-    param_vec.push_back(pid);
-    std::unique_ptr<Instruction> param_inst(
-        new Instruction(get_module()->context(), spv::Op::OpFunctionParameter,
-                        GetUintId(), pid, {}));
-    get_def_use_mgr()->AnalyzeInstDefUse(&*param_inst);
-    input_func->AddParameter(std::move(param_inst));
-  }
+      StartFunction(func_id, uint_type, param_types);
+  std::vector<uint32_t> param_ids = AddParameters(*input_func, param_types);
+
   // Create block
-  uint32_t blk_id = TakeNextId();
-  std::unique_ptr<Instruction> blk_label(NewLabel(blk_id));
-  std::unique_ptr<BasicBlock> new_blk_ptr =
-      MakeUnique<BasicBlock>(std::move(blk_label));
+  auto new_blk_ptr = MakeUnique<BasicBlock>(NewLabel(TakeNextId()));
   InstructionBuilder builder(
       context(), &*new_blk_ptr,
       IRContext::kAnalysisDefUse | IRContext::kAnalysisInstrToBlockMapping);
   // For each offset parameter, generate new offset with parameter, adding last
   // loaded value if it exists, and load value from input buffer at new offset.
   // Return last loaded value.
+  uint32_t ibuf_type_id = GetInputBufferTypeId();
   uint32_t buf_id = GetInputBufferId();
   uint32_t buf_ptr_id = GetInputBufferPtrId();
   uint32_t last_value_id = 0;
   for (uint32_t p = 0; p < param_cnt; ++p) {
     uint32_t offset_id;
     if (p == 0) {
-      offset_id = param_vec[0];
+      offset_id = param_ids[0];
     } else {
       if (ibuf_type_id != GetUintId()) {
-        Instruction* ucvt_inst =
-            builder.AddUnaryOp(GetUintId(), spv::Op::OpUConvert, last_value_id);
-        last_value_id = ucvt_inst->result_id();
+        last_value_id =
+            builder.AddUnaryOp(GetUintId(), spv::Op::OpUConvert, last_value_id)
+                ->result_id();
       }
-      Instruction* offset_inst = builder.AddBinaryOp(
-          GetUintId(), spv::Op::OpIAdd, last_value_id, param_vec[p]);
-      offset_id = offset_inst->result_id();
+      offset_id = builder.AddIAdd(GetUintId(), last_value_id, param_ids[p])
+                      ->result_id();
     }
-    Instruction* ac_inst = builder.AddTernaryOp(
-        buf_ptr_id, spv::Op::OpAccessChain, buf_id,
-        builder.GetUintConstantId(kDebugInputDataOffset), offset_id);
-    Instruction* load_inst =
-        builder.AddUnaryOp(ibuf_type_id, spv::Op::OpLoad, ac_inst->result_id());
-    last_value_id = load_inst->result_id();
+    Instruction* ac_inst = builder.AddAccessChain(
+        buf_ptr_id, buf_id,
+        {builder.GetUintConstantId(kDebugInputDataOffset), offset_id});
+    last_value_id =
+        builder.AddLoad(ibuf_type_id, ac_inst->result_id())->result_id();
   }
-  (void)builder.AddInstruction(MakeUnique<Instruction>(
-      context(), spv::Op::OpReturnValue, 0, 0,
-      std::initializer_list<Operand>{{SPV_OPERAND_TYPE_ID, {last_value_id}}}));
+  (void)builder.AddUnaryOp(0, spv::Op::OpReturnValue, last_value_id);
   // Close block and function and add function to module
   input_func->AddBasicBlock(std::move(new_blk_ptr));
-  std::unique_ptr<Instruction> func_end_inst(new Instruction(
-      get_module()->context(), spv::Op::OpFunctionEnd, 0, 0, {}));
-  get_def_use_mgr()->AnalyzeInstDefUse(&*func_end_inst);
-  input_func->SetFunctionEnd(std::move(func_end_inst));
+  input_func->SetFunctionEnd(EndFunction());
   context()->AddFunction(std::move(input_func));
 
   std::string name("direct_read_");

+ 26 - 5
3rdparty/spirv-tools/source/opt/instrument_pass.h

@@ -214,6 +214,10 @@ class InstrumentPass : public Pass {
   uint32_t GenDebugDirectRead(const std::vector<uint32_t>& offset_ids,
                               InstructionBuilder* builder);
 
+  uint32_t GenReadFunctionCall(uint32_t func_id,
+                               const std::vector<uint32_t>& args,
+                               InstructionBuilder* builder);
+
   // Generate code to convert integer |value_id| to 32bit, if needed. Return
   // an id to the 32bit equivalent.
   uint32_t Gen32BitCvtCode(uint32_t value_id, InstructionBuilder* builder);
@@ -222,6 +226,15 @@ class InstrumentPass : public Pass {
   // Return an id to the Uint equivalent.
   uint32_t GenUintCastCode(uint32_t value_id, InstructionBuilder* builder);
 
+  std::unique_ptr<Function> StartFunction(
+      uint32_t func_id, const analysis::Type* return_type,
+      const std::vector<const analysis::Type*>& param_types);
+
+  std::vector<uint32_t> AddParameters(
+      Function& func, const std::vector<const analysis::Type*>& param_types);
+
+  std::unique_ptr<Instruction> EndFunction();
+
   // Return new label.
   std::unique_ptr<Instruction> NewLabel(uint32_t label_id);
 
@@ -253,12 +266,20 @@ class InstrumentPass : public Pass {
   // Return id for void type
   uint32_t GetVoidId();
 
+  // Get registered type structures
+  analysis::Integer* GetInteger(uint32_t width, bool is_signed);
+  analysis::Struct* GetStruct(const std::vector<const analysis::Type*>& fields);
+  analysis::RuntimeArray* GetRuntimeArray(const analysis::Type* element);
+  analysis::Function* GetFunction(
+      const analysis::Type* return_val,
+      const std::vector<const analysis::Type*>& args);
+
   // Return pointer to type for runtime array of uint
-  analysis::Type* GetUintXRuntimeArrayType(uint32_t width,
-                                           analysis::Type** rarr_ty);
+  analysis::RuntimeArray* GetUintXRuntimeArrayType(
+      uint32_t width, analysis::RuntimeArray** rarr_ty);
 
   // Return pointer to type for runtime array of uint
-  analysis::Type* GetUintRuntimeArrayType(uint32_t width);
+  analysis::RuntimeArray* GetUintRuntimeArrayType(uint32_t width);
 
   // Return id for buffer uint type
   uint32_t GetOutputBufferPtrId();
@@ -448,10 +469,10 @@ class InstrumentPass : public Pass {
   bool storage_buffer_ext_defined_;
 
   // runtime array of uint type
-  analysis::Type* uint64_rarr_ty_;
+  analysis::RuntimeArray* uint64_rarr_ty_;
 
   // runtime array of uint type
-  analysis::Type* uint32_rarr_ty_;
+  analysis::RuntimeArray* uint32_rarr_ty_;
 
   // Pre-instrumentation same-block insts
   std::unordered_map<uint32_t, Instruction*> same_block_pre_;

+ 92 - 0
3rdparty/spirv-tools/source/opt/optimizer.cpp

@@ -1065,3 +1065,95 @@ Optimizer::PassToken CreateFixFuncCallArgumentsPass() {
       MakeUnique<opt::FixFuncCallArgumentsPass>());
 }
 }  // namespace spvtools
+
+extern "C" {
+
+SPIRV_TOOLS_EXPORT spv_optimizer_t* spvOptimizerCreate(spv_target_env env) {
+  return reinterpret_cast<spv_optimizer_t*>(new spvtools::Optimizer(env));
+}
+
+SPIRV_TOOLS_EXPORT void spvOptimizerDestroy(spv_optimizer_t* optimizer) {
+  delete reinterpret_cast<spvtools::Optimizer*>(optimizer);
+}
+
+SPIRV_TOOLS_EXPORT void spvOptimizerSetMessageConsumer(
+    spv_optimizer_t* optimizer, spv_message_consumer consumer) {
+  reinterpret_cast<spvtools::Optimizer*>(optimizer)->
+      SetMessageConsumer(
+          [consumer](spv_message_level_t level, const char* source,
+                     const spv_position_t& position, const char* message) {
+            return consumer(level, source, &position, message);
+          });
+}
+
+SPIRV_TOOLS_EXPORT void spvOptimizerRegisterLegalizationPasses(
+    spv_optimizer_t* optimizer) {
+  reinterpret_cast<spvtools::Optimizer*>(optimizer)->
+      RegisterLegalizationPasses();
+}
+
+SPIRV_TOOLS_EXPORT void spvOptimizerRegisterPerformancePasses(
+    spv_optimizer_t* optimizer) {
+  reinterpret_cast<spvtools::Optimizer*>(optimizer)->
+      RegisterPerformancePasses();
+}
+
+SPIRV_TOOLS_EXPORT void spvOptimizerRegisterSizePasses(
+    spv_optimizer_t* optimizer) {
+  reinterpret_cast<spvtools::Optimizer*>(optimizer)->RegisterSizePasses();
+}
+
+SPIRV_TOOLS_EXPORT bool spvOptimizerRegisterPassFromFlag(
+    spv_optimizer_t* optimizer, const char* flag)
+{
+  return reinterpret_cast<spvtools::Optimizer*>(optimizer)->
+      RegisterPassFromFlag(flag);
+}
+
+SPIRV_TOOLS_EXPORT bool spvOptimizerRegisterPassesFromFlags(
+    spv_optimizer_t* optimizer, const char** flags, const size_t flag_count) {
+  std::vector<std::string> opt_flags;
+  for (uint32_t i = 0; i < flag_count; i++) {
+    opt_flags.emplace_back(flags[i]);
+  }
+
+  return reinterpret_cast<spvtools::Optimizer*>(optimizer)->
+      RegisterPassesFromFlags(opt_flags);
+}
+
+SPIRV_TOOLS_EXPORT
+spv_result_t spvOptimizerRun(spv_optimizer_t* optimizer,
+                             const uint32_t* binary,
+                             const size_t word_count,
+                             spv_binary* optimized_binary,
+                             const spv_optimizer_options options) {
+  std::vector<uint32_t> optimized;
+
+  if (!reinterpret_cast<spvtools::Optimizer*>(optimizer)->
+      Run(binary, word_count, &optimized, options)) {
+    return SPV_ERROR_INTERNAL;
+  }
+
+  auto result_binary = new spv_binary_t();
+  if (!result_binary) {
+      *optimized_binary = nullptr;
+      return SPV_ERROR_OUT_OF_MEMORY;
+  }
+
+  result_binary->code = new uint32_t[optimized.size()];
+  if (!result_binary->code) {
+      delete result_binary;
+      *optimized_binary = nullptr;
+      return SPV_ERROR_OUT_OF_MEMORY;
+  }
+  result_binary->wordCount = optimized.size();
+
+  memcpy(result_binary->code, optimized.data(),
+         optimized.size() * sizeof(uint32_t));
+
+  *optimized_binary = result_binary;
+
+  return SPV_SUCCESS;
+}
+
+}  // extern "C"

+ 3 - 2
3rdparty/spirv-tools/source/val/validate_bitwise.cpp

@@ -206,13 +206,14 @@ spv_result_t BitwisePass(ValidationState_t& _, const Instruction* inst) {
                << spvOpcodeString(opcode);
 
       const uint32_t base_type = _.GetOperandTypeId(inst, 2);
-      const uint32_t base_dimension = _.GetDimension(base_type);
-      const uint32_t result_dimension = _.GetDimension(result_type);
 
       if (spv_result_t error = ValidateBaseType(_, inst, base_type)) {
         return error;
       }
 
+      const uint32_t base_dimension = _.GetDimension(base_type);
+      const uint32_t result_dimension = _.GetDimension(result_type);
+
       if (base_dimension != result_dimension)
         return _.diag(SPV_ERROR_INVALID_DATA, inst)
                << "Expected Base dimension to be equal to Result Type "

Some files were not shown because too many files changed in this diff