blob: 9184b6703e5f08155cd2674ffaf6c13312fc2716 [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);
Michał Pichlińskiaeb6e402017-11-30 22:52:4342 init::ShutdownGL(false);
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();
Peter Boströmf238104a2019-08-27 00:25:0354 gl_ = std::make_unique<::testing::StrictMock<MockGLInterface>>();
dyenda06bae2015-07-16 22:59:3055 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_) {
kylechar43c97732019-02-04 20:20:1774 client->SetCpuTimeForTesting(
75 base::BindRepeating(&GPUTimingFake::GetFakeCPUTime));
dyenda06bae2015-07-16 22:59:3076 cpu_time_bounded_ = true;
77 }
78 return client;
dyen26bd4c42015-06-10 01:39:4379 }
80
dyen26bd4c42015-06-10 01:39:4381 protected:
dyen26bd4c42015-06-10 01:39:4382 bool setup_ = false;
dyenda06bae2015-07-16 22:59:3083 bool cpu_time_bounded_ = false;
danakj25c52c32016-04-12 21:51:0884 std::unique_ptr<::testing::StrictMock<MockGLInterface>> gl_;
Geoff Langceb64f72017-01-30 17:02:5385 scoped_refptr<GLContextStub> context_;
kylecharfd721902016-05-27 16:00:2486 scoped_refptr<GLSurfaceStub> surface_;
dyenda06bae2015-07-16 22:59:3087 GPUTimingFake gpu_timing_fake_queries_;
dyen26bd4c42015-06-10 01:39:4388};
89
dyen26bd4c42015-06-10 01:39:4390TEST_F(GPUTimingTest, FakeTimerTest) {
dyen26bd4c42015-06-10 01:39:4391 scoped_refptr<GPUTimingClient> gpu_timing_client = CreateGPUTimingClient();
dyenb245d372015-07-25 01:18:3892
93 // Tests that we can properly set fake cpu times.
94 gpu_timing_fake_queries_.SetCurrentCPUTime(123);
dyen26bd4c42015-06-10 01:39:4395 EXPECT_EQ(123, gpu_timing_client->GetCurrentCPUTime());
96
kylechar43c97732019-02-04 20:20:1797 base::RepeatingCallback<int64_t(void)> empty;
dyen26bd4c42015-06-10 01:39:4398 gpu_timing_client->SetCpuTimeForTesting(empty);
99 EXPECT_NE(123, gpu_timing_client->GetCurrentCPUTime());
100}
101
dyen1fa421962015-06-17 21:25:39102TEST_F(GPUTimingTest, ForceTimeElapsedQuery) {
103 // Test that forcing time elapsed query affects all clients.
martina.kollarovaab306992016-02-26 11:01:10104 SetupGLContext("3.2", "GL_ARB_timer_query");
dyen1fa421962015-06-17 21:25:39105 scoped_refptr<GPUTimingClient> client1 = CreateGPUTimingClient();
106 EXPECT_FALSE(client1->IsForceTimeElapsedQuery());
107
108 scoped_refptr<GPUTimingClient> client_force = CreateGPUTimingClient();
109 EXPECT_FALSE(client1->IsForceTimeElapsedQuery());
110 client_force->ForceTimeElapsedQuery();
111 EXPECT_TRUE(client1->IsForceTimeElapsedQuery());
112
113 EXPECT_TRUE(client1->IsForceTimeElapsedQuery());
114
115 scoped_refptr<GPUTimingClient> client2 = CreateGPUTimingClient();
116 EXPECT_TRUE(client2->IsForceTimeElapsedQuery());
117}
118
dyenda06bae2015-07-16 22:59:30119TEST_F(GPUTimingTest, QueryTimeStampTest) {
120 SetupGLContext("3.2", "GL_ARB_timer_query");
121 scoped_refptr<GPUTimingClient> client = CreateGPUTimingClient();
danakj25c52c32016-04-12 21:51:08122 std::unique_ptr<GPUTimer> gpu_timer = client->CreateGPUTimer(false);
dyenda06bae2015-07-16 22:59:30123
dyenea6d8402016-02-02 00:55:01124 const int64_t begin_cpu_time = 1230;
dyenb245d372015-07-25 01:18:38125 const int64_t begin_gl_time = 10 * base::Time::kNanosecondsPerMicrosecond;
126 const int64_t cpu_gl_offset =
127 begin_gl_time / base::Time::kNanosecondsPerMicrosecond - begin_cpu_time;
128 gpu_timing_fake_queries_.SetCPUGLOffset(cpu_gl_offset);
129 gpu_timing_fake_queries_.SetCurrentCPUTime(begin_cpu_time);
dyenda06bae2015-07-16 22:59:30130 gpu_timing_fake_queries_.ExpectGPUTimeStampQuery(*gl_, false);
131
132 gpu_timer->QueryTimeStamp();
133
dyenb245d372015-07-25 01:18:38134 gpu_timing_fake_queries_.SetCurrentCPUTime(begin_cpu_time - 1);
dyenda06bae2015-07-16 22:59:30135 EXPECT_FALSE(gpu_timer->IsAvailable());
136
dyenb245d372015-07-25 01:18:38137 gpu_timing_fake_queries_.SetCurrentCPUTime(begin_cpu_time);
dyenda06bae2015-07-16 22:59:30138 EXPECT_TRUE(gpu_timer->IsAvailable());
dyenb245d372015-07-25 01:18:38139
140 gpu_timing_fake_queries_.SetCurrentCPUTime(begin_cpu_time + 1);
141 EXPECT_TRUE(gpu_timer->IsAvailable());
142
dyenda06bae2015-07-16 22:59:30143 EXPECT_EQ(0, gpu_timer->GetDeltaElapsed());
144
avi739878c2015-12-24 18:06:17145 int64_t start, end;
dyenda06bae2015-07-16 22:59:30146 gpu_timer->GetStartEndTimestamps(&start, &end);
dyenb245d372015-07-25 01:18:38147 EXPECT_EQ(begin_cpu_time, start);
148 EXPECT_EQ(begin_cpu_time, end);
dyenda06bae2015-07-16 22:59:30149}
150
151TEST_F(GPUTimingTest, QueryTimeStampUsingElapsedTest) {
152 // Test timestamp queries using GL_EXT_timer_query which does not support
153 // timestamp queries. Internally we fall back to time elapsed queries.
154 SetupGLContext("3.2", "GL_EXT_timer_query");
155 scoped_refptr<GPUTimingClient> client = CreateGPUTimingClient();
danakj25c52c32016-04-12 21:51:08156 std::unique_ptr<GPUTimer> gpu_timer = client->CreateGPUTimer(false);
dyenda06bae2015-07-16 22:59:30157 ASSERT_TRUE(client->IsForceTimeElapsedQuery());
158
dyenb245d372015-07-25 01:18:38159 const int64_t begin_cpu_time = 123;
160 const int64_t begin_gl_time = 10 * base::Time::kNanosecondsPerMicrosecond;
161 const int64_t cpu_gl_offset = begin_gl_time - begin_cpu_time;
162 gpu_timing_fake_queries_.SetCPUGLOffset(cpu_gl_offset);
163 gpu_timing_fake_queries_.SetCurrentCPUTime(begin_cpu_time);
dyenda06bae2015-07-16 22:59:30164 gpu_timing_fake_queries_.ExpectGPUTimeStampQuery(*gl_, true);
165
166 gpu_timer->QueryTimeStamp();
167
dyenb245d372015-07-25 01:18:38168 gpu_timing_fake_queries_.SetCurrentCPUTime(begin_cpu_time - 1);
dyenda06bae2015-07-16 22:59:30169 EXPECT_FALSE(gpu_timer->IsAvailable());
170
dyenb245d372015-07-25 01:18:38171 gpu_timing_fake_queries_.SetCurrentCPUTime(begin_cpu_time + 1);
dyenda06bae2015-07-16 22:59:30172 EXPECT_TRUE(gpu_timer->IsAvailable());
173 EXPECT_EQ(0, gpu_timer->GetDeltaElapsed());
174
avi739878c2015-12-24 18:06:17175 int64_t start, end;
dyenda06bae2015-07-16 22:59:30176 gpu_timer->GetStartEndTimestamps(&start, &end);
dyenb245d372015-07-25 01:18:38177 EXPECT_EQ(begin_cpu_time, start);
178 EXPECT_EQ(begin_cpu_time, end);
dyenda06bae2015-07-16 22:59:30179}
180
ewell71c79ec2016-02-18 00:45:41181TEST_F(GPUTimingTest, QueryTimestampUsingElapsedARBTest) {
182 // Test timestamp queries on platforms with GL_ARB_timer_query but still lack
183 // support for timestamp queries
184 SetupGLContext("3.2", "GL_ARB_timer_query");
185 scoped_refptr<GPUTimingClient> client = CreateGPUTimingClient();
danakj25c52c32016-04-12 21:51:08186 std::unique_ptr<GPUTimer> gpu_timer = client->CreateGPUTimer(false);
ewell71c79ec2016-02-18 00:45:41187
188 const int64_t begin_cpu_time = 123;
189 const int64_t begin_gl_time = 10 * base::Time::kNanosecondsPerMicrosecond;
190 const int64_t cpu_gl_offset = begin_gl_time - begin_cpu_time;
191 gpu_timing_fake_queries_.SetCPUGLOffset(cpu_gl_offset);
192 gpu_timing_fake_queries_.SetCurrentCPUTime(begin_cpu_time);
193
194 gpu_timing_fake_queries_.ExpectGPUTimeStampQuery(*gl_, true);
195
196 // Custom mock override to ensure the timestamp bits are 0
197 EXPECT_CALL(*gl_, GetQueryiv(GL_TIMESTAMP, GL_QUERY_COUNTER_BITS, NotNull()))
198 .Times(Exactly(1))
199 .WillRepeatedly(DoAll(SetArgPointee<2>(0), Return()));
200
201 gpu_timer->QueryTimeStamp();
202
203 gpu_timing_fake_queries_.SetCurrentCPUTime(begin_cpu_time - 1);
204 EXPECT_FALSE(gpu_timer->IsAvailable());
205
206 gpu_timing_fake_queries_.SetCurrentCPUTime(begin_cpu_time + 1);
207 EXPECT_TRUE(gpu_timer->IsAvailable());
208 EXPECT_EQ(0, gpu_timer->GetDeltaElapsed());
209
210 int64_t start, end;
211 gpu_timer->GetStartEndTimestamps(&start, &end);
212 // Force time elapsed won't be set until a query is actually attempted
213 ASSERT_TRUE(client->IsForceTimeElapsedQuery());
214 EXPECT_EQ(begin_cpu_time, start);
215 EXPECT_EQ(begin_cpu_time, end);
216}
217
kylecharfd721902016-05-27 16:00:24218} // namespace gl