blob: 635aa819d24e073286a7242d96003bbea2089bdf [file] [log] [blame]
Kaiyi Lifab51002021-08-21 15:12:02 -07001// Copyright 2021 The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14#include "VirtioGpuTimelines.h"
15
16#include <cinttypes>
17#include <cstdio>
18
Doug Horn0c2ea5a2021-10-29 17:30:16 -070019#include "host-common/GfxstreamFatalError.h"
Kaiyi Lifab51002021-08-21 15:12:02 -070020
21using TaskId = VirtioGpuTimelines::TaskId;
Kaiyi Li1fdd22e2022-03-31 10:17:23 -070022using Ring = VirtioGpuTimelines::Ring;
Kaiyi Lifab51002021-08-21 15:12:02 -070023using FenceId = VirtioGpuTimelines::FenceId;
24using AutoLock = android::base::AutoLock;
Kaiyi Li4935d312022-01-12 16:57:24 -080025using emugl::ABORT_REASON_OTHER;
26using emugl::FatalError;
Kaiyi Lifab51002021-08-21 15:12:02 -070027
Kaiyi Li1fdd22e2022-03-31 10:17:23 -070028std::unique_ptr<VirtioGpuTimelines> VirtioGpuTimelines::create(bool withAsyncCallback) {
29 return std::unique_ptr<VirtioGpuTimelines>(new VirtioGpuTimelines(withAsyncCallback));
30}
Kaiyi Lifab51002021-08-21 15:12:02 -070031
Kaiyi Li1fdd22e2022-03-31 10:17:23 -070032VirtioGpuTimelines::VirtioGpuTimelines(bool withAsyncCallback)
33 : mNextId(0), mWithAsyncCallback(withAsyncCallback) {}
34
35TaskId VirtioGpuTimelines::enqueueTask(const Ring& ring) {
Kaiyi Lifab51002021-08-21 15:12:02 -070036 AutoLock lock(mLock);
37
38 TaskId id = mNextId++;
Kaiyi Li1fdd22e2022-03-31 10:17:23 -070039 std::shared_ptr<Task> task(new Task(id, ring), [this](Task* task) {
Kaiyi Li61ebb7e2021-09-08 09:02:05 -070040 mTaskIdToTask.erase(task->mId);
41 delete task;
42 });
Kaiyi Lifab51002021-08-21 15:12:02 -070043 mTaskIdToTask[id] = task;
Kaiyi Li1fdd22e2022-03-31 10:17:23 -070044 mTimelineQueues[ring].emplace_back(std::move(task));
Kaiyi Lifab51002021-08-21 15:12:02 -070045 return id;
46}
47
Jason Macnak96de4eb2023-05-10 12:45:16 -070048void VirtioGpuTimelines::enqueueFence(const Ring& ring, FenceId fenceId,
Kaiyi Li1fdd22e2022-03-31 10:17:23 -070049 FenceCompletionCallback fenceCompletionCallback) {
Kaiyi Lifab51002021-08-21 15:12:02 -070050 AutoLock lock(mLock);
51
Jason Macnakfdecd452023-05-12 15:43:31 -070052 auto fence = std::make_unique<Fence>(fenceId, std::move(fenceCompletionCallback));
Kaiyi Li1fdd22e2022-03-31 10:17:23 -070053 mTimelineQueues[ring].emplace_back(std::move(fence));
54 if (mWithAsyncCallback) {
55 poll_locked(ring);
56 }
Kaiyi Lifab51002021-08-21 15:12:02 -070057}
58
59void VirtioGpuTimelines::notifyTaskCompletion(TaskId taskId) {
60 AutoLock lock(mLock);
61 auto iTask = mTaskIdToTask.find(taskId);
62 if (iTask == mTaskIdToTask.end()) {
Doug Horn0c2ea5a2021-10-29 17:30:16 -070063 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
64 << "Task(id = " << static_cast<uint64_t>(taskId) << ") can't be found";
Kaiyi Lifab51002021-08-21 15:12:02 -070065 }
66 std::shared_ptr<Task> task = iTask->second.lock();
67 if (task == nullptr) {
Doug Horn0c2ea5a2021-10-29 17:30:16 -070068 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
69 << "Task(id = " << static_cast<uint64_t>(taskId) << ") has been destroyed";
Kaiyi Lifab51002021-08-21 15:12:02 -070070 }
71 if (task->mId != taskId) {
Doug Horn0c2ea5a2021-10-29 17:30:16 -070072 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
73 << "Task id mismatch. Expected " << static_cast<uint64_t>(taskId) << " Actual "
74 << static_cast<uint64_t>(task->mId);
Kaiyi Lifab51002021-08-21 15:12:02 -070075 }
76 if (task->mHasCompleted) {
Doug Horn0c2ea5a2021-10-29 17:30:16 -070077 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
78 << "Task(id = " << static_cast<uint64_t>(taskId) << ") has been set to completed.";
Kaiyi Lifab51002021-08-21 15:12:02 -070079 }
80 task->mHasCompleted = true;
Kaiyi Li1fdd22e2022-03-31 10:17:23 -070081 if (mWithAsyncCallback) {
82 poll_locked(task->mRing);
83 }
Kaiyi Lifab51002021-08-21 15:12:02 -070084}
85
Kaiyi Li1fdd22e2022-03-31 10:17:23 -070086void VirtioGpuTimelines::poll() {
87 if (mWithAsyncCallback) {
88 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
89 << "Can't call poll with async callback enabled.";
90 }
91 AutoLock lock(mLock);
92 for (const auto& [ring, timeline] : mTimelineQueues) {
93 poll_locked(ring);
94 }
95}
96void VirtioGpuTimelines::poll_locked(const Ring& ring) {
97 auto iTimelineQueue = mTimelineQueues.find(ring);
Kaiyi Lifab51002021-08-21 15:12:02 -070098 if (iTimelineQueue == mTimelineQueues.end()) {
Doug Horn0c2ea5a2021-10-29 17:30:16 -070099 GFXSTREAM_ABORT(FatalError(ABORT_REASON_OTHER))
Kaiyi Li1fdd22e2022-03-31 10:17:23 -0700100 << "Ring(" << to_string(ring) << ") doesn't exist.";
Kaiyi Lifab51002021-08-21 15:12:02 -0700101 }
102 std::list<TimelineItem> &timelineQueue = iTimelineQueue->second;
103 auto i = timelineQueue.begin();
104 for (; i != timelineQueue.end(); i++) {
105 // This visitor will signal the fence and return whether the timeline
106 // item is an incompleted task.
107 struct {
108 bool operator()(std::unique_ptr<Fence> &fence) {
Jason Macnakfdecd452023-05-12 15:43:31 -0700109 fence->mCompletionCallback();
Kaiyi Lifab51002021-08-21 15:12:02 -0700110 return false;
111 }
112 bool operator()(std::shared_ptr<Task> &task) {
113 return !task->mHasCompleted;
114 }
115 } visitor;
116 if (std::visit(visitor, *i)) {
117 break;
118 }
119 }
120 timelineQueue.erase(timelineQueue.begin(), i);
Doug Horn0c2ea5a2021-10-29 17:30:16 -0700121}