Chromium Code Reviews| Index: gpu/command_buffer/service/program_manager.cc |
| diff --git a/gpu/command_buffer/service/program_manager.cc b/gpu/command_buffer/service/program_manager.cc |
| index d77635085b41baf596f2678c3f65522bf30e5892..f64619ddb473b6d7ef46c60e1b6aa9ba0d02b200 100644 |
| --- a/gpu/command_buffer/service/program_manager.cc |
| +++ b/gpu/command_buffer/service/program_manager.cc |
| @@ -107,6 +107,11 @@ bool IsBuiltInInvariant( |
| return hit->second.isInvariant; |
| } |
| +uint32 ComputeOffset(const void* start, const void* position) { |
| + return static_cast<const uint8*>(position) - |
| + static_cast<const uint8*>(start); |
| +} |
| + |
| } // anonymous namespace. |
| Program::UniformInfo::UniformInfo() |
| @@ -1201,11 +1206,6 @@ bool Program::CheckVaryingsPacking( |
| combined_map.size()); |
| } |
| -static uint32 ComputeOffset(const void* start, const void* position) { |
| - return static_cast<const uint8*>(position) - |
| - static_cast<const uint8*>(start); |
| -} |
| - |
| void Program::GetProgramInfo( |
| ProgramManager* manager, CommonDecoder::Bucket* bucket) const { |
| // NOTE: It seems to me the math in here does not need check for overflow |
| @@ -1290,6 +1290,127 @@ void Program::GetProgramInfo( |
| DCHECK_EQ(ComputeOffset(header, strings), size); |
| } |
| +void Program::GetUniformBlocks(CommonDecoder::Bucket* bucket) const { |
| + // The data is packed into the bucket in the following order |
| + // 1) header |
| + // 2) N entries of block data (except for name and indices) |
| + // 3) name1, indices1, name2, indices2, ..., nameN, indicesN |
| + // |
| + // We query all the data directly through GL calls, assuming they are |
| + // cheap through MANGLE. |
| + // |
| + // Security wise, the math in here does not need check for overflow |
| + // because the data being calucated from has various small limits. |
| + // See: MAX_VERTEX/FRAGMENT_UNIFORM_COMPONENTS (sample value: 896), |
| + // MAX_VERTEX/FRAGMENT_UNIFORM_BLOCKS (sample value: 12), |
| + // 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.
|
| + |
| + DCHECK(bucket); |
| + GLuint program = service_id(); |
| + |
| + size_t header_size = sizeof(UniformBlocksHeader); |
| + |
| + GLuint num_uniform_blocks = 0; |
| + GLint param = GL_FALSE; |
| + // We assume program is a valid program service id. |
| + glGetProgramiv(program, GL_LINK_STATUS, ¶m); |
| + if (param == GL_TRUE) { |
| + param = 0; |
| + glGetProgramiv(program, GL_ACTIVE_UNIFORM_BLOCKS, ¶m); |
| + num_uniform_blocks = static_cast<GLuint>(param); |
| + } |
| + if (num_uniform_blocks == 0) { |
| + // Although spec allows an implementation to return uniform block info |
| + // even if a link fails, for consistency, we disallow that. |
| + bucket->SetSize(header_size); |
| + UniformBlocksHeader* header = |
| + bucket->GetDataAs<UniformBlocksHeader*>(0, header_size); |
| + header->num_uniform_blocks = 0; |
| + return; |
| + } |
| + |
| + std::vector<UniformBlockInfo> blocks(num_uniform_blocks); |
| + size_t entry_size = sizeof(UniformBlockInfo) * num_uniform_blocks; |
| + size_t total_size = header_size + entry_size; |
| + for (GLuint ii = 0; ii < num_uniform_blocks; ++ii) { |
| + param = 0; |
| + glGetActiveUniformBlockiv(program, ii, GL_UNIFORM_BLOCK_BINDING, ¶m); |
| + blocks[ii].binding = static_cast<uint32_t>(param); |
| + |
| + param = 0; |
| + glGetActiveUniformBlockiv(program, ii, GL_UNIFORM_BLOCK_DATA_SIZE, ¶m); |
| + blocks[ii].data_size = static_cast<uint32_t>(param); |
| + |
| + blocks[ii].name_offset = static_cast<uint32_t>(total_size); |
| + param = 0; |
| + glGetActiveUniformBlockiv( |
| + program, ii, GL_UNIFORM_BLOCK_NAME_LENGTH, ¶m); |
| + blocks[ii].name_length = static_cast<uint32_t>(param); |
| + 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.
|
| + |
| + param = 0; |
| + glGetActiveUniformBlockiv( |
| + program, ii, GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS, ¶m); |
| + blocks[ii].active_uniforms = static_cast<uint32_t>(param); |
| + blocks[ii].active_uniform_offset = static_cast<uint32_t>(total_size); |
| + total_size += sizeof(uint32_t) * blocks[ii].active_uniforms; |
| + |
| + param = 0; |
| + glGetActiveUniformBlockiv( |
| + program, ii, GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER, ¶m); |
| + blocks[ii].referenced_by_vertex_shader = static_cast<uint32_t>(param); |
| + |
| + param = 0; |
| + glGetActiveUniformBlockiv( |
| + program, ii, GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER, ¶m); |
| + blocks[ii].referenced_by_fragment_shader = static_cast<uint32_t>(param); |
| + } |
| + DCHECK_LE(header_size + entry_size, total_size); |
| + size_t data_size = total_size - header_size - entry_size; |
| + |
| + bucket->SetSize(total_size); |
| + UniformBlocksHeader* header = |
| + bucket->GetDataAs<UniformBlocksHeader*>(0, total_size); |
| + UniformBlockInfo* entries = bucket->GetDataAs<UniformBlockInfo*>( |
| + header_size, entry_size); |
| + char* data = bucket->GetDataAs<char*>(header_size + entry_size, data_size); |
| + DCHECK(header); |
| + DCHECK(entries); |
| + DCHECK(data); |
| + |
| + // Copy over data for the header and entries. |
| + header->num_uniform_blocks = static_cast<uint32_t>(num_uniform_blocks); |
| + memcpy(entries, &blocks[0], entry_size); |
| + |
| + std::vector<GLint> params; |
| + GLsizei length; |
| + for (size_t ii = 0; ii < num_uniform_blocks; ++ii) { |
| + // Get active uniform name. |
| + size_t num_bytes = static_cast<size_t>(blocks[ii].name_length); |
| + memset(data, 0, num_bytes); |
| + length = 0; |
| + glGetActiveUniformBlockName( |
| + program, ii, static_cast<GLsizei>(num_bytes), &length, data); |
| + DCHECK_EQ(num_bytes, static_cast<size_t>(length) + 1); |
| + data += num_bytes; |
| + |
| + // Get active uniform indices. |
| + if (params.size() < blocks[ii].active_uniforms) |
| + params.resize(blocks[ii].active_uniforms); |
| + num_bytes = |
| + static_cast<size_t>(blocks[ii].active_uniforms) * sizeof(GLint); |
| + memset(¶ms[0], 0, num_bytes); |
| + glGetActiveUniformBlockiv( |
| + program, ii, GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES, ¶ms[0]); |
| + uint32_t* indices = reinterpret_cast<uint32_t*>(data); |
| + for (uint32_t uu = 0; uu < blocks[ii].active_uniforms; ++uu) { |
| + indices[uu] = static_cast<uint32_t>(params[uu]); |
| + } |
| + data += num_bytes; |
| + } |
| + DCHECK_EQ(ComputeOffset(header, data), total_size); |
| +} |
| + |
| Program::~Program() { |
| if (manager_) { |
| if (manager_->have_context_) { |