Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 |
| OLD | NEW |