mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 13:56:59 +01:00
graphics: support RDNA2 dependency waits
This commit is contained in:
@@ -60,12 +60,15 @@ constexpr OpcodeMap SOPK_OPCODE_LIST[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
constexpr OpcodeMap SOPP_OPCODE_LIST[] = {
|
constexpr OpcodeMap SOPP_OPCODE_LIST[] = {
|
||||||
{0x00u, Opcode::SNop}, {0x01u, Opcode::SEndpgm}, {0x02u, Opcode::SBranch},
|
{0x00u, Opcode::SNop}, {0x01u, Opcode::SEndpgm},
|
||||||
{0x04u, Opcode::SCbranchScc0}, {0x05u, Opcode::SCbranchScc1}, {0x06u, Opcode::SCbranchVccz},
|
{0x02u, Opcode::SBranch}, {0x04u, Opcode::SCbranchScc0},
|
||||||
{0x07u, Opcode::SCbranchVccnz}, {0x08u, Opcode::SCbranchExecz}, {0x09u, Opcode::SCbranchExecnz},
|
{0x05u, Opcode::SCbranchScc1}, {0x06u, Opcode::SCbranchVccz},
|
||||||
{0x0au, Opcode::SBarrier}, {0x0cu, Opcode::SWaitcnt}, {0x0eu, Opcode::SSleep},
|
{0x07u, Opcode::SCbranchVccnz}, {0x08u, Opcode::SCbranchExecz},
|
||||||
{0x10u, Opcode::SSendmsg}, {0x12u, Opcode::STrap}, {0x16u, Opcode::STtraceData},
|
{0x09u, Opcode::SCbranchExecnz}, {0x0au, Opcode::SBarrier},
|
||||||
{0x20u, Opcode::SInstPrefetch},
|
{0x0cu, Opcode::SWaitcnt}, {0x0eu, Opcode::SSleep},
|
||||||
|
{0x10u, Opcode::SSendmsg}, {0x12u, Opcode::STrap},
|
||||||
|
{0x16u, Opcode::STtraceData}, {0x20u, Opcode::SInstPrefetch},
|
||||||
|
{0x23u, Opcode::SWaitcntDepctr},
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr auto SOP1_OPS = Detail::MakeOpcodeTable<0x100>(SOP1_OPCODE_LIST);
|
constexpr auto SOP1_OPS = Detail::MakeOpcodeTable<0x100>(SOP1_OPCODE_LIST);
|
||||||
@@ -252,14 +255,14 @@ void DecodeSopp(uint32_t pc, std::span<const uint32_t> code, uint32_t word_index
|
|||||||
inst.src0.signed_val = inst.opcode == Opcode::STrap
|
inst.src0.signed_val = inst.opcode == Opcode::STrap
|
||||||
? static_cast<int32_t>(inst.src0.value)
|
? static_cast<int32_t>(inst.src0.value)
|
||||||
: static_cast<int32_t>(static_cast<int16_t>(simm));
|
: static_cast<int32_t>(static_cast<int16_t>(simm));
|
||||||
inst.src_count = (inst.opcode == Opcode::SNop || inst.opcode == Opcode::SWaitcnt ||
|
inst.src_count = (inst.opcode == Opcode::SNop || inst.opcode == Opcode::SWaitcnt ||
|
||||||
inst.opcode == Opcode::SSleep || inst.opcode == Opcode::SSendmsg ||
|
inst.opcode == Opcode::SWaitcntDepctr || inst.opcode == Opcode::SSleep ||
|
||||||
inst.opcode == Opcode::STrap || inst.opcode == Opcode::STtraceData ||
|
inst.opcode == Opcode::SSendmsg || inst.opcode == Opcode::STrap ||
|
||||||
inst.opcode == Opcode::SInstPrefetch)
|
inst.opcode == Opcode::STtraceData || inst.opcode == Opcode::SInstPrefetch)
|
||||||
? 1
|
? 1
|
||||||
: 0;
|
: 0;
|
||||||
inst.branch_offset = static_cast<int32_t>(static_cast<int16_t>(simm)) * 4;
|
inst.branch_offset = static_cast<int32_t>(static_cast<int16_t>(simm)) * 4;
|
||||||
inst.branch_target = pc + 4u + static_cast<uint32_t>(inst.branch_offset);
|
inst.branch_target = pc + 4u + static_cast<uint32_t>(inst.branch_offset);
|
||||||
SetRawWords(inst, code, word_index, 1);
|
SetRawWords(inst, code, word_index, 1);
|
||||||
|
|
||||||
if (inst.opcode == Opcode::Unsupported) {
|
if (inst.opcode == Opcode::Unsupported) {
|
||||||
|
|||||||
@@ -944,6 +944,7 @@ std::string OpcodeToString(Opcode opcode) {
|
|||||||
case Opcode::VInterpMovF32: return "v_interp_mov_f32";
|
case Opcode::VInterpMovF32: return "v_interp_mov_f32";
|
||||||
case Opcode::SNop: return "s_nop";
|
case Opcode::SNop: return "s_nop";
|
||||||
case Opcode::SWaitcnt: return "s_waitcnt";
|
case Opcode::SWaitcnt: return "s_waitcnt";
|
||||||
|
case Opcode::SWaitcntDepctr: return "s_waitcnt_depctr";
|
||||||
case Opcode::SBarrier: return "s_barrier";
|
case Opcode::SBarrier: return "s_barrier";
|
||||||
case Opcode::SBranch: return "s_branch";
|
case Opcode::SBranch: return "s_branch";
|
||||||
case Opcode::SCbranchScc0: return "s_cbranch_scc0";
|
case Opcode::SCbranchScc0: return "s_cbranch_scc0";
|
||||||
@@ -1058,6 +1059,7 @@ std::string InstructionToString(const Instruction& inst) {
|
|||||||
OperandToString(inst.src1).c_str()));
|
OperandToString(inst.src1).c_str()));
|
||||||
case Opcode::SNop:
|
case Opcode::SNop:
|
||||||
case Opcode::SWaitcnt:
|
case Opcode::SWaitcnt:
|
||||||
|
case Opcode::SWaitcntDepctr:
|
||||||
case Opcode::SSleep:
|
case Opcode::SSleep:
|
||||||
case Opcode::STrap:
|
case Opcode::STrap:
|
||||||
case Opcode::SSendmsg:
|
case Opcode::SSendmsg:
|
||||||
|
|||||||
@@ -531,6 +531,7 @@ enum class Opcode {
|
|||||||
|
|
||||||
SNop,
|
SNop,
|
||||||
SWaitcnt,
|
SWaitcnt,
|
||||||
|
SWaitcntDepctr,
|
||||||
SBarrier,
|
SBarrier,
|
||||||
SBranch,
|
SBranch,
|
||||||
SCbranchScc0,
|
SCbranchScc0,
|
||||||
|
|||||||
@@ -992,6 +992,7 @@ bool LowerControlInstruction(const Decoder::Instruction& decoded, BasicBlock& bl
|
|||||||
case Decoder::Opcode::SNop:
|
case Decoder::Opcode::SNop:
|
||||||
return LowerControlMarker(decoded, block, Opcode::ControlNop, true, error);
|
return LowerControlMarker(decoded, block, Opcode::ControlNop, true, error);
|
||||||
case Decoder::Opcode::SWaitcnt:
|
case Decoder::Opcode::SWaitcnt:
|
||||||
|
case Decoder::Opcode::SWaitcntDepctr:
|
||||||
return LowerControlMarker(decoded, block, Opcode::Waitcnt, true, error);
|
return LowerControlMarker(decoded, block, Opcode::Waitcnt, true, error);
|
||||||
case Decoder::Opcode::SBarrier:
|
case Decoder::Opcode::SBarrier:
|
||||||
return LowerControlMarker(decoded, block, Opcode::Barrier, false, error);
|
return LowerControlMarker(decoded, block, Opcode::Barrier, false, error);
|
||||||
@@ -1075,6 +1076,7 @@ bool IsControlOpcode(Decoder::Opcode opcode) {
|
|||||||
switch (opcode) {
|
switch (opcode) {
|
||||||
case Decoder::Opcode::SNop:
|
case Decoder::Opcode::SNop:
|
||||||
case Decoder::Opcode::SWaitcnt:
|
case Decoder::Opcode::SWaitcnt:
|
||||||
|
case Decoder::Opcode::SWaitcntDepctr:
|
||||||
case Decoder::Opcode::SBarrier:
|
case Decoder::Opcode::SBarrier:
|
||||||
case Decoder::Opcode::SSendmsg:
|
case Decoder::Opcode::SSendmsg:
|
||||||
case Decoder::Opcode::SSetregB32:
|
case Decoder::Opcode::SSetregB32:
|
||||||
|
|||||||
@@ -863,6 +863,7 @@ struct TestCase {
|
|||||||
std::vector<u32> expected_gds;
|
std::vector<u32> expected_gds;
|
||||||
std::vector<std::pair<std::string, size_t>> decoded_counts;
|
std::vector<std::pair<std::string, size_t>> decoded_counts;
|
||||||
std::vector<std::pair<std::string, size_t>> ir_counts;
|
std::vector<std::pair<std::string, size_t>> ir_counts;
|
||||||
|
std::vector<std::pair<std::string, size_t>> native_ir_counts;
|
||||||
u32 expected_storage_mip_descriptors = 0;
|
u32 expected_storage_mip_descriptors = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1087,6 +1088,32 @@ CompiledShader CompileCase(const TestCase &test) {
|
|||||||
text + " count=" + std::to_string(actual) +
|
text + " count=" + std::to_string(actual) +
|
||||||
", expected=" + std::to_string(expected));
|
", expected=" + std::to_string(expected));
|
||||||
}
|
}
|
||||||
|
if (!test.native_ir_counts.empty()) {
|
||||||
|
ShaderRecompiler::Decoder::Program decoded;
|
||||||
|
ShaderRecompiler::CFG::Graph cfg;
|
||||||
|
ShaderRecompiler::IR::Program native;
|
||||||
|
std::string native_error;
|
||||||
|
Require(test.name, "native decode",
|
||||||
|
ShaderRecompiler::Decoder::DecodeProgram(test.code, decoded,
|
||||||
|
&native_error),
|
||||||
|
native_error);
|
||||||
|
Require(test.name, "native CFG",
|
||||||
|
ShaderRecompiler::CFG::BuildGraph(decoded, cfg, &native_error) &&
|
||||||
|
ShaderRecompiler::CFG::Structurize(cfg, &native_error),
|
||||||
|
native_error);
|
||||||
|
Require(test.name, "native lowering",
|
||||||
|
ShaderRecompiler::IR::LowerProgram(decoded, cfg, options.stage,
|
||||||
|
options.wave_size, native,
|
||||||
|
&native_error),
|
||||||
|
native_error);
|
||||||
|
const auto native_ir = ShaderRecompiler::IR::ProgramToString(native);
|
||||||
|
for (const auto &[text, expected] : test.native_ir_counts) {
|
||||||
|
const auto actual = CountText(native_ir, text);
|
||||||
|
Require(test.name, "native IR", actual == expected,
|
||||||
|
text + " count=" + std::to_string(actual) +
|
||||||
|
", expected=" + std::to_string(expected));
|
||||||
|
}
|
||||||
|
}
|
||||||
if (test.expected_storage_mip_descriptors != 0) {
|
if (test.expected_storage_mip_descriptors != 0) {
|
||||||
const auto image = std::ranges::find_if(
|
const auto image = std::ranges::find_if(
|
||||||
result.program.info.images, [](const auto &resource) {
|
result.program.info.images, [](const auto &resource) {
|
||||||
@@ -10877,6 +10904,31 @@ TestCase ScalarTrapDisabledFallsThroughExactRaw() {
|
|||||||
return test;
|
return test;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TestCase ScalarWaitcntDepctrCapturedVmVsrc() {
|
||||||
|
using O = ShaderOpcode;
|
||||||
|
|
||||||
|
std::vector<u32> code;
|
||||||
|
AppendVMovU32(&code, 7, 7);
|
||||||
|
AppendVMovU32(&code, 31, 0);
|
||||||
|
AppendBufferStoreDword(&code, 7, 31);
|
||||||
|
code.push_back(0xbfa3ffe3u); // s_waitcnt_depctr vm_vsrc(0)
|
||||||
|
AppendVMovU32(&code, 7, 42);
|
||||||
|
AppendStoreVgpr(&code, 7, 1);
|
||||||
|
AppendEnd(&code);
|
||||||
|
|
||||||
|
TestCase test;
|
||||||
|
test.name = "ScalarWaitcntDepctrCapturedVmVsrc";
|
||||||
|
test.code = std::move(code);
|
||||||
|
test.initial = {0, 0};
|
||||||
|
test.expected = {7, 42};
|
||||||
|
test.opcodes = {O::VMovB32, O::BufferStoreDword, O::SWaitcntDepctr,
|
||||||
|
O::SEndpgm};
|
||||||
|
test.decoded_counts = {{"0x00000010: s_waitcnt_depctr 0x0000ffe3\n", 1}};
|
||||||
|
test.native_ir_counts = {{"0x00000010: Waitcnt null, 0x0000ffe3", 1}};
|
||||||
|
test.forbidden_spirv = {"OpControlBarrier", "OpMemoryBarrier"};
|
||||||
|
return test;
|
||||||
|
}
|
||||||
|
|
||||||
TestCase ScalarExtendedArithmetic() {
|
TestCase ScalarExtendedArithmetic() {
|
||||||
using O = ShaderOpcode;
|
using O = ShaderOpcode;
|
||||||
|
|
||||||
@@ -17569,6 +17621,7 @@ std::vector<TestCase> MakeCases() {
|
|||||||
AddCase(ScalarShiftCountsMaskLowBits);
|
AddCase(ScalarShiftCountsMaskLowBits);
|
||||||
AddCase(Rdna2ScalarOpcodes);
|
AddCase(Rdna2ScalarOpcodes);
|
||||||
AddCase(ScalarTrapDisabledFallsThroughExactRaw);
|
AddCase(ScalarTrapDisabledFallsThroughExactRaw);
|
||||||
|
AddCase(ScalarWaitcntDepctrCapturedVmVsrc);
|
||||||
AddCase(ScalarExtendedArithmetic);
|
AddCase(ScalarExtendedArithmetic);
|
||||||
AddCase(ScalarArithmeticSccCarryBorrowOverflow);
|
AddCase(ScalarArithmeticSccCarryBorrowOverflow);
|
||||||
AddCase(ScalarMinMaxSccComparisonEdges);
|
AddCase(ScalarMinMaxSccComparisonEdges);
|
||||||
@@ -21046,6 +21099,11 @@ int main(int argc, char **argv) {
|
|||||||
RunCase(&vulkan, Vop3CvtPkI16I32Captured());
|
RunCase(&vulkan, Vop3CvtPkI16I32Captured());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (argc == 2 && std::strcmp(argv[1], "--waitcnt-depctr-only") == 0) {
|
||||||
|
VulkanHarness vulkan;
|
||||||
|
RunCase(&vulkan, ScalarWaitcntDepctrCapturedVmVsrc());
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
if (argc == 2 && std::strcmp(argv[1], "--sff1-b64-only") == 0) {
|
if (argc == 2 && std::strcmp(argv[1], "--sff1-b64-only") == 0) {
|
||||||
VulkanHarness vulkan;
|
VulkanHarness vulkan;
|
||||||
RunCase(&vulkan, ScalarBitfieldPack());
|
RunCase(&vulkan, ScalarBitfieldPack());
|
||||||
|
|||||||
Reference in New Issue
Block a user