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