diff --git a/3rdparty/spirv-tools/include/generated/build-version.inc b/3rdparty/spirv-tools/include/generated/build-version.inc index 4190dea5d..0c3c9cff9 100644 --- a/3rdparty/spirv-tools/include/generated/build-version.inc +++ b/3rdparty/spirv-tools/include/generated/build-version.inc @@ -1 +1 @@ -"v2020.6", "SPIRV-Tools v2020.6 c0bce01cc910732f92772dde968d6611431e9d09" +"v2020.6", "SPIRV-Tools v2020.6 8c2b99d81e7a2a212e18d68f42f6e85763705093" diff --git a/3rdparty/spirv-tools/include/generated/generators.inc b/3rdparty/spirv-tools/include/generated/generators.inc index b0a58846b..b363a3f09 100644 --- a/3rdparty/spirv-tools/include/generated/generators.inc +++ b/3rdparty/spirv-tools/include/generated/generators.inc @@ -22,4 +22,5 @@ {21, "Google", "Clspv", "Google Clspv"}, {22, "Google", "MLIR SPIR-V Serializer", "Google MLIR SPIR-V Serializer"}, {23, "Google", "Tint Compiler", "Google Tint Compiler"}, -{24, "Google", "ANGLE Shader Compiler", "Google ANGLE Shader Compiler"}, \ No newline at end of file +{24, "Google", "ANGLE Shader Compiler", "Google ANGLE Shader Compiler"}, +{25, "Netease Games", "Messiah Shader Compiler", "Netease Games Messiah Shader Compiler"}, \ No newline at end of file diff --git a/3rdparty/spirv-tools/include/spirv-tools/libspirv.h b/3rdparty/spirv-tools/include/spirv-tools/libspirv.h index 558725b9b..6c7b5de57 100644 --- a/3rdparty/spirv-tools/include/spirv-tools/libspirv.h +++ b/3rdparty/spirv-tools/include/spirv-tools/libspirv.h @@ -326,6 +326,8 @@ typedef enum spv_binary_to_text_options_t { // time, but will use common names for scalar types, and debug names from // OpName instructions. SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES = SPV_BIT(6), + // Add some comments to the generated assembly + SPV_BINARY_TO_TEXT_OPTION_COMMENT = SPV_BIT(7), SPV_FORCE_32_BIT_ENUM(spv_binary_to_text_options_t) } spv_binary_to_text_options_t; diff --git a/3rdparty/spirv-tools/source/disassemble.cpp b/3rdparty/spirv-tools/source/disassemble.cpp index af30ce0be..e76325126 100644 --- a/3rdparty/spirv-tools/source/disassemble.cpp +++ b/3rdparty/spirv-tools/source/disassemble.cpp @@ -54,6 +54,7 @@ class Disassembler { indent_(spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_INDENT, options) ? kStandardIndent : 0), + comment_(spvIsInBitfield(SPV_BINARY_TO_TEXT_OPTION_COMMENT, options)), text_(), out_(print_ ? out_stream() : out_stream(text_)), stream_(out_.get()), @@ -118,6 +119,7 @@ class Disassembler { const bool print_; // Should we also print to the standard output stream? const bool color_; // Should we print in colour? const int indent_; // How much to indent. 0 means don't indent + const int comment_; // Should we comment the source spv_endianness_t endian_; // The detected endianness of the binary. std::stringstream text_; // Captures the text, if not printing. out_stream out_; // The Output stream. Either to text_ or standard output. @@ -126,6 +128,9 @@ class Disassembler { const bool show_byte_offset_; // Should we print byte offset, in hex? size_t byte_offset_; // The number of bytes processed so far. spvtools::NameMapper name_mapper_; + bool inserted_decoration_space_ = false; + bool inserted_debug_space_ = false; + bool inserted_type_space_ = false; }; spv_result_t Disassembler::HandleHeader(spv_endianness_t endian, @@ -134,7 +139,6 @@ spv_result_t Disassembler::HandleHeader(spv_endianness_t endian, endian_ = endian; if (header_) { - SetGrey(); const char* generator_tool = spvGeneratorStr(SPV_GENERATOR_TOOL_PART(generator)); stream_ << "; SPIR-V\n" @@ -150,7 +154,6 @@ spv_result_t Disassembler::HandleHeader(spv_endianness_t endian, stream_ << "; " << SPV_GENERATOR_MISC_PART(generator) << "\n" << "; Bound: " << id_bound << "\n" << "; Schema: " << schema << "\n"; - ResetColor(); } byte_offset_ = SPV_INDEX_INSTRUCTION * sizeof(uint32_t); @@ -160,6 +163,32 @@ spv_result_t Disassembler::HandleHeader(spv_endianness_t endian, spv_result_t Disassembler::HandleInstruction( const spv_parsed_instruction_t& inst) { + auto opcode = static_cast(inst.opcode); + if (comment_ && opcode == SpvOpFunction) { + stream_ << std::endl; + stream_ << std::string(indent_, ' '); + stream_ << "; Function " << name_mapper_(inst.result_id) << std::endl; + } + if (comment_ && !inserted_decoration_space_ && + spvOpcodeIsDecoration(opcode)) { + inserted_decoration_space_ = true; + stream_ << std::endl; + stream_ << std::string(indent_, ' '); + stream_ << "; Annotations" << std::endl; + } + if (comment_ && !inserted_debug_space_ && spvOpcodeIsDebug(opcode)) { + inserted_debug_space_ = true; + stream_ << std::endl; + stream_ << std::string(indent_, ' '); + stream_ << "; Debug Information" << std::endl; + } + if (comment_ && !inserted_type_space_ && spvOpcodeGeneratesType(opcode)) { + inserted_type_space_ = true; + stream_ << std::endl; + stream_ << std::string(indent_, ' '); + stream_ << "; Types, variables and constants" << std::endl; + } + if (inst.result_id) { SetBlue(); const std::string id_name = name_mapper_(inst.result_id); @@ -172,7 +201,7 @@ spv_result_t Disassembler::HandleInstruction( stream_ << std::string(indent_, ' '); } - stream_ << "Op" << spvOpcodeString(static_cast(inst.opcode)); + stream_ << "Op" << spvOpcodeString(opcode); for (uint16_t i = 0; i < inst.num_operands; i++) { const spv_operand_type_t type = inst.operands[i].type; @@ -182,6 +211,12 @@ spv_result_t Disassembler::HandleInstruction( EmitOperand(inst, i); } + if (comment_ && opcode == SpvOpName) { + const spv_parsed_operand_t& operand = inst.operands[0]; + const uint32_t word = inst.words[operand.offset]; + stream_ << " ; id %" << word; + } + if (show_byte_offset_) { SetGrey(); auto saved_flags = stream_.flags(); diff --git a/3rdparty/spirv-tools/source/opt/if_conversion.cpp b/3rdparty/spirv-tools/source/opt/if_conversion.cpp index 104182bc3..4284069a8 100644 --- a/3rdparty/spirv-tools/source/opt/if_conversion.cpp +++ b/3rdparty/spirv-tools/source/opt/if_conversion.cpp @@ -129,6 +129,7 @@ Pass::Status IfConversion::Process() { Instruction* select = builder.AddSelect(phi->type_id(), condition, true_value->result_id(), false_value->result_id()); + select->UpdateDebugInfoFrom(phi); context()->ReplaceAllUsesWith(phi->result_id(), select->result_id()); to_kill.push_back(phi); modified = true; diff --git a/3rdparty/spirv-tools/source/opt/local_access_chain_convert_pass.cpp b/3rdparty/spirv-tools/source/opt/local_access_chain_convert_pass.cpp index b57dd29a6..205cd7a31 100644 --- a/3rdparty/spirv-tools/source/opt/local_access_chain_convert_pass.cpp +++ b/3rdparty/spirv-tools/source/opt/local_access_chain_convert_pass.cpp @@ -95,9 +95,12 @@ bool LocalAccessChainConvertPass::ReplaceAccessChainLoad( return false; } + new_inst[0]->UpdateDebugInfoFrom(original_load); context()->get_decoration_mgr()->CloneDecorations( original_load->result_id(), ldResultId, {SpvDecorationRelaxedPrecision}); original_load->InsertBefore(std::move(new_inst)); + context()->get_debug_info_mgr()->AnalyzeDebugInst( + original_load->PreviousNode()); // Rewrite |original_load| into an extract. Instruction::OperandList new_operands; @@ -181,6 +184,10 @@ bool LocalAccessChainConvertPass::IsConstantIndexAccessChain( bool LocalAccessChainConvertPass::HasOnlySupportedRefs(uint32_t ptrId) { if (supported_ref_ptrs_.find(ptrId) != supported_ref_ptrs_.end()) return true; if (get_def_use_mgr()->WhileEachUser(ptrId, [this](Instruction* user) { + if (user->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugValue || + user->GetOpenCL100DebugOpcode() == OpenCLDebugInfo100DebugDeclare) { + return true; + } SpvOp op = user->opcode(); if (IsNonPtrAccessChain(op) || op == SpvOpCopyObject) { if (!HasOnlySupportedRefs(user->result_id())) { @@ -251,7 +258,6 @@ Pass::Status LocalAccessChainConvertPass::ConvertLocalAccessChains( Instruction* ptrInst = GetPtr(&*ii, &varId); if (!IsNonPtrAccessChain(ptrInst->opcode())) break; if (!IsTargetVar(varId)) break; - std::vector> newInsts; if (!ReplaceAccessChainLoad(ptrInst, &*ii)) { return Status::Failure; } @@ -259,21 +265,26 @@ Pass::Status LocalAccessChainConvertPass::ConvertLocalAccessChains( } break; case SpvOpStore: { uint32_t varId; - Instruction* ptrInst = GetPtr(&*ii, &varId); + Instruction* store = &*ii; + Instruction* ptrInst = GetPtr(store, &varId); if (!IsNonPtrAccessChain(ptrInst->opcode())) break; if (!IsTargetVar(varId)) break; std::vector> newInsts; - uint32_t valId = ii->GetSingleWordInOperand(kStoreValIdInIdx); + uint32_t valId = store->GetSingleWordInOperand(kStoreValIdInIdx); if (!GenAccessChainStoreReplacement(ptrInst, valId, &newInsts)) { return Status::Failure; } size_t num_of_instructions_to_skip = newInsts.size() - 1; - dead_instructions.push_back(&*ii); + dead_instructions.push_back(store); ++ii; ii = ii.InsertBefore(std::move(newInsts)); for (size_t i = 0; i < num_of_instructions_to_skip; ++i) { + ii->UpdateDebugInfoFrom(store); + context()->get_debug_info_mgr()->AnalyzeDebugInst(&*ii); ++ii; } + ii->UpdateDebugInfoFrom(store); + context()->get_debug_info_mgr()->AnalyzeDebugInst(&*ii); modified = true; } break; default: diff --git a/3rdparty/spirv-tools/source/opt/value_number_table.cpp b/3rdparty/spirv-tools/source/opt/value_number_table.cpp index 82549a6dc..32d6de94f 100644 --- a/3rdparty/spirv-tools/source/opt/value_number_table.cpp +++ b/3rdparty/spirv-tools/source/opt/value_number_table.cpp @@ -49,7 +49,8 @@ uint32_t ValueNumberTable::AssignValueNumber(Instruction* inst) { // have its own value number. // OpSampledImage and OpImage must remain in the same basic block in which // they are used, because of this we will assign each one it own value number. - if (!context()->IsCombinatorInstruction(inst)) { + if (!context()->IsCombinatorInstruction(inst) && + !inst->IsOpenCL100DebugInstr()) { value = TakeNextValueNumber(); id_to_value_[inst->result_id()] = value; return value; @@ -173,6 +174,12 @@ void ValueNumberTable::BuildDominatorTreeValueNumberTable() { } } + for (auto& inst : context()->module()->ext_inst_debuginfo()) { + if (inst.result_id() != 0) { + AssignValueNumber(&inst); + } + } + for (Function& func : *context()->module()) { // For best results we want to traverse the code in reverse post order. // This happens naturally because of the forward referencing rules. diff --git a/3rdparty/spirv-tools/source/val/validate.cpp b/3rdparty/spirv-tools/source/val/validate.cpp index f964b9b16..d6e992b15 100644 --- a/3rdparty/spirv-tools/source/val/validate.cpp +++ b/3rdparty/spirv-tools/source/val/validate.cpp @@ -284,9 +284,10 @@ spv_result_t ValidateBinaryUsingContextAndValidationState( const auto execution_model = inst->GetOperandAs(0); const char* str = reinterpret_cast( inst->words().data() + inst->operand(2).offset); + const std::string desc_name(str); ValidationState_t::EntryPointDescription desc; - desc.name = str; + desc.name = desc_name; std::vector interfaces; for (size_t j = 3; j < inst->operands().size(); ++j) @@ -303,7 +304,7 @@ spv_result_t ValidateBinaryUsingContextAndValidationState( check_inst->words().data() + inst->operand(2).offset); const std::string check_name(check_str); - if (desc.name == check_name && + if (desc_name == check_name && execution_model == check_execution_model) { return vstate->diag(SPV_ERROR_INVALID_DATA, inst) << "2 Entry points cannot share the same name and " diff --git a/3rdparty/spirv-tools/source/val/validate_layout.cpp b/3rdparty/spirv-tools/source/val/validate_layout.cpp index 707ad5248..b53f991e8 100644 --- a/3rdparty/spirv-tools/source/val/validate_layout.cpp +++ b/3rdparty/spirv-tools/source/val/validate_layout.cpp @@ -107,6 +107,11 @@ spv_result_t ModuleScopedInstructions(ValidationState_t& _, } while (_.IsOpcodeInCurrentLayoutSection(opcode) == false) { + if (_.IsOpcodeInPreviousLayoutSection(opcode)) { + return _.diag(SPV_ERROR_INVALID_LAYOUT, inst) + << spvOpcodeString(opcode) << " is in an invalid layout section"; + } + _.ProgressToNextLayoutSectionOrder(); switch (_.current_layout_section()) { @@ -135,6 +140,20 @@ spv_result_t ModuleScopedInstructions(ValidationState_t& _, // encountered inside of a function. spv_result_t FunctionScopedInstructions(ValidationState_t& _, const Instruction* inst, SpvOp opcode) { + // Make sure we advance into the function definitions when we hit + // non-function declaration instructions. + if (_.current_layout_section() == kLayoutFunctionDeclarations && + !_.IsOpcodeInCurrentLayoutSection(opcode)) { + _.ProgressToNextLayoutSectionOrder(); + + if (_.in_function_body()) { + if (auto error = _.current_function().RegisterSetFunctionDeclType( + FunctionDecl::kFunctionDeclDefinition)) { + return error; + } + } + } + if (_.IsOpcodeInCurrentLayoutSection(opcode)) { switch (opcode) { case SpvOpFunction: { @@ -208,12 +227,6 @@ spv_result_t FunctionScopedInstructions(ValidationState_t& _, return _.diag(SPV_ERROR_INVALID_LAYOUT, inst) << "A block must end with a branch instruction."; } - if (_.current_layout_section() == kLayoutFunctionDeclarations) { - _.ProgressToNextLayoutSectionOrder(); - if (auto error = _.current_function().RegisterSetFunctionDeclType( - FunctionDecl::kFunctionDeclDefinition)) - return error; - } break; case SpvOpExtInst: diff --git a/3rdparty/spirv-tools/source/val/validation_state.cpp b/3rdparty/spirv-tools/source/val/validation_state.cpp index 72793ecfc..e190b3cb2 100644 --- a/3rdparty/spirv-tools/source/val/validation_state.cpp +++ b/3rdparty/spirv-tools/source/val/validation_state.cpp @@ -30,114 +30,74 @@ namespace spvtools { namespace val { namespace { -bool IsInstructionInLayoutSection(ModuleLayoutSection layout, SpvOp op) { +ModuleLayoutSection InstructionLayoutSection( + ModuleLayoutSection current_section, SpvOp op) { // See Section 2.4 - bool out = false; - // clang-format off - switch (layout) { - case kLayoutCapabilities: out = op == SpvOpCapability; break; - case kLayoutExtensions: out = op == SpvOpExtension; break; - case kLayoutExtInstImport: out = op == SpvOpExtInstImport; break; - case kLayoutMemoryModel: out = op == SpvOpMemoryModel; break; - case kLayoutEntryPoint: out = op == SpvOpEntryPoint; break; - case kLayoutExecutionMode: - out = op == SpvOpExecutionMode || op == SpvOpExecutionModeId; + if (spvOpcodeGeneratesType(op) || spvOpcodeIsConstant(op)) + return kLayoutTypes; + + switch (op) { + case SpvOpCapability: + return kLayoutCapabilities; + case SpvOpExtension: + return kLayoutExtensions; + case SpvOpExtInstImport: + return kLayoutExtInstImport; + case SpvOpMemoryModel: + return kLayoutMemoryModel; + case SpvOpEntryPoint: + return kLayoutEntryPoint; + case SpvOpExecutionMode: + case SpvOpExecutionModeId: + return kLayoutExecutionMode; + case SpvOpSourceContinued: + case SpvOpSource: + case SpvOpSourceExtension: + case SpvOpString: + return kLayoutDebug1; + case SpvOpName: + case SpvOpMemberName: + return kLayoutDebug2; + case SpvOpModuleProcessed: + return kLayoutDebug3; + case SpvOpDecorate: + case SpvOpMemberDecorate: + case SpvOpGroupDecorate: + case SpvOpGroupMemberDecorate: + case SpvOpDecorationGroup: + case SpvOpDecorateId: + case SpvOpDecorateStringGOOGLE: + case SpvOpMemberDecorateStringGOOGLE: + return kLayoutAnnotations; + case SpvOpTypeForwardPointer: + return kLayoutTypes; + case SpvOpVariable: + if (current_section == kLayoutTypes) return kLayoutTypes; + return kLayoutFunctionDefinitions; + case SpvOpExtInst: + // SpvOpExtInst is only allowed in types section for certain extended + // instruction sets. This will be checked separately. + if (current_section == kLayoutTypes) return kLayoutTypes; + return kLayoutFunctionDefinitions; + case SpvOpLine: + case SpvOpNoLine: + case SpvOpUndef: + if (current_section == kLayoutTypes) return kLayoutTypes; + return kLayoutFunctionDefinitions; + case SpvOpFunction: + case SpvOpFunctionParameter: + case SpvOpFunctionEnd: + if (current_section == kLayoutFunctionDeclarations) + return kLayoutFunctionDeclarations; + return kLayoutFunctionDefinitions; + default: break; - case kLayoutDebug1: - switch (op) { - case SpvOpSourceContinued: - case SpvOpSource: - case SpvOpSourceExtension: - case SpvOpString: - out = true; - break; - default: break; - } - break; - case kLayoutDebug2: - switch (op) { - case SpvOpName: - case SpvOpMemberName: - out = true; - break; - default: break; - } - break; - case kLayoutDebug3: - // Only OpModuleProcessed is allowed here. - out = (op == SpvOpModuleProcessed); - break; - case kLayoutAnnotations: - switch (op) { - case SpvOpDecorate: - case SpvOpMemberDecorate: - case SpvOpGroupDecorate: - case SpvOpGroupMemberDecorate: - case SpvOpDecorationGroup: - case SpvOpDecorateId: - case SpvOpDecorateStringGOOGLE: - case SpvOpMemberDecorateStringGOOGLE: - out = true; - break; - default: break; - } - break; - case kLayoutTypes: - if (spvOpcodeGeneratesType(op) || spvOpcodeIsConstant(op)) { - out = true; - break; - } - switch (op) { - case SpvOpTypeForwardPointer: - case SpvOpVariable: - case SpvOpLine: - case SpvOpNoLine: - case SpvOpUndef: - // SpvOpExtInst is only allowed here for certain extended instruction - // sets. This will be checked separately - case SpvOpExtInst: - out = true; - break; - default: break; - } - break; - case kLayoutFunctionDeclarations: - case kLayoutFunctionDefinitions: - // NOTE: These instructions should NOT be in these layout sections - if (spvOpcodeGeneratesType(op) || spvOpcodeIsConstant(op)) { - out = false; - break; - } - switch (op) { - case SpvOpCapability: - case SpvOpExtension: - case SpvOpExtInstImport: - case SpvOpMemoryModel: - case SpvOpEntryPoint: - case SpvOpExecutionMode: - case SpvOpExecutionModeId: - case SpvOpSourceContinued: - case SpvOpSource: - case SpvOpSourceExtension: - case SpvOpString: - case SpvOpName: - case SpvOpMemberName: - case SpvOpModuleProcessed: - case SpvOpDecorate: - case SpvOpMemberDecorate: - case SpvOpGroupDecorate: - case SpvOpGroupMemberDecorate: - case SpvOpDecorationGroup: - case SpvOpTypeForwardPointer: - out = false; - break; - default: - out = true; - break; - } } - // clang-format on - return out; + return kLayoutFunctionDefinitions; +} + +bool IsInstructionInLayoutSection(ModuleLayoutSection layout, SpvOp op) { + return layout == InstructionLayoutSection(layout, op); } // Counts the number of instructions and functions in the file. @@ -311,6 +271,12 @@ void ValidationState_t::ProgressToNextLayoutSectionOrder() { } } +bool ValidationState_t::IsOpcodeInPreviousLayoutSection(SpvOp op) { + ModuleLayoutSection section = + InstructionLayoutSection(current_layout_section_, op); + return section < current_layout_section_; +} + bool ValidationState_t::IsOpcodeInCurrentLayoutSection(SpvOp op) { return IsInstructionInLayoutSection(current_layout_section_, op); } diff --git a/3rdparty/spirv-tools/source/val/validation_state.h b/3rdparty/spirv-tools/source/val/validation_state.h index e852c524c..aeb1ca861 100644 --- a/3rdparty/spirv-tools/source/val/validation_state.h +++ b/3rdparty/spirv-tools/source/val/validation_state.h @@ -195,6 +195,9 @@ class ValidationState_t { /// Increments the module_layout_order_section_ void ProgressToNextLayoutSectionOrder(); + /// Determines if the op instruction is in a previous layout section + bool IsOpcodeInPreviousLayoutSection(SpvOp op); + /// Determines if the op instruction is part of the current section bool IsOpcodeInCurrentLayoutSection(SpvOp op); @@ -718,6 +721,11 @@ class ValidationState_t { // https://github.com/KhronosGroup/Vulkan-Guide/blob/master/chapters/validation_overview.md std::string VkErrorID(uint32_t id, const char* reference = nullptr) const; + // Testing method to allow setting the current layout section. + void SetCurrentLayoutSectionForTesting(ModuleLayoutSection section) { + current_layout_section_ = section; + } + private: ValidationState_t(const ValidationState_t&);