mirror of
https://github.com/shadps4-emu/shadPS4.git
synced 2025-07-30 22:14:56 +00:00
shader_recompiler: Better BFS search
This commit is contained in:
parent
1638169bed
commit
7044cbcc99
@ -12,16 +12,17 @@
|
|||||||
namespace Shader::IR {
|
namespace Shader::IR {
|
||||||
|
|
||||||
template <typename Pred>
|
template <typename Pred>
|
||||||
auto BreadthFirstSearch(const Value& value, Pred&& pred)
|
auto BreadthFirstSearch(const Inst* inst, Pred&& pred)
|
||||||
-> std::invoke_result_t<Pred, const Inst*> {
|
-> std::invoke_result_t<Pred, const Inst*> {
|
||||||
if (value.IsImmediate()) {
|
// Most often case the instruction is the desired already.
|
||||||
// Nothing to do with immediates
|
if (const std::optional result = pred(inst)) {
|
||||||
return std::nullopt;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Breadth-first search visiting the right most arguments first
|
// Breadth-first search visiting the right most arguments first
|
||||||
boost::container::small_vector<const Inst*, 2> visited;
|
boost::container::small_vector<const Inst*, 2> visited;
|
||||||
std::queue<const Inst*> queue;
|
std::queue<const Inst*> queue;
|
||||||
queue.push(value.InstRecursive());
|
queue.push(inst);
|
||||||
|
|
||||||
while (!queue.empty()) {
|
while (!queue.empty()) {
|
||||||
// Pop one instruction from the queue
|
// Pop one instruction from the queue
|
||||||
@ -49,4 +50,14 @@ auto BreadthFirstSearch(const Value& value, Pred&& pred)
|
|||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename Pred>
|
||||||
|
auto BreadthFirstSearch(const Value& value, Pred&& pred)
|
||||||
|
-> std::invoke_result_t<Pred, const Inst*> {
|
||||||
|
if (value.IsImmediate()) {
|
||||||
|
// Nothing to do with immediates
|
||||||
|
return std::nullopt;
|
||||||
|
}
|
||||||
|
return BreadthFirstSearch(value.InstRecursive(), pred);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Shader::IR
|
} // namespace Shader::IR
|
||||||
|
@ -273,9 +273,18 @@ std::pair<const IR::Inst*, bool> TryDisableAnisoLod0(const IR::Inst* inst) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SharpLocation TrackSharp(const IR::Inst* inst) {
|
SharpLocation TrackSharp(const IR::Inst* inst) {
|
||||||
while (inst->GetOpcode() == IR::Opcode::Phi) {
|
// Search until we find a potential sharp source.
|
||||||
inst = inst->Arg(0).InstRecursive();
|
const auto pred0 = [](const IR::Inst* inst) -> std::optional<const IR::Inst*> {
|
||||||
}
|
if (inst->GetOpcode() == IR::Opcode::GetUserData ||
|
||||||
|
inst->GetOpcode() == IR::Opcode::ReadConst) {
|
||||||
|
return inst;
|
||||||
|
}
|
||||||
|
return std::nullopt;
|
||||||
|
};
|
||||||
|
const auto result = IR::BreadthFirstSearch(inst, pred0);
|
||||||
|
ASSERT_MSG(result, "Unable to track sharp source");
|
||||||
|
inst = result.value();
|
||||||
|
// If its from user data not much else to do.
|
||||||
if (inst->GetOpcode() == IR::Opcode::GetUserData) {
|
if (inst->GetOpcode() == IR::Opcode::GetUserData) {
|
||||||
return SharpLocation{
|
return SharpLocation{
|
||||||
.sgpr_base = u32(IR::ScalarReg::Max),
|
.sgpr_base = u32(IR::ScalarReg::Max),
|
||||||
@ -289,14 +298,14 @@ SharpLocation TrackSharp(const IR::Inst* inst) {
|
|||||||
const IR::Inst* spgpr_base = inst->Arg(0).InstRecursive();
|
const IR::Inst* spgpr_base = inst->Arg(0).InstRecursive();
|
||||||
|
|
||||||
// Retrieve SGPR pair that holds sbase
|
// Retrieve SGPR pair that holds sbase
|
||||||
const auto pred = [](const IR::Inst* inst) -> std::optional<IR::ScalarReg> {
|
const auto pred1 = [](const IR::Inst* inst) -> std::optional<IR::ScalarReg> {
|
||||||
if (inst->GetOpcode() == IR::Opcode::GetUserData) {
|
if (inst->GetOpcode() == IR::Opcode::GetUserData) {
|
||||||
return inst->Arg(0).ScalarReg();
|
return inst->Arg(0).ScalarReg();
|
||||||
}
|
}
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
};
|
};
|
||||||
const auto base0 = IR::BreadthFirstSearch(spgpr_base->Arg(0), pred);
|
const auto base0 = IR::BreadthFirstSearch(spgpr_base->Arg(0), pred1);
|
||||||
const auto base1 = IR::BreadthFirstSearch(spgpr_base->Arg(1), pred);
|
const auto base1 = IR::BreadthFirstSearch(spgpr_base->Arg(1), pred1);
|
||||||
ASSERT_MSG(base0 && base1, "Nested resource loads not supported");
|
ASSERT_MSG(base0 && base1, "Nested resource loads not supported");
|
||||||
|
|
||||||
// Return retrieved location.
|
// Return retrieved location.
|
||||||
@ -456,25 +465,19 @@ IR::Value PatchCubeCoord(IR::IREmitter& ir, const IR::Value& s, const IR::Value&
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descriptors& descriptors) {
|
void PatchImageInstruction(IR::Block& block, IR::Inst& inst, Info& info, Descriptors& descriptors) {
|
||||||
std::deque<IR::Inst*> insts{&inst};
|
const auto pred = [](const IR::Inst* inst) -> std::optional<const IR::Inst*> {
|
||||||
const auto& pred = [](auto opcode) -> bool {
|
const auto opcode = inst->GetOpcode();
|
||||||
return (opcode == IR::Opcode::CompositeConstructU32x2 || // IMAGE_SAMPLE (image+sampler)
|
if (opcode == IR::Opcode::CompositeConstructU32x2 || // IMAGE_SAMPLE (image+sampler)
|
||||||
opcode == IR::Opcode::ReadConst || // IMAGE_LOAD (image only)
|
opcode == IR::Opcode::ReadConst || // IMAGE_LOAD (image only)
|
||||||
opcode == IR::Opcode::GetUserData);
|
opcode == IR::Opcode::GetUserData) {
|
||||||
};
|
return inst;
|
||||||
|
|
||||||
IR::Inst* producer{};
|
|
||||||
while (!insts.empty() && (producer = insts.front(), !pred(producer->GetOpcode()))) {
|
|
||||||
for (auto arg_idx = 0u; arg_idx < producer->NumArgs(); ++arg_idx) {
|
|
||||||
const auto arg = producer->Arg(arg_idx);
|
|
||||||
if (arg.TryInstRecursive()) {
|
|
||||||
insts.push_back(arg.InstRecursive());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
insts.pop_front();
|
return std::nullopt;
|
||||||
}
|
};
|
||||||
ASSERT(pred(producer->GetOpcode()));
|
const auto result = IR::BreadthFirstSearch(&inst, pred);
|
||||||
auto [tsharp_handle, ssharp_handle] = [&] -> std::pair<IR::Inst*, IR::Inst*> {
|
ASSERT_MSG(result, "Unable to find image sharp source");
|
||||||
|
const IR::Inst* producer = result.value();
|
||||||
|
auto [tsharp_handle, ssharp_handle] = [&] -> std::pair<const IR::Inst*, const IR::Inst*> {
|
||||||
if (producer->GetOpcode() == IR::Opcode::CompositeConstructU32x2) {
|
if (producer->GetOpcode() == IR::Opcode::CompositeConstructU32x2) {
|
||||||
return std::make_pair(producer->Arg(0).InstRecursive(),
|
return std::make_pair(producer->Arg(0).InstRecursive(),
|
||||||
producer->Arg(1).InstRecursive());
|
producer->Arg(1).InstRecursive());
|
||||||
|
Loading…
Reference in New Issue
Block a user