1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
|
// 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 <map>
#include <set>
#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_mock.h"
namespace gpu {
namespace gles2 {
using ::testing::InvokeWithoutArgs;
using ::testing::Return;
using ::testing::ReturnRef;
using ::testing::ReturnPointee;
using ::testing::NotNull;
using ::testing::ElementsAreArray;
using ::testing::ElementsAre;
using ::testing::SetArrayArgument;
using ::testing::AtLeast;
using ::testing::SetArgPointee;
using ::testing::Pointee;
using ::testing::Unused;
using ::testing::Invoke;
using ::testing::_;
class MockOutputter : public Outputter {
public:
MockOutputter() {}
MOCK_METHOD3(Trace,
void(const std::string& name, int64 start_time, int64 end_time));
protected:
~MockOutputter() {}
};
class GlFakeQueries {
public:
GlFakeQueries() {}
void Reset() {
current_time_ = 0;
next_query_id_ = 23;
alloced_queries_.clear();
query_timestamp_.clear();
}
void SetCurrentGLTime(GLint64 current_time) { current_time_ = current_time; }
void GenQueriesARB(GLsizei n, GLuint* ids) {
for (GLsizei i = 0; i < n; i++) {
ids[i] = next_query_id_++;
alloced_queries_.insert(ids[i]);
}
}
void DeleteQueriesARB(GLsizei n, const GLuint* ids) {
for (GLsizei i = 0; i < n; i++) {
alloced_queries_.erase(ids[i]);
query_timestamp_.erase(ids[i]);
}
}
void GetQueryObjectiv(GLuint id, GLenum pname, GLint* params) {
switch (pname) {
case GL_QUERY_RESULT_AVAILABLE: {
std::map<GLuint, GLint64>::iterator it = query_timestamp_.find(id);
if (it != query_timestamp_.end() && it->second <= current_time_)
*params = 1;
else
*params = 0;
break;
}
default:
ASSERT_TRUE(false);
}
}
void QueryCounter(GLuint id, GLenum target) {
switch (target) {
case GL_TIMESTAMP:
ASSERT_TRUE(alloced_queries_.find(id) != alloced_queries_.end());
query_timestamp_[id] = current_time_;
break;
default:
ASSERT_TRUE(false);
}
}
void GetQueryObjectui64v(GLuint id, GLenum pname, GLuint64* params) {
switch (pname) {
case GL_QUERY_RESULT:
ASSERT_TRUE(query_timestamp_.find(id) != query_timestamp_.end());
*params = query_timestamp_.find(id)->second;
break;
default:
ASSERT_TRUE(false);
}
}
protected:
GLint64 current_time_;
GLuint next_query_id_;
std::set<GLuint> alloced_queries_;
std::map<GLuint, GLint64> query_timestamp_;
};
class BaseGpuTracerTest : public GpuServiceTest {
public:
BaseGpuTracerTest() {}
///////////////////////////////////////////////////////////////////////////
void DoTraceTest() {
MockOutputter* outputter = new MockOutputter();
scoped_refptr<Outputter> outputter_ref = outputter;
SetupTimerQueryMocks();
// Expected results
const std::string trace_name("trace_test");
const int64 offset_time = 3231;
const GLint64 start_timestamp = 7 * base::Time::kNanosecondsPerMicrosecond;
const GLint64 end_timestamp = 32 * base::Time::kNanosecondsPerMicrosecond;
const int64 expect_start_time =
(start_timestamp / base::Time::kNanosecondsPerMicrosecond) +
offset_time;
const int64 expect_end_time =
(end_timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_time;
// Expected Outputter::Trace call
EXPECT_CALL(*outputter,
Trace(trace_name, expect_start_time, expect_end_time));
scoped_refptr<GPUTrace> trace =
new GPUTrace(outputter_ref, trace_name, offset_time,
GetTracerType());
gl_fake_queries_.SetCurrentGLTime(start_timestamp);
trace->Start();
// Shouldn't be available before End() call
gl_fake_queries_.SetCurrentGLTime(end_timestamp);
EXPECT_FALSE(trace->IsAvailable());
trace->End();
// Shouldn't be available until the queries complete
gl_fake_queries_.SetCurrentGLTime(end_timestamp -
base::Time::kNanosecondsPerMicrosecond);
EXPECT_FALSE(trace->IsAvailable());
// Now it should be available
gl_fake_queries_.SetCurrentGLTime(end_timestamp);
EXPECT_TRUE(trace->IsAvailable());
// Proces should output expected Trace results to MockOutputter
trace->Process();
}
protected:
void SetUp() override {
GpuServiceTest::SetUp();
gl_fake_queries_.Reset();
}
void TearDown() override {
gl_.reset();
gl_fake_queries_.Reset();
GpuServiceTest::TearDown();
}
virtual void SetupTimerQueryMocks() {
// Delegate query APIs used by GPUTrace to a GlFakeQueries
EXPECT_CALL(*gl_, GenQueriesARB(_, NotNull())).Times(AtLeast(1)).WillOnce(
Invoke(&gl_fake_queries_, &GlFakeQueries::GenQueriesARB));
EXPECT_CALL(*gl_, GetQueryObjectiv(_, GL_QUERY_RESULT_AVAILABLE, NotNull()))
.Times(AtLeast(2))
.WillRepeatedly(
Invoke(&gl_fake_queries_, &GlFakeQueries::GetQueryObjectiv));
EXPECT_CALL(*gl_, QueryCounter(_, GL_TIMESTAMP))
.Times(AtLeast(2))
.WillRepeatedly(
Invoke(&gl_fake_queries_, &GlFakeQueries::QueryCounter));
EXPECT_CALL(*gl_, GetQueryObjectui64v(_, GL_QUERY_RESULT, NotNull()))
.Times(AtLeast(2))
.WillRepeatedly(
Invoke(&gl_fake_queries_, &GlFakeQueries::GetQueryObjectui64v));
EXPECT_CALL(*gl_, DeleteQueriesARB(2, NotNull()))
.Times(AtLeast(1))
.WillRepeatedly(
Invoke(&gl_fake_queries_, &GlFakeQueries::DeleteQueriesARB));
}
virtual GpuTracerType GetTracerType() = 0;
GlFakeQueries gl_fake_queries_;
};
class GpuARBTimerTracerTest : public BaseGpuTracerTest {
protected:
GpuTracerType GetTracerType() override { return kTracerTypeARBTimer; }
};
class GpuDisjointTimerTracerTest : public BaseGpuTracerTest {
protected:
GpuTracerType GetTracerType() override { return kTracerTypeDisjointTimer; }
};
TEST_F(GpuARBTimerTracerTest, GPUTrace) {
// Test basic timer query functionality
{
DoTraceTest();
}
}
TEST_F(GpuDisjointTimerTracerTest, GPUTrace) {
// Test basic timer query functionality
{
DoTraceTest();
}
}
} // namespace gles2
} // namespace gpu
|