Updated spirv-tools.
This commit is contained in:
parent
eff6f13011
commit
f334d0c1cb
31
3rdparty/spirv-tools/CHANGES
vendored
31
3rdparty/spirv-tools/CHANGES
vendored
@ -1,7 +1,34 @@
|
||||
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
|
||||
- General:
|
||||
|
@ -1 +1 @@
|
||||
"v2020.2-dev", "SPIRV-Tools v2020.2-dev 9897187ba975fbb16bbce48d1d45761bf27bfac1"
|
||||
"v2020.3-dev", "SPIRV-Tools v2020.3-dev eff6f130119f3e6acbf81f8432c0912296d4dfdb"
|
||||
|
@ -931,6 +931,7 @@ void AggressiveDCEPass::InitExtensions() {
|
||||
"SPV_NV_shading_rate",
|
||||
"SPV_NV_mesh_shader",
|
||||
"SPV_NV_ray_tracing",
|
||||
"SPV_KHR_ray_tracing",
|
||||
"SPV_EXT_fragment_invocation_density",
|
||||
"SPV_EXT_physical_storage_buffer",
|
||||
});
|
||||
|
17
3rdparty/spirv-tools/source/opt/function.cpp
vendored
17
3rdparty/spirv-tools/source/opt/function.cpp
vendored
@ -34,6 +34,11 @@ Function* Function::Clone(IRContext* ctx) const {
|
||||
},
|
||||
true);
|
||||
|
||||
for (const auto& i : debug_insts_in_header_) {
|
||||
clone->AddDebugInstructionInHeader(
|
||||
std::unique_ptr<Instruction>(i.Clone(ctx)));
|
||||
}
|
||||
|
||||
clone->blocks_.reserve(blocks_.size());
|
||||
for (const auto& b : blocks_) {
|
||||
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_) {
|
||||
if (!bb->WhileEachInst(f, run_on_debug_line_insts)) {
|
||||
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_) {
|
||||
if (!static_cast<const BasicBlock*>(bb.get())->WhileEachInst(
|
||||
f, run_on_debug_line_insts)) {
|
||||
|
9
3rdparty/spirv-tools/source/opt/function.h
vendored
9
3rdparty/spirv-tools/source/opt/function.h
vendored
@ -56,6 +56,8 @@ class Function {
|
||||
|
||||
// Appends a parameter to this function.
|
||||
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.
|
||||
inline void AddBasicBlock(std::unique_ptr<BasicBlock> b);
|
||||
// Appends a basic block to this function at the position |ip|.
|
||||
@ -151,6 +153,8 @@ class Function {
|
||||
std::unique_ptr<Instruction> def_inst_;
|
||||
// All parameters to this function.
|
||||
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
|
||||
std::vector<std::unique_ptr<BasicBlock>> blocks_;
|
||||
// The OpFunctionEnd instruction.
|
||||
@ -167,6 +171,11 @@ inline void Function::AddParameter(std::unique_ptr<Instruction> 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) {
|
||||
AddBasicBlock(std::move(b), end());
|
||||
}
|
||||
|
106
3rdparty/spirv-tools/source/opt/instruction.cpp
vendored
106
3rdparty/spirv-tools/source/opt/instruction.cpp
vendored
@ -16,6 +16,7 @@
|
||||
|
||||
#include <initializer_list>
|
||||
|
||||
#include "OpenCLDebugInfo100.h"
|
||||
#include "source/disassemble.h"
|
||||
#include "source/opt/fold.h"
|
||||
#include "source/opt/ir_context.h"
|
||||
@ -30,6 +31,11 @@ const uint32_t kTypeImageDimIndex = 1;
|
||||
const uint32_t kLoadBaseIndex = 0;
|
||||
const uint32_t kVariableStorageClassIndex = 0;
|
||||
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
|
||||
|
||||
Instruction::Instruction(IRContext* c)
|
||||
@ -38,7 +44,8 @@ Instruction::Instruction(IRContext* c)
|
||||
opcode_(SpvOpNop),
|
||||
has_type_id_(false),
|
||||
has_result_id_(false),
|
||||
unique_id_(c->TakeNextUniqueId()) {}
|
||||
unique_id_(c->TakeNextUniqueId()),
|
||||
dbg_scope_(kNoDebugScope, kNoInlinedAt) {}
|
||||
|
||||
Instruction::Instruction(IRContext* c, SpvOp op)
|
||||
: utils::IntrusiveNodeBase<Instruction>(),
|
||||
@ -46,7 +53,8 @@ Instruction::Instruction(IRContext* c, SpvOp op)
|
||||
opcode_(op),
|
||||
has_type_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,
|
||||
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_result_id_(inst.result_id != 0),
|
||||
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()) &&
|
||||
"Op(No)Line attaching to Op(No)Line found");
|
||||
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,
|
||||
uint32_t res_id, const OperandList& in_operands)
|
||||
: utils::IntrusiveNodeBase<Instruction>(),
|
||||
@ -75,7 +101,8 @@ Instruction::Instruction(IRContext* c, SpvOp op, uint32_t ty_id,
|
||||
has_type_id_(ty_id != 0),
|
||||
has_result_id_(res_id != 0),
|
||||
unique_id_(c->TakeNextUniqueId()),
|
||||
operands_() {
|
||||
operands_(),
|
||||
dbg_scope_(kNoDebugScope, kNoInlinedAt) {
|
||||
if (has_type_id_) {
|
||||
operands_.emplace_back(spv_operand_type_t::SPV_OPERAND_TYPE_TYPE_ID,
|
||||
std::initializer_list<uint32_t>{ty_id});
|
||||
@ -94,7 +121,12 @@ Instruction::Instruction(Instruction&& that)
|
||||
has_result_id_(that.has_result_id_),
|
||||
unique_id_(that.unique_id_),
|
||||
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) {
|
||||
opcode_ = that.opcode_;
|
||||
@ -103,6 +135,7 @@ Instruction& Instruction::operator=(Instruction&& that) {
|
||||
unique_id_ = that.unique_id_;
|
||||
operands_ = std::move(that.operands_);
|
||||
dbg_line_insts_ = std::move(that.dbg_line_insts_);
|
||||
dbg_scope_ = that.dbg_scope_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -114,6 +147,7 @@ Instruction* Instruction::Clone(IRContext* c) const {
|
||||
clone->unique_id_ = c->TakeNextUniqueId();
|
||||
clone->operands_ = operands_;
|
||||
clone->dbg_line_insts_ = dbg_line_insts_;
|
||||
clone->dbg_scope_ = dbg_scope_;
|
||||
return clone;
|
||||
}
|
||||
|
||||
@ -198,6 +232,14 @@ bool Instruction::IsVulkanStorageImage() const {
|
||||
|
||||
Instruction* base_type =
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
@ -224,6 +266,14 @@ bool Instruction::IsVulkanSampledImage() const {
|
||||
|
||||
Instruction* base_type =
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
@ -250,6 +300,14 @@ bool Instruction::IsVulkanStorageTexelBuffer() const {
|
||||
|
||||
Instruction* base_type =
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
@ -273,6 +331,13 @@ bool Instruction::IsVulkanStorageBuffer() const {
|
||||
Instruction* base_type =
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
@ -306,6 +371,14 @@ bool Instruction::IsVulkanUniformBuffer() const {
|
||||
|
||||
Instruction* base_type =
|
||||
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) {
|
||||
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 spvtools
|
||||
|
60
3rdparty/spirv-tools/source/opt/instruction.h
vendored
60
3rdparty/spirv-tools/source/opt/instruction.h
vendored
@ -32,6 +32,9 @@
|
||||
#include "source/opt/reflect.h"
|
||||
#include "spirv-tools/libspirv.h"
|
||||
|
||||
const uint32_t kNoDebugScope = 0;
|
||||
const uint32_t kNoInlinedAt = 0;
|
||||
|
||||
namespace spvtools {
|
||||
namespace opt {
|
||||
|
||||
@ -100,6 +103,44 @@ inline bool operator!=(const Operand& o1, const Operand& 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
|
||||
// operand, including the result id (if any) and result type id (if any). It
|
||||
// may also contain line-related debug instruction (OpLine, OpNoLine) directly
|
||||
@ -120,7 +161,8 @@ class Instruction : public utils::IntrusiveNodeBase<Instruction> {
|
||||
opcode_(SpvOpNop),
|
||||
has_type_id_(false),
|
||||
has_result_id_(false),
|
||||
unique_id_(0) {}
|
||||
unique_id_(0),
|
||||
dbg_scope_(kNoDebugScope, kNoInlinedAt) {}
|
||||
|
||||
// Creates a default OpNop instruction.
|
||||
Instruction(IRContext*);
|
||||
@ -134,6 +176,9 @@ class Instruction : public utils::IntrusiveNodeBase<Instruction> {
|
||||
Instruction(IRContext* c, const spv_parsed_instruction_t& inst,
|
||||
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|,
|
||||
// result id: |res_id| and input operands: |in_operands|.
|
||||
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
|
||||
inline void SetResultId(uint32_t res_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
|
||||
void RemoveOperand(uint32_t index) {
|
||||
operands_.erase(operands_.begin() + index);
|
||||
@ -482,6 +530,9 @@ class Instruction : public utils::IntrusiveNodeBase<Instruction> {
|
||||
// empty.
|
||||
std::vector<Instruction> dbg_line_insts_;
|
||||
|
||||
// DebugScope that wraps this instruction.
|
||||
DebugScope dbg_scope_;
|
||||
|
||||
friend InstructionList;
|
||||
};
|
||||
|
||||
@ -553,6 +604,13 @@ inline void Instruction::SetResultId(uint32_t 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) {
|
||||
// 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,
|
||||
|
140
3rdparty/spirv-tools/source/opt/ir_loader.cpp
vendored
140
3rdparty/spirv-tools/source/opt/ir_loader.cpp
vendored
@ -23,6 +23,10 @@
|
||||
#include "source/opt/reflect.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 opt {
|
||||
|
||||
@ -30,16 +34,60 @@ IrLoader::IrLoader(const MessageConsumer& consumer, Module* m)
|
||||
: consumer_(consumer),
|
||||
module_(m),
|
||||
source_("<instruction>"),
|
||||
inst_index_(0) {}
|
||||
inst_index_(0),
|
||||
last_dbg_scope_(kNoDebugScope, kNoInlinedAt) {}
|
||||
|
||||
bool IrLoader::AddInstruction(const spv_parsed_instruction_t* inst) {
|
||||
++inst_index_;
|
||||
const auto opcode = static_cast<SpvOp>(inst->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;
|
||||
}
|
||||
|
||||
// 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(
|
||||
new Instruction(module()->context(), *inst, std::move(dbg_line_info_)));
|
||||
dbg_line_info_.clear();
|
||||
@ -90,6 +138,7 @@ bool IrLoader::AddInstruction(const spv_parsed_instruction_t* inst) {
|
||||
block_->AddInstruction(std::move(spv_inst));
|
||||
function_->AddBasicBlock(std::move(block_));
|
||||
block_ = nullptr;
|
||||
last_dbg_scope_ = DebugScope(kNoDebugScope, kNoInlinedAt);
|
||||
} else {
|
||||
if (function_ == nullptr) { // Outside function definition
|
||||
SPIRV_ASSERT(consumer_, block_ == nullptr);
|
||||
@ -131,26 +180,32 @@ bool IrLoader::AddInstruction(const spv_parsed_instruction_t* inst) {
|
||||
return false;
|
||||
}
|
||||
} 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,
|
||||
"Debug info extension instruction other than DebugScope, "
|
||||
"DebugNoScope, DebugDeclare, and DebugValue found inside "
|
||||
@ -158,13 +213,26 @@ bool IrLoader::AddInstruction(const spv_parsed_instruction_t* inst) {
|
||||
opcode);
|
||||
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,
|
||||
"Debug info extension instruction other than DebugScope, "
|
||||
"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
3rdparty/spirv-tools/source/opt/ir_loader.h
vendored
3
3rdparty/spirv-tools/source/opt/ir_loader.h
vendored
@ -78,6 +78,9 @@ class IrLoader {
|
||||
std::unique_ptr<BasicBlock> block_;
|
||||
// Line related debug instructions accumulated thus far.
|
||||
std::vector<Instruction> dbg_line_info_;
|
||||
|
||||
// The last DebugScope information that IrLoader::AddInstruction() handled.
|
||||
DebugScope last_dbg_scope_;
|
||||
};
|
||||
|
||||
} // namespace opt
|
||||
|
@ -379,6 +379,7 @@ void LocalAccessChainConvertPass::InitExtensions() {
|
||||
"SPV_NV_shading_rate",
|
||||
"SPV_NV_mesh_shader",
|
||||
"SPV_NV_ray_tracing",
|
||||
"SPV_KHR_ray_tracing",
|
||||
"SPV_KHR_ray_query",
|
||||
"SPV_EXT_fragment_invocation_density",
|
||||
});
|
||||
|
@ -256,6 +256,7 @@ void LocalSingleBlockLoadStoreElimPass::InitExtensions() {
|
||||
"SPV_NV_shading_rate",
|
||||
"SPV_NV_mesh_shader",
|
||||
"SPV_NV_ray_tracing",
|
||||
"SPV_KHR_ray_tracing",
|
||||
"SPV_KHR_ray_query",
|
||||
"SPV_EXT_fragment_invocation_density",
|
||||
"SPV_EXT_physical_storage_buffer",
|
||||
|
21
3rdparty/spirv-tools/source/opt/module.cpp
vendored
21
3rdparty/spirv-tools/source/opt/module.cpp
vendored
@ -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_.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);
|
||||
|
||||
// We create new instructions for DebugScope. The bound must be updated.
|
||||
binary->data()[bound_idx] = header_.bound;
|
||||
}
|
||||
|
||||
uint32_t Module::ComputeIdBound() const {
|
||||
|
12
3rdparty/spirv-tools/source/opt/module.h
vendored
12
3rdparty/spirv-tools/source/opt/module.h
vendored
@ -17,6 +17,7 @@
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
@ -48,7 +49,7 @@ class Module {
|
||||
using const_inst_iterator = InstructionList::const_iterator;
|
||||
|
||||
// Creates an empty module with zero'd header.
|
||||
Module() : header_({}) {}
|
||||
Module() : header_({}), contains_debug_scope_(false) {}
|
||||
|
||||
// Sets the header to the given |header|.
|
||||
void SetHeader(const ModuleHeader& header) { header_ = header; }
|
||||
@ -118,6 +119,10 @@ class Module {
|
||||
// Appends a function to this module.
|
||||
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
|
||||
// module.
|
||||
std::vector<Instruction*> GetTypes();
|
||||
@ -295,6 +300,9 @@ class Module {
|
||||
// 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.
|
||||
std::vector<Instruction> trailing_dbg_line_info_;
|
||||
|
||||
// This module contains DebugScope or DebugNoScope.
|
||||
bool contains_debug_scope_;
|
||||
};
|
||||
|
||||
// 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));
|
||||
}
|
||||
|
||||
inline void Module::SetContainsDebugScope() { contains_debug_scope_ = true; }
|
||||
|
||||
inline Module::inst_iterator Module::capability_begin() {
|
||||
return capabilities_.begin();
|
||||
}
|
||||
|
@ -569,7 +569,12 @@ bool Optimizer::Run(const uint32_t* original_binary,
|
||||
}
|
||||
|
||||
#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;
|
||||
context->module()->ToBinary(&optimized_binary_with_nop,
|
||||
/* skip_nop = */ false);
|
||||
|
@ -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
|
||||
// incoming values. OpBranchConditional %cond %label %label produces two
|
||||
// predecessors in the CFG.
|
||||
|
Loading…
x
Reference in New Issue
Block a user