mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-26 11:44:16 +01:00
Fix waitForFences
crash on Mali drivers
Mali GPU drivers utilize the `ppoll()` syscall inside `waitForFences` which isn't correctly restarted after a signal, which we can receive at any time on a guest thread. This commit fixes that by recursively calling the function on failure till it succeeds or returns an unexpected error. Co-authored-by: PixelyIon <pixelyion@protonmail.com> Co-authored-by: Billy Laws <blaws05@gmail.com>
This commit is contained in:
parent
942e22f275
commit
cbc896c8f8
@ -68,7 +68,20 @@ namespace skyline::gpu {
|
|||||||
void Wait() {
|
void Wait() {
|
||||||
if (signalled.test(std::memory_order_consume))
|
if (signalled.test(std::memory_order_consume))
|
||||||
return;
|
return;
|
||||||
while (device.waitForFences(fence, false, std::numeric_limits<u64>::max()) != vk::Result::eSuccess);
|
|
||||||
|
vk::Result waitResult;
|
||||||
|
while ((waitResult = (*device).waitForFences(1, &fence, false, std::numeric_limits<u64>::max(), *device.getDispatcher())) != vk::Result::eSuccess) {
|
||||||
|
if (waitResult == vk::Result::eTimeout)
|
||||||
|
// Retry if the waiting time out
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (waitResult == vk::Result::eErrorInitializationFailed)
|
||||||
|
// eErrorInitializationFailed occurs on Mali GPU drivers due to them using the ppoll() syscall which isn't correctly restarted after a signal, we need to manually retry waiting in that case
|
||||||
|
continue;
|
||||||
|
|
||||||
|
throw exception("An error occurred while waiting for fence 0x{:X}: {}", static_cast<VkFence>(fence), vk::to_string(waitResult));
|
||||||
|
}
|
||||||
|
|
||||||
if (!signalled.test_and_set(std::memory_order_release))
|
if (!signalled.test_and_set(std::memory_order_release))
|
||||||
DestroyDependencies();
|
DestroyDependencies();
|
||||||
}
|
}
|
||||||
@ -80,7 +93,7 @@ namespace skyline::gpu {
|
|||||||
bool Wait(std::chrono::duration<u64, std::nano> timeout) {
|
bool Wait(std::chrono::duration<u64, std::nano> timeout) {
|
||||||
if (signalled.test(std::memory_order_consume))
|
if (signalled.test(std::memory_order_consume))
|
||||||
return true;
|
return true;
|
||||||
if (device.waitForFences(fence, false, timeout.count()) == vk::Result::eSuccess) {
|
if ((*device).waitForFences(1, &fence, false, std::numeric_limits<u64>::max(), *device.getDispatcher()) == vk::Result::eSuccess) {
|
||||||
if (!signalled.test_and_set(std::memory_order_release))
|
if (!signalled.test_and_set(std::memory_order_release))
|
||||||
DestroyDependencies();
|
DestroyDependencies();
|
||||||
return true;
|
return true;
|
||||||
@ -144,8 +157,8 @@ namespace skyline::gpu {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& dependency{*dependencies.begin()};
|
auto &dependency{*dependencies.begin()};
|
||||||
auto& lastDependency{*std::prev(dependencies.end())};
|
auto &lastDependency{*std::prev(dependencies.end())};
|
||||||
lastDependency->next = std::atomic_load_explicit(&list, std::memory_order_acquire);
|
lastDependency->next = std::atomic_load_explicit(&list, std::memory_order_acquire);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
Loading…
Reference in New Issue
Block a user