Commit 65ee5168 by Jamie Madill Committed by Commit Bot

Vulkan: Align submit and serial management code.

This progresses the goal of merging TaskProcessor and CommandQueue. Moving the serial management out of RendererVk allows these classes to have finer control over when thread synchronization locks happen. Note: device lost handling seems untested currently. Bug: b/172704839 Change-Id: I0cc61e1ffe41aad0b898d4146c8dbd08a2cebd3c Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2525140 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarCourtney Goeltzenleuchter <courtneygo@google.com>
parent 453a113a
......@@ -207,25 +207,27 @@ void CommandProcessorTask::initFlushAndQueueSubmit(
const Semaphore *semaphore,
egl::ContextPriority priority,
GarbageList &&currentGarbage,
ResourceUseList &&currentResources)
Serial submitQueueSerial)
{
mTask = CustomTask::FlushAndQueueSubmit;
mWaitSemaphores = std::move(waitSemaphores);
mWaitSemaphoreStageMasks = std::move(waitSemaphoreStageMasks);
mSemaphore = semaphore;
mGarbage = std::move(currentGarbage);
mResourceUseList = std::move(currentResources);
mPriority = priority;
mSerial = submitQueueSerial;
}
void CommandProcessorTask::initOneOffQueueSubmit(VkCommandBuffer oneOffCommandBufferVk,
egl::ContextPriority priority,
const Fence *fence)
const Fence *fence,
Serial submitQueueSerial)
{
mTask = CustomTask::OneOffQueueSubmit;
mOneOffCommandBufferVk = oneOffCommandBufferVk;
mOneOffFence = fence;
mPriority = priority;
mSerial = submitQueueSerial;
}
CommandProcessorTask &CommandProcessorTask::operator=(CommandProcessorTask &&rhs)
......@@ -246,7 +248,6 @@ CommandProcessorTask &CommandProcessorTask::operator=(CommandProcessorTask &&rhs
std::swap(mGarbage, rhs.mGarbage);
std::swap(mSerial, rhs.mSerial);
std::swap(mPriority, rhs.mPriority);
std::swap(mResourceUseList, rhs.mResourceUseList);
mOneOffCommandBufferVk = rhs.mOneOffCommandBufferVk;
copyPresentInfo(rhs.mPresentInfo);
......@@ -284,7 +285,7 @@ void CommandBatch::destroy(VkDevice device)
}
// TaskProcessor implementation.
TaskProcessor::TaskProcessor() = default;
TaskProcessor::TaskProcessor() : mCurrentQueueSerial(mQueueSerialFactory.generate()) {}
TaskProcessor::~TaskProcessor() = default;
......@@ -336,7 +337,7 @@ angle::Result TaskProcessor::checkCompletedCommands(Context *context)
}
ANGLE_VK_TRY(context, result);
rendererVk->onCompletedSerial(batch.serial);
mLastCompletedQueueSerial = batch.serial;
rendererVk->resetSharedFence(&batch.fence);
......@@ -352,13 +353,11 @@ angle::Result TaskProcessor::checkCompletedCommands(Context *context)
mInFlightCommands.erase(beginIter, beginIter + finishedCount);
}
Serial lastCompleted = rendererVk->getLastCompletedQueueSerial();
size_t freeIndex = 0;
for (; freeIndex < mGarbageQueue.size(); ++freeIndex)
{
GarbageAndSerial &garbageList = mGarbageQueue[freeIndex];
if (garbageList.getSerial() <= lastCompleted)
if (garbageList.getSerial() <= mLastCompletedQueueSerial)
{
for (GarbageObject &garbage : garbageList.get())
{
......@@ -508,7 +507,7 @@ angle::Result TaskProcessor::submitFrame(Context *context,
GarbageList *currentGarbage,
CommandPool *commandPool,
PrimaryCommandBuffer &&commandBuffer,
const Serial &queueSerial)
Serial submitQueueSerial)
{
ASSERT(isValidWorkerThread(context));
ANGLE_TRACE_EVENT0("gpu.angle", "TaskProcessor::submitFrame");
......@@ -518,13 +517,13 @@ angle::Result TaskProcessor::submitFrame(Context *context,
DeviceScoped<CommandBatch> scopedBatch(device);
CommandBatch &batch = scopedBatch.get();
batch.fence.copy(device, sharedFence);
batch.serial = queueSerial;
batch.serial = submitQueueSerial;
ANGLE_TRY(queueSubmit(context, queue, submitInfo, &batch.fence.get()));
ANGLE_TRY(queueSubmit(context, queue, submitInfo, &batch.fence.get(), batch.serial));
if (!currentGarbage->empty())
{
mGarbageQueue.emplace_back(std::move(*currentGarbage), queueSerial);
mGarbageQueue.emplace_back(std::move(*currentGarbage), submitQueueSerial);
}
// Store the primary CommandBuffer and command pool used for secondary CommandBuffers
......@@ -550,7 +549,8 @@ angle::Result TaskProcessor::submitFrame(Context *context,
angle::Result TaskProcessor::queueSubmit(Context *context,
VkQueue queue,
const VkSubmitInfo &submitInfo,
const Fence *fence)
const Fence *fence,
Serial submitQueueSerial)
{
ASSERT(isValidWorkerThread(context));
ANGLE_TRACE_EVENT0("gpu.angle", "TaskProcessor::queueSubmit");
......@@ -565,8 +565,10 @@ angle::Result TaskProcessor::queueSubmit(Context *context,
VkFence handle = fence ? fence->getHandle() : VK_NULL_HANDLE;
ANGLE_VK_TRY(context, vkQueueSubmit(queue, 1, &submitInfo, handle));
mLastSubmittedQueueSerial = submitQueueSerial;
// Now that we've submitted work, clean up RendererVk garbage
return context->getRenderer()->cleanupGarbage(false);
return context->getRenderer()->cleanupGarbage(mLastCompletedQueueSerial);
}
bool TaskProcessor::isValidWorkerThread(Context *context) const
......@@ -575,6 +577,13 @@ bool TaskProcessor::isValidWorkerThread(Context *context) const
std::this_thread::get_id() == mThreadId;
}
Serial TaskProcessor::reserveSubmitSerial()
{
Serial returnSerial = mCurrentQueueSerial;
mCurrentQueueSerial = mQueueSerialFactory.generate();
return returnSerial;
}
void CommandProcessor::handleError(VkResult errorCode,
const char *file,
const char *function,
......@@ -598,10 +607,7 @@ void CommandProcessor::handleError(VkResult errorCode,
}
CommandProcessor::CommandProcessor(RendererVk *renderer)
: Context(renderer),
mWorkerThreadIdle(false),
mCommandProcessorLastSubmittedSerial(mQueueSerialFactory.generate()),
mCommandProcessorCurrentQueueSerial(mQueueSerialFactory.generate())
: Context(renderer), mWorkerThreadIdle(false)
{
std::lock_guard<std::mutex> queueLock(mErrorMutex);
while (!mErrors.empty())
......@@ -631,19 +637,6 @@ void CommandProcessor::queueCommand(Context *context, CommandProcessorTask *task
// serials.
std::lock_guard<std::mutex> queueLock(mWorkerMutex);
if (task->getTaskCommand() == CustomTask::FlushAndQueueSubmit ||
task->getTaskCommand() == CustomTask::OneOffQueueSubmit)
{
std::lock_guard<std::mutex> lock(mCommandProcessorQueueSerialMutex);
// Flush submits work, so give it the current serial and generate a new one.
Serial queueSerial = mCommandProcessorCurrentQueueSerial;
task->setQueueSerial(queueSerial);
mCommandProcessorLastSubmittedSerial = mCommandProcessorCurrentQueueSerial;
mCommandProcessorCurrentQueueSerial = mQueueSerialFactory.generate();
task->getResourceUseList().releaseResourceUsesAndUpdateSerials(queueSerial);
}
if (context->getRenderer()->getFeatures().asynchronousCommandProcessing.enabled)
{
mTasks.emplace(std::move(*task));
......@@ -798,9 +791,9 @@ angle::Result CommandProcessor::processTask(Context *context, CommandProcessorTa
// TODO: https://issuetracker.google.com/issues/170328907 - vkQueueSubmit should be
// owned by TaskProcessor to ensure proper synchronization
ANGLE_TRY(mTaskProcessor.queueSubmit(context,
getRenderer()->getVkQueue(task->getPriority()),
submitInfo, task->getOneOffFence()));
ANGLE_TRY(mTaskProcessor.queueSubmit(
context, getRenderer()->getVkQueue(task->getPriority()), submitInfo,
task->getOneOffFence(), task->getQueueSerial()));
ANGLE_TRY(mTaskProcessor.checkCompletedCommands(context));
break;
}
......@@ -898,16 +891,28 @@ void CommandProcessor::shutdown(std::thread *commandProcessorThread)
}
}
Serial CommandProcessor::getLastSubmittedSerial()
Serial CommandProcessor::getLastCompletedQueueSerial()
{
std::lock_guard<std::mutex> lock(mCommandProcessorQueueSerialMutex);
return mCommandProcessorLastSubmittedSerial;
std::lock_guard<std::mutex> lock(mQueueSerialMutex);
return mTaskProcessor.getLastCompletedQueueSerial();
}
Serial CommandProcessor::getLastSubmittedQueueSerial()
{
std::lock_guard<std::mutex> lock(mQueueSerialMutex);
return mTaskProcessor.getLastSubmittedQueueSerial();
}
Serial CommandProcessor::getCurrentQueueSerial()
{
std::lock_guard<std::mutex> lock(mCommandProcessorQueueSerialMutex);
return mCommandProcessorCurrentQueueSerial;
std::lock_guard<std::mutex> lock(mQueueSerialMutex);
return mTaskProcessor.getCurrentQueueSerial();
}
Serial CommandProcessor::reserveSubmitSerial()
{
std::lock_guard<std::mutex> lock(mQueueSerialMutex);
return mTaskProcessor.reserveSubmitSerial();
}
// Wait until all commands up to and including serial have been processed
......@@ -947,13 +952,18 @@ void CommandProcessor::finishAllWork(Context *context)
}
// CommandQueue implementation.
CommandQueue::CommandQueue() = default;
CommandQueue::CommandQueue() : mCurrentQueueSerial(mQueueSerialFactory.generate()) {}
CommandQueue::~CommandQueue() = default;
void CommandQueue::destroy(VkDevice device)
void CommandQueue::destroy(RendererVk *renderer)
{
mPrimaryCommands.destroy(device);
mPrimaryCommandPool.destroy(device);
mLastCompletedQueueSerial = Serial::Infinite();
clearAllGarbage(renderer);
mPrimaryCommands.destroy(renderer->getDevice());
mPrimaryCommandPool.destroy(renderer->getDevice());
ASSERT(mInFlightCommands.empty() && mGarbageQueue.empty());
}
......@@ -1007,7 +1017,7 @@ angle::Result CommandQueue::retireFinishedCommands(Context *context, size_t fini
{
CommandBatch &batch = mInFlightCommands[commandIndex];
renderer->onCompletedSerial(batch.serial);
mLastCompletedQueueSerial = batch.serial;
renderer->resetSharedFence(&batch.fence);
ANGLE_TRACE_EVENT0("gpu.angle", "command buffer recycling");
batch.commandPool.destroy(device);
......@@ -1020,13 +1030,11 @@ angle::Result CommandQueue::retireFinishedCommands(Context *context, size_t fini
mInFlightCommands.erase(beginIter, beginIter + finishedCount);
}
Serial lastCompleted = renderer->getLastCompletedQueueSerial();
size_t freeIndex = 0;
for (; freeIndex < mGarbageQueue.size(); ++freeIndex)
{
GarbageAndSerial &garbageList = mGarbageQueue[freeIndex];
if (garbageList.getSerial() < lastCompleted)
if (garbageList.getSerial() < mLastCompletedQueueSerial)
{
for (GarbageObject &garbage : garbageList.get())
{
......@@ -1168,6 +1176,13 @@ angle::Result CommandQueue::finishToSerial(Context *context, Serial finishSerial
return angle::Result::Continue;
}
Serial CommandQueue::reserveSubmitSerial()
{
Serial returnSerial = mCurrentQueueSerial;
mCurrentQueueSerial = mQueueSerialFactory.generate();
return returnSerial;
}
angle::Result CommandQueue::submitFrame(
Context *context,
egl::ContextPriority priority,
......@@ -1175,9 +1190,9 @@ angle::Result CommandQueue::submitFrame(
const std::vector<VkPipelineStageFlags> &waitSemaphoreStageMasks,
const Semaphore *signalSemaphore,
Shared<Fence> &&sharedFence,
ResourceUseList &&resourceList,
GarbageList &&currentGarbage,
CommandPool *commandPool)
CommandPool *commandPool,
Serial submitQueueSerial)
{
// Start an empty primary buffer if we have an empty submit.
ANGLE_TRY(ensurePrimaryCommandBufferValid(context));
......@@ -1196,9 +1211,9 @@ angle::Result CommandQueue::submitFrame(
DeviceScoped<CommandBatch> scopedBatch(device);
CommandBatch &batch = scopedBatch.get();
batch.fence = std::move(sharedFence);
batch.serial = submitQueueSerial;
ANGLE_TRY(renderer->queueSubmit(context, priority, submitInfo, std::move(resourceList),
&batch.fence.get(), &batch.serial));
ANGLE_TRY(queueSubmit(context, priority, submitInfo, &batch.fence.get(), batch.serial));
if (!currentGarbage.empty())
{
......@@ -1306,5 +1321,27 @@ angle::Result CommandQueue::flushRenderPassCommands(Context *context,
return renderPassCommands->flushToPrimary(context->getRenderer()->getFeatures(),
&mPrimaryCommands, &renderPass);
}
angle::Result CommandQueue::queueSubmit(Context *context,
egl::ContextPriority contextPriority,
const VkSubmitInfo &submitInfo,
const Fence *fence,
Serial submitQueueSerial)
{
RendererVk *renderer = context->getRenderer();
if (kOutputVmaStatsString)
{
renderer->outputVmaStatString();
}
VkQueue queue = renderer->getVkQueue(contextPriority);
VkFence fenceHandle = fence ? fence->getHandle() : VK_NULL_HANDLE;
ANGLE_VK_TRY(context, vkQueueSubmit(queue, 1, &submitInfo, fenceHandle));
mLastSubmittedQueueSerial = submitQueueSerial;
// Now that we've submitted work, clean up RendererVk garbage
return renderer->cleanupGarbage(mLastCompletedQueueSerial);
}
} // namespace vk
} // namespace rx
......@@ -76,11 +76,12 @@ class CommandProcessorTask
const Semaphore *semaphore,
egl::ContextPriority priority,
GarbageList &&currentGarbage,
ResourceUseList &&currentResources);
Serial submitQueueSerial);
void initOneOffQueueSubmit(VkCommandBuffer oneOffCommandBufferVk,
egl::ContextPriority priority,
const Fence *fence);
const Fence *fence,
Serial submitQueueSerial);
CommandProcessorTask &operator=(CommandProcessorTask &&rhs);
......@@ -91,7 +92,6 @@ class CommandProcessorTask
void setQueueSerial(Serial serial) { mSerial = serial; }
Serial getQueueSerial() const { return mSerial; }
ResourceUseList &getResourceUseList() { return mResourceUseList; }
CustomTask getTaskCommand() { return mTask; }
std::vector<VkSemaphore> &getWaitSemaphores() { return mWaitSemaphores; }
std::vector<VkPipelineStageFlags> &getWaitSemaphoreStageMasks()
......@@ -123,7 +123,6 @@ class CommandProcessorTask
std::vector<VkPipelineStageFlags> mWaitSemaphoreStageMasks;
const Semaphore *mSemaphore;
GarbageList mGarbage;
ResourceUseList mResourceUseList;
// FinishToSerial & Flush command data
Serial mSerial;
......@@ -169,22 +168,30 @@ class CommandQueue final : angle::NonCopyable
~CommandQueue();
angle::Result init(Context *context);
void destroy(VkDevice device);
void destroy(RendererVk *renderer);
void handleDeviceLost(RendererVk *renderer);
void clearAllGarbage(RendererVk *renderer);
angle::Result finishToSerial(Context *context, Serial finishSerial, uint64_t timeout);
Serial reserveSubmitSerial();
angle::Result submitFrame(Context *context,
egl::ContextPriority priority,
const std::vector<VkSemaphore> &waitSemaphores,
const std::vector<VkPipelineStageFlags> &waitSemaphoreStageMasks,
const Semaphore *signalSemaphore,
Shared<Fence> &&sharedFence,
ResourceUseList &&resourceList,
GarbageList &&currentGarbage,
CommandPool *commandPool);
CommandPool *commandPool,
Serial submitQueueSerial);
angle::Result queueSubmit(Context *context,
egl::ContextPriority contextPriority,
const VkSubmitInfo &submitInfo,
const Fence *fence,
Serial submitQueueSerial);
angle::Result waitForSerialWithUserTimeout(vk::Context *context,
Serial serial,
......@@ -202,6 +209,10 @@ class CommandQueue final : angle::NonCopyable
const RenderPass &renderPass,
CommandBufferHelper *renderPassCommands);
ANGLE_INLINE Serial getLastSubmittedQueueSerial() const { return mLastSubmittedQueueSerial; }
ANGLE_INLINE Serial getLastCompletedQueueSerial() const { return mLastCompletedQueueSerial; }
ANGLE_INLINE Serial getCurrentQueueSerial() const { return mCurrentQueueSerial; }
private:
angle::Result releaseToCommandBatch(Context *context,
PrimaryCommandBuffer &&commandBuffer,
......@@ -222,6 +233,12 @@ class CommandQueue final : angle::NonCopyable
// Keeps a free list of reusable primary command buffers.
PrimaryCommandBuffer mPrimaryCommands;
PersistentCommandPool mPrimaryCommandPool;
// Queue serial management.
AtomicSerialFactory mQueueSerialFactory;
Serial mLastCompletedQueueSerial;
Serial mLastSubmittedQueueSerial;
Serial mCurrentQueueSerial;
};
class TaskProcessor : angle::NonCopyable
......@@ -249,11 +266,12 @@ class TaskProcessor : angle::NonCopyable
GarbageList *currentGarbage,
CommandPool *commandPool,
PrimaryCommandBuffer &&commandBuffer,
const Serial &queueSerial);
Serial submitQueueSerial);
angle::Result queueSubmit(Context *context,
VkQueue queue,
const VkSubmitInfo &submitInfo,
const Fence *fence);
const Fence *fence,
Serial submitQueueSerial);
void handleDeviceLost(Context *context);
......@@ -261,6 +279,12 @@ class TaskProcessor : angle::NonCopyable
VkResult getLastAndClearPresentResult(VkSwapchainKHR swapchain);
Serial reserveSubmitSerial();
ANGLE_INLINE Serial getLastSubmittedQueueSerial() const { return mLastSubmittedQueueSerial; }
ANGLE_INLINE Serial getLastCompletedQueueSerial() const { return mLastCompletedQueueSerial; }
ANGLE_INLINE Serial getCurrentQueueSerial() const { return mCurrentQueueSerial; }
private:
bool isValidWorkerThread(Context *context) const;
......@@ -276,12 +300,19 @@ class TaskProcessor : angle::NonCopyable
PersistentCommandPool mPrimaryCommandPool;
std::thread::id mThreadId;
// Queue serial management.
AtomicSerialFactory mQueueSerialFactory;
Serial mLastCompletedQueueSerial;
Serial mLastSubmittedQueueSerial;
Serial mCurrentQueueSerial;
// Track present info
std::mutex mSwapchainStatusMutex;
std::condition_variable mSwapchainStatusCondition;
std::map<VkSwapchainKHR, VkResult> mSwapchainStatus;
};
// TODO(jmadill): Give this the same API as CommandQueue. b/172704839
class CommandProcessor : public Context
{
public:
......@@ -307,8 +338,11 @@ class CommandProcessor : public Context
// Used by main thread to wait for worker thread to complete all outstanding work.
void waitForWorkComplete(Context *context);
Serial getLastCompletedQueueSerial();
Serial getLastSubmittedQueueSerial();
Serial getCurrentQueueSerial();
Serial getLastSubmittedSerial();
Serial reserveSubmitSerial();
// Wait until desired serial has been processed.
void finishToSerial(Context *context, Serial serial);
......@@ -353,10 +387,7 @@ class CommandProcessor : public Context
PrimaryCommandBuffer mPrimaryCommandBuffer;
TaskProcessor mTaskProcessor;
AtomicSerialFactory mQueueSerialFactory;
std::mutex mCommandProcessorQueueSerialMutex;
Serial mCommandProcessorLastSubmittedSerial;
Serial mCommandProcessorCurrentQueueSerial;
std::mutex mQueueSerialMutex;
mutable std::mutex mErrorMutex;
std::queue<Error> mErrors;
......
......@@ -517,7 +517,7 @@ void ContextVk::onDestroy(const gl::Context *context)
mCommandPool.destroy(device);
// This will clean up any outstanding buffer allocations
(void)mRenderer->cleanupGarbage(false);
(void)mRenderer->clearAllGarbage(this);
}
angle::Result ContextVk::getIncompleteTexture(const gl::Context *context,
......
......@@ -47,7 +47,7 @@ void DisplayVk::terminate()
mRenderer->reloadVolkIfNeeded();
ASSERT(mRenderer);
mRenderer->onDestroy();
mRenderer->onDestroy(this);
}
egl::Error DisplayVk::makeCurrent(egl::Display * /*display*/,
......
......@@ -64,8 +64,6 @@ constexpr uint32_t kPipelineCacheVkUpdatePeriod = 60;
// version of Vulkan.
constexpr uint32_t kPreferredVulkanAPIVersion = VK_API_VERSION_1_1;
constexpr bool kOutputVmaStatsString = false;
angle::vk::ICD ChooseICDFromAttribs(const egl::AttributeMap &attribs)
{
#if !defined(ANGLE_PLATFORM_ANDROID)
......@@ -465,8 +463,6 @@ RendererVk::RendererVk()
mMinImportedHostPointerAlignment(1),
mDefaultUniformBufferSize(kPreferredDefaultUniformBufferSize),
mDevice(VK_NULL_HANDLE),
mLastCompletedQueueSerial(mQueueSerialFactory.generate()),
mCurrentQueueSerial(mQueueSerialFactory.generate()),
mDeviceLost(false),
mPipelineCacheVkUpdateTimeout(kPipelineCacheVkUpdatePeriod),
mPipelineCacheDirty(false),
......@@ -504,15 +500,8 @@ void RendererVk::releaseSharedResources(vk::ResourceUseList *resourceList)
resourceList->releaseResourceUses();
}
void RendererVk::onDestroy()
void RendererVk::onDestroy(vk::Context *context)
{
if (getFeatures().commandProcessor.enabled)
{
// Shutdown worker thread
mCommandProcessor.shutdown(&mCommandProcessorThread);
}
mCommandQueue.destroy(mDevice);
// Force all commands to finish by flushing all queues.
for (VkQueue queue : mQueues)
{
......@@ -522,13 +511,19 @@ void RendererVk::onDestroy()
}
}
// Then assign an infinite "last completed" serial to force garbage to delete.
if (getFeatures().commandProcessor.enabled)
{
std::lock_guard<std::mutex> lock(mQueueSerialMutex);
mLastCompletedQueueSerial = Serial::Infinite();
// Shutdown worker thread
mCommandProcessor.shutdown(&mCommandProcessorThread);
}
else
{
std::lock_guard<std::mutex> lock(mCommandQueueMutex);
mCommandQueue.destroy(this);
}
(void)cleanupGarbage(true);
// Assigns an infinite "last completed" serial to force garbage to delete.
(void)cleanupGarbage(Serial::Infinite());
ASSERT(!hasSharedGarbage());
for (PendingOneOffCommands &pending : mPendingOneOffCommands)
......@@ -588,10 +583,6 @@ void RendererVk::onDestroy()
void RendererVk::notifyDeviceLost()
{
{
std::lock_guard<std::mutex> lock(mQueueSerialMutex);
mLastCompletedQueueSerial = getLastSubmittedQueueSerial();
}
mDeviceLost = true;
mDisplay->notifyDeviceLost();
}
......@@ -2242,38 +2233,6 @@ void RendererVk::outputVmaStatString()
mAllocator.freeStatsString(statsString);
}
angle::Result RendererVk::queueSubmit(vk::Context *context,
egl::ContextPriority priority,
const VkSubmitInfo &submitInfo,
vk::ResourceUseList &&resourceUseList,
const vk::Fence *fence,
Serial *serialOut)
{
if (kOutputVmaStatsString)
{
outputVmaStatString();
}
ASSERT(!getFeatures().commandProcessor.enabled);
{
std::lock_guard<decltype(mQueueMutex)> lock(mQueueMutex);
std::lock_guard<std::mutex> serialLock(mQueueSerialMutex);
VkFence handle = fence ? fence->getHandle() : VK_NULL_HANDLE;
ANGLE_VK_TRY(context, vkQueueSubmit(mQueues[priority], 1, &submitInfo, handle));
resourceUseList.releaseResourceUsesAndUpdateSerials(mCurrentQueueSerial);
*serialOut = mCurrentQueueSerial;
mLastSubmittedQueueSerial = mCurrentQueueSerial;
mCurrentQueueSerial = mQueueSerialFactory.generate();
}
ANGLE_TRY(cleanupGarbage(false));
return angle::Result::Continue;
}
angle::Result RendererVk::queueSubmitOneOff(vk::Context *context,
vk::PrimaryCommandBuffer &&primary,
egl::ContextPriority priority,
......@@ -2282,10 +2241,16 @@ angle::Result RendererVk::queueSubmitOneOff(vk::Context *context,
{
ANGLE_TRACE_EVENT0("gpu.angle", "RendererVk::queueSubmitOneOff");
Serial submitQueueSerial;
if (getFeatures().commandProcessor.enabled)
{
std::lock_guard<std::mutex> commandQueueLock(mCommandQueueMutex);
submitQueueSerial = mCommandProcessor.reserveSubmitSerial();
vk::CommandProcessorTask oneOffQueueSubmit;
oneOffQueueSubmit.initOneOffQueueSubmit(primary.getHandle(), priority, fence);
oneOffQueueSubmit.initOneOffQueueSubmit(primary.getHandle(), priority, fence,
submitQueueSerial);
queueCommand(context, &oneOffQueueSubmit);
// TODO: https://issuetracker.google.com/170312581 - should go away with improved fence
// management
......@@ -2293,20 +2258,32 @@ angle::Result RendererVk::queueSubmitOneOff(vk::Context *context,
{
waitForCommandProcessorIdle(context);
}
*serialOut = getLastSubmittedQueueSerial();
}
else
{
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = primary.ptr();
std::lock_guard<std::mutex> commandQueueLock(mCommandQueueMutex);
std::lock_guard<std::mutex> queueLock(mQueueMutex);
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
if (primary.valid())
{
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = primary.ptr();
}
submitQueueSerial = mCommandQueue.reserveSubmitSerial();
ANGLE_TRY(
queueSubmit(context, priority, submitInfo, vk::ResourceUseList(), fence, serialOut));
mCommandQueue.queueSubmit(context, priority, submitInfo, fence, submitQueueSerial));
}
mPendingOneOffCommands.push_back({*serialOut, std::move(primary)});
*serialOut = submitQueueSerial;
if (primary.valid())
{
mPendingOneOffCommands.push_back({*serialOut, std::move(primary)});
}
return angle::Result::Continue;
}
......@@ -2414,9 +2391,8 @@ bool RendererVk::hasFormatFeatureBits(VkFormat format, const VkFormatFeatureFlag
return IsMaskFlagSet(getFormatFeatureBits<features>(format, featureBits), featureBits);
}
angle::Result RendererVk::cleanupGarbage(bool block)
angle::Result RendererVk::cleanupGarbage(Serial lastCompletedQueueSerial)
{
Serial lastCompletedQueueSerial = getLastCompletedQueueSerial();
std::lock_guard<std::mutex> lock(mGarbageMutex);
for (auto garbageIter = mSharedGarbage.begin(); garbageIter != mSharedGarbage.end();)
......@@ -2457,15 +2433,6 @@ uint64_t RendererVk::getMaxFenceWaitTimeNs() const
return kMaxFenceWaitTimeNs;
}
void RendererVk::onCompletedSerial(Serial serial)
{
std::lock_guard<std::mutex> lock(mQueueSerialMutex);
if (serial > mLastCompletedQueueSerial)
{
mLastCompletedQueueSerial = serial;
}
}
void RendererVk::setGlobalDebugAnnotator()
{
// If the vkCmd*DebugUtilsLabelEXT functions exist, and if the kEnableDebugMarkersVarName
......@@ -2581,29 +2548,39 @@ angle::Result RendererVk::submitFrame(vk::Context *context,
vk::GarbageList &&currentGarbage,
vk::CommandPool *commandPool)
{
Serial submitQueueSerial;
if (mFeatures.commandProcessor.enabled)
{
std::lock_guard<std::mutex> commandQueueLock(mCommandQueueMutex);
submitQueueSerial = mCommandProcessor.reserveSubmitSerial();
vk::CommandProcessorTask flushAndQueueSubmit;
flushAndQueueSubmit.initFlushAndQueueSubmit(
std::move(waitSemaphores), std::move(waitSemaphoreStageMasks), signalSemaphore,
contextPriority, std::move(currentGarbage), std::move(resourceUseList));
contextPriority, std::move(currentGarbage), submitQueueSerial);
commandProcessorSyncErrorsAndQueueCommand(context, &flushAndQueueSubmit);
}
else
{
std::lock_guard<std::mutex> lock(mCommandQueueMutex);
std::lock_guard<std::mutex> commandQueueLock(mCommandQueueMutex);
std::lock_guard<std::mutex> queueLock(mQueueMutex);
submitQueueSerial = mCommandQueue.reserveSubmitSerial();
vk::Shared<vk::Fence> submitFence;
ANGLE_TRY(newSharedFence(context, &submitFence));
ANGLE_TRY(mCommandQueue.submitFrame(context, contextPriority, waitSemaphores,
waitSemaphoreStageMasks, signalSemaphore,
std::move(submitFence), std::move(resourceUseList),
std::move(currentGarbage), commandPool));
ANGLE_TRY(mCommandQueue.submitFrame(
context, contextPriority, waitSemaphores, waitSemaphoreStageMasks, signalSemaphore,
std::move(submitFence), std::move(currentGarbage), commandPool, submitQueueSerial));
waitSemaphores.clear();
waitSemaphoreStageMasks.clear();
}
resourceUseList.releaseResourceUsesAndUpdateSerials(submitQueueSerial);
return angle::Result::Continue;
}
......@@ -2672,8 +2649,7 @@ angle::Result RendererVk::waitForSerialWithUserTimeout(vk::Context *context,
angle::Result RendererVk::finish(vk::Context *context)
{
ANGLE_TRY(finishToSerial(context, mLastSubmittedQueueSerial));
return angle::Result::Continue;
return finishToSerial(context, getLastSubmittedQueueSerial());
}
angle::Result RendererVk::checkCompletedCommands(vk::Context *context)
......
......@@ -83,7 +83,7 @@ class RendererVk : angle::NonCopyable
const char *wsiLayer);
// Reload volk vk* function ptrs if needed for an already initialized RendererVk
void reloadVolkIfNeeded() const;
void onDestroy();
void onDestroy(vk::Context *context);
void notifyDeviceLost();
bool isDeviceLost() const;
......@@ -172,12 +172,6 @@ class RendererVk : angle::NonCopyable
}
// Queue submit that originates from the main thread
angle::Result queueSubmit(vk::Context *context,
egl::ContextPriority priority,
const VkSubmitInfo &submitInfo,
vk::ResourceUseList &&resourceList,
const vk::Fence *fence,
Serial *serialOut);
VkResult queuePresent(egl::ContextPriority priority, const VkPresentInfoKHR &presentInfo);
// This command buffer should be submitted immediately via queueSubmitOneOff.
......@@ -246,26 +240,39 @@ class RendererVk : angle::NonCopyable
{
return mCommandProcessor.getCurrentQueueSerial();
}
std::lock_guard<std::mutex> lock(mQueueSerialMutex);
return mCurrentQueueSerial;
else
{
std::lock_guard<std::mutex> lock(mCommandQueueMutex);
return mCommandQueue.getCurrentQueueSerial();
}
}
ANGLE_INLINE Serial getLastSubmittedQueueSerial()
{
if (getFeatures().commandProcessor.enabled)
{
return mCommandProcessor.getLastSubmittedSerial();
return mCommandProcessor.getLastSubmittedQueueSerial();
}
else
{
std::lock_guard<std::mutex> lock(mCommandQueueMutex);
return mCommandQueue.getLastSubmittedQueueSerial();
}
std::lock_guard<std::mutex> lock(mQueueSerialMutex);
return mLastSubmittedQueueSerial;
}
ANGLE_INLINE Serial getLastCompletedQueueSerial()
{
std::lock_guard<std::mutex> lock(mQueueSerialMutex);
return mLastCompletedQueueSerial;
if (mFeatures.commandProcessor.enabled)
{
return mCommandProcessor.getLastCompletedQueueSerial();
}
else
{
std::lock_guard<std::mutex> lock(mCommandQueueMutex);
return mCommandQueue.getLastCompletedQueueSerial();
}
}
void onCompletedSerial(Serial serial);
VkResult getLastPresentResult(VkSwapchainKHR swapchain)
{
return mCommandProcessor.getLastPresentResult(swapchain);
......@@ -301,7 +308,7 @@ class RendererVk : angle::NonCopyable
void outputVmaStatString();
angle::Result cleanupGarbage(bool block);
angle::Result cleanupGarbage(Serial lastCompletedQueueSerial);
angle::Result submitFrame(vk::Context *context,
egl::ContextPriority contextPriority,
......@@ -396,14 +403,8 @@ class RendererVk : angle::NonCopyable
VkDeviceSize mMinImportedHostPointerAlignment;
uint32_t mDefaultUniformBufferSize;
VkDevice mDevice;
AtomicSerialFactory mQueueSerialFactory;
AtomicSerialFactory mShaderSerialFactory;
std::mutex mQueueSerialMutex;
Serial mLastCompletedQueueSerial;
Serial mLastSubmittedQueueSerial;
Serial mCurrentQueueSerial;
bool mDeviceLost;
std::mutex mFenceRecyclerMutex;
......
......@@ -202,28 +202,9 @@ angle::Result SyncHelperNativeFence::initializeWithFd(ContextVk *contextVk, int
retain(&contextVk->getResourceUseList());
if (renderer->getFeatures().commandProcessor.enabled)
{
CommandProcessorTask oneOffQueueSubmit;
oneOffQueueSubmit.initOneOffQueueSubmit(VK_NULL_HANDLE, contextVk->getPriority(),
&fence.get());
renderer->queueCommand(contextVk, &oneOffQueueSubmit);
// TODO: https://issuetracker.google.com/170312581 - wait for now
if (renderer->getFeatures().asynchronousCommandProcessing.enabled)
{
ANGLE_TRACE_EVENT0("gpu.angle", "SyncHelperNativeFence::initializeWithFd");
renderer->waitForCommandProcessorIdle(contextVk);
}
}
else
{
Serial serialOut;
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
ANGLE_TRY(renderer->queueSubmit(contextVk, contextVk->getPriority(), submitInfo,
vk::ResourceUseList(), &fence.get(), &serialOut));
}
Serial serialOut;
ANGLE_TRY(renderer->queueSubmitOneOff(contextVk, vk::PrimaryCommandBuffer(),
contextVk->getPriority(), &fence.get(), &serialOut));
VkFenceGetFdInfoKHR fenceGetFdInfo = {};
fenceGetFdInfo.sType = VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR;
......
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