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

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

Issue 1419393005: command_buffer: Make inactive bound uniforms reserve the location (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix a cc bug exposed by the implementation Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "gpu/command_buffer/service/program_manager.h" 5 #include "gpu/command_buffer/service/program_manager.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <set> 8 #include <set>
9 #include <utility> 9 #include <utility>
10 #include <vector> 10 #include <vector>
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
112 uint32 ComputeOffset(const void* start, const void* position) { 112 uint32 ComputeOffset(const void* start, const void* position) {
113 return static_cast<const uint8*>(position) - 113 return static_cast<const uint8*>(position) -
114 static_cast<const uint8*>(start); 114 static_cast<const uint8*>(start);
115 } 115 }
116 116
117 } // anonymous namespace. 117 } // anonymous namespace.
118 118
119 Program::UniformInfo::UniformInfo() 119 Program::UniformInfo::UniformInfo()
120 : size(0), 120 : size(0),
121 type(GL_NONE), 121 type(GL_NONE),
122 accepts_api_type(0),
122 fake_location_base(0), 123 fake_location_base(0),
123 is_array(false) { 124 is_array(false) {}
124 }
125 125
126 Program::UniformInfo::UniformInfo(GLsizei _size, 126 Program::UniformInfo::UniformInfo(const std::string& client_name,
127 int client_location_base,
127 GLenum _type, 128 GLenum _type,
128 int _fake_location_base, 129 bool _is_array,
129 const std::string& _name) 130 const std::vector<GLint>& service_locations)
130 : size(_size), 131 : size(service_locations.size()),
131 type(_type), 132 type(_type),
132 accepts_api_type(0), 133 accepts_api_type(0),
133 fake_location_base(_fake_location_base), 134 fake_location_base(client_location_base),
134 is_array(false), 135 is_array(_is_array),
135 name(_name) { 136 name(client_name),
137 element_locations(service_locations) {
136 switch (type) { 138 switch (type) {
137 case GL_INT: 139 case GL_INT:
138 accepts_api_type = kUniform1i; 140 accepts_api_type = kUniform1i;
139 break; 141 break;
140 case GL_INT_VEC2: 142 case GL_INT_VEC2:
141 accepts_api_type = kUniform2i; 143 accepts_api_type = kUniform2i;
142 break; 144 break;
143 case GL_INT_VEC3: 145 case GL_INT_VEC3:
144 accepts_api_type = kUniform3i; 146 accepts_api_type = kUniform3i;
145 break; 147 break;
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
231 case GL_UNSIGNED_INT_SAMPLER_3D: 233 case GL_UNSIGNED_INT_SAMPLER_3D:
232 case GL_UNSIGNED_INT_SAMPLER_CUBE: 234 case GL_UNSIGNED_INT_SAMPLER_CUBE:
233 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: 235 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
234 accepts_api_type = kUniform1i; 236 accepts_api_type = kUniform1i;
235 break; 237 break;
236 238
237 default: 239 default:
238 NOTREACHED() << "Unhandled UniformInfo type " << type; 240 NOTREACHED() << "Unhandled UniformInfo type " << type;
239 break; 241 break;
240 } 242 }
243 DCHECK_LT(0, size);
244 DCHECK(is_array || size == 1);
245
246 size_t num_texture_units = IsSampler() ? static_cast<size_t>(size) : 0u;
247 texture_units.clear();
248 texture_units.resize(num_texture_units, 0);
241 } 249 }
242
243 Program::UniformInfo::~UniformInfo() {} 250 Program::UniformInfo::~UniformInfo() {}
244 251
245 bool ProgramManager::IsInvalidPrefix(const char* name, size_t length) { 252 bool ProgramManager::IsInvalidPrefix(const char* name, size_t length) {
246 static const char kInvalidPrefix[] = { 'g', 'l', '_' }; 253 static const char kInvalidPrefix[] = { 'g', 'l', '_' };
247 return (length >= sizeof(kInvalidPrefix) && 254 return (length >= sizeof(kInvalidPrefix) &&
248 memcmp(name, kInvalidPrefix, sizeof(kInvalidPrefix)) == 0); 255 memcmp(name, kInvalidPrefix, sizeof(kInvalidPrefix)) == 0);
249 } 256 }
250 257
251 Program::Program(ProgramManager* manager, GLuint service_id) 258 Program::Program(ProgramManager* manager, GLuint service_id)
252 : manager_(manager), 259 : manager_(manager),
253 use_count_(0), 260 use_count_(0),
254 max_attrib_name_length_(0), 261 max_attrib_name_length_(0),
255 max_uniform_name_length_(0), 262 max_uniform_name_length_(0),
256 service_id_(service_id), 263 service_id_(service_id),
257 deleted_(false), 264 deleted_(false),
258 valid_(false), 265 valid_(false),
259 link_status_(false), 266 link_status_(false),
260 uniforms_cleared_(false), 267 uniforms_cleared_(false),
261 num_uniforms_(0),
262 transform_feedback_buffer_mode_(GL_NONE) { 268 transform_feedback_buffer_mode_(GL_NONE) {
263 manager_->StartTracking(this); 269 manager_->StartTracking(this);
264 } 270 }
265 271
266 void Program::Reset() { 272 void Program::Reset() {
267 valid_ = false; 273 valid_ = false;
268 link_status_ = false; 274 link_status_ = false;
269 num_uniforms_ = 0;
270 max_uniform_name_length_ = 0; 275 max_uniform_name_length_ = 0;
271 max_attrib_name_length_ = 0; 276 max_attrib_name_length_ = 0;
272 attrib_infos_.clear(); 277 attrib_infos_.clear();
273 uniform_infos_.clear(); 278 uniform_infos_.clear();
279 uniform_locations_.clear();
274 fragment_input_infos_.clear(); 280 fragment_input_infos_.clear();
275 sampler_indices_.clear(); 281 sampler_indices_.clear();
276 attrib_location_to_index_map_.clear(); 282 attrib_location_to_index_map_.clear();
277 } 283 }
278 284
279 std::string Program::ProcessLogInfo( 285 std::string Program::ProcessLogInfo(
280 const std::string& log) { 286 const std::string& log) {
281 std::string output; 287 std::string output;
282 re2::StringPiece input(log); 288 re2::StringPiece input(log);
283 std::string prior_log; 289 std::string prior_log;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 set_log_info(ProcessLogInfo(log).c_str()); 321 set_log_info(ProcessLogInfo(log).c_str());
316 } 322 }
317 323
318 void Program::ClearUniforms( 324 void Program::ClearUniforms(
319 std::vector<uint8>* zero_buffer) { 325 std::vector<uint8>* zero_buffer) {
320 DCHECK(zero_buffer); 326 DCHECK(zero_buffer);
321 if (uniforms_cleared_) { 327 if (uniforms_cleared_) {
322 return; 328 return;
323 } 329 }
324 uniforms_cleared_ = true; 330 uniforms_cleared_ = true;
325 for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) { 331 for (const UniformInfo& uniform_info : uniform_infos_) {
326 const UniformInfo& uniform_info = uniform_infos_[ii];
327 if (!uniform_info.IsValid()) {
328 continue;
329 }
330 GLint location = uniform_info.element_locations[0]; 332 GLint location = uniform_info.element_locations[0];
331 GLsizei size = uniform_info.size; 333 GLsizei size = uniform_info.size;
332 uint32 unit_size = 334 uint32 unit_size =
333 GLES2Util::GetElementCountForUniformType(uniform_info.type) * 335 GLES2Util::GetElementCountForUniformType(uniform_info.type) *
334 GLES2Util::GetElementSizeForUniformType(uniform_info.type); 336 GLES2Util::GetElementSizeForUniformType(uniform_info.type);
335 DCHECK_LT(0u, unit_size); 337 DCHECK_LT(0u, unit_size);
336 uint32 size_needed = size * unit_size; 338 uint32 size_needed = size * unit_size;
337 if (size_needed > zero_buffer->size()) { 339 if (size_needed > zero_buffer->size()) {
338 zero_buffer->resize(size_needed, 0u); 340 zero_buffer->resize(size_needed, 0u);
339 } 341 }
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
437 location, size, false, reinterpret_cast<const GLfloat*>(zero)); 439 location, size, false, reinterpret_cast<const GLfloat*>(zero));
438 break; 440 break;
439 441
440 default: 442 default:
441 NOTREACHED(); 443 NOTREACHED();
442 break; 444 break;
443 } 445 }
444 } 446 }
445 } 447 }
446 448
447 namespace {
448
449 struct UniformData {
450 UniformData() : size(-1), type(GL_NONE), location(0), added(false) {
451 }
452 std::string queried_name;
453 std::string corrected_name;
454 std::string original_name;
455 GLsizei size;
456 GLenum type;
457 GLint location;
458 bool added;
459 };
460
461 } // anonymous namespace
462
463 void Program::Update() { 449 void Program::Update() {
464 Reset(); 450 Reset();
465 UpdateLogInfo(); 451 UpdateLogInfo();
466 link_status_ = true; 452 link_status_ = true;
467 uniforms_cleared_ = false; 453 uniforms_cleared_ = false;
468 GLint num_attribs = 0; 454 GLint num_attribs = 0;
469 GLint max_len = 0; 455 GLint max_len = 0;
470 GLint max_location = -1; 456 GLint max_location = -1;
471 glGetProgramiv(service_id_, GL_ACTIVE_ATTRIBUTES, &num_attribs); 457 glGetProgramiv(service_id_, GL_ACTIVE_ATTRIBUTES, &num_attribs);
472 glGetProgramiv(service_id_, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_len); 458 glGetProgramiv(service_id_, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_len);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
508 DVLOG(1) << "----: attribs for service_id: " << service_id(); 494 DVLOG(1) << "----: attribs for service_id: " << service_id();
509 for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) { 495 for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) {
510 const VertexAttrib& info = attrib_infos_[ii]; 496 const VertexAttrib& info = attrib_infos_[ii];
511 DVLOG(1) << ii << ": loc = " << info.location 497 DVLOG(1) << ii << ": loc = " << info.location
512 << ", size = " << info.size 498 << ", size = " << info.size
513 << ", type = " << GLES2Util::GetStringEnum(info.type) 499 << ", type = " << GLES2Util::GetStringEnum(info.type)
514 << ", name = " << info.name; 500 << ", name = " << info.name;
515 } 501 }
516 } 502 }
517 #endif 503 #endif
518 504 UpdateUniforms();
519 max_len = 0;
520 GLint num_uniforms = 0;
521 glGetProgramiv(service_id_, GL_ACTIVE_UNIFORMS, &num_uniforms);
522 glGetProgramiv(service_id_, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_len);
523 DCHECK(num_uniforms <= 0 || max_len > 0);
524 name_buffer.reset(new char[max_len]);
525
526 // Reads all the names.
527 std::vector<UniformData> uniform_data;
528 for (GLint ii = 0; ii < num_uniforms; ++ii) {
529 GLsizei length = 0;
530 UniformData data;
531 glGetActiveUniform(
532 service_id_, ii, max_len, &length,
533 &data.size, &data.type, name_buffer.get());
534 DCHECK(length < max_len);
535 DCHECK(length == 0 || name_buffer[length] == '\0');
536 data.queried_name = std::string(name_buffer.get());
537 GetCorrectedUniformData(data.queried_name, &data.corrected_name,
538 &data.original_name, &data.size, &data.type);
539 uniform_data.push_back(data);
540 }
541
542 // NOTE: We don't care if 2 uniforms are bound to the same location.
543 // One of them will take preference. The spec allows this, same as
544 // BindAttribLocation.
545 //
546 // The reason we don't check is if we were to fail we'd have to
547 // restore the previous program but since we've already linked successfully
548 // at this point the previous program is gone.
549
550 // Assigns the uniforms with bindings.
551 size_t next_available_index = 0;
552 for (size_t ii = 0; ii < uniform_data.size(); ++ii) {
553 UniformData& data = uniform_data[ii];
554 // Force builtin uniforms (gl_DepthRange) to have invalid location.
555 if (ProgramManager::IsInvalidPrefix(data.queried_name.c_str(),
556 data.queried_name.size())) {
557 data.location = -1;
558 } else {
559 data.location =
560 glGetUniformLocation(service_id_, data.queried_name.c_str());
561 }
562 // remove "[0]"
563 std::string short_name;
564 int element_index = 0;
565 bool good = GetUniformNameSansElement(data.original_name, &element_index,
566 &short_name);
567 DCHECK(good);
568 LocationMap::const_iterator it = bind_uniform_location_map_.find(
569 short_name);
570 if (it != bind_uniform_location_map_.end()) {
571 AddUniformInfo(
572 data.size, data.type, data.location, it->second, data.corrected_name,
573 data.original_name, &next_available_index);
574 data.added = true;
575 }
576 }
577
578 // Assigns the uniforms that were not bound.
579 for (size_t ii = 0; ii < uniform_data.size(); ++ii) {
580 const UniformData& data = uniform_data[ii];
581 if (!data.added) {
582 AddUniformInfo(
583 data.size, data.type, data.location, -1, data.corrected_name,
584 data.original_name, &next_available_index);
585 }
586 }
587 505
588 #if !defined(NDEBUG) 506 #if !defined(NDEBUG)
589 if (base::CommandLine::ForCurrentProcess()->HasSwitch( 507 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
590 switches::kEnableGPUServiceLoggingGPU)) { 508 switches::kEnableGPUServiceLoggingGPU)) {
591 DVLOG(1) << "----: uniforms for service_id: " << service_id(); 509 DVLOG(1) << "----: uniforms for service_id: " << service_id();
592 for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) { 510 size_t ii = 0;
593 const UniformInfo& info = uniform_infos_[ii]; 511 for (const UniformInfo& info : uniform_infos_) {
594 if (info.IsValid()) { 512 DVLOG(1) << ii++ << ": loc = " << info.element_locations[0]
595 DVLOG(1) << ii << ": loc = " << info.element_locations[0] 513 << ", size = " << info.size
596 << ", size = " << info.size 514 << ", type = " << GLES2Util::GetStringEnum(info.type)
597 << ", type = " << GLES2Util::GetStringEnum(info.type) 515 << ", name = " << info.name;
598 << ", name = " << info.name;
599 }
600 } 516 }
601 } 517 }
602 #endif 518 #endif
603 519
604 UpdateFragmentInputs(); 520 UpdateFragmentInputs();
605 521
606 valid_ = true; 522 valid_ = true;
607 } 523 }
608 524
525 void Program::UpdateUniforms() {
526 // Reserve each client-bound uniform location. This way unbound uniforms will
527 // not be allocated to locations that user expects bound uniforms to be, even
528 // if the expected uniforms are optimized away by the driver.
529 for (const auto& binding : bind_uniform_location_map_) {
530 if (binding.second < 0)
531 continue;
532 size_t client_location = static_cast<size_t>(binding.second);
533 if (uniform_locations_.size() <= client_location)
534 uniform_locations_.resize(client_location + 1);
535 uniform_locations_[client_location].SetInactive();
536 }
537
538 GLint num_uniforms = 0;
539 glGetProgramiv(service_id_, GL_ACTIVE_UNIFORMS, &num_uniforms);
540 if (num_uniforms <= 0)
541 return;
542
543 uniform_infos_.resize(num_uniforms);
544
545 GLint name_buffer_length = 0;
546 glGetProgramiv(service_id_, GL_ACTIVE_UNIFORM_MAX_LENGTH,
547 &name_buffer_length);
548 DCHECK(name_buffer_length > 0);
549 scoped_ptr<char[]> name_buffer(new char[name_buffer_length]);
550
551 size_t unused_client_location_cursor = 0;
552
553 for (GLint uniform_index = 0; uniform_index < num_uniforms; ++uniform_index) {
554 GLsizei name_length = 0;
555 GLsizei size = 0;
556 GLenum type = GL_NONE;
557 glGetActiveUniform(service_id_, uniform_index, name_buffer_length,
558 &name_length, &size, &type, name_buffer.get());
559 DCHECK(name_length < name_buffer_length);
560 DCHECK(name_length == 0 || name_buffer[name_length] == '\0');
561 std::string service_name(name_buffer.get(), name_length);
562
563 GLint service_location = -1;
564 // Force builtin uniforms (gl_DepthRange) to have invalid location.
565 if (!ProgramManager::IsInvalidPrefix(service_name.c_str(),
566 service_name.size())) {
567 service_location =
568 glGetUniformLocation(service_id_, service_name.c_str());
569 }
570
571 // Determine the client name of the uniform and whether it is an array
572 // or not.
573 bool is_array = false;
574 std::string client_name;
575 for (size_t i = 0; i < kMaxAttachedShaders && client_name.empty(); ++i) {
576 const auto& shader = attached_shaders_[i];
577 if (!shader)
578 continue;
579 const sh::ShaderVariable* info = nullptr;
580 const sh::Uniform* uniform = shader->GetUniformInfo(service_name);
581 if (uniform &&
582 uniform->findInfoByMappedName(service_name, &info, &client_name)) {
583 DCHECK(!client_name.empty());
584 is_array = info->arraySize > 0;
585 type = info->type;
586 size = std::max(1u, info->arraySize);
587 }
588 }
589 if (client_name.empty()) {
590 // This happens only in cases where we do not have ANGLE or run unit tests
591 // (or ANGLE has a severe bug).
592 client_name = service_name;
593 GLSLArrayName parsed_service_name(service_name);
594 is_array = size > 1 || parsed_service_name.IsArrayName();
595 }
596
597 std::string service_base_name = service_name;
598 std::string client_base_name = client_name;
599 if (is_array) {
600 // Some drivers incorrectly return an uniform name of size-1 array without
601 // "[0]". In this case, we correct the service name by appending "[0]" to
602 // it.
603 GLSLArrayName parsed_service_name(service_name);
604 if (parsed_service_name.IsArrayName()) {
605 service_base_name = parsed_service_name.base_name();
606 GLSLArrayName parsed_client_name(client_name);
607 client_base_name = parsed_client_name.base_name();
608 } else {
609 service_name += "[0]";
610 client_name += "[0]";
611 }
612 }
613
614 // Assign a location for the uniform: use either client-bound
615 // location or automatically assigned to an unused location.
616 size_t client_location_base = 0;
617 LocationMap::const_iterator it =
618 bind_uniform_location_map_.find(client_base_name);
619 if (it != bind_uniform_location_map_.end()) {
620 client_location_base = it->second;
621 } else {
622 while (unused_client_location_cursor < uniform_locations_.size() &&
623 !uniform_locations_[unused_client_location_cursor].IsUnused())
624 unused_client_location_cursor++;
625 if (unused_client_location_cursor == uniform_locations_.size())
626 uniform_locations_.resize(unused_client_location_cursor + 1);
627 client_location_base = unused_client_location_cursor;
628 unused_client_location_cursor++;
629 }
630
631 // Populate the uniform list entry.
632 std::vector<GLint> service_locations;
633 service_locations.resize(size);
634 service_locations[0] = service_location;
635
636 if (size > 1) {
637 for (GLsizei ii = 1; ii < size; ++ii) {
638 std::string element_name(service_base_name + "[" +
639 base::IntToString(ii) + "]");
640 service_locations[ii] =
641 glGetUniformLocation(service_id_, element_name.c_str());
642 }
643 }
644
645 UniformInfo& info = uniform_infos_[uniform_index];
646 info = UniformInfo(client_name, client_location_base, type, is_array,
647 service_locations);
648 if (info.IsSampler()) {
649 sampler_indices_.push_back(uniform_index);
650 }
651
652 // Populate the uniform location list entry.
653 // Before linking, we already validated that no two statically used uniforms
654 // are bound to the same location.
655 DCHECK(!uniform_locations_[client_location_base].IsActive());
656 uniform_locations_[client_location_base].SetActive(&info);
657
658 max_uniform_name_length_ = std::max(max_uniform_name_length_,
659 static_cast<GLsizei>(info.name.size()));
660 }
661 }
662
609 void Program::UpdateFragmentInputs() { 663 void Program::UpdateFragmentInputs() {
610 if (!feature_info().feature_flags().chromium_path_rendering) 664 if (!feature_info().feature_flags().chromium_path_rendering)
611 return; 665 return;
612 GLint num_fragment_inputs = 0; 666 GLint num_fragment_inputs = 0;
613 glGetProgramInterfaceiv(service_id_, GL_FRAGMENT_INPUT_NV, 667 glGetProgramInterfaceiv(service_id_, GL_FRAGMENT_INPUT_NV,
614 GL_ACTIVE_RESOURCES, &num_fragment_inputs); 668 GL_ACTIVE_RESOURCES, &num_fragment_inputs);
615 if (num_fragment_inputs <= 0) 669 if (num_fragment_inputs <= 0)
616 return; 670 return;
617 GLint max_len = 0; 671 GLint max_len = 0;
618 glGetProgramInterfaceiv(service_id_, GL_FRAGMENT_INPUT_NV, GL_MAX_NAME_LENGTH, 672 glGetProgramInterfaceiv(service_id_, GL_FRAGMENT_INPUT_NV, GL_MAX_NAME_LENGTH,
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after
910 return; 964 return;
911 } 965 }
912 glValidateProgram(service_id()); 966 glValidateProgram(service_id());
913 UpdateLogInfo(); 967 UpdateLogInfo();
914 } 968 }
915 969
916 GLint Program::GetUniformFakeLocation( 970 GLint Program::GetUniformFakeLocation(
917 const std::string& name) const { 971 const std::string& name) const {
918 GLSLArrayName parsed_name(name); 972 GLSLArrayName parsed_name(name);
919 973
920 for (GLuint ii = 0; ii < uniform_infos_.size(); ++ii) { 974 for (const UniformInfo& info : uniform_infos_) {
921 const UniformInfo& info = uniform_infos_[ii];
922 if (!info.IsValid()) {
923 continue;
924 }
925 if (info.name == name || 975 if (info.name == name ||
926 (info.is_array && 976 (info.is_array &&
927 info.name.compare(0, info.name.size() - 3, name) == 0)) { 977 info.name.compare(0, info.name.size() - 3, name) == 0)) {
928 return info.fake_location_base; 978 return info.fake_location_base;
929 } else if (parsed_name.IsArrayName() && info.is_array) { 979 } else if (parsed_name.IsArrayName() && info.is_array) {
930 // Look for an array specification. 980 // Look for an array specification.
931 size_t open_pos = info.name.find_last_of('['); 981 size_t open_pos = info.name.find_last_of('[');
932 if (info.name.compare(0, open_pos, parsed_name.base_name()) == 0) { 982 if (info.name.compare(0, open_pos, parsed_name.base_name()) == 0) {
933 int index = parsed_name.element_index(); 983 int index = parsed_name.element_index();
934 DCHECK(index >= 0);
935 if (index < info.size) { 984 if (index < info.size) {
936 DCHECK_GT(static_cast<int>(info.element_locations.size()), index); 985 DCHECK_GT(static_cast<int>(info.element_locations.size()), index);
937 if (info.element_locations[index] == -1) 986 if (info.element_locations[index] == -1)
938 return -1; 987 return -1;
939 return ProgramManager::MakeFakeLocation( 988 return ProgramManager::MakeFakeLocation(
940 info.fake_location_base, index); 989 info.fake_location_base, index);
941 } 990 }
942 } 991 }
943 } 992 }
944 } 993 }
945 return -1; 994 return -1;
946 } 995 }
947 996
948 GLint Program::GetAttribLocation( 997 GLint Program::GetAttribLocation(
949 const std::string& original_name) const { 998 const std::string& original_name) const {
950 for (GLuint ii = 0; ii < attrib_infos_.size(); ++ii) { 999 for (GLuint ii = 0; ii < attrib_infos_.size(); ++ii) {
951 const VertexAttrib& info = attrib_infos_[ii]; 1000 const VertexAttrib& info = attrib_infos_[ii];
952 if (info.name == original_name) { 1001 if (info.name == original_name) {
953 return info.location; 1002 return info.location;
954 } 1003 }
955 } 1004 }
956 return -1; 1005 return -1;
957 } 1006 }
958 1007
959 const Program::UniformInfo* 1008 const Program::UniformInfo*
960 Program::GetUniformInfoByFakeLocation( 1009 Program::GetUniformInfoByFakeLocation(
961 GLint fake_location, GLint* real_location, GLint* array_index) const { 1010 GLint fake_location, GLint* real_location, GLint* array_index) const {
962 DCHECK(real_location); 1011 DCHECK(real_location);
963 DCHECK(array_index); 1012 DCHECK(array_index);
964 if (fake_location < 0) { 1013 if (fake_location < 0)
965 return NULL; 1014 return nullptr;
966 } 1015 size_t location_index =
1016 GetUniformLocationIndexFromFakeLocation(fake_location);
1017 if (location_index >= uniform_locations_.size())
1018 return nullptr;
967 1019
968 GLint uniform_index = GetUniformInfoIndexFromFakeLocation(fake_location); 1020 if (!uniform_locations_[location_index].IsActive())
969 if (uniform_index >= 0 && 1021 return nullptr;
970 static_cast<size_t>(uniform_index) < uniform_infos_.size()) { 1022
971 const UniformInfo& uniform_info = uniform_infos_[uniform_index]; 1023 const UniformInfo* info = uniform_locations_[location_index].uniform();
972 if (!uniform_info.IsValid()) { 1024 size_t element_index = GetArrayElementIndexFromFakeLocation(fake_location);
973 return NULL; 1025 if (static_cast<GLsizei>(element_index) >= info->size)
974 } 1026 return nullptr;
975 GLint element_index = GetArrayElementIndexFromFakeLocation(fake_location); 1027 *real_location = info->element_locations[element_index];
976 if (element_index < uniform_info.size) { 1028 *array_index = element_index;
977 *real_location = uniform_info.element_locations[element_index]; 1029 return info;
978 *array_index = element_index; 1030 }
979 return &uniform_info; 1031
980 } 1032 bool Program::IsInactiveUniformLocationByFakeLocation(
981 } 1033 GLint fake_location) const {
982 return NULL; 1034 if (fake_location < 0)
1035 return true;
1036 size_t location_index =
1037 GetUniformLocationIndexFromFakeLocation(fake_location);
1038 if (location_index >= uniform_locations_.size())
1039 return false;
1040 return uniform_locations_[location_index].IsInactive();
983 } 1041 }
984 1042
985 const std::string* Program::GetAttribMappedName( 1043 const std::string* Program::GetAttribMappedName(
986 const std::string& original_name) const { 1044 const std::string& original_name) const {
987 for (auto shader : attached_shaders_) { 1045 for (auto shader : attached_shaders_) {
988 if (shader) { 1046 if (shader) {
989 const std::string* mapped_name = 1047 const std::string* mapped_name =
990 shader->GetAttribMappedName(original_name); 1048 shader->GetAttribMappedName(original_name);
991 if (mapped_name) 1049 if (mapped_name)
992 return mapped_name; 1050 return mapped_name;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1052 // string would exactly match the name of the variable if the suffix "[0]" 1110 // string would exactly match the name of the variable if the suffix "[0]"
1053 // were appended to the string". 1111 // were appended to the string".
1054 1112
1055 // At this point we can not know if the string identifies a simple variable, 1113 // At this point we can not know if the string identifies a simple variable,
1056 // a base name of an array, or nothing. Store both, so if user overwrites 1114 // a base name of an array, or nothing. Store both, so if user overwrites
1057 // either, both still work correctly. 1115 // either, both still work correctly.
1058 bind_fragment_input_location_map_[name] = location; 1116 bind_fragment_input_location_map_[name] = location;
1059 bind_fragment_input_location_map_[name + "[0]"] = location; 1117 bind_fragment_input_location_map_[name + "[0]"] = location;
1060 } 1118 }
1061 1119
1062 // Note: This is only valid to call right after a program has been linked
1063 // successfully.
1064 void Program::GetCorrectedUniformData(
1065 const std::string& name,
1066 std::string* corrected_name, std::string* original_name,
1067 GLsizei* size, GLenum* type) const {
1068 DCHECK(corrected_name && original_name && size && type);
1069 for (auto shader : attached_shaders_) {
1070 if (!shader)
1071 continue;
1072 const sh::ShaderVariable* info = NULL;
1073 const sh::Uniform* uniform = shader->GetUniformInfo(name);
1074 bool found = false;
1075 if (uniform)
1076 found = uniform->findInfoByMappedName(name, &info, original_name);
1077 if (found) {
1078 const std::string kArraySpec("[0]");
1079 if (info->arraySize > 0 &&
1080 !base::EndsWith(name, kArraySpec, base::CompareCase::SENSITIVE)) {
1081 *corrected_name = name + kArraySpec;
1082 *original_name += kArraySpec;
1083 } else {
1084 *corrected_name = name;
1085 }
1086 *type = info->type;
1087 *size = std::max(1u, info->arraySize);
1088 return;
1089 }
1090 }
1091 // TODO(zmo): this path should never be reached unless there is a serious
1092 // bug in the driver or in ANGLE translator.
1093 *corrected_name = name;
1094 *original_name = name;
1095 }
1096
1097 void Program::GetVertexAttribData( 1120 void Program::GetVertexAttribData(
1098 const std::string& name, std::string* original_name, GLenum* type) const { 1121 const std::string& name, std::string* original_name, GLenum* type) const {
1099 DCHECK(original_name); 1122 DCHECK(original_name);
1100 DCHECK(type); 1123 DCHECK(type);
1101 Shader* shader = attached_shaders_[ShaderTypeToIndex(GL_VERTEX_SHADER)].get(); 1124 Shader* shader = attached_shaders_[ShaderTypeToIndex(GL_VERTEX_SHADER)].get();
1102 if (shader) { 1125 if (shader) {
1103 // Vertex attributes can not be arrays or structs (GLSL ES 3.00.4, section 1126 // Vertex attributes can not be arrays or structs (GLSL ES 3.00.4, section
1104 // 4.3.4, "Input Variables"), so the top level sh::Attribute returns the 1127 // 4.3.4, "Input Variables"), so the top level sh::Attribute returns the
1105 // information we need. 1128 // information we need.
1106 const sh::Attribute* info = shader->GetAttribInfo(name); 1129 const sh::Attribute* info = shader->GetAttribInfo(name);
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
1170 1193
1171 if (visited_list.find(block.name) != visited_list.end()) 1194 if (visited_list.find(block.name) != visited_list.end())
1172 continue; 1195 continue;
1173 1196
1174 GetUniformBlockFromInterfaceBlock(shader.get(), block); 1197 GetUniformBlockFromInterfaceBlock(shader.get(), block);
1175 visited_list.insert(block.name); 1198 visited_list.insert(block.name);
1176 } 1199 }
1177 } 1200 }
1178 } 1201 }
1179 1202
1180 void Program::AddUniformInfo(
1181 GLsizei size, GLenum type, GLint location, GLint fake_base_location,
1182 const std::string& name, const std::string& original_name,
1183 size_t* next_available_index) {
1184 DCHECK(next_available_index);
1185 const char* kArraySpec = "[0]";
1186 size_t uniform_index =
1187 fake_base_location >= 0 ? fake_base_location : *next_available_index;
1188 if (uniform_infos_.size() < uniform_index + 1) {
1189 uniform_infos_.resize(uniform_index + 1);
1190 }
1191
1192 // Before linking, we already validated that no two statically used uniforms
1193 // are bound to the same location.
1194 DCHECK(!uniform_infos_[uniform_index].IsValid());
1195
1196 uniform_infos_[uniform_index] = UniformInfo(
1197 size, type, uniform_index, original_name);
1198 ++num_uniforms_;
1199
1200 UniformInfo& info = uniform_infos_[uniform_index];
1201 info.element_locations.resize(size);
1202 info.element_locations[0] = location;
1203 DCHECK_LE(0, size);
1204 size_t num_texture_units = info.IsSampler() ? static_cast<size_t>(size) : 0u;
1205 info.texture_units.clear();
1206 info.texture_units.resize(num_texture_units, 0);
1207
1208 if (size > 1) {
1209 // Go through the array element locations looking for a match.
1210 // We can skip the first element because it's the same as the
1211 // the location without the array operators.
1212 size_t array_pos = name.rfind(kArraySpec);
1213 std::string base_name = name;
1214 if (name.size() > 3) {
1215 if (array_pos != name.size() - 3) {
1216 info.name = name + kArraySpec;
1217 } else {
1218 base_name = name.substr(0, name.size() - 3);
1219 }
1220 }
1221 for (GLsizei ii = 1; ii < info.size; ++ii) {
1222 std::string element_name(base_name + "[" + base::IntToString(ii) + "]");
1223 info.element_locations[ii] =
1224 glGetUniformLocation(service_id_, element_name.c_str());
1225 }
1226 }
1227
1228 info.is_array =
1229 (size > 1 ||
1230 (info.name.size() > 3 &&
1231 info.name.rfind(kArraySpec) == info.name.size() - 3));
1232
1233 if (info.IsSampler()) {
1234 sampler_indices_.push_back(info.fake_location_base);
1235 }
1236 max_uniform_name_length_ =
1237 std::max(max_uniform_name_length_,
1238 static_cast<GLsizei>(info.name.size()));
1239
1240 while (*next_available_index < uniform_infos_.size() &&
1241 uniform_infos_[*next_available_index].IsValid()) {
1242 *next_available_index = *next_available_index + 1;
1243 }
1244 }
1245
1246 const Program::UniformInfo* 1203 const Program::UniformInfo*
1247 Program::GetUniformInfo( 1204 Program::GetUniformInfo(
1248 GLint index) const { 1205 GLint index) const {
1249 if (static_cast<size_t>(index) >= uniform_infos_.size()) { 1206 if (static_cast<size_t>(index) >= uniform_infos_.size()) {
1250 return NULL; 1207 return NULL;
1251 } 1208 }
1252 1209 return &uniform_infos_[index];
1253 const UniformInfo& info = uniform_infos_[index];
1254 return info.IsValid() ? &info : NULL;
1255 } 1210 }
1256 1211
1257 bool Program::SetSamplers( 1212 bool Program::SetSamplers(
1258 GLint num_texture_units, GLint fake_location, 1213 GLint num_texture_units, GLint fake_location,
1259 GLsizei count, const GLint* value) { 1214 GLsizei count, const GLint* value) {
1260 if (fake_location < 0) { 1215 if (fake_location < 0) {
1261 return true; 1216 return true;
1262 } 1217 }
1263 GLint uniform_index = GetUniformInfoIndexFromFakeLocation(fake_location); 1218 size_t location_index =
1264 if (uniform_index >= 0 && 1219 GetUniformLocationIndexFromFakeLocation(fake_location);
1265 static_cast<size_t>(uniform_index) < uniform_infos_.size()) { 1220 if (location_index >= uniform_infos_.size())
1266 UniformInfo& info = uniform_infos_[uniform_index]; 1221 return false;
1267 if (!info.IsValid()) { 1222
1268 return false; 1223 if (!uniform_locations_[location_index].IsActive())
1269 } 1224 return false;
1270 GLint element_index = GetArrayElementIndexFromFakeLocation(fake_location); 1225
1271 if (element_index < info.size) { 1226 UniformInfo* info = uniform_locations_[location_index].uniform();
1272 count = std::min(info.size - element_index, count); 1227
1273 if (info.IsSampler() && count > 0) { 1228 size_t element_index = GetArrayElementIndexFromFakeLocation(fake_location);
1274 for (GLsizei ii = 0; ii < count; ++ii) { 1229 if (static_cast<GLsizei>(element_index) >= info->size)
1275 if (value[ii] < 0 || value[ii] >= num_texture_units) { 1230 return true;
1276 return false; 1231 count = std::min(info->size - static_cast<GLsizei>(element_index), count);
1277 } 1232 if (info->IsSampler() && count > 0) {
1278 } 1233 for (GLsizei ii = 0; ii < count; ++ii) {
1279 std::copy(value, value + count, 1234 if (value[ii] < 0 || value[ii] >= num_texture_units) {
1280 info.texture_units.begin() + element_index); 1235 return false;
1281 return true;
1282 } 1236 }
1283 } 1237 }
1238 std::copy(value, value + count,
1239 info->texture_units.begin() + element_index);
1240 return true;
1284 } 1241 }
1285 return true; 1242 return true;
1286 } 1243 }
1287 1244
1288 void Program::GetProgramiv(GLenum pname, GLint* params) { 1245 void Program::GetProgramiv(GLenum pname, GLint* params) {
1289 switch (pname) { 1246 switch (pname) {
1290 case GL_ACTIVE_ATTRIBUTES: 1247 case GL_ACTIVE_ATTRIBUTES:
1291 *params = attrib_infos_.size(); 1248 *params = attrib_infos_.size();
1292 break; 1249 break;
1293 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH: 1250 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
1294 // Notice +1 to accomodate NULL terminator. 1251 // Notice +1 to accomodate NULL terminator.
1295 *params = max_attrib_name_length_ + 1; 1252 *params = max_attrib_name_length_ + 1;
1296 break; 1253 break;
1297 case GL_ACTIVE_UNIFORMS: 1254 case GL_ACTIVE_UNIFORMS:
1298 *params = num_uniforms_; 1255 *params = uniform_infos_.size();
1299 break; 1256 break;
1300 case GL_ACTIVE_UNIFORM_MAX_LENGTH: 1257 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
1301 // Notice +1 to accomodate NULL terminator. 1258 // Notice +1 to accomodate NULL terminator.
1302 *params = max_uniform_name_length_ + 1; 1259 *params = max_uniform_name_length_ + 1;
1303 break; 1260 break;
1304 case GL_LINK_STATUS: 1261 case GL_LINK_STATUS:
1305 *params = link_status_; 1262 *params = link_status_;
1306 break; 1263 break;
1307 case GL_INFO_LOG_LENGTH: 1264 case GL_INFO_LOG_LENGTH:
1308 // Notice +1 to accomodate NULL terminator. 1265 // Notice +1 to accomodate NULL terminator.
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
1650 // of an identifier is 256 characters. 1607 // of an identifier is 256 characters.
1651 uint32 num_locations = 0; 1608 uint32 num_locations = 0;
1652 uint32 total_string_size = 0; 1609 uint32 total_string_size = 0;
1653 1610
1654 for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) { 1611 for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) {
1655 const VertexAttrib& info = attrib_infos_[ii]; 1612 const VertexAttrib& info = attrib_infos_[ii];
1656 num_locations += 1; 1613 num_locations += 1;
1657 total_string_size += info.name.size(); 1614 total_string_size += info.name.size();
1658 } 1615 }
1659 1616
1660 for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) { 1617 for (const UniformInfo& info : uniform_infos_) {
1661 const UniformInfo& info = uniform_infos_[ii]; 1618 num_locations += info.element_locations.size();
1662 if (info.IsValid()) { 1619 total_string_size += info.name.size();
1663 num_locations += info.element_locations.size();
1664 total_string_size += info.name.size();
1665 }
1666 } 1620 }
1667 1621
1668 uint32 num_inputs = attrib_infos_.size() + num_uniforms_; 1622 uint32 num_inputs = attrib_infos_.size() + uniform_infos_.size();
1669 uint32 input_size = num_inputs * sizeof(ProgramInput); 1623 uint32 input_size = num_inputs * sizeof(ProgramInput);
1670 uint32 location_size = num_locations * sizeof(int32); 1624 uint32 location_size = num_locations * sizeof(int32);
1671 uint32 size = sizeof(ProgramInfoHeader) + 1625 uint32 size = sizeof(ProgramInfoHeader) +
1672 input_size + location_size + total_string_size; 1626 input_size + location_size + total_string_size;
1673 1627
1674 bucket->SetSize(size); 1628 bucket->SetSize(size);
1675 ProgramInfoHeader* header = bucket->GetDataAs<ProgramInfoHeader*>(0, size); 1629 ProgramInfoHeader* header = bucket->GetDataAs<ProgramInfoHeader*>(0, size);
1676 ProgramInput* inputs = bucket->GetDataAs<ProgramInput*>( 1630 ProgramInput* inputs = bucket->GetDataAs<ProgramInput*>(
1677 sizeof(ProgramInfoHeader), input_size); 1631 sizeof(ProgramInfoHeader), input_size);
1678 int32* locations = bucket->GetDataAs<int32*>( 1632 int32* locations = bucket->GetDataAs<int32*>(
1679 sizeof(ProgramInfoHeader) + input_size, location_size); 1633 sizeof(ProgramInfoHeader) + input_size, location_size);
1680 char* strings = bucket->GetDataAs<char*>( 1634 char* strings = bucket->GetDataAs<char*>(
1681 sizeof(ProgramInfoHeader) + input_size + location_size, 1635 sizeof(ProgramInfoHeader) + input_size + location_size,
1682 total_string_size); 1636 total_string_size);
1683 DCHECK(header); 1637 DCHECK(header);
1684 DCHECK(inputs); 1638 DCHECK(inputs);
1685 DCHECK(locations); 1639 DCHECK(locations);
1686 DCHECK(strings); 1640 DCHECK(strings);
1687 1641
1688 header->link_status = link_status_; 1642 header->link_status = link_status_;
1689 header->num_attribs = attrib_infos_.size(); 1643 header->num_attribs = attrib_infos_.size();
1690 header->num_uniforms = num_uniforms_; 1644 header->num_uniforms = uniform_infos_.size();
1691 1645
1692 for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) { 1646 for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) {
1693 const VertexAttrib& info = attrib_infos_[ii]; 1647 const VertexAttrib& info = attrib_infos_[ii];
1694 inputs->size = info.size; 1648 inputs->size = info.size;
1695 inputs->type = info.type; 1649 inputs->type = info.type;
1696 inputs->location_offset = ComputeOffset(header, locations); 1650 inputs->location_offset = ComputeOffset(header, locations);
1697 inputs->name_offset = ComputeOffset(header, strings); 1651 inputs->name_offset = ComputeOffset(header, strings);
1698 inputs->name_length = info.name.size(); 1652 inputs->name_length = info.name.size();
1699 *locations++ = info.location; 1653 *locations++ = info.location;
1700 memcpy(strings, info.name.c_str(), info.name.size()); 1654 memcpy(strings, info.name.c_str(), info.name.size());
1701 strings += info.name.size(); 1655 strings += info.name.size();
1702 ++inputs; 1656 ++inputs;
1703 } 1657 }
1704 1658
1705 for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) { 1659 for (const UniformInfo& info : uniform_infos_) {
1706 const UniformInfo& info = uniform_infos_[ii]; 1660 inputs->size = info.size;
1707 if (info.IsValid()) { 1661 inputs->type = info.type;
1708 inputs->size = info.size; 1662 inputs->location_offset = ComputeOffset(header, locations);
1709 inputs->type = info.type; 1663 inputs->name_offset = ComputeOffset(header, strings);
1710 inputs->location_offset = ComputeOffset(header, locations); 1664 inputs->name_length = info.name.size();
1711 inputs->name_offset = ComputeOffset(header, strings); 1665 DCHECK(static_cast<size_t>(info.size) == info.element_locations.size());
1712 inputs->name_length = info.name.size(); 1666 for (size_t jj = 0; jj < info.element_locations.size(); ++jj) {
1713 DCHECK(static_cast<size_t>(info.size) == info.element_locations.size()); 1667 if (info.element_locations[jj] == -1)
1714 for (size_t jj = 0; jj < info.element_locations.size(); ++jj) { 1668 *locations++ = -1;
1715 if (info.element_locations[jj] == -1) 1669 else
1716 *locations++ = -1; 1670 *locations++ =
1717 else 1671 ProgramManager::MakeFakeLocation(info.fake_location_base, jj);
1718 *locations++ = ProgramManager::MakeFakeLocation(ii, jj);
1719 }
1720 memcpy(strings, info.name.c_str(), info.name.size());
1721 strings += info.name.size();
1722 ++inputs;
1723 } 1672 }
1673 memcpy(strings, info.name.c_str(), info.name.size());
1674 strings += info.name.size();
1675 ++inputs;
1724 } 1676 }
1677 // NOTE: currently we do not pass inactive uniform binding locations
1678 // through the program info call.
1725 1679
1726 // NOTE: currently we do not pass fragment input infos through the program 1680 // NOTE: currently we do not pass fragment input infos through the program
1727 // info call, because they are not exposed through any getter function. 1681 // info call, because they are not exposed through any getter function.
1728 1682
1729 DCHECK_EQ(ComputeOffset(header, strings), size); 1683 DCHECK_EQ(ComputeOffset(header, strings), size);
1730 } 1684 }
1731 1685
1732 bool Program::GetUniformBlocks(CommonDecoder::Bucket* bucket) const { 1686 bool Program::GetUniformBlocks(CommonDecoder::Bucket* bucket) const {
1733 // The data is packed into the bucket in the following order 1687 // The data is packed into the bucket in the following order
1734 // 1) header 1688 // 1) header
(...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after
2168 DCHECK(program); 2122 DCHECK(program);
2169 program->ClearUniforms(&zero_); 2123 program->ClearUniforms(&zero_);
2170 } 2124 }
2171 2125
2172 int32 ProgramManager::MakeFakeLocation(int32 index, int32 element) { 2126 int32 ProgramManager::MakeFakeLocation(int32 index, int32 element) {
2173 return index + element * 0x10000; 2127 return index + element * 0x10000;
2174 } 2128 }
2175 2129
2176 } // namespace gles2 2130 } // namespace gles2
2177 } // namespace gpu 2131 } // namespace gpu
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698