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

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

Issue 10534173: GPU Program Caching (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Style fixes, thorough tests 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
OLDNEW
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/program_manager.h" 5 #include "gpu/command_buffer/service/program_manager.h"
6 6
7 #include <algorithm>
7 #include <set> 8 #include <set>
9 #include <utility>
8 #include <vector> 10 #include <vector>
9 11
10 #include "base/basictypes.h" 12 #include "base/basictypes.h"
11 #include "base/command_line.h" 13 #include "base/command_line.h"
12 #include "base/logging.h" 14 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h" 15 #include "base/memory/scoped_ptr.h"
14 #include "base/string_number_conversions.h" 16 #include "base/string_number_conversions.h"
15 #include "gpu/command_buffer/common/gles2_cmd_format.h" 17 #include "gpu/command_buffer/common/gles2_cmd_format.h"
16 #include "gpu/command_buffer/common/gles2_cmd_utils.h" 18 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
19 #include "gpu/command_buffer/service/feature_info.h"
17 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" 20 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
18 #include "gpu/command_buffer/service/gpu_switches.h" 21 #include "gpu/command_buffer/service/gpu_switches.h"
22 #include "gpu/command_buffer/service/program_cache.h"
19 23
20 namespace gpu { 24 namespace gpu {
21 namespace gles2 { 25 namespace gles2 {
22 26
23 namespace { 27 namespace {
24 28
25 int ShaderTypeToIndex(GLenum shader_type) { 29 int ShaderTypeToIndex(GLenum shader_type) {
26 switch (shader_type) { 30 switch (shader_type) {
27 case GL_VERTEX_SHADER: 31 case GL_VERTEX_SHADER:
28 return 0; 32 return 0;
29 case GL_FRAGMENT_SHADER: 33 case GL_FRAGMENT_SHADER:
30 return 1; 34 return 1;
31 default: 35 default:
32 NOTREACHED(); 36 NOTREACHED();
33 return 0; 37 return 0;
34 } 38 }
35 } 39 }
36 40
41 ShaderTranslator* ShaderIndexToTranslator(
42 int index,
43 ShaderTranslator* vertex_translator,
44 ShaderTranslator* fragment_translator) {
45 switch (index) {
46 case 0:
47 return vertex_translator;
48 case 1:
49 return fragment_translator;
50 default:
51 NOTREACHED();
52 return NULL;
53 }
54 }
55
37 // Given a name like "foo.bar[123].moo[456]" sets new_name to "foo.bar[123].moo" 56 // Given a name like "foo.bar[123].moo[456]" sets new_name to "foo.bar[123].moo"
38 // and sets element_index to 456. returns false if element expression was not a 57 // and sets element_index to 456. returns false if element expression was not a
39 // whole decimal number. For example: "foo[1b2]" 58 // whole decimal number. For example: "foo[1b2]"
40 bool GetUniformNameSansElement( 59 bool GetUniformNameSansElement(
41 const std::string name, int* element_index, std::string* new_name) { 60 const std::string name, int* element_index, std::string* new_name) {
42 DCHECK(element_index); 61 DCHECK(element_index);
43 DCHECK(new_name); 62 DCHECK(new_name);
44 if (name.size() < 3 || name[name.size() - 1] != ']') { 63 if (name.size() < 3 || name[name.size() - 1] != ']') {
45 *element_index = 0; 64 *element_index = 0;
46 *new_name = name; 65 *new_name = name;
(...skipping 306 matching lines...) Expand 10 before | Expand all | Expand 10 after
353 372
354 void ProgramManager::ProgramInfo::ExecuteBindAttribLocationCalls() { 373 void ProgramManager::ProgramInfo::ExecuteBindAttribLocationCalls() {
355 for (LocationMap::const_iterator it = bind_attrib_location_map_.begin(); 374 for (LocationMap::const_iterator it = bind_attrib_location_map_.begin();
356 it != bind_attrib_location_map_.end(); ++it) { 375 it != bind_attrib_location_map_.end(); ++it) {
357 const std::string* mapped_name = GetAttribMappedName(it->first); 376 const std::string* mapped_name = GetAttribMappedName(it->first);
358 if (mapped_name && *mapped_name != it->first) 377 if (mapped_name && *mapped_name != it->first)
359 glBindAttribLocation(service_id_, it->second, mapped_name->c_str()); 378 glBindAttribLocation(service_id_, it->second, mapped_name->c_str());
360 } 379 }
361 } 380 }
362 381
363 bool ProgramManager::ProgramInfo::Link() { 382 void ProgramManager::DoCompileShader(ShaderManager::ShaderInfo* info,
383 ShaderTranslator* translator,
384 FeatureInfo* feature_info) {
385 if (program_cache_ &&
386 program_cache_->GetShaderCompilationStatus(*info->source())
387 == ProgramCache::COMPILATION_SUCCEEDED) {
greggman 2012/07/10 21:43:30 style: operators go at end of previous line
dmurph 2012/07/11 23:32:52 Done.
388 info->SetStatus(true, "", translator);
389 info->set_pending_compilation(true);
390 return;
391 }
392 ForceCompileShader(info, translator, feature_info);
393 }
394
395 void ProgramManager::ForceCompileShader(ShaderManager::ShaderInfo* info,
396 ShaderTranslator* translator,
397 FeatureInfo* feature_info) {
398 // Translate GL ES 2.0 shader to Desktop GL shader and pass that to
399 // glShaderSource and then glCompileShader.
400 const char* shader_src = info->source() ? info->source()->c_str() : "";
401 if (translator) {
402 if (!translator->Translate(shader_src)) {
403 info->SetStatus(false, translator->info_log(), NULL);
404 return;
405 }
406 shader_src = translator->translated_shader();
407 if (!feature_info->feature_flags().angle_translated_shader_source)
408 info->UpdateTranslatedSource(shader_src);
409 }
410
411 glShaderSource(info->service_id(), 1, &shader_src, NULL);
412 glCompileShader(info->service_id());
413 if (feature_info->feature_flags().angle_translated_shader_source) {
414 GLint max_len = 0;
415 glGetShaderiv(info->service_id(),
416 GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE,
417 &max_len);
418 scoped_array<char> temp(new char[max_len]);
419 GLint len = 0;
420 glGetTranslatedShaderSourceANGLE(
421 info->service_id(), max_len, &len, temp.get());
422 DCHECK(max_len == 0 || len < max_len);
423 DCHECK(len == 0 || temp[len] == '\0');
424 info->UpdateTranslatedSource(temp.get());
425 }
426
427 GLint status = GL_FALSE;
428 glGetShaderiv(info->service_id(), GL_COMPILE_STATUS, &status);
429 if (status) {
430 info->SetStatus(true, "", translator);
431 if (program_cache_) {
432 program_cache_->ShaderCompilationSucceeded(*info->source());
433 }
434 } else {
435 // We cannot reach here if we are using the shader translator.
436 // All invalid shaders must be rejected by the translator.
437 // All translated shaders must compile.
438 LOG_IF(ERROR, translator)
439 << "Shader translator allowed/produced an invalid shader.";
440 GLint max_len = 0;
441 glGetShaderiv(info->service_id(), GL_INFO_LOG_LENGTH, &max_len);
442 scoped_array<char> temp(new char[max_len]);
443 GLint len = 0;
444 glGetShaderInfoLog(info->service_id(), max_len, &len, temp.get());
445 DCHECK(max_len == 0 || len < max_len);
446 DCHECK(len == 0 || temp[len] == '\0');
447 info->SetStatus(false, std::string(temp.get(), len).c_str(), NULL);
448 }
449 }
450
451 bool ProgramManager::ProgramInfo::Link(ShaderManager* manager,
452 ShaderTranslator* vertex_translator,
453 ShaderTranslator* fragment_translator,
454 FeatureInfo* feature_info) {
364 ClearLinkStatus(); 455 ClearLinkStatus();
365 if (!CanLink()) { 456 if (!CanLink()) {
366 set_log_info("missing shaders"); 457 set_log_info("missing shaders");
367 return false; 458 return false;
368 } 459 }
369 if (DetectAttribLocationBindingConflicts()) { 460 if (DetectAttribLocationBindingConflicts()) {
370 set_log_info("glBindAttribLocation() conflicts"); 461 set_log_info("glBindAttribLocation() conflicts");
371 return false; 462 return false;
372 } 463 }
373 ExecuteBindAttribLocationCalls(); 464 ExecuteBindAttribLocationCalls();
374 glLinkProgram(service_id()); 465
466 bool link = true;
467 ProgramCache* cache = manager_->program_cache_;
468 const std::string* shader_a = attached_shaders_[0]->source();
469 const std::string* shader_b = attached_shaders_[1]->source();
470 if (cache) {
471 ProgramCache::LinkedProgramStatus status = cache->GetLinkedProgramStatus(
472 *shader_a,
473 *shader_b,
474 &bind_attrib_location_map_);
475 switch (status) {
476 case ProgramCache::LINK_SUCCEEDED: {
477 ProgramCache::ProgramLoadResult success = cache->LoadLinkedProgram(
478 service_id(),
479 attached_shaders_[0],
480 attached_shaders_[1],
481 &bind_attrib_location_map_);
482 if (success == ProgramCache::PROGRAM_LOAD_SUCCESS) {
483 link = false;
484 break;
485 }
486 }
487 // no break
488 case ProgramCache::LINK_UNKNOWN: {
489 // compile our shaders + attach
490 const int kShaders = ProgramManager::ProgramInfo::kMaxAttachedShaders;
491 for (int i = 0; i < kShaders; ++i) {
492 ShaderManager::ShaderInfo* info = attached_shaders_[i].get();
493 if (info->IsPendingCacheMissCompilation()) {
494 ShaderTranslator* translator = ShaderIndexToTranslator(
495 i,
496 vertex_translator,
497 fragment_translator);
498 manager_->ForceCompileShader(attached_shaders_[i],
499 translator,
500 feature_info);
501 AttachShader(manager, info);
greggman 2012/07/10 21:43:30 You shouldn't need go call AttachShader nor glAtta
dmurph 2012/07/11 23:32:52 Done.
502 glAttachShader(service_id(), info->service_id());
503 info->set_pending_compilation(false);
greggman 2012/07/10 21:43:30 Should ForceCompileShader set set_pending_compilat
dmurph 2012/07/11 23:32:52 Hm.... What if we just moved it right after the if
greggman 2012/07/12 00:48:29 Maybe I'm mis-understanding. It seems like there's
504 CHECK(info->IsValid());
505 }
506 }
507 link = true;
508 break;
509 }
510 default:
511 NOTREACHED();
512 }
513 }
514
515 if (link) {
516 glLinkProgram(service_id());
517 }
518
375 GLint success = 0; 519 GLint success = 0;
376 glGetProgramiv(service_id(), GL_LINK_STATUS, &success); 520 glGetProgramiv(service_id(), GL_LINK_STATUS, &success);
377 if (success == GL_TRUE) { 521 if (success == GL_TRUE) {
378 Update(); 522 Update();
523 if (cache && link) {
524 cache->SaveLinkedProgram(service_id(),
525 attached_shaders_[0],
526 attached_shaders_[1],
527 &bind_attrib_location_map_);
528 }
379 } else { 529 } else {
380 UpdateLogInfo(); 530 UpdateLogInfo();
381 } 531 }
382 return success == GL_TRUE; 532 return success == GL_TRUE;
383 } 533 }
384 534
385 void ProgramManager::ProgramInfo::Validate() { 535 void ProgramManager::ProgramInfo::Validate() {
386 if (!IsValid()) { 536 if (!IsValid()) {
387 set_log_info("program not linked"); 537 set_log_info("program not linked");
388 return; 538 return;
(...skipping 452 matching lines...) Expand 10 before | Expand all | Expand 10 after
841 ProgramManager::ProgramInfo::~ProgramInfo() { 991 ProgramManager::ProgramInfo::~ProgramInfo() {
842 if (manager_) { 992 if (manager_) {
843 if (manager_->have_context_) { 993 if (manager_->have_context_) {
844 glDeleteProgram(service_id()); 994 glDeleteProgram(service_id());
845 } 995 }
846 manager_->StopTracking(this); 996 manager_->StopTracking(this);
847 manager_ = NULL; 997 manager_ = NULL;
848 } 998 }
849 } 999 }
850 1000
851 ProgramManager::ProgramManager() 1001
1002 ProgramManager::ProgramManager(ProgramCache* program_cache)
852 : program_info_count_(0), 1003 : program_info_count_(0),
853 have_context_(true), 1004 have_context_(true),
854 disable_workarounds_( 1005 disable_workarounds_(
855 CommandLine::ForCurrentProcess()->HasSwitch( 1006 CommandLine::ForCurrentProcess()->HasSwitch(
856 switches::kDisableGpuDriverBugWorkarounds)) { 1007 switches::kDisableGpuDriverBugWorkarounds)),
857 } 1008 program_cache_(program_cache) { }
858 1009
859 ProgramManager::~ProgramManager() { 1010 ProgramManager::~ProgramManager() {
860 DCHECK(program_infos_.empty()); 1011 DCHECK(program_infos_.empty());
861 } 1012 }
862 1013
863 void ProgramManager::Destroy(bool have_context) { 1014 void ProgramManager::Destroy(bool have_context) {
864 have_context_ = have_context; 1015 have_context_ = have_context;
865 program_infos_.clear(); 1016 program_infos_.clear();
866 } 1017 }
867 1018
(...skipping 25 matching lines...) Expand all
893 for (ProgramInfoMap::const_iterator it = program_infos_.begin(); 1044 for (ProgramInfoMap::const_iterator it = program_infos_.begin();
894 it != program_infos_.end(); ++it) { 1045 it != program_infos_.end(); ++it) {
895 if (it->second->service_id() == service_id) { 1046 if (it->second->service_id() == service_id) {
896 *client_id = it->first; 1047 *client_id = it->first;
897 return true; 1048 return true;
898 } 1049 }
899 } 1050 }
900 return false; 1051 return false;
901 } 1052 }
902 1053
1054 ProgramCache* ProgramManager::program_cache() const {
1055 return program_cache_;
1056 }
1057
903 bool ProgramManager::IsOwned(ProgramManager::ProgramInfo* info) { 1058 bool ProgramManager::IsOwned(ProgramManager::ProgramInfo* info) {
904 for (ProgramInfoMap::iterator it = program_infos_.begin(); 1059 for (ProgramInfoMap::iterator it = program_infos_.begin();
905 it != program_infos_.end(); ++it) { 1060 it != program_infos_.end(); ++it) {
906 if (it->second.get() == info) { 1061 if (it->second.get() == info) {
907 return true; 1062 return true;
908 } 1063 }
909 } 1064 }
910 return false; 1065 return false;
911 } 1066 }
912 1067
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
963 } 1118 }
964 1119
965 int32 ProgramManager::MakeFakeLocation(int32 index, int32 element) { 1120 int32 ProgramManager::MakeFakeLocation(int32 index, int32 element) {
966 return index + element * 0x10000; 1121 return index + element * 0x10000;
967 } 1122 }
968 1123
969 } // namespace gles2 1124 } // namespace gles2
970 } // namespace gpu 1125 } // namespace gpu
971 1126
972 1127
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698