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 10 matching lines...) Expand all Loading... |
21 #include "base/strings/stringprintf.h" | 21 #include "base/strings/stringprintf.h" |
22 #include "base/time/time.h" | 22 #include "base/time/time.h" |
23 #include "gpu/command_buffer/common/gles2_cmd_format.h" | 23 #include "gpu/command_buffer/common/gles2_cmd_format.h" |
24 #include "gpu/command_buffer/common/gles2_cmd_utils.h" | 24 #include "gpu/command_buffer/common/gles2_cmd_utils.h" |
25 #include "gpu/command_buffer/service/feature_info.h" | 25 #include "gpu/command_buffer/service/feature_info.h" |
26 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" | 26 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
27 #include "gpu/command_buffer/service/gpu_switches.h" | 27 #include "gpu/command_buffer/service/gpu_switches.h" |
28 #include "gpu/command_buffer/service/program_cache.h" | 28 #include "gpu/command_buffer/service/program_cache.h" |
29 #include "gpu/command_buffer/service/shader_manager.h" | 29 #include "gpu/command_buffer/service/shader_manager.h" |
30 #include "third_party/re2/re2/re2.h" | 30 #include "third_party/re2/re2/re2.h" |
| 31 #include "ui/gl/gl_version_info.h" |
31 | 32 |
32 using base::TimeDelta; | 33 using base::TimeDelta; |
33 using base::TimeTicks; | 34 using base::TimeTicks; |
34 | 35 |
35 namespace gpu { | 36 namespace gpu { |
36 namespace gles2 { | 37 namespace gles2 { |
37 | 38 |
38 namespace { | 39 namespace { |
39 | 40 |
40 int ShaderTypeToIndex(GLenum shader_type) { | 41 int ShaderTypeToIndex(GLenum shader_type) { |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
242 } | 243 } |
243 DCHECK_LT(0, size); | 244 DCHECK_LT(0, size); |
244 DCHECK(is_array || size == 1); | 245 DCHECK(is_array || size == 1); |
245 | 246 |
246 size_t num_texture_units = IsSampler() ? static_cast<size_t>(size) : 0u; | 247 size_t num_texture_units = IsSampler() ? static_cast<size_t>(size) : 0u; |
247 texture_units.clear(); | 248 texture_units.clear(); |
248 texture_units.resize(num_texture_units, 0); | 249 texture_units.resize(num_texture_units, 0); |
249 } | 250 } |
250 Program::UniformInfo::~UniformInfo() {} | 251 Program::UniformInfo::~UniformInfo() {} |
251 | 252 |
252 bool ProgramManager::IsInvalidPrefix(const char* name, size_t length) { | 253 bool ProgramManager::HasBuiltInPrefix(const std::string& name) { |
253 static const char kInvalidPrefix[] = { 'g', 'l', '_' }; | 254 return name.length() >= 3 && name[0] == 'g' && name[1] == 'l' && |
254 return (length >= sizeof(kInvalidPrefix) && | 255 name[2] == '_'; |
255 memcmp(name, kInvalidPrefix, sizeof(kInvalidPrefix)) == 0); | |
256 } | 256 } |
257 | 257 |
258 Program::Program(ProgramManager* manager, GLuint service_id) | 258 Program::Program(ProgramManager* manager, GLuint service_id) |
259 : manager_(manager), | 259 : manager_(manager), |
260 use_count_(0), | 260 use_count_(0), |
261 max_attrib_name_length_(0), | 261 max_attrib_name_length_(0), |
262 max_uniform_name_length_(0), | 262 max_uniform_name_length_(0), |
263 service_id_(service_id), | 263 service_id_(service_id), |
264 deleted_(false), | 264 deleted_(false), |
265 valid_(false), | 265 valid_(false), |
266 link_status_(false), | 266 link_status_(false), |
267 uniforms_cleared_(false), | 267 uniforms_cleared_(false), |
268 transform_feedback_buffer_mode_(GL_NONE) { | 268 transform_feedback_buffer_mode_(GL_NONE) { |
269 manager_->StartTracking(this); | 269 manager_->StartTracking(this); |
270 } | 270 } |
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 fragment_input_locations_.clear(); |
| 282 program_output_infos_.clear(); |
282 sampler_indices_.clear(); | 283 sampler_indices_.clear(); |
283 attrib_location_to_index_map_.clear(); | 284 attrib_location_to_index_map_.clear(); |
284 } | 285 } |
285 | 286 |
286 std::string Program::ProcessLogInfo( | 287 std::string Program::ProcessLogInfo( |
287 const std::string& log) { | 288 const std::string& log) { |
288 std::string output; | 289 std::string output; |
289 re2::StringPiece input(log); | 290 re2::StringPiece input(log); |
290 std::string prior_log; | 291 std::string prior_log; |
291 std::string hashed_name; | 292 std::string hashed_name; |
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
512 for (const UniformInfo& info : uniform_infos_) { | 513 for (const UniformInfo& info : uniform_infos_) { |
513 DVLOG(1) << ii++ << ": loc = " << info.element_locations[0] | 514 DVLOG(1) << ii++ << ": loc = " << info.element_locations[0] |
514 << ", size = " << info.size | 515 << ", size = " << info.size |
515 << ", type = " << GLES2Util::GetStringEnum(info.type) | 516 << ", type = " << GLES2Util::GetStringEnum(info.type) |
516 << ", name = " << info.name; | 517 << ", name = " << info.name; |
517 } | 518 } |
518 } | 519 } |
519 #endif | 520 #endif |
520 | 521 |
521 UpdateFragmentInputs(); | 522 UpdateFragmentInputs(); |
| 523 UpdateProgramOutputs(); |
522 | 524 |
523 valid_ = true; | 525 valid_ = true; |
524 } | 526 } |
525 | 527 |
526 void Program::UpdateUniforms() { | 528 void Program::UpdateUniforms() { |
527 // Reserve each client-bound uniform location. This way unbound uniforms will | 529 // Reserve each client-bound uniform location. This way unbound uniforms will |
528 // not be allocated to locations that user expects bound uniforms to be, even | 530 // not be allocated to locations that user expects bound uniforms to be, even |
529 // if the expected uniforms are optimized away by the driver. | 531 // if the expected uniforms are optimized away by the driver. |
530 for (const auto& binding : bind_uniform_location_map_) { | 532 for (const auto& binding : bind_uniform_location_map_) { |
531 if (binding.second < 0) | 533 if (binding.second < 0) |
(...skipping 24 matching lines...) Expand all Loading... |
556 GLsizei size = 0; | 558 GLsizei size = 0; |
557 GLenum type = GL_NONE; | 559 GLenum type = GL_NONE; |
558 glGetActiveUniform(service_id_, uniform_index, name_buffer_length, | 560 glGetActiveUniform(service_id_, uniform_index, name_buffer_length, |
559 &name_length, &size, &type, name_buffer.get()); | 561 &name_length, &size, &type, name_buffer.get()); |
560 DCHECK(name_length < name_buffer_length); | 562 DCHECK(name_length < name_buffer_length); |
561 DCHECK(name_length == 0 || name_buffer[name_length] == '\0'); | 563 DCHECK(name_length == 0 || name_buffer[name_length] == '\0'); |
562 std::string service_name(name_buffer.get(), name_length); | 564 std::string service_name(name_buffer.get(), name_length); |
563 | 565 |
564 GLint service_location = -1; | 566 GLint service_location = -1; |
565 // Force builtin uniforms (gl_DepthRange) to have invalid location. | 567 // Force builtin uniforms (gl_DepthRange) to have invalid location. |
566 if (!ProgramManager::IsInvalidPrefix(service_name.c_str(), | 568 if (!ProgramManager::HasBuiltInPrefix(service_name)) { |
567 service_name.size())) { | |
568 service_location = | 569 service_location = |
569 glGetUniformLocation(service_id_, service_name.c_str()); | 570 glGetUniformLocation(service_id_, service_name.c_str()); |
570 } | 571 } |
571 | 572 |
572 // Determine the client name of the uniform and whether it is an array | 573 // Determine the client name of the uniform and whether it is an array |
573 // or not. | 574 // or not. |
574 bool is_array = false; | 575 bool is_array = false; |
575 std::string client_name; | 576 std::string client_name; |
576 for (size_t i = 0; i < kMaxAttachedShaders && client_name.empty(); ++i) { | 577 for (size_t i = 0; i < kMaxAttachedShaders && client_name.empty(); ++i) { |
577 const auto& shader = attached_shaders_[i]; | 578 const auto& shader = attached_shaders_[i]; |
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
694 std::vector<size_t> client_location_indices; | 695 std::vector<size_t> client_location_indices; |
695 for (GLint ii = 0; ii < num_fragment_inputs; ++ii) { | 696 for (GLint ii = 0; ii < num_fragment_inputs; ++ii) { |
696 GLsizei name_length = 0; | 697 GLsizei name_length = 0; |
697 glGetProgramResourceName(service_id_, GL_FRAGMENT_INPUT_NV, ii, max_len, | 698 glGetProgramResourceName(service_id_, GL_FRAGMENT_INPUT_NV, ii, max_len, |
698 &name_length, name_buffer.get()); | 699 &name_length, name_buffer.get()); |
699 DCHECK(name_length < max_len); | 700 DCHECK(name_length < max_len); |
700 DCHECK(name_length == 0 || name_buffer[name_length] == '\0'); | 701 DCHECK(name_length == 0 || name_buffer[name_length] == '\0'); |
701 // A fragment shader can have gl_FragCoord, gl_FrontFacing or gl_PointCoord | 702 // A fragment shader can have gl_FragCoord, gl_FrontFacing or gl_PointCoord |
702 // built-ins as its input, as well as custom varyings. We are interested in | 703 // built-ins as its input, as well as custom varyings. We are interested in |
703 // custom varyings, client is allowed to bind only them. | 704 // custom varyings, client is allowed to bind only them. |
704 if (ProgramManager::IsInvalidPrefix(name_buffer.get(), name_length)) | 705 std::string service_name(name_buffer.get(), name_length); |
| 706 if (ProgramManager::HasBuiltInPrefix(service_name)) |
705 continue; | 707 continue; |
706 std::string service_name(name_buffer.get(), name_length); | |
707 // Unlike when binding uniforms, we expect the driver to give correct | 708 // Unlike when binding uniforms, we expect the driver to give correct |
708 // names: "name" for simple variable, "name[0]" for an array. | 709 // names: "name" for simple variable, "name[0]" for an array. |
709 GLsizei query_length = 0; | 710 GLsizei query_length = 0; |
710 GLint query_results[arraysize(kQueryProperties)] = { | 711 GLint query_results[arraysize(kQueryProperties)] = { |
711 0, | 712 0, |
712 }; | 713 }; |
713 glGetProgramResourceiv(service_id_, GL_FRAGMENT_INPUT_NV, ii, | 714 glGetProgramResourceiv(service_id_, GL_FRAGMENT_INPUT_NV, ii, |
714 arraysize(kQueryProperties), kQueryProperties, | 715 arraysize(kQueryProperties), kQueryProperties, |
715 arraysize(query_results), &query_length, | 716 arraysize(query_results), &query_length, |
716 query_results); | 717 query_results); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
781 for (size_t i = 0; i < client_location_indices.size(); ++i) { | 782 for (size_t i = 0; i < client_location_indices.size(); ++i) { |
782 size_t client_location = client_location_indices[i]; | 783 size_t client_location = client_location_indices[i]; |
783 // Before linking, we already validated that no two statically used fragment | 784 // Before linking, we already validated that no two statically used fragment |
784 // inputs are bound to the same location. | 785 // inputs are bound to the same location. |
785 DCHECK(!fragment_input_locations_[client_location].IsActive()); | 786 DCHECK(!fragment_input_locations_[client_location].IsActive()); |
786 fragment_input_locations_[client_location].SetActive( | 787 fragment_input_locations_[client_location].SetActive( |
787 &fragment_input_infos_[i]); | 788 &fragment_input_infos_[i]); |
788 } | 789 } |
789 } | 790 } |
790 | 791 |
| 792 void Program::UpdateProgramOutputs() { |
| 793 if (!feature_info().gl_version_info().IsES3Capable() || |
| 794 feature_info().disable_shader_translator()) |
| 795 return; |
| 796 |
| 797 Shader* fragment_shader = |
| 798 attached_shaders_[ShaderTypeToIndex(GL_FRAGMENT_SHADER)].get(); |
| 799 |
| 800 for (auto const& output_var : fragment_shader->output_variable_list()) { |
| 801 const std::string& service_name = output_var.mappedName; |
| 802 // A fragment shader can have gl_FragColor, gl_SecondaryFragColor, etc |
| 803 // built-ins as its output, as well as custom varyings. We are interested |
| 804 // only in custom varyings, client is allowed to bind only them. |
| 805 if (ProgramManager::HasBuiltInPrefix(service_name)) |
| 806 continue; |
| 807 |
| 808 std::string client_name = output_var.name; |
| 809 if (output_var.arraySize == 0) { |
| 810 GLint color_name = |
| 811 glGetFragDataLocation(service_id_, service_name.c_str()); |
| 812 if (color_name < 0) |
| 813 continue; |
| 814 GLint index = 0; |
| 815 if (feature_info().feature_flags().ext_blend_func_extended) |
| 816 index = glGetFragDataIndex(service_id_, service_name.c_str()); |
| 817 if (index < 0) |
| 818 continue; |
| 819 program_output_infos_.push_back( |
| 820 ProgramOutputInfo(color_name, index, client_name)); |
| 821 } else { |
| 822 for (size_t ii = 0; ii < output_var.arraySize; ++ii) { |
| 823 std::string array_spec(std::string("[") + base::IntToString(ii) + "]"); |
| 824 std::string service_element_name(service_name + array_spec); |
| 825 GLint color_name = |
| 826 glGetFragDataLocation(service_id_, service_element_name.c_str()); |
| 827 if (color_name < 0) |
| 828 continue; |
| 829 GLint index = 0; |
| 830 if (feature_info().feature_flags().ext_blend_func_extended) |
| 831 index = glGetFragDataIndex(service_id_, service_element_name.c_str()); |
| 832 if (index < 0) |
| 833 continue; |
| 834 program_output_infos_.push_back( |
| 835 ProgramOutputInfo(color_name, index, client_name + array_spec)); |
| 836 } |
| 837 } |
| 838 } |
| 839 } |
| 840 |
791 void Program::ExecuteBindAttribLocationCalls() { | 841 void Program::ExecuteBindAttribLocationCalls() { |
792 for (const auto& key_value : bind_attrib_location_map_) { | 842 for (const auto& key_value : bind_attrib_location_map_) { |
793 const std::string* mapped_name = GetAttribMappedName(key_value.first); | 843 const std::string* mapped_name = GetAttribMappedName(key_value.first); |
794 if (mapped_name) | 844 if (mapped_name) |
795 glBindAttribLocation(service_id_, key_value.second, mapped_name->c_str()); | 845 glBindAttribLocation(service_id_, key_value.second, mapped_name->c_str()); |
796 } | 846 } |
797 } | 847 } |
798 | 848 |
799 bool Program::ExecuteTransformFeedbackVaryingsCall() { | 849 bool Program::ExecuteTransformFeedbackVaryingsCall() { |
800 if (!transform_feedback_varyings_.empty()) { | 850 if (!transform_feedback_varyings_.empty()) { |
(...skipping 19 matching lines...) Expand all Loading... |
820 } | 870 } |
821 glTransformFeedbackVaryings(service_id_, | 871 glTransformFeedbackVaryings(service_id_, |
822 mapped_names.size(), | 872 mapped_names.size(), |
823 &mapped_names.front(), | 873 &mapped_names.front(), |
824 transform_feedback_buffer_mode_); | 874 transform_feedback_buffer_mode_); |
825 } | 875 } |
826 | 876 |
827 return true; | 877 return true; |
828 } | 878 } |
829 | 879 |
| 880 void Program::ExecuteProgramOutputBindCalls() { |
| 881 if (feature_info().disable_shader_translator()) { |
| 882 return; |
| 883 } |
| 884 |
| 885 Shader* fragment_shader = |
| 886 attached_shaders_[ShaderTypeToIndex(GL_FRAGMENT_SHADER)].get(); |
| 887 DCHECK(fragment_shader && fragment_shader->valid()); |
| 888 |
| 889 if (fragment_shader->shader_version() != 100) { |
| 890 // ES SL 1.00 does not have mechanism for introducing variables that could |
| 891 // be bound. This means that ES SL 1.00 binding calls would be to |
| 892 // non-existing variable names. Binding calls are only executed with ES SL |
| 893 // 3.00 and higher. |
| 894 for (auto const& output_var : fragment_shader->output_variable_list()) { |
| 895 size_t count = std::max(output_var.arraySize, 1u); |
| 896 bool is_array = output_var.arraySize > 0; |
| 897 |
| 898 for (size_t jj = 0; jj < count; ++jj) { |
| 899 std::string name = output_var.name; |
| 900 std::string array_spec; |
| 901 if (is_array) { |
| 902 array_spec = std::string("[") + base::IntToString(jj) + "]"; |
| 903 name += array_spec; |
| 904 } |
| 905 auto it = bind_program_output_location_index_map_.find(name); |
| 906 if (it == bind_program_output_location_index_map_.end()) |
| 907 continue; |
| 908 |
| 909 std::string mapped_name = output_var.mappedName; |
| 910 if (is_array) { |
| 911 mapped_name += array_spec; |
| 912 } |
| 913 const auto& binding = it->second; |
| 914 if (binding.second == 0) { |
| 915 // Handles the cases where client called glBindFragDataLocation as |
| 916 // well as glBindFragDataLocationIndexed with index == 0. |
| 917 glBindFragDataLocation(service_id_, binding.first, |
| 918 mapped_name.c_str()); |
| 919 } else { |
| 920 DCHECK(feature_info().feature_flags().ext_blend_func_extended); |
| 921 glBindFragDataLocationIndexed(service_id_, binding.first, |
| 922 binding.second, mapped_name.c_str()); |
| 923 } |
| 924 } |
| 925 } |
| 926 return; |
| 927 } |
| 928 |
| 929 // Support for EXT_blend_func_extended when used with ES SL 1.00 client |
| 930 // shader. |
| 931 |
| 932 if (feature_info().gl_version_info().is_es || |
| 933 !feature_info().feature_flags().ext_blend_func_extended) |
| 934 return; |
| 935 |
| 936 // The underlying context does not support EXT_blend_func_extended |
| 937 // natively, need to emulate it. |
| 938 |
| 939 // ES SL 1.00 is the only language which contains GLSL built-ins |
| 940 // that need to be bound to color indices. If clients use other |
| 941 // languages, they also bind the output variables themselves. |
| 942 // Map gl_SecondaryFragColorEXT / gl_SecondaryFragDataEXT of |
| 943 // EXT_blend_func_extended to real color indexes. |
| 944 for (auto const& output_var : fragment_shader->output_variable_list()) { |
| 945 const std::string& name = output_var.mappedName; |
| 946 if (name == "gl_FragColor") { |
| 947 DCHECK_EQ(-1, output_var.location); |
| 948 DCHECK_EQ(0u, output_var.arraySize); |
| 949 // We leave these unbound by not giving a binding name. The driver will |
| 950 // bind this. |
| 951 } else if (name == "gl_FragData") { |
| 952 DCHECK_EQ(-1, output_var.location); |
| 953 DCHECK_NE(0u, output_var.arraySize); |
| 954 // We leave these unbound by not giving a binding name. The driver will |
| 955 // bind this. |
| 956 } else if (name == "gl_SecondaryFragColorEXT") { |
| 957 DCHECK_EQ(-1, output_var.location); |
| 958 DCHECK_EQ(0u, output_var.arraySize); |
| 959 glBindFragDataLocationIndexed(service_id_, 0, 1, |
| 960 "angle_SecondaryFragColor"); |
| 961 } else if (name == "gl_SecondaryFragDataEXT") { |
| 962 DCHECK_EQ(-1, output_var.location); |
| 963 DCHECK_NE(0u, output_var.arraySize); |
| 964 glBindFragDataLocationIndexed(service_id_, 0, 1, |
| 965 "angle_SecondaryFragData"); |
| 966 } |
| 967 } |
| 968 } |
| 969 |
830 bool Program::Link(ShaderManager* manager, | 970 bool Program::Link(ShaderManager* manager, |
831 Program::VaryingsPackingOption varyings_packing_option, | 971 Program::VaryingsPackingOption varyings_packing_option, |
832 const ShaderCacheCallback& shader_callback) { | 972 const ShaderCacheCallback& shader_callback) { |
833 ClearLinkStatus(); | 973 ClearLinkStatus(); |
834 | 974 |
835 if (!AttachedShadersExist()) { | 975 if (!AttachedShadersExist()) { |
836 set_log_info("missing shaders"); | 976 set_log_info("missing shaders"); |
837 return false; | 977 return false; |
838 } | 978 } |
839 | 979 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
898 "or statically used varyings in fragment shader " | 1038 "or statically used varyings in fragment shader " |
899 "are not declared in vertex shader: " + | 1039 "are not declared in vertex shader: " + |
900 conflicting_name; | 1040 conflicting_name; |
901 set_log_info(ProcessLogInfo(info_log).c_str()); | 1041 set_log_info(ProcessLogInfo(info_log).c_str()); |
902 return false; | 1042 return false; |
903 } | 1043 } |
904 if (DetectFragmentInputLocationBindingConflicts()) { | 1044 if (DetectFragmentInputLocationBindingConflicts()) { |
905 set_log_info("glBindFragmentInputLocationCHROMIUM() conflicts"); | 1045 set_log_info("glBindFragmentInputLocationCHROMIUM() conflicts"); |
906 return false; | 1046 return false; |
907 } | 1047 } |
| 1048 if (DetectProgramOutputLocationBindingConflicts()) { |
| 1049 set_log_info("glBindFragDataLocation() conflicts"); |
| 1050 return false; |
| 1051 } |
908 if (DetectBuiltInInvariantConflicts()) { | 1052 if (DetectBuiltInInvariantConflicts()) { |
909 set_log_info("Invariant settings for certain built-in varyings " | 1053 set_log_info("Invariant settings for certain built-in varyings " |
910 "have to match"); | 1054 "have to match"); |
911 return false; | 1055 return false; |
912 } | 1056 } |
913 if (DetectGlobalNameConflicts(&conflicting_name)) { | 1057 if (DetectGlobalNameConflicts(&conflicting_name)) { |
914 std::string info_log = "Name conflicts between an uniform and an " | 1058 std::string info_log = "Name conflicts between an uniform and an " |
915 "attribute: " + conflicting_name; | 1059 "attribute: " + conflicting_name; |
916 set_log_info(ProcessLogInfo(info_log).c_str()); | 1060 set_log_info(ProcessLogInfo(info_log).c_str()); |
917 return false; | 1061 return false; |
918 } | 1062 } |
919 if (!CheckVaryingsPacking(varyings_packing_option)) { | 1063 if (!CheckVaryingsPacking(varyings_packing_option)) { |
920 set_log_info("Varyings over maximum register limit"); | 1064 set_log_info("Varyings over maximum register limit"); |
921 return false; | 1065 return false; |
922 } | 1066 } |
923 | 1067 |
924 ExecuteBindAttribLocationCalls(); | 1068 ExecuteBindAttribLocationCalls(); |
925 if (!ExecuteTransformFeedbackVaryingsCall()) { | 1069 if (!ExecuteTransformFeedbackVaryingsCall()) { |
926 return false; | 1070 return false; |
927 } | 1071 } |
| 1072 |
| 1073 ExecuteProgramOutputBindCalls(); |
| 1074 |
928 before_time = TimeTicks::Now(); | 1075 before_time = TimeTicks::Now(); |
929 if (cache && gfx::g_driver_gl.ext.b_GL_ARB_get_program_binary) { | 1076 if (cache && gfx::g_driver_gl.ext.b_GL_ARB_get_program_binary) { |
930 glProgramParameteri(service_id(), | 1077 glProgramParameteri(service_id(), |
931 PROGRAM_BINARY_RETRIEVABLE_HINT, | 1078 PROGRAM_BINARY_RETRIEVABLE_HINT, |
932 GL_TRUE); | 1079 GL_TRUE); |
933 } | 1080 } |
934 glLinkProgram(service_id()); | 1081 glLinkProgram(service_id()); |
935 } | 1082 } |
936 | 1083 |
937 GLint success = 0; | 1084 GLint success = 0; |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1141 // string would exactly match the name of the variable if the suffix "[0]" | 1288 // string would exactly match the name of the variable if the suffix "[0]" |
1142 // were appended to the string". | 1289 // were appended to the string". |
1143 | 1290 |
1144 // At this point we can not know if the string identifies a simple variable, | 1291 // At this point we can not know if the string identifies a simple variable, |
1145 // a base name of an array, or nothing. Store both, so if user overwrites | 1292 // a base name of an array, or nothing. Store both, so if user overwrites |
1146 // either, both still work correctly. | 1293 // either, both still work correctly. |
1147 bind_fragment_input_location_map_[name] = location; | 1294 bind_fragment_input_location_map_[name] = location; |
1148 bind_fragment_input_location_map_[name + "[0]"] = location; | 1295 bind_fragment_input_location_map_[name + "[0]"] = location; |
1149 } | 1296 } |
1150 | 1297 |
| 1298 void Program::SetProgramOutputLocationBinding(const std::string& name, |
| 1299 GLuint color_name) { |
| 1300 SetProgramOutputLocationIndexedBinding(name, color_name, 0); |
| 1301 } |
| 1302 |
| 1303 void Program::SetProgramOutputLocationIndexedBinding(const std::string& name, |
| 1304 GLuint color_name, |
| 1305 GLuint index) { |
| 1306 bind_program_output_location_index_map_[name] = |
| 1307 std::make_pair(color_name, index); |
| 1308 bind_program_output_location_index_map_[name + "[0]"] = |
| 1309 std::make_pair(color_name, index); |
| 1310 } |
| 1311 |
1151 void Program::GetVertexAttribData( | 1312 void Program::GetVertexAttribData( |
1152 const std::string& name, std::string* original_name, GLenum* type) const { | 1313 const std::string& name, std::string* original_name, GLenum* type) const { |
1153 DCHECK(original_name); | 1314 DCHECK(original_name); |
1154 DCHECK(type); | 1315 DCHECK(type); |
1155 Shader* shader = attached_shaders_[ShaderTypeToIndex(GL_VERTEX_SHADER)].get(); | 1316 Shader* shader = attached_shaders_[ShaderTypeToIndex(GL_VERTEX_SHADER)].get(); |
1156 if (shader) { | 1317 if (shader) { |
1157 // Vertex attributes can not be arrays or structs (GLSL ES 3.00.4, section | 1318 // Vertex attributes can not be arrays or structs (GLSL ES 3.00.4, section |
1158 // 4.3.4, "Input Variables"), so the top level sh::Attribute returns the | 1319 // 4.3.4, "Input Variables"), so the top level sh::Attribute returns the |
1159 // information we need. | 1320 // information we need. |
1160 const sh::Attribute* info = shader->GetAttribInfo(name); | 1321 const sh::Attribute* info = shader->GetAttribInfo(name); |
(...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1534 const sh::Varying* fragment_input = shader->GetVaryingInfo(*mapped_name); | 1695 const sh::Varying* fragment_input = shader->GetVaryingInfo(*mapped_name); |
1535 if (fragment_input && fragment_input->staticUse) { | 1696 if (fragment_input && fragment_input->staticUse) { |
1536 auto result = location_binding_used.insert(it.second); | 1697 auto result = location_binding_used.insert(it.second); |
1537 if (!result.second) | 1698 if (!result.second) |
1538 return true; | 1699 return true; |
1539 } | 1700 } |
1540 } | 1701 } |
1541 return false; | 1702 return false; |
1542 } | 1703 } |
1543 | 1704 |
| 1705 bool Program::DetectProgramOutputLocationBindingConflicts() const { |
| 1706 if (feature_info().disable_shader_translator()) { |
| 1707 return false; |
| 1708 } |
| 1709 |
| 1710 Shader* shader = |
| 1711 attached_shaders_[ShaderTypeToIndex(GL_FRAGMENT_SHADER)].get(); |
| 1712 DCHECK(shader && shader->valid()); |
| 1713 |
| 1714 if (shader->shader_version() == 100) |
| 1715 return false; |
| 1716 |
| 1717 std::set<LocationIndexMap::mapped_type> location_binding_used; |
| 1718 for (auto const& output_var : shader->output_variable_list()) { |
| 1719 if (!output_var.staticUse) |
| 1720 continue; |
| 1721 |
| 1722 size_t count = std::max(output_var.arraySize, 1u); |
| 1723 bool is_array = output_var.arraySize > 0; |
| 1724 |
| 1725 for (size_t jj = 0; jj < count; ++jj) { |
| 1726 std::string name = output_var.name; |
| 1727 if (is_array) |
| 1728 name += std::string("[") + base::IntToString(jj) + "]"; |
| 1729 |
| 1730 auto it = bind_program_output_location_index_map_.find(name); |
| 1731 if (it == bind_program_output_location_index_map_.end()) |
| 1732 continue; |
| 1733 auto result = location_binding_used.insert(it->second); |
| 1734 if (!result.second) |
| 1735 return true; |
| 1736 } |
| 1737 } |
| 1738 return false; |
| 1739 } |
| 1740 |
1544 bool Program::DetectBuiltInInvariantConflicts() const { | 1741 bool Program::DetectBuiltInInvariantConflicts() const { |
1545 DCHECK(attached_shaders_[0].get() && | 1742 DCHECK(attached_shaders_[0].get() && |
1546 attached_shaders_[0]->shader_type() == GL_VERTEX_SHADER && | 1743 attached_shaders_[0]->shader_type() == GL_VERTEX_SHADER && |
1547 attached_shaders_[1].get() && | 1744 attached_shaders_[1].get() && |
1548 attached_shaders_[1]->shader_type() == GL_FRAGMENT_SHADER); | 1745 attached_shaders_[1]->shader_type() == GL_FRAGMENT_SHADER); |
1549 const VaryingMap& vertex_varyings = attached_shaders_[0]->varying_map(); | 1746 const VaryingMap& vertex_varyings = attached_shaders_[0]->varying_map(); |
1550 const VaryingMap& fragment_varyings = attached_shaders_[1]->varying_map(); | 1747 const VaryingMap& fragment_varyings = attached_shaders_[1]->varying_map(); |
1551 | 1748 |
1552 bool gl_position_invariant = IsBuiltInInvariant( | 1749 bool gl_position_invariant = IsBuiltInInvariant( |
1553 vertex_varyings, "gl_Position"); | 1750 vertex_varyings, "gl_Position"); |
(...skipping 458 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2012 } | 2209 } |
2013 glGetActiveUniformsiv( | 2210 glGetActiveUniformsiv( |
2014 program, count, &indices[0], kPname[pname_index], ¶ms[0]); | 2211 program, count, &indices[0], kPname[pname_index], ¶ms[0]); |
2015 for (GLsizei ii = 0; ii < count; ++ii) { | 2212 for (GLsizei ii = 0; ii < count; ++ii) { |
2016 entries[kStride * ii + pname_index] = params[ii]; | 2213 entries[kStride * ii + pname_index] = params[ii]; |
2017 } | 2214 } |
2018 } | 2215 } |
2019 return true; | 2216 return true; |
2020 } | 2217 } |
2021 | 2218 |
| 2219 const Program::ProgramOutputInfo* Program::GetProgramOutputInfo( |
| 2220 const std::string& name) const { |
| 2221 for (const auto& info : program_output_infos_) { |
| 2222 if (info.name == name) { |
| 2223 return &info; |
| 2224 } |
| 2225 } |
| 2226 return nullptr; |
| 2227 } |
| 2228 |
| 2229 GLint Program::GetFragDataLocation(const std::string& original_name) const { |
| 2230 DCHECK(IsValid()); |
| 2231 const ProgramOutputInfo* info = GetProgramOutputInfo(original_name); |
| 2232 if (!info) |
| 2233 info = GetProgramOutputInfo(original_name + "[0]"); |
| 2234 if (!info) |
| 2235 return -1; |
| 2236 return info->color_name; |
| 2237 } |
| 2238 |
| 2239 GLint Program::GetFragDataIndex(const std::string& original_name) const { |
| 2240 DCHECK(IsValid()); |
| 2241 const ProgramOutputInfo* info = GetProgramOutputInfo(original_name); |
| 2242 if (!info) |
| 2243 info = GetProgramOutputInfo(original_name + "[0]"); |
| 2244 if (!info) |
| 2245 return -1; |
| 2246 return info->index; |
| 2247 } |
| 2248 |
2022 void Program::TransformFeedbackVaryings(GLsizei count, | 2249 void Program::TransformFeedbackVaryings(GLsizei count, |
2023 const char* const* varyings, | 2250 const char* const* varyings, |
2024 GLenum buffer_mode) { | 2251 GLenum buffer_mode) { |
2025 transform_feedback_varyings_.clear(); | 2252 transform_feedback_varyings_.clear(); |
2026 for (GLsizei i = 0; i < count; ++i) { | 2253 for (GLsizei i = 0; i < count; ++i) { |
2027 transform_feedback_varyings_.push_back(std::string(varyings[i])); | 2254 transform_feedback_varyings_.push_back(std::string(varyings[i])); |
2028 } | 2255 } |
2029 transform_feedback_buffer_mode_ = buffer_mode; | 2256 transform_feedback_buffer_mode_ = buffer_mode; |
2030 } | 2257 } |
2031 | 2258 |
2032 Program::~Program() { | 2259 Program::~Program() { |
2033 if (manager_) { | 2260 if (manager_) { |
2034 if (manager_->have_context_) { | 2261 if (manager_->have_context_) { |
2035 glDeleteProgram(service_id()); | 2262 glDeleteProgram(service_id()); |
2036 } | 2263 } |
2037 manager_->StopTracking(this); | 2264 manager_->StopTracking(this); |
2038 manager_ = NULL; | 2265 manager_ = NULL; |
2039 } | 2266 } |
2040 } | 2267 } |
2041 | 2268 |
2042 ProgramManager::ProgramManager(ProgramCache* program_cache, | 2269 ProgramManager::ProgramManager(ProgramCache* program_cache, |
2043 uint32 max_varying_vectors, | 2270 uint32 max_varying_vectors, |
| 2271 uint32 max_dual_source_draw_buffers, |
2044 FeatureInfo* feature_info) | 2272 FeatureInfo* feature_info) |
2045 : program_count_(0), | 2273 : program_count_(0), |
2046 have_context_(true), | 2274 have_context_(true), |
2047 program_cache_(program_cache), | 2275 program_cache_(program_cache), |
2048 max_varying_vectors_(max_varying_vectors), | 2276 max_varying_vectors_(max_varying_vectors), |
| 2277 max_dual_source_draw_buffers_(max_dual_source_draw_buffers), |
2049 feature_info_(feature_info) {} | 2278 feature_info_(feature_info) {} |
2050 | 2279 |
2051 ProgramManager::~ProgramManager() { | 2280 ProgramManager::~ProgramManager() { |
2052 DCHECK(programs_.empty()); | 2281 DCHECK(programs_.empty()); |
2053 } | 2282 } |
2054 | 2283 |
2055 void ProgramManager::Destroy(bool have_context) { | 2284 void ProgramManager::Destroy(bool have_context) { |
2056 have_context_ = have_context; | 2285 have_context_ = have_context; |
2057 programs_.clear(); | 2286 programs_.clear(); |
2058 } | 2287 } |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2153 DCHECK(program); | 2382 DCHECK(program); |
2154 program->ClearUniforms(&zero_); | 2383 program->ClearUniforms(&zero_); |
2155 } | 2384 } |
2156 | 2385 |
2157 int32 ProgramManager::MakeFakeLocation(int32 index, int32 element) { | 2386 int32 ProgramManager::MakeFakeLocation(int32 index, int32 element) { |
2158 return index + element * 0x10000; | 2387 return index + element * 0x10000; |
2159 } | 2388 } |
2160 | 2389 |
2161 } // namespace gles2 | 2390 } // namespace gles2 |
2162 } // namespace gpu | 2391 } // namespace gpu |
OLD | NEW |