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

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: 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 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
110 uint32 ComputeOffset(const void* start, const void* position) { 110 uint32 ComputeOffset(const void* start, const void* position) {
111 return static_cast<const uint8*>(position) - 111 return static_cast<const uint8*>(position) -
112 static_cast<const uint8*>(start); 112 static_cast<const uint8*>(start);
113 } 113 }
114 114
115 } // anonymous namespace. 115 } // anonymous namespace.
116 116
117 Program::UniformInfo::UniformInfo() 117 Program::UniformInfo::UniformInfo()
118 : size(0), 118 : size(0),
119 type(GL_NONE), 119 type(GL_NONE),
120 accepts_api_type(0),
120 fake_location_base(0), 121 fake_location_base(0),
121 is_array(false) { 122 is_array(false) {}
122 }
123 123
124 Program::UniformInfo::UniformInfo(GLsizei _size, 124 Program::UniformInfo::UniformInfo(const std::string& client_name,
125 int client_location_base,
125 GLenum _type, 126 GLenum _type,
126 int _fake_location_base, 127 bool _is_array,
127 const std::string& _name) 128 const std::vector<GLint>& service_locations)
128 : size(_size), 129 : size(service_locations.size()),
129 type(_type), 130 type(_type),
130 accepts_api_type(0), 131 accepts_api_type(0),
131 fake_location_base(_fake_location_base), 132 fake_location_base(client_location_base),
132 is_array(false), 133 is_array(_is_array),
133 name(_name) { 134 name(client_name),
135 element_locations(service_locations) {
134 switch (type) { 136 switch (type) {
135 case GL_INT: 137 case GL_INT:
136 accepts_api_type = kUniform1i; 138 accepts_api_type = kUniform1i;
137 break; 139 break;
138 case GL_INT_VEC2: 140 case GL_INT_VEC2:
139 accepts_api_type = kUniform2i; 141 accepts_api_type = kUniform2i;
140 break; 142 break;
141 case GL_INT_VEC3: 143 case GL_INT_VEC3:
142 accepts_api_type = kUniform3i; 144 accepts_api_type = kUniform3i;
143 break; 145 break;
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after
229 case GL_UNSIGNED_INT_SAMPLER_3D: 231 case GL_UNSIGNED_INT_SAMPLER_3D:
230 case GL_UNSIGNED_INT_SAMPLER_CUBE: 232 case GL_UNSIGNED_INT_SAMPLER_CUBE:
231 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY: 233 case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
232 accepts_api_type = kUniform1i; 234 accepts_api_type = kUniform1i;
233 break; 235 break;
234 236
235 default: 237 default:
236 NOTREACHED() << "Unhandled UniformInfo type " << type; 238 NOTREACHED() << "Unhandled UniformInfo type " << type;
237 break; 239 break;
238 } 240 }
241 DCHECK_LT(0, size);
242 DCHECK(is_array || size == 1);
243
244 size_t num_texture_units = IsSampler() ? static_cast<size_t>(size) : 0u;
245 texture_units.clear();
246 texture_units.resize(num_texture_units, 0);
239 } 247 }
240
241 Program::UniformInfo::~UniformInfo() {} 248 Program::UniformInfo::~UniformInfo() {}
242 249
243 bool ProgramManager::IsInvalidPrefix(const char* name, size_t length) { 250 bool ProgramManager::IsInvalidPrefix(const char* name, size_t length) {
244 static const char kInvalidPrefix[] = { 'g', 'l', '_' }; 251 static const char kInvalidPrefix[] = { 'g', 'l', '_' };
245 return (length >= sizeof(kInvalidPrefix) && 252 return (length >= sizeof(kInvalidPrefix) &&
246 memcmp(name, kInvalidPrefix, sizeof(kInvalidPrefix)) == 0); 253 memcmp(name, kInvalidPrefix, sizeof(kInvalidPrefix)) == 0);
247 } 254 }
248 255
249 Program::Program(ProgramManager* manager, GLuint service_id) 256 Program::Program(ProgramManager* manager, GLuint service_id)
250 : manager_(manager), 257 : manager_(manager),
251 use_count_(0), 258 use_count_(0),
252 max_attrib_name_length_(0), 259 max_attrib_name_length_(0),
253 max_uniform_name_length_(0), 260 max_uniform_name_length_(0),
254 service_id_(service_id), 261 service_id_(service_id),
255 deleted_(false), 262 deleted_(false),
256 valid_(false), 263 valid_(false),
257 link_status_(false), 264 link_status_(false),
258 uniforms_cleared_(false), 265 uniforms_cleared_(false),
259 num_uniforms_(0),
260 transform_feedback_buffer_mode_(GL_NONE) { 266 transform_feedback_buffer_mode_(GL_NONE) {
261 manager_->StartTracking(this); 267 manager_->StartTracking(this);
262 } 268 }
263 269
264 void Program::Reset() { 270 void Program::Reset() {
265 valid_ = false; 271 valid_ = false;
266 link_status_ = false; 272 link_status_ = false;
267 num_uniforms_ = 0;
268 max_uniform_name_length_ = 0; 273 max_uniform_name_length_ = 0;
269 max_attrib_name_length_ = 0; 274 max_attrib_name_length_ = 0;
270 attrib_infos_.clear(); 275 attrib_infos_.clear();
271 uniform_infos_.clear(); 276 uniform_infos_.clear();
277 uniform_locations_.clear();
272 fragment_input_infos_.clear(); 278 fragment_input_infos_.clear();
273 sampler_indices_.clear(); 279 sampler_indices_.clear();
274 attrib_location_to_index_map_.clear(); 280 attrib_location_to_index_map_.clear();
275 } 281 }
276 282
277 std::string Program::ProcessLogInfo( 283 std::string Program::ProcessLogInfo(
278 const std::string& log) { 284 const std::string& log) {
279 std::string output; 285 std::string output;
280 re2::StringPiece input(log); 286 re2::StringPiece input(log);
281 std::string prior_log; 287 std::string prior_log;
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
313 set_log_info(ProcessLogInfo(log).c_str()); 319 set_log_info(ProcessLogInfo(log).c_str());
314 } 320 }
315 321
316 void Program::ClearUniforms( 322 void Program::ClearUniforms(
317 std::vector<uint8>* zero_buffer) { 323 std::vector<uint8>* zero_buffer) {
318 DCHECK(zero_buffer); 324 DCHECK(zero_buffer);
319 if (uniforms_cleared_) { 325 if (uniforms_cleared_) {
320 return; 326 return;
321 } 327 }
322 uniforms_cleared_ = true; 328 uniforms_cleared_ = true;
323 for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) { 329 for (const UniformInfo& uniform_info : uniform_infos_) {
324 const UniformInfo& uniform_info = uniform_infos_[ii];
325 if (!uniform_info.IsValid()) {
326 continue;
327 }
328 GLint location = uniform_info.element_locations[0]; 330 GLint location = uniform_info.element_locations[0];
329 GLsizei size = uniform_info.size; 331 GLsizei size = uniform_info.size;
330 uint32 unit_size = 332 uint32 unit_size =
331 GLES2Util::GetElementCountForUniformType(uniform_info.type) * 333 GLES2Util::GetElementCountForUniformType(uniform_info.type) *
332 GLES2Util::GetElementSizeForUniformType(uniform_info.type); 334 GLES2Util::GetElementSizeForUniformType(uniform_info.type);
333 DCHECK_LT(0u, unit_size); 335 DCHECK_LT(0u, unit_size);
334 uint32 size_needed = size * unit_size; 336 uint32 size_needed = size * unit_size;
335 if (size_needed > zero_buffer->size()) { 337 if (size_needed > zero_buffer->size()) {
336 zero_buffer->resize(size_needed, 0u); 338 zero_buffer->resize(size_needed, 0u);
337 } 339 }
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
435 location, size, false, reinterpret_cast<const GLfloat*>(zero)); 437 location, size, false, reinterpret_cast<const GLfloat*>(zero));
436 break; 438 break;
437 439
438 default: 440 default:
439 NOTREACHED(); 441 NOTREACHED();
440 break; 442 break;
441 } 443 }
442 } 444 }
443 } 445 }
444 446
445 namespace {
446
447 struct UniformData {
448 UniformData() : size(-1), type(GL_NONE), location(0), added(false) {
449 }
450 std::string queried_name;
451 std::string corrected_name;
452 std::string original_name;
453 GLsizei size;
454 GLenum type;
455 GLint location;
456 bool added;
457 };
458
459 } // anonymous namespace
460
461 void Program::Update() { 447 void Program::Update() {
462 Reset(); 448 Reset();
463 UpdateLogInfo(); 449 UpdateLogInfo();
464 link_status_ = true; 450 link_status_ = true;
465 uniforms_cleared_ = false; 451 uniforms_cleared_ = false;
466 GLint num_attribs = 0; 452 GLint num_attribs = 0;
467 GLint max_len = 0; 453 GLint max_len = 0;
468 GLint max_location = -1; 454 GLint max_location = -1;
469 glGetProgramiv(service_id_, GL_ACTIVE_ATTRIBUTES, &num_attribs); 455 glGetProgramiv(service_id_, GL_ACTIVE_ATTRIBUTES, &num_attribs);
470 glGetProgramiv(service_id_, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_len); 456 glGetProgramiv(service_id_, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_len);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
506 DVLOG(1) << "----: attribs for service_id: " << service_id(); 492 DVLOG(1) << "----: attribs for service_id: " << service_id();
507 for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) { 493 for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) {
508 const VertexAttrib& info = attrib_infos_[ii]; 494 const VertexAttrib& info = attrib_infos_[ii];
509 DVLOG(1) << ii << ": loc = " << info.location 495 DVLOG(1) << ii << ": loc = " << info.location
510 << ", size = " << info.size 496 << ", size = " << info.size
511 << ", type = " << GLES2Util::GetStringEnum(info.type) 497 << ", type = " << GLES2Util::GetStringEnum(info.type)
512 << ", name = " << info.name; 498 << ", name = " << info.name;
513 } 499 }
514 } 500 }
515 #endif 501 #endif
516 502 UpdateUniforms();
517 max_len = 0;
518 GLint num_uniforms = 0;
519 glGetProgramiv(service_id_, GL_ACTIVE_UNIFORMS, &num_uniforms);
520 glGetProgramiv(service_id_, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_len);
521 DCHECK(num_uniforms <= 0 || max_len > 0);
522 name_buffer.reset(new char[max_len]);
523
524 // Reads all the names.
525 std::vector<UniformData> uniform_data;
526 for (GLint ii = 0; ii < num_uniforms; ++ii) {
527 GLsizei length = 0;
528 UniformData data;
529 glGetActiveUniform(
530 service_id_, ii, max_len, &length,
531 &data.size, &data.type, name_buffer.get());
532 DCHECK(length < max_len);
533 DCHECK(length == 0 || name_buffer[length] == '\0');
534 data.queried_name = std::string(name_buffer.get());
535 GetCorrectedUniformData(data.queried_name, &data.corrected_name,
536 &data.original_name, &data.size, &data.type);
537 uniform_data.push_back(data);
538 }
539
540 // NOTE: We don't care if 2 uniforms are bound to the same location.
541 // One of them will take preference. The spec allows this, same as
542 // BindAttribLocation.
543 //
544 // The reason we don't check is if we were to fail we'd have to
545 // restore the previous program but since we've already linked successfully
546 // at this point the previous program is gone.
547
548 // Assigns the uniforms with bindings.
549 size_t next_available_index = 0;
550 for (size_t ii = 0; ii < uniform_data.size(); ++ii) {
551 UniformData& data = uniform_data[ii];
552 // Force builtin uniforms (gl_DepthRange) to have invalid location.
553 if (ProgramManager::IsInvalidPrefix(data.queried_name.c_str(),
554 data.queried_name.size())) {
555 data.location = -1;
556 } else {
557 data.location =
558 glGetUniformLocation(service_id_, data.queried_name.c_str());
559 }
560 // remove "[0]"
561 std::string short_name;
562 int element_index = 0;
563 bool good = GetUniformNameSansElement(data.original_name, &element_index,
564 &short_name);
565 DCHECK(good);
566 LocationMap::const_iterator it = bind_uniform_location_map_.find(
567 short_name);
568 if (it != bind_uniform_location_map_.end()) {
569 AddUniformInfo(
570 data.size, data.type, data.location, it->second, data.corrected_name,
571 data.original_name, &next_available_index);
572 data.added = true;
573 }
574 }
575
576 // Assigns the uniforms that were not bound.
577 for (size_t ii = 0; ii < uniform_data.size(); ++ii) {
578 const UniformData& data = uniform_data[ii];
579 if (!data.added) {
580 AddUniformInfo(
581 data.size, data.type, data.location, -1, data.corrected_name,
582 data.original_name, &next_available_index);
583 }
584 }
585 503
586 #if !defined(NDEBUG) 504 #if !defined(NDEBUG)
587 if (base::CommandLine::ForCurrentProcess()->HasSwitch( 505 if (base::CommandLine::ForCurrentProcess()->HasSwitch(
588 switches::kEnableGPUServiceLoggingGPU)) { 506 switches::kEnableGPUServiceLoggingGPU)) {
589 DVLOG(1) << "----: uniforms for service_id: " << service_id(); 507 DVLOG(1) << "----: uniforms for service_id: " << service_id();
590 for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) { 508 size_t ii = 0;
591 const UniformInfo& info = uniform_infos_[ii]; 509 for (const UniformInfo& info : uniform_infos_) {
592 if (info.IsValid()) { 510 DVLOG(1) << ii++ << ": loc = " << info.element_locations[0]
593 DVLOG(1) << ii << ": loc = " << info.element_locations[0] 511 << ", size = " << info.size
594 << ", size = " << info.size 512 << ", type = " << GLES2Util::GetStringEnum(info.type)
595 << ", type = " << GLES2Util::GetStringEnum(info.type) 513 << ", name = " << info.name;
596 << ", name = " << info.name;
597 }
598 } 514 }
599 } 515 }
600 #endif 516 #endif
601 517
602 UpdateFragmentInputs(); 518 UpdateFragmentInputs();
603 519
604 valid_ = true; 520 valid_ = true;
605 } 521 }
606 522
523 void Program::UpdateUniforms() {
524 // Reserve each client-bound uniform location. This way unbound uniforms will
525 // not be allocated to locations that user expects bound uniforms to be, even
526 // if the expected uniforms are optimized away by the driver.
527 for (const auto& binding : bind_uniform_location_map_) {
528 if (binding.second < 0)
529 continue;
530 size_t client_location = static_cast<size_t>(binding.second);
531 if (uniform_locations_.size() <= client_location)
532 uniform_locations_.resize(client_location + 1);
533 uniform_locations_[client_location].SetInactive();
534 }
535
536 GLint num_uniforms = 0;
537 glGetProgramiv(service_id_, GL_ACTIVE_UNIFORMS, &num_uniforms);
538 if (num_uniforms <= 0)
539 return;
540
541 uniform_infos_.resize(num_uniforms);
542
543 GLint name_buffer_length = 0;
544 glGetProgramiv(service_id_, GL_ACTIVE_UNIFORM_MAX_LENGTH,
545 &name_buffer_length);
546 DCHECK(name_buffer_length > 0);
547 scoped_ptr<char[]> name_buffer(new char[name_buffer_length]);
548
549 size_t unused_client_location_cursor = 0;
550
551 for (GLint uniform_index = 0; uniform_index < num_uniforms; ++uniform_index) {
552 GLsizei name_length = 0;
553 GLsizei size = 0;
554 GLenum type = GL_NONE;
555 glGetActiveUniform(service_id_, uniform_index, name_buffer_length,
556 &name_length, &size, &type, name_buffer.get());
557 DCHECK(name_length < name_buffer_length);
558 DCHECK(name_length == 0 || name_buffer[name_length] == '\0');
559 std::string service_name(name_buffer.get(), name_length);
560
561 GLint service_location = -1;
562 // Force builtin uniforms (gl_DepthRange) to have invalid location.
563 if (!ProgramManager::IsInvalidPrefix(service_name.c_str(),
564 service_name.size())) {
565 service_location =
566 glGetUniformLocation(service_id_, service_name.c_str());
567 }
568
569 // Determine the client name of the uniform and whether it is an array
570 // or not.
571 bool is_array;
572 std::string client_name;
573 for (size_t i = 0; i < kMaxAttachedShaders && client_name.empty(); ++i) {
574 const auto& shader = attached_shaders_[i];
575 if (!shader)
576 continue;
577 const sh::ShaderVariable* info = nullptr;
578 const sh::Uniform* uniform = shader->GetUniformInfo(service_name);
579 if (uniform &&
580 uniform->findInfoByMappedName(service_name, &info, &client_name)) {
581 DCHECK(!client_name.empty());
582 is_array = info->arraySize > 0;
583 type = info->type;
584 size = std::max(1u, info->arraySize);
585 }
586 }
587 if (client_name.empty()) {
588 // This happens only in cases where we do not have ANGLE or run unit tests
589 // (or ANGLE has a severe bug).
590 client_name = service_name;
591 GLSLArrayName parsed_service_name(service_name);
592 is_array = size > 1 || parsed_service_name.IsArrayName();
593 }
594
595 std::string service_base_name = service_name;
596 std::string client_base_name = client_name;
597 if (is_array) {
598 // Some drivers incorrectly return an uniform name of size-1 array without
599 // "[0]". In this case, we correct the service name by appending "[0]" to
600 // it.
601 GLSLArrayName parsed_service_name(service_name);
602 if (parsed_service_name.IsArrayName()) {
603 service_base_name = parsed_service_name.base_name();
604 GLSLArrayName parsed_client_name(client_name);
605 client_base_name = parsed_client_name.base_name();
606 } else {
607 service_name += "[0]";
608 client_name += "[0]";
609 }
610 }
611
612 // Assign a location for the uniform: use either client-bound
613 // location or automatically assigned to an unused location.
614 size_t client_location_base = 0;
615 LocationMap::const_iterator it =
616 bind_uniform_location_map_.find(client_base_name);
617 if (it != bind_uniform_location_map_.end()) {
618 client_location_base = it->second;
619 } else {
620 while (unused_client_location_cursor < uniform_locations_.size() &&
621 !uniform_locations_[unused_client_location_cursor].IsUnused())
622 unused_client_location_cursor++;
623 if (unused_client_location_cursor == uniform_locations_.size())
624 uniform_locations_.resize(unused_client_location_cursor + 1);
625 client_location_base = unused_client_location_cursor;
626 unused_client_location_cursor++;
627 }
628
629 // Populate the uniform list entry.
630 std::vector<GLint> service_locations;
631 service_locations.resize(size);
632 service_locations[0] = service_location;
633
634 if (size > 1) {
635 for (GLsizei ii = 1; ii < size; ++ii) {
636 std::string element_name(service_base_name + "[" +
637 base::IntToString(ii) + "]");
638 service_locations[ii] =
639 glGetUniformLocation(service_id_, element_name.c_str());
640 }
641 }
642
643 UniformInfo& info = uniform_infos_[uniform_index];
644 info = UniformInfo(client_name, client_location_base, type, is_array,
645 service_locations);
646 if (info.IsSampler()) {
647 sampler_indices_.push_back(uniform_index);
648 }
649
650 // Populate the uniform location list entry.
651 // Before linking, we already validated that no two statically used uniforms
652 // are bound to the same location.
653 DCHECK(!uniform_locations_[client_location_base].IsActive());
654 uniform_locations_[client_location_base].SetActive(&info);
655
656 max_uniform_name_length_ = std::max(max_uniform_name_length_,
657 static_cast<GLsizei>(info.name.size()));
658 }
659 }
660
607 void Program::UpdateFragmentInputs() { 661 void Program::UpdateFragmentInputs() {
608 if (!feature_info().feature_flags().chromium_path_rendering) 662 if (!feature_info().feature_flags().chromium_path_rendering)
609 return; 663 return;
610 GLint num_fragment_inputs = 0; 664 GLint num_fragment_inputs = 0;
611 glGetProgramInterfaceiv(service_id_, GL_FRAGMENT_INPUT_NV, 665 glGetProgramInterfaceiv(service_id_, GL_FRAGMENT_INPUT_NV,
612 GL_ACTIVE_RESOURCES, &num_fragment_inputs); 666 GL_ACTIVE_RESOURCES, &num_fragment_inputs);
613 if (num_fragment_inputs <= 0) 667 if (num_fragment_inputs <= 0)
614 return; 668 return;
615 GLint max_len = 0; 669 GLint max_len = 0;
616 glGetProgramInterfaceiv(service_id_, GL_FRAGMENT_INPUT_NV, GL_MAX_NAME_LENGTH, 670 glGetProgramInterfaceiv(service_id_, GL_FRAGMENT_INPUT_NV, GL_MAX_NAME_LENGTH,
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
907 return; 961 return;
908 } 962 }
909 glValidateProgram(service_id()); 963 glValidateProgram(service_id());
910 UpdateLogInfo(); 964 UpdateLogInfo();
911 } 965 }
912 966
913 GLint Program::GetUniformFakeLocation( 967 GLint Program::GetUniformFakeLocation(
914 const std::string& name) const { 968 const std::string& name) const {
915 GLSLArrayName parsed_name(name); 969 GLSLArrayName parsed_name(name);
916 970
917 for (GLuint ii = 0; ii < uniform_infos_.size(); ++ii) { 971 for (const UniformInfo& info : uniform_infos_) {
918 const UniformInfo& info = uniform_infos_[ii];
919 if (!info.IsValid()) {
920 continue;
921 }
922 if (info.name == name || 972 if (info.name == name ||
923 (info.is_array && 973 (info.is_array &&
924 info.name.compare(0, info.name.size() - 3, name) == 0)) { 974 info.name.compare(0, info.name.size() - 3, name) == 0)) {
925 return info.fake_location_base; 975 return info.fake_location_base;
926 } else if (parsed_name.IsArrayName() && info.is_array) { 976 } else if (parsed_name.IsArrayName() && info.is_array) {
927 // Look for an array specification. 977 // Look for an array specification.
928 size_t open_pos = info.name.find_last_of('['); 978 size_t open_pos = info.name.find_last_of('[');
929 if (info.name.compare(0, open_pos, parsed_name.base_name()) == 0) { 979 if (info.name.compare(0, open_pos, parsed_name.base_name()) == 0) {
930 int index = parsed_name.element_index(); 980 int index = parsed_name.element_index();
931 DCHECK(index >= 0);
932 if (index < info.size) { 981 if (index < info.size) {
933 DCHECK_GT(static_cast<int>(info.element_locations.size()), index); 982 DCHECK_GT(static_cast<int>(info.element_locations.size()), index);
934 if (info.element_locations[index] == -1) 983 if (info.element_locations[index] == -1)
935 return -1; 984 return -1;
936 return ProgramManager::MakeFakeLocation( 985 return ProgramManager::MakeFakeLocation(
937 info.fake_location_base, index); 986 info.fake_location_base, index);
938 } 987 }
939 } 988 }
940 } 989 }
941 } 990 }
942 return -1; 991 return -1;
943 } 992 }
944 993
945 GLint Program::GetAttribLocation( 994 GLint Program::GetAttribLocation(
946 const std::string& original_name) const { 995 const std::string& original_name) const {
947 for (GLuint ii = 0; ii < attrib_infos_.size(); ++ii) { 996 for (GLuint ii = 0; ii < attrib_infos_.size(); ++ii) {
948 const VertexAttrib& info = attrib_infos_[ii]; 997 const VertexAttrib& info = attrib_infos_[ii];
949 if (info.name == original_name) { 998 if (info.name == original_name) {
950 return info.location; 999 return info.location;
951 } 1000 }
952 } 1001 }
953 return -1; 1002 return -1;
954 } 1003 }
955 1004
956 const Program::UniformInfo* 1005 const Program::UniformInfo*
957 Program::GetUniformInfoByFakeLocation( 1006 Program::GetUniformInfoByFakeLocation(
958 GLint fake_location, GLint* real_location, GLint* array_index) const { 1007 GLint fake_location, GLint* real_location, GLint* array_index) const {
959 DCHECK(real_location); 1008 DCHECK(real_location);
960 DCHECK(array_index); 1009 DCHECK(array_index);
961 if (fake_location < 0) { 1010 if (fake_location < 0)
962 return NULL; 1011 return nullptr;
963 } 1012 size_t location_index =
1013 GetUniformLocationIndexFromFakeLocation(fake_location);
1014 if (location_index >= uniform_locations_.size())
1015 return nullptr;
964 1016
965 GLint uniform_index = GetUniformInfoIndexFromFakeLocation(fake_location); 1017 if (!uniform_locations_[location_index].IsActive())
966 if (uniform_index >= 0 && 1018 return nullptr;
967 static_cast<size_t>(uniform_index) < uniform_infos_.size()) { 1019
968 const UniformInfo& uniform_info = uniform_infos_[uniform_index]; 1020 const UniformInfo* info = uniform_locations_[location_index].uniform();
969 if (!uniform_info.IsValid()) { 1021 size_t element_index = GetArrayElementIndexFromFakeLocation(fake_location);
970 return NULL; 1022 if (static_cast<GLsizei>(element_index) >= info->size)
971 } 1023 return nullptr;
972 GLint element_index = GetArrayElementIndexFromFakeLocation(fake_location); 1024 *real_location = info->element_locations[element_index];
973 if (element_index < uniform_info.size) { 1025 *array_index = element_index;
974 *real_location = uniform_info.element_locations[element_index]; 1026 return info;
975 *array_index = element_index; 1027 }
976 return &uniform_info; 1028
977 } 1029 bool Program::IsInactiveUniformLocationByFakeLocation(
978 } 1030 GLint fake_location) const {
979 return NULL; 1031 if (fake_location < 0)
1032 return true;
1033 size_t location_index =
1034 GetUniformLocationIndexFromFakeLocation(fake_location);
1035 if (location_index >= uniform_locations_.size())
1036 return false;
zmo 2015/11/20 00:23:42 Question: why false here?
Kimmo Kinnunen 2015/11/20 07:56:53 The function returns true only for locations of in
1037 return uniform_locations_[location_index].IsInactive();
980 } 1038 }
981 1039
982 const std::string* Program::GetAttribMappedName( 1040 const std::string* Program::GetAttribMappedName(
983 const std::string& original_name) const { 1041 const std::string& original_name) const {
984 for (auto shader : attached_shaders_) { 1042 for (auto shader : attached_shaders_) {
985 if (shader) { 1043 if (shader) {
986 const std::string* mapped_name = 1044 const std::string* mapped_name =
987 shader->GetAttribMappedName(original_name); 1045 shader->GetAttribMappedName(original_name);
988 if (mapped_name) 1046 if (mapped_name)
989 return mapped_name; 1047 return mapped_name;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
1049 // string would exactly match the name of the variable if the suffix "[0]" 1107 // string would exactly match the name of the variable if the suffix "[0]"
1050 // were appended to the string". 1108 // were appended to the string".
1051 1109
1052 // At this point we can not know if the string identifies a simple variable, 1110 // At this point we can not know if the string identifies a simple variable,
1053 // a base name of an array, or nothing. Store both, so if user overwrites 1111 // a base name of an array, or nothing. Store both, so if user overwrites
1054 // either, both still work correctly. 1112 // either, both still work correctly.
1055 bind_fragment_input_location_map_[name] = location; 1113 bind_fragment_input_location_map_[name] = location;
1056 bind_fragment_input_location_map_[name + "[0]"] = location; 1114 bind_fragment_input_location_map_[name + "[0]"] = location;
1057 } 1115 }
1058 1116
1059 // Note: This is only valid to call right after a program has been linked
1060 // successfully.
1061 void Program::GetCorrectedUniformData(
1062 const std::string& name,
1063 std::string* corrected_name, std::string* original_name,
1064 GLsizei* size, GLenum* type) const {
1065 DCHECK(corrected_name && original_name && size && type);
1066 for (auto shader : attached_shaders_) {
1067 if (!shader)
1068 continue;
1069 const sh::ShaderVariable* info = NULL;
1070 const sh::Uniform* uniform = shader->GetUniformInfo(name);
1071 bool found = false;
1072 if (uniform)
1073 found = uniform->findInfoByMappedName(name, &info, original_name);
1074 if (found) {
1075 const std::string kArraySpec("[0]");
1076 if (info->arraySize > 0 &&
1077 !base::EndsWith(name, kArraySpec, base::CompareCase::SENSITIVE)) {
1078 *corrected_name = name + kArraySpec;
1079 *original_name += kArraySpec;
1080 } else {
1081 *corrected_name = name;
1082 }
1083 *type = info->type;
1084 *size = std::max(1u, info->arraySize);
1085 return;
1086 }
1087 }
1088 // TODO(zmo): this path should never be reached unless there is a serious
1089 // bug in the driver or in ANGLE translator.
1090 *corrected_name = name;
1091 *original_name = name;
1092 }
1093
1094 void Program::GetVertexAttribData( 1117 void Program::GetVertexAttribData(
1095 const std::string& name, std::string* original_name, GLenum* type) const { 1118 const std::string& name, std::string* original_name, GLenum* type) const {
1096 DCHECK(original_name); 1119 DCHECK(original_name);
1097 DCHECK(type); 1120 DCHECK(type);
1098 Shader* shader = attached_shaders_[ShaderTypeToIndex(GL_VERTEX_SHADER)].get(); 1121 Shader* shader = attached_shaders_[ShaderTypeToIndex(GL_VERTEX_SHADER)].get();
1099 if (shader) { 1122 if (shader) {
1100 // Vertex attributes can not be arrays or structs (GLSL ES 3.00.4, section 1123 // Vertex attributes can not be arrays or structs (GLSL ES 3.00.4, section
1101 // 4.3.4, "Input Variables"), so the top level sh::Attribute returns the 1124 // 4.3.4, "Input Variables"), so the top level sh::Attribute returns the
1102 // information we need. 1125 // information we need.
1103 const sh::Attribute* info = shader->GetAttribInfo(name); 1126 const sh::Attribute* info = shader->GetAttribInfo(name);
1104 if (info) { 1127 if (info) {
1105 *original_name = info->name; 1128 *original_name = info->name;
1106 *type = info->type; 1129 *type = info->type;
1107 return; 1130 return;
1108 } 1131 }
1109 } 1132 }
1110 // TODO(zmo): this path should never be reached unless there is a serious 1133 // TODO(zmo): this path should never be reached unless there is a serious
1111 // bug in the driver or in ANGLE translator. 1134 // bug in the driver or in ANGLE translator.
1112 *original_name = name; 1135 *original_name = name;
1113 } 1136 }
1114 1137
1115 void Program::AddUniformInfo(
1116 GLsizei size, GLenum type, GLint location, GLint fake_base_location,
1117 const std::string& name, const std::string& original_name,
1118 size_t* next_available_index) {
1119 DCHECK(next_available_index);
1120 const char* kArraySpec = "[0]";
1121 size_t uniform_index =
1122 fake_base_location >= 0 ? fake_base_location : *next_available_index;
1123 if (uniform_infos_.size() < uniform_index + 1) {
1124 uniform_infos_.resize(uniform_index + 1);
1125 }
1126
1127 // Before linking, we already validated that no two statically used uniforms
1128 // are bound to the same location.
1129 DCHECK(!uniform_infos_[uniform_index].IsValid());
1130
1131 uniform_infos_[uniform_index] = UniformInfo(
1132 size, type, uniform_index, original_name);
1133 ++num_uniforms_;
1134
1135 UniformInfo& info = uniform_infos_[uniform_index];
1136 info.element_locations.resize(size);
1137 info.element_locations[0] = location;
1138 DCHECK_LE(0, size);
1139 size_t num_texture_units = info.IsSampler() ? static_cast<size_t>(size) : 0u;
1140 info.texture_units.clear();
1141 info.texture_units.resize(num_texture_units, 0);
1142
1143 if (size > 1) {
1144 // Go through the array element locations looking for a match.
1145 // We can skip the first element because it's the same as the
1146 // the location without the array operators.
1147 size_t array_pos = name.rfind(kArraySpec);
1148 std::string base_name = name;
1149 if (name.size() > 3) {
1150 if (array_pos != name.size() - 3) {
1151 info.name = name + kArraySpec;
1152 } else {
1153 base_name = name.substr(0, name.size() - 3);
1154 }
1155 }
1156 for (GLsizei ii = 1; ii < info.size; ++ii) {
1157 std::string element_name(base_name + "[" + base::IntToString(ii) + "]");
1158 info.element_locations[ii] =
1159 glGetUniformLocation(service_id_, element_name.c_str());
1160 }
1161 }
1162
1163 info.is_array =
1164 (size > 1 ||
1165 (info.name.size() > 3 &&
1166 info.name.rfind(kArraySpec) == info.name.size() - 3));
1167
1168 if (info.IsSampler()) {
1169 sampler_indices_.push_back(info.fake_location_base);
1170 }
1171 max_uniform_name_length_ =
1172 std::max(max_uniform_name_length_,
1173 static_cast<GLsizei>(info.name.size()));
1174
1175 while (*next_available_index < uniform_infos_.size() &&
1176 uniform_infos_[*next_available_index].IsValid()) {
1177 *next_available_index = *next_available_index + 1;
1178 }
1179 }
1180
1181 const Program::UniformInfo* 1138 const Program::UniformInfo*
1182 Program::GetUniformInfo( 1139 Program::GetUniformInfo(
1183 GLint index) const { 1140 GLint index) const {
1184 if (static_cast<size_t>(index) >= uniform_infos_.size()) { 1141 if (static_cast<size_t>(index) >= uniform_infos_.size()) {
1185 return NULL; 1142 return NULL;
1186 } 1143 }
1187 1144 return &uniform_infos_[index];
1188 const UniformInfo& info = uniform_infos_[index];
1189 return info.IsValid() ? &info : NULL;
1190 } 1145 }
1191 1146
1192 bool Program::SetSamplers( 1147 bool Program::SetSamplers(
1193 GLint num_texture_units, GLint fake_location, 1148 GLint num_texture_units, GLint fake_location,
1194 GLsizei count, const GLint* value) { 1149 GLsizei count, const GLint* value) {
1195 if (fake_location < 0) { 1150 if (fake_location < 0) {
1196 return true; 1151 return true;
1197 } 1152 }
1198 GLint uniform_index = GetUniformInfoIndexFromFakeLocation(fake_location); 1153 size_t location_index =
1199 if (uniform_index >= 0 && 1154 GetUniformLocationIndexFromFakeLocation(fake_location);
1200 static_cast<size_t>(uniform_index) < uniform_infos_.size()) { 1155 if (location_index >= uniform_infos_.size())
1201 UniformInfo& info = uniform_infos_[uniform_index]; 1156 return false;
1202 if (!info.IsValid()) { 1157
1203 return false; 1158 if (!uniform_locations_[location_index].IsActive())
1204 } 1159 return false;
1205 GLint element_index = GetArrayElementIndexFromFakeLocation(fake_location); 1160
1206 if (element_index < info.size) { 1161 UniformInfo* info = uniform_locations_[location_index].uniform();
1207 count = std::min(info.size - element_index, count); 1162
1208 if (info.IsSampler() && count > 0) { 1163 size_t element_index = GetArrayElementIndexFromFakeLocation(fake_location);
1209 for (GLsizei ii = 0; ii < count; ++ii) { 1164 if (static_cast<GLsizei>(element_index) >= info->size)
1210 if (value[ii] < 0 || value[ii] >= num_texture_units) { 1165 return true;
1211 return false; 1166 count = std::min(info->size - static_cast<GLsizei>(element_index), count);
1212 } 1167 if (info->IsSampler() && count > 0) {
1213 } 1168 for (GLsizei ii = 0; ii < count; ++ii) {
1214 std::copy(value, value + count, 1169 if (value[ii] < 0 || value[ii] >= num_texture_units) {
1215 info.texture_units.begin() + element_index); 1170 return false;
1216 return true;
1217 } 1171 }
1218 } 1172 }
1173 std::copy(value, value + count,
1174 info->texture_units.begin() + element_index);
1175 return true;
1219 } 1176 }
1220 return true; 1177 return true;
1221 } 1178 }
1222 1179
1223 void Program::GetProgramiv(GLenum pname, GLint* params) { 1180 void Program::GetProgramiv(GLenum pname, GLint* params) {
1224 switch (pname) { 1181 switch (pname) {
1225 case GL_ACTIVE_ATTRIBUTES: 1182 case GL_ACTIVE_ATTRIBUTES:
1226 *params = attrib_infos_.size(); 1183 *params = attrib_infos_.size();
1227 break; 1184 break;
1228 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH: 1185 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH:
1229 // Notice +1 to accomodate NULL terminator. 1186 // Notice +1 to accomodate NULL terminator.
1230 *params = max_attrib_name_length_ + 1; 1187 *params = max_attrib_name_length_ + 1;
1231 break; 1188 break;
1232 case GL_ACTIVE_UNIFORMS: 1189 case GL_ACTIVE_UNIFORMS:
1233 *params = num_uniforms_; 1190 *params = uniform_infos_.size();
1234 break; 1191 break;
1235 case GL_ACTIVE_UNIFORM_MAX_LENGTH: 1192 case GL_ACTIVE_UNIFORM_MAX_LENGTH:
1236 // Notice +1 to accomodate NULL terminator. 1193 // Notice +1 to accomodate NULL terminator.
1237 *params = max_uniform_name_length_ + 1; 1194 *params = max_uniform_name_length_ + 1;
1238 break; 1195 break;
1239 case GL_LINK_STATUS: 1196 case GL_LINK_STATUS:
1240 *params = link_status_; 1197 *params = link_status_;
1241 break; 1198 break;
1242 case GL_INFO_LOG_LENGTH: 1199 case GL_INFO_LOG_LENGTH:
1243 // Notice +1 to accomodate NULL terminator. 1200 // Notice +1 to accomodate NULL terminator.
(...skipping 341 matching lines...) Expand 10 before | Expand all | Expand 10 after
1585 // of an identifier is 256 characters. 1542 // of an identifier is 256 characters.
1586 uint32 num_locations = 0; 1543 uint32 num_locations = 0;
1587 uint32 total_string_size = 0; 1544 uint32 total_string_size = 0;
1588 1545
1589 for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) { 1546 for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) {
1590 const VertexAttrib& info = attrib_infos_[ii]; 1547 const VertexAttrib& info = attrib_infos_[ii];
1591 num_locations += 1; 1548 num_locations += 1;
1592 total_string_size += info.name.size(); 1549 total_string_size += info.name.size();
1593 } 1550 }
1594 1551
1595 for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) { 1552 for (const UniformInfo& info : uniform_infos_) {
1596 const UniformInfo& info = uniform_infos_[ii]; 1553 num_locations += info.element_locations.size();
1597 if (info.IsValid()) { 1554 total_string_size += info.name.size();
1598 num_locations += info.element_locations.size();
1599 total_string_size += info.name.size();
1600 }
1601 } 1555 }
1602 1556
1603 uint32 num_inputs = attrib_infos_.size() + num_uniforms_; 1557 uint32 num_inputs = attrib_infos_.size() + uniform_infos_.size();
1604 uint32 input_size = num_inputs * sizeof(ProgramInput); 1558 uint32 input_size = num_inputs * sizeof(ProgramInput);
1605 uint32 location_size = num_locations * sizeof(int32); 1559 uint32 location_size = num_locations * sizeof(int32);
1606 uint32 size = sizeof(ProgramInfoHeader) + 1560 uint32 size = sizeof(ProgramInfoHeader) +
1607 input_size + location_size + total_string_size; 1561 input_size + location_size + total_string_size;
1608 1562
1609 bucket->SetSize(size); 1563 bucket->SetSize(size);
1610 ProgramInfoHeader* header = bucket->GetDataAs<ProgramInfoHeader*>(0, size); 1564 ProgramInfoHeader* header = bucket->GetDataAs<ProgramInfoHeader*>(0, size);
1611 ProgramInput* inputs = bucket->GetDataAs<ProgramInput*>( 1565 ProgramInput* inputs = bucket->GetDataAs<ProgramInput*>(
1612 sizeof(ProgramInfoHeader), input_size); 1566 sizeof(ProgramInfoHeader), input_size);
1613 int32* locations = bucket->GetDataAs<int32*>( 1567 int32* locations = bucket->GetDataAs<int32*>(
1614 sizeof(ProgramInfoHeader) + input_size, location_size); 1568 sizeof(ProgramInfoHeader) + input_size, location_size);
1615 char* strings = bucket->GetDataAs<char*>( 1569 char* strings = bucket->GetDataAs<char*>(
1616 sizeof(ProgramInfoHeader) + input_size + location_size, 1570 sizeof(ProgramInfoHeader) + input_size + location_size,
1617 total_string_size); 1571 total_string_size);
1618 DCHECK(header); 1572 DCHECK(header);
1619 DCHECK(inputs); 1573 DCHECK(inputs);
1620 DCHECK(locations); 1574 DCHECK(locations);
1621 DCHECK(strings); 1575 DCHECK(strings);
1622 1576
1623 header->link_status = link_status_; 1577 header->link_status = link_status_;
1624 header->num_attribs = attrib_infos_.size(); 1578 header->num_attribs = attrib_infos_.size();
1625 header->num_uniforms = num_uniforms_; 1579 header->num_uniforms = uniform_infos_.size();
1626 1580
1627 for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) { 1581 for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) {
1628 const VertexAttrib& info = attrib_infos_[ii]; 1582 const VertexAttrib& info = attrib_infos_[ii];
1629 inputs->size = info.size; 1583 inputs->size = info.size;
1630 inputs->type = info.type; 1584 inputs->type = info.type;
1631 inputs->location_offset = ComputeOffset(header, locations); 1585 inputs->location_offset = ComputeOffset(header, locations);
1632 inputs->name_offset = ComputeOffset(header, strings); 1586 inputs->name_offset = ComputeOffset(header, strings);
1633 inputs->name_length = info.name.size(); 1587 inputs->name_length = info.name.size();
1634 *locations++ = info.location; 1588 *locations++ = info.location;
1635 memcpy(strings, info.name.c_str(), info.name.size()); 1589 memcpy(strings, info.name.c_str(), info.name.size());
1636 strings += info.name.size(); 1590 strings += info.name.size();
1637 ++inputs; 1591 ++inputs;
1638 } 1592 }
1639 1593
1640 for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) { 1594 for (const UniformInfo& info : uniform_infos_) {
1641 const UniformInfo& info = uniform_infos_[ii]; 1595 inputs->size = info.size;
1642 if (info.IsValid()) { 1596 inputs->type = info.type;
1643 inputs->size = info.size; 1597 inputs->location_offset = ComputeOffset(header, locations);
1644 inputs->type = info.type; 1598 inputs->name_offset = ComputeOffset(header, strings);
1645 inputs->location_offset = ComputeOffset(header, locations); 1599 inputs->name_length = info.name.size();
1646 inputs->name_offset = ComputeOffset(header, strings); 1600 DCHECK(static_cast<size_t>(info.size) == info.element_locations.size());
1647 inputs->name_length = info.name.size(); 1601 for (size_t jj = 0; jj < info.element_locations.size(); ++jj) {
1648 DCHECK(static_cast<size_t>(info.size) == info.element_locations.size()); 1602 if (info.element_locations[jj] == -1)
1649 for (size_t jj = 0; jj < info.element_locations.size(); ++jj) { 1603 *locations++ = -1;
1650 if (info.element_locations[jj] == -1) 1604 else
1651 *locations++ = -1; 1605 *locations++ =
1652 else 1606 ProgramManager::MakeFakeLocation(info.fake_location_base, jj);
1653 *locations++ = ProgramManager::MakeFakeLocation(ii, jj);
1654 }
1655 memcpy(strings, info.name.c_str(), info.name.size());
1656 strings += info.name.size();
1657 ++inputs;
1658 } 1607 }
1608 memcpy(strings, info.name.c_str(), info.name.size());
1609 strings += info.name.size();
1610 ++inputs;
1659 } 1611 }
1612 // NOTE: currently we do not pass inactive uniform binding locations
1613 // through the program info call.
1660 1614
1661 // NOTE: currently we do not pass fragment input infos through the program 1615 // NOTE: currently we do not pass fragment input infos through the program
1662 // info call, because they are not exposed through any getter function. 1616 // info call, because they are not exposed through any getter function.
1663 1617
1664 DCHECK_EQ(ComputeOffset(header, strings), size); 1618 DCHECK_EQ(ComputeOffset(header, strings), size);
1665 } 1619 }
1666 1620
1667 bool Program::GetUniformBlocks(CommonDecoder::Bucket* bucket) const { 1621 bool Program::GetUniformBlocks(CommonDecoder::Bucket* bucket) const {
1668 // The data is packed into the bucket in the following order 1622 // The data is packed into the bucket in the following order
1669 // 1) header 1623 // 1) header
(...skipping 433 matching lines...) Expand 10 before | Expand all | Expand 10 after
2103 DCHECK(program); 2057 DCHECK(program);
2104 program->ClearUniforms(&zero_); 2058 program->ClearUniforms(&zero_);
2105 } 2059 }
2106 2060
2107 int32 ProgramManager::MakeFakeLocation(int32 index, int32 element) { 2061 int32 ProgramManager::MakeFakeLocation(int32 index, int32 element) {
2108 return index + element * 0x10000; 2062 return index + element * 0x10000;
2109 } 2063 }
2110 2064
2111 } // namespace gles2 2065 } // namespace gles2
2112 } // namespace gpu 2066 } // namespace gpu
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698