diff options
author | Austin Annestrand <a.annestrand@samsung.com> | 2024-03-28 18:05:00 -0500 |
---|---|---|
committer | Angle LUCI CQ <angle-scoped@luci-project-accounts.iam.gserviceaccount.com> | 2024-04-18 22:16:15 +0000 |
commit | cc770518b07ce9ef45cd1c283e9f69b3711d304e (patch) | |
tree | cb4c12da9cd5b777b63f94b18d943841f766b1b0 | |
parent | c75b03ad1ca99d11cf0adf1efe5188a55acaa7cf (diff) | |
download | angle-cc770518b07ce9ef45cd1c283e9f69b3711d304e.tar.gz |
CL/VK: Implement flush & finish
Bug: angleproject:8632
Change-Id: I139e463c0b1c947cee68e65c40503e52f01e988b
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/5406615
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
Commit-Queue: Austin Annestrand <a.annestrand@samsung.com>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
-rw-r--r-- | src/libANGLE/renderer/vulkan/CLCommandQueueVk.cpp | 140 | ||||
-rw-r--r-- | src/libANGLE/renderer/vulkan/CLCommandQueueVk.h | 3 |
2 files changed, 132 insertions, 11 deletions
diff --git a/src/libANGLE/renderer/vulkan/CLCommandQueueVk.cpp b/src/libANGLE/renderer/vulkan/CLCommandQueueVk.cpp index 33f0de41f4..f461da52f3 100644 --- a/src/libANGLE/renderer/vulkan/CLCommandQueueVk.cpp +++ b/src/libANGLE/renderer/vulkan/CLCommandQueueVk.cpp @@ -26,12 +26,31 @@ namespace rx { +class CLAsyncFinishTask : public angle::Closure +{ + public: + CLAsyncFinishTask(CLCommandQueueVk *queueVk) : mQueueVk(queueVk) {} + + void operator()() override + { + ANGLE_TRACE_EVENT0("gpu.angle", "CLCommandQueueVk::finish (async)"); + if (IsError(mQueueVk->finish())) + { + ERR() << "Async finish (clFlush) failed for queue (" << mQueueVk << ")!"; + } + } + + private: + CLCommandQueueVk *mQueueVk; +}; + CLCommandQueueVk::CLCommandQueueVk(const cl::CommandQueue &commandQueue) : CLCommandQueueImpl(commandQueue), mContext(&commandQueue.getContext().getImpl<CLContextVk>()), mDevice(&commandQueue.getDevice().getImpl<CLDeviceVk>()), mComputePassCommands(nullptr), - mCurrentQueueSerialIndex(kInvalidQueueSerialIndex) + mCurrentQueueSerialIndex(kInvalidQueueSerialIndex), + mHasAnyCommandsPendingSubmission(false) {} angle::Result CLCommandQueueVk::init() @@ -391,14 +410,26 @@ angle::Result CLCommandQueueVk::enqueueBarrier() angle::Result CLCommandQueueVk::flush() { - UNIMPLEMENTED(); - ANGLE_CL_RETURN_ERROR(CL_OUT_OF_RESOURCES); + ANGLE_TRACE_EVENT0("gpu.angle", "CLCommandQueueVk::flush"); + + // Non-blocking finish + // TODO: Ideally we should try to find better impl. to avoid spawning a submit-thread/Task here + // https://anglebug.com/8669 + std::shared_ptr<angle::WaitableEvent> asyncEvent = + getPlatform()->postMultiThreadWorkerTask(std::make_shared<CLAsyncFinishTask>(this)); + ASSERT(asyncEvent != nullptr); + + return angle::Result::Continue; } angle::Result CLCommandQueueVk::finish() { - UNIMPLEMENTED(); - ANGLE_CL_RETURN_ERROR(CL_OUT_OF_RESOURCES); + std::scoped_lock<std::mutex> sl(mCommandQueueMutex); + + ANGLE_TRACE_EVENT0("gpu.angle", "CLCommandQueueVk::finish"); + + // Blocking finish + return finishInternal(); } angle::Result CLCommandQueueVk::processKernelResources(CLKernelVk &kernelVk, @@ -527,8 +558,22 @@ angle::Result CLCommandQueueVk::processKernelResources(CLKernelVk &kernelVk, angle::Result CLCommandQueueVk::flushComputePassCommands() { - UNIMPLEMENTED(); - ANGLE_CL_RETURN_ERROR(CL_OUT_OF_RESOURCES); + mLastFlushedQueueSerial = mComputePassCommands->getQueueSerial(); + + // Here, we flush our compute cmds to RendererVk's primary command buffer + ANGLE_TRY(mContext->getRenderer()->flushOutsideRPCommands( + mContext, getProtectionType(), egl::ContextPriority::Medium, &mComputePassCommands)); + + mHasAnyCommandsPendingSubmission = true; + + mContext->getPerfCounters().flushedOutsideRenderPassCommandBuffers++; + + // Generate new serial for next batch of cmds + mComputePassCommands->setQueueSerial( + mCurrentQueueSerialIndex, + mContext->getRenderer()->generateQueueSerial(mCurrentQueueSerialIndex)); + + return angle::Result::Continue; } angle::Result CLCommandQueueVk::processWaitlist(const cl::EventPtrs &waitEvents) @@ -567,8 +612,22 @@ angle::Result CLCommandQueueVk::processWaitlist(const cl::EventPtrs &waitEvents) angle::Result CLCommandQueueVk::submitCommands() { - UNIMPLEMENTED(); - ANGLE_CL_RETURN_ERROR(CL_OUT_OF_RESOURCES); + ANGLE_TRACE_EVENT0("gpu.angle", "CLCommandQueueVk::submitCommands()"); + + // Kick off renderer submit + ANGLE_TRY(mContext->getRenderer()->submitCommands(mContext, getProtectionType(), + egl::ContextPriority::Medium, nullptr, + nullptr, mLastFlushedQueueSerial)); + + mLastSubmittedQueueSerial = mLastFlushedQueueSerial; + + // Now that we have submitted commands, some of pending garbage may no longer pending + // and should be moved to garbage list. + mContext->getRenderer()->cleanupPendingSubmissionGarbage(); + + mHasAnyCommandsPendingSubmission = false; + + return angle::Result::Continue; } angle::Result CLCommandQueueVk::createEvent(CLEventImpl::CreateFunc *createFunc) @@ -596,8 +655,67 @@ angle::Result CLCommandQueueVk::createEvent(CLEventImpl::CreateFunc *createFunc) angle::Result CLCommandQueueVk::finishInternal() { - UNIMPLEMENTED(); - ANGLE_CL_RETURN_ERROR(CL_OUT_OF_RESOURCES); + for (cl::EventPtr event : mAssociatedEvents) + { + ANGLE_TRY(event->getImpl<CLEventVk>().setStatusAndExecuteCallback(CL_SUBMITTED)); + } + + if (!mComputePassCommands->empty()) + { + // If we still have dependant events, handle them now + if (!mDependantEvents.empty()) + { + for (const auto &depEvent : mDependantEvents) + { + if (depEvent->getImpl<CLEventVk>().isUserEvent()) + { + // We just wait here for user to set the event object + cl_int status = CL_QUEUED; + ANGLE_TRY(depEvent->getImpl<CLEventVk>().waitForUserEventStatus()); + ANGLE_TRY(depEvent->getImpl<CLEventVk>().getCommandExecutionStatus(status)); + if (status < 0) + { + ERR() << "Invalid dependant user-event (" << depEvent.get() + << ") status encountered!"; + mComputePassCommands->getCommandBuffer().reset(); + ANGLE_CL_RETURN_ERROR(CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST); + } + } + else + { + // Otherwise, we just need to submit/finish for dependant event queues + // here that are not associated with this queue + ANGLE_TRY(depEvent->getCommandQueue()->finish()); + } + } + mDependantEvents.clear(); + } + + ANGLE_TRY(flushComputePassCommands()); + } + + for (cl::EventPtr event : mAssociatedEvents) + { + ANGLE_TRY(event->getImpl<CLEventVk>().setStatusAndExecuteCallback(CL_RUNNING)); + } + + if (mHasAnyCommandsPendingSubmission) + { + // Submit and wait for fence + ANGLE_TRY(submitCommands()); + ANGLE_TRY(mContext->getRenderer()->finishQueueSerial(mContext, mLastSubmittedQueueSerial)); + } + + for (cl::EventPtr event : mAssociatedEvents) + { + ANGLE_TRY(event->getImpl<CLEventVk>().setStatusAndExecuteCallback(CL_COMPLETE)); + } + + mMemoryCaptures.clear(); + mAssociatedEvents.clear(); + mDependencyTracker.clear(); + + return angle::Result::Continue; } } // namespace rx diff --git a/src/libANGLE/renderer/vulkan/CLCommandQueueVk.h b/src/libANGLE/renderer/vulkan/CLCommandQueueVk.h index 0238a98545..44a387b278 100644 --- a/src/libANGLE/renderer/vulkan/CLCommandQueueVk.h +++ b/src/libANGLE/renderer/vulkan/CLCommandQueueVk.h @@ -261,6 +261,9 @@ class CLCommandQueueVk : public CLCommandQueueImpl // Resource reference capturing during execution cl::MemoryPtrs mMemoryCaptures; + + // Check to see if flush/finish can be skipped + bool mHasAnyCommandsPendingSubmission; }; } // namespace rx |