mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-25 20:36:54 +01:00
shader: V_CMPX_CLASS_F32
This commit is contained in:
@@ -351,6 +351,7 @@ enum class Opcode {
|
|||||||
V_CMP_GE_I32,
|
V_CMP_GE_I32,
|
||||||
V_CMP_T_I32,
|
V_CMP_T_I32,
|
||||||
V_CMP_CLASS_F32,
|
V_CMP_CLASS_F32,
|
||||||
|
V_CMPX_CLASS_F32,
|
||||||
V_CMP_LT_I16,
|
V_CMP_LT_I16,
|
||||||
V_CMP_EQ_I16,
|
V_CMP_EQ_I16,
|
||||||
V_CMP_LE_I16,
|
V_CMP_LE_I16,
|
||||||
|
|||||||
@@ -227,7 +227,8 @@ constexpr VopcOpcodeInfo VOPC_OPCODE_LIST[] = {
|
|||||||
{0x8eu, Opcode::V_CMP_GE_I16}, {0x91u, Opcode::V_CMPX_LT_I32},
|
{0x8eu, Opcode::V_CMP_GE_I16}, {0x91u, Opcode::V_CMPX_LT_I32},
|
||||||
{0x92u, Opcode::V_CMPX_EQ_I32}, {0x93u, Opcode::V_CMPX_LE_I32},
|
{0x92u, Opcode::V_CMPX_EQ_I32}, {0x93u, Opcode::V_CMPX_LE_I32},
|
||||||
{0x94u, Opcode::V_CMPX_GT_I32}, {0x95u, Opcode::V_CMPX_NE_I32},
|
{0x94u, Opcode::V_CMPX_GT_I32}, {0x95u, Opcode::V_CMPX_NE_I32},
|
||||||
{0x96u, Opcode::V_CMPX_GE_I32}, {0xa9u, Opcode::V_CMP_LT_U16},
|
{0x96u, Opcode::V_CMPX_GE_I32}, {0x98u, Opcode::V_CMPX_CLASS_F32},
|
||||||
|
{0xa9u, Opcode::V_CMP_LT_U16},
|
||||||
{0xaau, Opcode::V_CMP_EQ_U16}, {0xabu, Opcode::V_CMP_LE_U16},
|
{0xaau, Opcode::V_CMP_EQ_U16}, {0xabu, Opcode::V_CMP_LE_U16},
|
||||||
{0xacu, Opcode::V_CMP_GT_U16}, {0xadu, Opcode::V_CMP_NE_U16},
|
{0xacu, Opcode::V_CMP_GT_U16}, {0xadu, Opcode::V_CMP_NE_U16},
|
||||||
{0xaeu, Opcode::V_CMP_GE_U16}, {0xbcu, Opcode::V_CMPX_GT_U16},
|
{0xaeu, Opcode::V_CMP_GE_U16}, {0xbcu, Opcode::V_CMPX_GT_U16},
|
||||||
@@ -895,7 +896,8 @@ bool IsVopcFloatCompareOpcode(Opcode opcode) {
|
|||||||
case Opcode::V_CMPX_NGT_F16:
|
case Opcode::V_CMPX_NGT_F16:
|
||||||
case Opcode::V_CMPX_NEQ_F16:
|
case Opcode::V_CMPX_NEQ_F16:
|
||||||
case Opcode::V_CMPX_NLT_F16:
|
case Opcode::V_CMPX_NLT_F16:
|
||||||
case Opcode::V_CMP_CLASS_F32: return true;
|
case Opcode::V_CMP_CLASS_F32:
|
||||||
|
case Opcode::V_CMPX_CLASS_F32: return true;
|
||||||
default: return false;
|
default: return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1518,6 +1520,7 @@ bool IsVopcCompareExec(Opcode opcode) {
|
|||||||
case Opcode::V_CMPX_GT_I32:
|
case Opcode::V_CMPX_GT_I32:
|
||||||
case Opcode::V_CMPX_NE_I32:
|
case Opcode::V_CMPX_NE_I32:
|
||||||
case Opcode::V_CMPX_GE_I32:
|
case Opcode::V_CMPX_GE_I32:
|
||||||
|
case Opcode::V_CMPX_CLASS_F32:
|
||||||
case Opcode::V_CMPX_LT_U32:
|
case Opcode::V_CMPX_LT_U32:
|
||||||
case Opcode::V_CMPX_EQ_U32:
|
case Opcode::V_CMPX_EQ_U32:
|
||||||
case Opcode::V_CMPX_LE_U32:
|
case Opcode::V_CMPX_LE_U32:
|
||||||
|
|||||||
@@ -55,11 +55,11 @@ void Translator::EmitFloatOrderedCompare(const Decoder::Instruction& inst, bool
|
|||||||
EmitCompareResult(inst, ordered ? ir.LogicalNot(unordered) : unordered, false, false);
|
EmitCompareResult(inst, ordered ? ir.LogicalNot(unordered) : unordered, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Translator::V_CMP_CLASS_F32(const Decoder::Instruction& inst) {
|
void Translator::EmitFloatClassCompare(const Decoder::Instruction& inst, bool cmpx) {
|
||||||
const auto value = ReadOperand(inst.src0, IR::Type::F32);
|
const auto value = ReadOperand(inst.src0, IR::Type::F32);
|
||||||
const auto mask = ReadOperand(inst.src1, IR::Type::U32);
|
const auto mask = ReadOperand(inst.src1, IR::Type::U32);
|
||||||
EmitCompareResult(inst, IR::U1(ir.Emit(IR::ValueOpcode::FPCmpClass32, {value, mask})), false,
|
EmitCompareResult(inst, IR::U1(ir.Emit(IR::ValueOpcode::FPCmpClass32, {value, mask})), false,
|
||||||
false);
|
cmpx);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Libs::Graphics::ShaderRecompiler::Frontend
|
} // namespace Libs::Graphics::ShaderRecompiler::Frontend
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ private:
|
|||||||
void EmitFloatCompare(const Decoder::Instruction& inst, IR::ValueOpcode opcode, bool half,
|
void EmitFloatCompare(const Decoder::Instruction& inst, IR::ValueOpcode opcode, bool half,
|
||||||
bool cmpx);
|
bool cmpx);
|
||||||
void EmitFloatOrderedCompare(const Decoder::Instruction& inst, bool ordered);
|
void EmitFloatOrderedCompare(const Decoder::Instruction& inst, bool ordered);
|
||||||
void V_CMP_CLASS_F32(const Decoder::Instruction& inst);
|
void EmitFloatClassCompare(const Decoder::Instruction& inst, bool cmpx);
|
||||||
void V_CVT_F32_UBYTE(const Decoder::Instruction& inst, uint32_t byte_index);
|
void V_CVT_F32_UBYTE(const Decoder::Instruction& inst, uint32_t byte_index);
|
||||||
void V_CVT_F32_U32(const Decoder::Instruction& inst);
|
void V_CVT_F32_U32(const Decoder::Instruction& inst);
|
||||||
void V_CVT_F32_I32(const Decoder::Instruction& inst);
|
void V_CVT_F32_I32(const Decoder::Instruction& inst);
|
||||||
|
|||||||
@@ -271,7 +271,8 @@ bool Translator::EmitVector(const Decoder::Instruction& inst, std::string* error
|
|||||||
return true;
|
return true;
|
||||||
case O::V_CMP_O_F32: EmitFloatOrderedCompare(inst, true); return true;
|
case O::V_CMP_O_F32: EmitFloatOrderedCompare(inst, true); return true;
|
||||||
case O::V_CMP_U_F32: EmitFloatOrderedCompare(inst, false); return true;
|
case O::V_CMP_U_F32: EmitFloatOrderedCompare(inst, false); return true;
|
||||||
case O::V_CMP_CLASS_F32: V_CMP_CLASS_F32(inst); return true;
|
case O::V_CMP_CLASS_F32: EmitFloatClassCompare(inst, false); return true;
|
||||||
|
case O::V_CMPX_CLASS_F32: EmitFloatClassCompare(inst, true); return true;
|
||||||
|
|
||||||
case O::V_CVT_F32_UBYTE0: V_CVT_F32_UBYTE(inst, 0); return true;
|
case O::V_CVT_F32_UBYTE0: V_CVT_F32_UBYTE(inst, 0); return true;
|
||||||
case O::V_CVT_F32_UBYTE1: V_CVT_F32_UBYTE(inst, 1); return true;
|
case O::V_CVT_F32_UBYTE1: V_CVT_F32_UBYTE(inst, 1); return true;
|
||||||
|
|||||||
@@ -11931,6 +11931,7 @@ CoverageClass ClassifyOpcode(ShaderOpcode opcode,
|
|||||||
case Opcode::V_CMPX_NEQ_F32:
|
case Opcode::V_CMPX_NEQ_F32:
|
||||||
case Opcode::V_CMPX_NLT_F32:
|
case Opcode::V_CMPX_NLT_F32:
|
||||||
case Opcode::V_CMP_CLASS_F32:
|
case Opcode::V_CMP_CLASS_F32:
|
||||||
|
case Opcode::V_CMPX_CLASS_F32:
|
||||||
case Opcode::V_CMP_LT_F16:
|
case Opcode::V_CMP_LT_F16:
|
||||||
case Opcode::V_CMP_EQ_F16:
|
case Opcode::V_CMP_EQ_F16:
|
||||||
case Opcode::V_CMP_LE_F16:
|
case Opcode::V_CMP_LE_F16:
|
||||||
@@ -15785,6 +15786,38 @@ TestCase VectorCompareClassF32() {
|
|||||||
O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
|
O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TestCase VectorVopcSdwaCmpxClassF32CapturedExecMask() {
|
||||||
|
using O = ShaderOpcode;
|
||||||
|
|
||||||
|
std::vector<u32> code;
|
||||||
|
AppendVMovLiteral(&code, 13, 0x7fc00000u); // Quiet NaN.
|
||||||
|
AppendVMovU32(&code, 3, 7);
|
||||||
|
AppendVMovU32(&code, 31, 0);
|
||||||
|
code.push_back(EncodeSMovB32(106, InlineU32(2))); // qNaN class mask.
|
||||||
|
code.insert(code.end(), {0x7d30d4f9u, 0x8606000du});
|
||||||
|
AppendBufferStoreDword(&code, 3, 31);
|
||||||
|
|
||||||
|
code.push_back(EncodeSMovB32(126, InlineU32(1))); // Restore lane-zero EXEC.
|
||||||
|
AppendVMovLiteral(&code, 13, 0x3f800000u); // Positive normal.
|
||||||
|
AppendVMovU32(&code, 3, 9);
|
||||||
|
AppendVMovU32(&code, 31, 4);
|
||||||
|
code.push_back(EncodeSMovB32(106, InlineU32(2))); // qNaN class mask.
|
||||||
|
code.insert(code.end(), {0x7d30d4f9u, 0x8606000du});
|
||||||
|
AppendBufferStoreDword(&code, 3, 31);
|
||||||
|
AppendEnd(&code);
|
||||||
|
|
||||||
|
TestCase test{
|
||||||
|
"VectorVopcSdwaCmpxClassF32CapturedExecMask",
|
||||||
|
code,
|
||||||
|
{0x11111111u, 0x22222222u},
|
||||||
|
{7u, 0x22222222u},
|
||||||
|
{O::S_MOV_B32, O::V_MOV_B32, O::V_CMPX_CLASS_F32,
|
||||||
|
O::BUFFER_STORE_DWORD, O::S_ENDPGM}};
|
||||||
|
test.decoded_counts = {
|
||||||
|
{"V_CMPX_CLASS_F32 exec_lo, v13, vcc_lo", 2}};
|
||||||
|
return test;
|
||||||
|
}
|
||||||
|
|
||||||
TestCase VectorCompareF16Ops() {
|
TestCase VectorCompareF16Ops() {
|
||||||
using O = ShaderOpcode;
|
using O = ShaderOpcode;
|
||||||
|
|
||||||
@@ -20812,6 +20845,7 @@ std::vector<TestCase> MakeCases() {
|
|||||||
AddCase(VectorVopcCmpxNeU64CapturedExecMask);
|
AddCase(VectorVopcCmpxNeU64CapturedExecMask);
|
||||||
AddCase(VectorVop3CmpxNeI64CapturedExecMask);
|
AddCase(VectorVop3CmpxNeI64CapturedExecMask);
|
||||||
AddCase(VectorCompareClassF32);
|
AddCase(VectorCompareClassF32);
|
||||||
|
AddCase(VectorVopcSdwaCmpxClassF32CapturedExecMask);
|
||||||
AddCase(VectorCompareF16Ops);
|
AddCase(VectorCompareF16Ops);
|
||||||
AddCase(Vop2SdwaCndmaskSourceModifier);
|
AddCase(Vop2SdwaCndmaskSourceModifier);
|
||||||
AddCase(Vop2SdwaCndmaskCapturedByte3Source);
|
AddCase(Vop2SdwaCndmaskCapturedByte3Source);
|
||||||
|
|||||||
@@ -4231,6 +4231,67 @@ void TestNewShaderRecompilerRejectsDppOn64BitCompares() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TestNewShaderRecompilerCapturedVopcSdwaCmpxClass() {
|
||||||
|
using namespace ShaderRecompiler;
|
||||||
|
|
||||||
|
const uint32_t shader[] = {
|
||||||
|
0x7d30d4f9u, 0x8606000du, // v_cmpx_class_f32 exec, v13, vcc_lo (SDWA)
|
||||||
|
EncodeSopp(0x01),
|
||||||
|
};
|
||||||
|
|
||||||
|
Decoder::Instruction decoded;
|
||||||
|
std::string error;
|
||||||
|
Check(Decoder::DecodeInstruction(shader, 0u, decoded, &error),
|
||||||
|
error.c_str());
|
||||||
|
Check(decoded.family == Decoder::Family::VOPC &&
|
||||||
|
decoded.opcode == Decoder::Opcode::V_CMPX_CLASS_F32 &&
|
||||||
|
decoded.opcode_id == 0x98u && decoded.word_count == 2u &&
|
||||||
|
decoded.raw_count == 2u &&
|
||||||
|
decoded.dst.kind == Decoder::OperandKind::ExecLo &&
|
||||||
|
decoded.src_count == 2u &&
|
||||||
|
decoded.src0.kind == Decoder::OperandKind::Vgpr &&
|
||||||
|
decoded.src0.reg == 13u && decoded.src0.sdwa_sel == 6u &&
|
||||||
|
decoded.src1.kind == Decoder::OperandKind::VccLo &&
|
||||||
|
decoded.src1.sdwa_sel == 6u,
|
||||||
|
"decoder rejected captured SDWA V_CMPX_CLASS_F32 fields");
|
||||||
|
|
||||||
|
Decoder::Program program;
|
||||||
|
CFG::Graph graph;
|
||||||
|
IR::Program ir;
|
||||||
|
ShaderPixelInputInfo pixel{};
|
||||||
|
Frontend::TranslateOptions translate_options{};
|
||||||
|
translate_options.stage = ShaderType::Pixel;
|
||||||
|
translate_options.wave_size = 64u;
|
||||||
|
translate_options.pixel = &pixel;
|
||||||
|
Check(Decoder::DecodeProgram(shader, program, &error) &&
|
||||||
|
CFG::BuildGraph(program, graph, &error) &&
|
||||||
|
Frontend::TranslateProgram(program, graph, translate_options, ir,
|
||||||
|
&error),
|
||||||
|
error.c_str());
|
||||||
|
uint32_t class_compares = 0u;
|
||||||
|
uint32_t dynamic_exec_writes = 0u;
|
||||||
|
for (const auto *block : ir.blocks) {
|
||||||
|
for (const auto &inst : *block) {
|
||||||
|
class_compares +=
|
||||||
|
inst.GetOpcode() == IR::ValueOpcode::FPCmpClass32 ? 1u : 0u;
|
||||||
|
if (inst.GetOpcode() == IR::ValueOpcode::SetExec &&
|
||||||
|
!inst.Arg(0).Resolve().IsImmediate()) {
|
||||||
|
dynamic_exec_writes++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Check(class_compares == 1u && dynamic_exec_writes == 1u,
|
||||||
|
"captured V_CMPX_CLASS_F32 did not lower to class compare plus EXEC update");
|
||||||
|
|
||||||
|
auto options = MakeCompileOptions(ShaderType::Pixel);
|
||||||
|
CompileResult result;
|
||||||
|
Check(TryRecompile(shader, options, result, &error), error.c_str());
|
||||||
|
Check(Common::ContainsStr(result.decoded_dump,
|
||||||
|
"V_CMPX_CLASS_F32 exec_lo, v13, vcc_lo"),
|
||||||
|
"captured SDWA V_CMPX_CLASS_F32 was not present in the decoded dump");
|
||||||
|
CheckSpirvBinaryValidates(result.spirv);
|
||||||
|
}
|
||||||
|
|
||||||
void TestNewShaderRecompilerIrLookupMissFailsExplicitly() {
|
void TestNewShaderRecompilerIrLookupMissFailsExplicitly() {
|
||||||
ShaderRecompiler::Decoder::Program decoded;
|
ShaderRecompiler::Decoder::Program decoded;
|
||||||
ShaderRecompiler::Decoder::Instruction missing;
|
ShaderRecompiler::Decoder::Instruction missing;
|
||||||
@@ -12476,6 +12537,7 @@ int main() {
|
|||||||
// ShaderRecompilerComputeTests; keep the distinct decoder contract checks
|
// ShaderRecompilerComputeTests; keep the distinct decoder contract checks
|
||||||
// here.
|
// here.
|
||||||
TestNewShaderDecoderArchitecture();
|
TestNewShaderDecoderArchitecture();
|
||||||
|
TestNewShaderRecompilerCapturedVopcSdwaCmpxClass();
|
||||||
TestNewShaderRecompilerRejectsDppOn64BitCompares();
|
TestNewShaderRecompilerRejectsDppOn64BitCompares();
|
||||||
TestNewShaderRecompilerIrLookupMissFailsExplicitly();
|
TestNewShaderRecompilerIrLookupMissFailsExplicitly();
|
||||||
TestPsInputCountRegisterDecode();
|
TestPsInputCountRegisterDecode();
|
||||||
|
|||||||
Reference in New Issue
Block a user