| 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..d866504c5e950120760bd2d5707d8bd764a8aa29 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,141 @@ 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();
|
| +
|
| + uint32_t header_size = sizeof(UniformBlocksHeader);
|
| +
|
| + uint32_t 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<uint32_t>(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<uint32_t> size = sizeof(UniformBlockInfo);
|
| + size *= num_uniform_blocks;
|
| + uint32_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 (uint32_t 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 = 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 = size.ValueOrDefault(0);
|
| + base::CheckedNumeric<uint32_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;
|
| + uint32_t total_size = size.ValueOrDefault(0);
|
| + DCHECK_LE(header_size + entry_size, total_size);
|
| + uint32_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 = num_uniform_blocks;
|
| + memcpy(entries, &blocks[0], entry_size);
|
| +
|
| + std::vector<GLint> params;
|
| + for (uint32_t ii = 0; ii < num_uniform_blocks; ++ii) {
|
| + // Get active uniform name.
|
| + memcpy(data, names[ii].c_str(), blocks[ii].name_length);
|
| + data += blocks[ii].name_length;
|
| +
|
| + // Get active uniform indices.
|
| + if (params.size() < blocks[ii].active_uniforms)
|
| + params.resize(blocks[ii].active_uniforms);
|
| + uint32_t num_bytes = 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_) {
|
|
|