Commit 6a1fb047 by Jamie Madill Committed by Commit Bot

Vulkan: Align CommandQueue and TaskProcessor.

The intent is to merge these two classes and remove redundant code. Bug: b/172704839 Change-Id: I6eb66d7b4ddea3633b08df99464975cd59773b4e Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2524550 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 a428487a
......@@ -21,41 +21,6 @@ constexpr size_t kInFlightCommandsLimit = 100u;
constexpr bool kOutputVmaStatsString = false;
void InitializeSubmitInfo(VkSubmitInfo *submitInfo,
const PrimaryCommandBuffer &commandBuffer,
const std::vector<VkSemaphore> &waitSemaphores,
std::vector<VkPipelineStageFlags> *waitSemaphoreStageMasks,
const Semaphore *signalSemaphore)
{
// Verify that the submitInfo has been zero'd out.
ASSERT(submitInfo->signalSemaphoreCount == 0);
submitInfo->sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo->commandBufferCount = commandBuffer.valid() ? 1 : 0;
submitInfo->pCommandBuffers = commandBuffer.ptr();
if (waitSemaphoreStageMasks->size() < waitSemaphores.size())
{
waitSemaphoreStageMasks->resize(waitSemaphores.size(), VK_PIPELINE_STAGE_ALL_COMMANDS_BIT);
}
submitInfo->waitSemaphoreCount = static_cast<uint32_t>(waitSemaphores.size());
submitInfo->pWaitSemaphores = waitSemaphores.data();
submitInfo->pWaitDstStageMask = waitSemaphoreStageMasks->data();
if (signalSemaphore)
{
submitInfo->signalSemaphoreCount = 1;
submitInfo->pSignalSemaphores = signalSemaphore->ptr();
}
else
{
submitInfo->signalSemaphoreCount = 0;
submitInfo->pSignalSemaphores = nullptr;
}
}
// TODO(jmadill): De-duplicate. b/172704839
void InitializeSubmitInfo(VkSubmitInfo *submitInfo,
const vk::PrimaryCommandBuffer &commandBuffer,
const std::vector<VkSemaphore> &waitSemaphores,
const std::vector<VkPipelineStageFlags> &waitSemaphoreStageMasks,
......@@ -291,6 +256,7 @@ TaskProcessor::~TaskProcessor() = default;
void TaskProcessor::destroy(VkDevice device)
{
mPrimaryCommandBuffer.destroy(device);
mPrimaryCommandPool.destroy(device);
ASSERT(mInFlightCommands.empty() && mGarbageQueue.empty());
}
......@@ -305,21 +271,6 @@ angle::Result TaskProcessor::init(Context *context, std::thread::id threadId)
return angle::Result::Continue;
}
VkResult TaskProcessor::getLastAndClearPresentResult(VkSwapchainKHR swapchain)
{
std::unique_lock<std::mutex> lock(mSwapchainStatusMutex);
if (mSwapchainStatus.find(swapchain) == mSwapchainStatus.end())
{
// Wake when required swapchain status becomes available
mSwapchainStatusCondition.wait(lock, [this, swapchain] {
return mSwapchainStatus.find(swapchain) != mSwapchainStatus.end();
});
}
VkResult result = mSwapchainStatus[swapchain];
mSwapchainStatus.erase(swapchain);
return result;
}
angle::Result TaskProcessor::checkCompletedCommands(Context *context)
{
ANGLE_TRACE_EVENT0("gpu.angle", "TaskProcessor::checkCompletedCommands");
......@@ -343,7 +294,7 @@ angle::Result TaskProcessor::checkCompletedCommands(Context *context)
ANGLE_TRACE_EVENT0("gpu.angle", "command buffer recycling");
batch.commandPool.destroy(device);
ANGLE_TRY(releasePrimaryCommandBuffer(context, std::move(batch.primaryCommands)));
ANGLE_TRY(mPrimaryCommandPool.collect(context, std::move(batch.primaryCommands)));
++finishedCount;
}
......@@ -403,21 +354,25 @@ angle::Result TaskProcessor::releaseToCommandBatch(Context *context,
return angle::Result::Continue;
}
angle::Result TaskProcessor::allocatePrimaryCommandBuffer(Context *context,
PrimaryCommandBuffer *commandBufferOut)
angle::Result TaskProcessor::ensurePrimaryCommandBufferValid(Context *context)
{
ASSERT(isValidWorkerThread(context));
ANGLE_TRACE_EVENT0("gpu.angle", "TaskProcessor::allocatePrimaryCommandBuffer");
return mPrimaryCommandPool.allocate(context, commandBufferOut);
}
if (mPrimaryCommandBuffer.valid())
{
return angle::Result::Continue;
}
angle::Result TaskProcessor::releasePrimaryCommandBuffer(Context *context,
PrimaryCommandBuffer &&commandBuffer)
{
ASSERT(isValidWorkerThread(context));
ANGLE_TRACE_EVENT0("gpu.angle", "TaskProcessor::releasePrimaryCommandBuffer");
ASSERT(mPrimaryCommandPool.valid());
return mPrimaryCommandPool.collect(context, std::move(commandBuffer));
ANGLE_TRACE_EVENT0("gpu.angle", "TaskProcessor::ensurePrimaryCommandBufferValid");
ANGLE_TRY(mPrimaryCommandPool.allocate(context, &mPrimaryCommandBuffer));
VkCommandBufferBeginInfo beginInfo = {};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
beginInfo.pInheritanceInfo = nullptr;
ANGLE_VK_TRY(context, mPrimaryCommandBuffer.begin(beginInfo));
return angle::Result::Continue;
}
void TaskProcessor::handleDeviceLost(Context *context)
......@@ -484,42 +439,37 @@ angle::Result TaskProcessor::finishToSerial(Context *context, Serial serial)
return checkCompletedCommands(context);
}
VkResult TaskProcessor::present(VkQueue queue, const VkPresentInfoKHR &presentInfo)
angle::Result TaskProcessor::submitFrame(
Context *context,
egl::ContextPriority priority,
const std::vector<VkSemaphore> &waitSemaphores,
const std::vector<VkPipelineStageFlags> &waitSemaphoreStageMasks,
const Semaphore *signalSemaphore,
Shared<Fence> &&sharedFence,
GarbageList *currentGarbage,
CommandPool *commandPool,
Serial submitQueueSerial)
{
std::lock_guard<std::mutex> lock(mSwapchainStatusMutex);
ANGLE_TRACE_EVENT0("gpu.angle", "vkQueuePresentKHR");
VkResult result = vkQueuePresentKHR(queue, &presentInfo);
ASSERT(isValidWorkerThread(context));
ANGLE_TRACE_EVENT0("gpu.angle", "TaskProcessor::submitFrame");
// Verify that we are presenting one and only one swapchain
ASSERT(presentInfo.swapchainCount == 1);
ASSERT(presentInfo.pResults == nullptr);
mSwapchainStatus[presentInfo.pSwapchains[0]] = result;
// Start an empty primary buffer if we have an empty submit.
ANGLE_TRY(ensurePrimaryCommandBufferValid(context));
mSwapchainStatusCondition.notify_all();
ANGLE_VK_TRY(context, mPrimaryCommandBuffer.end());
return result;
}
angle::Result TaskProcessor::submitFrame(Context *context,
VkQueue queue,
const VkSubmitInfo &submitInfo,
const Shared<Fence> &sharedFence,
GarbageList *currentGarbage,
CommandPool *commandPool,
PrimaryCommandBuffer &&commandBuffer,
Serial submitQueueSerial)
{
ASSERT(isValidWorkerThread(context));
ANGLE_TRACE_EVENT0("gpu.angle", "TaskProcessor::submitFrame");
VkSubmitInfo submitInfo = {};
InitializeSubmitInfo(&submitInfo, mPrimaryCommandBuffer, waitSemaphores,
waitSemaphoreStageMasks, signalSemaphore);
VkDevice device = context->getDevice();
DeviceScoped<CommandBatch> scopedBatch(device);
CommandBatch &batch = scopedBatch.get();
batch.fence.copy(device, sharedFence);
batch.serial = submitQueueSerial;
batch.fence = std::move(sharedFence);
batch.serial = submitQueueSerial;
ANGLE_TRY(queueSubmit(context, queue, submitInfo, &batch.fence.get(), batch.serial));
ANGLE_TRY(queueSubmit(context, priority, submitInfo, &batch.fence.get(), batch.serial));
if (!currentGarbage->empty())
{
......@@ -528,7 +478,8 @@ angle::Result TaskProcessor::submitFrame(Context *context,
// Store the primary CommandBuffer and command pool used for secondary CommandBuffers
// in the in-flight list.
ANGLE_TRY(releaseToCommandBatch(context, std::move(commandBuffer), commandPool, &batch));
ANGLE_TRY(
releaseToCommandBatch(context, std::move(mPrimaryCommandBuffer), commandPool, &batch));
mInFlightCommands.emplace_back(scopedBatch.release());
......@@ -547,28 +498,31 @@ angle::Result TaskProcessor::submitFrame(Context *context,
}
angle::Result TaskProcessor::queueSubmit(Context *context,
VkQueue queue,
egl::ContextPriority priority,
const VkSubmitInfo &submitInfo,
const Fence *fence,
Serial submitQueueSerial)
{
RendererVk *renderer = context->getRenderer();
ASSERT(isValidWorkerThread(context));
ANGLE_TRACE_EVENT0("gpu.angle", "TaskProcessor::queueSubmit");
ASSERT((context->getRenderer()->getFeatures().asynchronousCommandProcessing.enabled == false) ||
ASSERT((renderer->getFeatures().asynchronousCommandProcessing.enabled == false) ||
std::this_thread::get_id() == mThreadId);
if (kOutputVmaStatsString)
{
context->getRenderer()->outputVmaStatString();
renderer->outputVmaStatString();
}
// Don't need a QueueMutex since all queue accesses are serialized through the worker.
VkQueue queue = renderer->getVkQueue(priority);
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(mLastCompletedQueueSerial);
return renderer->cleanupGarbage(mLastCompletedQueueSerial);
}
bool TaskProcessor::isValidWorkerThread(Context *context) const
......@@ -584,6 +538,23 @@ Serial TaskProcessor::reserveSubmitSerial()
return returnSerial;
}
angle::Result TaskProcessor::flushOutsideRPCommands(Context *context,
CommandBufferHelper *outsideRPCommands)
{
ANGLE_TRY(ensurePrimaryCommandBufferValid(context));
return outsideRPCommands->flushToPrimary(context->getRenderer()->getFeatures(),
&mPrimaryCommandBuffer, nullptr);
}
angle::Result TaskProcessor::flushRenderPassCommands(Context *context,
const RenderPass &renderPass,
CommandBufferHelper *renderPassCommands)
{
ANGLE_TRY(ensurePrimaryCommandBufferValid(context));
return renderPassCommands->flushToPrimary(context->getRenderer()->getFeatures(),
&mPrimaryCommandBuffer, &renderPass);
}
void CommandProcessor::handleError(VkResult errorCode,
const char *file,
const char *function,
......@@ -644,7 +615,7 @@ void CommandProcessor::queueCommand(Context *context, CommandProcessorTask *task
}
else
{
angle::Result result = processTask(context, task);
angle::Result result = processTask(task);
if (ANGLE_UNLIKELY(IsError(result)))
{
// TODO: Ignore error, similar to ANGLE_CONTEXT_TRY.
......@@ -660,13 +631,6 @@ angle::Result CommandProcessor::initTaskProcessor(Context *context)
// Initialization prior to work thread loop
ANGLE_TRY(mTaskProcessor.init(context, std::this_thread::get_id()));
// Allocate and begin primary command buffer
ANGLE_TRY(mTaskProcessor.allocatePrimaryCommandBuffer(context, &mPrimaryCommandBuffer));
VkCommandBufferBeginInfo beginInfo = {};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
beginInfo.pInheritanceInfo = nullptr;
ANGLE_VK_TRY(context, mPrimaryCommandBuffer.begin(beginInfo));
return angle::Result::Continue;
}
......@@ -713,7 +677,7 @@ angle::Result CommandProcessor::processTasksImpl(bool *exitThread)
mTasks.pop();
lock.unlock();
ANGLE_TRY(processTask(this, &task));
ANGLE_TRY(processTask(&task));
if (task.getTaskCommand() == CustomTask::Exit)
{
......@@ -729,51 +693,34 @@ angle::Result CommandProcessor::processTasksImpl(bool *exitThread)
return angle::Result::Stop;
}
angle::Result CommandProcessor::processTask(Context *context, CommandProcessorTask *task)
angle::Result CommandProcessor::processTask(CommandProcessorTask *task)
{
switch (task->getTaskCommand())
{
case CustomTask::Exit:
{
ANGLE_TRY(mTaskProcessor.finishToSerial(context, Serial::Infinite()));
ANGLE_TRY(mTaskProcessor.finishToSerial(this, Serial::Infinite()));
// Shutting down so cleanup
mTaskProcessor.destroy(mRenderer->getDevice());
mCommandPool.destroy(mRenderer->getDevice());
mPrimaryCommandBuffer.destroy(mRenderer->getDevice());
break;
}
case CustomTask::FlushAndQueueSubmit:
{
ANGLE_TRACE_EVENT0("gpu.angle", "processTask::FlushAndQueueSubmit");
// End command buffer
ANGLE_VK_TRY(context, mPrimaryCommandBuffer.end());
// 1. Create submitInfo
VkSubmitInfo submitInfo = {};
InitializeSubmitInfo(&submitInfo, mPrimaryCommandBuffer, task->getWaitSemaphores(),
&task->getWaitSemaphoreStageMasks(), task->getSemaphore());
// 2. Get shared submit fence. It's possible there are other users of this fence that
// Get shared submit fence. It's possible there are other users of this fence that
// must wait for the work to be submitted before waiting on the fence. Reset the fence
// immediately so we are sure to get a fresh one next time.
Shared<Fence> fence;
ANGLE_TRY(mRenderer->getNextSubmitFence(&fence, true));
ANGLE_TRY(mRenderer->newSharedFence(this, &fence));
// 3. Call submitFrame()
// Call submitFrame()
ANGLE_TRY(mTaskProcessor.submitFrame(
context, getRenderer()->getVkQueue(task->getPriority()), submitInfo, fence,
&task->getGarbage(), &mCommandPool, std::move(mPrimaryCommandBuffer),
task->getQueueSerial()));
// 4. Allocate & begin new primary command buffer
ANGLE_TRY(mTaskProcessor.allocatePrimaryCommandBuffer(context, &mPrimaryCommandBuffer));
VkCommandBufferBeginInfo beginInfo = {};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
beginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
beginInfo.pInheritanceInfo = nullptr;
ANGLE_VK_TRY(context, mPrimaryCommandBuffer.begin(beginInfo));
// Free this local reference
getRenderer()->resetSharedFence(&fence);
this, task->getPriority(), task->getWaitSemaphores(),
task->getWaitSemaphoreStageMasks(), task->getSemaphore(), std::move(fence),
&task->getGarbage(), &mCommandPool, task->getQueueSerial()));
ASSERT(task->getGarbage().empty());
break;
......@@ -791,21 +738,20 @@ 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(), task->getQueueSerial()));
ANGLE_TRY(mTaskProcessor.checkCompletedCommands(context));
ANGLE_TRY(mTaskProcessor.queueSubmit(this, task->getPriority(), submitInfo,
task->getOneOffFence(), task->getQueueSerial()));
ANGLE_TRY(mTaskProcessor.checkCompletedCommands(this));
break;
}
case CustomTask::FinishToSerial:
{
ANGLE_TRY(mTaskProcessor.finishToSerial(context, task->getQueueSerial()));
ANGLE_TRY(mTaskProcessor.finishToSerial(this, task->getQueueSerial()));
break;
}
case CustomTask::Present:
{
VkResult result = mTaskProcessor.present(getRenderer()->getVkQueue(task->getPriority()),
task->getPresentInfo());
VkResult result =
present(getRenderer()->getVkQueue(task->getPriority()), task->getPresentInfo());
if (ANGLE_UNLIKELY(result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR))
{
// We get to ignore these as they are not fatal
......@@ -816,15 +762,22 @@ angle::Result CommandProcessor::processTask(Context *context, CommandProcessorTa
// Don't leave processing loop, don't consider errors from present to be fatal.
// TODO: https://issuetracker.google.com/issues/170329600 - This needs to improve to
// properly parallelize present
context->handleError(result, __FILE__, __FUNCTION__, __LINE__);
handleError(result, __FILE__, __FUNCTION__, __LINE__);
}
break;
}
case CustomTask::ProcessCommands:
{
ASSERT(!task->getCommandBuffer()->empty());
ANGLE_TRY(task->getCommandBuffer()->flushToPrimary(
getRenderer()->getFeatures(), &mPrimaryCommandBuffer, task->getRenderPass()));
if (task->getRenderPass())
{
ANGLE_TRY(mTaskProcessor.flushRenderPassCommands(this, *task->getRenderPass(),
task->getCommandBuffer()));
}
else
{
ANGLE_TRY(mTaskProcessor.flushOutsideRPCommands(this, task->getCommandBuffer()));
}
ASSERT(task->getCommandBuffer()->empty());
task->getCommandBuffer()->releaseToContextQueue(task->getContextVk());
break;
......@@ -951,6 +904,37 @@ void CommandProcessor::finishAllWork(Context *context)
finishToSerial(context, Serial::Infinite());
}
VkResult CommandProcessor::getLastAndClearPresentResult(VkSwapchainKHR swapchain)
{
std::unique_lock<std::mutex> lock(mSwapchainStatusMutex);
if (mSwapchainStatus.find(swapchain) == mSwapchainStatus.end())
{
// Wake when required swapchain status becomes available
mSwapchainStatusCondition.wait(lock, [this, swapchain] {
return mSwapchainStatus.find(swapchain) != mSwapchainStatus.end();
});
}
VkResult result = mSwapchainStatus[swapchain];
mSwapchainStatus.erase(swapchain);
return result;
}
VkResult CommandProcessor::present(VkQueue queue, const VkPresentInfoKHR &presentInfo)
{
std::lock_guard<std::mutex> lock(mSwapchainStatusMutex);
ANGLE_TRACE_EVENT0("gpu.angle", "vkQueuePresentKHR");
VkResult result = vkQueuePresentKHR(queue, &presentInfo);
// Verify that we are presenting one and only one swapchain
ASSERT(presentInfo.swapchainCount == 1);
ASSERT(presentInfo.pResults == nullptr);
mSwapchainStatus[presentInfo.pSwapchains[0]] = result;
mSwapchainStatusCondition.notify_all();
return result;
}
// CommandQueue implementation.
CommandQueue::CommandQueue() : mCurrentQueueSerial(mQueueSerialFactory.generate()) {}
......@@ -1021,7 +1005,7 @@ angle::Result CommandQueue::retireFinishedCommands(Context *context, size_t fini
renderer->resetSharedFence(&batch.fence);
ANGLE_TRACE_EVENT0("gpu.angle", "command buffer recycling");
batch.commandPool.destroy(device);
ANGLE_TRY(releasePrimaryCommandBuffer(context, std::move(batch.primaryCommands)));
ANGLE_TRY(mPrimaryCommandPool.collect(context, std::move(batch.primaryCommands)));
}
if (finishedCount > 0)
......@@ -1093,22 +1077,6 @@ void CommandQueue::clearAllGarbage(RendererVk *renderer)
mGarbageQueue.clear();
}
angle::Result CommandQueue::allocatePrimaryCommandBuffer(Context *context,
PrimaryCommandBuffer *commandBufferOut)
{
return mPrimaryCommandPool.allocate(context, commandBufferOut);
}
angle::Result CommandQueue::releasePrimaryCommandBuffer(Context *context,
PrimaryCommandBuffer &&commandBuffer)
{
ASSERT(!context->getRenderer()->getFeatures().commandProcessor.enabled);
ASSERT(mPrimaryCommandPool.valid());
ANGLE_TRY(mPrimaryCommandPool.collect(context, std::move(commandBuffer)));
return angle::Result::Continue;
}
void CommandQueue::handleDeviceLost(RendererVk *renderer)
{
VkDevice device = renderer->getDevice();
......@@ -1294,7 +1262,7 @@ angle::Result CommandQueue::ensurePrimaryCommandBufferValid(Context *context)
return angle::Result::Continue;
}
ANGLE_TRY(allocatePrimaryCommandBuffer(context, &mPrimaryCommands));
ANGLE_TRY(mPrimaryCommandPool.allocate(context, &mPrimaryCommands));
VkCommandBufferBeginInfo beginInfo = {};
beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
......
......@@ -204,7 +204,6 @@ class CommandQueue final : angle::NonCopyable
angle::Result checkCompletedCommands(Context *context);
angle::Result flushOutsideRPCommands(Context *context, CommandBufferHelper *outsideRPCommands);
angle::Result flushRenderPassCommands(Context *context,
const RenderPass &renderPass,
CommandBufferHelper *renderPassCommands);
......@@ -220,10 +219,6 @@ class CommandQueue final : angle::NonCopyable
CommandBatch *batch);
angle::Result retireFinishedCommands(Context *context, size_t finishedCount);
angle::Result ensurePrimaryCommandBufferValid(Context *context);
angle::Result allocatePrimaryCommandBuffer(Context *context,
PrimaryCommandBuffer *commandBufferOut);
angle::Result releasePrimaryCommandBuffer(Context *context,
PrimaryCommandBuffer &&commandBuffer);
bool allInFlightCommandsAreAfterSerial(Serial serial) const;
......@@ -250,25 +245,19 @@ class TaskProcessor : angle::NonCopyable
angle::Result init(Context *context, std::thread::id threadId);
void destroy(VkDevice device);
angle::Result allocatePrimaryCommandBuffer(Context *context,
PrimaryCommandBuffer *commandBufferOut);
angle::Result releasePrimaryCommandBuffer(Context *context,
PrimaryCommandBuffer &&commandBuffer);
angle::Result finishToSerial(Context *context, Serial serial);
VkResult present(VkQueue queue, const VkPresentInfoKHR &presentInfo);
angle::Result submitFrame(Context *context,
VkQueue queue,
const VkSubmitInfo &submitInfo,
const Shared<Fence> &sharedFence,
egl::ContextPriority priority,
const std::vector<VkSemaphore> &waitSemaphores,
const std::vector<VkPipelineStageFlags> &waitSemaphoreStageMasks,
const Semaphore *signalSemaphore,
Shared<Fence> &&sharedFence,
GarbageList *currentGarbage,
CommandPool *commandPool,
PrimaryCommandBuffer &&commandBuffer,
Serial submitQueueSerial);
angle::Result queueSubmit(Context *context,
VkQueue queue,
egl::ContextPriority priority,
const VkSubmitInfo &submitInfo,
const Fence *fence,
Serial submitQueueSerial);
......@@ -277,7 +266,10 @@ class TaskProcessor : angle::NonCopyable
angle::Result checkCompletedCommands(Context *context);
VkResult getLastAndClearPresentResult(VkSwapchainKHR swapchain);
angle::Result flushOutsideRPCommands(Context *context, CommandBufferHelper *outsideRPCommands);
angle::Result flushRenderPassCommands(Context *context,
const RenderPass &renderPass,
CommandBufferHelper *renderPassCommands);
Serial reserveSubmitSerial();
......@@ -292,11 +284,13 @@ class TaskProcessor : angle::NonCopyable
PrimaryCommandBuffer &&commandBuffer,
CommandPool *commandPool,
CommandBatch *batch);
angle::Result ensurePrimaryCommandBufferValid(Context *context);
GarbageQueue mGarbageQueue;
std::vector<CommandBatch> mInFlightCommands;
// Keeps a free list of reusable primary command buffers.
PrimaryCommandBuffer mPrimaryCommandBuffer;
PersistentCommandPool mPrimaryCommandPool;
std::thread::id mThreadId;
......@@ -305,11 +299,6 @@ class TaskProcessor : angle::NonCopyable
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
......@@ -363,7 +352,7 @@ class CommandProcessor : public Context
VkResult getLastPresentResult(VkSwapchainKHR swapchain)
{
return mTaskProcessor.getLastAndClearPresentResult(swapchain);
return getLastAndClearPresentResult(swapchain);
}
private:
......@@ -372,7 +361,10 @@ class CommandProcessor : public Context
angle::Result processTasksImpl(bool *exitThread);
// Command processor thread, process a task
angle::Result processTask(Context *context, CommandProcessorTask *task);
angle::Result processTask(CommandProcessorTask *task);
VkResult getLastAndClearPresentResult(VkSwapchainKHR swapchain);
VkResult present(VkQueue queue, const VkPresentInfoKHR &presentInfo);
std::queue<CommandProcessorTask> mTasks;
mutable std::mutex mWorkerMutex;
......@@ -384,13 +376,17 @@ class CommandProcessor : public Context
bool mWorkerThreadIdle;
// Command pool to allocate processor thread primary command buffers from
CommandPool mCommandPool;
PrimaryCommandBuffer mPrimaryCommandBuffer;
TaskProcessor mTaskProcessor;
std::mutex mQueueSerialMutex;
mutable std::mutex mErrorMutex;
std::queue<Error> mErrors;
// Track present info
std::mutex mSwapchainStatusMutex;
std::condition_variable mSwapchainStatusCondition;
std::map<VkSwapchainKHR, VkResult> mSwapchainStatus;
};
} // namespace vk
......
......@@ -154,10 +154,10 @@ void SyncHelperNativeFence::releaseToRenderer(RendererVk *renderer)
renderer->collectGarbageAndReinit(&mUse, &mFenceWithFd);
}
// Note: Having mFenceWithFd hold the FD, so that ownership is with ICD. Meanwhile store a dup
// Note: We have mFenceWithFd hold the FD, so that ownership is with ICD. Meanwhile we store a dup
// of FD in SyncHelperNativeFence for further reference, i.e. dup of FD. Any call to clientWait
// or serverWait will ensure the FD or dup of FD goes to application or ICD. At release, above
// it's Garbage collected/destroyed. Otherwise can't time when to close(fd);
// it's Garbage collected/destroyed. Otherwise we can't time when to close(fd);
angle::Result SyncHelperNativeFence::initializeWithFd(ContextVk *contextVk, int inFd)
{
ASSERT(inFd >= kInvalidFenceFd);
......
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