Chromium Code Reviews| Index: gpu/command_buffer/service/program_manager.cc |
| diff --git a/gpu/command_buffer/service/program_manager.cc b/gpu/command_buffer/service/program_manager.cc |
| index 5d504a4afc97ae20a14c43f529ec652a37b86332..48ea8adc4dbdb26fe99d5546c7896690640b7e03 100644 |
| --- a/gpu/command_buffer/service/program_manager.cc |
| +++ b/gpu/command_buffer/service/program_manager.cc |
| @@ -8,10 +8,12 @@ |
| #include <set> |
| #include "base/basictypes.h" |
| +#include "base/bind.h" |
| #include "base/command_line.h" |
| #include "base/logging.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/string_number_conversions.h" |
| +#include "net/base/net_log.h" |
| #include "gpu/command_buffer/common/gles2_cmd_format.h" |
| #include "gpu/command_buffer/common/gles2_cmd_utils.h" |
| #include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
| @@ -253,7 +255,78 @@ void ProgramManager::ProgramInfo::ExecuteBindAttribLocationCalls() { |
| } |
| } |
| -bool ProgramManager::ProgramInfo::Link() { |
| +void ProgramManager::DoCompileShader(ShaderManager::ShaderInfo* info, |
| + ShaderTranslator* translator, |
| + FeatureInfo::Ref feature_info) { |
|
greggman
2012/06/15 08:10:24
feature_info should just be a raw pointer.
dmurph
2012/06/19 01:08:33
Done.
|
| + // Translate GL ES 2.0 shader to Desktop GL shader and pass that to |
| + // glShaderSource and then glCompileShader. |
| + const char* shader_src = info->source() ? info->source()->c_str() : ""; |
| + if (translator) { |
| + if (!translator->Translate(shader_src)) { |
| + info->SetStatus(false, translator->info_log(), NULL); |
| + if(shader_cache_) { |
| + shader_cache_->setShaderCompilationStatus( |
| + info->source()->c_str(), |
| + SHADER_CACHE_COMPILATION_SUCCEEDED); |
| + } |
| + return; |
| + } |
| + shader_src = translator->translated_shader(); |
| + if (!feature_info->feature_flags().angle_translated_shader_source) |
| + info->UpdateTranslatedSource(shader_src); |
| + } |
| + |
| + glShaderSource(info->service_id(), 1, &shader_src, NULL); |
| + glCompileShader(info->service_id()); |
| + if (feature_info->feature_flags().angle_translated_shader_source) { |
| + GLint max_len = 0; |
| + glGetShaderiv(info->service_id(), |
| + GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE, |
| + &max_len); |
| + scoped_array<char> temp(new char[max_len]); |
| + GLint len = 0; |
| + glGetTranslatedShaderSourceANGLE( |
| + info->service_id(), max_len, &len, temp.get()); |
| + DCHECK(max_len == 0 || len < max_len); |
| + DCHECK(len == 0 || temp[len] == '\0'); |
| + info->UpdateTranslatedSource(temp.get()); |
| + } |
| + |
| + GLint status = GL_FALSE; |
| + glGetShaderiv(info->service_id(), GL_COMPILE_STATUS, &status); |
| + if (status) { |
| + info->SetStatus(true, "", translator); |
| + if(shader_cache_) { |
| + shader_cache_->setShaderCompilationStatus( |
| + info->source()->c_str(), |
| + SHADER_CACHE_COMPILATION_SUCCEEDED); |
| + } |
| + } else { |
| + // We cannot reach here if we are using the shader translator. |
| + // All invalid shaders must be rejected by the translator. |
| + // All translated shaders must compile. |
| + LOG_IF(ERROR, translator) |
| + << "Shader translator allowed/produced an invalid shader."; |
| + GLint max_len = 0; |
| + glGetShaderiv(info->service_id(), GL_INFO_LOG_LENGTH, &max_len); |
| + scoped_array<char> temp(new char[max_len]); |
| + GLint len = 0; |
| + glGetShaderInfoLog(info->service_id(), max_len, &len, temp.get()); |
| + DCHECK(max_len == 0 || len < max_len); |
| + DCHECK(len == 0 || temp[len] == '\0'); |
| + info->SetStatus(false, std::string(temp.get(), len).c_str(), NULL); |
| + if(shader_cache_) { |
| + shader_cache_->setShaderCompilationStatus( |
| + info->source()->c_str(), |
| + SHADER_CACHE_COMPILATION_UNKNOWN); |
| + } |
| + } |
| +} |
| + |
| +bool ProgramManager::ProgramInfo::Link(ShaderManager* manager, |
| + ShaderTranslator* vertex_translator, |
| + ShaderTranslator* fragment_shader, |
| + FeatureInfo::Ref feature_info) { |
| ClearLinkStatus(); |
| if (!CanLink()) { |
| set_log_info("missing shaders"); |
| @@ -264,13 +337,88 @@ bool ProgramManager::ProgramInfo::Link() { |
| return false; |
| } |
| ExecuteBindAttribLocationCalls(); |
| - glLinkProgram(service_id()); |
| + |
| + bool link = true; |
| + ShaderCache* cache = manager_->shader_cache_; |
| + const char* shader_a = attached_shaders_[0]->source()->c_str(); |
| + const char* shader_b = attached_shaders_[1]->source()->c_str(); |
| + if(cache) { |
| + LinkedProgramStatus status = cache->getLinkedProgramStatus( |
| + shader_a, |
| + shader_b); |
| + switch(status) { |
| + case SHADER_CACHE_LINK_UNKNOWN: |
| + fprintf(stderr, |
| + "program %i not linked yet compiling and linking\n", |
| + service_id()); |
| + // compile our shaders + attach |
| + manager_->DoCompileShader(attached_shaders_[0], |
| + vertex_translator, |
| + feature_info); |
| + manager_->DoCompileShader(attached_shaders_[1], |
| + fragment_shader, |
| + feature_info); |
| + AttachShader(manager, attached_shaders_[0]); |
|
greggman
2012/06/15 08:10:24
Why do you have to attach here? Shouldn't they alr
dmurph
2012/06/19 01:08:33
Done.
|
| + glAttachShader(service_id(), attached_shaders_[0]->service_id()); |
| + AttachShader(manager, attached_shaders_[1]); |
| + glAttachShader(service_id(), attached_shaders_[1]->service_id()); |
| + link = true; |
| + break; |
| + case SHADER_CACHE_LINK_SUCCEEDED: |
| + fprintf(stderr, "program %i linked and cached!\n", service_id()); |
| + GLsizei length; |
| + GLenum format; |
| + const GLvoid* binary; |
| + cache->getLinkedProgram(shader_a, shader_b, |
| + &length, &format, &binary); |
| + glProgramBinary(service_id(), format, binary, length); |
| + link = false; |
| + break; |
| + } |
| + } |
| + |
| + if(link) { |
| + glLinkProgram(service_id()); |
| + } |
| + |
| GLint success = 0; |
| glGetProgramiv(service_id(), GL_LINK_STATUS, &success); |
| if (success == GL_TRUE) { |
| Update(); |
| + if(cache && link) { |
| + fprintf(stderr, "program %i just linked, caching\n", service_id()); |
| + GLsizei length; |
| + GLenum format; |
| + glGetProgramBinary(service_id(), |
|
greggman
2012/06/15 08:10:24
This code makes no sense to me. What is cache->cac
dmurph
2012/06/15 16:40:23
Sounds good, I didn't know I could query the size
|
| + kShaderCacheBufferSize, |
| + &length, |
| + &format, |
| + cache->cache_buffer()); |
| + fprintf(stderr, "got length of %i\n", length); |
| + |
| + if(length != 0) { |
| + GLvoid* trimedBinary = new char[length]; |
|
greggman
2012/06/15 08:10:24
Related to the above comment where does this memor
dmurph
2012/06/15 16:40:23
I like that, the memory issue was bothering me yes
|
| + memcpy(trimedBinary, cache->cache_buffer(), length); |
| + cache->setLinkedProgram(shader_a, |
| + shader_b, |
| + length, |
| + format, |
| + trimedBinary); |
| + cache->setLinkedProgramStatus(shader_a, |
| + shader_b, |
| + SHADER_CACHE_LINK_SUCCEEDED); |
| + fprintf(stderr, "caching [%s] and [%s]\n", shader_a, shader_b); |
| + } |
| + |
| + } |
| } else { |
| UpdateLogInfo(); |
| + if(cache) { |
| + fprintf(stderr, "program %i not linked correctly\n", service_id()); |
| + cache->setLinkedProgramStatus(shader_a, |
| + shader_b, |
| + SHADER_CACHE_LINK_UNKNOWN); |
| + } |
| } |
| return success == GL_TRUE; |
| } |
| @@ -683,14 +831,14 @@ ProgramManager::ProgramInfo::~ProgramInfo() { |
| // by at least 1 bit each time chrome is run. |
| static int uniform_random_offset_ = 3; |
| -ProgramManager::ProgramManager() |
| +ProgramManager::ProgramManager(base::WeakPtr<ShaderCache> shader_cache) |
| : uniform_swizzle_(uniform_random_offset_++ % 15), |
| program_info_count_(0), |
| have_context_(true), |
| disable_workarounds_( |
| CommandLine::ForCurrentProcess()->HasSwitch( |
| - switches::kDisableGpuDriverBugWorkarounds)) { |
| -} |
| + switches::kDisableGpuDriverBugWorkarounds)), |
| + shader_cache_(shader_cache){ } |
| ProgramManager::~ProgramManager() { |
| DCHECK(program_infos_.empty()); |
| @@ -736,6 +884,10 @@ bool ProgramManager::GetClientId(GLuint service_id, GLuint* client_id) const { |
| return false; |
| } |
| +ShaderCache* ProgramManager::GetShaderCache() const { |
| + return shader_cache_; |
| +} |
| + |
| bool ProgramManager::IsOwned(ProgramManager::ProgramInfo* info) { |
| for (ProgramInfoMap::iterator it = program_infos_.begin(); |
| it != program_infos_.end(); ++it) { |