mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-20 19:07:01 +02:00
shader: complete signed 64-bit integer comparisons
This commit is contained in:
+86
-28
@@ -4823,34 +4823,92 @@ void TestNewShaderDecoderArchitecture() {
|
||||
"VOP2 DPP V_PK_FMAC_F16 lost its implicit packed modifiers");
|
||||
}
|
||||
|
||||
void TestNewShaderRecompilerRejectsDppOn64BitCompares() {
|
||||
const uint32_t opcodes[] = {
|
||||
0xa2u, 0xa5u, 0xb5u, 0xe2u, 0xe4u, 0xe5u,
|
||||
0xf5u}; // eq_i64, ne_i64, cmpx_ne_i64, eq_u64, gt_u64, ne_u64, cmpx_ne_u64
|
||||
for (const auto opcode : opcodes) {
|
||||
const uint32_t shader[] = {
|
||||
EncodeVopc(opcode, 250u, 0u), // DPP escape in SRC0
|
||||
EncodeVop2Dpp(0u),
|
||||
0xbf810000u,
|
||||
};
|
||||
|
||||
ShaderRecompiler::Decoder::Program program;
|
||||
ShaderRecompiler::Decoder::DecodeProgram(shader, program);
|
||||
Check(program.instructions.size() == 2u,
|
||||
"64-bit VOPC DPP decode did not consume its modifier word");
|
||||
const auto &compare = program.instructions.front();
|
||||
Check(compare.opcode == ShaderRecompiler::Decoder::Opcode::UNSUPPORTED,
|
||||
"64-bit VOPC illegally accepted a DPP modifier");
|
||||
Check((compare.unsupported_reason.find("VOPC DPP modifier is not supported for opcode") != std::string::npos),
|
||||
"64-bit VOPC DPP rejection reason was not explicit");
|
||||
void TestNewShaderRecompilerInteger64CompareEncodings() {
|
||||
namespace D = ShaderRecompiler::Decoder;
|
||||
using O = D::Opcode;
|
||||
const O families[][8] = {
|
||||
{O::V_CMP_F_I64, O::V_CMP_LT_I64, O::V_CMP_EQ_I64, O::V_CMP_LE_I64,
|
||||
O::V_CMP_GT_I64, O::V_CMP_NE_I64, O::V_CMP_GE_I64, O::V_CMP_T_I64},
|
||||
{O::V_CMPX_F_I64, O::V_CMPX_LT_I64, O::V_CMPX_EQ_I64, O::V_CMPX_LE_I64,
|
||||
O::V_CMPX_GT_I64, O::V_CMPX_NE_I64, O::V_CMPX_GE_I64, O::V_CMPX_T_I64},
|
||||
{O::V_CMP_F_U64, O::V_CMP_LT_U64, O::V_CMP_EQ_U64, O::V_CMP_LE_U64,
|
||||
O::V_CMP_GT_U64, O::V_CMP_NE_U64, O::V_CMP_GE_U64, O::V_CMP_T_U64},
|
||||
{O::V_CMPX_F_U64, O::V_CMPX_LT_U64, O::V_CMPX_EQ_U64, O::V_CMPX_LE_U64,
|
||||
O::V_CMPX_GT_U64, O::V_CMPX_NE_U64, O::V_CMPX_GE_U64, O::V_CMPX_T_U64}};
|
||||
const uint32_t bases[] = {0xa0u, 0xb0u, 0xe0u, 0xf0u};
|
||||
for (uint32_t family = 0; family < std::size(families); ++family) {
|
||||
const bool update_exec = (family % 2) != 0;
|
||||
for (uint32_t predicate = 0; predicate < 8; ++predicate) {
|
||||
const auto encoding = bases[family] + predicate;
|
||||
for (const bool vop3 : {false, true}) {
|
||||
const std::array<uint32_t, 2> words = vop3
|
||||
? std::array{EncodeVop3Word0(encoding, 20),
|
||||
EncodeVop3Word1(257, 259, 0)}
|
||||
: std::array{EncodeVopc(encoding, 257, 3), 0xbf810000u};
|
||||
D::Instruction compare;
|
||||
D::DecodeInstruction(words, 0, compare);
|
||||
const auto destination = update_exec ? D::OperandKind::ExecLo
|
||||
: vop3 ? D::OperandKind::Sgpr : D::OperandKind::VccLo;
|
||||
Check(compare.family == (vop3 ? D::Family::VOP3 : D::Family::VOPC) &&
|
||||
compare.opcode == families[family][predicate] &&
|
||||
compare.opcode_id == encoding &&
|
||||
compare.word_count == (vop3 ? 2u : 1u) &&
|
||||
compare.dst.kind == destination &&
|
||||
(!vop3 || update_exec || compare.dst.reg == 20) &&
|
||||
compare.src_count == 2 &&
|
||||
compare.src0.kind == D::OperandKind::Vgpr && compare.src0.reg == 1 &&
|
||||
compare.src1.kind == D::OperandKind::Vgpr && compare.src1.reg == 3,
|
||||
"64-bit integer compare decoded incorrectly");
|
||||
for (const bool high_src0 : {false, true}) {
|
||||
// Only the compare's pair width makes v13 reachable by MOVRELD,
|
||||
// including predicates F/T that never read their operands.
|
||||
const uint32_t src0 = high_src0 ? 268u : 266u;
|
||||
const uint32_t src1 = high_src0 ? 10u : 12u;
|
||||
std::vector<uint32_t> shader{EncodeVop1(0x42, 12, 256)};
|
||||
if (vop3) {
|
||||
shader.push_back(EncodeVop3Word0(encoding, 20));
|
||||
shader.push_back(EncodeVop3Word1(src0, src1 + 256, 0));
|
||||
} else {
|
||||
shader.push_back(EncodeVopc(encoding, src0, src1));
|
||||
}
|
||||
shader.push_back(EncodeSopp(0x01));
|
||||
D::Program decoded;
|
||||
D::DecodeProgram(shader, decoded);
|
||||
ShaderComputeInputInfo compute{};
|
||||
ShaderRecompiler::Frontend::TranslateOptions options{.stage = ShaderType::Compute};
|
||||
options.input_info.compute = &compute;
|
||||
const auto program = ShaderRecompiler::Frontend::TranslateProgram(
|
||||
decoded, ShaderRecompiler::CFG::BuildGraph(decoded), options);
|
||||
bool includes_high_word = false;
|
||||
for (const auto *block : program.blocks) {
|
||||
for (const auto &inst : *block) {
|
||||
includes_high_word |=
|
||||
inst.GetOpcode() == ShaderRecompiler::IR::ValueOpcode::SetVectorRegister &&
|
||||
ShaderRecompiler::IR::RegIndex(inst.Arg(0).VectorRegister()) == 13;
|
||||
}
|
||||
}
|
||||
Check(includes_high_word, "64-bit compare omitted a VGPR pair's high word");
|
||||
}
|
||||
}
|
||||
for (const bool dpp : {false, true}) {
|
||||
const uint32_t shader[] = {
|
||||
EncodeVopc(encoding, dpp ? 250u : 249u, 3),
|
||||
dpp ? EncodeVop2Dpp(1) : EncodeVopcSdwa(1),
|
||||
0xbf810000u};
|
||||
D::Program program;
|
||||
D::DecodeProgram(shader, program);
|
||||
Check(program.instructions.size() == 2u &&
|
||||
program.instructions.back().opcode == O::S_ENDPGM,
|
||||
"64-bit VOPC decode did not consume its modifier word");
|
||||
const auto &compare = program.instructions.front();
|
||||
const auto reason = dpp ? "VOPC DPP modifier is not supported for opcode"
|
||||
: "VOPC SDWA modifier is not supported for opcode";
|
||||
Check(compare.opcode == O::UNSUPPORTED && compare.word_count == 2u &&
|
||||
compare.unsupported_reason.find(reason) != std::string::npos,
|
||||
"64-bit VOPC did not explicitly reject an illegal modifier");
|
||||
}
|
||||
}
|
||||
}
|
||||
const uint32_t sdwa[] = {EncodeVopc(0xa5u, 249u, 0u), 0x06060000u};
|
||||
ShaderRecompiler::Decoder::Instruction compare;
|
||||
ShaderRecompiler::Decoder::DecodeInstruction(sdwa, 0u, compare);
|
||||
Check(compare.opcode == ShaderRecompiler::Decoder::Opcode::UNSUPPORTED &&
|
||||
compare.word_count == 2u &&
|
||||
compare.unsupported_reason.find("VOPC SDWA modifier is not supported") != std::string::npos,
|
||||
"V_CMP_NE_I64 accepted an illegal SDWA encoding");
|
||||
}
|
||||
|
||||
void TestNewShaderRecompilerCapturedVopcSdwaCmpxClass() {
|
||||
@@ -15551,7 +15609,7 @@ int main() {
|
||||
TestVopcCmpxClassF16Decoder();
|
||||
TestNewShaderRecompilerCapturedVopcSdwaCmpxLtU16();
|
||||
TestNewShaderRecompilerIrLookupMissFailsExplicitly();
|
||||
TestNewShaderRecompilerRejectsDppOn64BitCompares();
|
||||
TestNewShaderRecompilerInteger64CompareEncodings();
|
||||
TestFloatComparisonInputModes();
|
||||
TestPsInputCountRegisterDecode();
|
||||
TestPixelAncillaryLayerInput();
|
||||
|
||||
Reference in New Issue
Block a user