mirror of
https://github.com/bkaradzic/bgfx.git
synced 2026-02-17 20:52:36 +01:00
Updated spirv-tools.
This commit is contained in:
@@ -1 +1 @@
|
||||
"v2020.6", "SPIRV-Tools v2020.6 fecfd7c6d825bb09bd025cbd64db0ecbef420f9a"
|
||||
"v2020.6", "SPIRV-Tools v2020.6 e4fdbb82647a417e30b6da25c632bddf5cf79a58"
|
||||
|
||||
@@ -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"},
|
||||
{26, "Xenia", "Xenia Emulator Microcode Translator", "Xenia Xenia Emulator Microcode Translator"},
|
||||
{27, "Embark Studios", "Rust GPU Compiler Backend", "Embark Studios Rust GPU Compiler Backend"},
|
||||
@@ -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<Instruction*>* 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,
|
||||
|
||||
@@ -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<Instruction*>* invisible_decls);
|
||||
|
||||
@@ -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<Instruction*> 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<Instruction*>& users) const {
|
||||
// Make sure there is exactly 1 store.
|
||||
|
||||
@@ -94,6 +94,10 @@ class LocalSingleStoreElimPass : public Pass {
|
||||
bool RewriteLoads(Instruction* store_inst,
|
||||
const std::vector<Instruction*>& 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<std::string> extensions_allowlist_;
|
||||
};
|
||||
|
||||
@@ -161,6 +161,7 @@ Optimizer& Optimizer::RegisterPerformancePasses() {
|
||||
.RegisterPass(CreateDeadBranchElimPass())
|
||||
.RegisterPass(CreateMergeReturnPass())
|
||||
.RegisterPass(CreateInlineExhaustivePass())
|
||||
.RegisterPass(CreateEliminateDeadFunctionsPass())
|
||||
.RegisterPass(CreateAggressiveDCEPass())
|
||||
.RegisterPass(CreatePrivateToLocalPass())
|
||||
.RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
|
||||
|
||||
106
3rdparty/spirv-tools/source/opt/ssa_rewrite_pass.cpp
vendored
106
3rdparty/spirv-tools/source/opt/ssa_rewrite_pass.cpp
vendored
@@ -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.
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user