瀏覽代碼

Updated spirv-tools.

Бранимир Караџић 4 年之前
父節點
當前提交
0e067a7a3a

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

@@ -1 +1 @@
-"v2021.4-dev", "SPIRV-Tools v2021.4-dev 6d1791ae2cbef975b42b8979526d79514be83329"
+"v2021.5-dev", "SPIRV-Tools v2021.5-dev 73acc9e59b165d08e3b418d207d84abd46cca49c"

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

@@ -530,7 +530,7 @@ static const spv_opcode_desc_t kOpcodeTableEntries[] = {
   {"USubSatINTEL", SpvOpUSubSatINTEL, 1, pygen_variable_caps_IntegerFunctions2INTEL, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
   {"USubSatINTEL", SpvOpUSubSatINTEL, 1, pygen_variable_caps_IntegerFunctions2INTEL, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
   {"IMul32x16INTEL", SpvOpIMul32x16INTEL, 1, pygen_variable_caps_IntegerFunctions2INTEL, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
   {"IMul32x16INTEL", SpvOpIMul32x16INTEL, 1, pygen_variable_caps_IntegerFunctions2INTEL, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
   {"UMul32x16INTEL", SpvOpUMul32x16INTEL, 1, pygen_variable_caps_IntegerFunctions2INTEL, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
   {"UMul32x16INTEL", SpvOpUMul32x16INTEL, 1, pygen_variable_caps_IntegerFunctions2INTEL, 4, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
-  {"ConstFunctionPointerINTEL", SpvOpConstFunctionPointerINTEL, 1, pygen_variable_caps_FunctionPointersINTEL, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_INTEL_function_pointers, 0xffffffffu, 0xffffffffu},
+  {"ConstantFunctionPointerINTEL", SpvOpConstantFunctionPointerINTEL, 1, pygen_variable_caps_FunctionPointersINTEL, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID}, 1, 1, 1, pygen_variable_exts_SPV_INTEL_function_pointers, 0xffffffffu, 0xffffffffu},
   {"FunctionPointerCallINTEL", SpvOpFunctionPointerCallINTEL, 1, pygen_variable_caps_FunctionPointersINTEL, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_VARIABLE_ID}, 1, 1, 1, pygen_variable_exts_SPV_INTEL_function_pointers, 0xffffffffu, 0xffffffffu},
   {"FunctionPointerCallINTEL", SpvOpFunctionPointerCallINTEL, 1, pygen_variable_caps_FunctionPointersINTEL, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_VARIABLE_ID}, 1, 1, 1, pygen_variable_exts_SPV_INTEL_function_pointers, 0xffffffffu, 0xffffffffu},
   {"AsmTargetINTEL", SpvOpAsmTargetINTEL, 1, pygen_variable_caps_AsmINTEL, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_LITERAL_STRING}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
   {"AsmTargetINTEL", SpvOpAsmTargetINTEL, 1, pygen_variable_caps_AsmINTEL, 3, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_LITERAL_STRING}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
   {"AsmINTEL", SpvOpAsmINTEL, 1, pygen_variable_caps_AsmINTEL, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_STRING, SPV_OPERAND_TYPE_LITERAL_STRING}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},
   {"AsmINTEL", SpvOpAsmINTEL, 1, pygen_variable_caps_AsmINTEL, 6, {SPV_OPERAND_TYPE_TYPE_ID, SPV_OPERAND_TYPE_RESULT_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_ID, SPV_OPERAND_TYPE_LITERAL_STRING, SPV_OPERAND_TYPE_LITERAL_STRING}, 1, 1, 0, nullptr, 0xffffffffu, 0xffffffffu},

+ 5 - 10
3rdparty/spirv-tools/source/opt/aggressive_dead_code_elim_pass.cpp

@@ -569,12 +569,7 @@ void AggressiveDCEPass::InitializeModuleScopeLiveInstructions() {
   }
   }
   // Keep all entry points.
   // Keep all entry points.
   for (auto& entry : get_module()->entry_points()) {
   for (auto& entry : get_module()->entry_points()) {
-    if (get_module()->version() >= SPV_SPIRV_VERSION_WORD(1, 4) &&
-        !preserve_interface_) {
-      // In SPIR-V 1.4 and later, entry points must list all global variables
-      // used. DCE can still remove non-input/output variables and update the
-      // interface list. Mark the entry point as live and inputs and outputs as
-      // live, but defer decisions all other interfaces.
+    if (!preserve_interface_) {
       live_insts_.Set(entry.unique_id());
       live_insts_.Set(entry.unique_id());
       // The actual function is live always.
       // The actual function is live always.
       AddToWorklist(
       AddToWorklist(
@@ -582,8 +577,9 @@ void AggressiveDCEPass::InitializeModuleScopeLiveInstructions() {
       for (uint32_t i = 3; i < entry.NumInOperands(); ++i) {
       for (uint32_t i = 3; i < entry.NumInOperands(); ++i) {
         auto* var = get_def_use_mgr()->GetDef(entry.GetSingleWordInOperand(i));
         auto* var = get_def_use_mgr()->GetDef(entry.GetSingleWordInOperand(i));
         auto storage_class = var->GetSingleWordInOperand(0u);
         auto storage_class = var->GetSingleWordInOperand(0u);
-        if (storage_class == SpvStorageClassInput ||
-            storage_class == SpvStorageClassOutput) {
+        // Vulkan support outputs without an associated input, but not inputs
+        // without an associated output.
+        if (storage_class == SpvStorageClassOutput) {
           AddToWorklist(var);
           AddToWorklist(var);
         }
         }
       }
       }
@@ -885,8 +881,7 @@ bool AggressiveDCEPass::ProcessGlobalValues() {
     }
     }
   }
   }
 
 
-  if (get_module()->version() >= SPV_SPIRV_VERSION_WORD(1, 4) &&
-      !preserve_interface_) {
+  if (!preserve_interface_) {
     // Remove the dead interface variables from the entry point interface list.
     // Remove the dead interface variables from the entry point interface list.
     for (auto& entry : get_module()->entry_points()) {
     for (auto& entry : get_module()->entry_points()) {
       std::vector<Operand> new_operands;
       std::vector<Operand> new_operands;

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

@@ -584,9 +584,9 @@ bool ReplaceCubeFaceCoord(IRContext* ctx, Instruction* inst,
   }
   }
 
 
   // Get the constants that will be used.
   // Get the constants that will be used.
-  uint32_t f0_const_id = const_mgr->GetFloatConst(0.0);
-  uint32_t f2_const_id = const_mgr->GetFloatConst(2.0);
-  uint32_t f0_5_const_id = const_mgr->GetFloatConst(0.5);
+  uint32_t f0_const_id = const_mgr->GetFloatConstId(0.0);
+  uint32_t f2_const_id = const_mgr->GetFloatConstId(2.0);
+  uint32_t f0_5_const_id = const_mgr->GetFloatConstId(0.5);
   const analysis::Constant* vec_const =
   const analysis::Constant* vec_const =
       const_mgr->GetConstant(v2_float_type, {f0_5_const_id, f0_5_const_id});
       const_mgr->GetConstant(v2_float_type, {f0_5_const_id, f0_5_const_id});
   uint32_t vec_const_id =
   uint32_t vec_const_id =
@@ -731,12 +731,12 @@ bool ReplaceCubeFaceIndex(IRContext* ctx, Instruction* inst,
   }
   }
 
 
   // Get the constants that will be used.
   // Get the constants that will be used.
-  uint32_t f0_const_id = const_mgr->GetFloatConst(0.0);
-  uint32_t f1_const_id = const_mgr->GetFloatConst(1.0);
-  uint32_t f2_const_id = const_mgr->GetFloatConst(2.0);
-  uint32_t f3_const_id = const_mgr->GetFloatConst(3.0);
-  uint32_t f4_const_id = const_mgr->GetFloatConst(4.0);
-  uint32_t f5_const_id = const_mgr->GetFloatConst(5.0);
+  uint32_t f0_const_id = const_mgr->GetFloatConstId(0.0);
+  uint32_t f1_const_id = const_mgr->GetFloatConstId(1.0);
+  uint32_t f2_const_id = const_mgr->GetFloatConstId(2.0);
+  uint32_t f3_const_id = const_mgr->GetFloatConstId(3.0);
+  uint32_t f4_const_id = const_mgr->GetFloatConstId(4.0);
+  uint32_t f5_const_id = const_mgr->GetFloatConstId(5.0);
 
 
   // Extract the input values.
   // Extract the input values.
   Instruction* x = ir_builder.AddCompositeExtract(float_type_id, input_id, {0});
   Instruction* x = ir_builder.AddCompositeExtract(float_type_id, input_id, {0});

+ 111 - 15
3rdparty/spirv-tools/source/opt/const_folding_rules.cpp

@@ -22,6 +22,45 @@ namespace {
 
 
 const uint32_t kExtractCompositeIdInIdx = 0;
 const uint32_t kExtractCompositeIdInIdx = 0;
 
 
+// Returns a constants with the value NaN of the given type.  Only works for
+// 32-bit and 64-bit float point types.  Returns |nullptr| if an error occurs.
+const analysis::Constant* GetNan(const analysis::Type* type,
+                                 analysis::ConstantManager* const_mgr) {
+  const analysis::Float* float_type = type->AsFloat();
+  if (float_type == nullptr) {
+    return nullptr;
+  }
+
+  switch (float_type->width()) {
+    case 32:
+      return const_mgr->GetFloatConst(std::numeric_limits<float>::quiet_NaN());
+    case 64:
+      return const_mgr->GetDoubleConst(
+          std::numeric_limits<double>::quiet_NaN());
+    default:
+      return nullptr;
+  }
+}
+
+// Returns a constants with the value INF of the given type.  Only works for
+// 32-bit and 64-bit float point types.  Returns |nullptr| if an error occurs.
+const analysis::Constant* GetInf(const analysis::Type* type,
+                                 analysis::ConstantManager* const_mgr) {
+  const analysis::Float* float_type = type->AsFloat();
+  if (float_type == nullptr) {
+    return nullptr;
+  }
+
+  switch (float_type->width()) {
+    case 32:
+      return const_mgr->GetFloatConst(std::numeric_limits<float>::infinity());
+    case 64:
+      return const_mgr->GetDoubleConst(std::numeric_limits<double>::infinity());
+    default:
+      return nullptr;
+  }
+}
+
 // Returns true if |type| is Float or a vector of Float.
 // Returns true if |type| is Float or a vector of Float.
 bool HasFloatingPoint(const analysis::Type* type) {
 bool HasFloatingPoint(const analysis::Type* type) {
   if (type->AsFloat()) {
   if (type->AsFloat()) {
@@ -33,6 +72,23 @@ bool HasFloatingPoint(const analysis::Type* type) {
   return false;
   return false;
 }
 }
 
 
+// Returns a constants with the value |-val| of the given type.  Only works for
+// 32-bit and 64-bit float point types.  Returns |nullptr| if an error occurs.
+const analysis::Constant* negateFPConst(const analysis::Type* result_type,
+                                        const analysis::Constant* val,
+                                        analysis::ConstantManager* const_mgr) {
+  const analysis::Float* float_type = result_type->AsFloat();
+  assert(float_type != nullptr);
+  if (float_type->width() == 32) {
+    float fa = val->GetFloat();
+    return const_mgr->GetFloatConst(-fa);
+  } else if (float_type->width() == 64) {
+    double da = val->GetDouble();
+    return const_mgr->GetDoubleConst(-da);
+  }
+  return nullptr;
+}
+
 // Folds an OpcompositeExtract where input is a composite constant.
 // Folds an OpcompositeExtract where input is a composite constant.
 ConstantFoldingRule FoldExtractWithConstants() {
 ConstantFoldingRule FoldExtractWithConstants() {
   return [](IRContext* context, Instruction* inst,
   return [](IRContext* context, Instruction* inst,
@@ -492,7 +548,60 @@ ConstantFoldingRule FoldQuantizeToF16() {
 ConstantFoldingRule FoldFSub() { return FoldFPBinaryOp(FOLD_FPARITH_OP(-)); }
 ConstantFoldingRule FoldFSub() { return FoldFPBinaryOp(FOLD_FPARITH_OP(-)); }
 ConstantFoldingRule FoldFAdd() { return FoldFPBinaryOp(FOLD_FPARITH_OP(+)); }
 ConstantFoldingRule FoldFAdd() { return FoldFPBinaryOp(FOLD_FPARITH_OP(+)); }
 ConstantFoldingRule FoldFMul() { return FoldFPBinaryOp(FOLD_FPARITH_OP(*)); }
 ConstantFoldingRule FoldFMul() { return FoldFPBinaryOp(FOLD_FPARITH_OP(*)); }
-ConstantFoldingRule FoldFDiv() { return FoldFPBinaryOp(FOLD_FPARITH_OP(/)); }
+
+// Returns the constant that results from evaluating |numerator| / 0.0.  Returns
+// |nullptr| if the result could not be evalutated.
+const analysis::Constant* FoldFPScalarDivideByZero(
+    const analysis::Type* result_type, const analysis::Constant* numerator,
+    analysis::ConstantManager* const_mgr) {
+  if (numerator == nullptr) {
+    return nullptr;
+  }
+
+  if (numerator->IsZero()) {
+    return GetNan(result_type, const_mgr);
+  }
+
+  const analysis::Constant* result = GetInf(result_type, const_mgr);
+  if (result == nullptr) {
+    return nullptr;
+  }
+
+  if (numerator->AsFloatConstant()->GetValueAsDouble() < 0.0) {
+    result = negateFPConst(result_type, result, const_mgr);
+  }
+  return result;
+}
+
+// Returns the result of folding |numerator| / |denominator|.  Returns |nullptr|
+// if it cannot be folded.
+const analysis::Constant* FoldScalarFPDivide(
+    const analysis::Type* result_type, const analysis::Constant* numerator,
+    const analysis::Constant* denominator,
+    analysis::ConstantManager* const_mgr) {
+  if (denominator == nullptr) {
+    return nullptr;
+  }
+
+  if (denominator->IsZero()) {
+    return FoldFPScalarDivideByZero(result_type, numerator, const_mgr);
+  }
+
+  const analysis::FloatConstant* denominator_float =
+      denominator->AsFloatConstant();
+  if (denominator_float && denominator->GetValueAsDouble() == -0.0) {
+    const analysis::Constant* result =
+        FoldFPScalarDivideByZero(result_type, numerator, const_mgr);
+    if (result != nullptr)
+      result = negateFPConst(result_type, result, const_mgr);
+    return result;
+  } else {
+    return FOLD_FPARITH_OP(/)(result_type, numerator, denominator, const_mgr);
+  }
+}
+
+// Returns the constant folding rule to fold |OpFDiv| with two constants.
+ConstantFoldingRule FoldFDiv() { return FoldFPBinaryOp(FoldScalarFPDivide); }
 
 
 bool CompareFloatingPoint(bool op_result, bool op_unordered,
 bool CompareFloatingPoint(bool op_result, bool op_unordered,
                           bool need_ordered) {
                           bool need_ordered) {
@@ -655,20 +764,7 @@ UnaryScalarFoldingRule FoldFNegateOp() {
             analysis::ConstantManager* const_mgr) -> const analysis::Constant* {
             analysis::ConstantManager* const_mgr) -> const analysis::Constant* {
     assert(result_type != nullptr && a != nullptr);
     assert(result_type != nullptr && a != nullptr);
     assert(result_type == a->type());
     assert(result_type == a->type());
-    const analysis::Float* float_type = result_type->AsFloat();
-    assert(float_type != nullptr);
-    if (float_type->width() == 32) {
-      float fa = a->GetFloat();
-      utils::FloatProxy<float> result(-fa);
-      std::vector<uint32_t> words = result.GetWords();
-      return const_mgr->GetConstant(result_type, words);
-    } else if (float_type->width() == 64) {
-      double da = a->GetDouble();
-      utils::FloatProxy<double> result(-da);
-      std::vector<uint32_t> words = result.GetWords();
-      return const_mgr->GetConstant(result_type, words);
-    }
-    return nullptr;
+    return negateFPConst(result_type, a, const_mgr);
   };
   };
 }
 }
 
 

+ 18 - 1
3rdparty/spirv-tools/source/opt/constants.cpp

@@ -420,13 +420,30 @@ const Constant* ConstantManager::GetNumericVectorConstantWithWords(
   return GetConstant(type, element_ids);
   return GetConstant(type, element_ids);
 }
 }
 
 
-uint32_t ConstantManager::GetFloatConst(float val) {
+uint32_t ConstantManager::GetFloatConstId(float val) {
+  const Constant* c = GetFloatConst(val);
+  return GetDefiningInstruction(c)->result_id();
+}
+
+const Constant* ConstantManager::GetFloatConst(float val) {
   Type* float_type = context()->get_type_mgr()->GetFloatType();
   Type* float_type = context()->get_type_mgr()->GetFloatType();
   utils::FloatProxy<float> v(val);
   utils::FloatProxy<float> v(val);
   const Constant* c = GetConstant(float_type, v.GetWords());
   const Constant* c = GetConstant(float_type, v.GetWords());
+  return c;
+}
+
+uint32_t ConstantManager::GetDoubleConstId(double val) {
+  const Constant* c = GetDoubleConst(val);
   return GetDefiningInstruction(c)->result_id();
   return GetDefiningInstruction(c)->result_id();
 }
 }
 
 
+const Constant* ConstantManager::GetDoubleConst(double val) {
+  Type* float_type = context()->get_type_mgr()->GetDoubleType();
+  utils::FloatProxy<double> v(val);
+  const Constant* c = GetConstant(float_type, v.GetWords());
+  return c;
+}
+
 uint32_t ConstantManager::GetSIntConst(int32_t val) {
 uint32_t ConstantManager::GetSIntConst(int32_t val) {
   Type* sint_type = context()->get_type_mgr()->GetSIntType();
   Type* sint_type = context()->get_type_mgr()->GetSIntType();
   const Constant* c = GetConstant(sint_type, {static_cast<uint32_t>(val)});
   const Constant* c = GetConstant(sint_type, {static_cast<uint32_t>(val)});

+ 10 - 1
3rdparty/spirv-tools/source/opt/constants.h

@@ -637,7 +637,16 @@ class ConstantManager {
   }
   }
 
 
   // Returns the id of a 32-bit floating point constant with value |val|.
   // Returns the id of a 32-bit floating point constant with value |val|.
-  uint32_t GetFloatConst(float val);
+  uint32_t GetFloatConstId(float val);
+
+  // Returns a 32-bit float constant with the given value.
+  const Constant* GetFloatConst(float val);
+
+  // Returns the id of a 64-bit floating point constant with value |val|.
+  uint32_t GetDoubleConstId(double val);
+
+  // Returns a 64-bit float constant with the given value.
+  const Constant* GetDoubleConst(double val);
 
 
   // Returns the id of a 32-bit signed integer constant with value |val|.
   // Returns the id of a 32-bit signed integer constant with value |val|.
   uint32_t GetSIntConst(int32_t val);
   uint32_t GetSIntConst(int32_t val);

+ 21 - 13
3rdparty/spirv-tools/source/opt/convert_to_half_pass.cpp

@@ -177,18 +177,21 @@ bool ConvertToHalfPass::GenHalfArith(Instruction* inst) {
   return modified;
   return modified;
 }
 }
 
 
-bool ConvertToHalfPass::ProcessPhi(Instruction* inst) {
-  // Add float16 converts of any float32 operands and change type
-  // of phi to float16 equivalent. Operand converts need to be added to
-  // preceeding blocks.
+bool ConvertToHalfPass::ProcessPhi(Instruction* inst, uint32_t from_width,
+                                   uint32_t to_width) {
+  // Add converts of any float operands to to_width if they are of from_width.
+  // If converting to 16, change type of phi to float16 equivalent and remember
+  // result id. Converts need to be added to preceeding blocks.
   uint32_t ocnt = 0;
   uint32_t ocnt = 0;
   uint32_t* prev_idp;
   uint32_t* prev_idp;
-  inst->ForEachInId([&ocnt, &prev_idp, this](uint32_t* idp) {
+  bool modified = false;
+  inst->ForEachInId([&ocnt, &prev_idp, &from_width, &to_width, &modified,
+                     this](uint32_t* idp) {
     if (ocnt % 2 == 0) {
     if (ocnt % 2 == 0) {
       prev_idp = idp;
       prev_idp = idp;
     } else {
     } else {
       Instruction* val_inst = get_def_use_mgr()->GetDef(*prev_idp);
       Instruction* val_inst = get_def_use_mgr()->GetDef(*prev_idp);
-      if (IsFloat(val_inst, 32)) {
+      if (IsFloat(val_inst, from_width)) {
         BasicBlock* bp = context()->get_instr_block(*idp);
         BasicBlock* bp = context()->get_instr_block(*idp);
         auto insert_before = bp->tail();
         auto insert_before = bp->tail();
         if (insert_before != bp->begin()) {
         if (insert_before != bp->begin()) {
@@ -197,15 +200,19 @@ bool ConvertToHalfPass::ProcessPhi(Instruction* inst) {
               insert_before->opcode() != SpvOpLoopMerge)
               insert_before->opcode() != SpvOpLoopMerge)
             ++insert_before;
             ++insert_before;
         }
         }
-        GenConvert(prev_idp, 16, &*insert_before);
+        GenConvert(prev_idp, to_width, &*insert_before);
+        modified = true;
       }
       }
     }
     }
     ++ocnt;
     ++ocnt;
   });
   });
-  inst->SetResultType(EquivFloatTypeId(inst->type_id(), 16));
-  get_def_use_mgr()->AnalyzeInstUse(inst);
-  converted_ids_.insert(inst->result_id());
-  return true;
+  if (to_width == 16u) {
+    inst->SetResultType(EquivFloatTypeId(inst->type_id(), 16u));
+    converted_ids_.insert(inst->result_id());
+    modified = true;
+  }
+  if (modified) get_def_use_mgr()->AnalyzeInstUse(inst);
+  return modified;
 }
 }
 
 
 bool ConvertToHalfPass::ProcessConvert(Instruction* inst) {
 bool ConvertToHalfPass::ProcessConvert(Instruction* inst) {
@@ -242,9 +249,10 @@ bool ConvertToHalfPass::ProcessImageRef(Instruction* inst) {
 }
 }
 
 
 bool ConvertToHalfPass::ProcessDefault(Instruction* inst) {
 bool ConvertToHalfPass::ProcessDefault(Instruction* inst) {
-  bool modified = false;
   // If non-relaxed instruction has changed operands, need to convert
   // If non-relaxed instruction has changed operands, need to convert
   // them back to float32
   // them back to float32
+  if (inst->opcode() == SpvOpPhi) return ProcessPhi(inst, 16u, 32u);
+  bool modified = false;
   inst->ForEachInId([&inst, &modified, this](uint32_t* idp) {
   inst->ForEachInId([&inst, &modified, this](uint32_t* idp) {
     if (converted_ids_.count(*idp) == 0) return;
     if (converted_ids_.count(*idp) == 0) return;
     uint32_t old_id = *idp;
     uint32_t old_id = *idp;
@@ -262,7 +270,7 @@ bool ConvertToHalfPass::GenHalfInst(Instruction* inst) {
   if (IsArithmetic(inst) && inst_relaxed)
   if (IsArithmetic(inst) && inst_relaxed)
     modified = GenHalfArith(inst);
     modified = GenHalfArith(inst);
   else if (inst->opcode() == SpvOpPhi && inst_relaxed)
   else if (inst->opcode() == SpvOpPhi && inst_relaxed)
-    modified = ProcessPhi(inst);
+    modified = ProcessPhi(inst, 32u, 16u);
   else if (inst->opcode() == SpvOpFConvert)
   else if (inst->opcode() == SpvOpFConvert)
     modified = ProcessConvert(inst);
     modified = ProcessConvert(inst);
   else if (image_ops_.count(inst->opcode()) != 0)
   else if (image_ops_.count(inst->opcode()) != 0)

+ 1 - 1
3rdparty/spirv-tools/source/opt/convert_to_half_pass.h

@@ -93,7 +93,7 @@ class ConvertToHalfPass : public Pass {
   bool GenHalfArith(Instruction* inst);
   bool GenHalfArith(Instruction* inst);
 
 
   // Gen code for relaxed phi |inst|
   // Gen code for relaxed phi |inst|
-  bool ProcessPhi(Instruction* inst);
+  bool ProcessPhi(Instruction* inst, uint32_t from_width, uint32_t to_width);
 
 
   // Gen code for relaxed convert |inst|
   // Gen code for relaxed convert |inst|
   bool ProcessConvert(Instruction* inst);
   bool ProcessConvert(Instruction* inst);

+ 1 - 1
3rdparty/spirv-tools/source/opt/reflect.h

@@ -52,7 +52,7 @@ inline bool IsTypeInst(SpvOp opcode) {
 }
 }
 inline bool IsConstantInst(SpvOp opcode) {
 inline bool IsConstantInst(SpvOp opcode) {
   return (opcode >= SpvOpConstantTrue && opcode <= SpvOpSpecConstantOp) ||
   return (opcode >= SpvOpConstantTrue && opcode <= SpvOpSpecConstantOp) ||
-         opcode == SpvOpConstFunctionPointerINTEL;
+         opcode == SpvOpConstantFunctionPointerINTEL;
 }
 }
 inline bool IsCompileTimeConstantInst(SpvOp opcode) {
 inline bool IsCompileTimeConstantInst(SpvOp opcode) {
   return opcode >= SpvOpConstantTrue && opcode <= SpvOpConstantNull;
   return opcode >= SpvOpConstantTrue && opcode <= SpvOpConstantNull;

+ 7 - 0
3rdparty/spirv-tools/source/opt/type_manager.h

@@ -160,6 +160,13 @@ class TypeManager {
 
 
   uint32_t GetFloatTypeId() { return GetTypeInstruction(GetFloatType()); }
   uint32_t GetFloatTypeId() { return GetTypeInstruction(GetFloatType()); }
 
 
+  Type* GetDoubleType() {
+    Float float_type(64);
+    return GetRegisteredType(&float_type);
+  }
+
+  uint32_t GetDoubleTypeId() { return GetTypeInstruction(GetDoubleType()); }
+
   Type* GetUIntVectorType(uint32_t size) {
   Type* GetUIntVectorType(uint32_t size) {
     Vector vec_type(GetUIntType(), size);
     Vector vec_type(GetUIntType(), size);
     return GetRegisteredType(&vec_type);
     return GetRegisteredType(&vec_type);

+ 15 - 14
3rdparty/spirv-tools/source/val/validate_annotation.cpp

@@ -230,7 +230,7 @@ bool IsNotMemberDecoration(SpvDecoration dec) {
 spv_result_t ValidateDecorationTarget(ValidationState_t& _, SpvDecoration dec,
 spv_result_t ValidateDecorationTarget(ValidationState_t& _, SpvDecoration dec,
                                       const Instruction* inst,
                                       const Instruction* inst,
                                       const Instruction* target) {
                                       const Instruction* target) {
-  auto fail = [&_, dec, inst, target](uint32_t vuid = 0) -> DiagnosticStream {
+  auto fail = [&_, dec, inst, target](uint32_t vuid) -> DiagnosticStream {
     DiagnosticStream ds = std::move(
     DiagnosticStream ds = std::move(
         _.diag(SPV_ERROR_INVALID_ID, inst)
         _.diag(SPV_ERROR_INVALID_ID, inst)
         << _.VkErrorID(vuid) << LogStringForDecoration(dec)
         << _.VkErrorID(vuid) << LogStringForDecoration(dec)
@@ -240,7 +240,7 @@ spv_result_t ValidateDecorationTarget(ValidationState_t& _, SpvDecoration dec,
   switch (dec) {
   switch (dec) {
     case SpvDecorationSpecId:
     case SpvDecorationSpecId:
       if (!spvOpcodeIsScalarSpecConstant(target->opcode())) {
       if (!spvOpcodeIsScalarSpecConstant(target->opcode())) {
-        return fail() << "must be a scalar specialization constant";
+        return fail(0) << "must be a scalar specialization constant";
       }
       }
       break;
       break;
     case SpvDecorationBlock:
     case SpvDecorationBlock:
@@ -249,14 +249,14 @@ spv_result_t ValidateDecorationTarget(ValidationState_t& _, SpvDecoration dec,
     case SpvDecorationGLSLPacked:
     case SpvDecorationGLSLPacked:
     case SpvDecorationCPacked:
     case SpvDecorationCPacked:
       if (target->opcode() != SpvOpTypeStruct) {
       if (target->opcode() != SpvOpTypeStruct) {
-        return fail() << "must be a structure type";
+        return fail(0) << "must be a structure type";
       }
       }
       break;
       break;
     case SpvDecorationArrayStride:
     case SpvDecorationArrayStride:
       if (target->opcode() != SpvOpTypeArray &&
       if (target->opcode() != SpvOpTypeArray &&
           target->opcode() != SpvOpTypeRuntimeArray &&
           target->opcode() != SpvOpTypeRuntimeArray &&
           target->opcode() != SpvOpTypePointer) {
           target->opcode() != SpvOpTypePointer) {
-        return fail() << "must be an array or pointer type";
+        return fail(0) << "must be an array or pointer type";
       }
       }
       break;
       break;
     case SpvDecorationBuiltIn:
     case SpvDecorationBuiltIn:
@@ -266,12 +266,13 @@ spv_result_t ValidateDecorationTarget(ValidationState_t& _, SpvDecoration dec,
                << "BuiltIns can only target variables, structure members or "
                << "BuiltIns can only target variables, structure members or "
                   "constants";
                   "constants";
       }
       }
-      if (inst->GetOperandAs<SpvBuiltIn>(2) == SpvBuiltInWorkgroupSize) {
+      if (_.HasCapability(SpvCapabilityShader) &&
+          inst->GetOperandAs<SpvBuiltIn>(2) == SpvBuiltInWorkgroupSize) {
         if (!spvOpcodeIsConstant(target->opcode())) {
         if (!spvOpcodeIsConstant(target->opcode())) {
-          return fail() << "must be a constant for WorkgroupSize";
+          return fail(0) << "must be a constant for WorkgroupSize";
         }
         }
       } else if (target->opcode() != SpvOpVariable) {
       } else if (target->opcode() != SpvOpVariable) {
-        return fail() << "must be a variable";
+        return fail(0) << "must be a variable";
       }
       }
       break;
       break;
     case SpvDecorationNoPerspective:
     case SpvDecorationNoPerspective:
@@ -293,10 +294,10 @@ spv_result_t ValidateDecorationTarget(ValidationState_t& _, SpvDecoration dec,
     case SpvDecorationAliasedPointer:
     case SpvDecorationAliasedPointer:
       if (target->opcode() != SpvOpVariable &&
       if (target->opcode() != SpvOpVariable &&
           target->opcode() != SpvOpFunctionParameter) {
           target->opcode() != SpvOpFunctionParameter) {
-        return fail() << "must be a memory object declaration";
+        return fail(0) << "must be a memory object declaration";
       }
       }
       if (_.GetIdOpcode(target->type_id()) != SpvOpTypePointer) {
       if (_.GetIdOpcode(target->type_id()) != SpvOpTypePointer) {
-        return fail() << "must be a pointer type";
+        return fail(0) << "must be a pointer type";
       }
       }
       break;
       break;
     case SpvDecorationInvariant:
     case SpvDecorationInvariant:
@@ -307,7 +308,7 @@ spv_result_t ValidateDecorationTarget(ValidationState_t& _, SpvDecoration dec,
     case SpvDecorationDescriptorSet:
     case SpvDecorationDescriptorSet:
     case SpvDecorationInputAttachmentIndex:
     case SpvDecorationInputAttachmentIndex:
       if (target->opcode() != SpvOpVariable) {
       if (target->opcode() != SpvOpVariable) {
-        return fail() << "must be a variable";
+        return fail(0) << "must be a variable";
       }
       }
       break;
       break;
     default:
     default:
@@ -337,7 +338,7 @@ spv_result_t ValidateDecorationTarget(ValidationState_t& _, SpvDecoration dec,
         break;
         break;
       case SpvDecorationIndex:
       case SpvDecorationIndex:
         if (sc != SpvStorageClassOutput) {
         if (sc != SpvStorageClassOutput) {
-          return fail() << "must be in the Output storage class";
+          return fail(0) << "must be in the Output storage class";
         }
         }
         break;
         break;
       case SpvDecorationBinding:
       case SpvDecorationBinding:
@@ -345,13 +346,13 @@ spv_result_t ValidateDecorationTarget(ValidationState_t& _, SpvDecoration dec,
         if (sc != SpvStorageClassStorageBuffer &&
         if (sc != SpvStorageClassStorageBuffer &&
             sc != SpvStorageClassUniform &&
             sc != SpvStorageClassUniform &&
             sc != SpvStorageClassUniformConstant) {
             sc != SpvStorageClassUniformConstant) {
-          return fail() << "must be in the StorageBuffer, Uniform, or "
-                           "UniformConstant storage class";
+          return fail(0) << "must be in the StorageBuffer, Uniform, or "
+                            "UniformConstant storage class";
         }
         }
         break;
         break;
       case SpvDecorationInputAttachmentIndex:
       case SpvDecorationInputAttachmentIndex:
         if (sc != SpvStorageClassUniformConstant) {
         if (sc != SpvStorageClassUniformConstant) {
-          return fail() << "must be in the UniformConstant storage class";
+          return fail(0) << "must be in the UniformConstant storage class";
         }
         }
         break;
         break;
       case SpvDecorationFlat:
       case SpvDecorationFlat: