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..a9aad10bd54ac9ef6eabc0faf1740dce1aa27b91 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,144 @@ void Program::GetProgramInfo( |
| DCHECK_EQ(ComputeOffset(header, strings), size); |
| } |
| +bool 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. |
| + |
| + 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 true; |
| + } |
| + |
| + std::vector<UniformBlockInfo> blocks(num_uniform_blocks); |
| + 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.
|
| + size *= num_uniform_blocks; |
| + size_t entry_size = size.ValueOrDefault(0); |
| + size += header_size; |
| + std::vector<std::string> names(num_uniform_blocks); |
| + GLint max_name_length = 0; |
| + glGetProgramiv( |
| + program, GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH, &max_name_length); |
| + std::vector<GLchar> buffer(max_name_length); |
| + GLsizei length; |
| + 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>(size.ValueOrDefault(0)); |
| + param = 0; |
| + glGetActiveUniformBlockiv( |
| + program, ii, GL_UNIFORM_BLOCK_NAME_LENGTH, ¶m); |
| + DCHECK_GE(max_name_length, param); |
| + memset(&buffer[0], 0, param); |
| + length = 0; |
| + glGetActiveUniformBlockName( |
| + program, ii, static_cast<GLsizei>(param), &length, &buffer[0]); |
| + DCHECK_EQ(param, length + 1); |
| + names[ii] = std::string(&buffer[0], length); |
| + // TODO(zmo): optimize the name mapping lookup. |
| + const std::string* original_name = GetOriginalNameFromHashedName(names[ii]); |
| + if (original_name) |
| + names[ii] = *original_name; |
| + blocks[ii].name_length = names[ii].size() + 1; |
| + size += blocks[ii].name_length; |
| + |
| + 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>(size.ValueOrDefault(0)); |
| + base::CheckedNumeric<size_t> indices_size = blocks[ii].active_uniforms; |
| + indices_size *= sizeof(uint32_t); |
| + if (!indices_size.IsValid()) |
| + return false; |
| + size += indices_size.ValueOrDefault(0); |
| + |
| + 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); |
| + } |
| + if (!size.IsValid()) |
| + return false; |
| + size_t total_size = size.ValueOrDefault(0); |
| + 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; |
| + 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); |
| + memcpy(data, names[ii].c_str(), num_bytes); |
| + 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); |
| + return true; |
| +} |
| + |
| Program::~Program() { |
| if (manager_) { |
| if (manager_->have_context_) { |