123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221 |
- // Copyright 2015 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "ui/gl/gpu_timing.h"
- #include <stdint.h>
- #include <memory>
- #include "base/bind.h"
- #include "base/memory/raw_ptr.h"
- #include "base/time/time.h"
- #include "testing/gtest/include/gtest/gtest.h"
- #include "ui/gl/gl_context_stub.h"
- #include "ui/gl/gl_implementation.h"
- #include "ui/gl/gl_mock.h"
- #include "ui/gl/gl_surface_stub.h"
- #include "ui/gl/gpu_preference.h"
- #include "ui/gl/gpu_timing_fake.h"
- #include "ui/gl/init/gl_factory.h"
- #include "ui/gl/test/gl_surface_test_support.h"
- namespace gl {
- using ::testing::Exactly;
- using ::testing::NotNull;
- using ::testing::DoAll;
- using ::testing::Return;
- using ::testing::SetArgPointee;
- class GPUTimingTest : public testing::Test {
- public:
- void SetUp() override {
- setup_ = false;
- cpu_time_bounded_ = false;
- }
- void TearDown() override {
- context_ = nullptr;
- surface_ = nullptr;
- if (setup_) {
- MockGLInterface::SetGLInterface(nullptr);
- GLSurfaceTestSupport::ShutdownGL(display_);
- }
- setup_ = false;
- cpu_time_bounded_ = false;
- gl_.reset();
- gpu_timing_fake_queries_.Reset();
- }
- void SetupGLContext(const char* gl_version, const char* gl_extensions) {
- ASSERT_FALSE(setup_) << "Cannot setup GL context twice.";
- SetGLGetProcAddressProc(MockGLInterface::GetGLProcAddress);
- display_ = GLSurfaceTestSupport::InitializeOneOffWithMockBindings();
- gl_ = std::make_unique<::testing::StrictMock<MockGLInterface>>();
- MockGLInterface::SetGLInterface(gl_.get());
- context_ = new GLContextStub;
- context_->SetExtensionsString(gl_extensions);
- context_->SetGLVersionString(gl_version);
- surface_ = new GLSurfaceStub;
- context_->MakeCurrent(surface_.get());
- gpu_timing_fake_queries_.Reset();
- setup_ = true;
- }
- scoped_refptr<GPUTimingClient> CreateGPUTimingClient() {
- if (!setup_) {
- SetupGLContext("2.0", "");
- }
- scoped_refptr<GPUTimingClient> client = context_->CreateGPUTimingClient();
- if (!cpu_time_bounded_) {
- client->SetCpuTimeForTesting(
- base::BindRepeating(&GPUTimingFake::GetFakeCPUTime));
- cpu_time_bounded_ = true;
- }
- return client;
- }
- protected:
- bool setup_ = false;
- bool cpu_time_bounded_ = false;
- std::unique_ptr<::testing::StrictMock<MockGLInterface>> gl_;
- scoped_refptr<GLContextStub> context_;
- scoped_refptr<GLSurfaceStub> surface_;
- GPUTimingFake gpu_timing_fake_queries_;
- raw_ptr<GLDisplay> display_ = nullptr;
- };
- TEST_F(GPUTimingTest, FakeTimerTest) {
- scoped_refptr<GPUTimingClient> gpu_timing_client = CreateGPUTimingClient();
- // Tests that we can properly set fake cpu times.
- gpu_timing_fake_queries_.SetCurrentCPUTime(123);
- EXPECT_EQ(123, gpu_timing_client->GetCurrentCPUTime());
- base::RepeatingCallback<int64_t(void)> empty;
- gpu_timing_client->SetCpuTimeForTesting(empty);
- EXPECT_NE(123, gpu_timing_client->GetCurrentCPUTime());
- }
- TEST_F(GPUTimingTest, ForceTimeElapsedQuery) {
- // Test that forcing time elapsed query affects all clients.
- SetupGLContext("3.2", "GL_ARB_timer_query");
- scoped_refptr<GPUTimingClient> client1 = CreateGPUTimingClient();
- EXPECT_FALSE(client1->IsForceTimeElapsedQuery());
- scoped_refptr<GPUTimingClient> client_force = CreateGPUTimingClient();
- EXPECT_FALSE(client1->IsForceTimeElapsedQuery());
- client_force->ForceTimeElapsedQuery();
- EXPECT_TRUE(client1->IsForceTimeElapsedQuery());
- EXPECT_TRUE(client1->IsForceTimeElapsedQuery());
- scoped_refptr<GPUTimingClient> client2 = CreateGPUTimingClient();
- EXPECT_TRUE(client2->IsForceTimeElapsedQuery());
- }
- TEST_F(GPUTimingTest, QueryTimeStampTest) {
- SetupGLContext("3.2", "GL_ARB_timer_query");
- scoped_refptr<GPUTimingClient> client = CreateGPUTimingClient();
- std::unique_ptr<GPUTimer> gpu_timer = client->CreateGPUTimer(false);
- const int64_t begin_cpu_time = 1230;
- const int64_t begin_gl_time = 10 * base::Time::kNanosecondsPerMicrosecond;
- const int64_t cpu_gl_offset =
- begin_gl_time / base::Time::kNanosecondsPerMicrosecond - begin_cpu_time;
- gpu_timing_fake_queries_.SetCPUGLOffset(cpu_gl_offset);
- gpu_timing_fake_queries_.SetCurrentCPUTime(begin_cpu_time);
- gpu_timing_fake_queries_.ExpectGPUTimeStampQuery(*gl_, false);
- gpu_timer->QueryTimeStamp();
- gpu_timing_fake_queries_.SetCurrentCPUTime(begin_cpu_time - 1);
- EXPECT_FALSE(gpu_timer->IsAvailable());
- gpu_timing_fake_queries_.SetCurrentCPUTime(begin_cpu_time);
- EXPECT_TRUE(gpu_timer->IsAvailable());
- gpu_timing_fake_queries_.SetCurrentCPUTime(begin_cpu_time + 1);
- EXPECT_TRUE(gpu_timer->IsAvailable());
- EXPECT_EQ(0, gpu_timer->GetDeltaElapsed());
- int64_t start, end;
- gpu_timer->GetStartEndTimestamps(&start, &end);
- EXPECT_EQ(begin_cpu_time, start);
- EXPECT_EQ(begin_cpu_time, end);
- }
- TEST_F(GPUTimingTest, QueryTimeStampUsingElapsedTest) {
- // Test timestamp queries using GL_EXT_timer_query which does not support
- // timestamp queries. Internally we fall back to time elapsed queries.
- SetupGLContext("3.2", "GL_EXT_timer_query");
- scoped_refptr<GPUTimingClient> client = CreateGPUTimingClient();
- std::unique_ptr<GPUTimer> gpu_timer = client->CreateGPUTimer(false);
- ASSERT_TRUE(client->IsForceTimeElapsedQuery());
- const int64_t begin_cpu_time = 123;
- const int64_t begin_gl_time = 10 * base::Time::kNanosecondsPerMicrosecond;
- const int64_t cpu_gl_offset = begin_gl_time - begin_cpu_time;
- gpu_timing_fake_queries_.SetCPUGLOffset(cpu_gl_offset);
- gpu_timing_fake_queries_.SetCurrentCPUTime(begin_cpu_time);
- gpu_timing_fake_queries_.ExpectGPUTimeStampQuery(*gl_, true);
- gpu_timer->QueryTimeStamp();
- gpu_timing_fake_queries_.SetCurrentCPUTime(begin_cpu_time - 1);
- EXPECT_FALSE(gpu_timer->IsAvailable());
- gpu_timing_fake_queries_.SetCurrentCPUTime(begin_cpu_time + 1);
- EXPECT_TRUE(gpu_timer->IsAvailable());
- EXPECT_EQ(0, gpu_timer->GetDeltaElapsed());
- int64_t start, end;
- gpu_timer->GetStartEndTimestamps(&start, &end);
- EXPECT_EQ(begin_cpu_time, start);
- EXPECT_EQ(begin_cpu_time, end);
- }
- TEST_F(GPUTimingTest, QueryTimestampUsingElapsedARBTest) {
- // Test timestamp queries on platforms with GL_ARB_timer_query but still lack
- // support for timestamp queries
- SetupGLContext("3.2", "GL_ARB_timer_query");
- scoped_refptr<GPUTimingClient> client = CreateGPUTimingClient();
- std::unique_ptr<GPUTimer> gpu_timer = client->CreateGPUTimer(false);
- const int64_t begin_cpu_time = 123;
- const int64_t begin_gl_time = 10 * base::Time::kNanosecondsPerMicrosecond;
- const int64_t cpu_gl_offset = begin_gl_time - begin_cpu_time;
- gpu_timing_fake_queries_.SetCPUGLOffset(cpu_gl_offset);
- gpu_timing_fake_queries_.SetCurrentCPUTime(begin_cpu_time);
- gpu_timing_fake_queries_.ExpectGPUTimeStampQuery(*gl_, true);
- // Custom mock override to ensure the timestamp bits are 0
- EXPECT_CALL(*gl_, GetQueryiv(GL_TIMESTAMP, GL_QUERY_COUNTER_BITS, NotNull()))
- .Times(Exactly(1))
- .WillRepeatedly(DoAll(SetArgPointee<2>(0), Return()));
- gpu_timer->QueryTimeStamp();
- gpu_timing_fake_queries_.SetCurrentCPUTime(begin_cpu_time - 1);
- EXPECT_FALSE(gpu_timer->IsAvailable());
- gpu_timing_fake_queries_.SetCurrentCPUTime(begin_cpu_time + 1);
- EXPECT_TRUE(gpu_timer->IsAvailable());
- EXPECT_EQ(0, gpu_timer->GetDeltaElapsed());
- int64_t start, end;
- gpu_timer->GetStartEndTimestamps(&start, &end);
- // Force time elapsed won't be set until a query is actually attempted
- ASSERT_TRUE(client->IsForceTimeElapsedQuery());
- EXPECT_EQ(begin_cpu_time, start);
- EXPECT_EQ(begin_cpu_time, end);
- }
- } // namespace gl
|