mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 22:06:59 +01:00
shader: fix incorrect per-lane VCCZ/EXECZ reads
This commit is contained in:
@@ -134,11 +134,15 @@ IR::U32 Translator::ReadRawU32(const Decoder::Operand& operand) {
|
|||||||
case Decoder::OperandKind::Scc:
|
case Decoder::OperandKind::Scc:
|
||||||
return ir.Select(ir.GetScc(), IR::U32(IR::Value(1u)), IR::U32(IR::Value(0u)));
|
return ir.Select(ir.GetScc(), IR::U32(IR::Value(1u)), IR::U32(IR::Value(0u)));
|
||||||
case Decoder::OperandKind::VccZ:
|
case Decoder::OperandKind::VccZ:
|
||||||
return ir.Select(ir.LogicalNot(ir.GetVcc()), IR::U32(IR::Value(1u)),
|
case Decoder::OperandKind::ExecZ: {
|
||||||
IR::U32(IR::Value(0u)));
|
const bool vcc = operand.kind == Decoder::OperandKind::VccZ;
|
||||||
case Decoder::OperandKind::ExecZ:
|
auto mask = vcc ? ir.GetVccLo() : ir.GetExecLo();
|
||||||
return ir.Select(ir.LogicalNot(ir.GetExec()), IR::U32(IR::Value(1u)),
|
if (program.wave_size == 64u) {
|
||||||
IR::U32(IR::Value(0u)));
|
mask = ir.BitwiseOr(mask, vcc ? ir.GetVccHi() : ir.GetExecHi());
|
||||||
|
}
|
||||||
|
const auto zero = IR::U32(IR::Value(0u));
|
||||||
|
return ir.Select(ir.IEqual(mask, zero), IR::U32(IR::Value(1u)), zero);
|
||||||
|
}
|
||||||
default: EXIT("invalid decoded operand used as a raw U32 source");
|
default: EXIT("invalid decoded operand used as a raw U32 source");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14982,16 +14982,36 @@ TestCase ScalarOrn2SaveexecB32(u32 wave_size, u32 threads) {
|
|||||||
{0xffffffffu, 107, 8, vcc_hi},
|
{0xffffffffu, 107, 8, vcc_hi},
|
||||||
{0xffffffffu, 127, 8, exec_hi},
|
{0xffffffffu, 127, 8, exec_hi},
|
||||||
{0xffffffffu, 253, 8, 1}, // SCC is a scalar value, not a mask.
|
{0xffffffffu, 253, 8, 1}, // SCC is a scalar value, not a mask.
|
||||||
|
{0xffffffffu, 251, 8, 0}, // VCCZ summarizes the whole mask.
|
||||||
|
{0x00000001u, 252, 8, 0xfffffffeu}, // EXECZ is uniform across lanes.
|
||||||
};
|
};
|
||||||
TestCase test;
|
TestCase test;
|
||||||
test.name = wave_size == 64 ? "ScalarOrn2SaveexecB32Wave64"
|
test.name = wave_size == 64 ? "ScalarOrn2SaveexecB32Wave64"
|
||||||
: threads == 32 ? "ScalarOrn2SaveexecB32Wave32"
|
: threads == 32 ? "ScalarOrn2SaveexecB32Wave32"
|
||||||
: "ScalarOrn2SaveexecB32PartialWave";
|
: "ScalarOrn2SaveexecB32PartialWave";
|
||||||
auto &code = test.code;
|
auto &code = test.code;
|
||||||
|
// Zero flags ignore high bits only in wave32 and include inactive low bits.
|
||||||
|
constexpr u32 masks[][2] = {{0, 0}, {0x80000000u, 0}, {0, 0x80000000u}};
|
||||||
|
for (const auto &mask : masks) {
|
||||||
|
AppendSMovLiteral(&code, 106, mask[0]);
|
||||||
|
AppendSMovLiteral(&code, 107, mask[1]);
|
||||||
|
AppendSMovLiteral(&code, 126, mask[0]);
|
||||||
|
AppendSMovLiteral(&code, 127, mask[1]);
|
||||||
|
code.push_back(EncodeSMovB32(20, 251));
|
||||||
|
code.push_back(EncodeSMovB32(21, 252));
|
||||||
|
code.push_back(EncodeSop1(0x04, 126, 193u));
|
||||||
|
const u32 zero = mask[0] == 0 && (wave_size == 32 || mask[1] == 0);
|
||||||
|
for (u32 reg = 20; reg <= 21; ++reg) {
|
||||||
|
AppendStoreSgprAtLaneDwordOffset(&code, reg, 0,
|
||||||
|
static_cast<u32>(test.expected.size()));
|
||||||
|
test.expected.insert(test.expected.end(), threads, zero);
|
||||||
|
}
|
||||||
|
}
|
||||||
for (const auto &item : cases) {
|
for (const auto &item : cases) {
|
||||||
AppendVMovU32(&code, 2, 0);
|
AppendVMovU32(&code, 2, 0);
|
||||||
AppendSMovLiteral(&code, 126, item.exec_lo);
|
AppendSMovLiteral(&code, 126, item.exec_lo);
|
||||||
AppendSMovLiteral(&code, 127, exec_hi);
|
AppendSMovLiteral(&code, 127, exec_hi);
|
||||||
|
AppendSMovLiteral(&code, 106, 1);
|
||||||
AppendSMovLiteral(&code, 107, vcc_hi);
|
AppendSMovLiteral(&code, 107, vcc_hi);
|
||||||
AppendSMovLiteral(&code, 6, 3);
|
AppendSMovLiteral(&code, 6, 3);
|
||||||
code.push_back(EncodeSopc(0x06, InlineU32(0), InlineU32(0)));
|
code.push_back(EncodeSopc(0x06, InlineU32(0), InlineU32(0)));
|
||||||
|
|||||||
Reference in New Issue
Block a user