mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-24 21:06:55 +02:00
shader: handle scalar guards for image bounds
This commit is contained in:
@@ -705,22 +705,10 @@ private:
|
||||
return false;
|
||||
}
|
||||
const auto* previous = block->ImmPredecessors()[0];
|
||||
const auto current_it = std::ranges::find(m_program.blocks, block);
|
||||
const auto previous_it = std::ranges::find(m_program.blocks, previous);
|
||||
if (current_it == m_program.blocks.end() || previous_it == m_program.blocks.end()) {
|
||||
return false;
|
||||
}
|
||||
const auto& info = m_program.block_info[previous_it - m_program.blocks.begin()];
|
||||
const auto id = m_program.block_info[current_it - m_program.blocks.begin()].id;
|
||||
const auto& term = info.terminator;
|
||||
if (term.kind == CFG::TerminatorKind::ConditionalBranch &&
|
||||
(term.true_block == id) != (term.false_block == id)) {
|
||||
bool positive = term.true_block == id;
|
||||
const auto* test = info.condition.Resolve().TryInstruction();
|
||||
while (test != nullptr && test->GetOpcode() == ValueOpcode::LogicalNot) {
|
||||
positive = !positive;
|
||||
test = test->Arg(0).Resolve().TryInstruction();
|
||||
}
|
||||
Value condition;
|
||||
bool positive = false;
|
||||
if (ConditionalEdge(previous, block, condition, positive)) {
|
||||
const auto* test = condition.TryInstruction();
|
||||
if (test != nullptr && test->NumArgs() == 2u &&
|
||||
((test->GetOpcode() == ValueOpcode::INotEqual32 && positive) ||
|
||||
(test->GetOpcode() == ValueOpcode::IEqual32 && !positive))) {
|
||||
@@ -801,9 +789,17 @@ private:
|
||||
condition = info.condition;
|
||||
positive = term.true_block == id;
|
||||
while (const auto* inst = condition.Resolve().TryInstruction()) {
|
||||
if (inst->GetOpcode() != ValueOpcode::LogicalNot) break;
|
||||
if (inst->GetOpcode() == ValueOpcode::LogicalNot) {
|
||||
positive = !positive;
|
||||
} else if (inst->GetOpcode() == ValueOpcode::ConditionRef) {
|
||||
// SCC is uniform across the guest wave; EXEC and VCC are lane predicates.
|
||||
const auto kind = inst->Flags<CFG::BranchCondition>();
|
||||
if (kind != CFG::BranchCondition::SccZero &&
|
||||
kind != CFG::BranchCondition::SccNonZero) break;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
condition = inst->Arg(0);
|
||||
positive = !positive;
|
||||
}
|
||||
condition = condition.Resolve();
|
||||
return true;
|
||||
|
||||
@@ -561,9 +561,10 @@ void TestInvariantIndirectImageMaterialization() {
|
||||
|
||||
void TestGuardedDirectImageTable() {
|
||||
namespace CFG = Libs::Graphics::ShaderRecompiler::CFG;
|
||||
enum class Guard { Nonzero, Zero, Unrelated, Bypass };
|
||||
enum class Guard { Nonzero, SccNonZero, Plain, Zero, Unrelated, Bypass, ExecZero, VccZero };
|
||||
const auto make_plan = [](Guard guard) {
|
||||
Fixture fixture(ShaderType::Pixel);
|
||||
fixture.program.wave_size = 64u;
|
||||
auto *entry = fixture.block;
|
||||
auto *middle = fixture.AddBlock();
|
||||
auto *before_sample = fixture.AddBlock();
|
||||
@@ -580,8 +581,19 @@ void TestGuardedDirectImageTable() {
|
||||
const auto nonzero = fixture.Emit(
|
||||
ValueOpcode::INotEqual32,
|
||||
{Value(0u), guard == Guard::Unrelated ? fixture.UserData(2) : mask});
|
||||
fixture.program.block_info[0].condition =
|
||||
fixture.Emit(ValueOpcode::LogicalNot, {nonzero});
|
||||
const auto kind = guard == Guard::ExecZero ? CFG::BranchCondition::ExecZero
|
||||
: guard == Guard::VccZero ? CFG::BranchCondition::VccZero
|
||||
: CFG::BranchCondition::SccZero;
|
||||
auto condition = nonzero;
|
||||
if (guard == Guard::SccNonZero) {
|
||||
condition = fixture.Emit(ValueOpcode::ConditionRef, {condition},
|
||||
CFG::BranchCondition::SccNonZero);
|
||||
}
|
||||
condition = fixture.Emit(ValueOpcode::LogicalNot, {condition});
|
||||
if (guard != Guard::Plain && guard != Guard::SccNonZero) {
|
||||
condition = fixture.Emit(ValueOpcode::ConditionRef, {condition}, kind);
|
||||
}
|
||||
fixture.program.block_info[0].condition = condition;
|
||||
fixture.program.block_info[0].terminator = {
|
||||
.kind = CFG::TerminatorKind::ConditionalBranch,
|
||||
.true_block = guard == Guard::Zero ? 1u : 4u,
|
||||
@@ -645,7 +657,10 @@ void TestGuardedDirectImageTable() {
|
||||
};
|
||||
|
||||
auto plan = make_plan(Guard::Nonzero);
|
||||
for (const auto guard : {Guard::Zero, Guard::Unrelated, Guard::Bypass}) {
|
||||
make_plan(Guard::SccNonZero);
|
||||
make_plan(Guard::Plain);
|
||||
for (const auto guard : {Guard::Zero, Guard::Unrelated, Guard::Bypass,
|
||||
Guard::ExecZero, Guard::VccZero}) {
|
||||
CheckFatal([&] { make_plan(guard); }, "not a valid runtime value",
|
||||
"direct table accepted a selector without a dominating nonzero guard");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user