Merge pull request #695 from tv7/feat/agc-submit-multi-dcbs

feat(libSceAgcDriver): implement sceAgcDriverSubmitMultiDcbs and sceAgcDriverAgrSubmitMultiDcbs
This commit is contained in:
Dean 2026-10-06 22:26:54 +13:00 committed by GitHub
commit 451b72ecc6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 45 additions and 11 deletions

View File

@ -5,5 +5,7 @@
extern "C" int APS5_VABI sceAgcDriverSubmitDcb(const Packet* packet);
extern "C" int APS5_VABI sceAgcDriverAgrSubmitDcb(const Packet* packet);
extern "C" int APS5_VABI sceAgcDriverSubmitMultiDcbs(std::uint32_t* const* dcbGpuAddrs, const std::uint32_t* dcbSizesInDwords, std::uint32_t count);
extern "C" int APS5_VABI sceAgcDriverAgrSubmitMultiDcbs(std::uint32_t* const* dcbGpuAddrs, const std::uint32_t* dcbSizesInDwords, std::uint32_t count);
#endif

View File

@ -10,6 +10,18 @@
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
static int SubmitMany(std::uint32_t* const* addresses, const std::uint32_t* sizes, std::uint32_t count) {
if (count == 0) return 0;
if (!addresses || !sizes) throw std::runtime_error("AGC driver: null multi-DCB arrays");
AgcDriver::GuestMemory::CheckRange(addresses, count * sizeof(*addresses), alignof(std::uint32_t*));
AgcDriver::GuestMemory::CheckRange(sizes, count * sizeof(*sizes), alignof(std::uint32_t));
for (std::uint32_t i = 0; i < count; ++i) {
const Packet packet{addresses[i], sizes[i], 0, {}};
AgcDriver::Submit(&packet, 0);
}
return 0;
}
extern "C" {
std::uint32_t APS5_VABI sceAgcDriverGetWaitRenderingPacketSizeInDwords() {
@ -33,12 +45,8 @@ int APS5_VABI sceAgcDriverSubmitDcb(const Packet* packet) {
return 0;
}
int APS5_VABI sceAgcDriverSubmitMultiDcbs(uint32_t* const* dcb_gpu_addrs, const uint32_t* dcb_sizes_in_dwords, uint32_t count) {
(void)dcb_gpu_addrs;
(void)dcb_sizes_in_dwords;
(void)count;
NotImplemented_nid_no_patch(__func__);
return 0;
int APS5_VABI sceAgcDriverSubmitMultiDcbs(std::uint32_t* const* dcbGpuAddrs, const std::uint32_t* dcbSizesInDwords, std::uint32_t count) {
return SubmitMany(dcbGpuAddrs, dcbSizesInDwords, count);
}
int APS5_VABI sceAgcDriverAgrSubmitDcb(const Packet* packet) {
@ -47,11 +55,7 @@ int APS5_VABI sceAgcDriverAgrSubmitDcb(const Packet* packet) {
}
int APS5_VABI sceAgcDriverAgrSubmitMultiDcbs(std::uint32_t* const* dcbGpuAddrs, const std::uint32_t* dcbSizesInDwords, std::uint32_t count) {
(void)dcbGpuAddrs;
(void)dcbSizesInDwords;
(void)count;
NotImplemented_nid_no_patch(__func__);
return 0;
return SubmitMany(dcbGpuAddrs, dcbSizesInDwords, count);
}
}

View File

@ -347,6 +347,33 @@ void testWaitFreeSubmissionTheCpuWaitsFor() {
AgcDriverWaitIdle_nid_postfix();
}
void testMultiSubmissions() {
alignas(64) static volatile std::uint32_t value = 0, done = 0;
check(sceAgcDriverSubmitMultiDcbs(nullptr, nullptr, 0) == 0, "empty multi-DCB submit failed");
check(sceAgcDriverAgrSubmitMultiDcbs(nullptr, nullptr, 0) == 0, "empty AGR multi-DCB submit failed");
std::array<std::uint32_t, 3> invalid{0xc0017600, 0x20c, 0};
std::array<std::uint32_t*, 1> invalidAddresses{invalid.data()};
std::array<std::uint32_t, 1> invalidSizes{2};
expectFailure([&] { sceAgcDriverSubmitMultiDcbs(nullptr, invalidSizes.data(), 1); });
expectFailure([&] { sceAgcDriverAgrSubmitMultiDcbs(invalidAddresses.data(), nullptr, 1); });
expectFailure([&] { sceAgcDriverSubmitMultiDcbs(invalidAddresses.data(), invalidSizes.data(), 1); });
expectFailure([&] { sceAgcDriverAgrSubmitMultiDcbs(invalidAddresses.data(), invalidSizes.data(), 1); });
for (bool agr : {false, true}) {
value = 0;
done = 0;
auto first = writeData(&value, 1);
auto second = writeData(&value, 2);
auto third = writeData(&done, 1);
std::array<std::uint32_t*, 3> addresses{first.data(), second.data(), third.data()};
std::array<std::uint32_t, 3> sizes{static_cast<std::uint32_t>(first.size()), static_cast<std::uint32_t>(second.size()), static_cast<std::uint32_t>(third.size())};
const int result = agr ? sceAgcDriverAgrSubmitMultiDcbs(addresses.data(), sizes.data(), 3) : sceAgcDriverSubmitMultiDcbs(addresses.data(), sizes.data(), 3);
check(result == 0, "multi-DCB submit failed");
waitFor(&done, 1, "the last DCB of a multi-DCB submit never ran");
check(value == 2, "multi-DCB submit did not run its DCBs in order");
AgcDriverWaitIdle_nid_postfix();
}
}
void testWorkerFailure() {
std::array<std::uint32_t, 5> words{0xc0031500, 1, 1, 1, 0x41};
Packet packet{words.data(), static_cast<std::uint32_t>(words.size()), 0, {}};
@ -442,6 +469,7 @@ int main() {
testWaitFreeSubmissionQueue0WaitsOn();
testWaitFreeSubmissionBehindHeldOne();
testWaitFreeSubmissionTheCpuWaitsFor();
testMultiSubmissions();
testWorkerFailure();
check(expectFailure([] { LibcRunShutdown_nid_postfix(); }).find("required shader register") != std::string::npos, "shutdown lost worker failure");
std::puts("AGC driver submit tests passed");