Merge pull request #695 from tv7/feat/agc-submit-multi-dcbs
feat(libSceAgcDriver): implement sceAgcDriverSubmitMultiDcbs and sceAgcDriverAgrSubmitMultiDcbs
This commit is contained in:
commit
451b72ecc6
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
Loading…
Reference in New Issue