Chromium Code Reviews| 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 size_t header_size = sizeof(UniformBlocksHeader); | |
| 1306 | |
| 1307 GLuint 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<GLuint>(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<size_t> size = sizeof(UniformBlockInfo); | |
|
piman
2015/01/29 02:05:16
CheckedNumeric<uint32_t> (here and other places) s
Zhenyao Mo
2015/01/29 17:52:30
Done.
| |
| 1328 size *= num_uniform_blocks; | |
| 1329 size_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 (GLuint 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 = static_cast<uint32_t>(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 = | |
| 1369 static_cast<uint32_t>(size.ValueOrDefault(0)); | |
| 1370 base::CheckedNumeric<size_t> indices_size = blocks[ii].active_uniforms; | |
| 1371 indices_size *= sizeof(uint32_t); | |
| 1372 if (!indices_size.IsValid()) | |
| 1373 return false; | |
| 1374 size += indices_size.ValueOrDefault(0); | |
| 1375 | |
| 1376 param = 0; | |
| 1377 glGetActiveUniformBlockiv( | |
| 1378 program, ii, GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER, ¶m); | |
| 1379 blocks[ii].referenced_by_vertex_shader = static_cast<uint32_t>(param); | |
| 1380 | |
| 1381 param = 0; | |
| 1382 glGetActiveUniformBlockiv( | |
| 1383 program, ii, GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER, ¶m); | |
| 1384 blocks[ii].referenced_by_fragment_shader = static_cast<uint32_t>(param); | |
| 1385 } | |
| 1386 if (!size.IsValid()) | |
| 1387 return false; | |
| 1388 size_t total_size = size.ValueOrDefault(0); | |
| 1389 DCHECK_LE(header_size + entry_size, total_size); | |
| 1390 size_t data_size = total_size - header_size - entry_size; | |
| 1391 | |
| 1392 bucket->SetSize(total_size); | |
| 1393 UniformBlocksHeader* header = | |
| 1394 bucket->GetDataAs<UniformBlocksHeader*>(0, total_size); | |
| 1395 UniformBlockInfo* entries = bucket->GetDataAs<UniformBlockInfo*>( | |
| 1396 header_size, entry_size); | |
| 1397 char* data = bucket->GetDataAs<char*>(header_size + entry_size, data_size); | |
| 1398 DCHECK(header); | |
| 1399 DCHECK(entries); | |
| 1400 DCHECK(data); | |
| 1401 | |
| 1402 // Copy over data for the header and entries. | |
| 1403 header->num_uniform_blocks = static_cast<uint32_t>(num_uniform_blocks); | |
| 1404 memcpy(entries, &blocks[0], entry_size); | |
| 1405 | |
| 1406 std::vector<GLint> params; | |
| 1407 for (size_t ii = 0; ii < num_uniform_blocks; ++ii) { | |
| 1408 // Get active uniform name. | |
| 1409 size_t num_bytes = static_cast<size_t>(blocks[ii].name_length); | |
| 1410 memcpy(data, names[ii].c_str(), num_bytes); | |
| 1411 data += num_bytes; | |
| 1412 | |
| 1413 // Get active uniform indices. | |
| 1414 if (params.size() < blocks[ii].active_uniforms) | |
| 1415 params.resize(blocks[ii].active_uniforms); | |
| 1416 num_bytes = | |
| 1417 static_cast<size_t>(blocks[ii].active_uniforms) * sizeof(GLint); | |
| 1418 memset(¶ms[0], 0, num_bytes); | |
| 1419 glGetActiveUniformBlockiv( | |
| 1420 program, ii, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, ¶ms[0]); | |
| 1421 uint32_t* indices = reinterpret_cast<uint32_t*>(data); | |
| 1422 for (uint32_t uu = 0; uu < blocks[ii].active_uniforms; ++uu) { | |
| 1423 indices[uu] = static_cast<uint32_t>(params[uu]); | |
| 1424 } | |
| 1425 data += num_bytes; | |
| 1426 } | |
| 1427 DCHECK_EQ(ComputeOffset(header, data), total_size); | |
| 1428 return true; | |
| 1429 } | |
| 1430 | |
| 1293 Program::~Program() { | 1431 Program::~Program() { |
| 1294 if (manager_) { | 1432 if (manager_) { |
| 1295 if (manager_->have_context_) { | 1433 if (manager_->have_context_) { |
| 1296 glDeleteProgram(service_id()); | 1434 glDeleteProgram(service_id()); |
| 1297 } | 1435 } |
| 1298 manager_->StopTracking(this); | 1436 manager_->StopTracking(this); |
| 1299 manager_ = NULL; | 1437 manager_ = NULL; |
| 1300 } | 1438 } |
| 1301 } | 1439 } |
| 1302 | 1440 |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1415 DCHECK(program); | 1553 DCHECK(program); |
| 1416 program->ClearUniforms(&zero_); | 1554 program->ClearUniforms(&zero_); |
| 1417 } | 1555 } |
| 1418 | 1556 |
| 1419 int32 ProgramManager::MakeFakeLocation(int32 index, int32 element) { | 1557 int32 ProgramManager::MakeFakeLocation(int32 index, int32 element) { |
| 1420 return index + element * 0x10000; | 1558 return index + element * 0x10000; |
| 1421 } | 1559 } |
| 1422 | 1560 |
| 1423 } // namespace gles2 | 1561 } // namespace gles2 |
| 1424 } // namespace gpu | 1562 } // namespace gpu |
| OLD | NEW |