shader: fix crash from packed ancillary used as DPP old operand (#1769)

shader: emit plain EXEC selects for DPP writes that reach every active lane (Street Fighter 6)
This commit is contained in:
Felipe
2026-10-23 04:51:32 -03:00
committed by GitHub
parent 719c44310a
commit 9dcff95e80
3 changed files with 19 additions and 2 deletions
@@ -132,7 +132,7 @@ uint32_t EmitDppWriteCondition(ValueEmitContext& ctx, const IR::DppMoveFlags& fl
enable(flags.bank_mask, 2u);
enable(flags.row_mask, 4u);
// Only row shifts (0x101-0x10f, 0x111-0x11f) can vacate a lane; other controls always read one.
const bool row_shift = !flags.dpp8 && flags.control > 0x100u && flags.control < 0x120u &&
const bool row_shift = flags.control > 0x100u && flags.control < 0x120u &&
flags.control != 0x110u;
if (!flags.bound_control && row_shift) {
writable = Binary(state, spv::OpLogicalAnd, TypeBool(state), writable,
@@ -319,7 +319,10 @@ void Translator::WriteRawU32(const Decoder::Operand& operand, IR::U32 value) {
case Decoder::OperandKind::Vgpr: {
const auto reg = static_cast<IR::VectorReg>(operand.reg);
const auto old = ir.GetVectorReg(reg);
if (operand.dpp) {
// DPP skips EXEC lanes only through row/bank masks, or for invalid sources without
// BOUND_CTRL (dpp8 reads zero); otherwise it is a plain masked write.
if (operand.dpp && (operand.dpp_row_mask != 0xfu || operand.dpp_bank_mask != 0xfu ||
(!operand.dpp_bound_ctrl && !operand.dpp8))) {
value = IR::U32(ir.Emit(IR::ValueOpcode::DppUpdateU32, {value, old, ir.GetExec()},
DppFlags(operand)));
} else {