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

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

Issue 10568003: Add support for GL_CHROMIUM_consistent_uniform_locations (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 6 months 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 | Annotate | Revision Log
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 <vector>
9 10
10 #include "base/basictypes.h" 11 #include "base/basictypes.h"
11 #include "base/command_line.h" 12 #include "base/command_line.h"
12 #include "base/logging.h" 13 #include "base/logging.h"
13 #include "base/memory/scoped_ptr.h" 14 #include "base/memory/scoped_ptr.h"
14 #include "base/string_number_conversions.h" 15 #include "base/string_number_conversions.h"
15 #include "gpu/command_buffer/common/gles2_cmd_format.h" 16 #include "gpu/command_buffer/common/gles2_cmd_format.h"
16 #include "gpu/command_buffer/common/gles2_cmd_utils.h" 17 #include "gpu/command_buffer/common/gles2_cmd_utils.h"
17 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" 18 #include "gpu/command_buffer/service/gles2_cmd_decoder.h"
18 #include "gpu/command_buffer/service/gpu_switches.h" 19 #include "gpu/command_buffer/service/gpu_switches.h"
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
156 glUniformMatrix4fv( 157 glUniformMatrix4fv(
157 location, size, false, reinterpret_cast<const GLfloat*>(zero)); 158 location, size, false, reinterpret_cast<const GLfloat*>(zero));
158 break; 159 break;
159 default: 160 default:
160 NOTREACHED(); 161 NOTREACHED();
161 break; 162 break;
162 } 163 }
163 } 164 }
164 } 165 }
165 166
167 namespace {
168
169 struct UniformData {
170 std::string queried_name;
171 std::string corrected_name;
172 std::string original_name;
173 GLsizei size;
174 GLenum type;
175 };
176
177 struct UniformDataComparer {
178 bool operator()(const UniformData& lhs, const UniformData& rhs) const {
179 return lhs.queried_name < rhs.queried_name;
180 }
181 };
182
183 } // anonymous namespace
184
166 void ProgramManager::ProgramInfo::Update() { 185 void ProgramManager::ProgramInfo::Update() {
167 Reset(); 186 Reset();
168 UpdateLogInfo(); 187 UpdateLogInfo();
169 link_status_ = true; 188 link_status_ = true;
170 uniforms_cleared_ = false; 189 uniforms_cleared_ = false;
171 GLint num_attribs = 0; 190 GLint num_attribs = 0;
172 GLint max_len = 0; 191 GLint max_len = 0;
173 GLint max_location = -1; 192 GLint max_location = -1;
174 glGetProgramiv(service_id_, GL_ACTIVE_ATTRIBUTES, &num_attribs); 193 glGetProgramiv(service_id_, GL_ACTIVE_ATTRIBUTES, &num_attribs);
175 glGetProgramiv(service_id_, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_len); 194 glGetProgramiv(service_id_, GL_ACTIVE_ATTRIBUTE_MAX_LENGTH, &max_len);
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) { 227 for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) {
209 const VertexAttribInfo& info = attrib_infos_[ii]; 228 const VertexAttribInfo& info = attrib_infos_[ii];
210 attrib_location_to_index_map_[info.location] = ii; 229 attrib_location_to_index_map_[info.location] = ii;
211 } 230 }
212 231
213 max_len = 0; 232 max_len = 0;
214 GLint num_uniforms = 0; 233 GLint num_uniforms = 0;
215 glGetProgramiv(service_id_, GL_ACTIVE_UNIFORMS, &num_uniforms); 234 glGetProgramiv(service_id_, GL_ACTIVE_UNIFORMS, &num_uniforms);
216 glGetProgramiv(service_id_, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_len); 235 glGetProgramiv(service_id_, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_len);
217 name_buffer.reset(new char[max_len]); 236 name_buffer.reset(new char[max_len]);
237
238 // Read all the names first and sort them so we get a consistent list
239 std::vector<UniformData> uniform_data_;
218 for (GLint ii = 0; ii < num_uniforms; ++ii) { 240 for (GLint ii = 0; ii < num_uniforms; ++ii) {
219 GLsizei length = 0; 241 GLsizei length = 0;
220 GLsizei size = 0; 242 UniformData data;
221 GLenum type = 0;
222 glGetActiveUniform( 243 glGetActiveUniform(
223 service_id_, ii, max_len, &length, &size, &type, name_buffer.get()); 244 service_id_, ii, max_len, &length,
245 &data.size, &data.type, name_buffer.get());
224 DCHECK(max_len == 0 || length < max_len); 246 DCHECK(max_len == 0 || length < max_len);
225 DCHECK(length == 0 || name_buffer[length] == '\0'); 247 DCHECK(length == 0 || name_buffer[length] == '\0');
226 // TODO(gman): Should we check for error?
227 if (!IsInvalidPrefix(name_buffer.get(), length)) { 248 if (!IsInvalidPrefix(name_buffer.get(), length)) {
228 GLint location = glGetUniformLocation(service_id_, name_buffer.get()); 249 data.queried_name = std::string(name_buffer.get());
229 std::string name;
230 std::string original_name;
231 GetCorrectedVariableInfo( 250 GetCorrectedVariableInfo(
232 true, name_buffer.get(), &name, &original_name, &size, &type); 251 true, name_buffer.get(), &data.corrected_name, &data.original_name,
233 const UniformInfo* info = AddUniformInfo( 252 &data.size, &data.type);
234 size, type, location, name, original_name); 253 uniform_data_.push_back(data);
235 if (info->IsSampler()) {
236 sampler_indices_.push_back(info->fake_location_base);
237 }
238 max_uniform_name_length_ =
239 std::max(max_uniform_name_length_,
240 static_cast<GLsizei>(info->name.size()));
241 } 254 }
242 } 255 }
256
257 std::sort(uniform_data_.begin(), uniform_data_.end(), UniformDataComparer());
258
259 for (size_t ii = 0; ii < uniform_data_.size(); ++ii) {
260 const UniformData& data = uniform_data_[ii];
261 GLint location = glGetUniformLocation(
262 service_id_, data.queried_name.c_str());
263 const UniformInfo* info = AddUniformInfo(
264 data.size, data.type, location, data.corrected_name,
265 data.original_name);
266 if (info->IsSampler()) {
267 sampler_indices_.push_back(info->fake_location_base);
268 }
269 max_uniform_name_length_ =
270 std::max(max_uniform_name_length_,
271 static_cast<GLsizei>(info->name.size()));
272 }
243 valid_ = true; 273 valid_ = true;
244 } 274 }
245 275
246 void ProgramManager::ProgramInfo::ExecuteBindAttribLocationCalls() { 276 void ProgramManager::ProgramInfo::ExecuteBindAttribLocationCalls() {
247 for (std::map<std::string, GLint>::const_iterator it = 277 for (std::map<std::string, GLint>::const_iterator it =
248 bind_attrib_location_map_.begin(); 278 bind_attrib_location_map_.begin();
249 it != bind_attrib_location_map_.end(); ++it) { 279 it != bind_attrib_location_map_.end(); ++it) {
250 const std::string* mapped_name = GetAttribMappedName(it->first); 280 const std::string* mapped_name = GetAttribMappedName(it->first);
251 if (mapped_name && *mapped_name != it->first) 281 if (mapped_name && *mapped_name != it->first)
252 glBindAttribLocation(service_id_, it->second, mapped_name->c_str()); 282 glBindAttribLocation(service_id_, it->second, mapped_name->c_str());
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 bool bad = false; 335 bool bad = false;
306 for (size_t pos = open_pos + 1; pos < last; ++pos) { 336 for (size_t pos = open_pos + 1; pos < last; ++pos) {
307 int8 digit = name[pos] - '0'; 337 int8 digit = name[pos] - '0';
308 if (digit < 0 || digit > 9) { 338 if (digit < 0 || digit > 9) {
309 bad = true; 339 bad = true;
310 break; 340 break;
311 } 341 }
312 index = index * 10 + digit; 342 index = index * 10 + digit;
313 } 343 }
314 if (!bad && index >= 0 && index < info.size) { 344 if (!bad && index >= 0 && index < info.size) {
315 return GetFakeLocation(info.fake_location_base, index); 345 return GLES2Util::MakeFakeLocation(info.fake_location_base, index);
316 } 346 }
317 } 347 }
318 } 348 }
319 } 349 }
320 return -1; 350 return -1;
321 } 351 }
322 352
323 GLint ProgramManager::ProgramInfo::GetAttribLocation( 353 GLint ProgramManager::ProgramInfo::GetAttribLocation(
324 const std::string& name) const { 354 const std::string& name) const {
325 for (GLuint ii = 0; ii < attrib_infos_.size(); ++ii) { 355 for (GLuint ii = 0; ii < attrib_infos_.size(); ++ii) {
(...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after
651 681
652 for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) { 682 for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) {
653 const UniformInfo& info = uniform_infos_[ii]; 683 const UniformInfo& info = uniform_infos_[ii];
654 inputs->size = info.size; 684 inputs->size = info.size;
655 inputs->type = info.type; 685 inputs->type = info.type;
656 inputs->location_offset = ComputeOffset(header, locations); 686 inputs->location_offset = ComputeOffset(header, locations);
657 inputs->name_offset = ComputeOffset(header, strings); 687 inputs->name_offset = ComputeOffset(header, strings);
658 inputs->name_length = info.name.size(); 688 inputs->name_length = info.name.size();
659 DCHECK(static_cast<size_t>(info.size) == info.element_locations.size()); 689 DCHECK(static_cast<size_t>(info.size) == info.element_locations.size());
660 for (size_t jj = 0; jj < info.element_locations.size(); ++jj) { 690 for (size_t jj = 0; jj < info.element_locations.size(); ++jj) {
661 *locations++ = manager->SwizzleLocation(ii + jj * 0x10000); 691 *locations++ = GLES2Util::SwizzleLocation(
692 GLES2Util::MakeFakeLocation(ii, jj));
662 } 693 }
663 memcpy(strings, info.name.c_str(), info.name.size()); 694 memcpy(strings, info.name.c_str(), info.name.size());
664 strings += info.name.size(); 695 strings += info.name.size();
665 ++inputs; 696 ++inputs;
666 } 697 }
667 698
668 DCHECK_EQ(ComputeOffset(header, strings), size); 699 DCHECK_EQ(ComputeOffset(header, strings), size);
669 } 700 }
670 701
671 ProgramManager::ProgramInfo::~ProgramInfo() { 702 ProgramManager::ProgramInfo::~ProgramInfo() {
672 if (manager_) { 703 if (manager_) {
673 if (manager_->have_context_) { 704 if (manager_->have_context_) {
674 glDeleteProgram(service_id()); 705 glDeleteProgram(service_id());
675 } 706 }
676 manager_->StopTracking(this); 707 manager_->StopTracking(this);
677 manager_ = NULL; 708 manager_ = NULL;
678 } 709 }
679 } 710 }
680 711
681 // TODO(gman): make this some kind of random number. Base::RandInt is not
682 // callable because of the sandbox. What matters is that it's possibly different
683 // by at least 1 bit each time chrome is run.
684 static int uniform_random_offset_ = 3;
685
686 ProgramManager::ProgramManager() 712 ProgramManager::ProgramManager()
687 : uniform_swizzle_(uniform_random_offset_++ % 15), 713 : program_info_count_(0),
688 program_info_count_(0),
689 have_context_(true), 714 have_context_(true),
690 disable_workarounds_( 715 disable_workarounds_(
691 CommandLine::ForCurrentProcess()->HasSwitch( 716 CommandLine::ForCurrentProcess()->HasSwitch(
692 switches::kDisableGpuDriverBugWorkarounds)) { 717 switches::kDisableGpuDriverBugWorkarounds)) {
693 } 718 }
694 719
695 ProgramManager::~ProgramManager() { 720 ProgramManager::~ProgramManager() {
696 DCHECK(program_infos_.empty()); 721 DCHECK(program_infos_.empty());
697 } 722 }
698 723
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
791 RemoveProgramInfoIfUnused(shader_manager, info); 816 RemoveProgramInfoIfUnused(shader_manager, info);
792 } 817 }
793 818
794 void ProgramManager::ClearUniforms(ProgramManager::ProgramInfo* info) { 819 void ProgramManager::ClearUniforms(ProgramManager::ProgramInfo* info) {
795 DCHECK(info); 820 DCHECK(info);
796 if (!disable_workarounds_) { 821 if (!disable_workarounds_) {
797 info->ClearUniforms(&zero_); 822 info->ClearUniforms(&zero_);
798 } 823 }
799 } 824 }
800 825
801 // Swizzles the locations to prevent developers from assuming they
802 // can do math on uniforms. According to the OpenGL ES 2.0 spec
803 // the location of "someuniform[1]" is not 'n' more than "someuniform[0]".
804 static GLint Swizzle(GLint location) {
805 return (location & 0xF0000000U) |
806 ((location & 0x0AAAAAAAU) >> 1) |
807 ((location & 0x05555555U) << 1);
808 }
809
810 // Adds uniform_swizzle_ to prevent developers from assuming that locations are
811 // always the same across GPUs and drivers.
812 GLint ProgramManager::SwizzleLocation(GLint v) const {
813 return v < 0 ? v : (Swizzle(v) + uniform_swizzle_);
814 }
815
816 GLint ProgramManager::UnswizzleLocation(GLint v) const {
817 return v < 0 ? v : Swizzle(v - uniform_swizzle_);
818 }
819
820 } // namespace gles2 826 } // namespace gles2
821 } // namespace gpu 827 } // namespace gpu
822 828
823 829
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