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 |