Skip to content

Commit

Permalink
Vulkan: Resignal unexecuted fences on thread stop.
Browse files Browse the repository at this point in the history
When resizing or similar, we may end up with frames we never ran.  This
also happens on startup.

We need them signaled at start so we can wait on them, or we may deadlock.
  • Loading branch information
unknownbrackets committed Nov 5, 2017
1 parent ebe9dca commit 5802747
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 14 deletions.
38 changes: 24 additions & 14 deletions ext/native/thin3d/VulkanRenderManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -189,35 +189,44 @@ void VulkanRenderManager::CreateBackbuffers() {

// Start the thread.
if (useThread) {
for (int i = 0; i < vulkan_->GetInflightFrames(); i++) {
// Reset all the frameData. Might be dirty from previous thread stop.
frameData_[i].readyForRun = false;
frameData_[i].readyForFence = true;
}

run_ = true;
// Won't necessarily be 0.
threadInitFrame_ = vulkan_->GetCurFrame();
thread_ = std::thread(&VulkanRenderManager::ThreadFunc, this);
}
}

void VulkanRenderManager::DestroyBackbuffers() {
if (useThread) {
void VulkanRenderManager::StopThread(bool shutdown) {
if (useThread && run_) {
run_ = false;
// Stop the thread.
for (int i = 0; i < vulkan_->GetInflightFrames(); i++) {
auto &frameData = frameData_[i];
{
std::unique_lock<std::mutex> lock(frameData_[i].push_mutex);
frameData_[i].push_condVar.notify_all();
std::unique_lock<std::mutex> lock(frameData.push_mutex);
frameData.push_condVar.notify_all();
}
{
std::unique_lock<std::mutex> lock(frameData_[i].pull_mutex);
frameData_[i].pull_condVar.notify_all();
std::unique_lock<std::mutex> lock(frameData.pull_mutex);
frameData.pull_condVar.notify_all();
}
}
thread_.join();

// Reset fences for next time around - must be done after join.
for (int i = 0; i < vulkan_->GetInflightFrames(); i++) {
auto &frameData = frameData_[i];
frameData.readyForRun = false;
if (!shutdown && !frameData.readyForFence) {
vkDestroyFence(vulkan_->GetDevice(), frameData.fence, nullptr);
frameData.fence = vulkan_->CreateFence(true);
}
}
}
}

void VulkanRenderManager::DestroyBackbuffers() {
StopThread(false);
vulkan_->WaitUntilQueueIdle();

VkDevice device = vulkan_->GetDevice();
Expand All @@ -237,9 +246,10 @@ void VulkanRenderManager::DestroyBackbuffers() {
}

VulkanRenderManager::~VulkanRenderManager() {
run_ = false;
VkDevice device = vulkan_->GetDevice();
StopThread(true);
vulkan_->WaitUntilQueueIdle();

VkDevice device = vulkan_->GetDevice();
vkDestroySemaphore(device, acquireSemaphore_, nullptr);
vkDestroySemaphore(device, renderingCompleteSemaphore_, nullptr);
for (int i = 0; i < vulkan_->GetInflightFrames(); i++) {
Expand Down
2 changes: 2 additions & 0 deletions ext/native/thin3d/VulkanRenderManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,8 @@ class VulkanRenderManager {
void FlushSync();
void EndSyncFrame(int frame);

void StopThread(bool shutdown);

// Permanent objects
VkSemaphore acquireSemaphore_;
VkSemaphore renderingCompleteSemaphore_;
Expand Down

0 comments on commit 5802747

Please sign in to comment.