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 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 } | 100 } |
101 | 101 |
102 bool IsBuiltInInvariant( | 102 bool IsBuiltInInvariant( |
103 const VaryingMap& varyings, const std::string& name) { | 103 const VaryingMap& varyings, const std::string& name) { |
104 VaryingMap::const_iterator hit = varyings.find(name); | 104 VaryingMap::const_iterator hit = varyings.find(name); |
105 if (hit == varyings.end()) | 105 if (hit == varyings.end()) |
106 return false; | 106 return false; |
107 return hit->second.isInvariant; | 107 return hit->second.isInvariant; |
108 } | 108 } |
109 | 109 |
| 110 uint32 ComputeOffset(const void* start, const void* position) { |
| 111 return static_cast<const uint8*>(position) - |
| 112 static_cast<const uint8*>(start); |
| 113 } |
| 114 |
110 } // anonymous namespace. | 115 } // anonymous namespace. |
111 | 116 |
112 Program::UniformInfo::UniformInfo() | 117 Program::UniformInfo::UniformInfo() |
113 : size(0), | 118 : size(0), |
114 type(GL_NONE), | 119 type(GL_NONE), |
115 fake_location_base(0), | 120 fake_location_base(0), |
116 is_array(false) { | 121 is_array(false) { |
117 } | 122 } |
118 | 123 |
119 Program::UniformInfo::UniformInfo(GLsizei _size, | 124 Program::UniformInfo::UniformInfo(GLsizei _size, |
(...skipping 1074 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1194 variables[index].type = iter->second.type; | 1199 variables[index].type = iter->second.type; |
1195 variables[index].size = iter->second.size; | 1200 variables[index].size = iter->second.size; |
1196 ++index; | 1201 ++index; |
1197 } | 1202 } |
1198 return ShCheckVariablesWithinPackingLimits( | 1203 return ShCheckVariablesWithinPackingLimits( |
1199 static_cast<int>(manager_->max_varying_vectors()), | 1204 static_cast<int>(manager_->max_varying_vectors()), |
1200 variables.get(), | 1205 variables.get(), |
1201 combined_map.size()); | 1206 combined_map.size()); |
1202 } | 1207 } |
1203 | 1208 |
1204 static uint32 ComputeOffset(const void* start, const void* position) { | |
1205 return static_cast<const uint8*>(position) - | |
1206 static_cast<const uint8*>(start); | |
1207 } | |
1208 | |
1209 void Program::GetProgramInfo( | 1209 void Program::GetProgramInfo( |
1210 ProgramManager* manager, CommonDecoder::Bucket* bucket) const { | 1210 ProgramManager* manager, CommonDecoder::Bucket* bucket) const { |
1211 // NOTE: It seems to me the math in here does not need check for overflow | 1211 // NOTE: It seems to me the math in here does not need check for overflow |
1212 // because the data being calucated from has various small limits. The max | 1212 // because the data being calucated from has various small limits. The max |
1213 // number of attribs + uniforms is somewhere well under 1024. The maximum size | 1213 // number of attribs + uniforms is somewhere well under 1024. The maximum size |
1214 // of an identifier is 256 characters. | 1214 // of an identifier is 256 characters. |
1215 uint32 num_locations = 0; | 1215 uint32 num_locations = 0; |
1216 uint32 total_string_size = 0; | 1216 uint32 total_string_size = 0; |
1217 | 1217 |
1218 for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) { | 1218 for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) { |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1283 } | 1283 } |
1284 memcpy(strings, info.name.c_str(), info.name.size()); | 1284 memcpy(strings, info.name.c_str(), info.name.size()); |
1285 strings += info.name.size(); | 1285 strings += info.name.size(); |
1286 ++inputs; | 1286 ++inputs; |
1287 } | 1287 } |
1288 } | 1288 } |
1289 | 1289 |
1290 DCHECK_EQ(ComputeOffset(header, strings), size); | 1290 DCHECK_EQ(ComputeOffset(header, strings), size); |
1291 } | 1291 } |
1292 | 1292 |
| 1293 bool Program::GetUniformBlocks(CommonDecoder::Bucket* bucket) const { |
| 1294 // The data is packed into the bucket in the following order |
| 1295 // 1) header |
| 1296 // 2) N entries of block data (except for name and indices) |
| 1297 // 3) name1, indices1, name2, indices2, ..., nameN, indicesN |
| 1298 // |
| 1299 // We query all the data directly through GL calls, assuming they are |
| 1300 // cheap through MANGLE. |
| 1301 |
| 1302 DCHECK(bucket); |
| 1303 GLuint program = service_id(); |
| 1304 |
| 1305 uint32_t header_size = sizeof(UniformBlocksHeader); |
| 1306 |
| 1307 uint32_t num_uniform_blocks = 0; |
| 1308 GLint param = GL_FALSE; |
| 1309 // We assume program is a valid program service id. |
| 1310 glGetProgramiv(program, GL_LINK_STATUS, ¶m); |
| 1311 if (param == GL_TRUE) { |
| 1312 param = 0; |
| 1313 glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, ¶m); |
| 1314 num_uniform_blocks = static_cast<uint32_t>(param); |
| 1315 } |
| 1316 if (num_uniform_blocks == 0) { |
| 1317 // Although spec allows an implementation to return uniform block info |
| 1318 // even if a link fails, for consistency, we disallow that. |
| 1319 bucket->SetSize(header_size); |
| 1320 UniformBlocksHeader* header = |
| 1321 bucket->GetDataAs<UniformBlocksHeader*>(0, header_size); |
| 1322 header->num_uniform_blocks = 0; |
| 1323 return true; |
| 1324 } |
| 1325 |
| 1326 std::vector<UniformBlockInfo> blocks(num_uniform_blocks); |
| 1327 base::CheckedNumeric<uint32_t> size = sizeof(UniformBlockInfo); |
| 1328 size *= num_uniform_blocks; |
| 1329 uint32_t entry_size = size.ValueOrDefault(0); |
| 1330 size += header_size; |
| 1331 std::vector<std::string> names(num_uniform_blocks); |
| 1332 GLint max_name_length = 0; |
| 1333 glGetProgramiv( |
| 1334 program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_name_length); |
| 1335 std::vector<GLchar> buffer(max_name_length); |
| 1336 GLsizei length; |
| 1337 for (uint32_t ii = 0; ii < num_uniform_blocks; ++ii) { |
| 1338 param = 0; |
| 1339 glGetActiveUniformBlockiv(program, ii, GL_UNIFORM_BLOCK_BINDING, ¶m); |
| 1340 blocks[ii].binding = static_cast<uint32_t>(param); |
| 1341 |
| 1342 param = 0; |
| 1343 glGetActiveUniformBlockiv(program, ii, GL_UNIFORM_BLOCK_DATA_SIZE, ¶m); |
| 1344 blocks[ii].data_size = static_cast<uint32_t>(param); |
| 1345 |
| 1346 blocks[ii].name_offset = size.ValueOrDefault(0); |
| 1347 param = 0; |
| 1348 glGetActiveUniformBlockiv( |
| 1349 program, ii, GL_UNIFORM_BLOCK_NAME_LENGTH, ¶m); |
| 1350 DCHECK_GE(max_name_length, param); |
| 1351 memset(&buffer[0], 0, param); |
| 1352 length = 0; |
| 1353 glGetActiveUniformBlockName( |
| 1354 program, ii, static_cast<GLsizei>(param), &length, &buffer[0]); |
| 1355 DCHECK_EQ(param, length + 1); |
| 1356 names[ii] = std::string(&buffer[0], length); |
| 1357 // TODO(zmo): optimize the name mapping lookup. |
| 1358 const std::string* original_name = GetOriginalNameFromHashedName(names[ii]); |
| 1359 if (original_name) |
| 1360 names[ii] = *original_name; |
| 1361 blocks[ii].name_length = names[ii].size() + 1; |
| 1362 size += blocks[ii].name_length; |
| 1363 |
| 1364 param = 0; |
| 1365 glGetActiveUniformBlockiv( |
| 1366 program, ii, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, ¶m); |
| 1367 blocks[ii].active_uniforms = static_cast<uint32_t>(param); |
| 1368 blocks[ii].active_uniform_offset = size.ValueOrDefault(0); |
| 1369 base::CheckedNumeric<uint32_t> indices_size = blocks[ii].active_uniforms; |
| 1370 indices_size *= sizeof(uint32_t); |
| 1371 if (!indices_size.IsValid()) |
| 1372 return false; |
| 1373 size += indices_size.ValueOrDefault(0); |
| 1374 |
| 1375 param = 0; |
| 1376 glGetActiveUniformBlockiv( |
| 1377 program, ii, GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER, ¶m); |
| 1378 blocks[ii].referenced_by_vertex_shader = static_cast<uint32_t>(param); |
| 1379 |
| 1380 param = 0; |
| 1381 glGetActiveUniformBlockiv( |
| 1382 program, ii, GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER, ¶m); |
| 1383 blocks[ii].referenced_by_fragment_shader = static_cast<uint32_t>(param); |
| 1384 } |
| 1385 if (!size.IsValid()) |
| 1386 return false; |
| 1387 uint32_t total_size = size.ValueOrDefault(0); |
| 1388 DCHECK_LE(header_size + entry_size, total_size); |
| 1389 uint32_t data_size = total_size - header_size - entry_size; |
| 1390 |
| 1391 bucket->SetSize(total_size); |
| 1392 UniformBlocksHeader* header = |
| 1393 bucket->GetDataAs<UniformBlocksHeader*>(0, total_size); |
| 1394 UniformBlockInfo* entries = bucket->GetDataAs<UniformBlockInfo*>( |
| 1395 header_size, entry_size); |
| 1396 char* data = bucket->GetDataAs<char*>(header_size + entry_size, data_size); |
| 1397 DCHECK(header); |
| 1398 DCHECK(entries); |
| 1399 DCHECK(data); |
| 1400 |
| 1401 // Copy over data for the header and entries. |
| 1402 header->num_uniform_blocks = num_uniform_blocks; |
| 1403 memcpy(entries, &blocks[0], entry_size); |
| 1404 |
| 1405 std::vector<GLint> params; |
| 1406 for (uint32_t ii = 0; ii < num_uniform_blocks; ++ii) { |
| 1407 // Get active uniform name. |
| 1408 memcpy(data, names[ii].c_str(), blocks[ii].name_length); |
| 1409 data += blocks[ii].name_length; |
| 1410 |
| 1411 // Get active uniform indices. |
| 1412 if (params.size() < blocks[ii].active_uniforms) |
| 1413 params.resize(blocks[ii].active_uniforms); |
| 1414 uint32_t num_bytes = blocks[ii].active_uniforms * sizeof(GLint); |
| 1415 memset(¶ms[0], 0, num_bytes); |
| 1416 glGetActiveUniformBlockiv( |
| 1417 program, ii, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, ¶ms[0]); |
| 1418 uint32_t* indices = reinterpret_cast<uint32_t*>(data); |
| 1419 for (uint32_t uu = 0; uu < blocks[ii].active_uniforms; ++uu) { |
| 1420 indices[uu] = static_cast<uint32_t>(params[uu]); |
| 1421 } |
| 1422 data += num_bytes; |
| 1423 } |
| 1424 DCHECK_EQ(ComputeOffset(header, data), total_size); |
| 1425 return true; |
| 1426 } |
| 1427 |
1293 Program::~Program() { | 1428 Program::~Program() { |
1294 if (manager_) { | 1429 if (manager_) { |
1295 if (manager_->have_context_) { | 1430 if (manager_->have_context_) { |
1296 glDeleteProgram(service_id()); | 1431 glDeleteProgram(service_id()); |
1297 } | 1432 } |
1298 manager_->StopTracking(this); | 1433 manager_->StopTracking(this); |
1299 manager_ = NULL; | 1434 manager_ = NULL; |
1300 } | 1435 } |
1301 } | 1436 } |
1302 | 1437 |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1415 DCHECK(program); | 1550 DCHECK(program); |
1416 program->ClearUniforms(&zero_); | 1551 program->ClearUniforms(&zero_); |
1417 } | 1552 } |
1418 | 1553 |
1419 int32 ProgramManager::MakeFakeLocation(int32 index, int32 element) { | 1554 int32 ProgramManager::MakeFakeLocation(int32 index, int32 element) { |
1420 return index + element * 0x10000; | 1555 return index + element * 0x10000; |
1421 } | 1556 } |
1422 | 1557 |
1423 } // namespace gles2 | 1558 } // namespace gles2 |
1424 } // namespace gpu | 1559 } // namespace gpu |
OLD | NEW |