mirror of
https://github.com/KytyPS5/KytyPS5.git
synced 2026-10-28 08:13:05 +00:00
agc: new ABI
This commit is contained in:
1 parent
d0a4c908a1
commit
a44dd88806
5 files changed
+155
-24
No files matched your search
@@ -2837,7 +2837,7 @@ KYTY_CP_OP_PARSER(CpOpSetShaderReg) {
|
||||
KYTY_CP_OP_PARSER(CpOpSetUconfigReg) {
|
||||
KYTY_PROFILER_FUNCTION();
|
||||
|
||||
if (Gen5::AgcIsWaitUserDataPacket(cmd_id, buffer)) {
|
||||
if (Gen5::AgcIsInternalDataPacket(cmd_id, buffer)) {
|
||||
return KYTY_PM4_LEN(cmd_id) - 1u;
|
||||
}
|
||||
|
||||
|
||||
+93
-21
@@ -2619,6 +2619,21 @@ static uint32_t decode_draw_index_initiator(uint64_t modifier) {
|
||||
return (static_cast<uint32_t>(modifier) >> 3u) & 0x20u;
|
||||
}
|
||||
|
||||
static constexpr uint32_t AGC_INTERNAL_DATA_REGISTER = 0x342u;
|
||||
static constexpr uint32_t AGC_DRAW_INDIRECT_MULTI_BEGIN_TAG = 0xc6000008u;
|
||||
static constexpr uint32_t AGC_DRAW_INDIRECT_MULTI_END_TAG = 0xc6000000u;
|
||||
static constexpr uint32_t AGC_WAIT_USER_DATA_BEGIN_32_TAG = 0xc8010000u;
|
||||
static constexpr uint32_t AGC_WAIT_USER_DATA_BEGIN_64_TAG = 0xc8020000u;
|
||||
static constexpr uint32_t AGC_WAIT_USER_DATA_END_TAG = 0xc8000000u;
|
||||
static constexpr uint32_t AGC_WAIT_USER_DATA_BEGIN_DW = 4u;
|
||||
static constexpr uint32_t AGC_INTERNAL_DATA_PACKET_SIZE_DW = 3u;
|
||||
|
||||
static void write_agc_internal_data_packet(uint32_t* cmd, uint32_t tag) {
|
||||
cmd[0] = KYTY_PM4(AGC_INTERNAL_DATA_PACKET_SIZE_DW, Pm4::IT_SET_UCONFIG_REG, 1u);
|
||||
cmd[1] = AGC_INTERNAL_DATA_REGISTER;
|
||||
cmd[2] = tag;
|
||||
}
|
||||
|
||||
uint32_t* KYTY_SYSV_ABI AgcDcbDrawIndex(CommandBuffer* buf, uint32_t index_count,
|
||||
const volatile void* index_addr, uint64_t modifier) {
|
||||
PRINT_NAME();
|
||||
@@ -2875,6 +2890,69 @@ uint32_t* KYTY_SYSV_ABI AgcDcbDrawIndirect(CommandBuffer* buf, uint32_t data_off
|
||||
return cmd;
|
||||
}
|
||||
|
||||
uint32_t* KYTY_SYSV_ABI AgcDcbDrawIndirectMulti(CommandBuffer* buf,
|
||||
uint32_t data_offset_in_bytes,
|
||||
uint32_t count_indirect,
|
||||
uint32_t max_count_or_count,
|
||||
const volatile void* count_addr,
|
||||
uint32_t stride_in_bytes, uint64_t modifier) {
|
||||
PRINT_NAME();
|
||||
|
||||
LOGF("\t data_offset = 0x%" PRIx32 "\n"
|
||||
"\t count_indirect = 0x%" PRIx32 "\n"
|
||||
"\t max_count_or_count = 0x%" PRIx32 "\n"
|
||||
"\t count_addr = 0x%016" PRIx64 "\n"
|
||||
"\t stride_in_bytes = 0x%" PRIx32 "\n"
|
||||
"\t modifier = 0x%016" PRIx64 "\n",
|
||||
data_offset_in_bytes, count_indirect, max_count_or_count,
|
||||
reinterpret_cast<uint64_t>(count_addr), stride_in_bytes, modifier);
|
||||
|
||||
if (buf == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
buf->DbgDump();
|
||||
|
||||
constexpr uint32_t draw_packet_size_dw = 10u;
|
||||
constexpr uint32_t total_size_dw =
|
||||
AGC_INTERNAL_DATA_PACKET_SIZE_DW + draw_packet_size_dw +
|
||||
AGC_INTERNAL_DATA_PACKET_SIZE_DW;
|
||||
auto* cmd = buf->AllocateDW(total_size_dw);
|
||||
if (cmd == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
write_agc_internal_data_packet(cmd, AGC_DRAW_INDIRECT_MULTI_BEGIN_TAG);
|
||||
auto* draw = cmd + AGC_INTERNAL_DATA_PACKET_SIZE_DW;
|
||||
auto* end = draw + draw_packet_size_dw;
|
||||
write_agc_internal_data_packet(end, AGC_DRAW_INDIRECT_MULTI_END_TAG);
|
||||
|
||||
const auto low = static_cast<uint32_t>(modifier);
|
||||
const auto sgpr_base = indirect_modifier_sgpr_base(low);
|
||||
const auto patch_offsets = decode_indirect_modifier_patch_offsets(modifier, false);
|
||||
const auto count_vaddr = reinterpret_cast<uint64_t>(count_addr);
|
||||
|
||||
uint32_t draw_index_location = 0x280u;
|
||||
if ((low & 0x8u) != 0) {
|
||||
draw_index_location = sgpr_base + extract_modifier_bits(low, 24u, 5u);
|
||||
}
|
||||
const auto draw_control = draw_index_location | ((low & 0x10u) << 23u) |
|
||||
((count_indirect & 0x1u) << 30u) | ((low & 0x8u) << 28u);
|
||||
|
||||
draw[0] = KYTY_PM4(draw_packet_size_dw, Pm4::IT_DRAW_INDIRECT_MULTI, 0u);
|
||||
draw[1] = data_offset_in_bytes;
|
||||
draw[2] = static_cast<uint32_t>(patch_offsets);
|
||||
draw[3] = static_cast<uint32_t>(patch_offsets >> 32u);
|
||||
draw[4] = draw_control;
|
||||
draw[5] = max_count_or_count;
|
||||
draw[6] = static_cast<uint32_t>(count_vaddr) & ~0x3u;
|
||||
draw[7] = static_cast<uint32_t>(count_vaddr >> 32u);
|
||||
draw[8] = stride_in_bytes;
|
||||
draw[9] = decode_indirect_draw_initiator(modifier);
|
||||
|
||||
return cmd;
|
||||
}
|
||||
|
||||
uint32_t* KYTY_SYSV_ABI AgcDcbDrawIndexIndirectMulti(CommandBuffer* buf,
|
||||
uint32_t data_offset_in_bytes,
|
||||
uint32_t count_indirect,
|
||||
@@ -3793,16 +3871,9 @@ uint32_t* KYTY_SYSV_ABI AgcDcbGetLodStats(CommandBuffer* buf, uint8_t cache_poli
|
||||
return cmd;
|
||||
}
|
||||
|
||||
static constexpr uint32_t AGC_WAIT_USER_DATA_REGISTER = 0x342u;
|
||||
static constexpr uint32_t AGC_WAIT_USER_DATA_BEGIN_32_TAG = 0xc8010000u;
|
||||
static constexpr uint32_t AGC_WAIT_USER_DATA_BEGIN_64_TAG = 0xc8020000u;
|
||||
static constexpr uint32_t AGC_WAIT_USER_DATA_END_TAG = 0xc8000000u;
|
||||
static constexpr uint32_t AGC_WAIT_USER_DATA_BEGIN_DW = 4u;
|
||||
static constexpr uint32_t AGC_WAIT_USER_DATA_END_DW = 3u;
|
||||
|
||||
static uint32_t* get_agc_wait_packet(uint32_t* cmd) {
|
||||
if (cmd == nullptr || KYTY_PM4_LEN(cmd[0]) != AGC_WAIT_USER_DATA_BEGIN_DW ||
|
||||
!AgcIsWaitUserDataPacket(cmd[0], cmd + 1)) {
|
||||
!AgcIsInternalDataPacket(cmd[0], cmd + 1)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -3946,20 +4017,22 @@ static uint32_t wait_reg_mem64_control(uint8_t compare_function, uint8_t op, uin
|
||||
((static_cast<uint32_t>(cache_policy) & 0x3u) << 25u);
|
||||
}
|
||||
|
||||
bool AgcIsWaitUserDataPacket(uint32_t cmd_id, const uint32_t* payload) {
|
||||
bool AgcIsInternalDataPacket(uint32_t cmd_id, const uint32_t* payload) {
|
||||
if (payload == nullptr || ((cmd_id >> 8u) & 0xffu) != Pm4::IT_SET_UCONFIG_REG ||
|
||||
KYTY_PM4_R(cmd_id) != 1u || payload[0] != AGC_WAIT_USER_DATA_REGISTER) {
|
||||
KYTY_PM4_R(cmd_id) != 1u || payload[0] != AGC_INTERNAL_DATA_REGISTER) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const auto size_dw = KYTY_PM4_LEN(cmd_id);
|
||||
if (size_dw != AGC_WAIT_USER_DATA_BEGIN_DW && size_dw != AGC_WAIT_USER_DATA_END_DW) {
|
||||
return false;
|
||||
if (size_dw == AGC_WAIT_USER_DATA_BEGIN_DW) {
|
||||
const auto tag = payload[1] & 0xffff0000u;
|
||||
return tag == AGC_WAIT_USER_DATA_BEGIN_32_TAG || tag == AGC_WAIT_USER_DATA_BEGIN_64_TAG;
|
||||
}
|
||||
const auto tag = payload[1] & 0xffff0000u;
|
||||
return (size_dw == AGC_WAIT_USER_DATA_BEGIN_DW &&
|
||||
(tag == AGC_WAIT_USER_DATA_BEGIN_32_TAG || tag == AGC_WAIT_USER_DATA_BEGIN_64_TAG)) ||
|
||||
(size_dw == AGC_WAIT_USER_DATA_END_DW && payload[1] == AGC_WAIT_USER_DATA_END_TAG);
|
||||
|
||||
return size_dw == AGC_INTERNAL_DATA_PACKET_SIZE_DW &&
|
||||
(payload[1] == AGC_WAIT_USER_DATA_END_TAG ||
|
||||
payload[1] == AGC_DRAW_INDIRECT_MULTI_BEGIN_TAG ||
|
||||
payload[1] == AGC_DRAW_INDIRECT_MULTI_END_TAG);
|
||||
}
|
||||
|
||||
uint32_t* KYTY_SYSV_ABI AgcDcbWaitRegMem(CommandBuffer* buf, uint8_t size, uint8_t compare_function,
|
||||
@@ -3998,7 +4071,8 @@ uint32_t* KYTY_SYSV_ABI AgcDcbWaitRegMem(CommandBuffer* buf, uint8_t size, uint8
|
||||
bool wait32 = (size == 0);
|
||||
auto poll = wait_reg_mem_poll_cycles_to_packet(poll_cycles);
|
||||
const auto wait_dw = wait32 ? 7u : 9u;
|
||||
const auto total_dw = AGC_WAIT_USER_DATA_BEGIN_DW + wait_dw + AGC_WAIT_USER_DATA_END_DW;
|
||||
const auto total_dw =
|
||||
AGC_WAIT_USER_DATA_BEGIN_DW + wait_dw + AGC_INTERNAL_DATA_PACKET_SIZE_DW;
|
||||
|
||||
auto* cmd = buf->AllocateDW(total_dw);
|
||||
|
||||
@@ -4007,16 +4081,14 @@ uint32_t* KYTY_SYSV_ABI AgcDcbWaitRegMem(CommandBuffer* buf, uint8_t size, uint8
|
||||
}
|
||||
|
||||
cmd[0] = KYTY_PM4(AGC_WAIT_USER_DATA_BEGIN_DW, Pm4::IT_SET_UCONFIG_REG, 1u);
|
||||
cmd[1] = AGC_WAIT_USER_DATA_REGISTER;
|
||||
cmd[1] = AGC_INTERNAL_DATA_REGISTER;
|
||||
cmd[2] = (wait32 ? AGC_WAIT_USER_DATA_BEGIN_32_TAG : AGC_WAIT_USER_DATA_BEGIN_64_TAG) |
|
||||
static_cast<uint32_t>((address_value >> 32u) & 0xffffu);
|
||||
cmd[3] = static_cast<uint32_t>(address_value);
|
||||
|
||||
auto* wait = cmd + AGC_WAIT_USER_DATA_BEGIN_DW;
|
||||
auto* end = wait + wait_dw;
|
||||
end[0] = KYTY_PM4(AGC_WAIT_USER_DATA_END_DW, Pm4::IT_SET_UCONFIG_REG, 1u);
|
||||
end[1] = AGC_WAIT_USER_DATA_REGISTER;
|
||||
end[2] = AGC_WAIT_USER_DATA_END_TAG;
|
||||
write_agc_internal_data_packet(end, AGC_WAIT_USER_DATA_END_TAG);
|
||||
|
||||
if (wait32) {
|
||||
wait[0] = KYTY_PM4(7, Pm4::IT_WAIT_REG_MEM, 0u);
|
||||
|
||||
+7
-1
@@ -171,6 +171,12 @@ uint32_t* KYTY_SYSV_ABI AgcDcbSetBaseIndirectArgs(CommandBuffer* buf, uint32_t s
|
||||
uint32_t* KYTY_SYSV_ABI AgcDcbDrawIndirect(CommandBuffer* buf, uint32_t data_offset_in_bytes,
|
||||
uint64_t modifier);
|
||||
uint32_t KYTY_SYSV_ABI AgcDcbDrawIndirectGetSize();
|
||||
uint32_t* KYTY_SYSV_ABI AgcDcbDrawIndirectMulti(CommandBuffer* buf,
|
||||
uint32_t data_offset_in_bytes,
|
||||
uint32_t count_indirect,
|
||||
uint32_t max_count_or_count,
|
||||
const volatile void* count_addr,
|
||||
uint32_t stride_in_bytes, uint64_t modifier);
|
||||
uint32_t* KYTY_SYSV_ABI AgcDcbDrawIndexIndirect(CommandBuffer* buf, uint32_t data_offset_in_bytes,
|
||||
uint64_t modifier);
|
||||
uint32_t* KYTY_SYSV_ABI AgcDcbDrawIndexIndirectMulti(CommandBuffer* buf,
|
||||
@@ -273,7 +279,7 @@ uint32_t* KYTY_SYSV_ABI AgcDcbWaitRegMem(CommandBuffer* buf, uint8_t size, uint8
|
||||
const volatile void* address, uint64_t reference,
|
||||
uint64_t mask, uint32_t poll_cycles);
|
||||
uint64_t KYTY_SYSV_ABI AgcDcbWaitOnAddressGetSize(uint32_t size);
|
||||
bool AgcIsWaitUserDataPacket(uint32_t cmd_id, const uint32_t* payload);
|
||||
bool AgcIsInternalDataPacket(uint32_t cmd_id, const uint32_t* payload);
|
||||
uint32_t* KYTY_SYSV_ABI AgcDcbSetMarker(CommandBuffer* buf, const char* str, uint32_t color);
|
||||
uint32_t* KYTY_SYSV_ABI AgcDcbPushMarker(CommandBuffer* buf, const char* str, uint32_t color);
|
||||
uint32_t* KYTY_SYSV_ABI AgcDcbPopMarker(CommandBuffer* buf);
|
||||
|
||||
@@ -111,6 +111,7 @@ LIB_DEFINE(InitAgcDriver_1) {
|
||||
LIB_FUNC("RmaJwLtc8rY", Gen5::AgcDcbSetBaseIndirectArgs);
|
||||
LIB_FUNC("1q1titRBL6o", Gen5::AgcDcbDrawIndirect);
|
||||
LIB_FUNC("cxPZ4Wgvdj8", Gen5::AgcDcbDrawIndirectGetSize);
|
||||
LIB_FUNC("kUlvghKs-mA", Gen5::AgcDcbDrawIndirectMulti);
|
||||
LIB_FUNC("t1vNu082-jM", Gen5::AgcDcbDrawIndexIndirect);
|
||||
LIB_FUNC("ypVBz4uPKcQ", Gen5::AgcDcbDrawIndexIndirectMulti);
|
||||
LIB_FUNC("CtB+A9-VxO0", Gen5::AgcDcbDispatchIndirect);
|
||||
|
||||
@@ -22835,12 +22835,58 @@ void CheckAgcWaitPackets(RenderContext &renderer) {
|
||||
packet_mismatch &&
|
||||
Gen5::AgcWaitRegMemPatchReference(invalid.data(), label32) ==
|
||||
packet_mismatch &&
|
||||
!Gen5::AgcIsWaitUserDataPacket(
|
||||
!Gen5::AgcIsInternalDataPacket(
|
||||
KYTY_PM4(2, Pm4::IT_SET_UCONFIG_REG, 1), &short_payload),
|
||||
"native wait patch accepted a packet without the AGC metadata prefix");
|
||||
std::printf("[host] %-32s ok\n", "AgcWaitPackets");
|
||||
}
|
||||
|
||||
void CheckAgcDrawIndirectMultiPacket(RenderContext &renderer) {
|
||||
GraphicsInitJmpTables();
|
||||
CommandProcessor processor(renderer);
|
||||
const auto execute = [&](uint32_t *packet, uint32_t size_dw) {
|
||||
Pm4Execution execution;
|
||||
return processor.Process(execution, packet, size_dw) ==
|
||||
Pm4ProcessResult::Complete;
|
||||
};
|
||||
|
||||
constexpr uint64_t modifier = 0x0000000069380b1dull;
|
||||
constexpr auto packet_mismatch = static_cast<int>(0x8a6c000cu);
|
||||
const auto *count_address = reinterpret_cast<const volatile void *>(
|
||||
static_cast<uintptr_t>(0x123456789abcdef3ull));
|
||||
constexpr std::array<uint32_t, 16> expected{
|
||||
0xc0017904u, 0x00000342u, 0xc6000008u, 0xc0082c00u,
|
||||
0x11223344u, 0x00000111u, 0x00000113u, 0xc8000115u,
|
||||
0x55667788u, 0x9abcdef0u, 0x12345678u, 0xaabbccddu,
|
||||
0x00000022u, 0xc0017904u, 0x00000342u, 0xc6000000u};
|
||||
|
||||
std::array<uint32_t, 16> packet{};
|
||||
AgcCommandBufferLayout dcb{packet.data(),
|
||||
packet.data() + packet.size(),
|
||||
packet.data(),
|
||||
packet.data() + packet.size(),
|
||||
nullptr,
|
||||
nullptr,
|
||||
0};
|
||||
auto *emitted = Gen5::AgcDcbDrawIndirectMulti(
|
||||
reinterpret_cast<Gen5::CommandBuffer *>(&dcb), 0x11223344u, 1u,
|
||||
0x55667788u, count_address, 0xaabbccddu, modifier);
|
||||
|
||||
const uint32_t invalid_payload[]{0x342u, 0xc6000010u};
|
||||
Require(
|
||||
"AgcDrawIndirectMulti", "native packet",
|
||||
emitted == packet.data() && dcb.cursor_up == packet.data() + packet.size() &&
|
||||
packet == expected && execute(packet.data(), 3u) &&
|
||||
execute(packet.data() + 13u, 3u) &&
|
||||
Gen5::AgcWaitRegMemPatchAddress(packet.data(), count_address) ==
|
||||
packet_mismatch &&
|
||||
Gen5::AgcWaitRegMemPatchReference(packet.data(), 0x12345678u) ==
|
||||
packet_mismatch &&
|
||||
!Gen5::AgcIsInternalDataPacket(0xc0017904u, invalid_payload),
|
||||
"drawIndirectMulti stream differs from native AGC");
|
||||
std::printf("[host] %-32s ok\n", "AgcDrawIndirectMulti");
|
||||
}
|
||||
|
||||
void CheckPm4ContextStateOperations(RenderContext &renderer) {
|
||||
GraphicsInitJmpTables();
|
||||
CommandProcessor processor(renderer);
|
||||
@@ -23228,6 +23274,11 @@ int main(int argc, char **argv) {
|
||||
CheckPm4WaitResume(vulkan.RuntimeRenderer());
|
||||
return 0;
|
||||
}
|
||||
if (argc == 2 && std::strcmp(argv[1], "--agc-draw-multi-only") == 0) {
|
||||
VulkanHarness vulkan;
|
||||
CheckAgcDrawIndirectMultiPacket(vulkan.RuntimeRenderer());
|
||||
return 0;
|
||||
}
|
||||
if (argc == 2 && std::strcmp(argv[1], "--rewind-only") == 0) {
|
||||
VulkanHarness vulkan;
|
||||
CheckPm4RewindResume(vulkan.RuntimeRenderer());
|
||||
@@ -23393,6 +23444,7 @@ int main(int argc, char **argv) {
|
||||
CheckPm4BlendColorRegisterRanges(vulkan.RuntimeRenderer());
|
||||
CheckPm4PolygonOffsetRegisters(vulkan.RuntimeRenderer());
|
||||
CheckAgcWaitPackets(vulkan.RuntimeRenderer());
|
||||
CheckAgcDrawIndirectMultiPacket(vulkan.RuntimeRenderer());
|
||||
CheckPm4ContextStateOperations(vulkan.RuntimeRenderer());
|
||||
CheckPm4WaitResume(vulkan.RuntimeRenderer());
|
||||
CheckPm4RewindResume(vulkan.RuntimeRenderer());
|
||||
|
||||
Reference in new issue
Block a user