Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(785)

Side by Side Diff: gpu/command_buffer/service/program_manager.cc

Issue 887513002: Implement glGetUniformBlocksCHROMIUM: service side data packing (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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, &param);
1317 if (param == GL_TRUE) {
1318 param = 0;
1319 glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, &param);
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, &param);
1338 blocks[ii].binding = static_cast<uint32_t>(param);
1339
1340 param = 0;
1341 glGetActiveUniformBlockiv(program, ii, GL_UNIFORM_BLOCK_DATA_SIZE, &param);
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, &param);
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, &param);
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, &param);
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, &param);
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(&params[0], 0, num_bytes);
1403 glGetActiveUniformBlockiv(
1404 program, ii, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, &params[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
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
OLDNEW
« no previous file with comments | « gpu/command_buffer/service/program_manager.h ('k') | gpu/command_buffer/service/program_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698