mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-31 09:28:29 +00:00
shader: treat call-target registers with several reaching definitions as GPU-selected
This commit is contained in:
1 parent
ee034be4b2
commit
abd77f574c
4 files changed
+19
-5
No files matched your search
@@ -504,8 +504,11 @@ void PrepareCallTargets(ShaderSource& source, const CompileOptions& options) {
|
|||||||
};
|
};
|
||||||
Register = [&](uint32_t before, uint32_t code) -> Value {
|
Register = [&](uint32_t before, uint32_t code) -> Value {
|
||||||
std::vector<uint32_t> crossed_calls;
|
std::vector<uint32_t> crossed_calls;
|
||||||
const auto index = CFG::FindScalarDefinition(source.decoded, graph, before, code,
|
const auto definition = CFG::FindScalarDefinition(source.decoded, graph, before, code,
|
||||||
source.wave_size, crossed_calls);
|
source.wave_size, crossed_calls);
|
||||||
|
// Several reaching definitions select the value on the GPU, so no SRT walk evaluates it.
|
||||||
|
if (!definition) return Value(&block.AppendNewInst(ValueOpcode::UndefU32));
|
||||||
|
const auto index = *definition;
|
||||||
for (const auto crossed: crossed_calls) {
|
for (const auto crossed: crossed_calls) {
|
||||||
std::ranges::find(source.calls, crossed, &ShaderSource::Call::instruction)->preserved_registers.set(code);
|
std::ranges::find(source.calls, crossed, &ShaderSource::Call::instruction)->preserved_registers.set(code);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1720,7 +1720,7 @@ bool MayWriteScalarRegister(const Decoder::Instruction& inst, uint32_t code, uin
|
|||||||
return InstructionWritesScalarCode(inst, code);
|
return InstructionWritesScalarCode(inst, code);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t FindScalarDefinition(const Decoder::Program& program, const Graph& graph,
|
std::optional<uint32_t> FindScalarDefinition(const Decoder::Program& program, const Graph& graph,
|
||||||
uint32_t before, uint32_t code, uint32_t wave_size,
|
uint32_t before, uint32_t code, uint32_t wave_size,
|
||||||
std::vector<uint32_t>& crossed_calls) {
|
std::vector<uint32_t>& crossed_calls) {
|
||||||
EXIT_IF(before >= program.instructions.size());
|
EXIT_IF(before >= program.instructions.size());
|
||||||
@@ -1748,7 +1748,7 @@ uint32_t FindScalarDefinition(const Decoder::Program& program, const Graph& grap
|
|||||||
if (MayWriteScalarRegister(inst, code, wave_size)) { index = i; break; }
|
if (MayWriteScalarRegister(inst, code, wave_size)) { index = i; break; }
|
||||||
}
|
}
|
||||||
if (index != UINT32_MAX || block->id == graph.entry_block) {
|
if (index != UINT32_MAX || block->id == graph.entry_block) {
|
||||||
EXIT_IF(definition && *definition != index);
|
if (definition && *definition != index) return std::nullopt;
|
||||||
definition = index;
|
definition = index;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -1758,7 +1758,7 @@ uint32_t FindScalarDefinition(const Decoder::Program& program, const Graph& grap
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
EXIT_IF(!definition);
|
EXIT_IF(!definition);
|
||||||
return *definition;
|
return definition;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string BranchConditionToString(BranchCondition condition) {
|
std::string BranchConditionToString(BranchCondition condition) {
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include "common/stringUtils.h"
|
#include "common/stringUtils.h"
|
||||||
#include "graphics/shader/recompiler/frontend/decode/ShaderDecoder.h"
|
#include "graphics/shader/recompiler/frontend/decode/ShaderDecoder.h"
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace Libs::Graphics::ShaderRecompiler::CFG {
|
namespace Libs::Graphics::ShaderRecompiler::CFG {
|
||||||
@@ -114,7 +115,9 @@ struct Graph {
|
|||||||
|
|
||||||
Graph BuildGraph(const Decoder::Program& program);
|
Graph BuildGraph(const Decoder::Program& program);
|
||||||
bool MayWriteScalarRegister(const Decoder::Instruction& inst, uint32_t code, uint32_t wave_size);
|
bool MayWriteScalarRegister(const Decoder::Instruction& inst, uint32_t code, uint32_t wave_size);
|
||||||
uint32_t FindScalarDefinition(const Decoder::Program& program, const Graph& graph,
|
// Returns the one instruction defining `code` that reaches `before` (UINT32_MAX: the entry value),
|
||||||
|
// or nullopt if several do.
|
||||||
|
std::optional<uint32_t> FindScalarDefinition(const Decoder::Program& program, const Graph& graph,
|
||||||
uint32_t before, uint32_t code, uint32_t wave_size,
|
uint32_t before, uint32_t code, uint32_t wave_size,
|
||||||
std::vector<uint32_t>& crossed_calls);
|
std::vector<uint32_t>& crossed_calls);
|
||||||
// Returns structured control flow or failure diagnostics without changing the native graph.
|
// Returns structured control flow or failure diagnostics without changing the native graph.
|
||||||
|
|||||||
@@ -11125,6 +11125,14 @@ void TestMemoryFedScalarLeafCall() {
|
|||||||
const auto skipped = PrepareShaderSource(gpu_callable, options);
|
const auto skipped = PrepareShaderSource(gpu_callable, options);
|
||||||
Check(skipped.unsupported_call_pc == 12u && skipped.calls.empty(),
|
Check(skipped.unsupported_call_pc == 12u && skipped.calls.empty(),
|
||||||
"GPU-buffer callable did not report its unsupported call site");
|
"GPU-buffer callable did not report its unsupported call site");
|
||||||
|
// The table index s20 is loop-carried, so two definitions reach the call.
|
||||||
|
const uint32_t loop_callable[] = {EncodeSmem0(0x08, 20, 0), 0xfa000000u,
|
||||||
|
EncodeSmem0(0x09, 14, 0), 20u << 25u, EncodeSop1(0x21, 14, 14),
|
||||||
|
EncodeSmem0(0x08, 20, 0), 20u << 25u, EncodeSopc(0x07, 20, 128),
|
||||||
|
EncodeSopp(0x05, 0xfff9u), EncodeSopp(0x01)};
|
||||||
|
const auto loop_skipped = PrepareShaderSource(loop_callable, options);
|
||||||
|
Check(loop_skipped.unsupported_call_pc == 16u && loop_skipped.calls.empty(),
|
||||||
|
"loop-selected GPU-buffer callable did not report its unsupported call site");
|
||||||
auto source = PrepareShaderSource(shader, options);
|
auto source = PrepareShaderSource(shader, options);
|
||||||
Check(source.calls.size() == 1 && source.decoded.has_swap_pc &&
|
Check(source.calls.size() == 1 && source.decoded.has_swap_pc &&
|
||||||
source.decoded.instructions[source.calls.front().instruction].branch_target == UINT32_MAX,
|
source.decoded.instructions[source.calls.front().instruction].branch_target == UINT32_MAX,
|
||||||
|
|||||||
Reference in new issue
Block a user