Can't seem to get around this condition variable... Oh well.

This commit is contained in:
Henrik Rydgård 2022-09-23 20:44:47 +02:00
parent f6c78584f6
commit c671b3f413
3 changed files with 29 additions and 1 deletions

View file

@ -1,3 +1,5 @@
#include <mutex>
#include "VulkanFrameData.h"
#include "Common/Log.h"
@ -26,6 +28,7 @@ void FrameData::Init(VulkanContext *vulkan, int index) {
// Creating the frame fence with true so they can be instantly waited on the first frame
fence = vulkan->CreateFence(true);
readyForFence = true;
// This fence one is used for synchronizing readbacks. Does not need preinitialization.
readbackFence = vulkan->CreateFence(false);
@ -169,7 +172,18 @@ void FrameData::SubmitPending(VulkanContext *vulkan, FrameSubmitType type, Frame
submit_info.signalSemaphoreCount = 1;
submit_info.pSignalSemaphores = &sharedData.renderingCompleteSemaphore;
}
VkResult res = vkQueueSubmit(vulkan->GetGraphicsQueue(), 1, &submit_info, fenceToTrigger);
VkResult res;
if (fenceToTrigger == fence) {
// The fence is waited on by the main thread, they are not allowed to access it simultaneously.
std::lock_guard<std::mutex> lock(fenceMutex);
res = vkQueueSubmit(vulkan->GetGraphicsQueue(), 1, &submit_info, fenceToTrigger);
readyForFence = true;
fenceCondVar.notify_one();
} else {
res = vkQueueSubmit(vulkan->GetGraphicsQueue(), 1, &submit_info, fenceToTrigger);
}
if (res == VK_ERROR_DEVICE_LOST) {
_assert_msg_(false, "Lost the Vulkan device in vkQueueSubmit! If this happens again, switch Graphics Backend away from Vulkan");
} else {

View file

@ -44,6 +44,10 @@ enum class FrameSubmitType {
struct FrameData {
bool skipSwap = false;
std::mutex fenceMutex;
std::condition_variable fenceCondVar;
bool readyForFence = true;
VkFence fence;
VkFence readbackFence; // Strictly speaking we might only need one global of these.

View file

@ -504,6 +504,16 @@ void VulkanRenderManager::BeginFrame(bool enableProfiling, bool enableLogProfile
VLOG("PUSH: Fencing %d", curFrame);
// Makes sure the submission from the previous time around has happened. Otherwise
// we are not allowed to wait from another thread here..
{
std::unique_lock<std::mutex> lock(frameData.fenceMutex);
while (!frameData.readyForFence) {
frameData.fenceCondVar.wait(lock);
}
frameData.readyForFence = false;
}
// This must be the very first Vulkan call we do in a new frame.
// Makes sure the very last command buffer from the frame before the previous has been fully executed.
if (vkWaitForFences(device, 1, &frameData.fence, true, UINT64_MAX) == VK_ERROR_DEVICE_LOST) {