Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(62)

Side by Side Diff: gpu/command_buffer/service/memory_program_cache_unittest.cc

Issue 10797055: gpu in-memory program cache implementation with a memory limit + lru eviction. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: nit fixes Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « gpu/command_buffer/service/memory_program_cache.cc ('k') | gpu/command_buffer/service/mocks.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012 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
5 #include "gpu/command_buffer/service/memory_program_cache.h"
6
7 #include "gpu/command_buffer/common/gl_mock.h"
8 #include "gpu/command_buffer/common/gles2_cmd_format.h"
9 #include "gpu/command_buffer/service/gl_utils.h"
10 #include "gpu/command_buffer/service/shader_translator.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "ui/gl/gl_bindings.h"
13
14 using ::testing::_;
15 using ::testing::ElementsAreArray;
16 using ::testing::Invoke;
17 using ::testing::SetArgPointee;
18 using ::testing::SetArrayArgument;
19
20 namespace {
21 typedef gpu::gles2::ShaderTranslator::VariableMap VariableMap;
22 } // anonymous namespace
23
24 namespace gpu {
25 namespace gles2 {
26
27 class ProgramBinaryEmulator {
28 public:
29 ProgramBinaryEmulator(GLsizei length,
30 GLenum format,
31 const char* binary)
32 : length_(length),
33 format_(format),
34 binary_(binary) { }
35
36 void GetProgramBinary(GLuint program,
37 GLsizei buffer_size,
38 GLsizei* length,
39 GLenum* format,
40 GLvoid* binary) {
41 *length = length_;
42 *format = format_;
43 memcpy(binary, binary_, length_);
44 }
45
46 void ProgramBinary(GLuint program,
47 GLenum format,
48 const GLvoid* binary,
49 GLsizei length) {
50 // format and length are verified by matcher
51 EXPECT_EQ(0, memcmp(binary_, binary, length));
52 }
53
54 GLsizei length() const { return length_; }
55 GLenum format() const { return format_; }
56 const char* binary() const { return binary_; }
57
58 private:
59 GLsizei length_;
60 GLenum format_;
61 const char* binary_;
62 };
63
64 class MemoryProgramCacheTest : public testing::Test {
65 public:
66 static const size_t kCacheSizeBytes = 1024;
67 static const GLuint kVertexShaderClientId = 90;
68 static const GLuint kVertexShaderServiceId = 100;
69 static const GLuint kFragmentShaderClientId = 91;
70 static const GLuint kFragmentShaderServiceId = 100;
71
72 MemoryProgramCacheTest()
73 : cache_(new MemoryProgramCache(kCacheSizeBytes)),
74 vertex_shader_(NULL),
75 fragment_shader_(NULL) { }
76 ~MemoryProgramCacheTest() {
77 shader_manager_.Destroy(false);
78 }
79
80 protected:
81 virtual void SetUp() {
82 gl_.reset(new ::testing::StrictMock<gfx::MockGLInterface>());
83 ::gfx::GLInterface::SetGLInterface(gl_.get());
84
85 vertex_shader_ = shader_manager_.CreateShaderInfo(kVertexShaderClientId,
86 kVertexShaderServiceId,
87 GL_VERTEX_SHADER);
88 fragment_shader_ = shader_manager_.CreateShaderInfo(
89 kFragmentShaderClientId,
90 kFragmentShaderServiceId,
91 GL_FRAGMENT_SHADER);
92 ASSERT_TRUE(vertex_shader_ != NULL);
93 ASSERT_TRUE(fragment_shader_ != NULL);
94 typedef ShaderTranslatorInterface::VariableInfo VariableInfo;
95 typedef ShaderTranslator::VariableMap VariableMap;
96 VariableMap vertex_attrib_map;
97 VariableMap vertex_uniform_map;
98 VariableMap fragment_attrib_map;
99 VariableMap fragment_uniform_map;
100
101 vertex_attrib_map["a"] = VariableInfo(1, 34, "a");
102 vertex_uniform_map["a"] = VariableInfo(0, 10, "a");
103 vertex_uniform_map["b"] = VariableInfo(2, 3114, "b");
104 fragment_attrib_map["jjjbb"] = VariableInfo(463, 1114, "jjjbb");
105 fragment_uniform_map["k"] = VariableInfo(10, 34413, "k");
106
107 vertex_shader_->set_attrib_map(vertex_attrib_map);
108 vertex_shader_->set_uniform_map(vertex_uniform_map);
109 fragment_shader_->set_attrib_map(vertex_attrib_map);
110 fragment_shader_->set_uniform_map(vertex_uniform_map);
111
112 vertex_shader_->UpdateSource("bbbalsldkdkdkd");
113 fragment_shader_->UpdateSource("bbbal sldkdkdkas 134 ad");
114 vertex_shader_->FlagSourceAsCompiled(true);
115 fragment_shader_->FlagSourceAsCompiled(true);
116
117 vertex_shader_->SetStatus(true, NULL, NULL);
118 fragment_shader_->SetStatus(true, NULL, NULL);
119 }
120
121 virtual void TearDown() {
122 ::gfx::GLInterface::SetGLInterface(NULL);
123 gl_.reset();
124 }
125
126 void SetExpectationsForSaveLinkedProgram(
127 const GLint program_id,
128 ProgramBinaryEmulator* emulator) const {
129 EXPECT_CALL(*gl_.get(),
130 GetProgramiv(program_id, GL_PROGRAM_BINARY_LENGTH_OES, _))
131 .WillOnce(SetArgPointee<2>(emulator->length()));
132 EXPECT_CALL(*gl_.get(),
133 GetProgramBinary(program_id, emulator->length(), _, _, _))
134 .WillOnce(Invoke(emulator, &ProgramBinaryEmulator::GetProgramBinary));
135 }
136
137 void SetExpectationsForLoadLinkedProgram(
138 const GLint program_id,
139 ProgramBinaryEmulator* emulator) const {
140 EXPECT_CALL(*gl_.get(),
141 ProgramBinary(program_id,
142 emulator->format(),
143 _,
144 emulator->length()))
145 .WillOnce(Invoke(emulator, &ProgramBinaryEmulator::ProgramBinary));
146 EXPECT_CALL(*gl_.get(),
147 GetProgramiv(program_id, GL_LINK_STATUS, _))
148 .WillOnce(SetArgPointee<2>(GL_TRUE));
149 }
150
151 void SetExpectationsForLoadLinkedProgramFailure(
152 const GLint program_id,
153 ProgramBinaryEmulator* emulator) const {
154 EXPECT_CALL(*gl_.get(),
155 ProgramBinary(program_id,
156 emulator->format(),
157 _,
158 emulator->length()))
159 .WillOnce(Invoke(emulator, &ProgramBinaryEmulator::ProgramBinary));
160 EXPECT_CALL(*gl_.get(),
161 GetProgramiv(program_id, GL_LINK_STATUS, _))
162 .WillOnce(SetArgPointee<2>(GL_FALSE));
163 }
164
165 // Use StrictMock to make 100% sure we know how GL will be called.
166 scoped_ptr< ::testing::StrictMock<gfx::MockGLInterface> > gl_;
167 scoped_ptr<MemoryProgramCache> cache_;
168 ShaderManager shader_manager_;
169 ShaderManager::ShaderInfo* vertex_shader_;
170 ShaderManager::ShaderInfo* fragment_shader_;
171 };
172
173 TEST_F(MemoryProgramCacheTest, CacheSave) {
174 const GLenum kFormat = 1;
175 const int kProgramId = 10;
176 const int kBinaryLength = 20;
177 char test_binary[kBinaryLength];
178 for (int i = 0; i < kBinaryLength; ++i) {
179 test_binary[i] = i;
180 }
181 ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
182
183 SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
184 cache_->SaveLinkedProgram(kProgramId, vertex_shader_, fragment_shader_, NULL);
185
186 EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
187 *vertex_shader_->deferred_compilation_source(),
188 *fragment_shader_->deferred_compilation_source(),
189 NULL));
190 }
191
192 TEST_F(MemoryProgramCacheTest, CacheLoadMatchesSave) {
193 const GLenum kFormat = 1;
194 const int kProgramId = 10;
195 const int kBinaryLength = 20;
196 char test_binary[kBinaryLength];
197 for (int i = 0; i < kBinaryLength; ++i) {
198 test_binary[i] = i;
199 }
200 ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
201
202 SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
203 cache_->SaveLinkedProgram(kProgramId, vertex_shader_, fragment_shader_, NULL);
204
205 VariableMap vertex_attrib_map = vertex_shader_->attrib_map();
206 VariableMap vertex_uniform_map = vertex_shader_->uniform_map();
207 VariableMap fragment_attrib_map = fragment_shader_->attrib_map();
208 VariableMap fragment_uniform_map = fragment_shader_->uniform_map();
209
210 vertex_shader_->set_attrib_map(VariableMap());
211 vertex_shader_->set_uniform_map(VariableMap());
212 fragment_shader_->set_attrib_map(VariableMap());
213 fragment_shader_->set_uniform_map(VariableMap());
214
215 SetExpectationsForLoadLinkedProgram(kProgramId, &emulator);
216
217 EXPECT_EQ(ProgramCache::PROGRAM_LOAD_SUCCESS, cache_->LoadLinkedProgram(
218 kProgramId,
219 vertex_shader_,
220 fragment_shader_,
221 NULL));
222
223 // apparently the hash_map implementation on android doesn't have the
224 // equality operator
225 #if !defined(OS_ANDROID)
226 EXPECT_EQ(vertex_attrib_map, vertex_shader_->attrib_map());
227 EXPECT_EQ(vertex_attrib_map, vertex_shader_->uniform_map());
228 EXPECT_EQ(vertex_attrib_map, fragment_shader_->attrib_map());
229 EXPECT_EQ(vertex_attrib_map, fragment_shader_->uniform_map());
230 #endif
231 }
232
233 TEST_F(MemoryProgramCacheTest, LoadFailOnLinkFalse) {
234 const GLenum kFormat = 1;
235 const int kProgramId = 10;
236 const int kBinaryLength = 20;
237 char test_binary[kBinaryLength];
238 for (int i = 0; i < kBinaryLength; ++i) {
239 test_binary[i] = i;
240 }
241 ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
242
243 SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
244 cache_->SaveLinkedProgram(kProgramId, vertex_shader_, fragment_shader_, NULL);
245
246 SetExpectationsForLoadLinkedProgramFailure(kProgramId, &emulator);
247 EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE, cache_->LoadLinkedProgram(
248 kProgramId,
249 vertex_shader_,
250 fragment_shader_,
251 NULL));
252 }
253
254 TEST_F(MemoryProgramCacheTest, LoadFailOnDifferentSource) {
255 const GLenum kFormat = 1;
256 const int kProgramId = 10;
257 const int kBinaryLength = 20;
258 char test_binary[kBinaryLength];
259 for (int i = 0; i < kBinaryLength; ++i) {
260 test_binary[i] = i;
261 }
262 ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
263
264 SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
265 cache_->SaveLinkedProgram(kProgramId, vertex_shader_, fragment_shader_, NULL);
266
267 const std::string vertex_orig_source =
268 *vertex_shader_->deferred_compilation_source();
269 vertex_shader_->UpdateSource("different!");
270 vertex_shader_->FlagSourceAsCompiled(true);
271 EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE, cache_->LoadLinkedProgram(
272 kProgramId,
273 vertex_shader_,
274 fragment_shader_,
275 NULL));
276
277 vertex_shader_->UpdateSource(vertex_orig_source.c_str());
278 vertex_shader_->FlagSourceAsCompiled(true);
279 fragment_shader_->UpdateSource("different!");
280 fragment_shader_->FlagSourceAsCompiled(true);
281 EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE, cache_->LoadLinkedProgram(
282 kProgramId,
283 vertex_shader_,
284 fragment_shader_,
285 NULL));
286 }
287
288 TEST_F(MemoryProgramCacheTest, LoadFailOnDifferentMap) {
289 const GLenum kFormat = 1;
290 const int kProgramId = 10;
291 const int kBinaryLength = 20;
292 char test_binary[kBinaryLength];
293 for (int i = 0; i < kBinaryLength; ++i) {
294 test_binary[i] = i;
295 }
296 ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
297
298 SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
299 ProgramCache::LocationMap binding_map;
300 binding_map["test"] = 512;
301 cache_->SaveLinkedProgram(kProgramId,
302 vertex_shader_,
303 fragment_shader_,
304 &binding_map);
305
306 binding_map["different!"] = 59;
307 EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE, cache_->LoadLinkedProgram(
308 kProgramId,
309 vertex_shader_,
310 fragment_shader_,
311 &binding_map));
312 EXPECT_EQ(ProgramCache::PROGRAM_LOAD_FAILURE, cache_->LoadLinkedProgram(
313 kProgramId,
314 vertex_shader_,
315 fragment_shader_,
316 NULL));
317 }
318
319 TEST_F(MemoryProgramCacheTest, MemoryProgramCacheEviction) {
320 typedef ShaderTranslator::VariableMap VariableMap;
321 const GLenum kFormat = 1;
322 const int kProgramId = 10;
323 const int kBinaryLength = 20;
324 char test_binary[kBinaryLength];
325 for (int i = 0; i < kBinaryLength; ++i) {
326 test_binary[i] = i;
327 }
328 ProgramBinaryEmulator emulator1(kBinaryLength, kFormat, test_binary);
329
330
331 SetExpectationsForSaveLinkedProgram(kProgramId, &emulator1);
332 cache_->SaveLinkedProgram(kProgramId, vertex_shader_, fragment_shader_, NULL);
333
334 const int kEvictingProgramId = 11;
335 const GLuint kEvictingBinaryLength = kCacheSizeBytes - kBinaryLength + 1;
336
337 // save old source and modify for new program
338 const std::string old_source =
339 *fragment_shader_->deferred_compilation_source();
340 fragment_shader_->UpdateSource("al sdfkjdk");
341 fragment_shader_->FlagSourceAsCompiled(true);
342
343 scoped_array<char> bigTestBinary =
344 scoped_array<char>(new char[kEvictingBinaryLength]);
345 for (size_t i = 0; i < kEvictingBinaryLength; ++i) {
346 bigTestBinary[i] = i % 250;
347 }
348 ProgramBinaryEmulator emulator2(kEvictingBinaryLength,
349 kFormat,
350 bigTestBinary.get());
351
352 SetExpectationsForSaveLinkedProgram(kEvictingProgramId, &emulator2);
353 cache_->SaveLinkedProgram(kEvictingProgramId,
354 vertex_shader_,
355 fragment_shader_,
356 NULL);
357
358 EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
359 *vertex_shader_->deferred_compilation_source(),
360 *fragment_shader_->deferred_compilation_source(),
361 NULL));
362 EXPECT_EQ(ProgramCache::LINK_UNKNOWN, cache_->GetLinkedProgramStatus(
363 old_source,
364 *fragment_shader_->deferred_compilation_source(),
365 NULL));
366 }
367
368 TEST_F(MemoryProgramCacheTest, SaveCorrectProgram) {
369 const GLenum kFormat = 1;
370 const int kProgramId = 10;
371 const int kBinaryLength = 20;
372 char test_binary[kBinaryLength];
373 for (int i = 0; i < kBinaryLength; ++i) {
374 test_binary[i] = i;
375 }
376 ProgramBinaryEmulator emulator1(kBinaryLength, kFormat, test_binary);
377
378 vertex_shader_->UpdateSource("different!");
379 SetExpectationsForSaveLinkedProgram(kProgramId, &emulator1);
380 cache_->SaveLinkedProgram(kProgramId, vertex_shader_, fragment_shader_, NULL);
381
382 EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
383 *vertex_shader_->deferred_compilation_source(),
384 *fragment_shader_->deferred_compilation_source(),
385 NULL));
386 }
387
388 TEST_F(MemoryProgramCacheTest, LoadCorrectProgram) {
389 const GLenum kFormat = 1;
390 const int kProgramId = 10;
391 const int kBinaryLength = 20;
392 char test_binary[kBinaryLength];
393 for (int i = 0; i < kBinaryLength; ++i) {
394 test_binary[i] = i;
395 }
396 ProgramBinaryEmulator emulator(kBinaryLength, kFormat, test_binary);
397
398 SetExpectationsForSaveLinkedProgram(kProgramId, &emulator);
399 cache_->SaveLinkedProgram(kProgramId, vertex_shader_, fragment_shader_, NULL);
400
401 EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
402 *vertex_shader_->deferred_compilation_source(),
403 *fragment_shader_->deferred_compilation_source(),
404 NULL));
405
406 SetExpectationsForLoadLinkedProgram(kProgramId, &emulator);
407
408 fragment_shader_->UpdateSource("different!");
409 EXPECT_EQ(ProgramCache::PROGRAM_LOAD_SUCCESS, cache_->LoadLinkedProgram(
410 kProgramId,
411 vertex_shader_,
412 fragment_shader_,
413 NULL));
414 }
415
416 } // namespace gles2
417 } // namespace gpu
OLDNEW
« no previous file with comments | « gpu/command_buffer/service/memory_program_cache.cc ('k') | gpu/command_buffer/service/mocks.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698