From da195018893207e7257dd0540ba3e60f392c1050 Mon Sep 17 00:00:00 2001 From: nmzik Date: Wed, 21 Oct 2026 23:33:30 +0200 Subject: [PATCH] shader: translate zero-kind branches as the negated nonzero vote --- .../recompiler/frontend/translate/Translate.cpp | 11 +++++++---- tests/ShaderRecompilerComputeTests.cpp | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/graphics/shader/recompiler/frontend/translate/Translate.cpp b/src/graphics/shader/recompiler/frontend/translate/Translate.cpp index 318dfde4b..c148e901c 100644 --- a/src/graphics/shader/recompiler/frontend/translate/Translate.cpp +++ b/src/graphics/shader/recompiler/frontend/translate/Translate.cpp @@ -739,14 +739,16 @@ void Translator::WriteCompareResult(const Decoder::Operand& operand, IR::U1 valu void Translator::AddBranchCondition(const CFG::Graph& graph, const CFG::BasicBlock& source, IR::Block& info) { const auto native_condition = [&](CFG::BranchCondition kind) -> IR::U1 { + // A zero kind negates the vote of the nonzero kind that follows it in the enum. + const bool zero = kind == CFG::BranchCondition::SccZero || + kind == CFG::BranchCondition::VccZero || + kind == CFG::BranchCondition::ExecZero; + if (zero) kind = static_cast(static_cast(kind) + 1); IR::U1 condition; switch (kind) { case CFG::BranchCondition::Always: condition = IR::U1(IR::Value(true)); break; - case CFG::BranchCondition::SccZero: condition = ir.LogicalNot(ir.GetScc()); break; case CFG::BranchCondition::SccNonZero: condition = ir.GetScc(); break; - case CFG::BranchCondition::VccZero: condition = ir.LogicalNot(ir.GetVcc()); break; case CFG::BranchCondition::VccNonZero: condition = ir.GetVcc(); break; - case CFG::BranchCondition::ExecZero: condition = ir.LogicalNot(ir.GetExec()); break; case CFG::BranchCondition::ExecNonZero: condition = ir.GetExec(); break; case CFG::BranchCondition::ScalarInstruction: EXIT_IF(instruction_branch_condition.IsEmpty()); @@ -754,7 +756,8 @@ void Translator::AddBranchCondition(const CFG::Graph& graph, const CFG::BasicBlo break; default: EXIT("block %u has an invalid native branch condition", source.id); } - return IR::U1(ir.Emit(IR::ValueOpcode::ConditionRef, {condition}, kind)); + const auto vote = IR::U1(ir.Emit(IR::ValueOpcode::ConditionRef, {condition}, kind)); + return zero ? ir.LogicalNot(vote) : vote; }; const auto expression = [&](auto&& self, uint32_t index) -> IR::U1 { const auto& value = graph.expressions.at(index); diff --git a/tests/ShaderRecompilerComputeTests.cpp b/tests/ShaderRecompilerComputeTests.cpp index 0d4272408..b87cc47e6 100644 --- a/tests/ShaderRecompilerComputeTests.cpp +++ b/tests/ShaderRecompilerComputeTests.cpp @@ -31177,7 +31177,7 @@ TestCase ScalarBranchRestoresInactiveLanes(u32 wave_size, u32 threads, bool uppe upper_nonzero ? O::S_CBRANCH_EXECNZ : O::S_CBRANCH_EXECZ, O::V_READLANE_B32, O::V_LSHLREV_B32, O::BUFFER_STORE_DWORD, O::S_ENDPGM}; - test.required_spirv = {upper_nonzero ? "OpGroupNonUniformAny" : "OpGroupNonUniformAll"}; + test.required_spirv = {"OpGroupNonUniformAny"}; test.compute_info.wave_size = wave_size; test.compute_info.threads_num[0] = threads; test.compute_info.thread_ids_num = 1;