Skip to content

Commit 87caa99

Browse files
authored
Fix potential deadlock in wait_for_next_frame() for timeline_semaphore example (#1531)
1 parent d7cc68c commit 87caa99

2 files changed

Lines changed: 14 additions & 6 deletions

File tree

samples/extensions/timeline_semaphore/timeline_semaphore.cpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -262,10 +262,10 @@ void TimelineSemaphore::signal_next_frame()
262262
}
263263

264264
// Waits for the timeline to reach MAX_STAGES for the current frame
265-
void TimelineSemaphore::wait_for_next_frame()
265+
void TimelineSemaphore::wait_for_next_frame(const uint64_t nextFrame)
266266
{
267267
// MAX_STAGES is used as it provides a boundary value between the stages of this frame and the next
268-
const uint64_t waitValue = (timeline.frame + 1) * Timeline::MAX_STAGES;
268+
const uint64_t waitValue = nextFrame * Timeline::MAX_STAGES;
269269

270270
VkSemaphoreWaitInfo waitInfo;
271271
waitInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO;
@@ -307,13 +307,17 @@ void TimelineSemaphore::do_compute_work()
307307
submit_info.signalSemaphoreCount = 1;
308308
submit_info.pSignalSemaphores = &timeline.semaphore;
309309

310+
// Define next frame prior to queue submit to prevent potential deadlock in wait_for_next_frame(). This can happen due to incorrect
311+
// waitValue caused by signalling the main thread to advance the frame before completion of wait_for_next_frame() in worker threads
312+
uint64_t nextFrame = timeline.frame + 1;
313+
310314
// If the threads are being killed, we need to skip the queue submission to allow the program to exit gracefully
311315
if (compute_worker.alive)
312316
{
313317
VK_CHECK(vkQueueSubmit(compute.queue, 1, &submit_info, VK_NULL_HANDLE));
314318
}
315319

316-
wait_for_next_frame();
320+
wait_for_next_frame(nextFrame);
317321
}
318322
}
319323

@@ -485,13 +489,17 @@ void TimelineSemaphore::do_graphics_work()
485489
wait_on_timeline(Timeline::draw);
486490
}
487491

492+
// Define next frame prior to queue submit to prevent potential deadlock in wait_for_next_frame(). This can happen due to incorrect
493+
// waitValue caused by signalling the main thread to advance the frame before completion of wait_for_next_frame() in worker threads
494+
uint64_t nextFrame = timeline.frame + 1;
495+
488496
// If the threads are being killed, we need to skip the queue submission to allow the program to exit gracefully
489497
if (graphics_worker.alive)
490498
{
491499
VK_CHECK(vkQueueSubmit(graphics.queue, 1, &submit_info, VK_NULL_HANDLE));
492500
}
493501

494-
wait_for_next_frame();
502+
wait_for_next_frame(nextFrame);
495503
}
496504
}
497505

samples/extensions/timeline_semaphore/timeline_semaphore.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2021-2025, Arm Limited and Contributors
1+
/* Copyright (c) 2021-2026, Arm Limited and Contributors
22
*
33
* SPDX-License-Identifier: Apache-2.0
44
*
@@ -104,7 +104,7 @@ class TimelineSemaphore : public ApiVulkanSample
104104
void signal_timeline(const Timeline::Stages stage);
105105
void wait_on_timeline(const Timeline::Stages stage);
106106
void signal_next_frame();
107-
void wait_for_next_frame();
107+
void wait_for_next_frame(const uint64_t nextFrame);
108108
uint64_t get_timeline_stage_value(const Timeline::Stages stage);
109109

110110
// Compute Work

0 commit comments

Comments
 (0)