blob: 9be021248f7c7c7ceaaae087e72f8984c3d24991 [file] [log] [blame]
// Copyright 2014 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 <stdint.h>
#include "base/bind.h"
#include "gpu/command_buffer/client/client_test_helper.h"
#include "gpu/command_buffer/service/gles2_cmd_decoder_mock.h"
#include "gpu/command_buffer/service/gpu_service_test.h"
#include "gpu/command_buffer/service/gpu_tracer.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_mock.h"
#include "ui/gl/gpu_timing.h"
#include "ui/gl/gpu_timing_fake.h"
namespace gpu {
namespace gles2 {
namespace {
using ::testing::_;
using ::testing::AtMost;
using ::testing::Exactly;
using ::testing::Invoke;
using ::testing::Return;
int64_t g_fakeCPUTime = 0;
int64_t FakeCpuTime() {
return g_fakeCPUTime;
}
class MockOutputter : public Outputter {
public:
MockOutputter() = default;
~MockOutputter() override = default;
MOCK_METHOD5(TraceDevice,
void(GpuTracerSource source,
const std::string& category,
const std::string& name,
int64_t start_time,
int64_t end_time));
MOCK_METHOD3(TraceServiceBegin,
void(GpuTracerSource source,
const std::string& category, const std::string& name));
MOCK_METHOD3(TraceServiceEnd,
void(GpuTracerSource source,
const std::string& category, const std::string& name));
};
class GPUTracerTester : public GPUTracer {
public:
explicit GPUTracerTester(GLES2Decoder* decoder)
: GPUTracer(decoder), tracing_enabled_(0) {
gpu_timing_client_->SetCpuTimeForTesting(base::Bind(&FakeCpuTime));
// Force tracing to be dependent on our mock variable here.
gpu_trace_srv_category = &tracing_enabled_;
gpu_trace_dev_category = &tracing_enabled_;
}
~GPUTracerTester() override = default;
void SetTracingEnabled(bool enabled) {
tracing_enabled_ = enabled ? 1 : 0;
}
private:
unsigned char tracing_enabled_;
};
class BaseGpuTest : public GpuServiceTest {
public:
explicit BaseGpuTest(gl::GPUTiming::TimerType test_timer_type)
: test_timer_type_(test_timer_type) {}
protected:
void SetUp() override {
g_fakeCPUTime = 0;
const char* gl_version = "3.2";
const char* extensions = "";
if (GetTimerType() == gl::GPUTiming::kTimerTypeEXT) {
gl_version = "2.1";
extensions = "GL_EXT_timer_query";
} else if (GetTimerType() == gl::GPUTiming::kTimerTypeDisjoint) {
gl_version = "OpenGL ES 3.0";
extensions = "GL_EXT_disjoint_timer_query";
} else if (GetTimerType() == gl::GPUTiming::kTimerTypeARB) {
// TODO(sievers): The tracer should not depend on ARB_occlusion_query.
// Try merge Query APIs (core, ARB, EXT) into a single binding each.
extensions = "GL_ARB_timer_query GL_ARB_occlusion_query";
}
GpuServiceTest::SetUpWithGLVersion(gl_version, extensions);
// Disjoint check should only be called by kTracerTypeDisjointTimer type.
if (GetTimerType() == gl::GPUTiming::kTimerTypeDisjoint)
gl_fake_queries_.ExpectDisjointCalls(*gl_);
else
gl_fake_queries_.ExpectNoDisjointCalls(*gl_);
gpu_timing_client_ = GetGLContext()->CreateGPUTimingClient();
gpu_timing_client_->SetCpuTimeForTesting(base::Bind(&FakeCpuTime));
gl_fake_queries_.Reset();
}
void TearDown() override {
gpu_timing_client_ = nullptr;
gl_fake_queries_.Reset();
GpuServiceTest::TearDown();
}
void ExpectTraceQueryMocks() {
if (gpu_timing_client_->IsAvailable()) {
// Delegate query APIs used by GPUTrace to a GlFakeQueries
const bool elapsed = (GetTimerType() == gl::GPUTiming::kTimerTypeEXT);
gl_fake_queries_.ExpectGPUTimerQuery(*gl_, elapsed);
}
}
void ExpectOutputterBeginMocks(MockOutputter* outputter,
GpuTracerSource source,
const std::string& category,
const std::string& name) {
EXPECT_CALL(*outputter,
TraceServiceBegin(source, category, name));
}
void 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) {
if (trace_service) {
EXPECT_CALL(*outputter,
TraceServiceEnd(source, category, name));
}
if (trace_device) {
EXPECT_CALL(*outputter,
TraceDevice(source, category, name,
expect_start_time, expect_end_time))
.Times(Exactly(1));
} else {
EXPECT_CALL(*outputter, TraceDevice(source, category, name,
expect_start_time, expect_end_time))
.Times(Exactly(0));
}
}
void ExpectDisjointOutputMocks(MockOutputter* outputter,
int64_t expect_start_time,
int64_t expect_end_time) {
EXPECT_CALL(*outputter,
TraceDevice(kTraceDisjoint, "DisjointEvent", _,
expect_start_time, expect_end_time))
.Times(Exactly(1));
}
void ExpectNoDisjointOutputMocks(MockOutputter* outputter) {
EXPECT_CALL(*outputter,
TraceDevice(kTraceDisjoint, "DisjointEvent", _, _, _))
.Times(Exactly(0));
}
void 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) {
if (tracing_service)
ExpectOutputterBeginMocks(outputter, source, category, name);
const bool valid_timer = tracing_device &&
gpu_timing_client_->IsAvailable();
ExpectOutputterEndMocks(outputter, source, category, name,
expect_start_time, expect_end_time,
tracing_service, valid_timer);
}
void ExpectTracerOffsetQueryMocks() {
if (GetTimerType() != gl::GPUTiming::kTimerTypeARB) {
gl_fake_queries_.ExpectNoOffsetCalculationQuery(*gl_);
} else {
gl_fake_queries_.ExpectOffsetCalculationQuery(*gl_);
}
}
gl::GPUTiming::TimerType GetTimerType() { return test_timer_type_; }
gl::GPUTiming::TimerType test_timer_type_;
gl::GPUTimingFake gl_fake_queries_;
scoped_refptr<gl::GPUTimingClient> gpu_timing_client_;
MockOutputter outputter_;
};
// Test GPUTrace calls all the correct gl calls.
class BaseGpuTraceTest : public BaseGpuTest {
public:
explicit BaseGpuTraceTest(gl::GPUTiming::TimerType test_timer_type)
: BaseGpuTest(test_timer_type) {}
void DoTraceTest(bool tracing_service, bool tracing_device) {
// Expected results
const GpuTracerSource tracer_source = kTraceCHROMIUM;
const std::string category_name("trace_category");
const std::string trace_name("trace_test");
const int64_t offset_time = 3231;
const GLint64 start_timestamp = 7 * base::Time::kNanosecondsPerMicrosecond;
const GLint64 end_timestamp = 32 * base::Time::kNanosecondsPerMicrosecond;
const int64_t expect_start_time =
(start_timestamp / base::Time::kNanosecondsPerMicrosecond) +
offset_time;
const int64_t expect_end_time =
(end_timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_time;
ExpectOutputterMocks(&outputter_, tracing_service, tracing_device,
tracer_source, category_name, trace_name,
expect_start_time, expect_end_time);
if (tracing_device)
ExpectTraceQueryMocks();
scoped_refptr<GPUTrace> trace = new GPUTrace(
&outputter_, gpu_timing_client_.get(), tracer_source, category_name,
trace_name, tracing_service, tracing_device);
gl_fake_queries_.SetCurrentGLTime(start_timestamp);
g_fakeCPUTime = expect_start_time;
trace->Start();
// Shouldn't be available before End() call
gl_fake_queries_.SetCurrentGLTime(end_timestamp);
g_fakeCPUTime = expect_end_time;
if (tracing_device)
EXPECT_FALSE(trace->IsAvailable());
trace->End();
// Shouldn't be available until the queries complete
gl_fake_queries_.SetCurrentGLTime(end_timestamp -
base::Time::kNanosecondsPerMicrosecond);
g_fakeCPUTime = expect_end_time - 1;
if (tracing_device)
EXPECT_FALSE(trace->IsAvailable());
// Now it should be available
gl_fake_queries_.SetCurrentGLTime(end_timestamp);
g_fakeCPUTime = expect_end_time;
EXPECT_TRUE(trace->IsAvailable());
// Process should output expected Trace results to MockOutputter
trace->Process();
// Destroy trace after we are done.
trace->Destroy(true);
}
};
class GpuARBTimerTraceTest : public BaseGpuTraceTest {
public:
GpuARBTimerTraceTest() : BaseGpuTraceTest(gl::GPUTiming::kTimerTypeARB) {}
};
class GpuDisjointTimerTraceTest : public BaseGpuTraceTest {
public:
GpuDisjointTimerTraceTest()
: BaseGpuTraceTest(gl::GPUTiming::kTimerTypeDisjoint) {}
};
TEST_F(GpuARBTimerTraceTest, ARBTimerTraceTestOff) {
DoTraceTest(false, false);
}
TEST_F(GpuARBTimerTraceTest, ARBTimerTraceTestServiceOnly) {
DoTraceTest(true, false);
}
TEST_F(GpuARBTimerTraceTest, ARBTimerTraceTestDeviceOnly) {
DoTraceTest(false, true);
}
TEST_F(GpuARBTimerTraceTest, ARBTimerTraceTestBothOn) {
DoTraceTest(true, true);
}
TEST_F(GpuDisjointTimerTraceTest, DisjointTimerTraceTestOff) {
DoTraceTest(false, false);
}
TEST_F(GpuDisjointTimerTraceTest, DisjointTimerTraceTestServiceOnly) {
DoTraceTest(true, false);
}
TEST_F(GpuDisjointTimerTraceTest, DisjointTimerTraceTestDeviceOnly) {
DoTraceTest(false, true);
}
TEST_F(GpuDisjointTimerTraceTest, DisjointTimerTraceTestBothOn) {
DoTraceTest(true, true);
}
// Test GPUTracer calls all the correct gl calls.
class BaseGpuTracerTest : public BaseGpuTest {
public:
explicit BaseGpuTracerTest(gl::GPUTiming::TimerType test_timer_type)
: BaseGpuTest(test_timer_type) {}
void DoBasicTracerTest() {
ExpectTracerOffsetQueryMocks();
FakeCommandBufferServiceBase command_buffer_service;
MockOutputter outputter;
MockGLES2Decoder decoder(&command_buffer_service, &outputter);
EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext()));
GPUTracerTester tracer(&decoder);
tracer.SetTracingEnabled(true);
ASSERT_TRUE(tracer.BeginDecoding());
ASSERT_TRUE(tracer.EndDecoding());
}
void DoDisabledTracingTest() {
ExpectTracerOffsetQueryMocks();
const GpuTracerSource source = static_cast<GpuTracerSource>(0);
FakeCommandBufferServiceBase command_buffer_service;
MockOutputter outputter;
MockGLES2Decoder decoder(&command_buffer_service, &outputter);
EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext()));
GPUTracerTester tracer(&decoder);
tracer.SetTracingEnabled(false);
ASSERT_TRUE(tracer.BeginDecoding());
ASSERT_TRUE(tracer.Begin("disabled_category", "disabled_name", source));
ASSERT_TRUE(tracer.End(source));
ASSERT_TRUE(tracer.EndDecoding());
}
void DoTracerMarkersTest() {
ExpectTracerOffsetQueryMocks();
gl_fake_queries_.ExpectGetErrorCalls(*gl_);
const std::string category_name("trace_category");
const std::string trace_name("trace_test");
const int64_t offset_time = 3231;
const GLint64 start_timestamp = 7 * base::Time::kNanosecondsPerMicrosecond;
const GLint64 end_timestamp = 32 * base::Time::kNanosecondsPerMicrosecond;
const int64_t expect_start_time =
(start_timestamp / base::Time::kNanosecondsPerMicrosecond) +
offset_time;
const int64_t expect_end_time =
(end_timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_time;
FakeCommandBufferServiceBase command_buffer_service;
MockOutputter outputter;
MockGLES2Decoder decoder(&command_buffer_service, &outputter);
EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext()));
GPUTracerTester tracer(&decoder);
tracer.SetTracingEnabled(true);
gl_fake_queries_.SetCurrentGLTime(start_timestamp);
g_fakeCPUTime = expect_start_time;
ASSERT_TRUE(tracer.BeginDecoding());
ExpectTraceQueryMocks();
// This will test multiple marker sources which overlap one another.
for (int i = 0; i < NUM_TRACER_SOURCES; ++i) {
// Set times so each source has a different time.
gl_fake_queries_.SetCurrentGLTime(
start_timestamp +
(i * base::Time::kNanosecondsPerMicrosecond));
g_fakeCPUTime = expect_start_time + i;
// Each trace name should be different to differentiate.
const char num_char = static_cast<char>('0' + i);
std::string source_category = category_name + num_char;
std::string source_trace_name = trace_name + num_char;
const GpuTracerSource source = static_cast<GpuTracerSource>(i);
ExpectOutputterBeginMocks(&outputter, source, source_category,
source_trace_name);
ASSERT_TRUE(tracer.Begin(source_category, source_trace_name, source));
}
for (int i = 0; i < NUM_TRACER_SOURCES; ++i) {
// Set times so each source has a different time.
gl_fake_queries_.SetCurrentGLTime(
end_timestamp +
(i * base::Time::kNanosecondsPerMicrosecond));
g_fakeCPUTime = expect_end_time + i;
// Each trace name should be different to differentiate.
const char num_char = static_cast<char>('0' + i);
std::string source_category = category_name + num_char;
std::string source_trace_name = trace_name + num_char;
const bool valid_timer = gpu_timing_client_->IsAvailable();
const GpuTracerSource source = static_cast<GpuTracerSource>(i);
ExpectOutputterEndMocks(&outputter, source, source_category,
source_trace_name, expect_start_time + i,
expect_end_time + i, true, valid_timer);
// Check if the current category/name are correct for this source.
ASSERT_EQ(source_category, tracer.CurrentCategory(source));
ASSERT_EQ(source_trace_name, tracer.CurrentName(source));
ASSERT_TRUE(tracer.End(source));
}
ASSERT_TRUE(tracer.EndDecoding());
tracer.ProcessTraces();
}
void DoOngoingTracerMarkerTest() {
ExpectTracerOffsetQueryMocks();
gl_fake_queries_.ExpectGetErrorCalls(*gl_);
const std::string category_name("trace_category");
const std::string trace_name("trace_test");
const GpuTracerSource source = static_cast<GpuTracerSource>(0);
const int64_t offset_time = 3231;
const GLint64 start_timestamp = 7 * base::Time::kNanosecondsPerMicrosecond;
const int64_t expect_start_time =
(start_timestamp / base::Time::kNanosecondsPerMicrosecond) +
offset_time;
const bool valid_timer = gpu_timing_client_->IsAvailable();
FakeCommandBufferServiceBase command_buffer_service;
MockOutputter outputter;
MockGLES2Decoder decoder(&command_buffer_service, &outputter);
EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext()));
GPUTracerTester tracer(&decoder);
// Create trace marker while traces are disabled.
gl_fake_queries_.SetCurrentGLTime(start_timestamp);
g_fakeCPUTime = expect_start_time;
tracer.SetTracingEnabled(false);
ASSERT_TRUE(tracer.BeginDecoding());
ASSERT_TRUE(tracer.Begin(category_name, trace_name, source));
ASSERT_TRUE(tracer.EndDecoding());
// Enable traces now.
tracer.SetTracingEnabled(true);
ExpectTraceQueryMocks();
// trace should happen when decoding begins, at time start+1.
gl_fake_queries_.SetCurrentGLTime(
start_timestamp +
(1 * base::Time::kNanosecondsPerMicrosecond));
g_fakeCPUTime = expect_start_time + 1;
ASSERT_TRUE(tracer.BeginDecoding());
// End decoding at time start+2.
ExpectOutputterEndMocks(&outputter, source, category_name, trace_name,
expect_start_time + 1, expect_start_time + 2, true,
valid_timer);
gl_fake_queries_.SetCurrentGLTime(
start_timestamp +
(2 * base::Time::kNanosecondsPerMicrosecond));
g_fakeCPUTime = expect_start_time + 2;
ASSERT_TRUE(tracer.EndDecoding());
// Begin decoding again at time start+3.
gl_fake_queries_.SetCurrentGLTime(
start_timestamp +
(3 * base::Time::kNanosecondsPerMicrosecond));
g_fakeCPUTime = expect_start_time + 3;
ASSERT_TRUE(tracer.BeginDecoding());
// End trace at time start+4
gl_fake_queries_.SetCurrentGLTime(
start_timestamp +
(4 * base::Time::kNanosecondsPerMicrosecond));
g_fakeCPUTime = expect_start_time + 4;
ExpectOutputterEndMocks(&outputter, source, category_name, trace_name,
expect_start_time + 3, expect_start_time + 4, true,
valid_timer);
ASSERT_TRUE(tracer.End(source));
// Increment time before we end decoding to test trace does not stop here.
gl_fake_queries_.SetCurrentGLTime(
start_timestamp +
(5 * base::Time::kNanosecondsPerMicrosecond));
g_fakeCPUTime = expect_start_time + 5;
ASSERT_TRUE(tracer.EndDecoding());
tracer.ProcessTraces();
}
void DoDisjointTest() {
// Cause a disjoint in a middle of a trace and expect no output calls.
ExpectTracerOffsetQueryMocks();
gl_fake_queries_.ExpectGetErrorCalls(*gl_);
const std::string category_name("trace_category");
const std::string trace_name("trace_test");
const GpuTracerSource source = static_cast<GpuTracerSource>(0);
const int64_t offset_time = 3231;
const GLint64 start_timestamp = 7 * base::Time::kNanosecondsPerMicrosecond;
const GLint64 end_timestamp = 32 * base::Time::kNanosecondsPerMicrosecond;
const int64_t expect_start_time =
(start_timestamp / base::Time::kNanosecondsPerMicrosecond) +
offset_time;
const int64_t expect_end_time =
(end_timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_time;
FakeCommandBufferServiceBase command_buffer_service;
MockOutputter outputter;
MockGLES2Decoder decoder(&command_buffer_service, &outputter);
EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext()));
GPUTracerTester tracer(&decoder);
tracer.SetTracingEnabled(true);
gl_fake_queries_.SetCurrentGLTime(start_timestamp);
g_fakeCPUTime = expect_start_time;
ASSERT_TRUE(tracer.BeginDecoding());
ExpectTraceQueryMocks();
ExpectOutputterBeginMocks(&outputter, source, category_name, trace_name);
ASSERT_TRUE(tracer.Begin(category_name, trace_name, source));
gl_fake_queries_.SetCurrentGLTime(end_timestamp);
g_fakeCPUTime = expect_end_time;
// Create GPUTimingClient to make sure disjoint value is correct. This
// should not interfere with the tracer's disjoint value.
scoped_refptr<gl::GPUTimingClient> disjoint_client =
GetGLContext()->CreateGPUTimingClient();
// We assert here based on the disjoint_client because if disjoints are not
// working properly there is no point testing the tracer output.
ASSERT_FALSE(disjoint_client->CheckAndResetTimerErrors());
gl_fake_queries_.SetDisjoint();
ASSERT_TRUE(disjoint_client->CheckAndResetTimerErrors());
ExpectDisjointOutputMocks(&outputter, expect_start_time, expect_end_time);
ExpectOutputterEndMocks(&outputter, source, category_name, trace_name,
expect_start_time, expect_end_time, true, false);
ASSERT_TRUE(tracer.End(source));
ASSERT_TRUE(tracer.EndDecoding());
tracer.ProcessTraces();
}
void DoOutsideDisjointTest() {
ExpectTracerOffsetQueryMocks();
gl_fake_queries_.ExpectGetErrorCalls(*gl_);
const std::string category_name("trace_category");
const std::string trace_name("trace_test");
const GpuTracerSource source = static_cast<GpuTracerSource>(0);
const int64_t offset_time = 3231;
const GLint64 start_timestamp = 7 * base::Time::kNanosecondsPerMicrosecond;
const GLint64 end_timestamp = 32 * base::Time::kNanosecondsPerMicrosecond;
const int64_t expect_start_time =
(start_timestamp / base::Time::kNanosecondsPerMicrosecond) +
offset_time;
const int64_t expect_end_time =
(end_timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_time;
FakeCommandBufferServiceBase command_buffer_service;
MockOutputter outputter;
MockGLES2Decoder decoder(&command_buffer_service, &outputter);
EXPECT_CALL(decoder, GetGLContext()).WillOnce(Return(GetGLContext()));
EXPECT_CALL(decoder, MakeCurrent()).WillRepeatedly(Return(true));
GPUTracerTester tracer(&decoder);
// Start a trace before tracing is enabled.
tracer.SetTracingEnabled(false);
ASSERT_TRUE(tracer.BeginDecoding());
ASSERT_TRUE(tracer.Begin(category_name, trace_name, source));
ASSERT_TRUE(tracer.EndDecoding());
// Enabling traces now, trace should be ongoing.
tracer.SetTracingEnabled(true);
gl_fake_queries_.SetCurrentGLTime(start_timestamp);
g_fakeCPUTime = expect_start_time;
// Disjoints before we start tracing anything should not do anything.
ExpectNoDisjointOutputMocks(&outputter);
gl_fake_queries_.SetDisjoint();
ExpectTraceQueryMocks();
ExpectOutputterBeginMocks(&outputter, source, category_name, trace_name);
ASSERT_TRUE(tracer.BeginDecoding());
// Set times so each source has a different time.
gl_fake_queries_.SetCurrentGLTime(end_timestamp);
g_fakeCPUTime = expect_end_time;
ExpectOutputterEndMocks(&outputter, source, category_name, trace_name,
expect_start_time, expect_end_time, true, true);
ASSERT_TRUE(tracer.End(source));
ASSERT_TRUE(tracer.EndDecoding());
tracer.ProcessTraces();
}
};
class InvalidTimerTracerTest : public BaseGpuTracerTest {
public:
InvalidTimerTracerTest()
: BaseGpuTracerTest(gl::GPUTiming::kTimerTypeInvalid) {}
};
class GpuEXTTimerTracerTest : public BaseGpuTracerTest {
public:
GpuEXTTimerTracerTest() : BaseGpuTracerTest(gl::GPUTiming::kTimerTypeEXT) {}
};
class GpuARBTimerTracerTest : public BaseGpuTracerTest {
public:
GpuARBTimerTracerTest() : BaseGpuTracerTest(gl::GPUTiming::kTimerTypeARB) {}
};
class GpuDisjointTimerTracerTest : public BaseGpuTracerTest {
public:
GpuDisjointTimerTracerTest()
: BaseGpuTracerTest(gl::GPUTiming::kTimerTypeDisjoint) {}
};
TEST_F(InvalidTimerTracerTest, InvalidTimerBasicTracerTest) {
DoBasicTracerTest();
}
TEST_F(GpuEXTTimerTracerTest, EXTTimerBasicTracerTest) {
DoBasicTracerTest();
}
TEST_F(GpuARBTimerTracerTest, ARBTimerBasicTracerTest) {
DoBasicTracerTest();
}
TEST_F(GpuDisjointTimerTracerTest, DisjointTimerBasicTracerTest) {
DoBasicTracerTest();
}
TEST_F(InvalidTimerTracerTest, InvalidTimerDisabledTest) {
DoDisabledTracingTest();
}
TEST_F(GpuEXTTimerTracerTest, EXTTimerDisabledTest) {
DoDisabledTracingTest();
}
TEST_F(GpuARBTimerTracerTest, ARBTimerDisabledTest) {
DoDisabledTracingTest();
}
TEST_F(GpuDisjointTimerTracerTest, DisjointTimerDisabledTest) {
DoDisabledTracingTest();
}
TEST_F(InvalidTimerTracerTest, InvalidTimerTracerMarkersTest) {
DoTracerMarkersTest();
}
TEST_F(GpuEXTTimerTracerTest, EXTTimerTracerMarkersTest) {
DoTracerMarkersTest();
}
TEST_F(GpuARBTimerTracerTest, ARBTimerTracerMarkersTest) {
DoTracerMarkersTest();
}
TEST_F(GpuDisjointTimerTracerTest, DisjointTimerBasicTracerMarkersTest) {
DoTracerMarkersTest();
}
TEST_F(InvalidTimerTracerTest, InvalidTimerOngoingTracerMarkersTest) {
DoOngoingTracerMarkerTest();
}
TEST_F(GpuEXTTimerTracerTest, EXTTimerOngoingTracerMarkersTest) {
DoOngoingTracerMarkerTest();
}
TEST_F(GpuARBTimerTracerTest, ARBTimerBasicOngoingTracerMarkersTest) {
DoOngoingTracerMarkerTest();
}
TEST_F(GpuDisjointTimerTracerTest, DisjointTimerOngoingTracerMarkersTest) {
DoOngoingTracerMarkerTest();
}
TEST_F(GpuDisjointTimerTracerTest, DisjointTimerDisjointTraceTest) {
DoDisjointTest();
}
TEST_F(GpuDisjointTimerTracerTest, NonrelevantDisjointTraceTest) {
DoOutsideDisjointTest();
}
class GPUTracerTest : public GpuServiceTest {
protected:
void SetUp() override {
g_fakeCPUTime = 0;
GpuServiceTest::SetUpWithGLVersion("3.2", "");
decoder_.reset(new MockGLES2Decoder(&command_buffer_service_, &outputter_));
EXPECT_CALL(*decoder_, GetGLContext())
.Times(AtMost(1))
.WillRepeatedly(Return(GetGLContext()));
tracer_tester_.reset(new GPUTracerTester(decoder_.get()));
}
void TearDown() override {
tracer_tester_ = nullptr;
decoder_ = nullptr;
GpuServiceTest::TearDown();
}
FakeCommandBufferServiceBase command_buffer_service_;
MockOutputter outputter_;
std::unique_ptr<MockGLES2Decoder> decoder_;
std::unique_ptr<GPUTracerTester> tracer_tester_;
};
TEST_F(GPUTracerTest, IsTracingTest) {
EXPECT_FALSE(tracer_tester_->IsTracing());
tracer_tester_->SetTracingEnabled(true);
EXPECT_TRUE(tracer_tester_->IsTracing());
}
// Test basic functionality of the GPUTracerTester.
TEST_F(GPUTracerTest, DecodeTest) {
ASSERT_TRUE(tracer_tester_->BeginDecoding());
EXPECT_FALSE(tracer_tester_->BeginDecoding());
ASSERT_TRUE(tracer_tester_->EndDecoding());
EXPECT_FALSE(tracer_tester_->EndDecoding());
}
TEST_F(GPUTracerTest, TraceDuringDecodeTest) {
const std::string category_name("trace_category");
const std::string trace_name("trace_test");
EXPECT_FALSE(
tracer_tester_->Begin(category_name, trace_name, kTraceCHROMIUM));
ASSERT_TRUE(tracer_tester_->BeginDecoding());
EXPECT_TRUE(
tracer_tester_->Begin(category_name, trace_name, kTraceCHROMIUM));
ASSERT_TRUE(tracer_tester_->EndDecoding());
}
TEST_F(GpuDisjointTimerTracerTest, MultipleClientsDisjointTest) {
scoped_refptr<gl::GPUTimingClient> client1 =
GetGLContext()->CreateGPUTimingClient();
scoped_refptr<gl::GPUTimingClient> client2 =
GetGLContext()->CreateGPUTimingClient();
// Test both clients are initialized as no errors.
ASSERT_FALSE(client1->CheckAndResetTimerErrors());
ASSERT_FALSE(client2->CheckAndResetTimerErrors());
// Issue a disjoint.
gl_fake_queries_.SetDisjoint();
ASSERT_TRUE(client1->CheckAndResetTimerErrors());
ASSERT_TRUE(client2->CheckAndResetTimerErrors());
// Test both are now reset.
ASSERT_FALSE(client1->CheckAndResetTimerErrors());
ASSERT_FALSE(client2->CheckAndResetTimerErrors());
// Issue a disjoint.
gl_fake_queries_.SetDisjoint();
// Test new client disjoint value is cleared.
scoped_refptr<gl::GPUTimingClient> client3 =
GetGLContext()->CreateGPUTimingClient();
ASSERT_TRUE(client1->CheckAndResetTimerErrors());
ASSERT_TRUE(client2->CheckAndResetTimerErrors());
ASSERT_FALSE(client3->CheckAndResetTimerErrors());
}
} // namespace
} // namespace gles2
} // namespace gpu