diff --git a/3rdparty/spirv-tools/include/generated/build-version.inc b/3rdparty/spirv-tools/include/generated/build-version.inc index 22af5e842..3a782c00d 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 fecfd7c6d825bb09bd025cbd64db0ecbef420f9a" +"v2020.6", "SPIRV-Tools v2020.6 e4fdbb82647a417e30b6da25c632bddf5cf79a58" diff --git a/3rdparty/spirv-tools/include/generated/generators.inc b/3rdparty/spirv-tools/include/generated/generators.inc index 212370fd4..5670308b9 100644 --- a/3rdparty/spirv-tools/include/generated/generators.inc +++ b/3rdparty/spirv-tools/include/generated/generators.inc @@ -24,4 +24,5 @@ {23, "Google", "Tint Compiler", "Google Tint Compiler"}, {24, "Google", "ANGLE Shader Compiler", "Google ANGLE Shader Compiler"}, {25, "Netease Games", "Messiah Shader Compiler", "Netease Games Messiah Shader Compiler"}, -{26, "Xenia", "Xenia Emulator Microcode Translator", "Xenia Xenia Emulator Microcode Translator"}, \ No newline at end of file +{26, "Xenia", "Xenia Emulator Microcode Translator", "Xenia Xenia Emulator Microcode Translator"}, +{27, "Embark Studios", "Rust GPU Compiler Backend", "Embark Studios Rust GPU Compiler Backend"}, \ No newline at end of file diff --git a/3rdparty/spirv-tools/source/opt/debug_info_manager.cpp b/3rdparty/spirv-tools/source/opt/debug_info_manager.cpp index 48285bda6..87ef65537 100644 --- a/3rdparty/spirv-tools/source/opt/debug_info_manager.cpp +++ b/3rdparty/spirv-tools/source/opt/debug_info_manager.cpp @@ -384,7 +384,8 @@ bool DebugInfoManager::IsVariableDebugDeclared(uint32_t variable_id) { return dbg_decl_itr != var_id_to_dbg_decl_.end(); } -void DebugInfoManager::KillDebugDeclares(uint32_t variable_id) { +bool DebugInfoManager::KillDebugDeclares(uint32_t variable_id) { + bool modified = false; auto dbg_decl_itr = var_id_to_dbg_decl_.find(variable_id); if (dbg_decl_itr != var_id_to_dbg_decl_.end()) { // We intentionally copy the list of DebugDeclare instructions because @@ -394,9 +395,11 @@ void DebugInfoManager::KillDebugDeclares(uint32_t variable_id) { for (auto* dbg_decl : copy_dbg_decls) { context()->KillInst(dbg_decl); + modified = true; } var_id_to_dbg_decl_.erase(dbg_decl_itr); } + return modified; } uint32_t DebugInfoManager::GetParentScope(uint32_t child_scope) { @@ -514,16 +517,18 @@ Instruction* DebugInfoManager::AddDebugValueWithIndex( return added_dbg_value; } -void DebugInfoManager::AddDebugValueIfVarDeclIsVisible( +bool DebugInfoManager::AddDebugValueIfVarDeclIsVisible( Instruction* scope_and_line, uint32_t variable_id, uint32_t value_id, Instruction* insert_pos, std::unordered_set* invisible_decls) { - auto dbg_decl_itr = var_id_to_dbg_decl_.find(variable_id); - if (dbg_decl_itr == var_id_to_dbg_decl_.end()) return; + assert(scope_and_line != nullptr); + auto dbg_decl_itr = var_id_to_dbg_decl_.find(variable_id); + if (dbg_decl_itr == var_id_to_dbg_decl_.end()) return false; + + bool modified = false; for (auto* dbg_decl_or_val : dbg_decl_itr->second) { - if (scope_and_line && - !IsDeclareVisibleToInstr(dbg_decl_or_val, scope_and_line)) { + if (!IsDeclareVisibleToInstr(dbg_decl_or_val, scope_and_line)) { if (invisible_decls) invisible_decls->insert(dbg_decl_or_val); continue; } @@ -547,10 +552,11 @@ void DebugInfoManager::AddDebugValueIfVarDeclIsVisible( kDebugValueOperandLocalVariableIndex), value_id, 0, index_id, insert_before); assert(added_dbg_value != nullptr); - added_dbg_value->UpdateDebugInfoFrom(scope_and_line ? scope_and_line - : dbg_decl_or_val); + added_dbg_value->UpdateDebugInfoFrom(scope_and_line); AnalyzeDebugInst(added_dbg_value); + modified = true; } + return modified; } bool DebugInfoManager::AddDebugValueForDecl(Instruction* dbg_decl, diff --git a/3rdparty/spirv-tools/source/opt/debug_info_manager.h b/3rdparty/spirv-tools/source/opt/debug_info_manager.h index edb11b73f..630be4f1d 100644 --- a/3rdparty/spirv-tools/source/opt/debug_info_manager.h +++ b/3rdparty/spirv-tools/source/opt/debug_info_manager.h @@ -138,14 +138,15 @@ class DebugInfoManager { bool IsVariableDebugDeclared(uint32_t variable_id); // Kills all debug declaration instructions with Deref whose 'Local Variable' - // operand is |variable_id|. - void KillDebugDeclares(uint32_t variable_id); + // operand is |variable_id|. Returns whether it kills an instruction or not. + bool KillDebugDeclares(uint32_t variable_id); // Generates a DebugValue instruction with value |value_id| for every local // variable that is in the scope of |scope_and_line| and whose memory is // |variable_id| and inserts it after the instruction |insert_pos|. - // |invisible_decls| returns DebugDeclares invisible to |scope_and_line|. - void AddDebugValueIfVarDeclIsVisible( + // Returns whether a DebugValue is added or not. |invisible_decls| returns + // DebugDeclares invisible to |scope_and_line|. + bool AddDebugValueIfVarDeclIsVisible( Instruction* scope_and_line, uint32_t variable_id, uint32_t value_id, Instruction* insert_pos, std::unordered_set* invisible_decls); diff --git a/3rdparty/spirv-tools/source/opt/local_single_store_elim_pass.cpp b/3rdparty/spirv-tools/source/opt/local_single_store_elim_pass.cpp index f1b8177bc..99c0fb2da 100644 --- a/3rdparty/spirv-tools/source/opt/local_single_store_elim_pass.cpp +++ b/3rdparty/spirv-tools/source/opt/local_single_store_elim_pass.cpp @@ -148,16 +148,41 @@ bool LocalSingleStoreElimPass::ProcessVariable(Instruction* var_inst) { context()->get_type_mgr()->GetType(var_inst->type_id()); const analysis::Type* store_type = var_type->AsPointer()->pointee_type(); if (!(store_type->AsStruct() || store_type->AsArray())) { - context()->get_debug_info_mgr()->AddDebugValueIfVarDeclIsVisible( - nullptr, var_id, store_inst->GetSingleWordInOperand(1), store_inst, - nullptr); - context()->get_debug_info_mgr()->KillDebugDeclares(var_id); + modified |= RewriteDebugDeclares(store_inst, var_id); } } return modified; } +bool LocalSingleStoreElimPass::RewriteDebugDeclares(Instruction* store_inst, + uint32_t var_id) { + std::unordered_set invisible_decls; + uint32_t value_id = store_inst->GetSingleWordInOperand(1); + bool modified = + context()->get_debug_info_mgr()->AddDebugValueIfVarDeclIsVisible( + store_inst, var_id, value_id, store_inst, &invisible_decls); + + // For cases like the argument passing for an inlined function, the value + // assignment is out of DebugDeclare's scope, but we have to preserve the + // value assignment information using DebugValue. Generally, we need + // ssa-rewrite analysis to decide a proper value assignment but at this point + // we confirm that |var_id| has a single store. We can safely add DebugValue. + if (!invisible_decls.empty()) { + BasicBlock* store_block = context()->get_instr_block(store_inst); + DominatorAnalysis* dominator_analysis = + context()->GetDominatorAnalysis(store_block->GetParent()); + for (auto* decl : invisible_decls) { + if (dominator_analysis->Dominates(store_inst, decl)) { + context()->get_debug_info_mgr()->AddDebugValueForDecl(decl, value_id); + modified = true; + } + } + } + modified |= context()->get_debug_info_mgr()->KillDebugDeclares(var_id); + return modified; +} + Instruction* LocalSingleStoreElimPass::FindSingleStoreAndCheckUses( Instruction* var_inst, const std::vector& users) const { // Make sure there is exactly 1 store. diff --git a/3rdparty/spirv-tools/source/opt/local_single_store_elim_pass.h b/3rdparty/spirv-tools/source/opt/local_single_store_elim_pass.h index d66a441a0..3aa0f02aa 100644 --- a/3rdparty/spirv-tools/source/opt/local_single_store_elim_pass.h +++ b/3rdparty/spirv-tools/source/opt/local_single_store_elim_pass.h @@ -94,6 +94,10 @@ class LocalSingleStoreElimPass : public Pass { bool RewriteLoads(Instruction* store_inst, const std::vector& uses, bool* all_rewritten); + // Replaces DebugDeclares of |var_id| with DebugValues using the value + // assignment of |store_inst|. + bool RewriteDebugDeclares(Instruction* store_inst, uint32_t var_id); + // Extensions supported by this pass. std::unordered_set extensions_allowlist_; }; diff --git a/3rdparty/spirv-tools/source/opt/optimizer.cpp b/3rdparty/spirv-tools/source/opt/optimizer.cpp index bc1441114..1ded2ee9b 100644 --- a/3rdparty/spirv-tools/source/opt/optimizer.cpp +++ b/3rdparty/spirv-tools/source/opt/optimizer.cpp @@ -161,6 +161,7 @@ Optimizer& Optimizer::RegisterPerformancePasses() { .RegisterPass(CreateDeadBranchElimPass()) .RegisterPass(CreateMergeReturnPass()) .RegisterPass(CreateInlineExhaustivePass()) + .RegisterPass(CreateEliminateDeadFunctionsPass()) .RegisterPass(CreateAggressiveDCEPass()) .RegisterPass(CreatePrivateToLocalPass()) .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass()) diff --git a/3rdparty/spirv-tools/source/opt/ssa_rewrite_pass.cpp b/3rdparty/spirv-tools/source/opt/ssa_rewrite_pass.cpp index 5a5688706..3ff036190 100644 --- a/3rdparty/spirv-tools/source/opt/ssa_rewrite_pass.cpp +++ b/3rdparty/spirv-tools/source/opt/ssa_rewrite_pass.cpp @@ -47,6 +47,7 @@ #include "source/opcode.h" #include "source/opt/cfg.h" #include "source/opt/mem_pass.h" +#include "source/opt/types.h" #include "source/util/make_unique.h" // Debug logging (0: Off, 1-N: Verbosity level). Replace this with the @@ -326,32 +327,94 @@ void SSARewriter::ProcessStore(Instruction* inst, BasicBlock* bb) { } bool SSARewriter::ProcessLoad(Instruction* inst, BasicBlock* bb) { + // Get the pointer that we are using to load from. uint32_t var_id = 0; (void)pass_->GetPtr(inst, &var_id); - if (pass_->IsTargetVar(var_id)) { - // Get the immediate reaching definition for |var_id|. - uint32_t val_id = GetReachingDef(var_id, bb); + + // Get the immediate reaching definition for |var_id|. + // + // In the presence of variable pointers, the reaching definition may be + // another pointer. For example, the following fragment: + // + // %2 = OpVariable %_ptr_Input_float Input + // %11 = OpVariable %_ptr_Function__ptr_Input_float Function + // OpStore %11 %2 + // %12 = OpLoad %_ptr_Input_float %11 + // %13 = OpLoad %float %12 + // + // corresponds to the pseudo-code: + // + // layout(location = 0) in flat float *%2 + // float %13; + // float *%12; + // float **%11; + // *%11 = %2; + // %12 = *%11; + // %13 = *%12; + // + // which ultimately, should correspond to: + // + // %13 = *%2; + // + // During rewriting, the pointer %12 is found to be replaceable by %2 (i.e., + // load_replacement_[12] is 2). However, when processing the load + // %13 = *%12, the type of %12's reaching definition is another float + // pointer (%2), instead of a float value. + // + // When this happens, we need to continue looking up the reaching definition + // chain until we get to a float value or a non-target var (i.e. a variable + // that cannot be SSA replaced, like %2 in this case since it is a function + // argument). + analysis::DefUseManager* def_use_mgr = pass_->context()->get_def_use_mgr(); + analysis::TypeManager* type_mgr = pass_->context()->get_type_mgr(); + analysis::Type* load_type = type_mgr->GetType(inst->type_id()); + uint32_t val_id = 0; + bool found_reaching_def = false; + while (!found_reaching_def) { + if (!pass_->IsTargetVar(var_id)) { + // If the variable we are loading from is not an SSA target (globals, + // function parameters), do nothing. + return true; + } + + val_id = GetReachingDef(var_id, bb); if (val_id == 0) { return false; } - // Schedule a replacement for the result of this load instruction with - // |val_id|. After all the rewriting decisions are made, every use of - // this load will be replaced with |val_id|. - const uint32_t load_id = inst->result_id(); - assert(load_replacement_.count(load_id) == 0); - load_replacement_[load_id] = val_id; - PhiCandidate* defining_phi = GetPhiCandidate(val_id); - if (defining_phi) { - defining_phi->AddUser(load_id); + // If the reaching definition is a pointer type different than the type of + // the instruction we are analyzing, then it must be a reference to another + // pointer (otherwise, this would be invalid SPIRV). We continue + // de-referencing it by making |val_id| be |var_id|. + // + // NOTE: if there is no reaching definition instruction, it means |val_id| + // is an undef. + Instruction* reaching_def_inst = def_use_mgr->GetDef(val_id); + if (reaching_def_inst && + !type_mgr->GetType(reaching_def_inst->type_id())->IsSame(load_type)) { + var_id = val_id; + } else { + found_reaching_def = true; } + } + + // Schedule a replacement for the result of this load instruction with + // |val_id|. After all the rewriting decisions are made, every use of + // this load will be replaced with |val_id|. + uint32_t load_id = inst->result_id(); + assert(load_replacement_.count(load_id) == 0); + load_replacement_[load_id] = val_id; + PhiCandidate* defining_phi = GetPhiCandidate(val_id); + if (defining_phi) { + defining_phi->AddUser(load_id); + } #if SSA_REWRITE_DEBUGGING_LEVEL > 1 - std::cerr << "\tFound load: " - << inst->PrettyPrint(SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES) - << " (replacement for %" << load_id << " is %" << val_id << ")\n"; + std::cerr << "\tFound load: " + << inst->PrettyPrint(SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES) + << " (replacement for %" << load_id << " is %" << val_id << ")\n"; #endif - } + return true; } @@ -390,8 +453,8 @@ bool SSARewriter::GenerateSSAReplacements(BasicBlock* bb) { } } - // Seal |bb|. This means that all the stores in it have been scanned and it's - // ready to feed them into its successors. + // Seal |bb|. This means that all the stores in it have been scanned and + // it's ready to feed them into its successors. SealBlock(bb); #if SSA_REWRITE_DEBUGGING_LEVEL > 1 @@ -504,8 +567,8 @@ bool SSARewriter::ApplyReplacements() { } // Scan uses for all inserted Phi instructions. Do this separately from the - // registration of the Phi instruction itself to avoid trying to analyze uses - // of Phi instructions that have not been registered yet. + // registration of the Phi instruction itself to avoid trying to analyze + // uses of Phi instructions that have not been registered yet. for (Instruction* phi_inst : generated_phis) { pass_->get_def_use_mgr()->AnalyzeInstUse(&*phi_inst); } @@ -562,7 +625,8 @@ void SSARewriter::FinalizePhiCandidate(PhiCandidate* phi_candidate) { // This candidate is now completed. phi_candidate->MarkComplete(); - // If |phi_candidate| is not trivial, add it to the list of Phis to generate. + // If |phi_candidate| is not trivial, add it to the list of Phis to + // generate. if (TryRemoveTrivialPhi(phi_candidate) == phi_candidate->result_id()) { // If we could not remove |phi_candidate|, it means that it is complete // and not trivial. Add it to the list of Phis to generate. diff --git a/3rdparty/spirv-tools/source/val/validate_builtins.cpp b/3rdparty/spirv-tools/source/val/validate_builtins.cpp index 1d85f8877..2c5604cd5 100644 --- a/3rdparty/spirv-tools/source/val/validate_builtins.cpp +++ b/3rdparty/spirv-tools/source/val/validate_builtins.cpp @@ -2603,17 +2603,19 @@ spv_result_t BuiltInsValidator::ValidateLayerOrViewportIndexAtReference( assert(function_id_ == 0); for (const auto em : {SpvExecutionModelVertex, SpvExecutionModelTessellationEvaluation, - SpvExecutionModelGeometry}) { + SpvExecutionModelGeometry, SpvExecutionModelMeshNV}) { id_to_at_reference_checks_[referenced_from_inst.id()].push_back( - std::bind(&BuiltInsValidator::ValidateNotCalledWithExecutionModel, - this, - "Vulkan spec doesn't allow BuiltIn Layer and " - "ViewportIndex to be " - "used for variables with Input storage class if " - "execution model is Vertex, TessellationEvaluation, or " - "Geometry.", - em, decoration, built_in_inst, referenced_from_inst, - std::placeholders::_1)); + std::bind( + &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, + std::string( + _.VkErrorID((operand == SpvBuiltInLayer) ? 4274 : 4406) + + "Vulkan spec doesn't allow BuiltIn Layer and " + "ViewportIndex to be " + "used for variables with Input storage class if " + "execution model is Vertex, TessellationEvaluation, " + "Geometry, or MeshNV."), + em, decoration, built_in_inst, referenced_from_inst, + std::placeholders::_1)); } } @@ -2621,11 +2623,12 @@ spv_result_t BuiltInsValidator::ValidateLayerOrViewportIndexAtReference( assert(function_id_ == 0); id_to_at_reference_checks_[referenced_from_inst.id()].push_back(std::bind( &BuiltInsValidator::ValidateNotCalledWithExecutionModel, this, - "Vulkan spec doesn't allow BuiltIn Layer and " - "ViewportIndex to be " - "used for variables with Output storage class if " - "execution model is " - "Fragment.", + std::string(_.VkErrorID((operand == SpvBuiltInLayer) ? 4275 : 4407) + + "Vulkan spec doesn't allow BuiltIn Layer and " + "ViewportIndex to be " + "used for variables with Output storage class if " + "execution model is " + "Fragment."), SpvExecutionModelFragment, decoration, built_in_inst, referenced_from_inst, std::placeholders::_1)); } diff --git a/3rdparty/spirv-tools/source/val/validation_state.cpp b/3rdparty/spirv-tools/source/val/validation_state.cpp index e190b3cb2..cb69dda30 100644 --- a/3rdparty/spirv-tools/source/val/validation_state.cpp +++ b/3rdparty/spirv-tools/source/val/validation_state.cpp @@ -1377,6 +1377,10 @@ std::string ValidationState_t::VkErrorID(uint32_t id, return VUID_WRAP(VUID-InstanceIndex-InstanceIndex-04265); case 4272: return VUID_WRAP(VUID-Layer-Layer-04272); + case 4274: + return VUID_WRAP(VUID-Layer-Layer-04274); + case 4275: + return VUID_WRAP(VUID-Layer-Layer-04275); case 4276: return VUID_WRAP(VUID-Layer-Layer-04276); case 4281: @@ -1469,6 +1473,10 @@ std::string ValidationState_t::VkErrorID(uint32_t id, return VUID_WRAP(VUID-ViewIndex-ViewIndex-04403); case 4404: return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04404); + case 4406: + return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04406); + case 4407: + return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04407); case 4408: return VUID_WRAP(VUID-ViewportIndex-ViewportIndex-04408); case 4422: @@ -1483,6 +1491,18 @@ std::string ValidationState_t::VkErrorID(uint32_t id, return VUID_WRAP(VUID-WorkgroupSize-WorkgroupSize-04426); case 4427: return VUID_WRAP(VUID-WorkgroupSize-WorkgroupSize-04427); + case 4484: + return VUID_WRAP(VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-04484); + case 4485: + return VUID_WRAP(VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-04485); + case 4486: + return VUID_WRAP(VUID-PrimitiveShadingRateKHR-PrimitiveShadingRateKHR-04486); + case 4490: + return VUID_WRAP(VUID-ShadingRateKHR-ShadingRateKHR-04490); + case 4491: + return VUID_WRAP(VUID-ShadingRateKHR-ShadingRateKHR-04491); + case 4492: + return VUID_WRAP(VUID-ShadingRateKHR-ShadingRateKHR-04492); default: return ""; // unknown id };