Hash :
02fa7313
Author :
Date :
2020-05-05T17:01:18
Vulkan:Initial worker thread disabled by default Created new CommandProcessor class that can be run as a worker thread. Running CommandProcessor within RendererVk as a worker thread that takes a CommmandBufferHelper (CBH) ptr as the interface and processes that CBH into a primary command buffer. Main thread has a queue of CBH to draw from. After submitting a CBH to the worker, it pulls next CBH from the queue. Worker thread releases CBH back to the main thread queue when done. Synchronization goes two ways: 1. Work submitted to worker thread is managaed with a mutex and condition variable based around the work queue. 2. Available CBH ptrs for the main thread have a mutex and condition variable that manages the CBH queue. The worker thread is disabled by default, and, when enabled, it will currently behave and perform as the non-threaded code. This is because the kNumCommandBuffers const in ContextVk.h is set to 2. With only 2 command buffers, they will be assigned to the inside and outside RenderPass command buffers respectively. Then, as soon as one is submitted, the main thread will stall waiting for it to be completed and put back into the queue mentioned in #2 above. The next step is to move command submission to the worker thread and update the number of command buffers so that processing/submission will occur in parallel with the main thread. Right now there is a race condition issue when attempting to run in parallel because the main thread updates and submits the same primary command buffers that are used in the worker thread, which is in violation of the Vulkan spec. The follow-on CL will fix this issue as the main thread will only touch SecondaryCommandBuffers and the worker thread will be the only thread touching the primary command buffers. Bug: b/154030730 Change-Id: Ib0c518bbd7ca9a3a7e789f4e1f2f7131ddc0509e Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2174719 Commit-Queue: Tobin Ehlis <tobine@google.com> Reviewed-by: Jamie Madill <jmadill@chromium.org>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
//
// Copyright 2020 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// CommandProcessor.h:
// A class to process and submit Vulkan command buffers that can be
// used in an asynchronous worker thread.
//
#ifndef LIBANGLE_RENDERER_VULKAN_COMMAND_PROCESSOR_H_
#define LIBANGLE_RENDERER_VULKAN_COMMAND_PROCESSOR_H_
#include <condition_variable>
#include <mutex>
#include <queue>
#include <thread>
#include "libANGLE/renderer/vulkan/vk_headers.h"
#include "libANGLE/renderer/vulkan/vk_helpers.h"
namespace rx
{
namespace vk
{
// CommandProcessorTask is used to queue a task to the worker thread when
// enableCommandProcessingThread feature is true.
// The typical task includes pointers in all values and the worker thread will
// process the SecondaryCommandBuffer commands in cbh into the primaryCB.
// There is a special task in which all of the pointers are null that will trigger
// the worker thread to exit, and is sent when the renderer instance shuts down.
struct CommandProcessorTask
{
ContextVk *contextVk;
// TODO: b/153666475 Removed primaryCB in threading phase2.
vk::PrimaryCommandBuffer *primaryCB;
CommandBufferHelper *commandBuffer;
};
static const CommandProcessorTask kEndCommandProcessorThread = {nullptr, nullptr, nullptr};
} // namespace vk
class CommandProcessor : angle::NonCopyable
{
public:
CommandProcessor();
~CommandProcessor() = default;
// Main worker loop that should be launched in its own thread. The
// loop waits for work to be submitted from a separate thread.
angle::Result processCommandProcessorTasks();
// Called asynchronously from workLoop() thread to queue work that is
// then processed by the workLoop() thread
void queueCommands(const vk::CommandProcessorTask &commands);
// Used by separate thread to wait for worker thread to complete all
// outstanding work.
void waitForWorkComplete();
// Stop the command processor loop
void shutdown(std::thread *commandProcessorThread);
private:
std::queue<vk::CommandProcessorTask> mCommandsQueue;
std::mutex mWorkerMutex;
// Signal worker thread when work is available
std::condition_variable mWorkAvailableCondition;
// Signal main thread when all work completed
std::condition_variable mWorkerIdleCondition;
// Track worker thread Idle state for assertion purposes
bool mWorkerThreadIdle;
};
} // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_COMMAND_PROCESSOR_H_