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> | |
8 #include <set> | 7 #include <set> |
9 #include <vector> | 8 #include <vector> |
10 | 9 |
11 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
12 #include "base/command_line.h" | 11 #include "base/command_line.h" |
13 #include "base/logging.h" | 12 #include "base/logging.h" |
14 #include "base/memory/scoped_ptr.h" | 13 #include "base/memory/scoped_ptr.h" |
15 #include "base/string_number_conversions.h" | 14 #include "base/string_number_conversions.h" |
16 #include "gpu/command_buffer/common/gles2_cmd_format.h" | 15 #include "gpu/command_buffer/common/gles2_cmd_format.h" |
17 #include "gpu/command_buffer/common/gles2_cmd_utils.h" | 16 #include "gpu/command_buffer/common/gles2_cmd_utils.h" |
18 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" | 17 #include "gpu/command_buffer/service/gles2_cmd_decoder.h" |
19 #include "gpu/command_buffer/service/gpu_switches.h" | 18 #include "gpu/command_buffer/service/gpu_switches.h" |
20 | 19 |
21 namespace gpu { | 20 namespace gpu { |
22 namespace gles2 { | 21 namespace gles2 { |
23 | 22 |
24 static int ShaderTypeToIndex(GLenum shader_type) { | 23 namespace { |
| 24 |
| 25 int ShaderTypeToIndex(GLenum shader_type) { |
25 switch (shader_type) { | 26 switch (shader_type) { |
26 case GL_VERTEX_SHADER: | 27 case GL_VERTEX_SHADER: |
27 return 0; | 28 return 0; |
28 case GL_FRAGMENT_SHADER: | 29 case GL_FRAGMENT_SHADER: |
29 return 1; | 30 return 1; |
30 default: | 31 default: |
31 NOTREACHED(); | 32 NOTREACHED(); |
32 return 0; | 33 return 0; |
33 } | 34 } |
34 } | 35 } |
35 | 36 |
| 37 // Given a name like "foo.bar[123].moo[456]" sets new_name to "foo.bar[123].moo" |
| 38 // and sets element_index to 456. returns false if element expression was not a |
| 39 // whole decimal number. For example: "foo[1b2]" |
| 40 bool GetUniformNameSansElement( |
| 41 const std::string name, int* element_index, std::string* new_name) { |
| 42 DCHECK(element_index); |
| 43 DCHECK(new_name); |
| 44 if (name.size() < 3 || name[name.size() - 1] != ']') { |
| 45 *element_index = 0; |
| 46 *new_name = name; |
| 47 return true; |
| 48 } |
| 49 |
| 50 // Look for an array specification. |
| 51 size_t open_pos = name.find_last_of('['); |
| 52 if (open_pos == std::string::npos || |
| 53 open_pos >= name.size() - 2) { |
| 54 return false; |
| 55 } |
| 56 |
| 57 GLint index = 0; |
| 58 size_t last = name.size() - 1; |
| 59 for (size_t pos = open_pos + 1; pos < last; ++pos) { |
| 60 int8 digit = name[pos] - '0'; |
| 61 if (digit < 0 || digit > 9) { |
| 62 return false; |
| 63 } |
| 64 index = index * 10 + digit; |
| 65 } |
| 66 |
| 67 if (index < 0) { |
| 68 return false; |
| 69 } |
| 70 |
| 71 *element_index = index; |
| 72 *new_name = name.substr(0, open_pos); |
| 73 return true; |
| 74 } |
| 75 |
| 76 } // anonymous namespace. |
| 77 |
| 78 ProgramManager::ProgramInfo::UniformInfo::UniformInfo() |
| 79 : size(0) { |
| 80 } |
| 81 |
36 ProgramManager::ProgramInfo::UniformInfo::UniformInfo( | 82 ProgramManager::ProgramInfo::UniformInfo::UniformInfo( |
37 GLsizei _size, | 83 GLsizei _size, |
38 GLenum _type, | 84 GLenum _type, |
39 int _fake_location_base, | 85 int _fake_location_base, |
40 const std::string& _name) | 86 const std::string& _name) |
41 : size(_size), | 87 : size(_size), |
42 type(_type), | 88 type(_type), |
43 fake_location_base(_fake_location_base), | 89 fake_location_base(_fake_location_base), |
44 is_array(false), | 90 is_array(false), |
45 name(_name) { | 91 name(_name) { |
(...skipping 10 matching lines...) Expand all Loading... |
56 ProgramManager::ProgramInfo::ProgramInfo( | 102 ProgramManager::ProgramInfo::ProgramInfo( |
57 ProgramManager* manager, GLuint service_id) | 103 ProgramManager* manager, GLuint service_id) |
58 : manager_(manager), | 104 : manager_(manager), |
59 use_count_(0), | 105 use_count_(0), |
60 max_attrib_name_length_(0), | 106 max_attrib_name_length_(0), |
61 max_uniform_name_length_(0), | 107 max_uniform_name_length_(0), |
62 service_id_(service_id), | 108 service_id_(service_id), |
63 deleted_(false), | 109 deleted_(false), |
64 valid_(false), | 110 valid_(false), |
65 link_status_(false), | 111 link_status_(false), |
66 uniforms_cleared_(false) { | 112 uniforms_cleared_(false), |
| 113 num_uniforms_(0) { |
67 manager_->StartTracking(this); | 114 manager_->StartTracking(this); |
68 } | 115 } |
69 | 116 |
70 void ProgramManager::ProgramInfo::Reset() { | 117 void ProgramManager::ProgramInfo::Reset() { |
71 valid_ = false; | 118 valid_ = false; |
72 link_status_ = false; | 119 link_status_ = false; |
| 120 num_uniforms_ = 0; |
73 max_uniform_name_length_ = 0; | 121 max_uniform_name_length_ = 0; |
74 max_attrib_name_length_ = 0; | 122 max_attrib_name_length_ = 0; |
75 attrib_infos_.clear(); | 123 attrib_infos_.clear(); |
76 uniform_infos_.clear(); | 124 uniform_infos_.clear(); |
77 sampler_indices_.clear(); | 125 sampler_indices_.clear(); |
78 attrib_location_to_index_map_.clear(); | 126 attrib_location_to_index_map_.clear(); |
79 } | 127 } |
80 | 128 |
81 void ProgramManager::ProgramInfo::UpdateLogInfo() { | 129 void ProgramManager::ProgramInfo::UpdateLogInfo() { |
82 GLint max_len = 0; | 130 GLint max_len = 0; |
(...skipping 12 matching lines...) Expand all Loading... |
95 | 143 |
96 void ProgramManager::ProgramInfo::ClearUniforms( | 144 void ProgramManager::ProgramInfo::ClearUniforms( |
97 std::vector<uint8>* zero_buffer) { | 145 std::vector<uint8>* zero_buffer) { |
98 DCHECK(zero_buffer); | 146 DCHECK(zero_buffer); |
99 if (uniforms_cleared_) { | 147 if (uniforms_cleared_) { |
100 return; | 148 return; |
101 } | 149 } |
102 uniforms_cleared_ = true; | 150 uniforms_cleared_ = true; |
103 for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) { | 151 for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) { |
104 const UniformInfo& uniform_info = uniform_infos_[ii]; | 152 const UniformInfo& uniform_info = uniform_infos_[ii]; |
| 153 if (!uniform_info.IsValid()) { |
| 154 continue; |
| 155 } |
105 GLint location = uniform_info.element_locations[0]; | 156 GLint location = uniform_info.element_locations[0]; |
106 GLsizei size = uniform_info.size; | 157 GLsizei size = uniform_info.size; |
107 uint32 unit_size = GLES2Util::GetGLDataTypeSizeForUniforms( | 158 uint32 unit_size = GLES2Util::GetGLDataTypeSizeForUniforms( |
108 uniform_info.type); | 159 uniform_info.type); |
109 uint32 size_needed = size * unit_size; | 160 uint32 size_needed = size * unit_size; |
110 if (size_needed > zero_buffer->size()) { | 161 if (size_needed > zero_buffer->size()) { |
111 zero_buffer->resize(size_needed, 0u); | 162 zero_buffer->resize(size_needed, 0u); |
112 } | 163 } |
113 const void* zero = &(*zero_buffer)[0]; | 164 const void* zero = &(*zero_buffer)[0]; |
114 switch (uniform_info.type) { | 165 switch (uniform_info.type) { |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
160 default: | 211 default: |
161 NOTREACHED(); | 212 NOTREACHED(); |
162 break; | 213 break; |
163 } | 214 } |
164 } | 215 } |
165 } | 216 } |
166 | 217 |
167 namespace { | 218 namespace { |
168 | 219 |
169 struct UniformData { | 220 struct UniformData { |
| 221 UniformData() : size(-1), type(GL_NONE), added(false) { |
| 222 } |
170 std::string queried_name; | 223 std::string queried_name; |
171 std::string corrected_name; | 224 std::string corrected_name; |
172 std::string original_name; | 225 std::string original_name; |
173 GLsizei size; | 226 GLsizei size; |
174 GLenum type; | 227 GLenum type; |
| 228 GLint location; |
| 229 bool added; |
175 }; | 230 }; |
176 | 231 |
177 struct UniformDataComparer { | 232 struct UniformDataComparer { |
178 bool operator()(const UniformData& lhs, const UniformData& rhs) const { | 233 bool operator()(const UniformData& lhs, const UniformData& rhs) const { |
179 return lhs.queried_name < rhs.queried_name; | 234 return lhs.queried_name < rhs.queried_name; |
180 } | 235 } |
181 }; | 236 }; |
182 | 237 |
183 } // anonymous namespace | 238 } // anonymous namespace |
184 | 239 |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
228 const VertexAttribInfo& info = attrib_infos_[ii]; | 283 const VertexAttribInfo& info = attrib_infos_[ii]; |
229 attrib_location_to_index_map_[info.location] = ii; | 284 attrib_location_to_index_map_[info.location] = ii; |
230 } | 285 } |
231 | 286 |
232 max_len = 0; | 287 max_len = 0; |
233 GLint num_uniforms = 0; | 288 GLint num_uniforms = 0; |
234 glGetProgramiv(service_id_, GL_ACTIVE_UNIFORMS, &num_uniforms); | 289 glGetProgramiv(service_id_, GL_ACTIVE_UNIFORMS, &num_uniforms); |
235 glGetProgramiv(service_id_, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_len); | 290 glGetProgramiv(service_id_, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_len); |
236 name_buffer.reset(new char[max_len]); | 291 name_buffer.reset(new char[max_len]); |
237 | 292 |
238 // Read all the names first and sort them so we get a consistent list | 293 // Reads all the names. |
239 std::vector<UniformData> uniform_data_; | 294 std::vector<UniformData> uniform_data_; |
240 for (GLint ii = 0; ii < num_uniforms; ++ii) { | 295 for (GLint ii = 0; ii < num_uniforms; ++ii) { |
241 GLsizei length = 0; | 296 GLsizei length = 0; |
242 UniformData data; | 297 UniformData data; |
243 glGetActiveUniform( | 298 glGetActiveUniform( |
244 service_id_, ii, max_len, &length, | 299 service_id_, ii, max_len, &length, |
245 &data.size, &data.type, name_buffer.get()); | 300 &data.size, &data.type, name_buffer.get()); |
246 DCHECK(max_len == 0 || length < max_len); | 301 DCHECK(max_len == 0 || length < max_len); |
247 DCHECK(length == 0 || name_buffer[length] == '\0'); | 302 DCHECK(length == 0 || name_buffer[length] == '\0'); |
248 if (!IsInvalidPrefix(name_buffer.get(), length)) { | 303 if (!IsInvalidPrefix(name_buffer.get(), length)) { |
249 data.queried_name = std::string(name_buffer.get()); | 304 data.queried_name = std::string(name_buffer.get()); |
250 GetCorrectedVariableInfo( | 305 GetCorrectedVariableInfo( |
251 true, name_buffer.get(), &data.corrected_name, &data.original_name, | 306 true, name_buffer.get(), &data.corrected_name, &data.original_name, |
252 &data.size, &data.type); | 307 &data.size, &data.type); |
253 uniform_data_.push_back(data); | 308 uniform_data_.push_back(data); |
254 } | 309 } |
255 } | 310 } |
256 | 311 |
257 std::sort(uniform_data_.begin(), uniform_data_.end(), UniformDataComparer()); | 312 // NOTE: We don't care if 2 uniforms are bound to the same location. |
| 313 // One of them will take preference. The spec allows this, same as |
| 314 // BindAttribLocation. |
| 315 // |
| 316 // The reason we don't check is if we were to fail we'd have to |
| 317 // restore the previous program but since we've already linked successfully |
| 318 // at this point the previous program is gone. |
258 | 319 |
| 320 // Assigns the uniforms with bindings. |
| 321 size_t next_available_index = 0; |
| 322 for (size_t ii = 0; ii < uniform_data_.size(); ++ii) { |
| 323 UniformData& data = uniform_data_[ii]; |
| 324 data.location = glGetUniformLocation( |
| 325 service_id_, data.queried_name.c_str()); |
| 326 // remove "[0]" |
| 327 std::string short_name; |
| 328 int element_index = 0; |
| 329 bool good ALLOW_UNUSED = GetUniformNameSansElement( |
| 330 data.queried_name, &element_index, &short_name);\ |
| 331 DCHECK(good); |
| 332 LocationMap::const_iterator it = bind_uniform_location_map_.find( |
| 333 short_name); |
| 334 if (it != bind_uniform_location_map_.end()) { |
| 335 data.added = AddUniformInfo( |
| 336 data.size, data.type, data.location, it->second, data.corrected_name, |
| 337 data.original_name, &next_available_index); |
| 338 } |
| 339 } |
| 340 |
| 341 // Assigns the uniforms that were not bound. |
259 for (size_t ii = 0; ii < uniform_data_.size(); ++ii) { | 342 for (size_t ii = 0; ii < uniform_data_.size(); ++ii) { |
260 const UniformData& data = uniform_data_[ii]; | 343 const UniformData& data = uniform_data_[ii]; |
261 GLint location = glGetUniformLocation( | 344 if (!data.added) { |
262 service_id_, data.queried_name.c_str()); | 345 AddUniformInfo( |
263 const UniformInfo* info = AddUniformInfo( | 346 data.size, data.type, data.location, -1, data.corrected_name, |
264 data.size, data.type, location, data.corrected_name, | 347 data.original_name, &next_available_index); |
265 data.original_name); | |
266 if (info->IsSampler()) { | |
267 sampler_indices_.push_back(info->fake_location_base); | |
268 } | 348 } |
269 max_uniform_name_length_ = | |
270 std::max(max_uniform_name_length_, | |
271 static_cast<GLsizei>(info->name.size())); | |
272 } | 349 } |
| 350 |
273 valid_ = true; | 351 valid_ = true; |
274 } | 352 } |
275 | 353 |
276 void ProgramManager::ProgramInfo::ExecuteBindAttribLocationCalls() { | 354 void ProgramManager::ProgramInfo::ExecuteBindAttribLocationCalls() { |
277 for (std::map<std::string, GLint>::const_iterator it = | 355 for (LocationMap::const_iterator it = bind_attrib_location_map_.begin(); |
278 bind_attrib_location_map_.begin(); | |
279 it != bind_attrib_location_map_.end(); ++it) { | 356 it != bind_attrib_location_map_.end(); ++it) { |
280 const std::string* mapped_name = GetAttribMappedName(it->first); | 357 const std::string* mapped_name = GetAttribMappedName(it->first); |
281 if (mapped_name && *mapped_name != it->first) | 358 if (mapped_name && *mapped_name != it->first) |
282 glBindAttribLocation(service_id_, it->second, mapped_name->c_str()); | 359 glBindAttribLocation(service_id_, it->second, mapped_name->c_str()); |
283 } | 360 } |
284 } | 361 } |
285 | 362 |
286 bool ProgramManager::ProgramInfo::Link() { | 363 bool ProgramManager::ProgramInfo::Link() { |
287 ClearLinkStatus(); | 364 ClearLinkStatus(); |
288 if (!CanLink()) { | 365 if (!CanLink()) { |
(...skipping 22 matching lines...) Expand all Loading... |
311 return; | 388 return; |
312 } | 389 } |
313 glValidateProgram(service_id()); | 390 glValidateProgram(service_id()); |
314 UpdateLogInfo(); | 391 UpdateLogInfo(); |
315 } | 392 } |
316 | 393 |
317 GLint ProgramManager::ProgramInfo::GetUniformFakeLocation( | 394 GLint ProgramManager::ProgramInfo::GetUniformFakeLocation( |
318 const std::string& name) const { | 395 const std::string& name) const { |
319 for (GLuint ii = 0; ii < uniform_infos_.size(); ++ii) { | 396 for (GLuint ii = 0; ii < uniform_infos_.size(); ++ii) { |
320 const UniformInfo& info = uniform_infos_[ii]; | 397 const UniformInfo& info = uniform_infos_[ii]; |
| 398 if (!info.IsValid()) { |
| 399 continue; |
| 400 } |
321 if (info.name == name || | 401 if (info.name == name || |
322 (info.is_array && | 402 (info.is_array && |
323 info.name.compare(0, info.name.size() - 3, name) == 0)) { | 403 info.name.compare(0, info.name.size() - 3, name) == 0)) { |
324 return info.fake_location_base; | 404 return info.fake_location_base; |
325 } else if (info.is_array && | 405 } else if (info.is_array && |
326 name.size() >= 3 && name[name.size() - 1] == ']') { | 406 name.size() >= 3 && name[name.size() - 1] == ']') { |
327 // Look for an array specification. | 407 // Look for an array specification. |
328 size_t open_pos = name.find_last_of('['); | 408 size_t open_pos = name.find_last_of('['); |
329 if (open_pos != std::string::npos && | 409 if (open_pos != std::string::npos && |
330 open_pos < name.size() - 2 && | 410 open_pos < name.size() - 2 && |
331 info.name.size() > open_pos && | 411 info.name.size() > open_pos && |
332 name.compare(0, open_pos, info.name, 0, open_pos) == 0) { | 412 name.compare(0, open_pos, info.name, 0, open_pos) == 0) { |
333 GLint index = 0; | 413 GLint index = 0; |
334 size_t last = name.size() - 1; | 414 size_t last = name.size() - 1; |
335 bool bad = false; | 415 bool bad = false; |
336 for (size_t pos = open_pos + 1; pos < last; ++pos) { | 416 for (size_t pos = open_pos + 1; pos < last; ++pos) { |
337 int8 digit = name[pos] - '0'; | 417 int8 digit = name[pos] - '0'; |
338 if (digit < 0 || digit > 9) { | 418 if (digit < 0 || digit > 9) { |
339 bad = true; | 419 bad = true; |
340 break; | 420 break; |
341 } | 421 } |
342 index = index * 10 + digit; | 422 index = index * 10 + digit; |
343 } | 423 } |
344 if (!bad && index >= 0 && index < info.size) { | 424 if (!bad && index >= 0 && index < info.size) { |
345 return GLES2Util::MakeFakeLocation(info.fake_location_base, index); | 425 return ProgramManager::MakeFakeLocation( |
| 426 info.fake_location_base, index); |
346 } | 427 } |
347 } | 428 } |
348 } | 429 } |
349 } | 430 } |
350 return -1; | 431 return -1; |
351 } | 432 } |
352 | 433 |
353 GLint ProgramManager::ProgramInfo::GetAttribLocation( | 434 GLint ProgramManager::ProgramInfo::GetAttribLocation( |
354 const std::string& name) const { | 435 const std::string& name) const { |
355 for (GLuint ii = 0; ii < attrib_infos_.size(); ++ii) { | 436 for (GLuint ii = 0; ii < attrib_infos_.size(); ++ii) { |
(...skipping 11 matching lines...) Expand all Loading... |
367 DCHECK(real_location); | 448 DCHECK(real_location); |
368 DCHECK(array_index); | 449 DCHECK(array_index); |
369 if (fake_location < 0) { | 450 if (fake_location < 0) { |
370 return NULL; | 451 return NULL; |
371 } | 452 } |
372 | 453 |
373 GLint uniform_index = GetUniformInfoIndexFromFakeLocation(fake_location); | 454 GLint uniform_index = GetUniformInfoIndexFromFakeLocation(fake_location); |
374 if (uniform_index >= 0 && | 455 if (uniform_index >= 0 && |
375 static_cast<size_t>(uniform_index) < uniform_infos_.size()) { | 456 static_cast<size_t>(uniform_index) < uniform_infos_.size()) { |
376 const UniformInfo& uniform_info = uniform_infos_[uniform_index]; | 457 const UniformInfo& uniform_info = uniform_infos_[uniform_index]; |
| 458 if (!uniform_info.IsValid()) { |
| 459 return NULL; |
| 460 } |
377 GLint element_index = GetArrayElementIndexFromFakeLocation(fake_location); | 461 GLint element_index = GetArrayElementIndexFromFakeLocation(fake_location); |
378 if (element_index < uniform_info.size) { | 462 if (element_index < uniform_info.size) { |
379 *real_location = uniform_info.element_locations[element_index]; | 463 *real_location = uniform_info.element_locations[element_index]; |
380 *array_index = element_index; | 464 *array_index = element_index; |
381 return &uniform_info; | 465 return &uniform_info; |
382 } | 466 } |
383 } | 467 } |
384 return NULL; | 468 return NULL; |
385 } | 469 } |
386 | 470 |
387 const std::string* ProgramManager::ProgramInfo::GetAttribMappedName( | 471 const std::string* ProgramManager::ProgramInfo::GetAttribMappedName( |
388 const std::string& original_name) const { | 472 const std::string& original_name) const { |
389 for (int ii = 0; ii < kMaxAttachedShaders; ++ii) { | 473 for (int ii = 0; ii < kMaxAttachedShaders; ++ii) { |
390 ShaderManager::ShaderInfo* shader_info = attached_shaders_[ii].get(); | 474 ShaderManager::ShaderInfo* shader_info = attached_shaders_[ii].get(); |
391 if (shader_info) { | 475 if (shader_info) { |
392 const std::string* mapped_name = | 476 const std::string* mapped_name = |
393 shader_info->GetAttribMappedName(original_name); | 477 shader_info->GetAttribMappedName(original_name); |
394 if (mapped_name) | 478 if (mapped_name) |
395 return mapped_name; | 479 return mapped_name; |
396 } | 480 } |
397 } | 481 } |
398 return NULL; | 482 return NULL; |
399 } | 483 } |
400 | 484 |
| 485 bool ProgramManager::ProgramInfo::SetUniformLocationBinding( |
| 486 const std::string& name, GLint location) { |
| 487 std::string short_name; |
| 488 int element_index = 0; |
| 489 if (!GetUniformNameSansElement(name, &element_index, &short_name) || |
| 490 element_index != 0) { |
| 491 return false; |
| 492 } |
| 493 |
| 494 bind_uniform_location_map_[short_name] = location; |
| 495 return true; |
| 496 } |
| 497 |
401 // Note: This is only valid to call right after a program has been linked | 498 // Note: This is only valid to call right after a program has been linked |
402 // successfully. | 499 // successfully. |
403 void ProgramManager::ProgramInfo::GetCorrectedVariableInfo( | 500 void ProgramManager::ProgramInfo::GetCorrectedVariableInfo( |
404 bool use_uniforms, | 501 bool use_uniforms, |
405 const std::string& name, std::string* corrected_name, | 502 const std::string& name, std::string* corrected_name, |
406 std::string* original_name, | 503 std::string* original_name, |
407 GLsizei* size, GLenum* type) const { | 504 GLsizei* size, GLenum* type) const { |
408 DCHECK(corrected_name); | 505 DCHECK(corrected_name); |
409 DCHECK(original_name); | 506 DCHECK(original_name); |
410 DCHECK(size); | 507 DCHECK(size); |
(...skipping 17 matching lines...) Expand all Loading... |
428 *size = variable_info->size; | 525 *size = variable_info->size; |
429 return; | 526 return; |
430 } | 527 } |
431 } | 528 } |
432 } | 529 } |
433 } | 530 } |
434 *corrected_name = name; | 531 *corrected_name = name; |
435 *original_name = name; | 532 *original_name = name; |
436 } | 533 } |
437 | 534 |
438 const ProgramManager::ProgramInfo::UniformInfo* | 535 bool ProgramManager::ProgramInfo::AddUniformInfo( |
439 ProgramManager::ProgramInfo::AddUniformInfo( | 536 GLsizei size, GLenum type, GLint location, GLint fake_base_location, |
440 GLsizei size, GLenum type, GLint location, | 537 const std::string& name, const std::string& original_name, |
441 const std::string& name, const std::string& original_name) { | 538 size_t* next_available_index) { |
| 539 DCHECK(next_available_index); |
442 const char* kArraySpec = "[0]"; | 540 const char* kArraySpec = "[0]"; |
443 int uniform_index = uniform_infos_.size(); | 541 size_t uniform_index = |
444 uniform_infos_.push_back( | 542 fake_base_location >= 0 ? fake_base_location : *next_available_index; |
445 UniformInfo(size, type, uniform_index, original_name)); | 543 if (uniform_infos_.size() < uniform_index + 1) { |
446 UniformInfo& info = uniform_infos_.back(); | 544 uniform_infos_.resize(uniform_index + 1); |
| 545 } |
| 546 |
| 547 // return if this location is already in use. |
| 548 if (uniform_infos_[uniform_index].IsValid()) { |
| 549 DCHECK_GE(fake_base_location, 0); |
| 550 return false; |
| 551 } |
| 552 |
| 553 uniform_infos_[uniform_index] = UniformInfo( |
| 554 size, type, uniform_index, original_name); |
| 555 ++num_uniforms_; |
| 556 |
| 557 UniformInfo& info = uniform_infos_[uniform_index]; |
447 info.element_locations.resize(size); | 558 info.element_locations.resize(size); |
448 info.element_locations[0] = location; | 559 info.element_locations[0] = location; |
449 DCHECK_GE(size, 0); | 560 DCHECK_GE(size, 0); |
450 size_t num_texture_units = info.IsSampler() ? static_cast<size_t>(size) : 0u; | 561 size_t num_texture_units = info.IsSampler() ? static_cast<size_t>(size) : 0u; |
451 info.texture_units.clear(); | 562 info.texture_units.clear(); |
452 info.texture_units.resize(num_texture_units, 0); | 563 info.texture_units.resize(num_texture_units, 0); |
453 | 564 |
454 if (size > 1) { | 565 if (size > 1) { |
455 // Go through the array element locations looking for a match. | 566 // Go through the array element locations looking for a match. |
456 // We can skip the first element because it's the same as the | 567 // We can skip the first element because it's the same as the |
(...skipping 12 matching lines...) Expand all Loading... |
469 info.element_locations[ii] = | 580 info.element_locations[ii] = |
470 glGetUniformLocation(service_id_, element_name.c_str()); | 581 glGetUniformLocation(service_id_, element_name.c_str()); |
471 } | 582 } |
472 } | 583 } |
473 | 584 |
474 info.is_array = | 585 info.is_array = |
475 (size > 1 || | 586 (size > 1 || |
476 (info.name.size() > 3 && | 587 (info.name.size() > 3 && |
477 info.name.rfind(kArraySpec) == info.name.size() - 3)); | 588 info.name.rfind(kArraySpec) == info.name.size() - 3)); |
478 | 589 |
479 return &info; | 590 if (info.IsSampler()) { |
| 591 sampler_indices_.push_back(info.fake_location_base); |
| 592 } |
| 593 max_uniform_name_length_ = |
| 594 std::max(max_uniform_name_length_, |
| 595 static_cast<GLsizei>(info.name.size())); |
| 596 |
| 597 while (*next_available_index < uniform_infos_.size() && |
| 598 uniform_infos_[*next_available_index].IsValid()) { |
| 599 *next_available_index = *next_available_index + 1; |
| 600 } |
| 601 |
| 602 return true; |
| 603 } |
| 604 |
| 605 const ProgramManager::ProgramInfo::UniformInfo* |
| 606 ProgramManager::ProgramInfo::GetUniformInfo( |
| 607 GLint index) const { |
| 608 if (static_cast<size_t>(index) >= uniform_infos_.size()) { |
| 609 return NULL; |
| 610 } |
| 611 |
| 612 const UniformInfo& info = uniform_infos_[index]; |
| 613 return info.IsValid() ? &info : NULL; |
480 } | 614 } |
481 | 615 |
482 bool ProgramManager::ProgramInfo::SetSamplers( | 616 bool ProgramManager::ProgramInfo::SetSamplers( |
483 GLint num_texture_units, GLint fake_location, | 617 GLint num_texture_units, GLint fake_location, |
484 GLsizei count, const GLint* value) { | 618 GLsizei count, const GLint* value) { |
485 if (fake_location < 0) { | 619 if (fake_location < 0) { |
486 return true; | 620 return true; |
487 } | 621 } |
488 GLint uniform_index = GetUniformInfoIndexFromFakeLocation(fake_location); | 622 GLint uniform_index = GetUniformInfoIndexFromFakeLocation(fake_location); |
489 if (uniform_index >= 0 && | 623 if (uniform_index >= 0 && |
490 static_cast<size_t>(uniform_index) < uniform_infos_.size()) { | 624 static_cast<size_t>(uniform_index) < uniform_infos_.size()) { |
491 UniformInfo& info = uniform_infos_[uniform_index]; | 625 UniformInfo& info = uniform_infos_[uniform_index]; |
| 626 if (!info.IsValid()) { |
| 627 return false; |
| 628 } |
492 GLint element_index = GetArrayElementIndexFromFakeLocation(fake_location); | 629 GLint element_index = GetArrayElementIndexFromFakeLocation(fake_location); |
493 if (element_index < info.size) { | 630 if (element_index < info.size) { |
494 count = std::min(info.size - element_index, count); | 631 count = std::min(info.size - element_index, count); |
495 if (info.IsSampler() && count > 0) { | 632 if (info.IsSampler() && count > 0) { |
496 for (GLsizei ii = 0; ii < count; ++ii) { | 633 for (GLsizei ii = 0; ii < count; ++ii) { |
497 if (value[ii] < 0 || value[ii] >= num_texture_units) { | 634 if (value[ii] < 0 || value[ii] >= num_texture_units) { |
498 return false; | 635 return false; |
499 } | 636 } |
500 } | 637 } |
501 std::copy(value, value + count, | 638 std::copy(value, value + count, |
502 info.texture_units.begin() + element_index); | 639 info.texture_units.begin() + element_index); |
503 return true; | 640 return true; |
504 } | 641 } |
505 } | 642 } |
506 } | 643 } |
507 return true; | 644 return true; |
508 } | 645 } |
509 | 646 |
510 void ProgramManager::ProgramInfo::GetProgramiv(GLenum pname, GLint* params) { | 647 void ProgramManager::ProgramInfo::GetProgramiv(GLenum pname, GLint* params) { |
511 switch (pname) { | 648 switch (pname) { |
512 case GL_ACTIVE_ATTRIBUTES: | 649 case GL_ACTIVE_ATTRIBUTES: |
513 *params = attrib_infos_.size(); | 650 *params = attrib_infos_.size(); |
514 break; | 651 break; |
515 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH: | 652 case GL_ACTIVE_ATTRIBUTE_MAX_LENGTH: |
516 // Notice +1 to accomodate NULL terminator. | 653 // Notice +1 to accomodate NULL terminator. |
517 *params = max_attrib_name_length_ + 1; | 654 *params = max_attrib_name_length_ + 1; |
518 break; | 655 break; |
519 case GL_ACTIVE_UNIFORMS: | 656 case GL_ACTIVE_UNIFORMS: |
520 *params = uniform_infos_.size(); | 657 *params = num_uniforms_; |
521 break; | 658 break; |
522 case GL_ACTIVE_UNIFORM_MAX_LENGTH: | 659 case GL_ACTIVE_UNIFORM_MAX_LENGTH: |
523 // Notice +1 to accomodate NULL terminator. | 660 // Notice +1 to accomodate NULL terminator. |
524 *params = max_uniform_name_length_ + 1; | 661 *params = max_uniform_name_length_ + 1; |
525 break; | 662 break; |
526 case GL_LINK_STATUS: | 663 case GL_LINK_STATUS: |
527 *params = link_status_; | 664 *params = link_status_; |
528 break; | 665 break; |
529 case GL_INFO_LOG_LENGTH: | 666 case GL_INFO_LOG_LENGTH: |
530 // Notice +1 to accomodate NULL terminator. | 667 // Notice +1 to accomodate NULL terminator. |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
586 for (int ii = 0; ii < kMaxAttachedShaders; ++ii) { | 723 for (int ii = 0; ii < kMaxAttachedShaders; ++ii) { |
587 if (!attached_shaders_[ii] || !attached_shaders_[ii]->IsValid()) { | 724 if (!attached_shaders_[ii] || !attached_shaders_[ii]->IsValid()) { |
588 return false; | 725 return false; |
589 } | 726 } |
590 } | 727 } |
591 return true; | 728 return true; |
592 } | 729 } |
593 | 730 |
594 bool ProgramManager::ProgramInfo::DetectAttribLocationBindingConflicts() const { | 731 bool ProgramManager::ProgramInfo::DetectAttribLocationBindingConflicts() const { |
595 std::set<GLint> location_binding_used; | 732 std::set<GLint> location_binding_used; |
596 for (std::map<std::string, GLint>::const_iterator it = | 733 for (LocationMap::const_iterator it = bind_attrib_location_map_.begin(); |
597 bind_attrib_location_map_.begin(); | |
598 it != bind_attrib_location_map_.end(); ++it) { | 734 it != bind_attrib_location_map_.end(); ++it) { |
599 // Find out if an attribute is declared in this program's shaders. | 735 // Find out if an attribute is declared in this program's shaders. |
600 bool active = false; | 736 bool active = false; |
601 for (int ii = 0; ii < kMaxAttachedShaders; ++ii) { | 737 for (int ii = 0; ii < kMaxAttachedShaders; ++ii) { |
602 if (!attached_shaders_[ii] || !attached_shaders_[ii]->IsValid()) | 738 if (!attached_shaders_[ii] || !attached_shaders_[ii]->IsValid()) |
603 continue; | 739 continue; |
604 if (attached_shaders_[ii]->GetAttribInfo(it->first)) { | 740 if (attached_shaders_[ii]->GetAttribInfo(it->first)) { |
605 active = true; | 741 active = true; |
606 break; | 742 break; |
607 } | 743 } |
(...skipping 23 matching lines...) Expand all Loading... |
631 uint32 total_string_size = 0; | 767 uint32 total_string_size = 0; |
632 | 768 |
633 for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) { | 769 for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) { |
634 const VertexAttribInfo& info = attrib_infos_[ii]; | 770 const VertexAttribInfo& info = attrib_infos_[ii]; |
635 num_locations += 1; | 771 num_locations += 1; |
636 total_string_size += info.name.size(); | 772 total_string_size += info.name.size(); |
637 } | 773 } |
638 | 774 |
639 for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) { | 775 for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) { |
640 const UniformInfo& info = uniform_infos_[ii]; | 776 const UniformInfo& info = uniform_infos_[ii]; |
641 num_locations += info.element_locations.size(); | 777 if (info.IsValid()) { |
642 total_string_size += info.name.size(); | 778 num_locations += info.element_locations.size(); |
| 779 total_string_size += info.name.size(); |
| 780 } |
643 } | 781 } |
644 | 782 |
645 uint32 num_inputs = attrib_infos_.size() + uniform_infos_.size(); | 783 uint32 num_inputs = attrib_infos_.size() + num_uniforms_; |
646 uint32 input_size = num_inputs * sizeof(ProgramInput); | 784 uint32 input_size = num_inputs * sizeof(ProgramInput); |
647 uint32 location_size = num_locations * sizeof(int32); | 785 uint32 location_size = num_locations * sizeof(int32); |
648 uint32 size = sizeof(ProgramInfoHeader) + | 786 uint32 size = sizeof(ProgramInfoHeader) + |
649 input_size + location_size + total_string_size; | 787 input_size + location_size + total_string_size; |
650 | 788 |
651 bucket->SetSize(size); | 789 bucket->SetSize(size); |
652 ProgramInfoHeader* header = bucket->GetDataAs<ProgramInfoHeader*>(0, size); | 790 ProgramInfoHeader* header = bucket->GetDataAs<ProgramInfoHeader*>(0, size); |
653 ProgramInput* inputs = bucket->GetDataAs<ProgramInput*>( | 791 ProgramInput* inputs = bucket->GetDataAs<ProgramInput*>( |
654 sizeof(ProgramInfoHeader), input_size); | 792 sizeof(ProgramInfoHeader), input_size); |
655 int32* locations = bucket->GetDataAs<int32*>( | 793 int32* locations = bucket->GetDataAs<int32*>( |
656 sizeof(ProgramInfoHeader) + input_size, location_size); | 794 sizeof(ProgramInfoHeader) + input_size, location_size); |
657 char* strings = bucket->GetDataAs<char*>( | 795 char* strings = bucket->GetDataAs<char*>( |
658 sizeof(ProgramInfoHeader) + input_size + location_size, | 796 sizeof(ProgramInfoHeader) + input_size + location_size, |
659 total_string_size); | 797 total_string_size); |
660 DCHECK(header); | 798 DCHECK(header); |
661 DCHECK(inputs); | 799 DCHECK(inputs); |
662 DCHECK(locations); | 800 DCHECK(locations); |
663 DCHECK(strings); | 801 DCHECK(strings); |
664 | 802 |
665 header->link_status = link_status_; | 803 header->link_status = link_status_; |
666 header->num_attribs = attrib_infos_.size(); | 804 header->num_attribs = attrib_infos_.size(); |
667 header->num_uniforms = uniform_infos_.size(); | 805 header->num_uniforms = num_uniforms_; |
668 | 806 |
669 for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) { | 807 for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) { |
670 const VertexAttribInfo& info = attrib_infos_[ii]; | 808 const VertexAttribInfo& info = attrib_infos_[ii]; |
671 inputs->size = info.size; | 809 inputs->size = info.size; |
672 inputs->type = info.type; | 810 inputs->type = info.type; |
673 inputs->location_offset = ComputeOffset(header, locations); | 811 inputs->location_offset = ComputeOffset(header, locations); |
674 inputs->name_offset = ComputeOffset(header, strings); | 812 inputs->name_offset = ComputeOffset(header, strings); |
675 inputs->name_length = info.name.size(); | 813 inputs->name_length = info.name.size(); |
676 *locations++ = info.location; | 814 *locations++ = info.location; |
677 memcpy(strings, info.name.c_str(), info.name.size()); | 815 memcpy(strings, info.name.c_str(), info.name.size()); |
678 strings += info.name.size(); | 816 strings += info.name.size(); |
679 ++inputs; | 817 ++inputs; |
680 } | 818 } |
681 | 819 |
682 for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) { | 820 for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) { |
683 const UniformInfo& info = uniform_infos_[ii]; | 821 const UniformInfo& info = uniform_infos_[ii]; |
684 inputs->size = info.size; | 822 if (info.IsValid()) { |
685 inputs->type = info.type; | 823 inputs->size = info.size; |
686 inputs->location_offset = ComputeOffset(header, locations); | 824 inputs->type = info.type; |
687 inputs->name_offset = ComputeOffset(header, strings); | 825 inputs->location_offset = ComputeOffset(header, locations); |
688 inputs->name_length = info.name.size(); | 826 inputs->name_offset = ComputeOffset(header, strings); |
689 DCHECK(static_cast<size_t>(info.size) == info.element_locations.size()); | 827 inputs->name_length = info.name.size(); |
690 for (size_t jj = 0; jj < info.element_locations.size(); ++jj) { | 828 DCHECK(static_cast<size_t>(info.size) == info.element_locations.size()); |
691 *locations++ = GLES2Util::SwizzleLocation( | 829 for (size_t jj = 0; jj < info.element_locations.size(); ++jj) { |
692 GLES2Util::MakeFakeLocation(ii, jj)); | 830 *locations++ = ProgramManager::MakeFakeLocation(ii, jj); |
| 831 } |
| 832 memcpy(strings, info.name.c_str(), info.name.size()); |
| 833 strings += info.name.size(); |
| 834 ++inputs; |
693 } | 835 } |
694 memcpy(strings, info.name.c_str(), info.name.size()); | |
695 strings += info.name.size(); | |
696 ++inputs; | |
697 } | 836 } |
698 | 837 |
699 DCHECK_EQ(ComputeOffset(header, strings), size); | 838 DCHECK_EQ(ComputeOffset(header, strings), size); |
700 } | 839 } |
701 | 840 |
702 ProgramManager::ProgramInfo::~ProgramInfo() { | 841 ProgramManager::ProgramInfo::~ProgramInfo() { |
703 if (manager_) { | 842 if (manager_) { |
704 if (manager_->have_context_) { | 843 if (manager_->have_context_) { |
705 glDeleteProgram(service_id()); | 844 glDeleteProgram(service_id()); |
706 } | 845 } |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
816 RemoveProgramInfoIfUnused(shader_manager, info); | 955 RemoveProgramInfoIfUnused(shader_manager, info); |
817 } | 956 } |
818 | 957 |
819 void ProgramManager::ClearUniforms(ProgramManager::ProgramInfo* info) { | 958 void ProgramManager::ClearUniforms(ProgramManager::ProgramInfo* info) { |
820 DCHECK(info); | 959 DCHECK(info); |
821 if (!disable_workarounds_) { | 960 if (!disable_workarounds_) { |
822 info->ClearUniforms(&zero_); | 961 info->ClearUniforms(&zero_); |
823 } | 962 } |
824 } | 963 } |
825 | 964 |
| 965 int32 ProgramManager::MakeFakeLocation(int32 index, int32 element) { |
| 966 return index + element * 0x10000; |
| 967 } |
| 968 |
826 } // namespace gles2 | 969 } // namespace gles2 |
827 } // namespace gpu | 970 } // namespace gpu |
828 | 971 |
829 | 972 |
OLD | NEW |