Skip to content

A solution to multi-thread support in CommandQueue::WaitForFence #904

@wmylxmj

Description

@wmylxmj

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); 
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions