| 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 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 271 | 271 |
| 272 void Program::Reset() { | 272 void Program::Reset() { |
| 273 valid_ = false; | 273 valid_ = false; |
| 274 link_status_ = false; | 274 link_status_ = false; |
| 275 max_uniform_name_length_ = 0; | 275 max_uniform_name_length_ = 0; |
| 276 max_attrib_name_length_ = 0; | 276 max_attrib_name_length_ = 0; |
| 277 attrib_infos_.clear(); | 277 attrib_infos_.clear(); |
| 278 uniform_infos_.clear(); | 278 uniform_infos_.clear(); |
| 279 uniform_locations_.clear(); | 279 uniform_locations_.clear(); |
| 280 fragment_input_infos_.clear(); | 280 fragment_input_infos_.clear(); |
| 281 fragment_input_locations_.clear(); |
| 281 sampler_indices_.clear(); | 282 sampler_indices_.clear(); |
| 282 attrib_location_to_index_map_.clear(); | 283 attrib_location_to_index_map_.clear(); |
| 283 } | 284 } |
| 284 | 285 |
| 285 std::string Program::ProcessLogInfo( | 286 std::string Program::ProcessLogInfo( |
| 286 const std::string& log) { | 287 const std::string& log) { |
| 287 std::string output; | 288 std::string output; |
| 288 re2::StringPiece input(log); | 289 re2::StringPiece input(log); |
| 289 std::string prior_log; | 290 std::string prior_log; |
| 290 std::string hashed_name; | 291 std::string hashed_name; |
| (...skipping 365 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 656 uniform_locations_[client_location_base].SetActive(&info); | 657 uniform_locations_[client_location_base].SetActive(&info); |
| 657 | 658 |
| 658 max_uniform_name_length_ = std::max(max_uniform_name_length_, | 659 max_uniform_name_length_ = std::max(max_uniform_name_length_, |
| 659 static_cast<GLsizei>(info.name.size())); | 660 static_cast<GLsizei>(info.name.size())); |
| 660 } | 661 } |
| 661 } | 662 } |
| 662 | 663 |
| 663 void Program::UpdateFragmentInputs() { | 664 void Program::UpdateFragmentInputs() { |
| 664 if (!feature_info().feature_flags().chromium_path_rendering) | 665 if (!feature_info().feature_flags().chromium_path_rendering) |
| 665 return; | 666 return; |
| 667 for (const auto& binding : bind_fragment_input_location_map_) { |
| 668 if (binding.second < 0) |
| 669 continue; |
| 670 size_t client_location = static_cast<size_t>(binding.second); |
| 671 if (fragment_input_locations_.size() <= client_location) |
| 672 fragment_input_locations_.resize(client_location + 1); |
| 673 fragment_input_locations_[client_location].SetInactive(); |
| 674 } |
| 675 |
| 666 GLint num_fragment_inputs = 0; | 676 GLint num_fragment_inputs = 0; |
| 667 glGetProgramInterfaceiv(service_id_, GL_FRAGMENT_INPUT_NV, | 677 glGetProgramInterfaceiv(service_id_, GL_FRAGMENT_INPUT_NV, |
| 668 GL_ACTIVE_RESOURCES, &num_fragment_inputs); | 678 GL_ACTIVE_RESOURCES, &num_fragment_inputs); |
| 669 if (num_fragment_inputs <= 0) | 679 if (num_fragment_inputs <= 0) |
| 670 return; | 680 return; |
| 681 |
| 671 GLint max_len = 0; | 682 GLint max_len = 0; |
| 672 glGetProgramInterfaceiv(service_id_, GL_FRAGMENT_INPUT_NV, GL_MAX_NAME_LENGTH, | 683 glGetProgramInterfaceiv(service_id_, GL_FRAGMENT_INPUT_NV, GL_MAX_NAME_LENGTH, |
| 673 &max_len); | 684 &max_len); |
| 674 DCHECK(max_len > 0); | 685 DCHECK(max_len > 0); |
| 675 | 686 |
| 676 scoped_ptr<char[]> name_buffer(new char[max_len]); | 687 scoped_ptr<char[]> name_buffer(new char[max_len]); |
| 677 | 688 |
| 678 Shader* fragment_shader = | 689 Shader* fragment_shader = |
| 679 attached_shaders_[ShaderTypeToIndex(GL_FRAGMENT_SHADER)].get(); | 690 attached_shaders_[ShaderTypeToIndex(GL_FRAGMENT_SHADER)].get(); |
| 680 | 691 |
| 681 const GLenum kQueryProperties[] = {GL_LOCATION, GL_TYPE, GL_ARRAY_SIZE}; | 692 const GLenum kQueryProperties[] = {GL_LOCATION, GL_TYPE, GL_ARRAY_SIZE}; |
| 682 | 693 |
| 694 std::vector<size_t> client_location_indices; |
| 683 for (GLint ii = 0; ii < num_fragment_inputs; ++ii) { | 695 for (GLint ii = 0; ii < num_fragment_inputs; ++ii) { |
| 684 GLsizei name_length = 0; | 696 GLsizei name_length = 0; |
| 685 glGetProgramResourceName(service_id_, GL_FRAGMENT_INPUT_NV, ii, max_len, | 697 glGetProgramResourceName(service_id_, GL_FRAGMENT_INPUT_NV, ii, max_len, |
| 686 &name_length, name_buffer.get()); | 698 &name_length, name_buffer.get()); |
| 687 DCHECK(name_length < max_len); | 699 DCHECK(name_length < max_len); |
| 688 DCHECK(name_length == 0 || name_buffer[name_length] == '\0'); | 700 DCHECK(name_length == 0 || name_buffer[name_length] == '\0'); |
| 689 // A fragment shader can have gl_FragCoord, gl_FrontFacing or gl_PointCoord | 701 // A fragment shader can have gl_FragCoord, gl_FrontFacing or gl_PointCoord |
| 690 // built-ins as its input, as well as custom varyings. We are interested in | 702 // built-ins as its input, as well as custom varyings. We are interested in |
| 691 // custom varyings, client is allowed to bind only them. | 703 // custom varyings, client is allowed to bind only them. |
| 692 if (ProgramManager::IsInvalidPrefix(name_buffer.get(), name_length)) | 704 if (ProgramManager::IsInvalidPrefix(name_buffer.get(), name_length)) |
| (...skipping 28 matching lines...) Expand all Loading... |
| 721 client_name = service_name; | 733 client_name = service_name; |
| 722 if (size <= 0) | 734 if (size <= 0) |
| 723 continue; | 735 continue; |
| 724 } | 736 } |
| 725 | 737 |
| 726 auto it = bind_fragment_input_location_map_.find(client_name); | 738 auto it = bind_fragment_input_location_map_.find(client_name); |
| 727 if (it != bind_fragment_input_location_map_.end() && it->second >= 0 && | 739 if (it != bind_fragment_input_location_map_.end() && it->second >= 0 && |
| 728 query_results[0] >= 0) { | 740 query_results[0] >= 0) { |
| 729 size_t client_location = static_cast<size_t>(it->second); | 741 size_t client_location = static_cast<size_t>(it->second); |
| 730 GLuint service_location = static_cast<GLuint>(query_results[0]); | 742 GLuint service_location = static_cast<GLuint>(query_results[0]); |
| 731 | 743 fragment_input_infos_.push_back( |
| 732 if (fragment_input_infos_.size() <= client_location) | 744 FragmentInputInfo(type, service_location)); |
| 733 fragment_input_infos_.resize(client_location + 1); | 745 client_location_indices.push_back(client_location); |
| 734 DCHECK(!fragment_input_infos_[client_location].IsValid()); | |
| 735 fragment_input_infos_[client_location] = | |
| 736 FragmentInputInfo(type, service_location); | |
| 737 } | 746 } |
| 738 | 747 |
| 739 if (size <= 1) | 748 if (size <= 1) |
| 740 continue; | 749 continue; |
| 741 GLSLArrayName parsed_client_name(client_name); | 750 GLSLArrayName parsed_client_name(client_name); |
| 742 GLSLArrayName parsed_service_name(service_name); | 751 GLSLArrayName parsed_service_name(service_name); |
| 743 if (!parsed_client_name.IsArrayName() || | 752 if (!parsed_client_name.IsArrayName() || |
| 744 parsed_client_name.element_index() != 0 || | 753 parsed_client_name.element_index() != 0 || |
| 745 !parsed_service_name.IsArrayName() || | 754 !parsed_service_name.IsArrayName() || |
| 746 parsed_service_name.element_index() != 0) { | 755 parsed_service_name.element_index() != 0) { |
| 747 NOTREACHED() << "GLSL array variable names should end with \"[0]\". " | 756 NOTREACHED() << "GLSL array variable names should end with \"[0]\". " |
| 748 "Likely driver or ANGLE error."; | 757 "Likely driver or ANGLE error."; |
| 749 continue; | 758 continue; |
| 750 } | 759 } |
| 751 | 760 |
| 752 for (GLsizei jj = 1; jj < size; ++jj) { | 761 for (GLsizei jj = 1; jj < size; ++jj) { |
| 753 std::string array_spec(std::string("[") + base::IntToString(jj) + "]"); | 762 std::string array_spec(std::string("[") + base::IntToString(jj) + "]"); |
| 754 std::string client_element_name = | 763 std::string client_element_name = |
| 755 parsed_client_name.base_name() + array_spec; | 764 parsed_client_name.base_name() + array_spec; |
| 756 | 765 |
| 757 auto it = bind_fragment_input_location_map_.find(client_element_name); | 766 auto it = bind_fragment_input_location_map_.find(client_element_name); |
| 758 if (it != bind_fragment_input_location_map_.end() && it->second >= 0) { | 767 if (it != bind_fragment_input_location_map_.end() && it->second >= 0) { |
| 759 size_t client_location = static_cast<size_t>(it->second); | 768 size_t client_location = static_cast<size_t>(it->second); |
| 760 std::string service_element_name = | 769 std::string service_element_name = |
| 761 parsed_service_name.base_name() + array_spec; | 770 parsed_service_name.base_name() + array_spec; |
| 762 GLint service_location = glGetProgramResourceLocation( | 771 GLint service_location = glGetProgramResourceLocation( |
| 763 service_id_, GL_FRAGMENT_INPUT_NV, service_element_name.c_str()); | 772 service_id_, GL_FRAGMENT_INPUT_NV, service_element_name.c_str()); |
| 764 if (service_location >= 0) { | 773 if (service_location >= 0) { |
| 765 if (fragment_input_infos_.size() <= client_location) | 774 fragment_input_infos_.push_back( |
| 766 fragment_input_infos_.resize(client_location + 1); | 775 FragmentInputInfo(type, static_cast<GLuint>(service_location))); |
| 767 DCHECK(!fragment_input_infos_[client_location].IsValid()); | 776 client_location_indices.push_back(client_location); |
| 768 fragment_input_infos_[client_location] = | |
| 769 FragmentInputInfo(type, static_cast<GLuint>(service_location)); | |
| 770 } | 777 } |
| 771 } | 778 } |
| 772 } | 779 } |
| 773 } | 780 } |
| 781 for (size_t i = 0; i < client_location_indices.size(); ++i) { |
| 782 size_t client_location = client_location_indices[i]; |
| 783 // Before linking, we already validated that no two statically used fragment |
| 784 // inputs are bound to the same location. |
| 785 DCHECK(!fragment_input_locations_[client_location].IsActive()); |
| 786 fragment_input_locations_[client_location].SetActive( |
| 787 &fragment_input_infos_[i]); |
| 788 } |
| 774 } | 789 } |
| 775 | 790 |
| 776 void Program::ExecuteBindAttribLocationCalls() { | 791 void Program::ExecuteBindAttribLocationCalls() { |
| 777 for (const auto& key_value : bind_attrib_location_map_) { | 792 for (const auto& key_value : bind_attrib_location_map_) { |
| 778 const std::string* mapped_name = GetAttribMappedName(key_value.first); | 793 const std::string* mapped_name = GetAttribMappedName(key_value.first); |
| 779 if (mapped_name) | 794 if (mapped_name) |
| 780 glBindAttribLocation(service_id_, key_value.second, mapped_name->c_str()); | 795 glBindAttribLocation(service_id_, key_value.second, mapped_name->c_str()); |
| 781 } | 796 } |
| 782 } | 797 } |
| 783 | 798 |
| (...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1017 if (fake_location < 0) | 1032 if (fake_location < 0) |
| 1018 return nullptr; | 1033 return nullptr; |
| 1019 size_t location_index = | 1034 size_t location_index = |
| 1020 GetUniformLocationIndexFromFakeLocation(fake_location); | 1035 GetUniformLocationIndexFromFakeLocation(fake_location); |
| 1021 if (location_index >= uniform_locations_.size()) | 1036 if (location_index >= uniform_locations_.size()) |
| 1022 return nullptr; | 1037 return nullptr; |
| 1023 | 1038 |
| 1024 if (!uniform_locations_[location_index].IsActive()) | 1039 if (!uniform_locations_[location_index].IsActive()) |
| 1025 return nullptr; | 1040 return nullptr; |
| 1026 | 1041 |
| 1027 const UniformInfo* info = uniform_locations_[location_index].uniform(); | 1042 const UniformInfo* info = |
| 1043 uniform_locations_[location_index].shader_variable(); |
| 1028 size_t element_index = GetArrayElementIndexFromFakeLocation(fake_location); | 1044 size_t element_index = GetArrayElementIndexFromFakeLocation(fake_location); |
| 1029 if (static_cast<GLsizei>(element_index) >= info->size) | 1045 if (static_cast<GLsizei>(element_index) >= info->size) |
| 1030 return nullptr; | 1046 return nullptr; |
| 1031 *real_location = info->element_locations[element_index]; | 1047 *real_location = info->element_locations[element_index]; |
| 1032 *array_index = element_index; | 1048 *array_index = element_index; |
| 1033 return info; | 1049 return info; |
| 1034 } | 1050 } |
| 1035 | 1051 |
| 1036 bool Program::IsInactiveUniformLocationByFakeLocation( | 1052 bool Program::IsInactiveUniformLocationByFakeLocation( |
| 1037 GLint fake_location) const { | 1053 GLint fake_location) const { |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1078 shader->GetOriginalNameFromHashedName(hashed_name); | 1094 shader->GetOriginalNameFromHashedName(hashed_name); |
| 1079 if (original_name) | 1095 if (original_name) |
| 1080 return original_name; | 1096 return original_name; |
| 1081 } | 1097 } |
| 1082 } | 1098 } |
| 1083 return nullptr; | 1099 return nullptr; |
| 1084 } | 1100 } |
| 1085 | 1101 |
| 1086 const Program::FragmentInputInfo* Program::GetFragmentInputInfoByFakeLocation( | 1102 const Program::FragmentInputInfo* Program::GetFragmentInputInfoByFakeLocation( |
| 1087 GLint fake_location) const { | 1103 GLint fake_location) const { |
| 1088 if (fake_location < 0 || | 1104 if (fake_location < 0) |
| 1089 static_cast<size_t>(fake_location) >= fragment_input_infos_.size()) | |
| 1090 return nullptr; | 1105 return nullptr; |
| 1091 const FragmentInputInfo* info = &fragment_input_infos_[fake_location]; | 1106 size_t location_index = static_cast<size_t>(fake_location); |
| 1092 if (!info->IsValid()) | 1107 if (location_index >= fragment_input_locations_.size()) |
| 1093 return nullptr; | 1108 return nullptr; |
| 1094 return info; | 1109 if (!fragment_input_locations_[location_index].IsActive()) |
| 1110 return nullptr; |
| 1111 return fragment_input_locations_[location_index].shader_variable(); |
| 1112 } |
| 1113 |
| 1114 bool Program::IsInactiveFragmentInputLocationByFakeLocation( |
| 1115 GLint fake_location) const { |
| 1116 if (fake_location < 0) |
| 1117 return true; |
| 1118 size_t location_index = static_cast<size_t>(fake_location); |
| 1119 if (location_index >= fragment_input_locations_.size()) |
| 1120 return false; |
| 1121 return fragment_input_locations_[location_index].IsInactive(); |
| 1095 } | 1122 } |
| 1096 | 1123 |
| 1097 bool Program::SetUniformLocationBinding( | 1124 bool Program::SetUniformLocationBinding( |
| 1098 const std::string& name, GLint location) { | 1125 const std::string& name, GLint location) { |
| 1099 std::string short_name; | 1126 std::string short_name; |
| 1100 int element_index = 0; | 1127 int element_index = 0; |
| 1101 if (!GetUniformNameSansElement(name, &element_index, &short_name) || | 1128 if (!GetUniformNameSansElement(name, &element_index, &short_name) || |
| 1102 element_index != 0) { | 1129 element_index != 0) { |
| 1103 return false; | 1130 return false; |
| 1104 } | 1131 } |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1220 return true; | 1247 return true; |
| 1221 } | 1248 } |
| 1222 size_t location_index = | 1249 size_t location_index = |
| 1223 GetUniformLocationIndexFromFakeLocation(fake_location); | 1250 GetUniformLocationIndexFromFakeLocation(fake_location); |
| 1224 if (location_index >= uniform_infos_.size()) | 1251 if (location_index >= uniform_infos_.size()) |
| 1225 return false; | 1252 return false; |
| 1226 | 1253 |
| 1227 if (!uniform_locations_[location_index].IsActive()) | 1254 if (!uniform_locations_[location_index].IsActive()) |
| 1228 return false; | 1255 return false; |
| 1229 | 1256 |
| 1230 UniformInfo* info = uniform_locations_[location_index].uniform(); | 1257 UniformInfo* info = uniform_locations_[location_index].shader_variable(); |
| 1231 | 1258 |
| 1232 size_t element_index = GetArrayElementIndexFromFakeLocation(fake_location); | 1259 size_t element_index = GetArrayElementIndexFromFakeLocation(fake_location); |
| 1233 if (static_cast<GLsizei>(element_index) >= info->size) | 1260 if (static_cast<GLsizei>(element_index) >= info->size) |
| 1234 return true; | 1261 return true; |
| 1235 count = std::min(info->size - static_cast<GLsizei>(element_index), count); | 1262 count = std::min(info->size - static_cast<GLsizei>(element_index), count); |
| 1236 if (info->IsSampler() && count > 0) { | 1263 if (info->IsSampler() && count > 0) { |
| 1237 for (GLsizei ii = 0; ii < count; ++ii) { | 1264 for (GLsizei ii = 0; ii < count; ++ii) { |
| 1238 if (value[ii] < 0 || value[ii] >= num_texture_units) { | 1265 if (value[ii] < 0 || value[ii] >= num_texture_units) { |
| 1239 return false; | 1266 return false; |
| 1240 } | 1267 } |
| (...skipping 885 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2126 DCHECK(program); | 2153 DCHECK(program); |
| 2127 program->ClearUniforms(&zero_); | 2154 program->ClearUniforms(&zero_); |
| 2128 } | 2155 } |
| 2129 | 2156 |
| 2130 int32 ProgramManager::MakeFakeLocation(int32 index, int32 element) { | 2157 int32 ProgramManager::MakeFakeLocation(int32 index, int32 element) { |
| 2131 return index + element * 0x10000; | 2158 return index + element * 0x10000; |
| 2132 } | 2159 } |
| 2133 | 2160 |
| 2134 } // namespace gles2 | 2161 } // namespace gles2 |
| 2135 } // namespace gpu | 2162 } // namespace gpu |
| OLD | NEW |