Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(174)

Side by Side Diff: gpu/ipc/service/gpu_scheduler_unittest.cc

Issue 2440093003: WIP GPU scheduler + delayed activation / tile draw
Patch Set: SignalSyncToken -> IsFenceSyncReleased Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « gpu/ipc/service/gpu_scheduler.cc ('k') | ppapi/proxy/ppapi_command_buffer_proxy.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "gpu/ipc/service/gpu_scheduler.h"
6
7 #include <algorithm>
8
9 #include "base/memory/ptr_util.h"
10 #include "base/test/test_mock_time_task_runner.h"
11 #include "gpu/ipc/service/gpu_command_stream.h"
12 #include "testing/gmock/include/gmock/gmock.h"
13 #include "testing/gmock_mutant.h"
14 #include "testing/gtest/include/gtest/gtest.h"
15
16 namespace gpu {
17 namespace {
18
19 using ::testing::_;
20 using ::testing::CreateFunctor;
21 using ::testing::Invoke;
22 using ::testing::Return;
23 using ::testing::StrictMock;
24
25 base::TimeDelta kSchedulingGranularity =
26 base::TimeDelta::FromMicroseconds(1000);
27
28 base::TimeDelta kTimeSliceRealTime = base::TimeDelta::FromMicroseconds(16000);
29 base::TimeDelta kTimeSliceHigh = base::TimeDelta::FromMicroseconds(8000);
30 base::TimeDelta kTimeSliceNormal = base::TimeDelta::FromMicroseconds(4000);
31 base::TimeDelta kTimeSliceLow = base::TimeDelta::FromMicroseconds(2000);
32
33 base::TimeDelta kRealTimeMaxWaitDuration =
34 base::TimeDelta::FromMicroseconds(4000);
35
36 base::TimeDelta kSchedulerPollingInterval =
37 base::TimeDelta::FromMicroseconds(100);
38
39 class TestTaskRunner : public base::TestMockTimeTaskRunner {
40 public:
41 TestTaskRunner()
42 : TestMockTimeTaskRunner(), run_pending_only_(false), pending_tasks_(0) {}
43
44 void RunPendingTasksUntil(base::TimeTicks target) {
45 run_pending_only_ = true;
46 pending_tasks_ = TestMockTimeTaskRunner::GetPendingTaskCount();
47 base::TimeDelta delta = target - TestMockTimeTaskRunner::NowTicks();
48 TestMockTimeTaskRunner::FastForwardBy(delta);
49 run_pending_only_ = false;
50 }
51
52 protected:
53 ~TestTaskRunner() override {}
54
55 bool IsElapsingStopped() override {
56 if (run_pending_only_)
57 return pending_tasks_ == 0;
58 return TestMockTimeTaskRunner::IsElapsingStopped();
59 }
60
61 void OnAfterTaskRun() override {
62 if (run_pending_only_ && pending_tasks_ > 0)
63 pending_tasks_--;
64 }
65
66 private:
67 bool run_pending_only_;
68 size_t pending_tasks_;
69 };
70
71 class TestGpuScheduler : public GpuScheduler {
72 public:
73 static std::unique_ptr<TestGpuScheduler> Create(
74 scoped_refptr<TestTaskRunner> task_runner) {
75 GpuSchedulerSettings settings;
76 base::TimeDelta priority_time_slice[kNumGpuStreamPriorities] = {
77 kTimeSliceRealTime, kTimeSliceHigh, kTimeSliceNormal, kTimeSliceLow};
78 std::copy(priority_time_slice,
79 priority_time_slice + kNumGpuStreamPriorities,
80 settings.priority_time_slice);
81 settings.scheduling_granularity = kSchedulingGranularity;
82 settings.real_time_max_wait_duration = kRealTimeMaxWaitDuration;
83
84 return base::WrapUnique(new TestGpuScheduler(settings, task_runner));
85 }
86
87 TestGpuScheduler(const GpuSchedulerSettings& settings,
88 scoped_refptr<TestTaskRunner> task_runner)
89 : GpuScheduler(settings, task_runner, task_runner),
90 task_runner_(task_runner) {}
91 ~TestGpuScheduler() override {}
92
93 void RunPendingTasks() { task_runner_->RunPendingTasksUntil(now_); }
94
95 void AdvanceSchedulingTick() { AdvanceNow(kSchedulingGranularity); }
96
97 void AdvanceNow(base::TimeDelta delta) { now_ += delta; }
98
99 protected:
100 base::TimeTicks Now() const override { return task_runner_->NowTicks(); }
101
102 private:
103 scoped_refptr<TestTaskRunner> task_runner_;
104 base::TimeTicks now_;
105
106 DISALLOW_COPY_AND_ASSIGN(TestGpuScheduler);
107 };
108
109 class MockGpuCommandStream : public GpuCommandStream {
110 public:
111 MockGpuCommandStream(TestGpuScheduler* scheduler, GpuStreamPriority priority)
112 : scheduler_(scheduler), priority_(priority), can_run_(false) {}
113 ~MockGpuCommandStream() override {}
114
115 bool CanRun() const override { return can_run_; }
116 void set_can_run(bool can_run) { can_run_ = can_run; }
117
118 GpuStreamPriority Priority() const override { return priority_; }
119
120 void EnablePolling() {
121 ON_CALL(*this, Run())
122 .WillByDefault(Invoke(this, &MockGpuCommandStream::PollScheduler));
123 }
124
125 void DisablePolling() { ON_CALL(*this, Run()).WillByDefault(Return()); }
126
127 base::TimeDelta poll_duration() const { return poll_duration_; }
128
129 void PollScheduler() {
130 poll_duration_ = base::TimeDelta();
131 while (!scheduler_->NeedsRescheduling()) {
132 poll_duration_ += kSchedulerPollingInterval;
133 scheduler_->AdvanceNow(kSchedulerPollingInterval);
134 scheduler_->RunPendingTasks();
135 }
136 }
137
138 MOCK_METHOD0(Run, void());
139
140 private:
141 TestGpuScheduler* scheduler_;
142 GpuStreamPriority priority_;
143 bool can_run_;
144 base::TimeDelta poll_duration_;
145 };
146
147 class GpuSchedulerTest : public testing::Test {
148 public:
149 GpuSchedulerTest()
150 : task_runner_(new TestTaskRunner),
151 scheduler_(TestGpuScheduler::Create(task_runner_)) {}
152 ~GpuSchedulerTest() override {}
153
154 protected:
155 scoped_refptr<TestTaskRunner> task_runner_;
156 std::unique_ptr<TestGpuScheduler> scheduler_;
157 };
158
159 TEST_F(GpuSchedulerTest, SingleStream) {
160 StrictMock<MockGpuCommandStream> stream(scheduler_.get(),
161 GpuStreamPriority::NORMAL);
162 scheduler_->AddStream(&stream);
163 stream.set_can_run(true);
164 scheduler_->OnStreamCanRun(&stream);
165 for (int i = 0; i < 5; ++i) {
166 EXPECT_CALL(stream, Run());
167 scheduler_->RunPendingTasks();
168 }
169 }
170
171 TEST_F(GpuSchedulerTest, CanRun) {
172 StrictMock<MockGpuCommandStream> stream(scheduler_.get(),
173 GpuStreamPriority::NORMAL);
174 scheduler_->AddStream(&stream);
175 stream.set_can_run(true);
176 scheduler_->OnStreamCanRun(&stream);
177 for (int i = 0; i < 5; ++i) {
178 EXPECT_CALL(stream, Run());
179 scheduler_->RunPendingTasks();
180 }
181 EXPECT_CALL(stream, Run())
182 .WillOnce(Invoke(CreateFunctor(&MockGpuCommandStream::set_can_run,
183 base::Unretained(&stream), false)));
184 scheduler_->RunPendingTasks();
185 // No more Run.
186 scheduler_->RunPendingTasks();
187 }
188
189 TEST_F(GpuSchedulerTest, MultipleStreams) {
190 StrictMock<MockGpuCommandStream> stream1(scheduler_.get(),
191 GpuStreamPriority::LOW);
192 scheduler_->AddStream(&stream1);
193 stream1.set_can_run(true);
194 scheduler_->OnStreamCanRun(&stream1);
195
196 StrictMock<MockGpuCommandStream> stream2(scheduler_.get(),
197 GpuStreamPriority::NORMAL);
198 scheduler_->AddStream(&stream2);
199 stream2.set_can_run(true);
200 scheduler_->OnStreamCanRun(&stream2);
201
202 for (int i = 0; i < 5; ++i) {
203 EXPECT_CALL(stream2, Run());
204 scheduler_->RunPendingTasks();
205 EXPECT_CALL(stream1, Run());
206 scheduler_->RunPendingTasks();
207 }
208 }
209
210 TEST_F(GpuSchedulerTest, Timeslice) {
211 StrictMock<MockGpuCommandStream> stream(scheduler_.get(),
212 GpuStreamPriority::NORMAL);
213 scheduler_->AddStream(&stream);
214 stream.set_can_run(true);
215 scheduler_->OnStreamCanRun(&stream);
216
217 stream.EnablePolling();
218 EXPECT_CALL(stream, Run());
219 scheduler_->RunPendingTasks();
220 EXPECT_EQ(kTimeSliceNormal, stream.poll_duration());
221 }
222
223 TEST_F(GpuSchedulerTest, Preemption) {
224 StrictMock<MockGpuCommandStream> stream1(scheduler_.get(),
225 GpuStreamPriority::NORMAL);
226 scheduler_->AddStream(&stream1);
227 stream1.set_can_run(true);
228 scheduler_->OnStreamCanRun(&stream1);
229
230 StrictMock<MockGpuCommandStream> stream2(scheduler_.get(),
231 GpuStreamPriority::REAL_TIME);
232 scheduler_->AddStream(&stream2);
233 stream2.set_can_run(true);
234
235 auto kRealTimeRunnableDelay = base::TimeDelta::FromMicroseconds(2500);
236 task_runner_->PostDelayedTask(FROM_HERE,
237 base::Bind(&TestGpuScheduler::OnStreamCanRun,
238 base::Unretained(scheduler_.get()),
239 base::Unretained(&stream2)),
240 kRealTimeRunnableDelay);
241
242 stream1.EnablePolling();
243 EXPECT_CALL(stream1, Run());
244 scheduler_->RunPendingTasks();
245 EXPECT_EQ(kRealTimeRunnableDelay + kSchedulerPollingInterval,
246 stream1.poll_duration());
247 }
248
249 TEST_F(GpuSchedulerTest, RemoveWhileRunning) {
250 StrictMock<MockGpuCommandStream> stream(scheduler_.get(),
251 GpuStreamPriority::NORMAL);
252 scheduler_->AddStream(&stream);
253 stream.set_can_run(true);
254 scheduler_->OnStreamCanRun(&stream);
255
256 EXPECT_CALL(stream, Run())
257 .WillOnce(Invoke(CreateFunctor(&TestGpuScheduler::RemoveStream,
258 base::Unretained(scheduler_.get()),
259 base::Unretained(&stream))));
260 scheduler_->RunPendingTasks();
261 // No more Run.
262 scheduler_->RunPendingTasks();
263 }
264
265 TEST_F(GpuSchedulerTest, PriorityInversion) {
266 StrictMock<MockGpuCommandStream> stream1(scheduler_.get(),
267 GpuStreamPriority::REAL_TIME);
268 scheduler_->AddStream(&stream1);
269 stream1.set_can_run(true);
270 scheduler_->OnStreamCanRun(&stream1);
271
272 StrictMock<MockGpuCommandStream> stream2(scheduler_.get(),
273 GpuStreamPriority::NORMAL);
274 scheduler_->AddStream(&stream2);
275 stream2.set_can_run(true);
276 scheduler_->OnStreamCanRun(&stream2);
277
278 StrictMock<MockGpuCommandStream> stream3(scheduler_.get(),
279 GpuStreamPriority::LOW);
280 scheduler_->AddStream(&stream3);
281 stream3.set_can_run(true);
282 scheduler_->OnStreamCanRun(&stream3);
283
284 EXPECT_CALL(stream1, Run())
285 .WillOnce(Invoke(CreateFunctor(&TestGpuScheduler::AddStreamDependency,
286 base::Unretained(scheduler_.get()),
287 base::Unretained(&stream3),
288 base::Unretained(&stream1))));
289 scheduler_->RunPendingTasks();
290
291 EXPECT_CALL(stream3, Run())
292 .WillOnce(Invoke(CreateFunctor(&TestGpuScheduler::RemoveStreamDependency,
293 base::Unretained(scheduler_.get()),
294 base::Unretained(&stream3),
295 base::Unretained(&stream1))));
296 scheduler_->RunPendingTasks();
297
298 EXPECT_CALL(stream2, Run());
299 scheduler_->RunPendingTasks();
300
301 EXPECT_CALL(stream3, Run());
302 scheduler_->RunPendingTasks();
303
304 EXPECT_CALL(stream1, Run());
305 scheduler_->RunPendingTasks();
306 }
307
308 } // namespace
309 } // namespace gpu
OLDNEW
« no previous file with comments | « gpu/ipc/service/gpu_scheduler.cc ('k') | ppapi/proxy/ppapi_command_buffer_proxy.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698