OLD | NEW |
---|---|
(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 testBinary[kBinaryLength]; | |
greggman
2012/07/21 00:49:32
style: variables are under_score
| |
178 for (int i = 0; i < kBinaryLength; ++i) { | |
179 testBinary[i] = i; | |
180 } | |
181 ProgramBinaryEmulator emulator(kBinaryLength, kFormat, testBinary); | |
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 testBinary[kBinaryLength]; | |
greggman
2012/07/21 00:49:32
style: variables are under_score
| |
197 for (int i = 0; i < kBinaryLength; ++i) { | |
198 testBinary[i] = i; | |
199 } | |
200 ProgramBinaryEmulator emulator(kBinaryLength, kFormat, testBinary); | |
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 testBinary[kBinaryLength]; | |
greggman
2012/07/21 00:49:32
style: variables are under_score
| |
238 for (int i = 0; i < kBinaryLength; ++i) { | |
239 testBinary[i] = i; | |
240 } | |
241 ProgramBinaryEmulator emulator(kBinaryLength, kFormat, testBinary); | |
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 testBinary[kBinaryLength]; | |
greggman
2012/07/21 00:49:32
style: variables are under_score
| |
259 for (int i = 0; i < kBinaryLength; ++i) { | |
260 testBinary[i] = i; | |
261 } | |
262 ProgramBinaryEmulator emulator(kBinaryLength, kFormat, testBinary); | |
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 testBinary[kBinaryLength]; | |
greggman
2012/07/21 00:49:32
style: variables are under_score
| |
293 for (int i = 0; i < kBinaryLength; ++i) { | |
294 testBinary[i] = i; | |
295 } | |
296 ProgramBinaryEmulator emulator(kBinaryLength, kFormat, testBinary); | |
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 testBinary[kBinaryLength]; | |
greggman
2012/07/21 00:49:32
style: variables are under_score
| |
325 for (int i = 0; i < kBinaryLength; ++i) { | |
326 testBinary[i] = i; | |
327 } | |
328 ProgramBinaryEmulator emulator1(kBinaryLength, kFormat, testBinary); | |
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 = | |
greggman
2012/07/21 00:49:32
style: variables are under_score
| |
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 testBinary[kBinaryLength]; | |
greggman
2012/07/21 00:49:32
style: variables are under_score
| |
373 for (int i = 0; i < kBinaryLength; ++i) { | |
374 testBinary[i] = i; | |
375 } | |
376 ProgramBinaryEmulator emulator1(kBinaryLength, kFormat, testBinary); | |
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 testBinary[kBinaryLength]; | |
greggman
2012/07/21 00:49:32
style: variables are under_score
| |
393 for (int i = 0; i < kBinaryLength; ++i) { | |
394 testBinary[i] = i; | |
395 } | |
396 ProgramBinaryEmulator emulator(kBinaryLength, kFormat, testBinary); | |
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 | |
OLD | NEW |