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 void 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 // Security wise, the math in here does not need check for overflow | |
| 1303 // because the data being calucated from has various small limits. | |
| 1304 // See: MAX_VERTEX/FRAGMENT_UNIFORM_COMPONENTS (sample value: 896), | |
| 1305 // MAX_VERTEX/FRAGMENT_UNIFORM_BLOCKS (sample value: 12), | |
| 1306 // max size of an idenfifier: 1024. | |
|
piman
2015/01/28 23:29:42
We haven't checked all drivers though, including f
Zhenyao Mo
2015/01/29 01:45:36
OK, I'll use CheckedNumeric instead then.
| |
| 1307 | |
| 1308 DCHECK(bucket); | |
| 1309 GLuint program = service_id(); | |
| 1310 | |
| 1311 size_t header_size = sizeof(UniformBlocksHeader); | |
| 1312 | |
| 1313 GLuint num_uniform_blocks = 0; | |
| 1314 GLint param = GL_FALSE; | |
| 1315 // We assume program is a valid program service id. | |
| 1316 glGetProgramiv(program, GL_LINK_STATUS, ¶m); | |
| 1317 if (param == GL_TRUE) { | |
| 1318 param = 0; | |
| 1319 glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, ¶m); | |
| 1320 num_uniform_blocks = static_cast<GLuint>(param); | |
| 1321 } | |
| 1322 if (num_uniform_blocks == 0) { | |
| 1323 // Although spec allows an implementation to return uniform block info | |
| 1324 // even if a link fails, for consistency, we disallow that. | |
| 1325 bucket->SetSize(header_size); | |
| 1326 UniformBlocksHeader* header = | |
| 1327 bucket->GetDataAs<UniformBlocksHeader*>(0, header_size); | |
| 1328 header->num_uniform_blocks = 0; | |
| 1329 return; | |
| 1330 } | |
| 1331 | |
| 1332 std::vector<UniformBlockInfo> blocks(num_uniform_blocks); | |
| 1333 size_t entry_size = sizeof(UniformBlockInfo) * num_uniform_blocks; | |
| 1334 size_t total_size = header_size + entry_size; | |
| 1335 for (GLuint ii = 0; ii < num_uniform_blocks; ++ii) { | |
| 1336 param = 0; | |
| 1337 glGetActiveUniformBlockiv(program, ii, GL_UNIFORM_BLOCK_BINDING, ¶m); | |
| 1338 blocks[ii].binding = static_cast<uint32_t>(param); | |
| 1339 | |
| 1340 param = 0; | |
| 1341 glGetActiveUniformBlockiv(program, ii, GL_UNIFORM_BLOCK_DATA_SIZE, ¶m); | |
| 1342 blocks[ii].data_size = static_cast<uint32_t>(param); | |
| 1343 | |
| 1344 blocks[ii].name_offset = static_cast<uint32_t>(total_size); | |
| 1345 param = 0; | |
| 1346 glGetActiveUniformBlockiv( | |
| 1347 program, ii, GL_UNIFORM_BLOCK_NAME_LENGTH, ¶m); | |
| 1348 blocks[ii].name_length = static_cast<uint32_t>(param); | |
| 1349 total_size += blocks[ii].name_length; | |
|
piman
2015/01/28 23:29:42
Do we need to deal with remapped uniform names, wh
Zhenyao Mo
2015/01/29 01:45:36
Done.
| |
| 1350 | |
| 1351 param = 0; | |
| 1352 glGetActiveUniformBlockiv( | |
| 1353 program, ii, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, ¶m); | |
| 1354 blocks[ii].active_uniforms = static_cast<uint32_t>(param); | |
| 1355 blocks[ii].active_uniform_offset = static_cast<uint32_t>(total_size); | |
| 1356 total_size += sizeof(uint32_t) * blocks[ii].active_uniforms; | |
| 1357 | |
| 1358 param = 0; | |
| 1359 glGetActiveUniformBlockiv( | |
| 1360 program, ii, GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER, ¶m); | |
| 1361 blocks[ii].referenced_by_vertex_shader = static_cast<uint32_t>(param); | |
| 1362 | |
| 1363 param = 0; | |
| 1364 glGetActiveUniformBlockiv( | |
| 1365 program, ii, GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER, ¶m); | |
| 1366 blocks[ii].referenced_by_fragment_shader = static_cast<uint32_t>(param); | |
| 1367 } | |
| 1368 DCHECK_LE(header_size + entry_size, total_size); | |
| 1369 size_t data_size = total_size - header_size - entry_size; | |
| 1370 | |
| 1371 bucket->SetSize(total_size); | |
| 1372 UniformBlocksHeader* header = | |
| 1373 bucket->GetDataAs<UniformBlocksHeader*>(0, total_size); | |
| 1374 UniformBlockInfo* entries = bucket->GetDataAs<UniformBlockInfo*>( | |
| 1375 header_size, entry_size); | |
| 1376 char* data = bucket->GetDataAs<char*>(header_size + entry_size, data_size); | |
| 1377 DCHECK(header); | |
| 1378 DCHECK(entries); | |
| 1379 DCHECK(data); | |
| 1380 | |
| 1381 // Copy over data for the header and entries. | |
| 1382 header->num_uniform_blocks = static_cast<uint32_t>(num_uniform_blocks); | |
| 1383 memcpy(entries, &blocks[0], entry_size); | |
| 1384 | |
| 1385 std::vector<GLint> params; | |
| 1386 GLsizei length; | |
| 1387 for (size_t ii = 0; ii < num_uniform_blocks; ++ii) { | |
| 1388 // Get active uniform name. | |
| 1389 size_t num_bytes = static_cast<size_t>(blocks[ii].name_length); | |
| 1390 memset(data, 0, num_bytes); | |
| 1391 length = 0; | |
| 1392 glGetActiveUniformBlockName( | |
| 1393 program, ii, static_cast<GLsizei>(num_bytes), &length, data); | |
| 1394 DCHECK_EQ(num_bytes, static_cast<size_t>(length) + 1); | |
| 1395 data += num_bytes; | |
| 1396 | |
| 1397 // Get active uniform indices. | |
| 1398 if (params.size() < blocks[ii].active_uniforms) | |
| 1399 params.resize(blocks[ii].active_uniforms); | |
| 1400 num_bytes = | |
| 1401 static_cast<size_t>(blocks[ii].active_uniforms) * sizeof(GLint); | |
| 1402 memset(¶ms[0], 0, num_bytes); | |
| 1403 glGetActiveUniformBlockiv( | |
| 1404 program, ii, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, ¶ms[0]); | |
| 1405 uint32_t* indices = reinterpret_cast<uint32_t*>(data); | |
| 1406 for (uint32_t uu = 0; uu < blocks[ii].active_uniforms; ++uu) { | |
| 1407 indices[uu] = static_cast<uint32_t>(params[uu]); | |
| 1408 } | |
| 1409 data += num_bytes; | |
| 1410 } | |
| 1411 DCHECK_EQ(ComputeOffset(header, data), total_size); | |
| 1412 } | |
| 1413 | |
| 1293 Program::~Program() { | 1414 Program::~Program() { |
| 1294 if (manager_) { | 1415 if (manager_) { |
| 1295 if (manager_->have_context_) { | 1416 if (manager_->have_context_) { |
| 1296 glDeleteProgram(service_id()); | 1417 glDeleteProgram(service_id()); |
| 1297 } | 1418 } |
| 1298 manager_->StopTracking(this); | 1419 manager_->StopTracking(this); |
| 1299 manager_ = NULL; | 1420 manager_ = NULL; |
| 1300 } | 1421 } |
| 1301 } | 1422 } |
| 1302 | 1423 |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1415 DCHECK(program); | 1536 DCHECK(program); |
| 1416 program->ClearUniforms(&zero_); | 1537 program->ClearUniforms(&zero_); |
| 1417 } | 1538 } |
| 1418 | 1539 |
| 1419 int32 ProgramManager::MakeFakeLocation(int32 index, int32 element) { | 1540 int32 ProgramManager::MakeFakeLocation(int32 index, int32 element) { |
| 1420 return index + element * 0x10000; | 1541 return index + element * 0x10000; |
| 1421 } | 1542 } |
| 1422 | 1543 |
| 1423 } // namespace gles2 | 1544 } // namespace gles2 |
| 1424 } // namespace gpu | 1545 } // namespace gpu |
| OLD | NEW |