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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 1 // Copyright (c) 2011 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 "../client/program_info_manager.h"
6 #include "../client/gles2_implementation.h"
7
8 #include <map>
9
10 namespace gpu {
11 namespace gles2 {
12
13 class NonCachedProgramInfoManager : public ProgramInfoManager {
14 public:
15 NonCachedProgramInfoManager();
16 virtual ~NonCachedProgramInfoManager();
17
18 virtual void CreateInfo(GLuint program);
19
20 virtual void DeleteInfo(GLuint program);
21
22 virtual bool GetProgramiv(
23 GLES2Implementation* gl, GLuint program, GLenum pname, GLint* params);
24
25 virtual GLint GetAttribLocation(
26 GLES2Implementation* gl, GLuint program, const char* name);
27
28 virtual GLint GetUniformLocation(
29 GLES2Implementation* gl, GLuint program, const char* name);
30
31 virtual bool GetActiveAttrib(
32 GLES2Implementation* gl,
33 GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
34 GLint* size, GLenum* type, char* name);
35
36 virtual bool GetActiveUniform(
37 GLES2Implementation* gl,
38 GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
39 GLint* size, GLenum* type, char* name);
40
41 };
42
43 NonCachedProgramInfoManager::NonCachedProgramInfoManager() {
44 }
45
46 NonCachedProgramInfoManager::~NonCachedProgramInfoManager() {
47 }
48
49 void NonCachedProgramInfoManager::CreateInfo(GLuint /* program */) {
50 }
51
52 void NonCachedProgramInfoManager::DeleteInfo(GLuint /* program */) {
53 }
54
55 bool NonCachedProgramInfoManager::GetProgramiv(
56 GLES2Implementation* /* gl */,
57 GLuint /* program */,
58 GLenum /* pname */,
59 GLint* /* params */) {
60 return false;
61 }
62
63 GLint NonCachedProgramInfoManager::GetAttribLocation(
64 GLES2Implementation* gl, GLuint program, const char* name) {
65 return gl->GetAttribLocationHelper(program, name);
66 }
67
68 GLint NonCachedProgramInfoManager::GetUniformLocation(
69 GLES2Implementation* gl, GLuint program, const char* name) {
70 return gl->GetUniformLocationHelper(program, name);
71 }
72
73 bool NonCachedProgramInfoManager::GetActiveAttrib(
74 GLES2Implementation* gl,
75 GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
76 GLint* size, GLenum* type, char* name) {
77 return gl->GetActiveAttribHelper(
78 program, index, bufsize, length, size, type, name);
79 }
80
81 bool NonCachedProgramInfoManager::GetActiveUniform(
82 GLES2Implementation* gl,
83 GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
84 GLint* size, GLenum* type, char* name) {
85 return gl->GetActiveUniformHelper(
86 program, index, bufsize, length, size, type, name);
87 }
88
89 class CachedProgramInfoManager : public ProgramInfoManager {
90 public:
91 CachedProgramInfoManager();
92 virtual ~CachedProgramInfoManager();
93
94 virtual void CreateInfo(GLuint program);
95
96 virtual void DeleteInfo(GLuint program);
97
98 virtual bool GetProgramiv(
99 GLES2Implementation* gl,
100 GLuint program, GLenum pname, GLint* params);
101
102 virtual GLint GetAttribLocation(
103 GLES2Implementation* gl, GLuint program, const char* name);
104
105 virtual GLint GetUniformLocation(
106 GLES2Implementation* gl, GLuint program, const char* name);
107
108 virtual bool GetActiveAttrib(
109 GLES2Implementation* gl,
110 GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
111 GLint* size, GLenum* type, char* name);
112
113 virtual bool GetActiveUniform(
114 GLES2Implementation* gl,
115 GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
116 GLint* size, GLenum* type, char* name);
117
118 private:
119 class ProgramInfo {
120 public:
121 struct UniformInfo {
122 UniformInfo(GLsizei _size, GLenum _type, const std::string& _name);
123
124 GLsizei size;
125 GLenum type;
126 bool is_array;
127 std::string name;
128 std::vector<GLint> element_locations;
129 };
130 struct VertexAttribInfo {
131 VertexAttribInfo(GLsizei _size, GLenum _type, const std::string& _name,
132 GLint _location)
133 : size(_size),
134 type(_type),
135 location(_location),
136 name(_name) {
137 }
138 GLsizei size;
139 GLenum type;
140 GLint location;
141 std::string name;
142 };
143
144 typedef std::vector<UniformInfo> UniformInfoVector;
145 typedef std::vector<VertexAttribInfo> AttribInfoVector;
146
147 ProgramInfo();
148
149 const AttribInfoVector& GetAttribInfos() const {
150 return attrib_infos_;
151 }
152
153 const VertexAttribInfo* GetAttribInfo(GLint index) const {
154 return (static_cast<size_t>(index) < attrib_infos_.size()) ?
155 &attrib_infos_[index] : NULL;
156 }
157
158 GLint GetAttribLocation(const std::string& name) const;
159
160 const UniformInfo* GetUniformInfo(GLint index) const {
161 return (static_cast<size_t>(index) < uniform_infos_.size()) ?
162 &uniform_infos_[index] : NULL;
163 }
164
165 // Gets the location of a uniform by name.
166 GLint GetUniformLocation(const std::string& name) const;
167
168 bool GetProgramiv(GLenum pname, GLint* params);
169
170 // Updates the program info after a successful link.
171 void Update(GLES2Implementation* gl, GLuint program);
172
173 private:
174 bool cached_;
175
176 GLsizei max_attrib_name_length_;
177
178 // Attrib by index.
179 AttribInfoVector attrib_infos_;
180
181 GLsizei max_uniform_name_length_;
182
183 // Uniform info by index.
184 UniformInfoVector uniform_infos_;
185
186 // This is true if glLinkProgram was successful last time it was called.
187 bool link_status_;
188 };
189
190 ProgramInfo* GetProgramInfo(GLES2Implementation* gl, GLuint program);
191
192 // TODO(gman): Switch to a faster container.
193 typedef std::map<GLuint, ProgramInfo> ProgramInfoMap;
194
195 ProgramInfoMap program_infos_;
196 };
197
198 CachedProgramInfoManager::ProgramInfo::UniformInfo::UniformInfo(
199 GLsizei _size, GLenum _type, const std::string& _name)
200 : size(_size),
201 type(_type),
202 name(_name) {
203 is_array = (!name.empty() && name[name.size() - 1] == ']');
204 GPU_DCHECK(!(size > 1 && !is_array));
205 }
206
207 CachedProgramInfoManager::ProgramInfo::ProgramInfo()
208 : cached_(false),
209 max_attrib_name_length_(0),
210 max_uniform_name_length_(0),
211 link_status_(false) {
212 }
213
214 // TODO(gman): Add a faster lookup.
215 GLint CachedProgramInfoManager::ProgramInfo::GetAttribLocation(
216 const std::string& name) const {
217 for (GLuint ii = 0; ii < attrib_infos_.size(); ++ii) {
218 const VertexAttribInfo& info = attrib_infos_[ii];
219 if (info.name == name) {
220 return info.location;
221 }
222 }
223 return -1;
224 }
225
226 // TODO(gman): Add a faster lookup.
227 GLint CachedProgramInfoManager::ProgramInfo::GetUniformLocation(
228 const std::string& name) const {
229 for (GLuint ii = 0; ii < uniform_infos_.size(); ++ii) {
230 const UniformInfo& info = uniform_infos_[ii];
231 if (info.name == name ||
232 (info.is_array &&
233 info.name.compare(0, info.name.size() - 3, name) == 0)) {
234 return info.element_locations[0];
235 } else if (info.is_array &&
236 name.size() >= 3 && name[name.size() - 1] == ']') {
237 // Look for an array specification.
238 size_t open_pos = name.find_last_of('[');
239 if (open_pos != std::string::npos &&
240 open_pos < name.size() - 2 &&
241 info.name.size() > open_pos &&
242 name.compare(0, open_pos, info.name, 0, open_pos) == 0) {
243 GLint index = 0;
244 size_t last = name.size() - 1;
245 bool bad = false;
246 for (size_t pos = open_pos + 1; pos < last; ++pos) {
247 int8 digit = name[pos] - '0';
248 if (digit < 0 || digit > 9) {
249 bad = true;
250 break;
251 }
252 index = index * 10 + digit;
253 }
254 if (!bad && index >= 0 && index < info.size) {
255 return info.element_locations[index];
256 }
257 }
258 }
259 }
260 return -1;
261 }
262
263 bool CachedProgramInfoManager::ProgramInfo::GetProgramiv(
264 GLenum pname, GLint* params) {
265 switch (pname) {
266 case GL_LINK_STATUS:
267 *params = link_status_;
268 return true;
269 case GL_ACTIVE_ATTRIBUTES:
270 *params = attrib_infos_.size();
271 return true;
272 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
273 *params = max_attrib_name_length_;
274 return true;
275 case GL_ACTIVE_UNIFORMS:
276 *params = uniform_infos_.size();
277 return true;
278 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
279 *params = max_uniform_name_length_;
280 return true;
281 default:
282 break;
283 }
284 return false;
285 }
286
287 template<typename T> static T LocalGetAs(
288 const std::vector<int8>& data, uint32 offset, size_t size) {
289 const int8* p = &data[0] + offset;
290 if (offset + size > data.size()) {
291 GPU_NOTREACHED();
292 return NULL;
293 }
294 return static_cast<T>(static_cast<const void*>(p));
295 }
296
297 void CachedProgramInfoManager::ProgramInfo::Update(
298 GLES2Implementation* gl, GLuint program) {
299 if (cached_) {
300 return;
301 }
302 std::vector<int8> result;
303 gl->GetProgramInfoCHROMIUMHelper(program, &result);
304 if (result.empty()) {
305 // This should only happen on a lost context.
306 return;
307 }
308 GPU_DCHECK_GE(result.size(), sizeof(ProgramInfoHeader));
309 const ProgramInfoHeader* header = LocalGetAs<const ProgramInfoHeader*>(
310 result, 0, sizeof(header));
311 link_status_ = header->link_status != 0;
312 if (!link_status_) {
313 return;
314 }
315 attrib_infos_.clear();
316 uniform_infos_.clear();
317 max_attrib_name_length_ = 0;
318 max_uniform_name_length_ = 0;
319 const ProgramInput* inputs = LocalGetAs<const ProgramInput*>(
320 result, sizeof(*header),
321 sizeof(ProgramInput) * (header->num_attribs + header->num_uniforms));
322 const ProgramInput* input = inputs;
323 for (uint32 ii = 0; ii < header->num_attribs; ++ii) {
324 const int32* location = LocalGetAs<const int32*>(
325 result, input->location_offset, sizeof(int32));
326 const char* name_buf = LocalGetAs<const char*>(
327 result, input->name_offset, input->name_length);
328 std::string name(name_buf, input->name_length);
329 attrib_infos_.push_back(
330 VertexAttribInfo(input->size, input->type, name, *location));
331 max_attrib_name_length_ = std::max(
332 static_cast<GLsizei>(name.size() + 1), max_attrib_name_length_);
333 ++input;
334 }
335 for (uint32 ii = 0; ii < header->num_uniforms; ++ii) {
336 const int32* locations = LocalGetAs<const int32*>(
337 result, input->location_offset, sizeof(int32) * input->size);
338 const char* name_buf = LocalGetAs<const char*>(
339 result, input->name_offset, input->name_length);
340 std::string name(name_buf, input->name_length);
341 UniformInfo info(input->size, input->type, name);
342 max_uniform_name_length_ = std::max(
343 static_cast<GLsizei>(name.size() + 1), max_uniform_name_length_);
344 for (int32 jj = 0; jj < input->size; ++jj) {
345 info.element_locations.push_back(locations[jj]);
346 }
347 uniform_infos_.push_back(info);
348 ++input;
349 }
350 GPU_DCHECK_EQ(header->num_attribs + header->num_uniforms,
351 static_cast<uint32>(input - inputs));
352 cached_ = true;
353 }
354
355 CachedProgramInfoManager::CachedProgramInfoManager() {
356 }
357
358 CachedProgramInfoManager::~CachedProgramInfoManager() {
359
360 }
361
362 CachedProgramInfoManager::ProgramInfo*
363 CachedProgramInfoManager::GetProgramInfo(
364 GLES2Implementation* gl, GLuint program) {
365 ProgramInfoMap::iterator it = program_infos_.find(program);
366 if (it == program_infos_.end()) {
367 return NULL;
368 }
369 ProgramInfo* info = &it->second;
370 info->Update(gl, program);
371 return info;
372 }
373
374 void CachedProgramInfoManager::CreateInfo(GLuint program) {
375 DeleteInfo(program);
376 std::pair<ProgramInfoMap::iterator, bool> result =
377 program_infos_.insert(std::make_pair(program, ProgramInfo()));
378
379 GPU_DCHECK(result.second);
380 }
381
382 void CachedProgramInfoManager::DeleteInfo(GLuint program) {
383 program_infos_.erase(program);
384 }
385
386 bool CachedProgramInfoManager::GetProgramiv(
387 GLES2Implementation* gl, GLuint program, GLenum pname, GLint* params) {
388 ProgramInfo* info = GetProgramInfo(gl, program);
389 if (!info) {
390 return false;
391 }
392 return info->GetProgramiv(pname, params);
393 }
394
395 GLint CachedProgramInfoManager::GetAttribLocation(
396 GLES2Implementation* gl, GLuint program, const char* name) {
397 ProgramInfo* info = GetProgramInfo(gl, program);
398 if (info) {
399 return info->GetAttribLocation(name);
400 }
401 return gl->GetAttribLocationHelper(program, name);
402 }
403
404 GLint CachedProgramInfoManager::GetUniformLocation(
405 GLES2Implementation* gl, GLuint program, const char* name) {
406 ProgramInfo* info = GetProgramInfo(gl, program);
407 if (info) {
408 return info->GetUniformLocation(name);
409 }
410 return gl->GetUniformLocationHelper(program, name);
411 }
412
413 bool CachedProgramInfoManager::GetActiveAttrib(
414 GLES2Implementation* gl,
415 GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
416 GLint* size, GLenum* type, char* name) {
417 ProgramInfo* info = GetProgramInfo(gl, program);
418 if (info) {
419 const ProgramInfo::VertexAttribInfo* attrib_info =
420 info->GetAttribInfo(index);
421 if (attrib_info) {
422 if (size) {
423 *size = attrib_info->size;
424 }
425 if (type) {
426 *type = attrib_info->type;
427 }
428 if (length || name) {
429 GLsizei max_size = std::min(static_cast<size_t>(bufsize) - 1,
430 std::max(static_cast<size_t>(0),
431 attrib_info->name.size()));
432 if (length) {
433 *length = max_size;
434 }
435 if (name && bufsize > 0) {
436 memcpy(name, attrib_info->name.c_str(), max_size);
437 name[max_size] = '\0';
438 }
439 }
440 return true;
441 }
442 }
443 return gl->GetActiveAttribHelper(
444 program, index, bufsize, length, size, type, name);
445 }
446
447 bool CachedProgramInfoManager::GetActiveUniform(
448 GLES2Implementation* gl,
449 GLuint program, GLuint index, GLsizei bufsize, GLsizei* length,
450 GLint* size, GLenum* type, char* name) {
451 ProgramInfo* info = GetProgramInfo(gl, program);
452 if (info) {
453 const ProgramInfo::UniformInfo* uniform_info = info->GetUniformInfo(index);
454 if (uniform_info) {
455 if (size) {
456 *size = uniform_info->size;
457 }
458 if (type) {
459 *type = uniform_info->type;
460 }
461 if (length || name) {
462 GLsizei max_size = std::min(static_cast<size_t>(bufsize) - 1,
463 std::max(static_cast<size_t>(0),
464 uniform_info->name.size()));
465 if (length) {
466 *length = max_size;
467 }
468 if (name && bufsize > 0) {
469 memcpy(name, uniform_info->name.c_str(), max_size);
470 name[max_size] = '\0';
471 }
472 }
473 return true;
474 }
475 }
476 return gl->GetActiveUniformHelper(
477 program, index, bufsize, length, size, type, name);
478 }
479
480 ProgramInfoManager::ProgramInfoManager() {
481 }
482
483 ProgramInfoManager::~ProgramInfoManager() {
484 }
485
486 ProgramInfoManager* ProgramInfoManager::Create(bool shared_resources) {
487 if (shared_resources) {
488 return new NonCachedProgramInfoManager();
489 } else {
490 return new CachedProgramInfoManager();
491 }
492 }
493
494 } // namespace gles2
495 } // namespace gpu
496
OLDNEW
« 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