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

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

Issue 1309743005: command_buffer: Implement EXT_blend_func_extended (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@new-05-path-fragment-input-gen
Patch Set: rebase Created 5 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "gpu/command_buffer/service/program_manager.h" 5 #include "gpu/command_buffer/service/program_manager.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <set> 8 #include <set>
9 #include <utility> 9 #include <utility>
10 #include <vector> 10 #include <vector>
(...skipping 10 matching lines...) Expand all
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
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
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
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
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
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
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
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
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
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
2012 } 2209 }
2013 glGetActiveUniformsiv( 2210 glGetActiveUniformsiv(
2014 program, count, &indices[0], kPname[pname_index], &params[0]); 2211 program, count, &indices[0], kPname[pname_index], &params[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
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
OLDNEW
« no previous file with comments | « gpu/command_buffer/service/program_manager.h ('k') | gpu/command_buffer/service/program_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698