Commit 49c13282 by Jamie Madill Committed by Commit Bot

Vulkan: Merge async command queue features.

This merges the 'commandProcessor' and 'asyncCommandProcessing' features into one new 'asyncCommandQueue' features. Conceptually the command processor is asynchronous use of the CommandQueue. This renaming updates the code to reflect the usage. Bug: b/172704839 Change-Id: I1d7ca1187f802eed48823a01b57fb520527f2540 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2525144 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCourtney Goeltzenleuchter <courtneygo@google.com> Reviewed-by: 's avatarTim Van Patten <timvp@google.com>
parent f19a4a20
......@@ -334,18 +334,11 @@ struct FeaturesVk : FeatureSetBase
"fine grained pipeline stage dependency information",
&members, "http://anglebug.com/4633"};
// Tell Vulkan back-end to use CommandProcessor class to dispatch work to the GPU. The work will
// happen asynchronously in a different thread if asynchronousCommandProcessing is true.
// Otherwise use Renderer::CommandQueue to dispatch work.
// TODO(jmadill): Merge these two features. b/172704839
Feature commandProcessor = {"commandProcessor", FeatureCategory::VulkanFeatures,
"Use CommandProcessor class to dispatch work to GPU.", &members,
"http://anglebug.com/4324"};
Feature asynchronousCommandProcessing = {"asynchronousCommandProcessing",
FeatureCategory::VulkanFeatures,
"Enable/Disable parallel processing of worker thread",
&members, "http://anglebug.com/4324"};
// Tell the Vulkan back-end to use the async command queue to dispatch work to the GPU. Command
// buffer work will happened in a worker thread. Otherwise use Renderer::CommandQueue directly.
Feature asyncCommandQueue = {"asyncCommandQueue", FeatureCategory::VulkanFeatures,
"Use CommandQueue worker thread to dispatch work to GPU.",
&members, "http://anglebug.com/4324"};
// Whether the VkDevice supports the VK_KHR_shader_float16_int8 extension and has the
// shaderFloat16 feature.
......
......@@ -299,22 +299,8 @@ void CommandProcessor::queueCommand(Context *context, CommandProcessorTask *task
// serials.
std::lock_guard<std::mutex> queueLock(mWorkerMutex);
if (context->getRenderer()->getFeatures().asynchronousCommandProcessing.enabled)
{
mTasks.emplace(std::move(*task));
mWorkAvailableCondition.notify_one();
}
else
{
angle::Result result = processTask(task);
if (ANGLE_UNLIKELY(IsError(result)))
{
// TODO: Ignore error, similar to ANGLE_CONTEXT_TRY.
// Vulkan errors will get passed back to the calling context. We are still in the
// context's thread so no mutex needed.
return;
}
}
mTasks.emplace(std::move(*task));
mWorkAvailableCondition.notify_one();
}
void CommandProcessor::processTasks()
......@@ -488,7 +474,6 @@ void CommandProcessor::checkCompletedCommands(Context *context)
void CommandProcessor::waitForWorkComplete(Context *context)
{
ASSERT(getRenderer()->getFeatures().asynchronousCommandProcessing.enabled);
ANGLE_TRACE_EVENT0("gpu.angle", "CommandProcessor::waitForWorkComplete");
std::unique_lock<std::mutex> lock(mWorkerMutex);
mWorkerIdleCondition.wait(lock, [this] { return (mTasks.empty() && mWorkerThreadIdle); });
......@@ -518,13 +503,10 @@ void CommandProcessor::shutdown(std::thread *commandProcessorThread)
CommandProcessorTask endTask;
endTask.initTask(CustomTask::Exit);
queueCommand(this, &endTask);
if (this->getRenderer()->getFeatures().asynchronousCommandProcessing.enabled)
waitForWorkComplete(nullptr);
if (commandProcessorThread->joinable())
{
waitForWorkComplete(nullptr);
if (commandProcessorThread->joinable())
{
commandProcessorThread->join();
}
commandProcessorThread->join();
}
}
......@@ -562,20 +544,14 @@ void CommandProcessor::finishToSerial(Context *context, Serial serial)
// Wait until the worker is idle. At that point we know that the finishToSerial command has
// completed executing, including any associated state cleanup.
if (context->getRenderer()->getFeatures().asynchronousCommandProcessing.enabled)
{
waitForWorkComplete(context);
}
waitForWorkComplete(context);
}
void CommandProcessor::handleDeviceLost()
{
ANGLE_TRACE_EVENT0("gpu.angle", "CommandProcessor::handleDeviceLost");
std::unique_lock<std::mutex> lock(mWorkerMutex);
if (getRenderer()->getFeatures().asynchronousCommandProcessing.enabled)
{
mWorkerIdleCondition.wait(lock, [this] { return (mTasks.empty() && mWorkerThreadIdle); });
}
mWorkerIdleCondition.wait(lock, [this] { return (mTasks.empty() && mWorkerThreadIdle); });
// Worker thread is idle and command queue is empty so good to continue
mCommandQueue.handleDeviceLost(mRenderer);
......
......@@ -3025,7 +3025,8 @@ angle::Result ContextVk::onMakeCurrent(const gl::Context *context)
angle::Result ContextVk::onUnMakeCurrent(const gl::Context *context)
{
ANGLE_TRY(flushImpl(nullptr));
if (mRenderer->getFeatures().commandProcessor.enabled)
// TODO(courtneygo): Clean this up. b/170328907 b/170329600
if (mRenderer->getFeatures().asyncCommandQueue.enabled)
{
ANGLE_TRACE_EVENT0("gpu.angle", "ContextVk::onUnMakeCurrent");
mRenderer->finishAllWork(this);
......
......@@ -187,10 +187,10 @@ angle::Result QueryVk::getResult(const gl::Context *context, bool wait)
if (mQueryHelper.hasPendingWork(contextVk))
{
ANGLE_TRY(contextVk->flushImpl(nullptr));
if (contextVk->getRenderer()->getFeatures().asynchronousCommandProcessing.enabled)
if (renderer->getFeatures().asyncCommandQueue.enabled)
{
// TODO: https://issuetracker.google.com/170312581 - For now just stalling here
contextVk->getRenderer()->waitForCommandProcessorIdle(contextVk);
renderer->waitForCommandProcessorIdle(contextVk);
}
ASSERT(!mQueryHelperTimeElapsedBegin.hasPendingWork(contextVk));
......
......@@ -513,7 +513,7 @@ void RendererVk::onDestroy(vk::Context *context)
}
}
if (getFeatures().commandProcessor.enabled)
if (getFeatures().asyncCommandQueue.enabled)
{
// Shutdown worker thread
mCommandProcessor.shutdown(&mCommandProcessorThread);
......@@ -915,10 +915,8 @@ angle::Result RendererVk::initialize(DisplayVk *displayVk,
setGlobalDebugAnnotator();
if (getFeatures().commandProcessor.enabled)
if (mFeatures.asyncCommandQueue.enabled)
{
// TODO(jmadill): Clean up. b/172704839
ASSERT(mFeatures.asynchronousCommandProcessing.enabled);
mCommandProcessorThread =
std::thread(&vk::CommandProcessor::processTasks, &mCommandProcessor);
waitForCommandProcessorIdle(displayVk);
......@@ -1944,10 +1942,7 @@ void RendererVk::initFeatures(DisplayVk *displayVk,
ANGLE_FEATURE_CONDITION(&mFeatures, preferAggregateBarrierCalls, isNvidia || isAMD || isIntel);
// Currently disabled by default: http://anglebug.com/4324
ANGLE_FEATURE_CONDITION(&mFeatures, commandProcessor, false);
// Currently disabled by default: http://anglebug.com/4324
ANGLE_FEATURE_CONDITION(&mFeatures, asynchronousCommandProcessing, false);
ANGLE_FEATURE_CONDITION(&mFeatures, asyncCommandQueue, false);
ANGLE_FEATURE_CONDITION(&mFeatures, supportsYUVSamplerConversion,
mSamplerYcbcrConversionFeatures.samplerYcbcrConversion != VK_FALSE);
......@@ -2242,10 +2237,9 @@ angle::Result RendererVk::queueSubmitOneOff(vk::Context *context,
Serial *serialOut)
{
ANGLE_TRACE_EVENT0("gpu.angle", "RendererVk::queueSubmitOneOff");
Serial submitQueueSerial;
if (getFeatures().commandProcessor.enabled)
if (mFeatures.asyncCommandQueue.enabled)
{
std::lock_guard<std::mutex> commandQueueLock(mCommandQueueMutex);
submitQueueSerial = mCommandProcessor.reserveSubmitSerial();
......@@ -2256,10 +2250,7 @@ angle::Result RendererVk::queueSubmitOneOff(vk::Context *context,
queueCommand(context, &oneOffQueueSubmit);
// TODO: https://issuetracker.google.com/170312581 - should go away with improved fence
// management
if (getFeatures().asynchronousCommandProcessing.enabled)
{
waitForCommandProcessorIdle(context);
}
waitForCommandProcessorIdle(context);
}
else
{
......@@ -2295,7 +2286,7 @@ VkResult RendererVk::queuePresent(egl::ContextPriority priority,
{
ANGLE_TRACE_EVENT0("gpu.angle", "RendererVk::queuePresent");
ASSERT(!getFeatures().commandProcessor.enabled);
ASSERT(!mFeatures.asyncCommandQueue.enabled);
std::lock_guard<decltype(mQueueMutex)> lock(mQueueMutex);
......@@ -2552,7 +2543,7 @@ angle::Result RendererVk::submitFrame(vk::Context *context,
{
Serial submitQueueSerial;
if (mFeatures.commandProcessor.enabled)
if (mFeatures.asyncCommandQueue.enabled)
{
std::lock_guard<std::mutex> commandQueueLock(mCommandQueueMutex);
submitQueueSerial = mCommandProcessor.reserveSubmitSerial();
......@@ -2588,7 +2579,7 @@ angle::Result RendererVk::submitFrame(vk::Context *context,
void RendererVk::clearAllGarbage(vk::Context *context)
{
if (mFeatures.commandProcessor.enabled)
if (mFeatures.asyncCommandQueue.enabled)
{
// Issue command to CommandProcessor to ensure all work is complete, which will return any
// garbage items as well.
......@@ -2603,7 +2594,7 @@ void RendererVk::clearAllGarbage(vk::Context *context)
void RendererVk::handleDeviceLost()
{
if (mFeatures.commandProcessor.enabled)
if (mFeatures.asyncCommandQueue.enabled)
{
mCommandProcessor.handleDeviceLost();
}
......@@ -2616,7 +2607,7 @@ void RendererVk::handleDeviceLost()
angle::Result RendererVk::finishToSerial(vk::Context *context, Serial serial)
{
if (mFeatures.commandProcessor.enabled)
if (mFeatures.asyncCommandQueue.enabled)
{
mCommandProcessor.finishToSerial(context, serial);
}
......@@ -2635,7 +2626,7 @@ angle::Result RendererVk::waitForSerialWithUserTimeout(vk::Context *context,
VkResult *result)
{
ANGLE_TRACE_EVENT0("gpu.angle", "RendererVk::waitForSerialWithUserTimeout");
if (mFeatures.commandProcessor.enabled)
if (mFeatures.asyncCommandQueue.enabled)
{
// TODO: https://issuetracker.google.com/170312581 - Wait with timeout.
mCommandProcessor.finishToSerial(context, serial);
......@@ -2656,7 +2647,7 @@ angle::Result RendererVk::finish(vk::Context *context)
angle::Result RendererVk::checkCompletedCommands(vk::Context *context)
{
if (mFeatures.commandProcessor.enabled)
if (mFeatures.asyncCommandQueue.enabled)
{
// TODO: https://issuetracker.google.com/169788986 - would be better if we could just wait
// for the work we need but that requires QueryHelper to use the actual serial for the
......@@ -2677,7 +2668,7 @@ angle::Result RendererVk::flushRenderPassCommands(vk::Context *context,
vk::CommandBufferHelper **renderPassCommands)
{
ANGLE_TRACE_EVENT0("gpu.angle", "RendererVk::flushRenderPassCommands");
if (mFeatures.commandProcessor.enabled)
if (mFeatures.asyncCommandQueue.enabled)
{
(*renderPassCommands)->markClosed();
vk::CommandProcessorTask flushToPrimary;
......@@ -2698,7 +2689,7 @@ angle::Result RendererVk::flushOutsideRPCommands(vk::Context *context,
vk::CommandBufferHelper **outsideRPCommands)
{
ANGLE_TRACE_EVENT0("gpu.angle", "RendererVk::flushOutsideRPCommands");
if (mFeatures.commandProcessor.enabled)
if (mFeatures.asyncCommandQueue.enabled)
{
(*outsideRPCommands)->markClosed();
vk::CommandProcessorTask flushToPrimary;
......
......@@ -236,7 +236,7 @@ class RendererVk : angle::NonCopyable
ANGLE_INLINE Serial getCurrentQueueSerial()
{
if (getFeatures().commandProcessor.enabled)
if (mFeatures.asyncCommandQueue.enabled)
{
return mCommandProcessor.getCurrentQueueSerial();
}
......@@ -249,7 +249,7 @@ class RendererVk : angle::NonCopyable
ANGLE_INLINE Serial getLastSubmittedQueueSerial()
{
if (getFeatures().commandProcessor.enabled)
if (mFeatures.asyncCommandQueue.enabled)
{
return mCommandProcessor.getLastSubmittedQueueSerial();
}
......@@ -262,7 +262,7 @@ class RendererVk : angle::NonCopyable
ANGLE_INLINE Serial getLastCompletedQueueSerial()
{
if (mFeatures.commandProcessor.enabled)
if (mFeatures.asyncCommandQueue.enabled)
{
return mCommandProcessor.getLastCompletedQueueSerial();
}
......@@ -293,7 +293,7 @@ class RendererVk : angle::NonCopyable
vk::Error getAndClearPendingError() { return mCommandProcessor.getAndClearPendingError(); }
void waitForCommandProcessorIdle(vk::Context *context)
{
ASSERT(getFeatures().asynchronousCommandProcessing.enabled);
ASSERT(getFeatures().asyncCommandQueue.enabled);
mCommandProcessor.waitForWorkComplete(context);
}
......
......@@ -1404,7 +1404,7 @@ angle::Result WindowSurfaceVk::present(ContextVk *contextVk,
mCurrentSwapHistoryIndex == mSwapHistory.size() ? 0 : mCurrentSwapHistoryIndex;
VkResult result;
if (renderer->getFeatures().commandProcessor.enabled)
if (renderer->getFeatures().asyncCommandQueue.enabled)
{
vk::CommandProcessorTask present;
present.initPresent(contextVk->getPriority(), presentInfo);
......@@ -1481,7 +1481,7 @@ angle::Result WindowSurfaceVk::doDeferredAcquireNextImage(const gl::Context *con
ContextVk *contextVk = vk::GetImpl(context);
DisplayVk *displayVk = vk::GetImpl(context->getDisplay());
if (contextVk->getFeatures().commandProcessor.enabled)
if (contextVk->getFeatures().asyncCommandQueue.enabled)
{
VkResult result = contextVk->getRenderer()->getLastPresentResult(mSwapchain);
......
......@@ -34,7 +34,7 @@ void SyncHelper::releaseToRenderer(RendererVk *renderer)
renderer->collectGarbageAndReinit(&mUse, &mEvent);
// TODO: https://issuetracker.google.com/170312581 - Currently just stalling on worker thread
// here to try and avoid race condition. If this works, need some alternate solution
if (renderer->getFeatures().asynchronousCommandProcessing.enabled)
if (renderer->getFeatures().asyncCommandQueue.enabled)
{
ANGLE_TRACE_EVENT0("gpu.angle", "SyncHelper::releaseToRenderer");
renderer->waitForCommandProcessorIdle(nullptr);
......@@ -267,7 +267,7 @@ angle::Result SyncHelperNativeFence::clientWait(Context *context,
// TODO: https://issuetracker.google.com/170312581 - If we are using worker need to wait for the
// commands to be issued before waiting on the fence.
if (contextVk->getRenderer()->getFeatures().asynchronousCommandProcessing.enabled)
if (contextVk->getRenderer()->getFeatures().asyncCommandQueue.enabled)
{
ANGLE_TRACE_EVENT0("gpu.angle", "SyncHelperNativeFence::clientWait");
contextVk->getRenderer()->waitForCommandProcessorIdle(contextVk);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment