Browse Source

Updated spirv-tools.

Бранимир Караџић 5 years ago
parent
commit
f334d0c1cb

+ 29 - 2
3rdparty/spirv-tools/CHANGES

@@ -1,7 +1,34 @@
 Revision history for SPIRV-Tools
 Revision history for SPIRV-Tools
 
 
-v2020.2-dev 2020-02-03
- - Start v2020.2-dev
+v2020.3-dev 2020-03-26
+ - Start v2020.3-dev
+
+v2020.2 2020-03-26
+ - General:
+   - Support extended instructions in the vscode language server
+   - Make spvOpcodeString part of the public API (#3174)
+   - Added guide to writing a spirv-fuzz fuzzer pass (#3190)
+   - Add support for KHR_ray_{query,tracing} extensions (#3235)
+ - Optimizer
+   - Debug Printf support (#3215)
+   - Add data structure for DebugScope, DebugDeclare in spirv-opt (#3183)
+   - Fix identification of Vulkan images and buffers (#3253)
+ - Validator
+   - Add support for SPV_AMD_shader_image_load_store_lod (#3186)
+   - Add validation rules for OpenCL.DebugInfo.100 extension (#3133)
+   - Adding WebGPU specific Workgroup scope rule (#3204)
+   - Disallow phis of images, samplers and sampled images (#3246)
+ - Reduce
+ - Fuzz
+   - Fuzzer passes to add local and global variables (#3175)
+   - Add fuzzer passes to add loads/stores (#3176)
+   - Fuzzer pass to add function calls (#3178)
+   - Fuzzer pass that adds access chains (#3182)
+   - Fuzzer pass to add equation instructions (#3202)
+   - Add swap commutable operands transformation (#3205)
+   - Add fuzzer pass to permute function parameters (#3212)
+   - Allow OpPhi operand to be replaced with a composite synonym (#3221)
+ - Linker
 
 
 v2020.1 2020-02-03
 v2020.1 2020-02-03
  - General:
  - General:

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

@@ -1 +1 @@
-"v2020.2-dev", "SPIRV-Tools v2020.2-dev 9897187ba975fbb16bbce48d1d45761bf27bfac1"
+"v2020.3-dev", "SPIRV-Tools v2020.3-dev eff6f130119f3e6acbf81f8432c0912296d4dfdb"

+ 1 - 0
3rdparty/spirv-tools/source/opt/aggressive_dead_code_elim_pass.cpp

@@ -931,6 +931,7 @@ void AggressiveDCEPass::InitExtensions() {
       "SPV_NV_shading_rate",
       "SPV_NV_shading_rate",
       "SPV_NV_mesh_shader",
       "SPV_NV_mesh_shader",
       "SPV_NV_ray_tracing",
       "SPV_NV_ray_tracing",
+      "SPV_KHR_ray_tracing",
       "SPV_EXT_fragment_invocation_density",
       "SPV_EXT_fragment_invocation_density",
       "SPV_EXT_physical_storage_buffer",
       "SPV_EXT_physical_storage_buffer",
   });
   });

+ 17 - 0
3rdparty/spirv-tools/source/opt/function.cpp

@@ -34,6 +34,11 @@ Function* Function::Clone(IRContext* ctx) const {
       },
       },
       true);
       true);
 
 
+  for (const auto& i : debug_insts_in_header_) {
+    clone->AddDebugInstructionInHeader(
+        std::unique_ptr<Instruction>(i.Clone(ctx)));
+  }
+
   clone->blocks_.reserve(blocks_.size());
   clone->blocks_.reserve(blocks_.size());
   for (const auto& b : blocks_) {
   for (const auto& b : blocks_) {
     std::unique_ptr<BasicBlock> bb(b->Clone(ctx));
     std::unique_ptr<BasicBlock> bb(b->Clone(ctx));
@@ -79,6 +84,12 @@ bool Function::WhileEachInst(const std::function<bool(Instruction*)>& f,
     }
     }
   }
   }
 
 
+  for (auto& di : debug_insts_in_header_) {
+    if (!di.WhileEachInst(f, run_on_debug_line_insts)) {
+      return false;
+    }
+  }
+
   for (auto& bb : blocks_) {
   for (auto& bb : blocks_) {
     if (!bb->WhileEachInst(f, run_on_debug_line_insts)) {
     if (!bb->WhileEachInst(f, run_on_debug_line_insts)) {
       return false;
       return false;
@@ -106,6 +117,12 @@ bool Function::WhileEachInst(const std::function<bool(const Instruction*)>& f,
     }
     }
   }
   }
 
 
+  for (const auto& di : debug_insts_in_header_) {
+    if (!di.WhileEachInst(f, run_on_debug_line_insts)) {
+      return false;
+    }
+  }
+
   for (const auto& bb : blocks_) {
   for (const auto& bb : blocks_) {
     if (!static_cast<const BasicBlock*>(bb.get())->WhileEachInst(
     if (!static_cast<const BasicBlock*>(bb.get())->WhileEachInst(
             f, run_on_debug_line_insts)) {
             f, run_on_debug_line_insts)) {

+ 9 - 0
3rdparty/spirv-tools/source/opt/function.h

@@ -56,6 +56,8 @@ class Function {
 
 
   // Appends a parameter to this function.
   // Appends a parameter to this function.
   inline void AddParameter(std::unique_ptr<Instruction> p);
   inline void AddParameter(std::unique_ptr<Instruction> p);
+  // Appends a debug instruction in function header to this function.
+  inline void AddDebugInstructionInHeader(std::unique_ptr<Instruction> p);
   // Appends a basic block to this function.
   // Appends a basic block to this function.
   inline void AddBasicBlock(std::unique_ptr<BasicBlock> b);
   inline void AddBasicBlock(std::unique_ptr<BasicBlock> b);
   // Appends a basic block to this function at the position |ip|.
   // Appends a basic block to this function at the position |ip|.
@@ -151,6 +153,8 @@ class Function {
   std::unique_ptr<Instruction> def_inst_;
   std::unique_ptr<Instruction> def_inst_;
   // All parameters to this function.
   // All parameters to this function.
   std::vector<std::unique_ptr<Instruction>> params_;
   std::vector<std::unique_ptr<Instruction>> params_;
+  // All debug instructions in this function's header.
+  InstructionList debug_insts_in_header_;
   // All basic blocks inside this function in specification order
   // All basic blocks inside this function in specification order
   std::vector<std::unique_ptr<BasicBlock>> blocks_;
   std::vector<std::unique_ptr<BasicBlock>> blocks_;
   // The OpFunctionEnd instruction.
   // The OpFunctionEnd instruction.
@@ -167,6 +171,11 @@ inline void Function::AddParameter(std::unique_ptr<Instruction> p) {
   params_.emplace_back(std::move(p));
   params_.emplace_back(std::move(p));
 }
 }
 
 
+inline void Function::AddDebugInstructionInHeader(
+    std::unique_ptr<Instruction> p) {
+  debug_insts_in_header_.push_back(std::move(p));
+}
+
 inline void Function::AddBasicBlock(std::unique_ptr<BasicBlock> b) {
 inline void Function::AddBasicBlock(std::unique_ptr<BasicBlock> b) {
   AddBasicBlock(std::move(b), end());
   AddBasicBlock(std::move(b), end());
 }
 }

+ 101 - 5
3rdparty/spirv-tools/source/opt/instruction.cpp

@@ -16,6 +16,7 @@
 
 
 #include <initializer_list>
 #include <initializer_list>
 
 
+#include "OpenCLDebugInfo100.h"
 #include "source/disassemble.h"
 #include "source/disassemble.h"
 #include "source/opt/fold.h"
 #include "source/opt/fold.h"
 #include "source/opt/ir_context.h"
 #include "source/opt/ir_context.h"
@@ -30,6 +31,11 @@ const uint32_t kTypeImageDimIndex = 1;
 const uint32_t kLoadBaseIndex = 0;
 const uint32_t kLoadBaseIndex = 0;
 const uint32_t kVariableStorageClassIndex = 0;
 const uint32_t kVariableStorageClassIndex = 0;
 const uint32_t kTypeImageSampledIndex = 5;
 const uint32_t kTypeImageSampledIndex = 5;
+
+// Constants for OpenCL.DebugInfo.100 extension instructions.
+const uint32_t kDebugScopeNumWords = 7;
+const uint32_t kDebugScopeNumWordsWithoutInlinedAt = 6;
+const uint32_t kDebugNoScopeNumWords = 5;
 }  // namespace
 }  // namespace
 
 
 Instruction::Instruction(IRContext* c)
 Instruction::Instruction(IRContext* c)
@@ -38,7 +44,8 @@ Instruction::Instruction(IRContext* c)
       opcode_(SpvOpNop),
       opcode_(SpvOpNop),
       has_type_id_(false),
       has_type_id_(false),
       has_result_id_(false),
       has_result_id_(false),
-      unique_id_(c->TakeNextUniqueId()) {}
+      unique_id_(c->TakeNextUniqueId()),
+      dbg_scope_(kNoDebugScope, kNoInlinedAt) {}
 
 
 Instruction::Instruction(IRContext* c, SpvOp op)
 Instruction::Instruction(IRContext* c, SpvOp op)
     : utils::IntrusiveNodeBase<Instruction>(),
     : utils::IntrusiveNodeBase<Instruction>(),
@@ -46,7 +53,8 @@ Instruction::Instruction(IRContext* c, SpvOp op)
       opcode_(op),
       opcode_(op),
       has_type_id_(false),
       has_type_id_(false),
       has_result_id_(false),
       has_result_id_(false),
-      unique_id_(c->TakeNextUniqueId()) {}
+      unique_id_(c->TakeNextUniqueId()),
+      dbg_scope_(kNoDebugScope, kNoInlinedAt) {}
 
 
 Instruction::Instruction(IRContext* c, const spv_parsed_instruction_t& inst,
 Instruction::Instruction(IRContext* c, const spv_parsed_instruction_t& inst,
                          std::vector<Instruction>&& dbg_line)
                          std::vector<Instruction>&& dbg_line)
@@ -55,7 +63,8 @@ Instruction::Instruction(IRContext* c, const spv_parsed_instruction_t& inst,
       has_type_id_(inst.type_id != 0),
       has_type_id_(inst.type_id != 0),
       has_result_id_(inst.result_id != 0),
       has_result_id_(inst.result_id != 0),
       unique_id_(c->TakeNextUniqueId()),
       unique_id_(c->TakeNextUniqueId()),
-      dbg_line_insts_(std::move(dbg_line)) {
+      dbg_line_insts_(std::move(dbg_line)),
+      dbg_scope_(kNoDebugScope, kNoInlinedAt) {
   assert((!IsDebugLineInst(opcode_) || dbg_line.empty()) &&
   assert((!IsDebugLineInst(opcode_) || dbg_line.empty()) &&
          "Op(No)Line attaching to Op(No)Line found");
          "Op(No)Line attaching to Op(No)Line found");
   for (uint32_t i = 0; i < inst.num_operands; ++i) {
   for (uint32_t i = 0; i < inst.num_operands; ++i) {
@@ -67,6 +76,23 @@ Instruction::Instruction(IRContext* c, const spv_parsed_instruction_t& inst,
   }
   }
 }
 }
 
 
+Instruction::Instruction(IRContext* c, const spv_parsed_instruction_t& inst,
+                         const DebugScope& dbg_scope)
+    : context_(c),
+      opcode_(static_cast<SpvOp>(inst.opcode)),
+      has_type_id_(inst.type_id != 0),
+      has_result_id_(inst.result_id != 0),
+      unique_id_(c->TakeNextUniqueId()),
+      dbg_scope_(dbg_scope) {
+  for (uint32_t i = 0; i < inst.num_operands; ++i) {
+    const auto& current_payload = inst.operands[i];
+    std::vector<uint32_t> words(
+        inst.words + current_payload.offset,
+        inst.words + current_payload.offset + current_payload.num_words);
+    operands_.emplace_back(current_payload.type, std::move(words));
+  }
+}
+
 Instruction::Instruction(IRContext* c, SpvOp op, uint32_t ty_id,
 Instruction::Instruction(IRContext* c, SpvOp op, uint32_t ty_id,
                          uint32_t res_id, const OperandList& in_operands)
                          uint32_t res_id, const OperandList& in_operands)
     : utils::IntrusiveNodeBase<Instruction>(),
     : utils::IntrusiveNodeBase<Instruction>(),
@@ -75,7 +101,8 @@ Instruction::Instruction(IRContext* c, SpvOp op, uint32_t ty_id,
       has_type_id_(ty_id != 0),
       has_type_id_(ty_id != 0),
       has_result_id_(res_id != 0),
       has_result_id_(res_id != 0),
       unique_id_(c->TakeNextUniqueId()),
       unique_id_(c->TakeNextUniqueId()),
-      operands_() {
+      operands_(),
+      dbg_scope_(kNoDebugScope, kNoInlinedAt) {
   if (has_type_id_) {
   if (has_type_id_) {
     operands_.emplace_back(spv_operand_type_t::SPV_OPERAND_TYPE_TYPE_ID,
     operands_.emplace_back(spv_operand_type_t::SPV_OPERAND_TYPE_TYPE_ID,
                            std::initializer_list<uint32_t>{ty_id});
                            std::initializer_list<uint32_t>{ty_id});
@@ -94,7 +121,12 @@ Instruction::Instruction(Instruction&& that)
       has_result_id_(that.has_result_id_),
       has_result_id_(that.has_result_id_),
       unique_id_(that.unique_id_),
       unique_id_(that.unique_id_),
       operands_(std::move(that.operands_)),
       operands_(std::move(that.operands_)),
-      dbg_line_insts_(std::move(that.dbg_line_insts_)) {}
+      dbg_line_insts_(std::move(that.dbg_line_insts_)),
+      dbg_scope_(that.dbg_scope_) {
+  for (auto& i : dbg_line_insts_) {
+    i.dbg_scope_ = that.dbg_scope_;
+  }
+}
 
 
 Instruction& Instruction::operator=(Instruction&& that) {
 Instruction& Instruction::operator=(Instruction&& that) {
   opcode_ = that.opcode_;
   opcode_ = that.opcode_;
@@ -103,6 +135,7 @@ Instruction& Instruction::operator=(Instruction&& that) {
   unique_id_ = that.unique_id_;
   unique_id_ = that.unique_id_;
   operands_ = std::move(that.operands_);
   operands_ = std::move(that.operands_);
   dbg_line_insts_ = std::move(that.dbg_line_insts_);
   dbg_line_insts_ = std::move(that.dbg_line_insts_);
+  dbg_scope_ = that.dbg_scope_;
   return *this;
   return *this;
 }
 }
 
 
@@ -114,6 +147,7 @@ Instruction* Instruction::Clone(IRContext* c) const {
   clone->unique_id_ = c->TakeNextUniqueId();
   clone->unique_id_ = c->TakeNextUniqueId();
   clone->operands_ = operands_;
   clone->operands_ = operands_;
   clone->dbg_line_insts_ = dbg_line_insts_;
   clone->dbg_line_insts_ = dbg_line_insts_;
+  clone->dbg_scope_ = dbg_scope_;
   return clone;
   return clone;
 }
 }
 
 
@@ -198,6 +232,14 @@ bool Instruction::IsVulkanStorageImage() const {
 
 
   Instruction* base_type =
   Instruction* base_type =
       context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
       context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
+
+  // Unpack the optional layer of arraying.
+  if (base_type->opcode() == SpvOpTypeArray ||
+      base_type->opcode() == SpvOpTypeRuntimeArray) {
+    base_type = context()->get_def_use_mgr()->GetDef(
+        base_type->GetSingleWordInOperand(0));
+  }
+
   if (base_type->opcode() != SpvOpTypeImage) {
   if (base_type->opcode() != SpvOpTypeImage) {
     return false;
     return false;
   }
   }
@@ -224,6 +266,14 @@ bool Instruction::IsVulkanSampledImage() const {
 
 
   Instruction* base_type =
   Instruction* base_type =
       context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
       context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
+
+  // Unpack the optional layer of arraying.
+  if (base_type->opcode() == SpvOpTypeArray ||
+      base_type->opcode() == SpvOpTypeRuntimeArray) {
+    base_type = context()->get_def_use_mgr()->GetDef(
+        base_type->GetSingleWordInOperand(0));
+  }
+
   if (base_type->opcode() != SpvOpTypeImage) {
   if (base_type->opcode() != SpvOpTypeImage) {
     return false;
     return false;
   }
   }
@@ -250,6 +300,14 @@ bool Instruction::IsVulkanStorageTexelBuffer() const {
 
 
   Instruction* base_type =
   Instruction* base_type =
       context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
       context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
+
+  // Unpack the optional layer of arraying.
+  if (base_type->opcode() == SpvOpTypeArray ||
+      base_type->opcode() == SpvOpTypeRuntimeArray) {
+    base_type = context()->get_def_use_mgr()->GetDef(
+        base_type->GetSingleWordInOperand(0));
+  }
+
   if (base_type->opcode() != SpvOpTypeImage) {
   if (base_type->opcode() != SpvOpTypeImage) {
     return false;
     return false;
   }
   }
@@ -273,6 +331,13 @@ bool Instruction::IsVulkanStorageBuffer() const {
   Instruction* base_type =
   Instruction* base_type =
       context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
       context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
 
 
+  // Unpack the optional layer of arraying.
+  if (base_type->opcode() == SpvOpTypeArray ||
+      base_type->opcode() == SpvOpTypeRuntimeArray) {
+    base_type = context()->get_def_use_mgr()->GetDef(
+        base_type->GetSingleWordInOperand(0));
+  }
+
   if (base_type->opcode() != SpvOpTypeStruct) {
   if (base_type->opcode() != SpvOpTypeStruct) {
     return false;
     return false;
   }
   }
@@ -306,6 +371,14 @@ bool Instruction::IsVulkanUniformBuffer() const {
 
 
   Instruction* base_type =
   Instruction* base_type =
       context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
       context()->get_def_use_mgr()->GetDef(GetSingleWordInOperand(1));
+
+  // Unpack the optional layer of arraying.
+  if (base_type->opcode() == SpvOpTypeArray ||
+      base_type->opcode() == SpvOpTypeRuntimeArray) {
+    base_type = context()->get_def_use_mgr()->GetDef(
+        base_type->GetSingleWordInOperand(0));
+  }
+
   if (base_type->opcode() != SpvOpTypeStruct) {
   if (base_type->opcode() != SpvOpTypeStruct) {
     return false;
     return false;
   }
   }
@@ -735,5 +808,28 @@ bool Instruction::IsOpcodeSafeToDelete() const {
   }
   }
 }
 }
 
 
+void DebugScope::ToBinary(uint32_t type_id, uint32_t result_id,
+                          uint32_t ext_set,
+                          std::vector<uint32_t>* binary) const {
+  uint32_t num_words = kDebugScopeNumWords;
+  OpenCLDebugInfo100Instructions dbg_opcode = OpenCLDebugInfo100DebugScope;
+  if (GetLexicalScope() == kNoDebugScope) {
+    num_words = kDebugNoScopeNumWords;
+    dbg_opcode = OpenCLDebugInfo100DebugNoScope;
+  } else if (GetInlinedAt() == kNoInlinedAt) {
+    num_words = kDebugScopeNumWordsWithoutInlinedAt;
+  }
+  std::vector<uint32_t> operands = {
+      (num_words << 16) | static_cast<uint16_t>(SpvOpExtInst),
+      type_id,
+      result_id,
+      ext_set,
+      static_cast<uint32_t>(dbg_opcode),
+  };
+  binary->insert(binary->end(), operands.begin(), operands.end());
+  if (GetLexicalScope() != kNoDebugScope) binary->push_back(GetLexicalScope());
+  if (GetInlinedAt() != kNoInlinedAt) binary->push_back(GetInlinedAt());
+}
+
 }  // namespace opt
 }  // namespace opt
 }  // namespace spvtools
 }  // namespace spvtools

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

@@ -32,6 +32,9 @@
 #include "source/opt/reflect.h"
 #include "source/opt/reflect.h"
 #include "spirv-tools/libspirv.h"
 #include "spirv-tools/libspirv.h"
 
 
+const uint32_t kNoDebugScope = 0;
+const uint32_t kNoInlinedAt = 0;
+
 namespace spvtools {
 namespace spvtools {
 namespace opt {
 namespace opt {
 
 
@@ -100,6 +103,44 @@ inline bool operator!=(const Operand& o1, const Operand& o2) {
   return !(o1 == o2);
   return !(o1 == o2);
 }
 }
 
 
+// This structure is used to represent a DebugScope instruction from
+// the OpenCL.100.DebugInfo extened instruction set. Note that we can
+// ignore the result id of DebugScope instruction because it is not
+// used for anything. We do not keep it to reduce the size of
+// structure.
+// TODO: Let validator check that the result id is not used anywhere.
+class DebugScope {
+ public:
+  DebugScope(uint32_t lexical_scope, uint32_t inlined_at)
+      : lexical_scope_(lexical_scope), inlined_at_(inlined_at) {}
+
+  inline bool operator!=(const DebugScope& d) const {
+    return lexical_scope_ != d.lexical_scope_ || inlined_at_ != d.inlined_at_;
+  }
+
+  // Accessor functions for |lexical_scope_|.
+  uint32_t GetLexicalScope() const { return lexical_scope_; }
+  void SetLexicalScope(uint32_t scope) { lexical_scope_ = scope; }
+
+  // Accessor functions for |inlined_at_|.
+  uint32_t GetInlinedAt() const { return inlined_at_; }
+  void SetInlinedAt(uint32_t at) { inlined_at_ = at; }
+
+  // Pushes the binary segments for this DebugScope instruction into
+  // the back of *|binary|.
+  void ToBinary(uint32_t type_id, uint32_t result_id, uint32_t ext_set,
+                std::vector<uint32_t>* binary) const;
+
+ private:
+  // The result id of the lexical scope in which this debug scope is
+  // contained. The value is kNoDebugScope if there is no scope.
+  uint32_t lexical_scope_;
+
+  // The result id of DebugInlinedAt if instruction in this debug scope
+  // is inlined. The value is kNoInlinedAt if it is not inlined.
+  uint32_t inlined_at_;
+};
+
 // A SPIR-V instruction. It contains the opcode and any additional logical
 // A SPIR-V instruction. It contains the opcode and any additional logical
 // operand, including the result id (if any) and result type id (if any). It
 // operand, including the result id (if any) and result type id (if any). It
 // may also contain line-related debug instruction (OpLine, OpNoLine) directly
 // may also contain line-related debug instruction (OpLine, OpNoLine) directly
@@ -120,7 +161,8 @@ class Instruction : public utils::IntrusiveNodeBase<Instruction> {
         opcode_(SpvOpNop),
         opcode_(SpvOpNop),
         has_type_id_(false),
         has_type_id_(false),
         has_result_id_(false),
         has_result_id_(false),
-        unique_id_(0) {}
+        unique_id_(0),
+        dbg_scope_(kNoDebugScope, kNoInlinedAt) {}
 
 
   // Creates a default OpNop instruction.
   // Creates a default OpNop instruction.
   Instruction(IRContext*);
   Instruction(IRContext*);
@@ -134,6 +176,9 @@ class Instruction : public utils::IntrusiveNodeBase<Instruction> {
   Instruction(IRContext* c, const spv_parsed_instruction_t& inst,
   Instruction(IRContext* c, const spv_parsed_instruction_t& inst,
               std::vector<Instruction>&& dbg_line = {});
               std::vector<Instruction>&& dbg_line = {});
 
 
+  Instruction(IRContext* c, const spv_parsed_instruction_t& inst,
+              const DebugScope& dbg_scope);
+
   // Creates an instruction with the given opcode |op|, type id: |ty_id|,
   // Creates an instruction with the given opcode |op|, type id: |ty_id|,
   // result id: |res_id| and input operands: |in_operands|.
   // result id: |res_id| and input operands: |in_operands|.
   Instruction(IRContext* c, SpvOp op, uint32_t ty_id, uint32_t res_id,
   Instruction(IRContext* c, SpvOp op, uint32_t ty_id, uint32_t res_id,
@@ -230,6 +275,9 @@ class Instruction : public utils::IntrusiveNodeBase<Instruction> {
   // Sets the result id
   // Sets the result id
   inline void SetResultId(uint32_t res_id);
   inline void SetResultId(uint32_t res_id);
   inline bool HasResultId() const { return has_result_id_; }
   inline bool HasResultId() const { return has_result_id_; }
+  // Sets DebugScope.
+  inline void SetDebugScope(const DebugScope& scope);
+  inline const DebugScope& GetDebugScope() const { return dbg_scope_; }
   // Remove the |index|-th operand
   // Remove the |index|-th operand
   void RemoveOperand(uint32_t index) {
   void RemoveOperand(uint32_t index) {
     operands_.erase(operands_.begin() + index);
     operands_.erase(operands_.begin() + index);
@@ -482,6 +530,9 @@ class Instruction : public utils::IntrusiveNodeBase<Instruction> {
   // empty.
   // empty.
   std::vector<Instruction> dbg_line_insts_;
   std::vector<Instruction> dbg_line_insts_;
 
 
+  // DebugScope that wraps this instruction.
+  DebugScope dbg_scope_;
+
   friend InstructionList;
   friend InstructionList;
 };
 };
 
 
@@ -553,6 +604,13 @@ inline void Instruction::SetResultId(uint32_t res_id) {
   operands_[ridx].words = {res_id};
   operands_[ridx].words = {res_id};
 }
 }
 
 
+inline void Instruction::SetDebugScope(const DebugScope& scope) {
+  dbg_scope_ = scope;
+  for (auto& i : dbg_line_insts_) {
+    i.dbg_scope_ = scope;
+  }
+}
+
 inline void Instruction::SetResultType(uint32_t ty_id) {
 inline void Instruction::SetResultType(uint32_t ty_id) {
   // TODO(dsinclair): Allow setting a type id if there wasn't one
   // TODO(dsinclair): Allow setting a type id if there wasn't one
   // previously. Need to make room in the operands_ array to place the result,
   // previously. Need to make room in the operands_ array to place the result,

+ 110 - 30
3rdparty/spirv-tools/source/opt/ir_loader.cpp

@@ -23,6 +23,10 @@
 #include "source/opt/reflect.h"
 #include "source/opt/reflect.h"
 #include "source/util/make_unique.h"
 #include "source/util/make_unique.h"
 
 
+static const uint32_t kExtInstSetIndex = 4;
+static const uint32_t kLexicalScopeIndex = 5;
+static const uint32_t kInlinedAtIndex = 6;
+
 namespace spvtools {
 namespace spvtools {
 namespace opt {
 namespace opt {
 
 
@@ -30,16 +34,60 @@ IrLoader::IrLoader(const MessageConsumer& consumer, Module* m)
     : consumer_(consumer),
     : consumer_(consumer),
       module_(m),
       module_(m),
       source_("<instruction>"),
       source_("<instruction>"),
-      inst_index_(0) {}
+      inst_index_(0),
+      last_dbg_scope_(kNoDebugScope, kNoInlinedAt) {}
 
 
 bool IrLoader::AddInstruction(const spv_parsed_instruction_t* inst) {
 bool IrLoader::AddInstruction(const spv_parsed_instruction_t* inst) {
   ++inst_index_;
   ++inst_index_;
   const auto opcode = static_cast<SpvOp>(inst->opcode);
   const auto opcode = static_cast<SpvOp>(inst->opcode);
   if (IsDebugLineInst(opcode)) {
   if (IsDebugLineInst(opcode)) {
-    dbg_line_info_.push_back(Instruction(module()->context(), *inst));
+    dbg_line_info_.push_back(
+        Instruction(module()->context(), *inst, last_dbg_scope_));
     return true;
     return true;
   }
   }
 
 
+  // If it is a DebugScope or DebugNoScope of debug extension, we do not
+  // create a new instruction, but simply keep the information in
+  // struct DebugScope.
+  if (opcode == SpvOpExtInst && spvExtInstIsDebugInfo(inst->ext_inst_type)) {
+    const uint32_t ext_inst_index = inst->words[kExtInstSetIndex];
+    if (inst->ext_inst_type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100) {
+      const OpenCLDebugInfo100Instructions ext_inst_key =
+          OpenCLDebugInfo100Instructions(ext_inst_index);
+      if (ext_inst_key == OpenCLDebugInfo100DebugScope) {
+        uint32_t inlined_at = 0;
+        if (inst->num_words > kInlinedAtIndex)
+          inlined_at = inst->words[kInlinedAtIndex];
+        last_dbg_scope_ =
+            DebugScope(inst->words[kLexicalScopeIndex], inlined_at);
+        module()->SetContainsDebugScope();
+        return true;
+      }
+      if (ext_inst_key == OpenCLDebugInfo100DebugNoScope) {
+        last_dbg_scope_ = DebugScope(kNoDebugScope, kNoInlinedAt);
+        module()->SetContainsDebugScope();
+        return true;
+      }
+    } else {
+      const DebugInfoInstructions ext_inst_key =
+          DebugInfoInstructions(ext_inst_index);
+      if (ext_inst_key == DebugInfoDebugScope) {
+        uint32_t inlined_at = 0;
+        if (inst->num_words > kInlinedAtIndex)
+          inlined_at = inst->words[kInlinedAtIndex];
+        last_dbg_scope_ =
+            DebugScope(inst->words[kLexicalScopeIndex], inlined_at);
+        module()->SetContainsDebugScope();
+        return true;
+      }
+      if (ext_inst_key == DebugInfoDebugNoScope) {
+        last_dbg_scope_ = DebugScope(kNoDebugScope, kNoInlinedAt);
+        module()->SetContainsDebugScope();
+        return true;
+      }
+    }
+  }
+
   std::unique_ptr<Instruction> spv_inst(
   std::unique_ptr<Instruction> spv_inst(
       new Instruction(module()->context(), *inst, std::move(dbg_line_info_)));
       new Instruction(module()->context(), *inst, std::move(dbg_line_info_)));
   dbg_line_info_.clear();
   dbg_line_info_.clear();
@@ -90,6 +138,7 @@ bool IrLoader::AddInstruction(const spv_parsed_instruction_t* inst) {
     block_->AddInstruction(std::move(spv_inst));
     block_->AddInstruction(std::move(spv_inst));
     function_->AddBasicBlock(std::move(block_));
     function_->AddBasicBlock(std::move(block_));
     block_ = nullptr;
     block_ = nullptr;
+    last_dbg_scope_ = DebugScope(kNoDebugScope, kNoInlinedAt);
   } else {
   } else {
     if (function_ == nullptr) {  // Outside function definition
     if (function_ == nullptr) {  // Outside function definition
       SPIRV_ASSERT(consumer_, block_ == nullptr);
       SPIRV_ASSERT(consumer_, block_ == nullptr);
@@ -131,26 +180,32 @@ bool IrLoader::AddInstruction(const spv_parsed_instruction_t* inst) {
         return false;
         return false;
       }
       }
     } else {
     } else {
-      if (block_ == nullptr) {  // Inside function but outside blocks
-        if (opcode != SpvOpFunctionParameter) {
-          Errorf(consumer_, src, loc,
-                 "Non-OpFunctionParameter (opcode: %d) found inside "
-                 "function but outside basic block",
-                 opcode);
-          return false;
-        }
-        function_->AddParameter(std::move(spv_inst));
-      } else {
-        if (opcode == SpvOpExtInst &&
-            spvExtInstIsDebugInfo(inst->ext_inst_type)) {
-          const uint32_t ext_inst_index = inst->words[4];
-          if (inst->ext_inst_type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100) {
-            const OpenCLDebugInfo100Instructions ext_inst_key =
-                OpenCLDebugInfo100Instructions(ext_inst_index);
-            if (ext_inst_key != OpenCLDebugInfo100DebugScope &&
-                ext_inst_key != OpenCLDebugInfo100DebugNoScope &&
-                ext_inst_key != OpenCLDebugInfo100DebugDeclare &&
-                ext_inst_key != OpenCLDebugInfo100DebugValue) {
+      if (opcode == SpvOpLoopMerge || opcode == SpvOpSelectionMerge)
+        last_dbg_scope_ = DebugScope(kNoDebugScope, kNoInlinedAt);
+      if (last_dbg_scope_.GetLexicalScope() != kNoDebugScope)
+        spv_inst->SetDebugScope(last_dbg_scope_);
+      if (opcode == SpvOpExtInst &&
+          spvExtInstIsDebugInfo(inst->ext_inst_type)) {
+        const uint32_t ext_inst_index = inst->words[kExtInstSetIndex];
+        if (inst->ext_inst_type == SPV_EXT_INST_TYPE_OPENCL_DEBUGINFO_100) {
+          const OpenCLDebugInfo100Instructions ext_inst_key =
+              OpenCLDebugInfo100Instructions(ext_inst_index);
+          switch (ext_inst_key) {
+            case OpenCLDebugInfo100DebugDeclare: {
+              if (block_ == nullptr)  // Inside function but outside blocks
+                function_->AddDebugInstructionInHeader(std::move(spv_inst));
+              else
+                block_->AddInstruction(std::move(spv_inst));
+              break;
+            }
+            case OpenCLDebugInfo100DebugValue: {
+              if (block_ == nullptr)  // Inside function but outside blocks
+                function_->AddDebugInstructionInHeader(std::move(spv_inst));
+              else
+                block_->AddInstruction(std::move(spv_inst));
+              break;
+            }
+            default: {
               Errorf(consumer_, src, loc,
               Errorf(consumer_, src, loc,
                      "Debug info extension instruction other than DebugScope, "
                      "Debug info extension instruction other than DebugScope, "
                      "DebugNoScope, DebugDeclare, and DebugValue found inside "
                      "DebugNoScope, DebugDeclare, and DebugValue found inside "
@@ -158,13 +213,26 @@ bool IrLoader::AddInstruction(const spv_parsed_instruction_t* inst) {
                      opcode);
                      opcode);
               return false;
               return false;
             }
             }
-          } else {
-            const DebugInfoInstructions ext_inst_key =
-                DebugInfoInstructions(ext_inst_index);
-            if (ext_inst_key != DebugInfoDebugScope &&
-                ext_inst_key != DebugInfoDebugNoScope &&
-                ext_inst_key != DebugInfoDebugDeclare &&
-                ext_inst_key != DebugInfoDebugValue) {
+          }
+        } else {
+          const DebugInfoInstructions ext_inst_key =
+              DebugInfoInstructions(ext_inst_index);
+          switch (ext_inst_key) {
+            case DebugInfoDebugDeclare: {
+              if (block_ == nullptr)  // Inside function but outside blocks
+                function_->AddDebugInstructionInHeader(std::move(spv_inst));
+              else
+                block_->AddInstruction(std::move(spv_inst));
+              break;
+            }
+            case DebugInfoDebugValue: {
+              if (block_ == nullptr)  // Inside function but outside blocks
+                function_->AddDebugInstructionInHeader(std::move(spv_inst));
+              else
+                block_->AddInstruction(std::move(spv_inst));
+              break;
+            }
+            default: {
               Errorf(consumer_, src, loc,
               Errorf(consumer_, src, loc,
                      "Debug info extension instruction other than DebugScope, "
                      "Debug info extension instruction other than DebugScope, "
                      "DebugNoScope, DebugDeclare, and DebugValue found inside "
                      "DebugNoScope, DebugDeclare, and DebugValue found inside "
@@ -174,7 +242,19 @@ bool IrLoader::AddInstruction(const spv_parsed_instruction_t* inst) {
             }
             }
           }
           }
         }
         }
-        block_->AddInstruction(std::move(spv_inst));
+      } else {
+        if (block_ == nullptr) {  // Inside function but outside blocks
+          if (opcode != SpvOpFunctionParameter) {
+            Errorf(consumer_, src, loc,
+                   "Non-OpFunctionParameter (opcode: %d) found inside "
+                   "function but outside basic block",
+                   opcode);
+            return false;
+          }
+          function_->AddParameter(std::move(spv_inst));
+        } else {
+          block_->AddInstruction(std::move(spv_inst));
+        }
       }
       }
     }
     }
   }
   }

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

@@ -78,6 +78,9 @@ class IrLoader {
   std::unique_ptr<BasicBlock> block_;
   std::unique_ptr<BasicBlock> block_;
   // Line related debug instructions accumulated thus far.
   // Line related debug instructions accumulated thus far.
   std::vector<Instruction> dbg_line_info_;
   std::vector<Instruction> dbg_line_info_;
+
+  // The last DebugScope information that IrLoader::AddInstruction() handled.
+  DebugScope last_dbg_scope_;
 };
 };
 
 
 }  // namespace opt
 }  // namespace opt

+ 1 - 0
3rdparty/spirv-tools/source/opt/local_access_chain_convert_pass.cpp

@@ -379,6 +379,7 @@ void LocalAccessChainConvertPass::InitExtensions() {
       "SPV_NV_shading_rate",
       "SPV_NV_shading_rate",
       "SPV_NV_mesh_shader",
       "SPV_NV_mesh_shader",
       "SPV_NV_ray_tracing",
       "SPV_NV_ray_tracing",
+      "SPV_KHR_ray_tracing",
       "SPV_KHR_ray_query",
       "SPV_KHR_ray_query",
       "SPV_EXT_fragment_invocation_density",
       "SPV_EXT_fragment_invocation_density",
   });
   });

+ 1 - 0
3rdparty/spirv-tools/source/opt/local_single_block_elim_pass.cpp

@@ -256,6 +256,7 @@ void LocalSingleBlockLoadStoreElimPass::InitExtensions() {
       "SPV_NV_shading_rate",
       "SPV_NV_shading_rate",
       "SPV_NV_mesh_shader",
       "SPV_NV_mesh_shader",
       "SPV_NV_ray_tracing",
       "SPV_NV_ray_tracing",
+      "SPV_KHR_ray_tracing",
       "SPV_KHR_ray_query",
       "SPV_KHR_ray_query",
       "SPV_EXT_fragment_invocation_density",
       "SPV_EXT_fragment_invocation_density",
       "SPV_EXT_physical_storage_buffer",
       "SPV_EXT_physical_storage_buffer",

+ 19 - 2
3rdparty/spirv-tools/source/opt/module.cpp

@@ -137,10 +137,27 @@ void Module::ToBinary(std::vector<uint32_t>* binary, bool skip_nop) const {
   binary->push_back(header_.bound);
   binary->push_back(header_.bound);
   binary->push_back(header_.reserved);
   binary->push_back(header_.reserved);
 
 
-  auto write_inst = [binary, skip_nop](const Instruction* i) {
-    if (!(skip_nop && i->IsNop())) i->ToBinaryWithoutAttachedDebugInsts(binary);
+  size_t bound_idx = binary->size() - 2;
+  DebugScope last_scope(kNoDebugScope, kNoInlinedAt);
+  auto write_inst = [binary, skip_nop, &last_scope,
+                     this](const Instruction* i) {
+    if (!(skip_nop && i->IsNop())) {
+      const auto& scope = i->GetDebugScope();
+      if (scope != last_scope) {
+        // Emit DebugScope |scope| to |binary|.
+        auto dbg_inst = ext_inst_debuginfo_.begin();
+        scope.ToBinary(dbg_inst->type_id(), context()->TakeNextId(),
+                       dbg_inst->GetSingleWordOperand(2), binary);
+        last_scope = scope;
+      }
+
+      i->ToBinaryWithoutAttachedDebugInsts(binary);
+    }
   };
   };
   ForEachInst(write_inst, true);
   ForEachInst(write_inst, true);
+
+  // We create new instructions for DebugScope. The bound must be updated.
+  binary->data()[bound_idx] = header_.bound;
 }
 }
 
 
 uint32_t Module::ComputeIdBound() const {
 uint32_t Module::ComputeIdBound() const {

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

@@ -17,6 +17,7 @@
 
 
 #include <functional>
 #include <functional>
 #include <memory>
 #include <memory>
+#include <unordered_map>
 #include <utility>
 #include <utility>
 #include <vector>
 #include <vector>
 
 
@@ -48,7 +49,7 @@ class Module {
   using const_inst_iterator = InstructionList::const_iterator;
   using const_inst_iterator = InstructionList::const_iterator;
 
 
   // Creates an empty module with zero'd header.
   // Creates an empty module with zero'd header.
-  Module() : header_({}) {}
+  Module() : header_({}), contains_debug_scope_(false) {}
 
 
   // Sets the header to the given |header|.
   // Sets the header to the given |header|.
   void SetHeader(const ModuleHeader& header) { header_ = header; }
   void SetHeader(const ModuleHeader& header) { header_ = header; }
@@ -118,6 +119,10 @@ class Module {
   // Appends a function to this module.
   // Appends a function to this module.
   inline void AddFunction(std::unique_ptr<Function> f);
   inline void AddFunction(std::unique_ptr<Function> f);
 
 
+  // Sets |contains_debug_scope_| as true.
+  inline void SetContainsDebugScope();
+  inline bool ContainsDebugScope() { return contains_debug_scope_; }
+
   // Returns a vector of pointers to type-declaration instructions in this
   // Returns a vector of pointers to type-declaration instructions in this
   // module.
   // module.
   std::vector<Instruction*> GetTypes();
   std::vector<Instruction*> GetTypes();
@@ -295,6 +300,9 @@ class Module {
   // If the module ends with Op*Line instruction, they will not be attached to
   // If the module ends with Op*Line instruction, they will not be attached to
   // any instruction.  We record them here, so they will not be lost.
   // any instruction.  We record them here, so they will not be lost.
   std::vector<Instruction> trailing_dbg_line_info_;
   std::vector<Instruction> trailing_dbg_line_info_;
+
+  // This module contains DebugScope or DebugNoScope.
+  bool contains_debug_scope_;
 };
 };
 
 
 // Pretty-prints |module| to |str|. Returns |str|.
 // Pretty-prints |module| to |str|. Returns |str|.
@@ -356,6 +364,8 @@ inline void Module::AddFunction(std::unique_ptr<Function> f) {
   functions_.emplace_back(std::move(f));
   functions_.emplace_back(std::move(f));
 }
 }
 
 
+inline void Module::SetContainsDebugScope() { contains_debug_scope_ = true; }
+
 inline Module::inst_iterator Module::capability_begin() {
 inline Module::inst_iterator Module::capability_begin() {
   return capabilities_.begin();
   return capabilities_.begin();
 }
 }

+ 6 - 1
3rdparty/spirv-tools/source/opt/optimizer.cpp

@@ -569,7 +569,12 @@ bool Optimizer::Run(const uint32_t* original_binary,
   }
   }
 
 
 #ifndef NDEBUG
 #ifndef NDEBUG
-  if (status == opt::Pass::Status::SuccessWithoutChange) {
+  // We do not keep the result id of DebugScope in struct DebugScope.
+  // Instead, we assign random ids for them, which results in sanity
+  // check failures. We want to skip the sanity check when the module
+  // contains DebugScope instructions.
+  if (status == opt::Pass::Status::SuccessWithoutChange &&
+      !context->module()->ContainsDebugScope()) {
     std::vector<uint32_t> optimized_binary_with_nop;
     std::vector<uint32_t> optimized_binary_with_nop;
     context->module()->ToBinary(&optimized_binary_with_nop,
     context->module()->ToBinary(&optimized_binary_with_nop,
                                 /* skip_nop = */ false);
                                 /* skip_nop = */ false);

+ 9 - 0
3rdparty/spirv-tools/source/val/validate_cfg.cpp

@@ -62,6 +62,15 @@ spv_result_t ValidatePhi(ValidationState_t& _, const Instruction* inst) {
     }
     }
   }
   }
 
 
+  if (!_.options()->before_hlsl_legalization) {
+    if (type_opcode == SpvOpTypeSampledImage ||
+        (_.HasCapability(SpvCapabilityShader) &&
+         (type_opcode == SpvOpTypeImage || type_opcode == SpvOpTypeSampler))) {
+      return _.diag(SPV_ERROR_INVALID_ID, inst)
+             << "Result type cannot be Op" << spvOpcodeString(type_opcode);
+    }
+  }
+
   // Create a uniqued vector of predecessor ids for comparison against
   // Create a uniqued vector of predecessor ids for comparison against
   // incoming values. OpBranchConditional %cond %label %label produces two
   // incoming values. OpBranchConditional %cond %label %label produces two
   // predecessors in the CFG.
   // predecessors in the CFG.