src/third_party/angle/src/libANGLE/renderer/vulkan/CommandProcessor.cpp
// If there are any inflight commands worker will look for fence that corresponds to the request
// serial or the last available fence and wait on that fence. Will then do necessary cleanup work.
// This can cause the worker thread to block.
// TODO: https://issuetracker.google.com/issues/170312581 - A more optimal solution might be to do
// the wait in CommandProcessor rather than the worker thread. That would require protecting access
// to mInFlightCommands
If there are any inflight commands worker will look for fence that corresponds to the request
serial or the last available fence and wait on that fence. Will then do necessary cleanup work.
This can cause the worker thread to block.
If there are any inflight commands worker will look for fence that corresponds to the request serial or the last available fence and wait on that fence . Will then do necessary cleanup work . This can cause the worker thread to block .
angle::Result TaskProcessor::finishToSerial(vk::Context *context, Serial serial)
{
    ASSERT(isValidWorkerThread(context));
    ANGLE_TRACE_EVENT0("gpu.angle", "TaskProcessor::finishToSerial");
    RendererVk *rendererVk = context->getRenderer();
    uint64_t timeout       = rendererVk->getMaxFenceWaitTimeNs();
    std::unique_lock<std::mutex> inFlightLock(mInFlightCommandsMutex);
    if (mInFlightCommands.empty())
    {
        return angle::Result::Continue;
    }
    size_t batchIndex = mInFlightCommands.size() - 1;
    for (size_t i = 0; i < mInFlightCommands.size(); ++i)
    {
        if (mInFlightCommands[i].serial >= serial)
        {
            batchIndex = i;
            break;
        }
    }
    const vk::CommandBatch &batch = mInFlightCommands[batchIndex];
    inFlightLock.unlock();
    VkDevice device = context->getDevice();
    ANGLE_VK_TRY(context, batch.fence.get().wait(device, timeout));
    return lockAndCheckCompletedCommands(context);
}
angle :: Result TaskProcessor :: finishToSerial ( vk :: Context * context , Serial serial ) { ASSERT ( isValidWorkerThread ( context ) ) ; ANGLE_TRACE_EVENT0 ( " " , " " ) ; RendererVk * rendererVk = context -> getRenderer ( ) ; uint64_t timeout = rendererVk -> getMaxFenceWaitTimeNs ( ) ; std :: unique_lock < std :: mutex > inFlightLock ( mInFlightCommandsMutex ) ; if ( mInFlightCommands . empty ( ) ) { return angle :: Result :: Continue ; } size_t batchIndex = mInFlightCommands . size ( ) - 1 ; for ( size_t i = 0 ; i < mInFlightCommands . size ( ) ; ++ i ) { if ( mInFlightCommands [ i ] . serial >= serial ) { batchIndex = i ; break ; } } const vk :: CommandBatch & batch = mInFlightCommands [ batchIndex ] ; inFlightLock . unlock ( ) ; VkDevice device = context -> getDevice ( ) ; ANGLE_VK_TRY ( context , batch . fence . get ( ) . wait ( device , timeout ) ) ; return lockAndCheckCompletedCommands ( context ) ; }
If there are any inflight commands worker will look for fence that corresponds to the request
serial or the last available fence and wait on that fence.
If there are any inflight commands worker will look for fence that corresponds to the request serial or the last available fence and wait on that fence .
// No outstanding work, nothing to wait for. // Find the first batch with serial equal to or bigger than given serial (note that // the batch serials are unique, otherwise upper-bound would have been necessary). // Don't need to hold the lock while waiting for the fence // Wait for it finish // Clean up finished batches.