1 // 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 <gmock/gmock.h>
15 #include <gtest/gtest.h>
16
17 #include "VirtioGpuTimelines.h"
18
19 #include <memory>
20
21 namespace gfxstream {
22 namespace {
23
24 using RingGlobal = VirtioGpuRingGlobal;
25 using RingContextSpecific = VirtioGpuRingContextSpecific;
26
TEST(VirtioGpuTimelinesTest,Init)27 TEST(VirtioGpuTimelinesTest, Init) {
28 std::unique_ptr<VirtioGpuTimelines> virtioGpuTimelines = VirtioGpuTimelines::create(true);
29 virtioGpuTimelines = VirtioGpuTimelines::create(false);
30 }
31
TEST(VirtioGpuTimelinesTest,TasksShouldHaveDifferentIds)32 TEST(VirtioGpuTimelinesTest, TasksShouldHaveDifferentIds) {
33 std::unique_ptr<VirtioGpuTimelines> virtioGpuTimelines = VirtioGpuTimelines::create(true);
34 auto taskId1 = virtioGpuTimelines->enqueueTask(RingGlobal{});
35 auto taskId2 = virtioGpuTimelines->enqueueTask(RingGlobal{});
36 ASSERT_NE(taskId1, taskId2);
37 }
38
TEST(VirtioGpuTimelinesTest,CantPollWithAsyncCallbackEnabled)39 TEST(VirtioGpuTimelinesTest, CantPollWithAsyncCallbackEnabled) {
40 EXPECT_DEATH(
41 {
42 std::unique_ptr<VirtioGpuTimelines> virtioGpuTimelines =
43 VirtioGpuTimelines::create(true);
44 virtioGpuTimelines->poll();
45 },
46 ".*");
47 }
48
TEST(VirtioGpuTimelinesTest,MultipleTasksAndFencesWithSyncCallback)49 TEST(VirtioGpuTimelinesTest, MultipleTasksAndFencesWithSyncCallback) {
50 std::unique_ptr<VirtioGpuTimelines> virtioGpuTimelines = VirtioGpuTimelines::create(false);
51 using namespace testing;
52 MockFunction<void()> check;
53 MockFunction<void()> fence1Callback;
54 MockFunction<void()> fence2Callback;
55 MockFunction<void()> fence3Callback;
56 VirtioGpuTimelines::FenceId fenceId = 0;
57 {
58 InSequence s;
59
60 EXPECT_CALL(check, Call());
61 EXPECT_CALL(fence1Callback, Call());
62 EXPECT_CALL(fence2Callback, Call());
63 EXPECT_CALL(fence3Callback, Call());
64 }
65
66 auto task1Id = virtioGpuTimelines->enqueueTask(RingGlobal{});
67 virtioGpuTimelines->enqueueFence(RingGlobal{}, fenceId++, fence1Callback.AsStdFunction());
68 auto task2Id = virtioGpuTimelines->enqueueTask(RingGlobal{});
69 virtioGpuTimelines->enqueueFence(RingGlobal{}, fenceId++, fence2Callback.AsStdFunction());
70 virtioGpuTimelines->notifyTaskCompletion(task1Id);
71 auto task3Id = virtioGpuTimelines->enqueueTask(RingGlobal{});
72 virtioGpuTimelines->enqueueFence(RingGlobal{}, fenceId++, fence3Callback.AsStdFunction());
73 virtioGpuTimelines->notifyTaskCompletion(task2Id);
74 virtioGpuTimelines->notifyTaskCompletion(task3Id);
75 check.Call();
76 virtioGpuTimelines->poll();
77 }
78
TEST(VirtioGpuTimelinesTest,MultipleTasksAndFencesWithAsyncCallback)79 TEST(VirtioGpuTimelinesTest, MultipleTasksAndFencesWithAsyncCallback) {
80 std::unique_ptr<VirtioGpuTimelines> virtioGpuTimelines = VirtioGpuTimelines::create(true);
81 using namespace testing;
82 MockFunction<void(int)> check;
83 MockFunction<void()> fence1Callback;
84 MockFunction<void()> fence2Callback;
85 MockFunction<void()> fence3Callback;
86 VirtioGpuTimelines::FenceId fenceId = 0;
87 {
88 InSequence s;
89
90 EXPECT_CALL(check, Call(1));
91 EXPECT_CALL(fence1Callback, Call());
92 EXPECT_CALL(check, Call(2));
93 EXPECT_CALL(check, Call(3));
94 EXPECT_CALL(fence2Callback, Call());
95 EXPECT_CALL(check, Call(4));
96 EXPECT_CALL(fence3Callback, Call());
97 }
98
99 auto task1Id = virtioGpuTimelines->enqueueTask(RingGlobal{});
100 virtioGpuTimelines->enqueueFence(RingGlobal{}, fenceId++, fence1Callback.AsStdFunction());
101 auto task2Id = virtioGpuTimelines->enqueueTask(RingGlobal{});
102 virtioGpuTimelines->enqueueFence(RingGlobal{}, fenceId++, fence2Callback.AsStdFunction());
103 check.Call(1);
104 virtioGpuTimelines->notifyTaskCompletion(task1Id);
105 check.Call(2);
106 auto task3Id = virtioGpuTimelines->enqueueTask(RingGlobal{});
107 virtioGpuTimelines->enqueueFence(RingGlobal{}, fenceId++, fence3Callback.AsStdFunction());
108 check.Call(3);
109 virtioGpuTimelines->notifyTaskCompletion(task2Id);
110 check.Call(4);
111 virtioGpuTimelines->notifyTaskCompletion(task3Id);
112 }
113
TEST(VirtioGpuTimelinesTest,FencesWithoutPendingTasksWithAsyncCallback)114 TEST(VirtioGpuTimelinesTest, FencesWithoutPendingTasksWithAsyncCallback) {
115 std::unique_ptr<VirtioGpuTimelines> virtioGpuTimelines = VirtioGpuTimelines::create(true);
116 using namespace testing;
117 MockFunction<void()> fenceCallback1;
118 MockFunction<void()> fenceCallback2;
119 VirtioGpuTimelines::FenceId fenceId = 0;
120 {
121 InSequence s;
122 EXPECT_CALL(fenceCallback1, Call());
123 EXPECT_CALL(fenceCallback2, Call());
124 }
125
126 virtioGpuTimelines->enqueueFence(RingGlobal{}, fenceId++, fenceCallback1.AsStdFunction());
127 virtioGpuTimelines->enqueueFence(RingGlobal{}, fenceId++, fenceCallback2.AsStdFunction());
128 }
129
TEST(VirtioGpuTimelinesTest,FencesSharingSamePendingTasksWithAsyncCallback)130 TEST(VirtioGpuTimelinesTest, FencesSharingSamePendingTasksWithAsyncCallback) {
131 std::unique_ptr<VirtioGpuTimelines> virtioGpuTimelines = VirtioGpuTimelines::create(true);
132 using namespace testing;
133 MockFunction<void()> fenceCallback1;
134 MockFunction<void()> fenceCallback2;
135 MockFunction<void(int)> check;
136 VirtioGpuTimelines::FenceId fenceId = 0;
137 {
138 InSequence s;
139 EXPECT_CALL(check, Call(1));
140 EXPECT_CALL(fenceCallback1, Call());
141 EXPECT_CALL(fenceCallback2, Call());
142 }
143
144 auto taskId = virtioGpuTimelines->enqueueTask(RingGlobal{});
145 virtioGpuTimelines->enqueueFence(RingGlobal{}, fenceId++, fenceCallback1.AsStdFunction());
146 virtioGpuTimelines->enqueueFence(RingGlobal{}, fenceId++, fenceCallback2.AsStdFunction());
147 check.Call(1);
148 virtioGpuTimelines->notifyTaskCompletion(taskId);
149 }
150
TEST(VirtioGpuTimelinesTest,TasksAndFencesOnMultipleContextsWithAsyncCallback)151 TEST(VirtioGpuTimelinesTest, TasksAndFencesOnMultipleContextsWithAsyncCallback) {
152 std::unique_ptr<VirtioGpuTimelines> virtioGpuTimelines = VirtioGpuTimelines::create(true);
153 using namespace testing;
154 MockFunction<void()> fence1Callback;
155 MockFunction<void()> fence2Callback;
156 MockFunction<void()> fence3Callback;
157 MockFunction<void(int)> check;
158 {
159 InSequence s;
160
161 EXPECT_CALL(check, Call(1));
162 EXPECT_CALL(fence1Callback, Call());
163 EXPECT_CALL(check, Call(2));
164 EXPECT_CALL(fence2Callback, Call());
165 EXPECT_CALL(check, Call(3));
166 EXPECT_CALL(fence3Callback, Call());
167 }
168 auto taskId2 = virtioGpuTimelines->enqueueTask(RingContextSpecific{
169 .mCtxId = 2,
170 .mRingIdx = 0,
171 });
172 auto taskId3 = virtioGpuTimelines->enqueueTask(RingContextSpecific{
173 .mCtxId = 3,
174 .mRingIdx = 0,
175 });
176 check.Call(1);
177 virtioGpuTimelines->enqueueFence(RingGlobal{}, 1, fence1Callback.AsStdFunction());
178 check.Call(2);
179 virtioGpuTimelines->enqueueFence(
180 RingContextSpecific{
181 .mCtxId = 2,
182 .mRingIdx = 0,
183 },
184 2, fence2Callback.AsStdFunction());
185 virtioGpuTimelines->enqueueFence(
186 RingContextSpecific{
187 .mCtxId = 3,
188 .mRingIdx = 0,
189 },
190 3, fence3Callback.AsStdFunction());
191 virtioGpuTimelines->notifyTaskCompletion(taskId2);
192 check.Call(3);
193 virtioGpuTimelines->notifyTaskCompletion(taskId3);
194 }
195
TEST(VirtioGpuTimelinesTest,TasksAndFencesOnMultipleRingsWithAsyncCallback)196 TEST(VirtioGpuTimelinesTest, TasksAndFencesOnMultipleRingsWithAsyncCallback) {
197 std::unique_ptr<VirtioGpuTimelines> virtioGpuTimelines = VirtioGpuTimelines::create(true);
198 using namespace testing;
199 MockFunction<void()> fence1Callback;
200 MockFunction<void()> fence2Callback;
201 MockFunction<void()> fence3Callback;
202 MockFunction<void(int)> check;
203 {
204 InSequence s;
205
206 EXPECT_CALL(check, Call(1));
207 EXPECT_CALL(fence1Callback, Call());
208 EXPECT_CALL(check, Call(2));
209 EXPECT_CALL(fence2Callback, Call());
210 EXPECT_CALL(check, Call(3));
211 EXPECT_CALL(fence3Callback, Call());
212 }
213 auto taskId2 = virtioGpuTimelines->enqueueTask(RingContextSpecific{
214 .mCtxId = 1,
215 .mRingIdx = 2,
216 });
217 auto taskId3 = virtioGpuTimelines->enqueueTask(RingContextSpecific{
218 .mCtxId = 1,
219 .mRingIdx = 3,
220 });
221 check.Call(1);
222 virtioGpuTimelines->enqueueFence(
223 RingContextSpecific{
224 .mCtxId = 1,
225 .mRingIdx = 1,
226 },
227 1, fence1Callback.AsStdFunction());
228 check.Call(2);
229 virtioGpuTimelines->enqueueFence(
230 RingContextSpecific{
231 .mCtxId = 1,
232 .mRingIdx = 2,
233 },
234 2, fence2Callback.AsStdFunction());
235 virtioGpuTimelines->enqueueFence(
236 RingContextSpecific{
237 .mCtxId = 1,
238 .mRingIdx = 3,
239 },
240 3, fence3Callback.AsStdFunction());
241 virtioGpuTimelines->notifyTaskCompletion(taskId2);
242 check.Call(3);
243 virtioGpuTimelines->notifyTaskCompletion(taskId3);
244 }
245
246 } // namespace
247 } // namespace gfxstream
248