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

Unified Diff: gpu/command_buffer/client/program_info_manager.cc

Issue 7358006: Cache OpenGL program info on the client side of the command buffer. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 9 years, 4 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 side-by-side diff with in-line comments
Download patch
Index: gpu/command_buffer/client/program_info_manager.cc
diff --git a/gpu/command_buffer/client/program_info_manager.cc b/gpu/command_buffer/client/program_info_manager.cc
index 8b137891791fe96927ad78e64b0aad7bded08bdc..57a037d3256f4420196bb939fc8d196adac03407 100644
--- a/gpu/command_buffer/client/program_info_manager.cc
+++ b/gpu/command_buffer/client/program_info_manager.cc
@@ -1 +1,496 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "../client/program_info_manager.h"
+#include "../client/gles2_implementation.h"
+
+#include <map>
+
+namespace gpu {
+namespace gles2 {
+
+class NonCachedProgramInfoManager : public ProgramInfoManager {
+ public:
+ NonCachedProgramInfoManager();
+ virtual ~NonCachedProgramInfoManager();
+
+ virtual void CreateInfo(GLuint program);
+
+ virtual void DeleteInfo(GLuint program);
+
+ virtual bool GetProgramiv(
+ GLES2Implementation* gl, GLuint program, GLenum pname, GLint* params);
+
+ virtual GLint GetAttribLocation(
+ GLES2Implementation* gl, GLuint program, const char* name);
+
+ virtual GLint GetUniformLocation(
+ GLES2Implementation* gl, GLuint program, const char* name);
+
+ virtual bool GetActiveAttrib(
+ GLES2Implementation* gl,
+ GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
+ GLint* size, GLenum* type, char* name);
+
+ virtual bool GetActiveUniform(
+ GLES2Implementation* gl,
+ GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
+ GLint* size, GLenum* type, char* name);
+
+};
+
+NonCachedProgramInfoManager::NonCachedProgramInfoManager() {
+}
+
+NonCachedProgramInfoManager::~NonCachedProgramInfoManager() {
+}
+
+void NonCachedProgramInfoManager::CreateInfo(GLuint /* program */) {
+}
+
+void NonCachedProgramInfoManager::DeleteInfo(GLuint /* program */) {
+}
+
+bool NonCachedProgramInfoManager::GetProgramiv(
+ GLES2Implementation* /* gl */,
+ GLuint /* program */,
+ GLenum /* pname */,
+ GLint* /* params */) {
+ return false;
+}
+
+GLint NonCachedProgramInfoManager::GetAttribLocation(
+ GLES2Implementation* gl, GLuint program, const char* name) {
+ return gl->GetAttribLocationHelper(program, name);
+}
+
+GLint NonCachedProgramInfoManager::GetUniformLocation(
+ GLES2Implementation* gl, GLuint program, const char* name) {
+ return gl->GetUniformLocationHelper(program, name);
+}
+
+bool NonCachedProgramInfoManager::GetActiveAttrib(
+ GLES2Implementation* gl,
+ GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
+ GLint* size, GLenum* type, char* name) {
+ return gl->GetActiveAttribHelper(
+ program, index, bufsize, length, size, type, name);
+}
+
+bool NonCachedProgramInfoManager::GetActiveUniform(
+ GLES2Implementation* gl,
+ GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
+ GLint* size, GLenum* type, char* name) {
+ return gl->GetActiveUniformHelper(
+ program, index, bufsize, length, size, type, name);
+}
+
+class CachedProgramInfoManager : public ProgramInfoManager {
+ public:
+ CachedProgramInfoManager();
+ virtual ~CachedProgramInfoManager();
+
+ virtual void CreateInfo(GLuint program);
+
+ virtual void DeleteInfo(GLuint program);
+
+ virtual bool GetProgramiv(
+ GLES2Implementation* gl,
+ GLuint program, GLenum pname, GLint* params);
+
+ virtual GLint GetAttribLocation(
+ GLES2Implementation* gl, GLuint program, const char* name);
+
+ virtual GLint GetUniformLocation(
+ GLES2Implementation* gl, GLuint program, const char* name);
+
+ virtual bool GetActiveAttrib(
+ GLES2Implementation* gl,
+ GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
+ GLint* size, GLenum* type, char* name);
+
+ virtual bool GetActiveUniform(
+ GLES2Implementation* gl,
+ GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
+ GLint* size, GLenum* type, char* name);
+
+ private:
+ class ProgramInfo {
+ public:
+ struct UniformInfo {
+ UniformInfo(GLsizei _size, GLenum _type, const std::string& _name);
+
+ GLsizei size;
+ GLenum type;
+ bool is_array;
+ std::string name;
+ std::vector<GLint> element_locations;
+ };
+ struct VertexAttribInfo {
+ VertexAttribInfo(GLsizei _size, GLenum _type, const std::string& _name,
+ GLint _location)
+ : size(_size),
+ type(_type),
+ location(_location),
+ name(_name) {
+ }
+ GLsizei size;
+ GLenum type;
+ GLint location;
+ std::string name;
+ };
+
+ typedef std::vector<UniformInfo> UniformInfoVector;
+ typedef std::vector<VertexAttribInfo> AttribInfoVector;
+
+ ProgramInfo();
+
+ const AttribInfoVector& GetAttribInfos() const {
+ return attrib_infos_;
+ }
+
+ const VertexAttribInfo* GetAttribInfo(GLint index) const {
+ return (static_cast<size_t>(index) < attrib_infos_.size()) ?
+ &attrib_infos_[index] : NULL;
+ }
+
+ GLint GetAttribLocation(const std::string& name) const;
+
+ const UniformInfo* GetUniformInfo(GLint index) const {
+ return (static_cast<size_t>(index) < uniform_infos_.size()) ?
+ &uniform_infos_[index] : NULL;
+ }
+
+ // Gets the location of a uniform by name.
+ GLint GetUniformLocation(const std::string& name) const;
+
+ bool GetProgramiv(GLenum pname, GLint* params);
+
+ // Updates the program info after a successful link.
+ void Update(GLES2Implementation* gl, GLuint program);
+
+ private:
+ bool cached_;
+
+ GLsizei max_attrib_name_length_;
+
+ // Attrib by index.
+ AttribInfoVector attrib_infos_;
+
+ GLsizei max_uniform_name_length_;
+
+ // Uniform info by index.
+ UniformInfoVector uniform_infos_;
+
+ // This is true if glLinkProgram was successful last time it was called.
+ bool link_status_;
+ };
+
+ ProgramInfo* GetProgramInfo(GLES2Implementation* gl, GLuint program);
+
+ // TODO(gman): Switch to a faster container.
+ typedef std::map<GLuint, ProgramInfo> ProgramInfoMap;
+
+ ProgramInfoMap program_infos_;
+};
+
+CachedProgramInfoManager::ProgramInfo::UniformInfo::UniformInfo(
+ GLsizei _size, GLenum _type, const std::string& _name)
+ : size(_size),
+ type(_type),
+ name(_name) {
+ is_array = (!name.empty() && name[name.size() - 1] == ']');
+ GPU_DCHECK(!(size > 1 && !is_array));
+}
+
+CachedProgramInfoManager::ProgramInfo::ProgramInfo()
+ : cached_(false),
+ max_attrib_name_length_(0),
+ max_uniform_name_length_(0),
+ link_status_(false) {
+}
+
+// TODO(gman): Add a faster lookup.
+GLint CachedProgramInfoManager::ProgramInfo::GetAttribLocation(
+ const std::string& name) const {
+ for (GLuint ii = 0; ii < attrib_infos_.size(); ++ii) {
+ const VertexAttribInfo& info = attrib_infos_[ii];
+ if (info.name == name) {
+ return info.location;
+ }
+ }
+ return -1;
+}
+
+// TODO(gman): Add a faster lookup.
+GLint CachedProgramInfoManager::ProgramInfo::GetUniformLocation(
+ const std::string& name) const {
+ for (GLuint ii = 0; ii < uniform_infos_.size(); ++ii) {
+ const UniformInfo& info = uniform_infos_[ii];
+ if (info.name == name ||
+ (info.is_array &&
+ info.name.compare(0, info.name.size() - 3, name) == 0)) {
+ return info.element_locations[0];
+ } else if (info.is_array &&
+ name.size() >= 3 && name[name.size() - 1] == ']') {
+ // Look for an array specification.
+ size_t open_pos = name.find_last_of('[');
+ if (open_pos != std::string::npos &&
+ open_pos < name.size() - 2 &&
+ info.name.size() > open_pos &&
+ name.compare(0, open_pos, info.name, 0, open_pos) == 0) {
+ GLint index = 0;
+ size_t last = name.size() - 1;
+ bool bad = false;
+ for (size_t pos = open_pos + 1; pos < last; ++pos) {
+ int8 digit = name[pos] - '0';
+ if (digit < 0 || digit > 9) {
+ bad = true;
+ break;
+ }
+ index = index * 10 + digit;
+ }
+ if (!bad && index >= 0 && index < info.size) {
+ return info.element_locations[index];
+ }
+ }
+ }
+ }
+ return -1;
+}
+
+bool CachedProgramInfoManager::ProgramInfo::GetProgramiv(
+ GLenum pname, GLint* params) {
+ switch (pname) {
+ case GL_LINK_STATUS:
+ *params = link_status_;
+ return true;
+ case GL_ACTIVE_ATTRIBUTES:
+ *params = attrib_infos_.size();
+ return true;
+ case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
+ *params = max_attrib_name_length_;
+ return true;
+ case GL_ACTIVE_UNIFORMS:
+ *params = uniform_infos_.size();
+ return true;
+ case GL_ACTIVE_UNIFORM_MAX_LENGTH:
+ *params = max_uniform_name_length_;
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+template<typename T> static T LocalGetAs(
+ const std::vector<int8>& data, uint32 offset, size_t size) {
+ const int8* p = &data[0] + offset;
+ if (offset + size > data.size()) {
+ GPU_NOTREACHED();
+ return NULL;
+ }
+ return static_cast<T>(static_cast<const void*>(p));
+}
+
+void CachedProgramInfoManager::ProgramInfo::Update(
+ GLES2Implementation* gl, GLuint program) {
+ if (cached_) {
+ return;
+ }
+ std::vector<int8> result;
+ gl->GetProgramInfoCHROMIUMHelper(program, &result);
+ if (result.empty()) {
+ // This should only happen on a lost context.
+ return;
+ }
+ GPU_DCHECK_GE(result.size(), sizeof(ProgramInfoHeader));
+ const ProgramInfoHeader* header = LocalGetAs<const ProgramInfoHeader*>(
+ result, 0, sizeof(header));
+ link_status_ = header->link_status != 0;
+ if (!link_status_) {
+ return;
+ }
+ attrib_infos_.clear();
+ uniform_infos_.clear();
+ max_attrib_name_length_ = 0;
+ max_uniform_name_length_ = 0;
+ const ProgramInput* inputs = LocalGetAs<const ProgramInput*>(
+ result, sizeof(*header),
+ sizeof(ProgramInput) * (header->num_attribs + header->num_uniforms));
+ const ProgramInput* input = inputs;
+ for (uint32 ii = 0; ii < header->num_attribs; ++ii) {
+ const int32* location = LocalGetAs<const int32*>(
+ result, input->location_offset, sizeof(int32));
+ const char* name_buf = LocalGetAs<const char*>(
+ result, input->name_offset, input->name_length);
+ std::string name(name_buf, input->name_length);
+ attrib_infos_.push_back(
+ VertexAttribInfo(input->size, input->type, name, *location));
+ max_attrib_name_length_ = std::max(
+ static_cast<GLsizei>(name.size() + 1), max_attrib_name_length_);
+ ++input;
+ }
+ for (uint32 ii = 0; ii < header->num_uniforms; ++ii) {
+ const int32* locations = LocalGetAs<const int32*>(
+ result, input->location_offset, sizeof(int32) * input->size);
+ const char* name_buf = LocalGetAs<const char*>(
+ result, input->name_offset, input->name_length);
+ std::string name(name_buf, input->name_length);
+ UniformInfo info(input->size, input->type, name);
+ max_uniform_name_length_ = std::max(
+ static_cast<GLsizei>(name.size() + 1), max_uniform_name_length_);
+ for (int32 jj = 0; jj < input->size; ++jj) {
+ info.element_locations.push_back(locations[jj]);
+ }
+ uniform_infos_.push_back(info);
+ ++input;
+ }
+ GPU_DCHECK_EQ(header->num_attribs + header->num_uniforms,
+ static_cast<uint32>(input - inputs));
+ cached_ = true;
+}
+
+CachedProgramInfoManager::CachedProgramInfoManager() {
+}
+
+CachedProgramInfoManager::~CachedProgramInfoManager() {
+
+}
+
+CachedProgramInfoManager::ProgramInfo*
+ CachedProgramInfoManager::GetProgramInfo(
+ GLES2Implementation* gl, GLuint program) {
+ ProgramInfoMap::iterator it = program_infos_.find(program);
+ if (it == program_infos_.end()) {
+ return NULL;
+ }
+ ProgramInfo* info = &it->second;
+ info->Update(gl, program);
+ return info;
+}
+
+void CachedProgramInfoManager::CreateInfo(GLuint program) {
+ DeleteInfo(program);
+ std::pair<ProgramInfoMap::iterator, bool> result =
+ program_infos_.insert(std::make_pair(program, ProgramInfo()));
+
+ GPU_DCHECK(result.second);
+}
+
+void CachedProgramInfoManager::DeleteInfo(GLuint program) {
+ program_infos_.erase(program);
+}
+
+bool CachedProgramInfoManager::GetProgramiv(
+ GLES2Implementation* gl, GLuint program, GLenum pname, GLint* params) {
+ ProgramInfo* info = GetProgramInfo(gl, program);
+ if (!info) {
+ return false;
+ }
+ return info->GetProgramiv(pname, params);
+}
+
+GLint CachedProgramInfoManager::GetAttribLocation(
+ GLES2Implementation* gl, GLuint program, const char* name) {
+ ProgramInfo* info = GetProgramInfo(gl, program);
+ if (info) {
+ return info->GetAttribLocation(name);
+ }
+ return gl->GetAttribLocationHelper(program, name);
+}
+
+GLint CachedProgramInfoManager::GetUniformLocation(
+ GLES2Implementation* gl, GLuint program, const char* name) {
+ ProgramInfo* info = GetProgramInfo(gl, program);
+ if (info) {
+ return info->GetUniformLocation(name);
+ }
+ return gl->GetUniformLocationHelper(program, name);
+}
+
+bool CachedProgramInfoManager::GetActiveAttrib(
+ GLES2Implementation* gl,
+ GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
+ GLint* size, GLenum* type, char* name) {
+ ProgramInfo* info = GetProgramInfo(gl, program);
+ if (info) {
+ const ProgramInfo::VertexAttribInfo* attrib_info =
+ info->GetAttribInfo(index);
+ if (attrib_info) {
+ if (size) {
+ *size = attrib_info->size;
+ }
+ if (type) {
+ *type = attrib_info->type;
+ }
+ if (length || name) {
+ GLsizei max_size = std::min(static_cast<size_t>(bufsize) - 1,
+ std::max(static_cast<size_t>(0),
+ attrib_info->name.size()));
+ if (length) {
+ *length = max_size;
+ }
+ if (name && bufsize > 0) {
+ memcpy(name, attrib_info->name.c_str(), max_size);
+ name[max_size] = '\0';
+ }
+ }
+ return true;
+ }
+ }
+ return gl->GetActiveAttribHelper(
+ program, index, bufsize, length, size, type, name);
+}
+
+bool CachedProgramInfoManager::GetActiveUniform(
+ GLES2Implementation* gl,
+ GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
+ GLint* size, GLenum* type, char* name) {
+ ProgramInfo* info = GetProgramInfo(gl, program);
+ if (info) {
+ const ProgramInfo::UniformInfo* uniform_info = info->GetUniformInfo(index);
+ if (uniform_info) {
+ if (size) {
+ *size = uniform_info->size;
+ }
+ if (type) {
+ *type = uniform_info->type;
+ }
+ if (length || name) {
+ GLsizei max_size = std::min(static_cast<size_t>(bufsize) - 1,
+ std::max(static_cast<size_t>(0),
+ uniform_info->name.size()));
+ if (length) {
+ *length = max_size;
+ }
+ if (name && bufsize > 0) {
+ memcpy(name, uniform_info->name.c_str(), max_size);
+ name[max_size] = '\0';
+ }
+ }
+ return true;
+ }
+ }
+ return gl->GetActiveUniformHelper(
+ program, index, bufsize, length, size, type, name);
+}
+
+ProgramInfoManager::ProgramInfoManager() {
+}
+
+ProgramInfoManager::~ProgramInfoManager() {
+}
+
+ProgramInfoManager* ProgramInfoManager::Create(bool shared_resources) {
+ if (shared_resources) {
+ return new NonCachedProgramInfoManager();
+ } else {
+ return new CachedProgramInfoManager();
+ }
+}
+
+} // namespace gles2
+} // namespace gpu
« no previous file with comments | « gpu/command_buffer/client/program_info_manager.h ('k') | gpu/command_buffer/client/program_info_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698