Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / gpu / command_buffer / service / program_manager.cc
blobb9a38351721dabe62772e65197d08c3d89d83439
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
3 // found in the LICENSE file.
5 #include "gpu/command_buffer/service/program_manager.h"
7 #include <algorithm>
8 #include <set>
9 #include <utility>
10 #include <vector>
12 #include "base/basictypes.h"
13 #include "base/command_line.h"
14 #include "base/logging.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/metrics/histogram.h"
17 #include "base/numerics/safe_math.h"
18 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_util.h"
20 #include "base/time/time.h"
21 #include "gpu/command_buffer/common/gles2_cmd_format.h"
22 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
23 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
24 #include "gpu/command_buffer/service/gpu_switches.h"
25 #include "gpu/command_buffer/service/program_cache.h"
26 #include "gpu/command_buffer/service/shader_manager.h"
27 #include "third_party/re2/re2/re2.h"
29 using base::TimeDelta;
30 using base::TimeTicks;
32 namespace gpu {
33 namespace gles2 {
35 namespace {
37 int ShaderTypeToIndex(GLenum shader_type) {
38 switch (shader_type) {
39 case GL_VERTEX_SHADER:
40 return 0;
41 case GL_FRAGMENT_SHADER:
42 return 1;
43 default:
44 NOTREACHED();
45 return 0;
49 // Given a name like "foo.bar[123].moo[456]" sets new_name to "foo.bar[123].moo"
50 // and sets element_index to 456. returns false if element expression was not a
51 // whole decimal number. For example: "foo[1b2]"
52 bool GetUniformNameSansElement(
53 const std::string& name, int* element_index, std::string* new_name) {
54 DCHECK(element_index);
55 DCHECK(new_name);
56 if (name.size() < 3 || name[name.size() - 1] != ']') {
57 *element_index = 0;
58 *new_name = name;
59 return true;
62 // Look for an array specification.
63 size_t open_pos = name.find_last_of('[');
64 if (open_pos == std::string::npos ||
65 open_pos >= name.size() - 2) {
66 return false;
69 base::CheckedNumeric<GLint> index = 0;
70 size_t last = name.size() - 1;
71 for (size_t pos = open_pos + 1; pos < last; ++pos) {
72 int8 digit = name[pos] - '0';
73 if (digit < 0 || digit > 9) {
74 return false;
76 index = index * 10 + digit;
78 if (!index.IsValid()) {
79 return false;
82 *element_index = index.ValueOrDie();
83 *new_name = name.substr(0, open_pos);
84 return true;
87 bool IsBuiltInFragmentVarying(const std::string& name) {
88 // Built-in variables for fragment shaders.
89 const char* kBuiltInVaryings[] = {
90 "gl_FragCoord",
91 "gl_FrontFacing",
92 "gl_PointCoord"
94 for (size_t ii = 0; ii < arraysize(kBuiltInVaryings); ++ii) {
95 if (name == kBuiltInVaryings[ii])
96 return true;
98 return false;
101 bool IsBuiltInInvariant(
102 const VaryingMap& varyings, const std::string& name) {
103 VaryingMap::const_iterator hit = varyings.find(name);
104 if (hit == varyings.end())
105 return false;
106 return hit->second.isInvariant;
109 uint32 ComputeOffset(const void* start, const void* position) {
110 return static_cast<const uint8*>(position) -
111 static_cast<const uint8*>(start);
114 } // anonymous namespace.
116 Program::UniformInfo::UniformInfo()
117 : size(0),
118 type(GL_NONE),
119 fake_location_base(0),
120 is_array(false) {
123 Program::UniformInfo::UniformInfo(GLsizei _size,
124 GLenum _type,
125 int _fake_location_base,
126 const std::string& _name)
127 : size(_size),
128 type(_type),
129 accepts_api_type(0),
130 fake_location_base(_fake_location_base),
131 is_array(false),
132 name(_name) {
133 switch (type) {
134 case GL_INT:
135 accepts_api_type = kUniform1i;
136 break;
137 case GL_INT_VEC2:
138 accepts_api_type = kUniform2i;
139 break;
140 case GL_INT_VEC3:
141 accepts_api_type = kUniform3i;
142 break;
143 case GL_INT_VEC4:
144 accepts_api_type = kUniform4i;
145 break;
147 case GL_UNSIGNED_INT:
148 accepts_api_type = kUniform1ui;
149 break;
150 case GL_UNSIGNED_INT_VEC2:
151 accepts_api_type = kUniform2ui;
152 break;
153 case GL_UNSIGNED_INT_VEC3:
154 accepts_api_type = kUniform3ui;
155 break;
156 case GL_UNSIGNED_INT_VEC4:
157 accepts_api_type = kUniform4ui;
158 break;
160 case GL_BOOL:
161 accepts_api_type = kUniform1i | kUniform1ui | kUniform1f;
162 break;
163 case GL_BOOL_VEC2:
164 accepts_api_type = kUniform2i | kUniform2ui | kUniform2f;
165 break;
166 case GL_BOOL_VEC3:
167 accepts_api_type = kUniform3i | kUniform3ui | kUniform3f;
168 break;
169 case GL_BOOL_VEC4:
170 accepts_api_type = kUniform4i | kUniform4ui | kUniform4f;
171 break;
173 case GL_FLOAT:
174 accepts_api_type = kUniform1f;
175 break;
176 case GL_FLOAT_VEC2:
177 accepts_api_type = kUniform2f;
178 break;
179 case GL_FLOAT_VEC3:
180 accepts_api_type = kUniform3f;
181 break;
182 case GL_FLOAT_VEC4:
183 accepts_api_type = kUniform4f;
184 break;
186 case GL_FLOAT_MAT2:
187 accepts_api_type = kUniformMatrix2f;
188 break;
189 case GL_FLOAT_MAT3:
190 accepts_api_type = kUniformMatrix3f;
191 break;
192 case GL_FLOAT_MAT4:
193 accepts_api_type = kUniformMatrix4f;
194 break;
196 case GL_FLOAT_MAT2x3:
197 accepts_api_type = kUniformMatrix2x3f;
198 break;
199 case GL_FLOAT_MAT2x4:
200 accepts_api_type = kUniformMatrix2x4f;
201 break;
202 case GL_FLOAT_MAT3x2:
203 accepts_api_type = kUniformMatrix3x2f;
204 break;
205 case GL_FLOAT_MAT3x4:
206 accepts_api_type = kUniformMatrix3x4f;
207 break;
208 case GL_FLOAT_MAT4x2:
209 accepts_api_type = kUniformMatrix4x2f;
210 break;
211 case GL_FLOAT_MAT4x3:
212 accepts_api_type = kUniformMatrix4x3f;
213 break;
215 case GL_SAMPLER_2D:
216 case GL_SAMPLER_2D_RECT_ARB:
217 case GL_SAMPLER_CUBE:
218 case GL_SAMPLER_3D_OES:
219 case GL_SAMPLER_EXTERNAL_OES:
220 case GL_SAMPLER_2D_ARRAY:
221 case GL_SAMPLER_2D_SHADOW:
222 case GL_SAMPLER_2D_ARRAY_SHADOW:
223 case GL_INT_SAMPLER_2D:
224 case GL_INT_SAMPLER_3D:
225 case GL_INT_SAMPLER_CUBE:
226 case GL_INT_SAMPLER_2D_ARRAY:
227 case GL_UNSIGNED_INT_SAMPLER_2D:
228 case GL_UNSIGNED_INT_SAMPLER_3D:
229 case GL_UNSIGNED_INT_SAMPLER_CUBE:
230 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
231 accepts_api_type = kUniform1i;
232 break;
234 default:
235 NOTREACHED() << "Unhandled UniformInfo type " << type;
236 break;
240 Program::UniformInfo::~UniformInfo() {}
242 bool ProgramManager::IsInvalidPrefix(const char* name, size_t length) {
243 static const char kInvalidPrefix[] = { 'g', 'l', '_' };
244 return (length >= sizeof(kInvalidPrefix) &&
245 memcmp(name, kInvalidPrefix, sizeof(kInvalidPrefix)) == 0);
248 Program::Program(ProgramManager* manager, GLuint service_id)
249 : manager_(manager),
250 use_count_(0),
251 max_attrib_name_length_(0),
252 max_uniform_name_length_(0),
253 service_id_(service_id),
254 deleted_(false),
255 valid_(false),
256 link_status_(false),
257 uniforms_cleared_(false),
258 num_uniforms_(0),
259 transform_feedback_buffer_mode_(GL_NONE) {
260 manager_->StartTracking(this);
263 void Program::Reset() {
264 valid_ = false;
265 link_status_ = false;
266 num_uniforms_ = 0;
267 max_uniform_name_length_ = 0;
268 max_attrib_name_length_ = 0;
269 attrib_infos_.clear();
270 uniform_infos_.clear();
271 sampler_indices_.clear();
272 attrib_location_to_index_map_.clear();
275 std::string Program::ProcessLogInfo(
276 const std::string& log) {
277 std::string output;
278 re2::StringPiece input(log);
279 std::string prior_log;
280 std::string hashed_name;
281 while (RE2::Consume(&input,
282 "(.*?)(webgl_[0123456789abcdefABCDEF]+)",
283 &prior_log,
284 &hashed_name)) {
285 output += prior_log;
287 const std::string* original_name =
288 GetOriginalNameFromHashedName(hashed_name);
289 if (original_name)
290 output += *original_name;
291 else
292 output += hashed_name;
295 return output + input.as_string();
298 void Program::UpdateLogInfo() {
299 GLint max_len = 0;
300 glGetProgramiv(service_id_, GL_INFO_LOG_LENGTH, &max_len);
301 if (max_len == 0) {
302 set_log_info(NULL);
303 return;
305 scoped_ptr<char[]> temp(new char[max_len]);
306 GLint len = 0;
307 glGetProgramInfoLog(service_id_, max_len, &len, temp.get());
308 DCHECK(max_len == 0 || len < max_len);
309 DCHECK(len == 0 || temp[len] == '\0');
310 std::string log(temp.get(), len);
311 set_log_info(ProcessLogInfo(log).c_str());
314 void Program::ClearUniforms(
315 std::vector<uint8>* zero_buffer) {
316 DCHECK(zero_buffer);
317 if (uniforms_cleared_) {
318 return;
320 uniforms_cleared_ = true;
321 for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) {
322 const UniformInfo& uniform_info = uniform_infos_[ii];
323 if (!uniform_info.IsValid()) {
324 continue;
326 GLint location = uniform_info.element_locations[0];
327 GLsizei size = uniform_info.size;
328 uint32 unit_size =
329 GLES2Util::GetElementCountForUniformType(uniform_info.type) *
330 GLES2Util::GetElementSizeForUniformType(uniform_info.type);
331 DCHECK_LT(0u, unit_size);
332 uint32 size_needed = size * unit_size;
333 if (size_needed > zero_buffer->size()) {
334 zero_buffer->resize(size_needed, 0u);
336 const void* zero = &(*zero_buffer)[0];
337 switch (uniform_info.type) {
338 case GL_FLOAT:
339 glUniform1fv(location, size, reinterpret_cast<const GLfloat*>(zero));
340 break;
341 case GL_FLOAT_VEC2:
342 glUniform2fv(location, size, reinterpret_cast<const GLfloat*>(zero));
343 break;
344 case GL_FLOAT_VEC3:
345 glUniform3fv(location, size, reinterpret_cast<const GLfloat*>(zero));
346 break;
347 case GL_FLOAT_VEC4:
348 glUniform4fv(location, size, reinterpret_cast<const GLfloat*>(zero));
349 break;
350 case GL_INT:
351 case GL_BOOL:
352 case GL_SAMPLER_2D:
353 case GL_SAMPLER_CUBE:
354 case GL_SAMPLER_EXTERNAL_OES: // extension.
355 case GL_SAMPLER_2D_RECT_ARB: // extension.
356 glUniform1iv(location, size, reinterpret_cast<const GLint*>(zero));
357 break;
358 case GL_INT_VEC2:
359 case GL_BOOL_VEC2:
360 glUniform2iv(location, size, reinterpret_cast<const GLint*>(zero));
361 break;
362 case GL_INT_VEC3:
363 case GL_BOOL_VEC3:
364 glUniform3iv(location, size, reinterpret_cast<const GLint*>(zero));
365 break;
366 case GL_INT_VEC4:
367 case GL_BOOL_VEC4:
368 glUniform4iv(location, size, reinterpret_cast<const GLint*>(zero));
369 break;
370 case GL_FLOAT_MAT2:
371 glUniformMatrix2fv(
372 location, size, false, reinterpret_cast<const GLfloat*>(zero));
373 break;
374 case GL_FLOAT_MAT3:
375 glUniformMatrix3fv(
376 location, size, false, reinterpret_cast<const GLfloat*>(zero));
377 break;
378 case GL_FLOAT_MAT4:
379 glUniformMatrix4fv(
380 location, size, false, reinterpret_cast<const GLfloat*>(zero));
381 break;
383 // ES3 types.
384 case GL_UNSIGNED_INT:
385 glUniform1uiv(location, size, reinterpret_cast<const GLuint*>(zero));
386 break;
387 case GL_SAMPLER_3D:
388 case GL_SAMPLER_2D_SHADOW:
389 case GL_SAMPLER_2D_ARRAY:
390 case GL_SAMPLER_2D_ARRAY_SHADOW:
391 case GL_SAMPLER_CUBE_SHADOW:
392 case GL_INT_SAMPLER_2D:
393 case GL_INT_SAMPLER_3D:
394 case GL_INT_SAMPLER_CUBE:
395 case GL_INT_SAMPLER_2D_ARRAY:
396 case GL_UNSIGNED_INT_SAMPLER_2D:
397 case GL_UNSIGNED_INT_SAMPLER_3D:
398 case GL_UNSIGNED_INT_SAMPLER_CUBE:
399 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
400 glUniform1iv(location, size, reinterpret_cast<const GLint*>(zero));
401 break;
402 case GL_UNSIGNED_INT_VEC2:
403 glUniform2uiv(location, size, reinterpret_cast<const GLuint*>(zero));
404 break;
405 case GL_UNSIGNED_INT_VEC3:
406 glUniform3uiv(location, size, reinterpret_cast<const GLuint*>(zero));
407 break;
408 case GL_UNSIGNED_INT_VEC4:
409 glUniform4uiv(location, size, reinterpret_cast<const GLuint*>(zero));
410 break;
411 case GL_FLOAT_MAT2x3:
412 glUniformMatrix2x3fv(
413 location, size, false, reinterpret_cast<const GLfloat*>(zero));
414 break;
415 case GL_FLOAT_MAT3x2:
416 glUniformMatrix3x2fv(
417 location, size, false, reinterpret_cast<const GLfloat*>(zero));
418 break;
419 case GL_FLOAT_MAT2x4:
420 glUniformMatrix2x4fv(
421 location, size, false, reinterpret_cast<const GLfloat*>(zero));
422 break;
423 case GL_FLOAT_MAT4x2:
424 glUniformMatrix4x2fv(
425 location, size, false, reinterpret_cast<const GLfloat*>(zero));
426 break;
427 case GL_FLOAT_MAT3x4:
428 glUniformMatrix3x4fv(
429 location, size, false, reinterpret_cast<const GLfloat*>(zero));
430 break;
431 case GL_FLOAT_MAT4x3:
432 glUniformMatrix4x3fv(
433 location, size, false, reinterpret_cast<const GLfloat*>(zero));
434 break;
436 default:
437 NOTREACHED();
438 break;
443 namespace {
445 struct UniformData {
446 UniformData() : size(-1), type(GL_NONE), location(0), added(false) {
448 std::string queried_name;
449 std::string corrected_name;
450 std::string original_name;
451 GLsizei size;
452 GLenum type;
453 GLint location;
454 bool added;
457 struct UniformDataComparer {
458 bool operator()(const UniformData& lhs, const UniformData& rhs) const {
459 return lhs.queried_name < rhs.queried_name;
463 } // anonymous namespace
465 void Program::Update() {
466 Reset();
467 UpdateLogInfo();
468 link_status_ = true;
469 uniforms_cleared_ = false;
470 GLint num_attribs = 0;
471 GLint max_len = 0;
472 GLint max_location = -1;
473 glGetProgramiv(service_id_, GL_ACTIVE_ATTRIBUTES, &num_attribs);
474 glGetProgramiv(service_id_, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_len);
475 // TODO(gman): Should we check for error?
476 scoped_ptr<char[]> name_buffer(new char[max_len]);
477 for (GLint ii = 0; ii < num_attribs; ++ii) {
478 GLsizei length = 0;
479 GLsizei size = 0;
480 GLenum type = 0;
481 glGetActiveAttrib(
482 service_id_, ii, max_len, &length, &size, &type, name_buffer.get());
483 DCHECK(max_len == 0 || length < max_len);
484 DCHECK(length == 0 || name_buffer[length] == '\0');
485 std::string original_name;
486 GetVertexAttribData(name_buffer.get(), &original_name, &type);
487 // TODO(gman): Should we check for error?
488 GLint location = glGetAttribLocation(service_id_, name_buffer.get());
489 if (location > max_location) {
490 max_location = location;
492 attrib_infos_.push_back(VertexAttrib(1, type, original_name, location));
493 max_attrib_name_length_ = std::max(
494 max_attrib_name_length_, static_cast<GLsizei>(original_name.size()));
497 // Create attrib location to index map.
498 attrib_location_to_index_map_.resize(max_location + 1);
499 for (GLint ii = 0; ii <= max_location; ++ii) {
500 attrib_location_to_index_map_[ii] = -1;
502 for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) {
503 const VertexAttrib& info = attrib_infos_[ii];
504 attrib_location_to_index_map_[info.location] = ii;
507 #if !defined(NDEBUG)
508 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
509 switches::kEnableGPUServiceLoggingGPU)) {
510 DVLOG(1) << "----: attribs for service_id: " << service_id();
511 for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) {
512 const VertexAttrib& info = attrib_infos_[ii];
513 DVLOG(1) << ii << ": loc = " << info.location
514 << ", size = " << info.size
515 << ", type = " << GLES2Util::GetStringEnum(info.type)
516 << ", name = " << info.name;
519 #endif
521 max_len = 0;
522 GLint num_uniforms = 0;
523 glGetProgramiv(service_id_, GL_ACTIVE_UNIFORMS, &num_uniforms);
524 glGetProgramiv(service_id_, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_len);
525 name_buffer.reset(new char[max_len]);
527 // Reads all the names.
528 std::vector<UniformData> uniform_data;
529 for (GLint ii = 0; ii < num_uniforms; ++ii) {
530 GLsizei length = 0;
531 UniformData data;
532 glGetActiveUniform(
533 service_id_, ii, max_len, &length,
534 &data.size, &data.type, name_buffer.get());
535 DCHECK(max_len == 0 || length < max_len);
536 DCHECK(length == 0 || name_buffer[length] == '\0');
537 data.queried_name = std::string(name_buffer.get());
538 GetCorrectedUniformData(data.queried_name, &data.corrected_name,
539 &data.original_name, &data.size, &data.type);
540 uniform_data.push_back(data);
543 // NOTE: We don't care if 2 uniforms are bound to the same location.
544 // One of them will take preference. The spec allows this, same as
545 // BindAttribLocation.
547 // The reason we don't check is if we were to fail we'd have to
548 // restore the previous program but since we've already linked successfully
549 // at this point the previous program is gone.
551 // Assigns the uniforms with bindings.
552 size_t next_available_index = 0;
553 for (size_t ii = 0; ii < uniform_data.size(); ++ii) {
554 UniformData& data = uniform_data[ii];
555 // Force builtin uniforms (gl_DepthRange) to have invalid location.
556 if (ProgramManager::IsInvalidPrefix(data.queried_name.c_str(),
557 data.queried_name.size())) {
558 data.location = -1;
559 } else {
560 data.location =
561 glGetUniformLocation(service_id_, data.queried_name.c_str());
563 // remove "[0]"
564 std::string short_name;
565 int element_index = 0;
566 bool good = GetUniformNameSansElement(data.queried_name, &element_index,
567 &short_name);
568 DCHECK(good);
569 LocationMap::const_iterator it = bind_uniform_location_map_.find(
570 short_name);
571 if (it != bind_uniform_location_map_.end()) {
572 AddUniformInfo(
573 data.size, data.type, data.location, it->second, data.corrected_name,
574 data.original_name, &next_available_index);
575 data.added = true;
579 // Assigns the uniforms that were not bound.
580 for (size_t ii = 0; ii < uniform_data.size(); ++ii) {
581 const UniformData& data = uniform_data[ii];
582 if (!data.added) {
583 AddUniformInfo(
584 data.size, data.type, data.location, -1, data.corrected_name,
585 data.original_name, &next_available_index);
589 #if !defined(NDEBUG)
590 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
591 switches::kEnableGPUServiceLoggingGPU)) {
592 DVLOG(1) << "----: uniforms for service_id: " << service_id();
593 for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) {
594 const UniformInfo& info = uniform_infos_[ii];
595 if (info.IsValid()) {
596 DVLOG(1) << ii << ": loc = " << info.element_locations[0]
597 << ", size = " << info.size
598 << ", type = " << GLES2Util::GetStringEnum(info.type)
599 << ", name = " << info.name;
603 #endif
605 valid_ = true;
608 void Program::ExecuteBindAttribLocationCalls() {
609 for (const auto& key_value : bind_attrib_location_map_) {
610 const std::string* mapped_name = GetAttribMappedName(key_value.first);
611 if (mapped_name)
612 glBindAttribLocation(service_id_, key_value.second, mapped_name->c_str());
616 bool Program::ExecuteTransformFeedbackVaryingsCall() {
617 if (!transform_feedback_varyings_.empty()) {
618 Shader* vertex_shader = attached_shaders_[0].get();
619 if (!vertex_shader) {
620 set_log_info("TransformFeedbackVaryings: missing vertex shader");
621 return false;
624 std::vector<const char*> mapped_names;
625 mapped_names.reserve(transform_feedback_varyings_.size());
626 for (StringVector::const_iterator it =
627 transform_feedback_varyings_.begin();
628 it != transform_feedback_varyings_.end(); ++it) {
629 const std::string& orig = *it;
630 const std::string* mapped = vertex_shader->GetVaryingMappedName(orig);
631 if (!mapped) {
632 std::string log = "TransformFeedbackVaryings: no varying named " + orig;
633 set_log_info(log.c_str());
634 return false;
636 mapped_names.push_back(mapped->c_str());
638 glTransformFeedbackVaryings(service_id_,
639 mapped_names.size(),
640 &mapped_names.front(),
641 transform_feedback_buffer_mode_);
644 return true;
647 bool Program::Link(ShaderManager* manager,
648 Program::VaryingsPackingOption varyings_packing_option,
649 const ShaderCacheCallback& shader_callback) {
650 ClearLinkStatus();
652 if (!AttachedShadersExist()) {
653 set_log_info("missing shaders");
654 return false;
657 TimeTicks before_time = TimeTicks::Now();
658 bool link = true;
659 ProgramCache* cache = manager_->program_cache_;
660 if (cache) {
661 DCHECK(!attached_shaders_[0]->last_compiled_source().empty() &&
662 !attached_shaders_[1]->last_compiled_source().empty());
663 ProgramCache::LinkedProgramStatus status = cache->GetLinkedProgramStatus(
664 attached_shaders_[0]->last_compiled_signature(),
665 attached_shaders_[1]->last_compiled_signature(),
666 &bind_attrib_location_map_,
667 transform_feedback_varyings_,
668 transform_feedback_buffer_mode_);
670 bool cache_hit = status == ProgramCache::LINK_SUCCEEDED;
671 UMA_HISTOGRAM_BOOLEAN("GPU.ProgramCache.CacheHit", cache_hit);
673 if (cache_hit) {
674 ProgramCache::ProgramLoadResult success =
675 cache->LoadLinkedProgram(service_id(),
676 attached_shaders_[0].get(),
677 attached_shaders_[1].get(),
678 &bind_attrib_location_map_,
679 transform_feedback_varyings_,
680 transform_feedback_buffer_mode_,
681 shader_callback);
682 link = success != ProgramCache::PROGRAM_LOAD_SUCCESS;
683 UMA_HISTOGRAM_BOOLEAN("GPU.ProgramCache.LoadBinarySuccess", !link);
687 if (link) {
688 CompileAttachedShaders();
690 if (!CanLink()) {
691 set_log_info("invalid shaders");
692 return false;
694 if (DetectShaderVersionMismatch()) {
695 set_log_info("Versions of linked shaders have to match.");
696 return false;
698 if (DetectAttribLocationBindingConflicts()) {
699 set_log_info("glBindAttribLocation() conflicts");
700 return false;
702 std::string conflicting_name;
703 if (DetectUniformsMismatch(&conflicting_name)) {
704 std::string info_log = "Uniforms with the same name but different "
705 "type/precision: " + conflicting_name;
706 set_log_info(ProcessLogInfo(info_log).c_str());
707 return false;
709 if (DetectUniformLocationBindingConflicts()) {
710 set_log_info("glBindUniformLocationCHROMIUM() conflicts");
711 return false;
713 if (DetectVaryingsMismatch(&conflicting_name)) {
714 std::string info_log = "Varyings with the same name but different type, "
715 "or statically used varyings in fragment shader "
716 "are not declared in vertex shader: " +
717 conflicting_name;
718 set_log_info(ProcessLogInfo(info_log).c_str());
719 return false;
721 if (DetectBuiltInInvariantConflicts()) {
722 set_log_info("Invariant settings for certain built-in varyings "
723 "have to match");
724 return false;
726 if (DetectGlobalNameConflicts(&conflicting_name)) {
727 std::string info_log = "Name conflicts between an uniform and an "
728 "attribute: " + conflicting_name;
729 set_log_info(ProcessLogInfo(info_log).c_str());
730 return false;
732 if (!CheckVaryingsPacking(varyings_packing_option)) {
733 set_log_info("Varyings over maximum register limit");
734 return false;
737 ExecuteBindAttribLocationCalls();
738 if (!ExecuteTransformFeedbackVaryingsCall()) {
739 return false;
741 before_time = TimeTicks::Now();
742 if (cache && gfx::g_driver_gl.ext.b_GL_ARB_get_program_binary) {
743 glProgramParameteri(service_id(),
744 PROGRAM_BINARY_RETRIEVABLE_HINT,
745 GL_TRUE);
747 glLinkProgram(service_id());
750 GLint success = 0;
751 glGetProgramiv(service_id(), GL_LINK_STATUS, &success);
752 if (success == GL_TRUE) {
753 Update();
754 if (link) {
755 if (cache) {
756 cache->SaveLinkedProgram(service_id(),
757 attached_shaders_[0].get(),
758 attached_shaders_[1].get(),
759 &bind_attrib_location_map_,
760 transform_feedback_varyings_,
761 transform_feedback_buffer_mode_,
762 shader_callback);
764 UMA_HISTOGRAM_CUSTOM_COUNTS(
765 "GPU.ProgramCache.BinaryCacheMissTime",
766 static_cast<base::HistogramBase::Sample>(
767 (TimeTicks::Now() - before_time).InMicroseconds()),
769 static_cast<base::HistogramBase::Sample>(
770 TimeDelta::FromSeconds(10).InMicroseconds()),
771 50);
772 } else {
773 UMA_HISTOGRAM_CUSTOM_COUNTS(
774 "GPU.ProgramCache.BinaryCacheHitTime",
775 static_cast<base::HistogramBase::Sample>(
776 (TimeTicks::Now() - before_time).InMicroseconds()),
778 static_cast<base::HistogramBase::Sample>(
779 TimeDelta::FromSeconds(1).InMicroseconds()),
780 50);
782 } else {
783 UpdateLogInfo();
785 return success == GL_TRUE;
788 void Program::Validate() {
789 if (!IsValid()) {
790 set_log_info("program not linked");
791 return;
793 glValidateProgram(service_id());
794 UpdateLogInfo();
797 GLint Program::GetUniformFakeLocation(
798 const std::string& name) const {
799 bool getting_array_location = false;
800 size_t open_pos = std::string::npos;
801 int index = 0;
802 if (!GLES2Util::ParseUniformName(
803 name, &open_pos, &index, &getting_array_location)) {
804 return -1;
806 for (GLuint ii = 0; ii < uniform_infos_.size(); ++ii) {
807 const UniformInfo& info = uniform_infos_[ii];
808 if (!info.IsValid()) {
809 continue;
811 if (info.name == name ||
812 (info.is_array &&
813 info.name.compare(0, info.name.size() - 3, name) == 0)) {
814 return info.fake_location_base;
815 } else if (getting_array_location && info.is_array) {
816 // Look for an array specification.
817 size_t open_pos_2 = info.name.find_last_of('[');
818 if (open_pos_2 == open_pos &&
819 name.compare(0, open_pos, info.name, 0, open_pos) == 0) {
820 if (index >= 0 && index < info.size) {
821 DCHECK_GT(static_cast<int>(info.element_locations.size()), index);
822 if (info.element_locations[index] == -1)
823 return -1;
824 return ProgramManager::MakeFakeLocation(
825 info.fake_location_base, index);
830 return -1;
833 GLint Program::GetAttribLocation(
834 const std::string& original_name) const {
835 for (GLuint ii = 0; ii < attrib_infos_.size(); ++ii) {
836 const VertexAttrib& info = attrib_infos_[ii];
837 if (info.name == original_name) {
838 return info.location;
841 return -1;
844 const Program::UniformInfo*
845 Program::GetUniformInfoByFakeLocation(
846 GLint fake_location, GLint* real_location, GLint* array_index) const {
847 DCHECK(real_location);
848 DCHECK(array_index);
849 if (fake_location < 0) {
850 return NULL;
853 GLint uniform_index = GetUniformInfoIndexFromFakeLocation(fake_location);
854 if (uniform_index >= 0 &&
855 static_cast<size_t>(uniform_index) < uniform_infos_.size()) {
856 const UniformInfo& uniform_info = uniform_infos_[uniform_index];
857 if (!uniform_info.IsValid()) {
858 return NULL;
860 GLint element_index = GetArrayElementIndexFromFakeLocation(fake_location);
861 if (element_index < uniform_info.size) {
862 *real_location = uniform_info.element_locations[element_index];
863 *array_index = element_index;
864 return &uniform_info;
867 return NULL;
870 const std::string* Program::GetAttribMappedName(
871 const std::string& original_name) const {
872 for (auto shader : attached_shaders_) {
873 if (shader) {
874 const std::string* mapped_name =
875 shader->GetAttribMappedName(original_name);
876 if (mapped_name)
877 return mapped_name;
880 return nullptr;
883 const std::string* Program::GetUniformMappedName(
884 const std::string& original_name) const {
885 for (auto shader : attached_shaders_) {
886 if (shader) {
887 const std::string* mapped_name =
888 shader->GetUniformMappedName(original_name);
889 if (mapped_name)
890 return mapped_name;
893 return nullptr;
896 const std::string* Program::GetOriginalNameFromHashedName(
897 const std::string& hashed_name) const {
898 for (auto shader : attached_shaders_) {
899 if (shader) {
900 const std::string* original_name =
901 shader->GetOriginalNameFromHashedName(hashed_name);
902 if (original_name)
903 return original_name;
906 return nullptr;
909 bool Program::SetUniformLocationBinding(
910 const std::string& name, GLint location) {
911 std::string short_name;
912 int element_index = 0;
913 if (!GetUniformNameSansElement(name, &element_index, &short_name) ||
914 element_index != 0) {
915 return false;
917 bind_uniform_location_map_[short_name] = location;
918 return true;
921 // Note: This is only valid to call right after a program has been linked
922 // successfully.
923 void Program::GetCorrectedUniformData(
924 const std::string& name,
925 std::string* corrected_name, std::string* original_name,
926 GLsizei* size, GLenum* type) const {
927 DCHECK(corrected_name && original_name && size && type);
928 for (auto shader : attached_shaders_) {
929 if (!shader)
930 continue;
931 const sh::ShaderVariable* info = NULL;
932 const sh::Uniform* uniform = shader->GetUniformInfo(name);
933 bool found = false;
934 if (uniform)
935 found = uniform->findInfoByMappedName(name, &info, original_name);
936 if (found) {
937 const std::string kArraySpec("[0]");
938 if (info->arraySize > 0 &&
939 !base::EndsWith(name, kArraySpec, base::CompareCase::SENSITIVE)) {
940 *corrected_name = name + kArraySpec;
941 *original_name += kArraySpec;
942 } else {
943 *corrected_name = name;
945 *type = info->type;
946 *size = std::max(1u, info->arraySize);
947 return;
950 // TODO(zmo): this path should never be reached unless there is a serious
951 // bug in the driver or in ANGLE translator.
952 *corrected_name = name;
953 *original_name = name;
956 void Program::GetVertexAttribData(
957 const std::string& name, std::string* original_name, GLenum* type) const {
958 DCHECK(original_name);
959 DCHECK(type);
960 Shader* shader = attached_shaders_[ShaderTypeToIndex(GL_VERTEX_SHADER)].get();
961 if (shader) {
962 // Vertex attributes can not be arrays or structs (GLSL ES 3.00.4, section
963 // 4.3.4, "Input Variables"), so the top level sh::Attribute returns the
964 // information we need.
965 const sh::Attribute* info = shader->GetAttribInfo(name);
966 if (info) {
967 *original_name = info->name;
968 *type = info->type;
969 return;
972 // TODO(zmo): this path should never be reached unless there is a serious
973 // bug in the driver or in ANGLE translator.
974 *original_name = name;
977 void Program::AddUniformInfo(
978 GLsizei size, GLenum type, GLint location, GLint fake_base_location,
979 const std::string& name, const std::string& original_name,
980 size_t* next_available_index) {
981 DCHECK(next_available_index);
982 const char* kArraySpec = "[0]";
983 size_t uniform_index =
984 fake_base_location >= 0 ? fake_base_location : *next_available_index;
985 if (uniform_infos_.size() < uniform_index + 1) {
986 uniform_infos_.resize(uniform_index + 1);
989 // Before linking, we already validated that no two statically used uniforms
990 // are bound to the same location.
991 DCHECK(!uniform_infos_[uniform_index].IsValid());
993 uniform_infos_[uniform_index] = UniformInfo(
994 size, type, uniform_index, original_name);
995 ++num_uniforms_;
997 UniformInfo& info = uniform_infos_[uniform_index];
998 info.element_locations.resize(size);
999 info.element_locations[0] = location;
1000 DCHECK_GE(size, 0);
1001 size_t num_texture_units = info.IsSampler() ? static_cast<size_t>(size) : 0u;
1002 info.texture_units.clear();
1003 info.texture_units.resize(num_texture_units, 0);
1005 if (size > 1) {
1006 // Go through the array element locations looking for a match.
1007 // We can skip the first element because it's the same as the
1008 // the location without the array operators.
1009 size_t array_pos = name.rfind(kArraySpec);
1010 std::string base_name = name;
1011 if (name.size() > 3) {
1012 if (array_pos != name.size() - 3) {
1013 info.name = name + kArraySpec;
1014 } else {
1015 base_name = name.substr(0, name.size() - 3);
1018 for (GLsizei ii = 1; ii < info.size; ++ii) {
1019 std::string element_name(base_name + "[" + base::IntToString(ii) + "]");
1020 info.element_locations[ii] =
1021 glGetUniformLocation(service_id_, element_name.c_str());
1025 info.is_array =
1026 (size > 1 ||
1027 (info.name.size() > 3 &&
1028 info.name.rfind(kArraySpec) == info.name.size() - 3));
1030 if (info.IsSampler()) {
1031 sampler_indices_.push_back(info.fake_location_base);
1033 max_uniform_name_length_ =
1034 std::max(max_uniform_name_length_,
1035 static_cast<GLsizei>(info.name.size()));
1037 while (*next_available_index < uniform_infos_.size() &&
1038 uniform_infos_[*next_available_index].IsValid()) {
1039 *next_available_index = *next_available_index + 1;
1043 const Program::UniformInfo*
1044 Program::GetUniformInfo(
1045 GLint index) const {
1046 if (static_cast<size_t>(index) >= uniform_infos_.size()) {
1047 return NULL;
1050 const UniformInfo& info = uniform_infos_[index];
1051 return info.IsValid() ? &info : NULL;
1054 bool Program::SetSamplers(
1055 GLint num_texture_units, GLint fake_location,
1056 GLsizei count, const GLint* value) {
1057 if (fake_location < 0) {
1058 return true;
1060 GLint uniform_index = GetUniformInfoIndexFromFakeLocation(fake_location);
1061 if (uniform_index >= 0 &&
1062 static_cast<size_t>(uniform_index) < uniform_infos_.size()) {
1063 UniformInfo& info = uniform_infos_[uniform_index];
1064 if (!info.IsValid()) {
1065 return false;
1067 GLint element_index = GetArrayElementIndexFromFakeLocation(fake_location);
1068 if (element_index < info.size) {
1069 count = std::min(info.size - element_index, count);
1070 if (info.IsSampler() && count > 0) {
1071 for (GLsizei ii = 0; ii < count; ++ii) {
1072 if (value[ii] < 0 || value[ii] >= num_texture_units) {
1073 return false;
1076 std::copy(value, value + count,
1077 info.texture_units.begin() + element_index);
1078 return true;
1082 return true;
1085 void Program::GetProgramiv(GLenum pname, GLint* params) {
1086 switch (pname) {
1087 case GL_ACTIVE_ATTRIBUTES:
1088 *params = attrib_infos_.size();
1089 break;
1090 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
1091 // Notice +1 to accomodate NULL terminator.
1092 *params = max_attrib_name_length_ + 1;
1093 break;
1094 case GL_ACTIVE_UNIFORMS:
1095 *params = num_uniforms_;
1096 break;
1097 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
1098 // Notice +1 to accomodate NULL terminator.
1099 *params = max_uniform_name_length_ + 1;
1100 break;
1101 case GL_LINK_STATUS:
1102 *params = link_status_;
1103 break;
1104 case GL_INFO_LOG_LENGTH:
1105 // Notice +1 to accomodate NULL terminator.
1106 *params = log_info_.get() ? (log_info_->size() + 1) : 0;
1107 break;
1108 case GL_DELETE_STATUS:
1109 *params = deleted_;
1110 break;
1111 case GL_VALIDATE_STATUS:
1112 if (!IsValid()) {
1113 *params = GL_FALSE;
1114 } else {
1115 glGetProgramiv(service_id_, pname, params);
1117 break;
1118 default:
1119 glGetProgramiv(service_id_, pname, params);
1120 break;
1124 bool Program::AttachShader(
1125 ShaderManager* shader_manager,
1126 Shader* shader) {
1127 DCHECK(shader_manager);
1128 DCHECK(shader);
1129 int index = ShaderTypeToIndex(shader->shader_type());
1130 if (attached_shaders_[index].get() != NULL) {
1131 return false;
1133 attached_shaders_[index] = scoped_refptr<Shader>(shader);
1134 shader_manager->UseShader(shader);
1135 return true;
1138 bool Program::DetachShader(
1139 ShaderManager* shader_manager,
1140 Shader* shader) {
1141 DCHECK(shader_manager);
1142 DCHECK(shader);
1143 if (attached_shaders_[ShaderTypeToIndex(shader->shader_type())].get() !=
1144 shader) {
1145 return false;
1147 attached_shaders_[ShaderTypeToIndex(shader->shader_type())] = NULL;
1148 shader_manager->UnuseShader(shader);
1149 return true;
1152 void Program::DetachShaders(ShaderManager* shader_manager) {
1153 DCHECK(shader_manager);
1154 for (auto shader : attached_shaders_) {
1155 if (shader) {
1156 DetachShader(shader_manager, shader.get());
1161 void Program::CompileAttachedShaders() {
1162 for (auto shader : attached_shaders_) {
1163 if (shader) {
1164 shader->DoCompile();
1169 bool Program::AttachedShadersExist() const {
1170 for (auto shader : attached_shaders_) {
1171 if (!shader)
1172 return false;
1174 return true;
1177 bool Program::CanLink() const {
1178 for (auto shader : attached_shaders_) {
1179 if (!shader || !shader->valid()) {
1180 return false;
1183 return true;
1186 bool Program::DetectShaderVersionMismatch() const {
1187 int version = Shader::kUndefinedShaderVersion;
1188 for (auto shader : attached_shaders_) {
1189 if (shader) {
1190 if (version != Shader::kUndefinedShaderVersion &&
1191 shader->shader_version() != version) {
1192 return true;
1194 version = shader->shader_version();
1195 DCHECK(version != Shader::kUndefinedShaderVersion);
1198 return false;
1201 bool Program::DetectAttribLocationBindingConflicts() const {
1202 std::set<GLint> location_binding_used;
1203 for (const auto& key_value : bind_attrib_location_map_) {
1204 // Find out if an attribute is statically used in this program's shaders.
1205 const sh::Attribute* attrib = NULL;
1206 const std::string* mapped_name = GetAttribMappedName(key_value.first);
1207 if (!mapped_name)
1208 continue;
1209 for (auto shader : attached_shaders_) {
1210 if (!shader || !shader->valid())
1211 continue;
1212 attrib = shader->GetAttribInfo(*mapped_name);
1213 if (attrib) {
1214 if (attrib->staticUse)
1215 break;
1216 else
1217 attrib = NULL;
1220 if (attrib) {
1221 size_t num_of_locations = 1;
1222 switch (attrib->type) {
1223 case GL_FLOAT_MAT2:
1224 num_of_locations = 2;
1225 break;
1226 case GL_FLOAT_MAT3:
1227 num_of_locations = 3;
1228 break;
1229 case GL_FLOAT_MAT4:
1230 num_of_locations = 4;
1231 break;
1232 default:
1233 break;
1235 for (size_t ii = 0; ii < num_of_locations; ++ii) {
1236 GLint loc = key_value.second + ii;
1237 auto result = location_binding_used.insert(loc);
1238 if (!result.second)
1239 return true;
1243 return false;
1246 bool Program::DetectUniformLocationBindingConflicts() const {
1247 std::set<GLint> location_binding_used;
1248 for (auto it : bind_uniform_location_map_) {
1249 // Find out if an attribute is statically used in this program's shaders.
1250 const sh::Uniform* uniform = nullptr;
1251 const std::string* mapped_name = GetUniformMappedName(it.first);
1252 if (!mapped_name)
1253 continue;
1254 for (auto shader : attached_shaders_) {
1255 if (!shader || !shader->valid())
1256 continue;
1257 uniform = shader->GetUniformInfo(*mapped_name);
1258 if (uniform) {
1259 if (uniform->staticUse)
1260 break;
1261 else
1262 uniform = nullptr;
1265 if (uniform) {
1266 auto result = location_binding_used.insert(it.second);
1267 if (!result.second)
1268 return true;
1271 return false;
1274 bool Program::DetectUniformsMismatch(std::string* conflicting_name) const {
1275 typedef std::map<std::string, const sh::Uniform*> UniformPointerMap;
1276 UniformPointerMap uniform_pointer_map;
1277 for (auto shader : attached_shaders_) {
1278 const UniformMap& shader_uniforms = shader->uniform_map();
1279 for (const auto& key_value : shader_uniforms) {
1280 const std::string& name = key_value.first;
1281 UniformPointerMap::iterator hit = uniform_pointer_map.find(name);
1282 if (hit == uniform_pointer_map.end()) {
1283 uniform_pointer_map[name] = &(key_value.second);
1284 } else {
1285 // If a uniform is in the map, i.e., it has already been declared by
1286 // another shader, then the type, precision, etc. must match.
1287 if (hit->second->isSameUniformAtLinkTime(key_value.second))
1288 continue;
1289 *conflicting_name = name;
1290 return true;
1294 return false;
1297 bool Program::DetectVaryingsMismatch(std::string* conflicting_name) const {
1298 DCHECK(attached_shaders_[0].get() &&
1299 attached_shaders_[0]->shader_type() == GL_VERTEX_SHADER &&
1300 attached_shaders_[1].get() &&
1301 attached_shaders_[1]->shader_type() == GL_FRAGMENT_SHADER);
1302 const VaryingMap* vertex_varyings = &(attached_shaders_[0]->varying_map());
1303 const VaryingMap* fragment_varyings = &(attached_shaders_[1]->varying_map());
1305 int shader_version = attached_shaders_[0]->shader_version();
1307 for (const auto& key_value : *fragment_varyings) {
1308 const std::string& name = key_value.first;
1309 if (IsBuiltInFragmentVarying(name))
1310 continue;
1312 VaryingMap::const_iterator hit = vertex_varyings->find(name);
1313 if (hit == vertex_varyings->end()) {
1314 if (key_value.second.staticUse) {
1315 *conflicting_name = name;
1316 return true;
1318 continue;
1321 if (!hit->second.isSameVaryingAtLinkTime(key_value.second,
1322 shader_version)) {
1323 *conflicting_name = name;
1324 return true;
1328 return false;
1331 bool Program::DetectBuiltInInvariantConflicts() const {
1332 DCHECK(attached_shaders_[0].get() &&
1333 attached_shaders_[0]->shader_type() == GL_VERTEX_SHADER &&
1334 attached_shaders_[1].get() &&
1335 attached_shaders_[1]->shader_type() == GL_FRAGMENT_SHADER);
1336 const VaryingMap& vertex_varyings = attached_shaders_[0]->varying_map();
1337 const VaryingMap& fragment_varyings = attached_shaders_[1]->varying_map();
1339 bool gl_position_invariant = IsBuiltInInvariant(
1340 vertex_varyings, "gl_Position");
1341 bool gl_point_size_invariant = IsBuiltInInvariant(
1342 vertex_varyings, "gl_PointSize");
1344 bool gl_frag_coord_invariant = IsBuiltInInvariant(
1345 fragment_varyings, "gl_FragCoord");
1346 bool gl_point_coord_invariant = IsBuiltInInvariant(
1347 fragment_varyings, "gl_PointCoord");
1349 return ((gl_frag_coord_invariant && !gl_position_invariant) ||
1350 (gl_point_coord_invariant && !gl_point_size_invariant));
1353 bool Program::DetectGlobalNameConflicts(std::string* conflicting_name) const {
1354 DCHECK(attached_shaders_[0].get() &&
1355 attached_shaders_[0]->shader_type() == GL_VERTEX_SHADER &&
1356 attached_shaders_[1].get() &&
1357 attached_shaders_[1]->shader_type() == GL_FRAGMENT_SHADER);
1358 const UniformMap* uniforms[2];
1359 uniforms[0] = &(attached_shaders_[0]->uniform_map());
1360 uniforms[1] = &(attached_shaders_[1]->uniform_map());
1361 const AttributeMap* attribs =
1362 &(attached_shaders_[0]->attrib_map());
1364 for (const auto& key_value : *attribs) {
1365 for (int ii = 0; ii < 2; ++ii) {
1366 if (uniforms[ii]->find(key_value.first) != uniforms[ii]->end()) {
1367 *conflicting_name = key_value.first;
1368 return true;
1372 return false;
1375 bool Program::CheckVaryingsPacking(
1376 Program::VaryingsPackingOption option) const {
1377 DCHECK(attached_shaders_[0].get() &&
1378 attached_shaders_[0]->shader_type() == GL_VERTEX_SHADER &&
1379 attached_shaders_[1].get() &&
1380 attached_shaders_[1]->shader_type() == GL_FRAGMENT_SHADER);
1381 const VaryingMap* vertex_varyings = &(attached_shaders_[0]->varying_map());
1382 const VaryingMap* fragment_varyings = &(attached_shaders_[1]->varying_map());
1384 std::map<std::string, ShVariableInfo> combined_map;
1386 for (const auto& key_value : *fragment_varyings) {
1387 if (!key_value.second.staticUse && option == kCountOnlyStaticallyUsed)
1388 continue;
1389 if (!IsBuiltInFragmentVarying(key_value.first)) {
1390 VaryingMap::const_iterator vertex_iter =
1391 vertex_varyings->find(key_value.first);
1392 if (vertex_iter == vertex_varyings->end() ||
1393 (!vertex_iter->second.staticUse &&
1394 option == kCountOnlyStaticallyUsed))
1395 continue;
1398 ShVariableInfo var;
1399 var.type = static_cast<sh::GLenum>(key_value.second.type);
1400 var.size = std::max(1u, key_value.second.arraySize);
1401 combined_map[key_value.first] = var;
1404 if (combined_map.size() == 0)
1405 return true;
1406 scoped_ptr<ShVariableInfo[]> variables(
1407 new ShVariableInfo[combined_map.size()]);
1408 size_t index = 0;
1409 for (const auto& key_value : combined_map) {
1410 variables[index].type = key_value.second.type;
1411 variables[index].size = key_value.second.size;
1412 ++index;
1414 return ShCheckVariablesWithinPackingLimits(
1415 static_cast<int>(manager_->max_varying_vectors()),
1416 variables.get(),
1417 combined_map.size());
1420 void Program::GetProgramInfo(
1421 ProgramManager* manager, CommonDecoder::Bucket* bucket) const {
1422 // NOTE: It seems to me the math in here does not need check for overflow
1423 // because the data being calucated from has various small limits. The max
1424 // number of attribs + uniforms is somewhere well under 1024. The maximum size
1425 // of an identifier is 256 characters.
1426 uint32 num_locations = 0;
1427 uint32 total_string_size = 0;
1429 for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) {
1430 const VertexAttrib& info = attrib_infos_[ii];
1431 num_locations += 1;
1432 total_string_size += info.name.size();
1435 for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) {
1436 const UniformInfo& info = uniform_infos_[ii];
1437 if (info.IsValid()) {
1438 num_locations += info.element_locations.size();
1439 total_string_size += info.name.size();
1443 uint32 num_inputs = attrib_infos_.size() + num_uniforms_;
1444 uint32 input_size = num_inputs * sizeof(ProgramInput);
1445 uint32 location_size = num_locations * sizeof(int32);
1446 uint32 size = sizeof(ProgramInfoHeader) +
1447 input_size + location_size + total_string_size;
1449 bucket->SetSize(size);
1450 ProgramInfoHeader* header = bucket->GetDataAs<ProgramInfoHeader*>(0, size);
1451 ProgramInput* inputs = bucket->GetDataAs<ProgramInput*>(
1452 sizeof(ProgramInfoHeader), input_size);
1453 int32* locations = bucket->GetDataAs<int32*>(
1454 sizeof(ProgramInfoHeader) + input_size, location_size);
1455 char* strings = bucket->GetDataAs<char*>(
1456 sizeof(ProgramInfoHeader) + input_size + location_size,
1457 total_string_size);
1458 DCHECK(header);
1459 DCHECK(inputs);
1460 DCHECK(locations);
1461 DCHECK(strings);
1463 header->link_status = link_status_;
1464 header->num_attribs = attrib_infos_.size();
1465 header->num_uniforms = num_uniforms_;
1467 for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) {
1468 const VertexAttrib& info = attrib_infos_[ii];
1469 inputs->size = info.size;
1470 inputs->type = info.type;
1471 inputs->location_offset = ComputeOffset(header, locations);
1472 inputs->name_offset = ComputeOffset(header, strings);
1473 inputs->name_length = info.name.size();
1474 *locations++ = info.location;
1475 memcpy(strings, info.name.c_str(), info.name.size());
1476 strings += info.name.size();
1477 ++inputs;
1480 for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) {
1481 const UniformInfo& info = uniform_infos_[ii];
1482 if (info.IsValid()) {
1483 inputs->size = info.size;
1484 inputs->type = info.type;
1485 inputs->location_offset = ComputeOffset(header, locations);
1486 inputs->name_offset = ComputeOffset(header, strings);
1487 inputs->name_length = info.name.size();
1488 DCHECK(static_cast<size_t>(info.size) == info.element_locations.size());
1489 for (size_t jj = 0; jj < info.element_locations.size(); ++jj) {
1490 if (info.element_locations[jj] == -1)
1491 *locations++ = -1;
1492 else
1493 *locations++ = ProgramManager::MakeFakeLocation(ii, jj);
1495 memcpy(strings, info.name.c_str(), info.name.size());
1496 strings += info.name.size();
1497 ++inputs;
1501 DCHECK_EQ(ComputeOffset(header, strings), size);
1504 bool Program::GetUniformBlocks(CommonDecoder::Bucket* bucket) const {
1505 // The data is packed into the bucket in the following order
1506 // 1) header
1507 // 2) N entries of block data (except for name and indices)
1508 // 3) name1, indices1, name2, indices2, ..., nameN, indicesN
1510 // We query all the data directly through GL calls, assuming they are
1511 // cheap through MANGLE.
1513 DCHECK(bucket);
1514 GLuint program = service_id();
1516 uint32_t header_size = sizeof(UniformBlocksHeader);
1517 bucket->SetSize(header_size); // In case we fail.
1519 uint32_t num_uniform_blocks = 0;
1520 GLint param = GL_FALSE;
1521 // We assume program is a valid program service id.
1522 glGetProgramiv(program, GL_LINK_STATUS, &param);
1523 if (param == GL_TRUE) {
1524 param = 0;
1525 glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &param);
1526 num_uniform_blocks = static_cast<uint32_t>(param);
1528 if (num_uniform_blocks == 0) {
1529 // Although spec allows an implementation to return uniform block info
1530 // even if a link fails, for consistency, we disallow that.
1531 return true;
1534 std::vector<UniformBlockInfo> blocks(num_uniform_blocks);
1535 base::CheckedNumeric<uint32_t> size = sizeof(UniformBlockInfo);
1536 size *= num_uniform_blocks;
1537 uint32_t entry_size = size.ValueOrDefault(0);
1538 size += header_size;
1539 std::vector<std::string> names(num_uniform_blocks);
1540 GLint max_name_length = 0;
1541 glGetProgramiv(
1542 program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_name_length);
1543 std::vector<GLchar> buffer(max_name_length);
1544 GLsizei length;
1545 for (uint32_t ii = 0; ii < num_uniform_blocks; ++ii) {
1546 param = 0;
1547 glGetActiveUniformBlockiv(program, ii, GL_UNIFORM_BLOCK_BINDING, &param);
1548 blocks[ii].binding = static_cast<uint32_t>(param);
1550 param = 0;
1551 glGetActiveUniformBlockiv(program, ii, GL_UNIFORM_BLOCK_DATA_SIZE, &param);
1552 blocks[ii].data_size = static_cast<uint32_t>(param);
1554 blocks[ii].name_offset = size.ValueOrDefault(0);
1555 param = 0;
1556 glGetActiveUniformBlockiv(
1557 program, ii, GL_UNIFORM_BLOCK_NAME_LENGTH, &param);
1558 DCHECK_GE(max_name_length, param);
1559 memset(&buffer[0], 0, param);
1560 length = 0;
1561 glGetActiveUniformBlockName(
1562 program, ii, static_cast<GLsizei>(param), &length, &buffer[0]);
1563 DCHECK_EQ(param, length + 1);
1564 names[ii] = std::string(&buffer[0], length);
1565 // TODO(zmo): optimize the name mapping lookup.
1566 const std::string* original_name = GetOriginalNameFromHashedName(names[ii]);
1567 if (original_name)
1568 names[ii] = *original_name;
1569 blocks[ii].name_length = names[ii].size() + 1;
1570 size += blocks[ii].name_length;
1572 param = 0;
1573 glGetActiveUniformBlockiv(
1574 program, ii, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, &param);
1575 blocks[ii].active_uniforms = static_cast<uint32_t>(param);
1576 blocks[ii].active_uniform_offset = size.ValueOrDefault(0);
1577 base::CheckedNumeric<uint32_t> indices_size = blocks[ii].active_uniforms;
1578 indices_size *= sizeof(uint32_t);
1579 if (!indices_size.IsValid())
1580 return false;
1581 size += indices_size.ValueOrDefault(0);
1583 param = 0;
1584 glGetActiveUniformBlockiv(
1585 program, ii, GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER, &param);
1586 blocks[ii].referenced_by_vertex_shader = static_cast<uint32_t>(param);
1588 param = 0;
1589 glGetActiveUniformBlockiv(
1590 program, ii, GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER, &param);
1591 blocks[ii].referenced_by_fragment_shader = static_cast<uint32_t>(param);
1593 if (!size.IsValid())
1594 return false;
1595 uint32_t total_size = size.ValueOrDefault(0);
1596 DCHECK_LE(header_size + entry_size, total_size);
1597 uint32_t data_size = total_size - header_size - entry_size;
1599 bucket->SetSize(total_size);
1600 UniformBlocksHeader* header =
1601 bucket->GetDataAs<UniformBlocksHeader*>(0, header_size);
1602 UniformBlockInfo* entries = bucket->GetDataAs<UniformBlockInfo*>(
1603 header_size, entry_size);
1604 char* data = bucket->GetDataAs<char*>(header_size + entry_size, data_size);
1605 DCHECK(header);
1606 DCHECK(entries);
1607 DCHECK(data);
1609 // Copy over data for the header and entries.
1610 header->num_uniform_blocks = num_uniform_blocks;
1611 memcpy(entries, &blocks[0], entry_size);
1613 std::vector<GLint> params;
1614 for (uint32_t ii = 0; ii < num_uniform_blocks; ++ii) {
1615 // Get active uniform name.
1616 memcpy(data, names[ii].c_str(), names[ii].length() + 1);
1617 data += names[ii].length() + 1;
1619 // Get active uniform indices.
1620 if (params.size() < blocks[ii].active_uniforms)
1621 params.resize(blocks[ii].active_uniforms);
1622 uint32_t num_bytes = blocks[ii].active_uniforms * sizeof(GLint);
1623 memset(&params[0], 0, num_bytes);
1624 glGetActiveUniformBlockiv(
1625 program, ii, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, &params[0]);
1626 uint32_t* indices = reinterpret_cast<uint32_t*>(data);
1627 for (uint32_t uu = 0; uu < blocks[ii].active_uniforms; ++uu) {
1628 indices[uu] = static_cast<uint32_t>(params[uu]);
1630 data += num_bytes;
1632 DCHECK_EQ(ComputeOffset(header, data), total_size);
1633 return true;
1636 bool Program::GetTransformFeedbackVaryings(
1637 CommonDecoder::Bucket* bucket) const {
1638 // The data is packed into the bucket in the following order
1639 // 1) header
1640 // 2) N entries of varying data (except for name)
1641 // 3) name1, name2, ..., nameN
1643 // We query all the data directly through GL calls, assuming they are
1644 // cheap through MANGLE.
1646 DCHECK(bucket);
1647 GLuint program = service_id();
1649 uint32_t header_size = sizeof(TransformFeedbackVaryingsHeader);
1650 bucket->SetSize(header_size); // In case we fail.
1652 GLenum transform_feedback_buffer_mode = 0;
1653 GLint param = 0;
1654 glGetProgramiv(program, GL_TRANSFORM_FEEDBACK_BUFFER_MODE, &param);
1655 transform_feedback_buffer_mode = static_cast<GLenum>(param);
1657 uint32_t num_transform_feedback_varyings = 0;
1658 param = GL_FALSE;
1659 // We assume program is a valid program service id.
1660 glGetProgramiv(program, GL_LINK_STATUS, &param);
1661 if (param == GL_TRUE) {
1662 param = 0;
1663 glGetProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYINGS, &param);
1664 num_transform_feedback_varyings = static_cast<uint32_t>(param);
1666 if (num_transform_feedback_varyings == 0) {
1667 TransformFeedbackVaryingsHeader* header =
1668 bucket->GetDataAs<TransformFeedbackVaryingsHeader*>(0, header_size);
1669 header->transform_feedback_buffer_mode = transform_feedback_buffer_mode;
1670 return true;
1673 std::vector<TransformFeedbackVaryingInfo> varyings(
1674 num_transform_feedback_varyings);
1675 base::CheckedNumeric<uint32_t> size = sizeof(TransformFeedbackVaryingInfo);
1676 size *= num_transform_feedback_varyings;
1677 uint32_t entry_size = size.ValueOrDefault(0);
1678 size += header_size;
1679 std::vector<std::string> names(num_transform_feedback_varyings);
1680 GLint max_name_length = 0;
1681 glGetProgramiv(
1682 program, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &max_name_length);
1683 if (max_name_length < 1)
1684 max_name_length = 1;
1685 std::vector<char> buffer(max_name_length);
1686 for (uint32_t ii = 0; ii < num_transform_feedback_varyings; ++ii) {
1687 GLsizei var_size = 0;
1688 GLsizei var_name_length = 0;
1689 GLenum var_type = 0;
1690 glGetTransformFeedbackVarying(
1691 program, ii, max_name_length,
1692 &var_name_length, &var_size, &var_type, &buffer[0]);
1693 varyings[ii].size = static_cast<uint32_t>(var_size);
1694 varyings[ii].type = static_cast<uint32_t>(var_type);
1695 varyings[ii].name_offset = static_cast<uint32_t>(size.ValueOrDefault(0));
1696 DCHECK_GT(max_name_length, var_name_length);
1697 names[ii] = std::string(&buffer[0], var_name_length);
1698 // TODO(zmo): optimize the name mapping lookup.
1699 const std::string* original_name = GetOriginalNameFromHashedName(names[ii]);
1700 if (original_name)
1701 names[ii] = *original_name;
1702 varyings[ii].name_length = names[ii].size() + 1;
1703 size += names[ii].size();
1704 size += 1;
1706 if (!size.IsValid())
1707 return false;
1708 uint32_t total_size = size.ValueOrDefault(0);
1709 DCHECK_LE(header_size + entry_size, total_size);
1710 uint32_t data_size = total_size - header_size - entry_size;
1712 bucket->SetSize(total_size);
1713 TransformFeedbackVaryingsHeader* header =
1714 bucket->GetDataAs<TransformFeedbackVaryingsHeader*>(0, header_size);
1715 TransformFeedbackVaryingInfo* entries =
1716 bucket->GetDataAs<TransformFeedbackVaryingInfo*>(header_size, entry_size);
1717 char* data = bucket->GetDataAs<char*>(header_size + entry_size, data_size);
1718 DCHECK(header);
1719 DCHECK(entries);
1720 DCHECK(data);
1722 // Copy over data for the header and entries.
1723 header->transform_feedback_buffer_mode = transform_feedback_buffer_mode;
1724 header->num_transform_feedback_varyings = num_transform_feedback_varyings;
1725 memcpy(entries, &varyings[0], entry_size);
1727 for (uint32_t ii = 0; ii < num_transform_feedback_varyings; ++ii) {
1728 memcpy(data, names[ii].c_str(), names[ii].length() + 1);
1729 data += names[ii].length() + 1;
1731 DCHECK_EQ(ComputeOffset(header, data), total_size);
1732 return true;
1735 bool Program::GetUniformsES3(CommonDecoder::Bucket* bucket) const {
1736 // The data is packed into the bucket in the following order
1737 // 1) header
1738 // 2) N entries of UniformES3Info
1740 // We query all the data directly through GL calls, assuming they are
1741 // cheap through MANGLE.
1743 DCHECK(bucket);
1744 GLuint program = service_id();
1746 uint32_t header_size = sizeof(UniformsES3Header);
1747 bucket->SetSize(header_size); // In case we fail.
1749 GLsizei count = 0;
1750 GLint param = GL_FALSE;
1751 // We assume program is a valid program service id.
1752 glGetProgramiv(program, GL_LINK_STATUS, &param);
1753 if (param == GL_TRUE) {
1754 param = 0;
1755 glGetProgramiv(program, GL_ACTIVE_UNIFORMS, &count);
1757 if (count == 0) {
1758 return true;
1761 base::CheckedNumeric<uint32_t> size = sizeof(UniformES3Info);
1762 size *= count;
1763 uint32_t entry_size = size.ValueOrDefault(0);
1764 size += header_size;
1765 if (!size.IsValid())
1766 return false;
1767 uint32_t total_size = size.ValueOrDefault(0);
1768 bucket->SetSize(total_size);
1769 UniformsES3Header* header =
1770 bucket->GetDataAs<UniformsES3Header*>(0, header_size);
1771 DCHECK(header);
1772 header->num_uniforms = static_cast<uint32_t>(count);
1774 // Instead of GetDataAs<UniformES3Info*>, we do GetDataAs<int32_t>. This is
1775 // because struct UniformES3Info is defined as five int32_t.
1776 // By doing this, we can fill the structs through loops.
1777 int32_t* entries =
1778 bucket->GetDataAs<int32_t*>(header_size, entry_size);
1779 DCHECK(entries);
1780 const size_t kStride = sizeof(UniformES3Info) / sizeof(int32_t);
1782 const GLenum kPname[] = {
1783 GL_UNIFORM_BLOCK_INDEX,
1784 GL_UNIFORM_OFFSET,
1785 GL_UNIFORM_ARRAY_STRIDE,
1786 GL_UNIFORM_MATRIX_STRIDE,
1787 GL_UNIFORM_IS_ROW_MAJOR,
1789 const GLint kDefaultValue[] = { -1, -1, -1, -1, 0 };
1790 const size_t kNumPnames = arraysize(kPname);
1791 std::vector<GLuint> indices(count);
1792 for (GLsizei ii = 0; ii < count; ++ii) {
1793 indices[ii] = ii;
1795 std::vector<GLint> params(count);
1796 for (size_t pname_index = 0; pname_index < kNumPnames; ++pname_index) {
1797 for (GLsizei ii = 0; ii < count; ++ii) {
1798 params[ii] = kDefaultValue[pname_index];
1800 glGetActiveUniformsiv(
1801 program, count, &indices[0], kPname[pname_index], &params[0]);
1802 for (GLsizei ii = 0; ii < count; ++ii) {
1803 entries[kStride * ii + pname_index] = params[ii];
1806 return true;
1809 void Program::TransformFeedbackVaryings(GLsizei count,
1810 const char* const* varyings,
1811 GLenum buffer_mode) {
1812 transform_feedback_varyings_.clear();
1813 for (GLsizei i = 0; i < count; ++i) {
1814 transform_feedback_varyings_.push_back(std::string(varyings[i]));
1816 transform_feedback_buffer_mode_ = buffer_mode;
1819 Program::~Program() {
1820 if (manager_) {
1821 if (manager_->have_context_) {
1822 glDeleteProgram(service_id());
1824 manager_->StopTracking(this);
1825 manager_ = NULL;
1830 ProgramManager::ProgramManager(ProgramCache* program_cache,
1831 uint32 max_varying_vectors)
1832 : program_count_(0),
1833 have_context_(true),
1834 program_cache_(program_cache),
1835 max_varying_vectors_(max_varying_vectors) { }
1837 ProgramManager::~ProgramManager() {
1838 DCHECK(programs_.empty());
1841 void ProgramManager::Destroy(bool have_context) {
1842 have_context_ = have_context;
1843 programs_.clear();
1846 void ProgramManager::StartTracking(Program* /* program */) {
1847 ++program_count_;
1850 void ProgramManager::StopTracking(Program* /* program */) {
1851 --program_count_;
1854 Program* ProgramManager::CreateProgram(
1855 GLuint client_id, GLuint service_id) {
1856 std::pair<ProgramMap::iterator, bool> result =
1857 programs_.insert(
1858 std::make_pair(client_id,
1859 scoped_refptr<Program>(
1860 new Program(this, service_id))));
1861 DCHECK(result.second);
1862 return result.first->second.get();
1865 Program* ProgramManager::GetProgram(GLuint client_id) {
1866 ProgramMap::iterator it = programs_.find(client_id);
1867 return it != programs_.end() ? it->second.get() : NULL;
1870 bool ProgramManager::GetClientId(GLuint service_id, GLuint* client_id) const {
1871 // This doesn't need to be fast. It's only used during slow queries.
1872 for (const auto& key_value : programs_) {
1873 if (key_value.second->service_id() == service_id) {
1874 *client_id = key_value.first;
1875 return true;
1878 return false;
1881 ProgramCache* ProgramManager::program_cache() const {
1882 return program_cache_;
1885 bool ProgramManager::IsOwned(Program* program) const {
1886 for (const auto& key_value : programs_) {
1887 if (key_value.second.get() == program) {
1888 return true;
1891 return false;
1894 void ProgramManager::RemoveProgramInfoIfUnused(
1895 ShaderManager* shader_manager, Program* program) {
1896 DCHECK(shader_manager);
1897 DCHECK(program);
1898 DCHECK(IsOwned(program));
1899 if (program->IsDeleted() && !program->InUse()) {
1900 program->DetachShaders(shader_manager);
1901 for (ProgramMap::iterator it = programs_.begin();
1902 it != programs_.end(); ++it) {
1903 if (it->second.get() == program) {
1904 programs_.erase(it);
1905 return;
1908 NOTREACHED();
1912 void ProgramManager::MarkAsDeleted(
1913 ShaderManager* shader_manager,
1914 Program* program) {
1915 DCHECK(shader_manager);
1916 DCHECK(program);
1917 DCHECK(IsOwned(program));
1918 program->MarkAsDeleted();
1919 RemoveProgramInfoIfUnused(shader_manager, program);
1922 void ProgramManager::UseProgram(Program* program) {
1923 DCHECK(program);
1924 DCHECK(IsOwned(program));
1925 program->IncUseCount();
1928 void ProgramManager::UnuseProgram(
1929 ShaderManager* shader_manager,
1930 Program* program) {
1931 DCHECK(shader_manager);
1932 DCHECK(program);
1933 DCHECK(IsOwned(program));
1934 program->DecUseCount();
1935 RemoveProgramInfoIfUnused(shader_manager, program);
1938 void ProgramManager::ClearUniforms(Program* program) {
1939 DCHECK(program);
1940 program->ClearUniforms(&zero_);
1943 int32 ProgramManager::MakeFakeLocation(int32 index, int32 element) {
1944 return index + element * 0x10000;
1947 } // namespace gles2
1948 } // namespace gpu