aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-29 01:26:52 -0400
committerTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-29 01:26:52 -0400
commite8bc734d1040044abe117a369a9f80a792e51df4 (patch)
tree03bc201a0d2d37606b2c785ddef94d963ec851ee /src
parent2bb0f8acdf79816ae1c474c42e2b63dbaa4500e8 (diff)
video_core: guard the fence manager's uncommitted operations
SyncOperation appended to uncommitted_operations without a lock while SignalFence moved that list into pending_operations under `guard` on another thread; a list corrupted this way crashed the fencing thread. They now share a lock of their own, held for no callbacks (SignalFence runs callbacks under `guard`, so taking `guard` here could deadlock).
Diffstat (limited to 'src')
-rw-r--r--src/video_core/fence_manager.h15
1 files changed, 12 insertions, 3 deletions
diff --git a/src/video_core/fence_manager.h b/src/video_core/fence_manager.h
index 776c01e3fa..65d8f24aae 100644
--- a/src/video_core/fence_manager.h
+++ b/src/video_core/fence_manager.h
@@ -68,6 +68,10 @@ public:
}
void SyncOperation(std::function<void()>&& func) {
+ // Not only the GPU thread queues these (query cache work runs elsewhere too), while
+ // SignalFence moves the list into pending_operations: unguarded, the list was corrupted
+ // and the fencing thread crashed walking it. Its own lock, held for no callbacks.
+ std::scoped_lock lock{uncommitted_guard};
uncommitted_operations.emplace_back(std::move(func));
}
@@ -82,10 +86,14 @@ public:
if constexpr (can_async_check) {
guard.lock();
}
- if (delay_fence) {
- uncommitted_operations.emplace_back(std::move(func));
+ {
+ std::scoped_lock lock{uncommitted_guard};
+ if (delay_fence) {
+ uncommitted_operations.emplace_back(std::move(func));
+ }
+ pending_operations.emplace_back(std::move(uncommitted_operations));
+ uncommitted_operations.clear(); // moved-from: make it empty explicitly
}
- pending_operations.emplace_back(std::move(uncommitted_operations));
QueueFence(new_fence);
if (!delay_fence) {
func();
@@ -261,6 +269,7 @@ private:
std::mutex guard;
std::mutex ring_guard;
+ std::mutex uncommitted_guard; ///< Guards uncommitted_operations
std::condition_variable cv;
std::jthread fence_thread;