blob: 6fa9b06f7e1d46f4b844ebf8593735fbb9374e82 [file] [log] [blame]
dyen26bd4c42015-06-10 01:39:431// Copyright 2015 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
danakj25c52c32016-04-12 21:51:085#include "ui/gl/gpu_timing.h"
6
avi739878c2015-12-24 18:06:177#include <stdint.h>
8
danakj25c52c32016-04-12 21:51:089#include <memory>
10
dyen26bd4c42015-06-10 01:39:4311#include "base/bind.h"
dyen26bd4c42015-06-10 01:39:4312#include "testing/gtest/include/gtest/gtest.h"
Geoff Langceb64f72017-01-30 17:02:5313#include "ui/gl/gl_context_stub.h"
dyen26bd4c42015-06-10 01:39:4314#include "ui/gl/gl_implementation.h"
15#include "ui/gl/gl_mock.h"
piman39f67692016-05-12 03:25:1416#include "ui/gl/gl_surface_stub.h"
dyen26bd4c42015-06-10 01:39:4317#include "ui/gl/gpu_preference.h"
dyenda06bae2015-07-16 22:59:3018#include "ui/gl/gpu_timing_fake.h"
kylechar16666242016-07-04 20:54:4519#include "ui/gl/init/gl_factory.h"
sadrulba162cd2015-07-20 22:34:2620#include "ui/gl/test/gl_surface_test_support.h"
dyen26bd4c42015-06-10 01:39:4321
kylechar7a463842016-05-26 14:46:1222namespace gl {
dyen26bd4c42015-06-10 01:39:4323
ewell71c79ec2016-02-18 00:45:4124using ::testing::Exactly;
25using ::testing::NotNull;
26using ::testing::DoAll;
27using ::testing::Return;
28using ::testing::SetArgPointee;
29
dyen26bd4c42015-06-10 01:39:4330class GPUTimingTest : public testing::Test {
31 public:
32 void SetUp() override {
33 setup_ = false;
dyenda06bae2015-07-16 22:59:3034 cpu_time_bounded_ = false;
dyen26bd4c42015-06-10 01:39:4335 }
36
37 void TearDown() override {
piman39f67692016-05-12 03:25:1438 context_ = nullptr;
39 surface_ = nullptr;
dyenda06bae2015-07-16 22:59:3040 if (setup_) {
41 MockGLInterface::SetGLInterface(NULL);
cwallez3f8acfc2016-12-02 23:10:0242 init::ShutdownGL();
dyenda06bae2015-07-16 22:59:3043 }
44 setup_ = false;
45 cpu_time_bounded_ = false;
dyenda06bae2015-07-16 22:59:3046 gl_.reset();
47 gpu_timing_fake_queries_.Reset();
dyen26bd4c42015-06-10 01:39:4348 }
49
50 void SetupGLContext(const char* gl_version, const char* gl_extensions) {
51 ASSERT_FALSE(setup_) << "Cannot setup GL context twice.";
dyenda06bae2015-07-16 22:59:3052 SetGLGetProcAddressProc(MockGLInterface::GetGLProcAddress);
sadrulba162cd2015-07-20 22:34:2653 GLSurfaceTestSupport::InitializeOneOffWithMockBindings();
dyenda06bae2015-07-16 22:59:3054 gl_.reset(new ::testing::StrictMock<MockGLInterface>());
55 MockGLInterface::SetGLInterface(gl_.get());
dyen26bd4c42015-06-10 01:39:4356
Geoff Langceb64f72017-01-30 17:02:5357 context_ = new GLContextStub;
58 context_->SetExtensionsString(gl_extensions);
dyen26bd4c42015-06-10 01:39:4359 context_->SetGLVersionString(gl_version);
kylecharfd721902016-05-27 16:00:2460 surface_ = new GLSurfaceStub;
piman39f67692016-05-12 03:25:1461 context_->MakeCurrent(surface_.get());
dyenda06bae2015-07-16 22:59:3062 gpu_timing_fake_queries_.Reset();
dyen26bd4c42015-06-10 01:39:4363
64 setup_ = true;
65 }
66
67 scoped_refptr<GPUTimingClient> CreateGPUTimingClient() {
68 if (!setup_) {
69 SetupGLContext("2.0", "");
70 }
dyenda06bae2015-07-16 22:59:3071
72 scoped_refptr<GPUTimingClient> client = context_->CreateGPUTimingClient();
73 if (!cpu_time_bounded_) {
dyenb245d372015-07-25 01:18:3874 client->SetCpuTimeForTesting(base::Bind(&GPUTimingFake::GetFakeCPUTime));
dyenda06bae2015-07-16 22:59:3075 cpu_time_bounded_ = true;
76 }
77 return client;
dyen26bd4c42015-06-10 01:39:4378 }
79
dyen26bd4c42015-06-10 01:39:4380 protected:
dyen26bd4c42015-06-10 01:39:4381 bool setup_ = false;
dyenda06bae2015-07-16 22:59:3082 bool cpu_time_bounded_ = false;
danakj25c52c32016-04-12 21:51:0883 std::unique_ptr<::testing::StrictMock<MockGLInterface>> gl_;
Geoff Langceb64f72017-01-30 17:02:5384 scoped_refptr<GLContextStub> context_;
kylecharfd721902016-05-27 16:00:2485 scoped_refptr<GLSurfaceStub> surface_;
dyenda06bae2015-07-16 22:59:3086 GPUTimingFake gpu_timing_fake_queries_;
dyen26bd4c42015-06-10 01:39:4387};
88
dyen26bd4c42015-06-10 01:39:4389TEST_F(GPUTimingTest, FakeTimerTest) {
dyen26bd4c42015-06-10 01:39:4390 scoped_refptr<GPUTimingClient> gpu_timing_client = CreateGPUTimingClient();
dyenb245d372015-07-25 01:18:3891
92 // Tests that we can properly set fake cpu times.
93 gpu_timing_fake_queries_.SetCurrentCPUTime(123);
dyen26bd4c42015-06-10 01:39:4394 EXPECT_EQ(123, gpu_timing_client->GetCurrentCPUTime());
95
96 base::Callback<int64_t(void)> empty;
97 gpu_timing_client->SetCpuTimeForTesting(empty);
98 EXPECT_NE(123, gpu_timing_client->GetCurrentCPUTime());
99}
100
dyen1fa421962015-06-17 21:25:39101TEST_F(GPUTimingTest, ForceTimeElapsedQuery) {
102 // Test that forcing time elapsed query affects all clients.
martina.kollarovaab306992016-02-26 11:01:10103 SetupGLContext("3.2", "GL_ARB_timer_query");
dyen1fa421962015-06-17 21:25:39104 scoped_refptr<GPUTimingClient> client1 = CreateGPUTimingClient();
105 EXPECT_FALSE(client1->IsForceTimeElapsedQuery());
106
107 scoped_refptr<GPUTimingClient> client_force = CreateGPUTimingClient();
108 EXPECT_FALSE(client1->IsForceTimeElapsedQuery());
109 client_force->ForceTimeElapsedQuery();
110 EXPECT_TRUE(client1->IsForceTimeElapsedQuery());
111
112 EXPECT_TRUE(client1->IsForceTimeElapsedQuery());
113
114 scoped_refptr<GPUTimingClient> client2 = CreateGPUTimingClient();
115 EXPECT_TRUE(client2->IsForceTimeElapsedQuery());
116}
117
dyenda06bae2015-07-16 22:59:30118TEST_F(GPUTimingTest, QueryTimeStampTest) {
119 SetupGLContext("3.2", "GL_ARB_timer_query");
120 scoped_refptr<GPUTimingClient> client = CreateGPUTimingClient();
danakj25c52c32016-04-12 21:51:08121 std::unique_ptr<GPUTimer> gpu_timer = client->CreateGPUTimer(false);
dyenda06bae2015-07-16 22:59:30122
dyenea6d8402016-02-02 00:55:01123 const int64_t begin_cpu_time = 1230;
dyenb245d372015-07-25 01:18:38124 const int64_t begin_gl_time = 10 * base::Time::kNanosecondsPerMicrosecond;
125 const int64_t cpu_gl_offset =
126 begin_gl_time / base::Time::kNanosecondsPerMicrosecond - begin_cpu_time;
127 gpu_timing_fake_queries_.SetCPUGLOffset(cpu_gl_offset);
128 gpu_timing_fake_queries_.SetCurrentCPUTime(begin_cpu_time);
dyenda06bae2015-07-16 22:59:30129 gpu_timing_fake_queries_.ExpectGPUTimeStampQuery(*gl_, false);
130
131 gpu_timer->QueryTimeStamp();
132
dyenb245d372015-07-25 01:18:38133 gpu_timing_fake_queries_.SetCurrentCPUTime(begin_cpu_time - 1);
dyenda06bae2015-07-16 22:59:30134 EXPECT_FALSE(gpu_timer->IsAvailable());
135
dyenb245d372015-07-25 01:18:38136 gpu_timing_fake_queries_.SetCurrentCPUTime(begin_cpu_time);
dyenda06bae2015-07-16 22:59:30137 EXPECT_TRUE(gpu_timer->IsAvailable());
dyenb245d372015-07-25 01:18:38138
139 gpu_timing_fake_queries_.SetCurrentCPUTime(begin_cpu_time + 1);
140 EXPECT_TRUE(gpu_timer->IsAvailable());
141
dyenda06bae2015-07-16 22:59:30142 EXPECT_EQ(0, gpu_timer->GetDeltaElapsed());
143
avi739878c2015-12-24 18:06:17144 int64_t start, end;
dyenda06bae2015-07-16 22:59:30145 gpu_timer->GetStartEndTimestamps(&start, &end);
dyenb245d372015-07-25 01:18:38146 EXPECT_EQ(begin_cpu_time, start);
147 EXPECT_EQ(begin_cpu_time, end);
dyenda06bae2015-07-16 22:59:30148}
149
150TEST_F(GPUTimingTest, QueryTimeStampUsingElapsedTest) {
151 // Test timestamp queries using GL_EXT_timer_query which does not support
152 // timestamp queries. Internally we fall back to time elapsed queries.
153 SetupGLContext("3.2", "GL_EXT_timer_query");
154 scoped_refptr<GPUTimingClient> client = CreateGPUTimingClient();
danakj25c52c32016-04-12 21:51:08155 std::unique_ptr<GPUTimer> gpu_timer = client->CreateGPUTimer(false);
dyenda06bae2015-07-16 22:59:30156 ASSERT_TRUE(client->IsForceTimeElapsedQuery());
157
dyenb245d372015-07-25 01:18:38158 const int64_t begin_cpu_time = 123;
159 const int64_t begin_gl_time = 10 * base::Time::kNanosecondsPerMicrosecond;
160 const int64_t cpu_gl_offset = begin_gl_time - begin_cpu_time;
161 gpu_timing_fake_queries_.SetCPUGLOffset(cpu_gl_offset);
162 gpu_timing_fake_queries_.SetCurrentCPUTime(begin_cpu_time);
dyenda06bae2015-07-16 22:59:30163 gpu_timing_fake_queries_.ExpectGPUTimeStampQuery(*gl_, true);
164
165 gpu_timer->QueryTimeStamp();
166
dyenb245d372015-07-25 01:18:38167 gpu_timing_fake_queries_.SetCurrentCPUTime(begin_cpu_time - 1);
dyenda06bae2015-07-16 22:59:30168 EXPECT_FALSE(gpu_timer->IsAvailable());
169
dyenb245d372015-07-25 01:18:38170 gpu_timing_fake_queries_.SetCurrentCPUTime(begin_cpu_time + 1);
dyenda06bae2015-07-16 22:59:30171 EXPECT_TRUE(gpu_timer->IsAvailable());
172 EXPECT_EQ(0, gpu_timer->GetDeltaElapsed());
173
avi739878c2015-12-24 18:06:17174 int64_t start, end;
dyenda06bae2015-07-16 22:59:30175 gpu_timer->GetStartEndTimestamps(&start, &end);
dyenb245d372015-07-25 01:18:38176 EXPECT_EQ(begin_cpu_time, start);
177 EXPECT_EQ(begin_cpu_time, end);
dyenda06bae2015-07-16 22:59:30178}
179
ewell71c79ec2016-02-18 00:45:41180TEST_F(GPUTimingTest, QueryTimestampUsingElapsedARBTest) {
181 // Test timestamp queries on platforms with GL_ARB_timer_query but still lack
182 // support for timestamp queries
183 SetupGLContext("3.2", "GL_ARB_timer_query");
184 scoped_refptr<GPUTimingClient> client = CreateGPUTimingClient();
danakj25c52c32016-04-12 21:51:08185 std::unique_ptr<GPUTimer> gpu_timer = client->CreateGPUTimer(false);
ewell71c79ec2016-02-18 00:45:41186
187 const int64_t begin_cpu_time = 123;
188 const int64_t begin_gl_time = 10 * base::Time::kNanosecondsPerMicrosecond;
189 const int64_t cpu_gl_offset = begin_gl_time - begin_cpu_time;
190 gpu_timing_fake_queries_.SetCPUGLOffset(cpu_gl_offset);
191 gpu_timing_fake_queries_.SetCurrentCPUTime(begin_cpu_time);
192
193 gpu_timing_fake_queries_.ExpectGPUTimeStampQuery(*gl_, true);
194
195 // Custom mock override to ensure the timestamp bits are 0
196 EXPECT_CALL(*gl_, GetQueryiv(GL_TIMESTAMP, GL_QUERY_COUNTER_BITS, NotNull()))
197 .Times(Exactly(1))
198 .WillRepeatedly(DoAll(SetArgPointee<2>(0), Return()));
199
200 gpu_timer->QueryTimeStamp();
201
202 gpu_timing_fake_queries_.SetCurrentCPUTime(begin_cpu_time - 1);
203 EXPECT_FALSE(gpu_timer->IsAvailable());
204
205 gpu_timing_fake_queries_.SetCurrentCPUTime(begin_cpu_time + 1);
206 EXPECT_TRUE(gpu_timer->IsAvailable());
207 EXPECT_EQ(0, gpu_timer->GetDeltaElapsed());
208
209 int64_t start, end;
210 gpu_timer->GetStartEndTimestamps(&start, &end);
211 // Force time elapsed won't be set until a query is actually attempted
212 ASSERT_TRUE(client->IsForceTimeElapsedQuery());
213 EXPECT_EQ(begin_cpu_time, start);
214 EXPECT_EQ(begin_cpu_time, end);
215}
216
kylecharfd721902016-05-27 16:00:24217} // namespace gl