1 // Copyright 2014 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 <stdint.h>
6
7 #include "base/bind.h"
8 #include "gpu/command_buffer/client/client_test_helper.h"
9 #include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h"
10 #include "gpu/command_buffer/service/gpu_service_test.h"
11 #include "gpu/command_buffer/service/gpu_tracer.h"
12 #include "testing/gtest/include/gtest/gtest.h"
13 #include "ui/gl/gl_context.h"
14 #include "ui/gl/gl_mock.h"
15 #include "ui/gl/gpu_timing.h"
16 #include "ui/gl/gpu_timing_fake.h"
17
18 namespace gpu {
19 namespace gles2 {
20 namespace {
21
22 using ::testing::_;
23 using ::testing::AtMost;
24 using ::testing::Exactly;
25 using ::testing::Invoke;
26 using ::testing::Return;
27
28 int64_t g_fakeCPUTime = 0;
FakeCpuTime()29 int64_t FakeCpuTime() {
30 return g_fakeCPUTime;
31 }
32
33 class MockOutputter : public Outputter {
34 public:
35 MockOutputter() = default;
36 ~MockOutputter() override = default;
37
38 MOCK_METHOD5(TraceDevice,
39 void(GpuTracerSource source,
40 const std::string& category,
41 const std::string& name,
42 int64_t start_time,
43 int64_t end_time));
44 MOCK_METHOD3(TraceServiceBegin,
45 void(GpuTracerSource source,
46 const std::string& category, const std::string& name));
47 MOCK_METHOD3(TraceServiceEnd,
48 void(GpuTracerSource source,
49 const std::string& category, const std::string& name));
50 };
51
52 class GPUTracerTester : public GPUTracer {
53 public:
GPUTracerTester(GLES2Decoder * decoder)54 explicit GPUTracerTester(GLES2Decoder* decoder)
55 : GPUTracer(decoder), tracing_enabled_(0) {
56 gpu_timing_client_->SetCpuTimeForTesting(base::BindRepeating(&FakeCpuTime));
57
58 // Force tracing to be dependent on our mock variable here.
59 gpu_trace_srv_category_ = &tracing_enabled_;
60 gpu_trace_dev_category_ = &tracing_enabled_;
61 }
62
63 ~GPUTracerTester() override = default;
64
SetTracingEnabled(bool enabled)65 void SetTracingEnabled(bool enabled) {
66 tracing_enabled_ = enabled ? 1 : 0;
67 }
68
69 private:
70 unsigned char tracing_enabled_;
71 };
72
73 class BaseGpuTest : public GpuServiceTest {
74 public:
BaseGpuTest(gl::GPUTiming::TimerType test_timer_type)75 explicit BaseGpuTest(gl::GPUTiming::TimerType test_timer_type)
76 : test_timer_type_(test_timer_type) {}
77
78 protected:
SetUp()79 void SetUp() override {
80 g_fakeCPUTime = 0;
81 const char* gl_version = "3.2";
82 const char* extensions = "";
83 if (GetTimerType() == gl::GPUTiming::kTimerTypeEXT) {
84 gl_version = "2.1";
85 extensions = "GL_EXT_timer_query";
86 } else if (GetTimerType() == gl::GPUTiming::kTimerTypeDisjoint) {
87 gl_version = "OpenGL ES 3.0";
88 extensions = "GL_EXT_disjoint_timer_query";
89 } else if (GetTimerType() == gl::GPUTiming::kTimerTypeARB) {
90 // TODO(sievers): The tracer should not depend on ARB_occlusion_query.
91 // Try merge Query APIs (core, ARB, EXT) into a single binding each.
92 extensions = "GL_ARB_timer_query GL_ARB_occlusion_query";
93 }
94 GpuServiceTest::SetUpWithGLVersion(gl_version, extensions);
95
96 // Disjoint check should only be called by kTracerTypeDisjointTimer type.
97 if (GetTimerType() == gl::GPUTiming::kTimerTypeDisjoint)
98 gl_fake_queries_.ExpectDisjointCalls(*gl_);
99 else
100 gl_fake_queries_.ExpectNoDisjointCalls(*gl_);
101
102 gpu_timing_client_ = GetGLContext()->CreateGPUTimingClient();
103 gpu_timing_client_->SetCpuTimeForTesting(base::BindRepeating(&FakeCpuTime));
104 gl_fake_queries_.Reset();
105 }
106
TearDown()107 void TearDown() override {
108 gpu_timing_client_ = nullptr;
109 gl_fake_queries_.Reset();
110 GpuServiceTest::TearDown();
111 }
112
ExpectTraceQueryMocks()113 void ExpectTraceQueryMocks() {
114 if (gpu_timing_client_->IsAvailable()) {
115 // Delegate query APIs used by GPUTrace to a GlFakeQueries
116 const bool elapsed = (GetTimerType() == gl::GPUTiming::kTimerTypeEXT);
117 gl_fake_queries_.ExpectGPUTimerQuery(*gl_, elapsed);
118 }
119 }
120
ExpectOutputterBeginMocks(MockOutputter * outputter,GpuTracerSource source,const std::string & category,const std::string & name)121 void ExpectOutputterBeginMocks(MockOutputter* outputter,
122 GpuTracerSource source,
123 const std::string& category,
124 const std::string& name) {
125 EXPECT_CALL(*outputter,
126 TraceServiceBegin(source, category, name));
127 }
128
ExpectOutputterEndMocks(MockOutputter * outputter,GpuTracerSource source,const std::string & category,const std::string & name,int64_t expect_start_time,int64_t expect_end_time,bool trace_service,bool trace_device)129 void ExpectOutputterEndMocks(MockOutputter* outputter,
130 GpuTracerSource source,
131 const std::string& category,
132 const std::string& name,
133 int64_t expect_start_time,
134 int64_t expect_end_time,
135 bool trace_service,
136 bool trace_device) {
137 if (trace_service) {
138 EXPECT_CALL(*outputter,
139 TraceServiceEnd(source, category, name));
140 }
141
142 if (trace_device) {
143 EXPECT_CALL(*outputter,
144 TraceDevice(source, category, name,
145 expect_start_time, expect_end_time))
146 .Times(Exactly(1));
147 } else {
148 EXPECT_CALL(*outputter, TraceDevice(source, category, name,
149 expect_start_time, expect_end_time))
150 .Times(Exactly(0));
151 }
152 }
153
ExpectDisjointOutputMocks(MockOutputter * outputter,int64_t expect_start_time,int64_t expect_end_time)154 void ExpectDisjointOutputMocks(MockOutputter* outputter,
155 int64_t expect_start_time,
156 int64_t expect_end_time) {
157 EXPECT_CALL(*outputter,
158 TraceDevice(kTraceDisjoint, "DisjointEvent", _,
159 expect_start_time, expect_end_time))
160 .Times(Exactly(1));
161 }
162
ExpectNoDisjointOutputMocks(MockOutputter * outputter)163 void ExpectNoDisjointOutputMocks(MockOutputter* outputter) {
164 EXPECT_CALL(*outputter,
165 TraceDevice(kTraceDisjoint, "DisjointEvent", _, _, _))
166 .Times(Exactly(0));
167 }
168
ExpectOutputterMocks(MockOutputter * outputter,bool tracing_service,bool tracing_device,GpuTracerSource source,const std::string & category,const std::string & name,int64_t expect_start_time,int64_t expect_end_time)169 void ExpectOutputterMocks(MockOutputter* outputter,
170 bool tracing_service,
171 bool tracing_device,
172 GpuTracerSource source,
173 const std::string& category,
174 const std::string& name,
175 int64_t expect_start_time,
176 int64_t expect_end_time) {
177 if (tracing_service)
178 ExpectOutputterBeginMocks(outputter, source, category, name);
179 const bool valid_timer = tracing_device &&
180 gpu_timing_client_->IsAvailable();
181 ExpectOutputterEndMocks(outputter, source, category, name,
182 expect_start_time, expect_end_time,
183 tracing_service, valid_timer);
184 }
185
ExpectTracerOffsetQueryMocks()186 void ExpectTracerOffsetQueryMocks() {
187 if (GetTimerType() != gl::GPUTiming::kTimerTypeARB) {
188 gl_fake_queries_.ExpectNoOffsetCalculationQuery(*gl_);
189 } else {
190 gl_fake_queries_.ExpectOffsetCalculationQuery(*gl_);
191 }
192 }
193
GetTimerType()194 gl::GPUTiming::TimerType GetTimerType() { return test_timer_type_; }
195
196 gl::GPUTiming::TimerType test_timer_type_;
197 gl::GPUTimingFake gl_fake_queries_;
198
199 scoped_refptr<gl::GPUTimingClient> gpu_timing_client_;
200 MockOutputter outputter_;
201 };
202
203 // Test GPUTrace calls all the correct gl calls.
204 class BaseGpuTraceTest : public BaseGpuTest {
205 public:
BaseGpuTraceTest(gl::GPUTiming::TimerType test_timer_type)206 explicit BaseGpuTraceTest(gl::GPUTiming::TimerType test_timer_type)
207 : BaseGpuTest(test_timer_type) {}
208
DoTraceTest(bool tracing_service,bool tracing_device)209 void DoTraceTest(bool tracing_service, bool tracing_device) {
210 // Expected results
211 const GpuTracerSource tracer_source = kTraceCHROMIUM;
212 const std::string category_name("trace_category");
213 const std::string trace_name("trace_test");
214 const int64_t offset_time = 3231;
215 const GLint64 start_timestamp = 7 * base::Time::kNanosecondsPerMicrosecond;
216 const GLint64 end_timestamp = 32 * base::Time::kNanosecondsPerMicrosecond;
217 const int64_t expect_start_time =
218 (start_timestamp / base::Time::kNanosecondsPerMicrosecond) +
219 offset_time;
220 const int64_t expect_end_time =
221 (end_timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_time;
222
223 ExpectOutputterMocks(&outputter_, tracing_service, tracing_device,
224 tracer_source, category_name, trace_name,
225 expect_start_time, expect_end_time);
226
227 if (tracing_device)
228 ExpectTraceQueryMocks();
229
230 scoped_refptr<GPUTrace> trace = new GPUTrace(
231 &outputter_, gpu_timing_client_.get(), tracer_source, category_name,
232 trace_name, tracing_service, tracing_device);
233
234 gl_fake_queries_.SetCurrentGLTime(start_timestamp);
235 g_fakeCPUTime = expect_start_time;
236 trace->Start();
237
238 // Shouldn't be available before End() call
239 gl_fake_queries_.SetCurrentGLTime(end_timestamp);
240 g_fakeCPUTime = expect_end_time;
241 if (tracing_device)
242 EXPECT_FALSE(trace->IsAvailable());
243
244 trace->End();
245
246 // Shouldn't be available until the queries complete
247 gl_fake_queries_.SetCurrentGLTime(end_timestamp -
248 base::Time::kNanosecondsPerMicrosecond);
249 g_fakeCPUTime = expect_end_time - 1;
250 if (tracing_device)
251 EXPECT_FALSE(trace->IsAvailable());
252
253 // Now it should be available
254 gl_fake_queries_.SetCurrentGLTime(end_timestamp);
255 g_fakeCPUTime = expect_end_time;
256 EXPECT_TRUE(trace->IsAvailable());
257
258 // Process should output expected Trace results to MockOutputter
259 trace->Process();
260
261 // Destroy trace after we are done.
262 trace->Destroy(true);
263 }
264 };
265
266 class GpuARBTimerTraceTest : public BaseGpuTraceTest {
267 public:
GpuARBTimerTraceTest()268 GpuARBTimerTraceTest() : BaseGpuTraceTest(gl::GPUTiming::kTimerTypeARB) {}
269 };
270
271 class GpuDisjointTimerTraceTest : public BaseGpuTraceTest {
272 public:
GpuDisjointTimerTraceTest()273 GpuDisjointTimerTraceTest()
274 : BaseGpuTraceTest(gl::GPUTiming::kTimerTypeDisjoint) {}
275 };
276
TEST_F(GpuARBTimerTraceTest,ARBTimerTraceTestOff)277 TEST_F(GpuARBTimerTraceTest, ARBTimerTraceTestOff) {
278 DoTraceTest(false, false);
279 }
280
TEST_F(GpuARBTimerTraceTest,ARBTimerTraceTestServiceOnly)281 TEST_F(GpuARBTimerTraceTest, ARBTimerTraceTestServiceOnly) {
282 DoTraceTest(true, false);
283 }
284
TEST_F(GpuARBTimerTraceTest,ARBTimerTraceTestDeviceOnly)285 TEST_F(GpuARBTimerTraceTest, ARBTimerTraceTestDeviceOnly) {
286 DoTraceTest(false, true);
287 }
288
TEST_F(GpuARBTimerTraceTest,ARBTimerTraceTestBothOn)289 TEST_F(GpuARBTimerTraceTest, ARBTimerTraceTestBothOn) {
290 DoTraceTest(true, true);
291 }
292
TEST_F(GpuDisjointTimerTraceTest,DisjointTimerTraceTestOff)293 TEST_F(GpuDisjointTimerTraceTest, DisjointTimerTraceTestOff) {
294 DoTraceTest(false, false);
295 }
296
TEST_F(GpuDisjointTimerTraceTest,DisjointTimerTraceTestServiceOnly)297 TEST_F(GpuDisjointTimerTraceTest, DisjointTimerTraceTestServiceOnly) {
298 DoTraceTest(true, false);
299 }
300
TEST_F(GpuDisjointTimerTraceTest,DisjointTimerTraceTestDeviceOnly)301 TEST_F(GpuDisjointTimerTraceTest, DisjointTimerTraceTestDeviceOnly) {
302 DoTraceTest(false, true);
303 }
304
TEST_F(GpuDisjointTimerTraceTest,DisjointTimerTraceTestBothOn)305 TEST_F(GpuDisjointTimerTraceTest, DisjointTimerTraceTestBothOn) {
306 DoTraceTest(true, true);
307 }
308
309 // Test GPUTracer calls all the correct gl calls.
310 class BaseGpuTracerTest : public BaseGpuTest {
311 public:
BaseGpuTracerTest(gl::GPUTiming::TimerType test_timer_type)312 explicit BaseGpuTracerTest(gl::GPUTiming::TimerType test_timer_type)
313 : BaseGpuTest(test_timer_type) {}
314
DoBasicTracerTest()315 void DoBasicTracerTest() {
316 ExpectTracerOffsetQueryMocks();
317
318 FakeCommandBufferServiceBase command_buffer_service;
319 FakeDecoderClient client;
320 MockOutputter outputter;
321 MockGLES2Decoder decoder(&client, &command_buffer_service, &outputter);
322 EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext()));
323 GPUTracerTester tracer(&decoder);
324 tracer.SetTracingEnabled(true);
325
326 ASSERT_TRUE(tracer.BeginDecoding());
327 ASSERT_TRUE(tracer.EndDecoding());
328 }
329
DoDisabledTracingTest()330 void DoDisabledTracingTest() {
331 ExpectTracerOffsetQueryMocks();
332
333 const GpuTracerSource source = static_cast<GpuTracerSource>(0);
334
335 FakeCommandBufferServiceBase command_buffer_service;
336 FakeDecoderClient client;
337 MockOutputter outputter;
338 MockGLES2Decoder decoder(&client, &command_buffer_service, &outputter);
339 EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext()));
340 GPUTracerTester tracer(&decoder);
341 tracer.SetTracingEnabled(false);
342
343 ASSERT_TRUE(tracer.BeginDecoding());
344 ASSERT_TRUE(tracer.Begin("disabled_category", "disabled_name", source));
345 ASSERT_TRUE(tracer.End(source));
346 ASSERT_TRUE(tracer.EndDecoding());
347 }
348
DoTracerMarkersTest()349 void DoTracerMarkersTest() {
350 ExpectTracerOffsetQueryMocks();
351 gl_fake_queries_.ExpectGetErrorCalls(*gl_);
352
353 const std::string category_name("trace_category");
354 const std::string trace_name("trace_test");
355 const int64_t offset_time = 3231;
356 const GLint64 start_timestamp = 7 * base::Time::kNanosecondsPerMicrosecond;
357 const GLint64 end_timestamp = 32 * base::Time::kNanosecondsPerMicrosecond;
358 const int64_t expect_start_time =
359 (start_timestamp / base::Time::kNanosecondsPerMicrosecond) +
360 offset_time;
361 const int64_t expect_end_time =
362 (end_timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_time;
363
364 FakeCommandBufferServiceBase command_buffer_service;
365 FakeDecoderClient client;
366 MockOutputter outputter;
367 MockGLES2Decoder decoder(&client, &command_buffer_service, &outputter);
368 EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext()));
369 GPUTracerTester tracer(&decoder);
370 tracer.SetTracingEnabled(true);
371
372 gl_fake_queries_.SetCurrentGLTime(start_timestamp);
373 g_fakeCPUTime = expect_start_time;
374
375 ASSERT_TRUE(tracer.BeginDecoding());
376
377 ExpectTraceQueryMocks();
378
379 // This will test multiple marker sources which overlap one another.
380 for (int i = 0; i < NUM_TRACER_SOURCES; ++i) {
381 // Set times so each source has a different time.
382 gl_fake_queries_.SetCurrentGLTime(
383 start_timestamp +
384 (i * base::Time::kNanosecondsPerMicrosecond));
385 g_fakeCPUTime = expect_start_time + i;
386
387 // Each trace name should be different to differentiate.
388 const char num_char = static_cast<char>('0' + i);
389 std::string source_category = category_name + num_char;
390 std::string source_trace_name = trace_name + num_char;
391
392 const GpuTracerSource source = static_cast<GpuTracerSource>(i);
393 ExpectOutputterBeginMocks(&outputter, source, source_category,
394 source_trace_name);
395 ASSERT_TRUE(tracer.Begin(source_category, source_trace_name, source));
396 }
397 for (int i = 0; i < NUM_TRACER_SOURCES; ++i) {
398 // Set times so each source has a different time.
399 gl_fake_queries_.SetCurrentGLTime(
400 end_timestamp +
401 (i * base::Time::kNanosecondsPerMicrosecond));
402 g_fakeCPUTime = expect_end_time + i;
403
404 // Each trace name should be different to differentiate.
405 const char num_char = static_cast<char>('0' + i);
406 std::string source_category = category_name + num_char;
407 std::string source_trace_name = trace_name + num_char;
408
409 const bool valid_timer = gpu_timing_client_->IsAvailable();
410 const GpuTracerSource source = static_cast<GpuTracerSource>(i);
411 ExpectOutputterEndMocks(&outputter, source, source_category,
412 source_trace_name, expect_start_time + i,
413 expect_end_time + i, true, valid_timer);
414 // Check if the current category/name are correct for this source.
415 ASSERT_EQ(source_category, tracer.CurrentCategory(source));
416 ASSERT_EQ(source_trace_name, tracer.CurrentName(source));
417
418 ASSERT_TRUE(tracer.End(source));
419 }
420 ASSERT_TRUE(tracer.EndDecoding());
421 tracer.ProcessTraces();
422 }
423
DoOngoingTracerMarkerTest()424 void DoOngoingTracerMarkerTest() {
425 ExpectTracerOffsetQueryMocks();
426 gl_fake_queries_.ExpectGetErrorCalls(*gl_);
427
428 const std::string category_name("trace_category");
429 const std::string trace_name("trace_test");
430 const GpuTracerSource source = static_cast<GpuTracerSource>(0);
431 const int64_t offset_time = 3231;
432 const GLint64 start_timestamp = 7 * base::Time::kNanosecondsPerMicrosecond;
433 const int64_t expect_start_time =
434 (start_timestamp / base::Time::kNanosecondsPerMicrosecond) +
435 offset_time;
436 const bool valid_timer = gpu_timing_client_->IsAvailable();
437
438 FakeCommandBufferServiceBase command_buffer_service;
439 FakeDecoderClient client;
440 MockOutputter outputter;
441 MockGLES2Decoder decoder(&client, &command_buffer_service, &outputter);
442 EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext()));
443 GPUTracerTester tracer(&decoder);
444
445 // Create trace marker while traces are disabled.
446 gl_fake_queries_.SetCurrentGLTime(start_timestamp);
447 g_fakeCPUTime = expect_start_time;
448
449 tracer.SetTracingEnabled(false);
450 ASSERT_TRUE(tracer.BeginDecoding());
451 ASSERT_TRUE(tracer.Begin(category_name, trace_name, source));
452 ASSERT_TRUE(tracer.EndDecoding());
453
454 // Enable traces now.
455 tracer.SetTracingEnabled(true);
456 ExpectTraceQueryMocks();
457
458 // trace should happen when decoding begins, at time start+1.
459 gl_fake_queries_.SetCurrentGLTime(
460 start_timestamp +
461 (1 * base::Time::kNanosecondsPerMicrosecond));
462 g_fakeCPUTime = expect_start_time + 1;
463 ASSERT_TRUE(tracer.BeginDecoding());
464
465 // End decoding at time start+2.
466 ExpectOutputterEndMocks(&outputter, source, category_name, trace_name,
467 expect_start_time + 1, expect_start_time + 2, true,
468 valid_timer);
469 gl_fake_queries_.SetCurrentGLTime(
470 start_timestamp +
471 (2 * base::Time::kNanosecondsPerMicrosecond));
472 g_fakeCPUTime = expect_start_time + 2;
473 ASSERT_TRUE(tracer.EndDecoding());
474
475 // Begin decoding again at time start+3.
476 gl_fake_queries_.SetCurrentGLTime(
477 start_timestamp +
478 (3 * base::Time::kNanosecondsPerMicrosecond));
479 g_fakeCPUTime = expect_start_time + 3;
480 ASSERT_TRUE(tracer.BeginDecoding());
481
482 // End trace at time start+4
483 gl_fake_queries_.SetCurrentGLTime(
484 start_timestamp +
485 (4 * base::Time::kNanosecondsPerMicrosecond));
486 g_fakeCPUTime = expect_start_time + 4;
487 ExpectOutputterEndMocks(&outputter, source, category_name, trace_name,
488 expect_start_time + 3, expect_start_time + 4, true,
489 valid_timer);
490 ASSERT_TRUE(tracer.End(source));
491
492 // Increment time before we end decoding to test trace does not stop here.
493 gl_fake_queries_.SetCurrentGLTime(
494 start_timestamp +
495 (5 * base::Time::kNanosecondsPerMicrosecond));
496 g_fakeCPUTime = expect_start_time + 5;
497 ASSERT_TRUE(tracer.EndDecoding());
498 tracer.ProcessTraces();
499 }
500
DoDisjointTest()501 void DoDisjointTest() {
502 // Cause a disjoint in a middle of a trace and expect no output calls.
503 ExpectTracerOffsetQueryMocks();
504 gl_fake_queries_.ExpectGetErrorCalls(*gl_);
505
506 const std::string category_name("trace_category");
507 const std::string trace_name("trace_test");
508 const GpuTracerSource source = static_cast<GpuTracerSource>(0);
509 const int64_t offset_time = 3231;
510 const GLint64 start_timestamp = 7 * base::Time::kNanosecondsPerMicrosecond;
511 const GLint64 end_timestamp = 32 * base::Time::kNanosecondsPerMicrosecond;
512 const int64_t expect_start_time =
513 (start_timestamp / base::Time::kNanosecondsPerMicrosecond) +
514 offset_time;
515 const int64_t expect_end_time =
516 (end_timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_time;
517
518 FakeCommandBufferServiceBase command_buffer_service;
519 FakeDecoderClient client;
520 MockOutputter outputter;
521 MockGLES2Decoder decoder(&client, &command_buffer_service, &outputter);
522 EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext()));
523 GPUTracerTester tracer(&decoder);
524 tracer.SetTracingEnabled(true);
525
526 gl_fake_queries_.SetCurrentGLTime(start_timestamp);
527 g_fakeCPUTime = expect_start_time;
528
529 ASSERT_TRUE(tracer.BeginDecoding());
530
531 ExpectTraceQueryMocks();
532
533 ExpectOutputterBeginMocks(&outputter, source, category_name, trace_name);
534 ASSERT_TRUE(tracer.Begin(category_name, trace_name, source));
535
536 gl_fake_queries_.SetCurrentGLTime(end_timestamp);
537 g_fakeCPUTime = expect_end_time;
538
539 // Create GPUTimingClient to make sure disjoint value is correct. This
540 // should not interfere with the tracer's disjoint value.
541 scoped_refptr<gl::GPUTimingClient> disjoint_client =
542 GetGLContext()->CreateGPUTimingClient();
543
544 // We assert here based on the disjoint_client because if disjoints are not
545 // working properly there is no point testing the tracer output.
546 ASSERT_FALSE(disjoint_client->CheckAndResetTimerErrors());
547 gl_fake_queries_.SetDisjoint();
548 ASSERT_TRUE(disjoint_client->CheckAndResetTimerErrors());
549
550 ExpectDisjointOutputMocks(&outputter, expect_start_time, expect_end_time);
551
552 ExpectOutputterEndMocks(&outputter, source, category_name, trace_name,
553 expect_start_time, expect_end_time, true, false);
554
555 ASSERT_TRUE(tracer.End(source));
556 ASSERT_TRUE(tracer.EndDecoding());
557 tracer.ProcessTraces();
558 }
559
DoOutsideDisjointTest()560 void DoOutsideDisjointTest() {
561 ExpectTracerOffsetQueryMocks();
562 gl_fake_queries_.ExpectGetErrorCalls(*gl_);
563
564 const std::string category_name("trace_category");
565 const std::string trace_name("trace_test");
566 const GpuTracerSource source = static_cast<GpuTracerSource>(0);
567 const int64_t offset_time = 3231;
568 const GLint64 start_timestamp = 7 * base::Time::kNanosecondsPerMicrosecond;
569 const GLint64 end_timestamp = 32 * base::Time::kNanosecondsPerMicrosecond;
570 const int64_t expect_start_time =
571 (start_timestamp / base::Time::kNanosecondsPerMicrosecond) +
572 offset_time;
573 const int64_t expect_end_time =
574 (end_timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_time;
575
576 FakeCommandBufferServiceBase command_buffer_service;
577 FakeDecoderClient client;
578 MockOutputter outputter;
579 MockGLES2Decoder decoder(&client, &command_buffer_service, &outputter);
580 EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext()));
581 EXPECT_CALL(decoder, MakeCurrent()).WillRepeatedly(Return(true));
582 GPUTracerTester tracer(&decoder);
583
584 // Start a trace before tracing is enabled.
585 tracer.SetTracingEnabled(false);
586 ASSERT_TRUE(tracer.BeginDecoding());
587 ASSERT_TRUE(tracer.Begin(category_name, trace_name, source));
588 ASSERT_TRUE(tracer.EndDecoding());
589
590 // Enabling traces now, trace should be ongoing.
591 tracer.SetTracingEnabled(true);
592 gl_fake_queries_.SetCurrentGLTime(start_timestamp);
593 g_fakeCPUTime = expect_start_time;
594
595 // Disjoints before we start tracing anything should not do anything.
596 ExpectNoDisjointOutputMocks(&outputter);
597 gl_fake_queries_.SetDisjoint();
598
599 ExpectTraceQueryMocks();
600 ExpectOutputterBeginMocks(&outputter, source, category_name, trace_name);
601 ASSERT_TRUE(tracer.BeginDecoding());
602
603 // Set times so each source has a different time.
604 gl_fake_queries_.SetCurrentGLTime(end_timestamp);
605 g_fakeCPUTime = expect_end_time;
606
607 ExpectOutputterEndMocks(&outputter, source, category_name, trace_name,
608 expect_start_time, expect_end_time, true, true);
609
610 ASSERT_TRUE(tracer.End(source));
611 ASSERT_TRUE(tracer.EndDecoding());
612 tracer.ProcessTraces();
613 }
614 };
615
616 class InvalidTimerTracerTest : public BaseGpuTracerTest {
617 public:
InvalidTimerTracerTest()618 InvalidTimerTracerTest()
619 : BaseGpuTracerTest(gl::GPUTiming::kTimerTypeInvalid) {}
620 };
621
622 class GpuEXTTimerTracerTest : public BaseGpuTracerTest {
623 public:
GpuEXTTimerTracerTest()624 GpuEXTTimerTracerTest() : BaseGpuTracerTest(gl::GPUTiming::kTimerTypeEXT) {}
625 };
626
627 class GpuARBTimerTracerTest : public BaseGpuTracerTest {
628 public:
GpuARBTimerTracerTest()629 GpuARBTimerTracerTest() : BaseGpuTracerTest(gl::GPUTiming::kTimerTypeARB) {}
630 };
631
632 class GpuDisjointTimerTracerTest : public BaseGpuTracerTest {
633 public:
GpuDisjointTimerTracerTest()634 GpuDisjointTimerTracerTest()
635 : BaseGpuTracerTest(gl::GPUTiming::kTimerTypeDisjoint) {}
636 };
637
TEST_F(InvalidTimerTracerTest,InvalidTimerBasicTracerTest)638 TEST_F(InvalidTimerTracerTest, InvalidTimerBasicTracerTest) {
639 DoBasicTracerTest();
640 }
641
TEST_F(GpuEXTTimerTracerTest,EXTTimerBasicTracerTest)642 TEST_F(GpuEXTTimerTracerTest, EXTTimerBasicTracerTest) {
643 DoBasicTracerTest();
644 }
645
TEST_F(GpuARBTimerTracerTest,ARBTimerBasicTracerTest)646 TEST_F(GpuARBTimerTracerTest, ARBTimerBasicTracerTest) {
647 DoBasicTracerTest();
648 }
649
TEST_F(GpuDisjointTimerTracerTest,DisjointTimerBasicTracerTest)650 TEST_F(GpuDisjointTimerTracerTest, DisjointTimerBasicTracerTest) {
651 DoBasicTracerTest();
652 }
653
TEST_F(InvalidTimerTracerTest,InvalidTimerDisabledTest)654 TEST_F(InvalidTimerTracerTest, InvalidTimerDisabledTest) {
655 DoDisabledTracingTest();
656 }
657
TEST_F(GpuEXTTimerTracerTest,EXTTimerDisabledTest)658 TEST_F(GpuEXTTimerTracerTest, EXTTimerDisabledTest) {
659 DoDisabledTracingTest();
660 }
661
TEST_F(GpuARBTimerTracerTest,ARBTimerDisabledTest)662 TEST_F(GpuARBTimerTracerTest, ARBTimerDisabledTest) {
663 DoDisabledTracingTest();
664 }
665
TEST_F(GpuDisjointTimerTracerTest,DisjointTimerDisabledTest)666 TEST_F(GpuDisjointTimerTracerTest, DisjointTimerDisabledTest) {
667 DoDisabledTracingTest();
668 }
669
TEST_F(InvalidTimerTracerTest,InvalidTimerTracerMarkersTest)670 TEST_F(InvalidTimerTracerTest, InvalidTimerTracerMarkersTest) {
671 DoTracerMarkersTest();
672 }
673
TEST_F(GpuEXTTimerTracerTest,EXTTimerTracerMarkersTest)674 TEST_F(GpuEXTTimerTracerTest, EXTTimerTracerMarkersTest) {
675 DoTracerMarkersTest();
676 }
677
TEST_F(GpuARBTimerTracerTest,ARBTimerTracerMarkersTest)678 TEST_F(GpuARBTimerTracerTest, ARBTimerTracerMarkersTest) {
679 DoTracerMarkersTest();
680 }
681
TEST_F(GpuDisjointTimerTracerTest,DisjointTimerBasicTracerMarkersTest)682 TEST_F(GpuDisjointTimerTracerTest, DisjointTimerBasicTracerMarkersTest) {
683 DoTracerMarkersTest();
684 }
685
TEST_F(InvalidTimerTracerTest,InvalidTimerOngoingTracerMarkersTest)686 TEST_F(InvalidTimerTracerTest, InvalidTimerOngoingTracerMarkersTest) {
687 DoOngoingTracerMarkerTest();
688 }
689
TEST_F(GpuEXTTimerTracerTest,EXTTimerOngoingTracerMarkersTest)690 TEST_F(GpuEXTTimerTracerTest, EXTTimerOngoingTracerMarkersTest) {
691 DoOngoingTracerMarkerTest();
692 }
693
TEST_F(GpuARBTimerTracerTest,ARBTimerBasicOngoingTracerMarkersTest)694 TEST_F(GpuARBTimerTracerTest, ARBTimerBasicOngoingTracerMarkersTest) {
695 DoOngoingTracerMarkerTest();
696 }
697
TEST_F(GpuDisjointTimerTracerTest,DisjointTimerOngoingTracerMarkersTest)698 TEST_F(GpuDisjointTimerTracerTest, DisjointTimerOngoingTracerMarkersTest) {
699 DoOngoingTracerMarkerTest();
700 }
701
TEST_F(GpuDisjointTimerTracerTest,DisjointTimerDisjointTraceTest)702 TEST_F(GpuDisjointTimerTracerTest, DisjointTimerDisjointTraceTest) {
703 DoDisjointTest();
704 }
705
TEST_F(GpuDisjointTimerTracerTest,NonrelevantDisjointTraceTest)706 TEST_F(GpuDisjointTimerTracerTest, NonrelevantDisjointTraceTest) {
707 DoOutsideDisjointTest();
708 }
709
710 class GPUTracerTest : public GpuServiceTest {
711 protected:
SetUp()712 void SetUp() override {
713 g_fakeCPUTime = 0;
714 GpuServiceTest::SetUpWithGLVersion("3.2", "");
715 decoder_.reset(
716 new MockGLES2Decoder(&client_, &command_buffer_service_, &outputter_));
717 EXPECT_CALL(*decoder_, GetGLContext())
718 .Times(AtMost(1))
719 .WillRepeatedly(Return(GetGLContext()));
720 tracer_tester_.reset(new GPUTracerTester(decoder_.get()));
721 }
722
TearDown()723 void TearDown() override {
724 tracer_tester_ = nullptr;
725 decoder_ = nullptr;
726 GpuServiceTest::TearDown();
727 }
728
729 FakeCommandBufferServiceBase command_buffer_service_;
730 FakeDecoderClient client_;
731 MockOutputter outputter_;
732 std::unique_ptr<MockGLES2Decoder> decoder_;
733 std::unique_ptr<GPUTracerTester> tracer_tester_;
734 };
735
TEST_F(GPUTracerTest,IsTracingTest)736 TEST_F(GPUTracerTest, IsTracingTest) {
737 EXPECT_FALSE(tracer_tester_->IsTracing());
738 tracer_tester_->SetTracingEnabled(true);
739 EXPECT_TRUE(tracer_tester_->IsTracing());
740 }
741 // Test basic functionality of the GPUTracerTester.
TEST_F(GPUTracerTest,DecodeTest)742 TEST_F(GPUTracerTest, DecodeTest) {
743 ASSERT_TRUE(tracer_tester_->BeginDecoding());
744 EXPECT_FALSE(tracer_tester_->BeginDecoding());
745 ASSERT_TRUE(tracer_tester_->EndDecoding());
746 EXPECT_FALSE(tracer_tester_->EndDecoding());
747 }
748
TEST_F(GPUTracerTest,TraceDuringDecodeTest)749 TEST_F(GPUTracerTest, TraceDuringDecodeTest) {
750 const std::string category_name("trace_category");
751 const std::string trace_name("trace_test");
752
753 EXPECT_FALSE(
754 tracer_tester_->Begin(category_name, trace_name, kTraceCHROMIUM));
755
756 ASSERT_TRUE(tracer_tester_->BeginDecoding());
757 EXPECT_TRUE(
758 tracer_tester_->Begin(category_name, trace_name, kTraceCHROMIUM));
759 ASSERT_TRUE(tracer_tester_->EndDecoding());
760 }
761
TEST_F(GpuDisjointTimerTracerTest,MultipleClientsDisjointTest)762 TEST_F(GpuDisjointTimerTracerTest, MultipleClientsDisjointTest) {
763 scoped_refptr<gl::GPUTimingClient> client1 =
764 GetGLContext()->CreateGPUTimingClient();
765 scoped_refptr<gl::GPUTimingClient> client2 =
766 GetGLContext()->CreateGPUTimingClient();
767
768 // Test both clients are initialized as no errors.
769 ASSERT_FALSE(client1->CheckAndResetTimerErrors());
770 ASSERT_FALSE(client2->CheckAndResetTimerErrors());
771
772 // Issue a disjoint.
773 gl_fake_queries_.SetDisjoint();
774
775 ASSERT_TRUE(client1->CheckAndResetTimerErrors());
776 ASSERT_TRUE(client2->CheckAndResetTimerErrors());
777
778 // Test both are now reset.
779 ASSERT_FALSE(client1->CheckAndResetTimerErrors());
780 ASSERT_FALSE(client2->CheckAndResetTimerErrors());
781
782 // Issue a disjoint.
783 gl_fake_queries_.SetDisjoint();
784
785 // Test new client disjoint value is cleared.
786 scoped_refptr<gl::GPUTimingClient> client3 =
787 GetGLContext()->CreateGPUTimingClient();
788 ASSERT_TRUE(client1->CheckAndResetTimerErrors());
789 ASSERT_TRUE(client2->CheckAndResetTimerErrors());
790 ASSERT_FALSE(client3->CheckAndResetTimerErrors());
791 }
792
793 } // namespace
794 } // namespace gles2
795 } // namespace gpu
796