OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "gpu/command_buffer/service/memory_program_cache.h" | 5 #include "gpu/command_buffer/service/memory_program_cache.h" |
6 | 6 |
7 #include "base/base64.h" | 7 #include "base/base64.h" |
8 #include "base/callback.h" | 8 #include "base/callback.h" |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
(...skipping 22 matching lines...) Expand all Loading... |
33 return gpu::kDefaultMaxProgramCacheMemoryBytes; | 33 return gpu::kDefaultMaxProgramCacheMemoryBytes; |
34 } | 34 } |
35 | 35 |
36 } // anonymous namespace | 36 } // anonymous namespace |
37 | 37 |
38 namespace gpu { | 38 namespace gpu { |
39 namespace gles2 { | 39 namespace gles2 { |
40 | 40 |
41 namespace { | 41 namespace { |
42 | 42 |
43 enum ShaderMapType { | |
44 ATTRIB_MAP = 0, | |
45 UNIFORM_MAP, | |
46 VARYING_MAP | |
47 }; | |
48 | |
49 void FillShaderVariableProto( | 43 void FillShaderVariableProto( |
50 ShaderVariableProto* proto, const sh::ShaderVariable& variable) { | 44 ShaderVariableProto* proto, const sh::ShaderVariable& variable) { |
51 proto->set_type(variable.type); | 45 proto->set_type(variable.type); |
52 proto->set_precision(variable.precision); | 46 proto->set_precision(variable.precision); |
53 proto->set_name(variable.name); | 47 proto->set_name(variable.name); |
54 proto->set_mapped_name(variable.mappedName); | 48 proto->set_mapped_name(variable.mappedName); |
55 proto->set_array_size(variable.arraySize); | 49 proto->set_array_size(variable.arraySize); |
56 proto->set_static_use(variable.staticUse); | 50 proto->set_static_use(variable.staticUse); |
57 for (size_t ii = 0; ii < variable.fields.size(); ++ii) { | 51 for (size_t ii = 0; ii < variable.fields.size(); ++ii) { |
58 ShaderVariableProto* field = proto->add_fields(); | 52 ShaderVariableProto* field = proto->add_fields(); |
(...skipping 13 matching lines...) Expand all Loading... |
72 FillShaderVariableProto(proto->mutable_basic(), uniform); | 66 FillShaderVariableProto(proto->mutable_basic(), uniform); |
73 } | 67 } |
74 | 68 |
75 void FillShaderVaryingProto( | 69 void FillShaderVaryingProto( |
76 ShaderVaryingProto* proto, const sh::Varying& varying) { | 70 ShaderVaryingProto* proto, const sh::Varying& varying) { |
77 FillShaderVariableProto(proto->mutable_basic(), varying); | 71 FillShaderVariableProto(proto->mutable_basic(), varying); |
78 proto->set_interpolation(varying.interpolation); | 72 proto->set_interpolation(varying.interpolation); |
79 proto->set_is_invariant(varying.isInvariant); | 73 proto->set_is_invariant(varying.isInvariant); |
80 } | 74 } |
81 | 75 |
| 76 void FillShaderOutputVariableProto(ShaderOutputVariableProto* proto, |
| 77 const sh::OutputVariable& attrib) { |
| 78 FillShaderVariableProto(proto->mutable_basic(), attrib); |
| 79 proto->set_location(attrib.location); |
| 80 } |
| 81 |
82 void FillShaderProto(ShaderProto* proto, const char* sha, | 82 void FillShaderProto(ShaderProto* proto, const char* sha, |
83 const Shader* shader) { | 83 const Shader* shader) { |
84 proto->set_sha(sha, gpu::gles2::ProgramCache::kHashLength); | 84 proto->set_sha(sha, gpu::gles2::ProgramCache::kHashLength); |
85 for (AttributeMap::const_iterator iter = shader->attrib_map().begin(); | 85 for (AttributeMap::const_iterator iter = shader->attrib_map().begin(); |
86 iter != shader->attrib_map().end(); ++iter) { | 86 iter != shader->attrib_map().end(); ++iter) { |
87 ShaderAttributeProto* info = proto->add_attribs(); | 87 ShaderAttributeProto* info = proto->add_attribs(); |
88 FillShaderAttributeProto(info, iter->second); | 88 FillShaderAttributeProto(info, iter->second); |
89 } | 89 } |
90 for (UniformMap::const_iterator iter = shader->uniform_map().begin(); | 90 for (UniformMap::const_iterator iter = shader->uniform_map().begin(); |
91 iter != shader->uniform_map().end(); ++iter) { | 91 iter != shader->uniform_map().end(); ++iter) { |
92 ShaderUniformProto* info = proto->add_uniforms(); | 92 ShaderUniformProto* info = proto->add_uniforms(); |
93 FillShaderUniformProto(info, iter->second); | 93 FillShaderUniformProto(info, iter->second); |
94 } | 94 } |
95 for (VaryingMap::const_iterator iter = shader->varying_map().begin(); | 95 for (VaryingMap::const_iterator iter = shader->varying_map().begin(); |
96 iter != shader->varying_map().end(); ++iter) { | 96 iter != shader->varying_map().end(); ++iter) { |
97 ShaderVaryingProto* info = proto->add_varyings(); | 97 ShaderVaryingProto* info = proto->add_varyings(); |
98 FillShaderVaryingProto(info, iter->second); | 98 FillShaderVaryingProto(info, iter->second); |
99 } | 99 } |
| 100 for (auto iter = shader->output_variable_list().begin(); |
| 101 iter != shader->output_variable_list().end(); ++iter) { |
| 102 ShaderOutputVariableProto* info = proto->add_output_variables(); |
| 103 FillShaderOutputVariableProto(info, *iter); |
| 104 } |
100 } | 105 } |
101 | 106 |
102 void RetrieveShaderVariableInfo( | 107 void RetrieveShaderVariableInfo( |
103 const ShaderVariableProto& proto, sh::ShaderVariable* variable) { | 108 const ShaderVariableProto& proto, sh::ShaderVariable* variable) { |
104 variable->type = proto.type(); | 109 variable->type = proto.type(); |
105 variable->precision = proto.precision(); | 110 variable->precision = proto.precision(); |
106 variable->name = proto.name(); | 111 variable->name = proto.name(); |
107 variable->mappedName = proto.mapped_name(); | 112 variable->mappedName = proto.mapped_name(); |
108 variable->arraySize = proto.array_size(); | 113 variable->arraySize = proto.array_size(); |
109 variable->staticUse = proto.static_use(); | 114 variable->staticUse = proto.static_use(); |
(...skipping 21 matching lines...) Expand all Loading... |
131 void RetrieveShaderVaryingInfo( | 136 void RetrieveShaderVaryingInfo( |
132 const ShaderVaryingProto& proto, VaryingMap* map) { | 137 const ShaderVaryingProto& proto, VaryingMap* map) { |
133 sh::Varying varying; | 138 sh::Varying varying; |
134 RetrieveShaderVariableInfo(proto.basic(), &varying); | 139 RetrieveShaderVariableInfo(proto.basic(), &varying); |
135 varying.interpolation = static_cast<sh::InterpolationType>( | 140 varying.interpolation = static_cast<sh::InterpolationType>( |
136 proto.interpolation()); | 141 proto.interpolation()); |
137 varying.isInvariant = proto.is_invariant(); | 142 varying.isInvariant = proto.is_invariant(); |
138 (*map)[proto.basic().mapped_name()] = varying; | 143 (*map)[proto.basic().mapped_name()] = varying; |
139 } | 144 } |
140 | 145 |
| 146 void RetrieveShaderOutputVariableInfo(const ShaderOutputVariableProto& proto, |
| 147 OutputVariableList* list) { |
| 148 sh::OutputVariable output_variable; |
| 149 RetrieveShaderVariableInfo(proto.basic(), &output_variable); |
| 150 output_variable.location = proto.location(); |
| 151 list->push_back(output_variable); |
| 152 } |
| 153 |
141 void RunShaderCallback(const ShaderCacheCallback& callback, | 154 void RunShaderCallback(const ShaderCacheCallback& callback, |
142 GpuProgramProto* proto, | 155 GpuProgramProto* proto, |
143 std::string sha_string) { | 156 std::string sha_string) { |
144 std::string shader; | 157 std::string shader; |
145 proto->SerializeToString(&shader); | 158 proto->SerializeToString(&shader); |
146 | 159 |
147 std::string key; | 160 std::string key; |
148 base::Base64Encode(sha_string, &key); | 161 base::Base64Encode(sha_string, &key); |
149 callback.Run(key, shader); | 162 callback.Run(key, shader); |
150 } | 163 } |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
206 static_cast<const GLvoid*>(value->data()), | 219 static_cast<const GLvoid*>(value->data()), |
207 value->length()); | 220 value->length()); |
208 GLint success = 0; | 221 GLint success = 0; |
209 glGetProgramiv(program, GL_LINK_STATUS, &success); | 222 glGetProgramiv(program, GL_LINK_STATUS, &success); |
210 if (success == GL_FALSE) { | 223 if (success == GL_FALSE) { |
211 return PROGRAM_LOAD_FAILURE; | 224 return PROGRAM_LOAD_FAILURE; |
212 } | 225 } |
213 shader_a->set_attrib_map(value->attrib_map_0()); | 226 shader_a->set_attrib_map(value->attrib_map_0()); |
214 shader_a->set_uniform_map(value->uniform_map_0()); | 227 shader_a->set_uniform_map(value->uniform_map_0()); |
215 shader_a->set_varying_map(value->varying_map_0()); | 228 shader_a->set_varying_map(value->varying_map_0()); |
| 229 shader_a->set_output_variable_list(value->output_variable_list_0()); |
216 shader_b->set_attrib_map(value->attrib_map_1()); | 230 shader_b->set_attrib_map(value->attrib_map_1()); |
217 shader_b->set_uniform_map(value->uniform_map_1()); | 231 shader_b->set_uniform_map(value->uniform_map_1()); |
218 shader_b->set_varying_map(value->varying_map_1()); | 232 shader_b->set_varying_map(value->varying_map_1()); |
| 233 shader_b->set_output_variable_list(value->output_variable_list_1()); |
219 | 234 |
220 if (!shader_callback.is_null() && | 235 if (!shader_callback.is_null() && |
221 !base::CommandLine::ForCurrentProcess()->HasSwitch( | 236 !base::CommandLine::ForCurrentProcess()->HasSwitch( |
222 switches::kDisableGpuShaderDiskCache)) { | 237 switches::kDisableGpuShaderDiskCache)) { |
223 scoped_ptr<GpuProgramProto> proto( | 238 scoped_ptr<GpuProgramProto> proto( |
224 GpuProgramProto::default_instance().New()); | 239 GpuProgramProto::default_instance().New()); |
225 proto->set_sha(sha, kHashLength); | 240 proto->set_sha(sha, kHashLength); |
226 proto->set_format(value->format()); | 241 proto->set_format(value->format()); |
227 proto->set_program(value->data(), value->length()); | 242 proto->set_program(value->data(), value->length()); |
228 | 243 |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
295 GpuProgramProto::default_instance().New()); | 310 GpuProgramProto::default_instance().New()); |
296 proto->set_sha(sha, kHashLength); | 311 proto->set_sha(sha, kHashLength); |
297 proto->set_format(format); | 312 proto->set_format(format); |
298 proto->set_program(binary.get(), length); | 313 proto->set_program(binary.get(), length); |
299 | 314 |
300 FillShaderProto(proto->mutable_vertex_shader(), a_sha, shader_a); | 315 FillShaderProto(proto->mutable_vertex_shader(), a_sha, shader_a); |
301 FillShaderProto(proto->mutable_fragment_shader(), b_sha, shader_b); | 316 FillShaderProto(proto->mutable_fragment_shader(), b_sha, shader_b); |
302 RunShaderCallback(shader_callback, proto.get(), sha_string); | 317 RunShaderCallback(shader_callback, proto.get(), sha_string); |
303 } | 318 } |
304 | 319 |
305 store_.Put(sha_string, | 320 store_.Put( |
306 new ProgramCacheValue(length, | 321 sha_string, |
307 format, | 322 new ProgramCacheValue( |
308 binary.release(), | 323 length, format, binary.release(), sha_string, a_sha, |
309 sha_string, | 324 shader_a->attrib_map(), shader_a->uniform_map(), |
310 a_sha, | 325 shader_a->varying_map(), shader_a->output_variable_list(), b_sha, |
311 shader_a->attrib_map(), | 326 shader_b->attrib_map(), shader_b->uniform_map(), |
312 shader_a->uniform_map(), | 327 shader_b->varying_map(), shader_b->output_variable_list(), this)); |
313 shader_a->varying_map(), | |
314 b_sha, | |
315 shader_b->attrib_map(), | |
316 shader_b->uniform_map(), | |
317 shader_b->varying_map(), | |
318 this)); | |
319 | 328 |
320 UMA_HISTOGRAM_COUNTS("GPU.ProgramCache.MemorySizeAfterKb", | 329 UMA_HISTOGRAM_COUNTS("GPU.ProgramCache.MemorySizeAfterKb", |
321 curr_size_bytes_ / 1024); | 330 curr_size_bytes_ / 1024); |
322 } | 331 } |
323 | 332 |
324 void MemoryProgramCache::LoadProgram(const std::string& program) { | 333 void MemoryProgramCache::LoadProgram(const std::string& program) { |
325 scoped_ptr<GpuProgramProto> proto(GpuProgramProto::default_instance().New()); | 334 scoped_ptr<GpuProgramProto> proto(GpuProgramProto::default_instance().New()); |
326 if (proto->ParseFromString(program)) { | 335 if (proto->ParseFromString(program)) { |
327 AttributeMap vertex_attribs; | 336 AttributeMap vertex_attribs; |
328 UniformMap vertex_uniforms; | 337 UniformMap vertex_uniforms; |
329 VaryingMap vertex_varyings; | 338 VaryingMap vertex_varyings; |
| 339 OutputVariableList vertex_output_variables; |
330 for (int i = 0; i < proto->vertex_shader().attribs_size(); i++) { | 340 for (int i = 0; i < proto->vertex_shader().attribs_size(); i++) { |
331 RetrieveShaderAttributeInfo(proto->vertex_shader().attribs(i), | 341 RetrieveShaderAttributeInfo(proto->vertex_shader().attribs(i), |
332 &vertex_attribs); | 342 &vertex_attribs); |
333 } | 343 } |
334 for (int i = 0; i < proto->vertex_shader().uniforms_size(); i++) { | 344 for (int i = 0; i < proto->vertex_shader().uniforms_size(); i++) { |
335 RetrieveShaderUniformInfo(proto->vertex_shader().uniforms(i), | 345 RetrieveShaderUniformInfo(proto->vertex_shader().uniforms(i), |
336 &vertex_uniforms); | 346 &vertex_uniforms); |
337 } | 347 } |
338 for (int i = 0; i < proto->vertex_shader().varyings_size(); i++) { | 348 for (int i = 0; i < proto->vertex_shader().varyings_size(); i++) { |
339 RetrieveShaderVaryingInfo(proto->vertex_shader().varyings(i), | 349 RetrieveShaderVaryingInfo(proto->vertex_shader().varyings(i), |
340 &vertex_varyings); | 350 &vertex_varyings); |
341 } | 351 } |
| 352 for (int i = 0; i < proto->vertex_shader().output_variables_size(); i++) { |
| 353 RetrieveShaderOutputVariableInfo( |
| 354 proto->vertex_shader().output_variables(i), &vertex_output_variables); |
| 355 } |
342 | 356 |
343 AttributeMap fragment_attribs; | 357 AttributeMap fragment_attribs; |
344 UniformMap fragment_uniforms; | 358 UniformMap fragment_uniforms; |
345 VaryingMap fragment_varyings; | 359 VaryingMap fragment_varyings; |
| 360 OutputVariableList fragment_output_variables; |
346 for (int i = 0; i < proto->fragment_shader().attribs_size(); i++) { | 361 for (int i = 0; i < proto->fragment_shader().attribs_size(); i++) { |
347 RetrieveShaderAttributeInfo(proto->fragment_shader().attribs(i), | 362 RetrieveShaderAttributeInfo(proto->fragment_shader().attribs(i), |
348 &fragment_attribs); | 363 &fragment_attribs); |
349 } | 364 } |
350 for (int i = 0; i < proto->fragment_shader().uniforms_size(); i++) { | 365 for (int i = 0; i < proto->fragment_shader().uniforms_size(); i++) { |
351 RetrieveShaderUniformInfo(proto->fragment_shader().uniforms(i), | 366 RetrieveShaderUniformInfo(proto->fragment_shader().uniforms(i), |
352 &fragment_uniforms); | 367 &fragment_uniforms); |
353 } | 368 } |
354 for (int i = 0; i < proto->fragment_shader().varyings_size(); i++) { | 369 for (int i = 0; i < proto->fragment_shader().varyings_size(); i++) { |
355 RetrieveShaderVaryingInfo(proto->fragment_shader().varyings(i), | 370 RetrieveShaderVaryingInfo(proto->fragment_shader().varyings(i), |
356 &fragment_varyings); | 371 &fragment_varyings); |
357 } | 372 } |
| 373 for (int i = 0; i < proto->fragment_shader().output_variables_size(); i++) { |
| 374 RetrieveShaderOutputVariableInfo( |
| 375 proto->fragment_shader().output_variables(i), |
| 376 &fragment_output_variables); |
| 377 } |
358 | 378 |
359 scoped_ptr<char[]> binary(new char[proto->program().length()]); | 379 scoped_ptr<char[]> binary(new char[proto->program().length()]); |
360 memcpy(binary.get(), proto->program().c_str(), proto->program().length()); | 380 memcpy(binary.get(), proto->program().c_str(), proto->program().length()); |
361 | 381 |
362 store_.Put(proto->sha(), | 382 store_.Put( |
363 new ProgramCacheValue(proto->program().length(), | 383 proto->sha(), |
364 proto->format(), | 384 new ProgramCacheValue( |
365 binary.release(), | 385 proto->program().length(), proto->format(), binary.release(), |
366 proto->sha(), | 386 proto->sha(), proto->vertex_shader().sha().c_str(), vertex_attribs, |
367 proto->vertex_shader().sha().c_str(), | 387 vertex_uniforms, vertex_varyings, vertex_output_variables, |
368 vertex_attribs, | 388 proto->fragment_shader().sha().c_str(), fragment_attribs, |
369 vertex_uniforms, | 389 fragment_uniforms, fragment_varyings, fragment_output_variables, |
370 vertex_varyings, | 390 this)); |
371 proto->fragment_shader().sha().c_str(), | |
372 fragment_attribs, | |
373 fragment_uniforms, | |
374 fragment_varyings, | |
375 this)); | |
376 | 391 |
377 UMA_HISTOGRAM_COUNTS("GPU.ProgramCache.MemorySizeAfterKb", | 392 UMA_HISTOGRAM_COUNTS("GPU.ProgramCache.MemorySizeAfterKb", |
378 curr_size_bytes_ / 1024); | 393 curr_size_bytes_ / 1024); |
379 } else { | 394 } else { |
380 LOG(ERROR) << "Failed to parse proto file."; | 395 LOG(ERROR) << "Failed to parse proto file."; |
381 } | 396 } |
382 } | 397 } |
383 | 398 |
384 MemoryProgramCache::ProgramCacheValue::ProgramCacheValue( | 399 MemoryProgramCache::ProgramCacheValue::ProgramCacheValue( |
385 GLsizei length, | 400 GLsizei length, |
386 GLenum format, | 401 GLenum format, |
387 const char* data, | 402 const char* data, |
388 const std::string& program_hash, | 403 const std::string& program_hash, |
389 const char* shader_0_hash, | 404 const char* shader_0_hash, |
390 const AttributeMap& attrib_map_0, | 405 const AttributeMap& attrib_map_0, |
391 const UniformMap& uniform_map_0, | 406 const UniformMap& uniform_map_0, |
392 const VaryingMap& varying_map_0, | 407 const VaryingMap& varying_map_0, |
| 408 const OutputVariableList& output_variable_list_0, |
393 const char* shader_1_hash, | 409 const char* shader_1_hash, |
394 const AttributeMap& attrib_map_1, | 410 const AttributeMap& attrib_map_1, |
395 const UniformMap& uniform_map_1, | 411 const UniformMap& uniform_map_1, |
396 const VaryingMap& varying_map_1, | 412 const VaryingMap& varying_map_1, |
| 413 const OutputVariableList& output_variable_list_1, |
397 MemoryProgramCache* program_cache) | 414 MemoryProgramCache* program_cache) |
398 : length_(length), | 415 : length_(length), |
399 format_(format), | 416 format_(format), |
400 data_(data), | 417 data_(data), |
401 program_hash_(program_hash), | 418 program_hash_(program_hash), |
402 shader_0_hash_(shader_0_hash, kHashLength), | 419 shader_0_hash_(shader_0_hash, kHashLength), |
403 attrib_map_0_(attrib_map_0), | 420 attrib_map_0_(attrib_map_0), |
404 uniform_map_0_(uniform_map_0), | 421 uniform_map_0_(uniform_map_0), |
405 varying_map_0_(varying_map_0), | 422 varying_map_0_(varying_map_0), |
| 423 output_variable_list_0_(output_variable_list_0), |
406 shader_1_hash_(shader_1_hash, kHashLength), | 424 shader_1_hash_(shader_1_hash, kHashLength), |
407 attrib_map_1_(attrib_map_1), | 425 attrib_map_1_(attrib_map_1), |
408 uniform_map_1_(uniform_map_1), | 426 uniform_map_1_(uniform_map_1), |
409 varying_map_1_(varying_map_1), | 427 varying_map_1_(varying_map_1), |
| 428 output_variable_list_1_(output_variable_list_1), |
410 program_cache_(program_cache) { | 429 program_cache_(program_cache) { |
411 program_cache_->curr_size_bytes_ += length_; | 430 program_cache_->curr_size_bytes_ += length_; |
412 program_cache_->LinkedProgramCacheSuccess(program_hash); | 431 program_cache_->LinkedProgramCacheSuccess(program_hash); |
413 } | 432 } |
414 | 433 |
415 MemoryProgramCache::ProgramCacheValue::~ProgramCacheValue() { | 434 MemoryProgramCache::ProgramCacheValue::~ProgramCacheValue() { |
416 program_cache_->curr_size_bytes_ -= length_; | 435 program_cache_->curr_size_bytes_ -= length_; |
417 program_cache_->Evict(program_hash_); | 436 program_cache_->Evict(program_hash_); |
418 } | 437 } |
419 | 438 |
420 } // namespace gles2 | 439 } // namespace gles2 |
421 } // namespace gpu | 440 } // namespace gpu |
OLD | NEW |