There is a TODO in MiniEngine/Core/CommandListManager.cpp:
void CommandQueue::WaitForFence(uint64_t FenceValue)
{
if (IsFenceComplete(FenceValue))
return;
// TODO: Think about how this might affect a multi-threaded situation. Suppose thread A
// wants to wait for fence 100, then thread B comes along and wants to wait for 99. If
// the fence can only have one event set on completion, then thread B has to wait for
// 100 before it knows 99 is ready. Maybe insert sequential events?
{
std::lock_guard<std::mutex> LockGuard(m_EventMutex);
m_pFence->SetEventOnCompletion(FenceValue, m_FenceEventHandle);
WaitForSingleObject(m_FenceEventHandle, INFINITE);
m_LastCompletedFenceValue = FenceValue;
}
}
I think it can be solved simply with an event pool:
std::queue<HANDLE> m_AvailableFenceEventHandles;
Modify the original function to:
void CommandQueue::WaitForFence(uint64_t FenceValue) {
if (IsFenceComplete(FenceValue))
return;
HANDLE fenceEventHandle = nullptr;
{
std::lock_guard<std::mutex> lock(m_EventMutex);
if (!m_AvailableFenceEventHandles.empty()) {
fenceEventHandle = m_AvailableFenceEventHandles.front();
m_AvailableFenceEventHandles.pop();
}
}
if (!fenceEventHandle) {
fenceEventHandle = CreateEvent(nullptr, FALSE, FALSE, nullptr);
ASSERT(fenceEventHandle != nullptr);
}
m_pFence->SetEventOnCompletion(FenceValue, fenceEventHandle);
WaitForSingleObject(fenceEventHandle, INFINITE);
{
std::lock_guard<std::mutex> lock(m_EventMutex);
m_LastCompletedFenceValue = std::max(m_LastCompletedFenceValue, FenceValue);
m_AvailableFenceEventHandles.emplace(fenceEventHandle);
}
}
There is a TODO in MiniEngine/Core/CommandListManager.cpp:
I think it can be solved simply with an event pool:
Modify the original function to: