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 94e7bdeaa0cdec21a92f42e1a4cd6ccc859bf212..fa8af4d13253a715c4b54c03a09ab53175be8c50 100644 |
--- a/gpu/command_buffer/service/program_manager.cc |
+++ b/gpu/command_buffer/service/program_manager.cc |
@@ -117,20 +117,22 @@ uint32 ComputeOffset(const void* start, const void* position) { |
Program::UniformInfo::UniformInfo() |
: size(0), |
type(GL_NONE), |
+ accepts_api_type(0), |
fake_location_base(0), |
- is_array(false) { |
-} |
+ is_array(false) {} |
-Program::UniformInfo::UniformInfo(GLsizei _size, |
+Program::UniformInfo::UniformInfo(const std::string& client_name, |
+ int client_location_base, |
GLenum _type, |
- int _fake_location_base, |
- const std::string& _name) |
- : size(_size), |
+ bool _is_array, |
+ const std::vector<GLint>& service_locations) |
+ : size(service_locations.size()), |
type(_type), |
accepts_api_type(0), |
- fake_location_base(_fake_location_base), |
- is_array(false), |
- name(_name) { |
+ fake_location_base(client_location_base), |
+ is_array(_is_array), |
+ name(client_name), |
+ element_locations(service_locations) { |
switch (type) { |
case GL_INT: |
accepts_api_type = kUniform1i; |
@@ -236,8 +238,13 @@ Program::UniformInfo::UniformInfo(GLsizei _size, |
NOTREACHED() << "Unhandled UniformInfo type " << type; |
break; |
} |
-} |
+ DCHECK_LT(0, size); |
+ DCHECK(is_array || size == 1); |
+ size_t num_texture_units = IsSampler() ? static_cast<size_t>(size) : 0u; |
+ texture_units.clear(); |
+ texture_units.resize(num_texture_units, 0); |
+} |
Program::UniformInfo::~UniformInfo() {} |
bool ProgramManager::IsInvalidPrefix(const char* name, size_t length) { |
@@ -256,7 +263,6 @@ Program::Program(ProgramManager* manager, GLuint service_id) |
valid_(false), |
link_status_(false), |
uniforms_cleared_(false), |
- num_uniforms_(0), |
transform_feedback_buffer_mode_(GL_NONE) { |
manager_->StartTracking(this); |
} |
@@ -264,11 +270,11 @@ Program::Program(ProgramManager* manager, GLuint service_id) |
void Program::Reset() { |
valid_ = false; |
link_status_ = false; |
- num_uniforms_ = 0; |
max_uniform_name_length_ = 0; |
max_attrib_name_length_ = 0; |
attrib_infos_.clear(); |
uniform_infos_.clear(); |
+ uniform_locations_.clear(); |
fragment_input_infos_.clear(); |
sampler_indices_.clear(); |
attrib_location_to_index_map_.clear(); |
@@ -320,11 +326,7 @@ void Program::ClearUniforms( |
return; |
} |
uniforms_cleared_ = true; |
- for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) { |
- const UniformInfo& uniform_info = uniform_infos_[ii]; |
- if (!uniform_info.IsValid()) { |
- continue; |
- } |
+ for (const UniformInfo& uniform_info : uniform_infos_) { |
GLint location = uniform_info.element_locations[0]; |
GLsizei size = uniform_info.size; |
uint32 unit_size = |
@@ -442,22 +444,6 @@ void Program::ClearUniforms( |
} |
} |
-namespace { |
- |
-struct UniformData { |
- UniformData() : size(-1), type(GL_NONE), location(0), added(false) { |
- } |
- std::string queried_name; |
- std::string corrected_name; |
- std::string original_name; |
- GLsizei size; |
- GLenum type; |
- GLint location; |
- bool added; |
-}; |
- |
-} // anonymous namespace |
- |
void Program::Update() { |
Reset(); |
UpdateLogInfo(); |
@@ -513,95 +499,163 @@ void Program::Update() { |
} |
} |
#endif |
+ UpdateUniforms(); |
+ |
+#if !defined(NDEBUG) |
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
+ switches::kEnableGPUServiceLoggingGPU)) { |
+ DVLOG(1) << "----: uniforms for service_id: " << service_id(); |
+ size_t ii = 0; |
+ for (const UniformInfo& info : uniform_infos_) { |
+ DVLOG(1) << ii++ << ": loc = " << info.element_locations[0] |
+ << ", size = " << info.size |
+ << ", type = " << GLES2Util::GetStringEnum(info.type) |
+ << ", name = " << info.name; |
+ } |
+ } |
+#endif |
+ |
+ UpdateFragmentInputs(); |
+ |
+ valid_ = true; |
+} |
+ |
+void Program::UpdateUniforms() { |
+ // Reserve each client-bound uniform location. This way unbound uniforms will |
+ // not be allocated to locations that user expects bound uniforms to be, even |
+ // if the expected uniforms are optimized away by the driver. |
+ for (const auto& binding : bind_uniform_location_map_) { |
+ if (binding.second < 0) |
+ continue; |
+ size_t client_location = static_cast<size_t>(binding.second); |
+ if (uniform_locations_.size() <= client_location) |
+ uniform_locations_.resize(client_location + 1); |
+ uniform_locations_[client_location].SetInactive(); |
+ } |
- max_len = 0; |
GLint num_uniforms = 0; |
glGetProgramiv(service_id_, GL_ACTIVE_UNIFORMS, &num_uniforms); |
- glGetProgramiv(service_id_, GL_ACTIVE_UNIFORM_MAX_LENGTH, &max_len); |
- DCHECK(num_uniforms <= 0 || max_len > 0); |
- name_buffer.reset(new char[max_len]); |
+ if (num_uniforms <= 0) |
+ return; |
- // Reads all the names. |
- std::vector<UniformData> uniform_data; |
- for (GLint ii = 0; ii < num_uniforms; ++ii) { |
- GLsizei length = 0; |
- UniformData data; |
- glGetActiveUniform( |
- service_id_, ii, max_len, &length, |
- &data.size, &data.type, name_buffer.get()); |
- DCHECK(length < max_len); |
- DCHECK(length == 0 || name_buffer[length] == '\0'); |
- data.queried_name = std::string(name_buffer.get()); |
- GetCorrectedUniformData(data.queried_name, &data.corrected_name, |
- &data.original_name, &data.size, &data.type); |
- uniform_data.push_back(data); |
- } |
+ uniform_infos_.resize(num_uniforms); |
- // NOTE: We don't care if 2 uniforms are bound to the same location. |
- // One of them will take preference. The spec allows this, same as |
- // BindAttribLocation. |
- // |
- // The reason we don't check is if we were to fail we'd have to |
- // restore the previous program but since we've already linked successfully |
- // at this point the previous program is gone. |
- |
- // Assigns the uniforms with bindings. |
- size_t next_available_index = 0; |
- for (size_t ii = 0; ii < uniform_data.size(); ++ii) { |
- UniformData& data = uniform_data[ii]; |
+ GLint name_buffer_length = 0; |
+ glGetProgramiv(service_id_, GL_ACTIVE_UNIFORM_MAX_LENGTH, |
+ &name_buffer_length); |
+ DCHECK(name_buffer_length > 0); |
+ scoped_ptr<char[]> name_buffer(new char[name_buffer_length]); |
+ |
+ size_t unused_client_location_cursor = 0; |
+ |
+ for (GLint uniform_index = 0; uniform_index < num_uniforms; ++uniform_index) { |
+ GLsizei name_length = 0; |
+ GLsizei size = 0; |
+ GLenum type = GL_NONE; |
+ glGetActiveUniform(service_id_, uniform_index, name_buffer_length, |
+ &name_length, &size, &type, name_buffer.get()); |
+ DCHECK(name_length < name_buffer_length); |
+ DCHECK(name_length == 0 || name_buffer[name_length] == '\0'); |
+ std::string service_name(name_buffer.get(), name_length); |
+ |
+ GLint service_location = -1; |
// Force builtin uniforms (gl_DepthRange) to have invalid location. |
- if (ProgramManager::IsInvalidPrefix(data.queried_name.c_str(), |
- data.queried_name.size())) { |
- data.location = -1; |
- } else { |
- data.location = |
- glGetUniformLocation(service_id_, data.queried_name.c_str()); |
- } |
- // remove "[0]" |
- std::string short_name; |
- int element_index = 0; |
- bool good = GetUniformNameSansElement(data.original_name, &element_index, |
- &short_name); |
- DCHECK(good); |
- LocationMap::const_iterator it = bind_uniform_location_map_.find( |
- short_name); |
- if (it != bind_uniform_location_map_.end()) { |
- AddUniformInfo( |
- data.size, data.type, data.location, it->second, data.corrected_name, |
- data.original_name, &next_available_index); |
- data.added = true; |
+ if (!ProgramManager::IsInvalidPrefix(service_name.c_str(), |
+ service_name.size())) { |
+ service_location = |
+ glGetUniformLocation(service_id_, service_name.c_str()); |
} |
- } |
- // Assigns the uniforms that were not bound. |
- for (size_t ii = 0; ii < uniform_data.size(); ++ii) { |
- const UniformData& data = uniform_data[ii]; |
- if (!data.added) { |
- AddUniformInfo( |
- data.size, data.type, data.location, -1, data.corrected_name, |
- data.original_name, &next_available_index); |
+ // Determine the client name of the uniform and whether it is an array |
+ // or not. |
+ bool is_array; |
+ std::string client_name; |
+ for (size_t i = 0; i < kMaxAttachedShaders && client_name.empty(); ++i) { |
+ const auto& shader = attached_shaders_[i]; |
+ if (!shader) |
+ continue; |
+ const sh::ShaderVariable* info = nullptr; |
+ const sh::Uniform* uniform = shader->GetUniformInfo(service_name); |
+ if (uniform && |
+ uniform->findInfoByMappedName(service_name, &info, &client_name)) { |
+ DCHECK(!client_name.empty()); |
+ is_array = info->arraySize > 0; |
+ type = info->type; |
+ size = std::max(1u, info->arraySize); |
+ } |
+ } |
+ if (client_name.empty()) { |
+ // This happens only in cases where we do not have ANGLE or run unit tests |
+ // (or ANGLE has a severe bug). |
+ client_name = service_name; |
+ GLSLArrayName parsed_service_name(service_name); |
+ is_array = size > 1 || parsed_service_name.IsArrayName(); |
+ } |
+ |
+ std::string service_base_name = service_name; |
+ std::string client_base_name = client_name; |
+ if (is_array) { |
+ // Some drivers incorrectly return an uniform name of size-1 array without |
+ // "[0]". In this case, we correct the service name by appending "[0]" to |
+ // it. |
+ GLSLArrayName parsed_service_name(service_name); |
+ if (parsed_service_name.IsArrayName()) { |
+ service_base_name = parsed_service_name.base_name(); |
+ GLSLArrayName parsed_client_name(client_name); |
+ client_base_name = parsed_client_name.base_name(); |
+ } else { |
+ service_name += "[0]"; |
+ client_name += "[0]"; |
+ } |
} |
- } |
-#if !defined(NDEBUG) |
- if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
- switches::kEnableGPUServiceLoggingGPU)) { |
- DVLOG(1) << "----: uniforms for service_id: " << service_id(); |
- for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) { |
- const UniformInfo& info = uniform_infos_[ii]; |
- if (info.IsValid()) { |
- DVLOG(1) << ii << ": loc = " << info.element_locations[0] |
- << ", size = " << info.size |
- << ", type = " << GLES2Util::GetStringEnum(info.type) |
- << ", name = " << info.name; |
+ // Assign a location for the uniform: use either client-bound |
+ // location or automatically assigned to an unused location. |
+ size_t client_location_base = 0; |
+ LocationMap::const_iterator it = |
+ bind_uniform_location_map_.find(client_base_name); |
+ if (it != bind_uniform_location_map_.end()) { |
+ client_location_base = it->second; |
+ } else { |
+ while (unused_client_location_cursor < uniform_locations_.size() && |
+ !uniform_locations_[unused_client_location_cursor].IsUnused()) |
+ unused_client_location_cursor++; |
+ if (unused_client_location_cursor == uniform_locations_.size()) |
+ uniform_locations_.resize(unused_client_location_cursor + 1); |
+ client_location_base = unused_client_location_cursor; |
+ unused_client_location_cursor++; |
+ } |
+ |
+ // Populate the uniform list entry. |
+ std::vector<GLint> service_locations; |
+ service_locations.resize(size); |
+ service_locations[0] = service_location; |
+ |
+ if (size > 1) { |
+ for (GLsizei ii = 1; ii < size; ++ii) { |
+ std::string element_name(service_base_name + "[" + |
+ base::IntToString(ii) + "]"); |
+ service_locations[ii] = |
+ glGetUniformLocation(service_id_, element_name.c_str()); |
} |
} |
- } |
-#endif |
- UpdateFragmentInputs(); |
+ UniformInfo& info = uniform_infos_[uniform_index]; |
+ info = UniformInfo(client_name, client_location_base, type, is_array, |
+ service_locations); |
+ if (info.IsSampler()) { |
+ sampler_indices_.push_back(uniform_index); |
+ } |
- valid_ = true; |
+ // Populate the uniform location list entry. |
+ // Before linking, we already validated that no two statically used uniforms |
+ // are bound to the same location. |
+ DCHECK(!uniform_locations_[client_location_base].IsActive()); |
+ uniform_locations_[client_location_base].SetActive(&info); |
+ |
+ max_uniform_name_length_ = std::max(max_uniform_name_length_, |
+ static_cast<GLsizei>(info.name.size())); |
+ } |
} |
void Program::UpdateFragmentInputs() { |
@@ -914,11 +968,7 @@ GLint Program::GetUniformFakeLocation( |
const std::string& name) const { |
GLSLArrayName parsed_name(name); |
- for (GLuint ii = 0; ii < uniform_infos_.size(); ++ii) { |
- const UniformInfo& info = uniform_infos_[ii]; |
- if (!info.IsValid()) { |
- continue; |
- } |
+ for (const UniformInfo& info : uniform_infos_) { |
if (info.name == name || |
(info.is_array && |
info.name.compare(0, info.name.size() - 3, name) == 0)) { |
@@ -928,7 +978,6 @@ GLint Program::GetUniformFakeLocation( |
size_t open_pos = info.name.find_last_of('['); |
if (info.name.compare(0, open_pos, parsed_name.base_name()) == 0) { |
int index = parsed_name.element_index(); |
- DCHECK(index >= 0); |
if (index < info.size) { |
DCHECK_GT(static_cast<int>(info.element_locations.size()), index); |
if (info.element_locations[index] == -1) |
@@ -958,25 +1007,34 @@ const Program::UniformInfo* |
GLint fake_location, GLint* real_location, GLint* array_index) const { |
DCHECK(real_location); |
DCHECK(array_index); |
- if (fake_location < 0) { |
- return NULL; |
- } |
+ if (fake_location < 0) |
+ return nullptr; |
+ size_t location_index = |
+ GetUniformLocationIndexFromFakeLocation(fake_location); |
+ if (location_index >= uniform_locations_.size()) |
+ return nullptr; |
- GLint uniform_index = GetUniformInfoIndexFromFakeLocation(fake_location); |
- if (uniform_index >= 0 && |
- static_cast<size_t>(uniform_index) < uniform_infos_.size()) { |
- const UniformInfo& uniform_info = uniform_infos_[uniform_index]; |
- if (!uniform_info.IsValid()) { |
- return NULL; |
- } |
- GLint element_index = GetArrayElementIndexFromFakeLocation(fake_location); |
- if (element_index < uniform_info.size) { |
- *real_location = uniform_info.element_locations[element_index]; |
- *array_index = element_index; |
- return &uniform_info; |
- } |
- } |
- return NULL; |
+ if (!uniform_locations_[location_index].IsActive()) |
+ return nullptr; |
+ |
+ const UniformInfo* info = uniform_locations_[location_index].uniform(); |
+ size_t element_index = GetArrayElementIndexFromFakeLocation(fake_location); |
+ if (static_cast<GLsizei>(element_index) >= info->size) |
+ return nullptr; |
+ *real_location = info->element_locations[element_index]; |
+ *array_index = element_index; |
+ return info; |
+} |
+ |
+bool Program::IsInactiveUniformLocationByFakeLocation( |
+ GLint fake_location) const { |
+ if (fake_location < 0) |
+ return true; |
+ size_t location_index = |
+ GetUniformLocationIndexFromFakeLocation(fake_location); |
+ if (location_index >= uniform_locations_.size()) |
+ return false; |
zmo
2015/11/20 00:23:42
Question: why false here?
Kimmo Kinnunen
2015/11/20 07:56:53
The function returns true only for locations of in
|
+ return uniform_locations_[location_index].IsInactive(); |
} |
const std::string* Program::GetAttribMappedName( |
@@ -1056,41 +1114,6 @@ void Program::SetFragmentInputLocationBinding(const std::string& name, |
bind_fragment_input_location_map_[name + "[0]"] = location; |
} |
-// Note: This is only valid to call right after a program has been linked |
-// successfully. |
-void Program::GetCorrectedUniformData( |
- const std::string& name, |
- std::string* corrected_name, std::string* original_name, |
- GLsizei* size, GLenum* type) const { |
- DCHECK(corrected_name && original_name && size && type); |
- for (auto shader : attached_shaders_) { |
- if (!shader) |
- continue; |
- const sh::ShaderVariable* info = NULL; |
- const sh::Uniform* uniform = shader->GetUniformInfo(name); |
- bool found = false; |
- if (uniform) |
- found = uniform->findInfoByMappedName(name, &info, original_name); |
- if (found) { |
- const std::string kArraySpec("[0]"); |
- if (info->arraySize > 0 && |
- !base::EndsWith(name, kArraySpec, base::CompareCase::SENSITIVE)) { |
- *corrected_name = name + kArraySpec; |
- *original_name += kArraySpec; |
- } else { |
- *corrected_name = name; |
- } |
- *type = info->type; |
- *size = std::max(1u, info->arraySize); |
- return; |
- } |
- } |
- // TODO(zmo): this path should never be reached unless there is a serious |
- // bug in the driver or in ANGLE translator. |
- *corrected_name = name; |
- *original_name = name; |
-} |
- |
void Program::GetVertexAttribData( |
const std::string& name, std::string* original_name, GLenum* type) const { |
DCHECK(original_name); |
@@ -1112,81 +1135,13 @@ void Program::GetVertexAttribData( |
*original_name = name; |
} |
-void Program::AddUniformInfo( |
- GLsizei size, GLenum type, GLint location, GLint fake_base_location, |
- const std::string& name, const std::string& original_name, |
- size_t* next_available_index) { |
- DCHECK(next_available_index); |
- const char* kArraySpec = "[0]"; |
- size_t uniform_index = |
- fake_base_location >= 0 ? fake_base_location : *next_available_index; |
- if (uniform_infos_.size() < uniform_index + 1) { |
- uniform_infos_.resize(uniform_index + 1); |
- } |
- |
- // Before linking, we already validated that no two statically used uniforms |
- // are bound to the same location. |
- DCHECK(!uniform_infos_[uniform_index].IsValid()); |
- |
- uniform_infos_[uniform_index] = UniformInfo( |
- size, type, uniform_index, original_name); |
- ++num_uniforms_; |
- |
- UniformInfo& info = uniform_infos_[uniform_index]; |
- info.element_locations.resize(size); |
- info.element_locations[0] = location; |
- DCHECK_LE(0, size); |
- size_t num_texture_units = info.IsSampler() ? static_cast<size_t>(size) : 0u; |
- info.texture_units.clear(); |
- info.texture_units.resize(num_texture_units, 0); |
- |
- if (size > 1) { |
- // Go through the array element locations looking for a match. |
- // We can skip the first element because it's the same as the |
- // the location without the array operators. |
- size_t array_pos = name.rfind(kArraySpec); |
- std::string base_name = name; |
- if (name.size() > 3) { |
- if (array_pos != name.size() - 3) { |
- info.name = name + kArraySpec; |
- } else { |
- base_name = name.substr(0, name.size() - 3); |
- } |
- } |
- for (GLsizei ii = 1; ii < info.size; ++ii) { |
- std::string element_name(base_name + "[" + base::IntToString(ii) + "]"); |
- info.element_locations[ii] = |
- glGetUniformLocation(service_id_, element_name.c_str()); |
- } |
- } |
- |
- info.is_array = |
- (size > 1 || |
- (info.name.size() > 3 && |
- info.name.rfind(kArraySpec) == info.name.size() - 3)); |
- |
- if (info.IsSampler()) { |
- sampler_indices_.push_back(info.fake_location_base); |
- } |
- max_uniform_name_length_ = |
- std::max(max_uniform_name_length_, |
- static_cast<GLsizei>(info.name.size())); |
- |
- while (*next_available_index < uniform_infos_.size() && |
- uniform_infos_[*next_available_index].IsValid()) { |
- *next_available_index = *next_available_index + 1; |
- } |
-} |
- |
const Program::UniformInfo* |
Program::GetUniformInfo( |
GLint index) const { |
if (static_cast<size_t>(index) >= uniform_infos_.size()) { |
return NULL; |
} |
- |
- const UniformInfo& info = uniform_infos_[index]; |
- return info.IsValid() ? &info : NULL; |
+ return &uniform_infos_[index]; |
} |
bool Program::SetSamplers( |
@@ -1195,27 +1150,29 @@ bool Program::SetSamplers( |
if (fake_location < 0) { |
return true; |
} |
- GLint uniform_index = GetUniformInfoIndexFromFakeLocation(fake_location); |
- if (uniform_index >= 0 && |
- static_cast<size_t>(uniform_index) < uniform_infos_.size()) { |
- UniformInfo& info = uniform_infos_[uniform_index]; |
- if (!info.IsValid()) { |
- return false; |
- } |
- GLint element_index = GetArrayElementIndexFromFakeLocation(fake_location); |
- if (element_index < info.size) { |
- count = std::min(info.size - element_index, count); |
- if (info.IsSampler() && count > 0) { |
- for (GLsizei ii = 0; ii < count; ++ii) { |
- if (value[ii] < 0 || value[ii] >= num_texture_units) { |
- return false; |
- } |
- } |
- std::copy(value, value + count, |
- info.texture_units.begin() + element_index); |
- return true; |
+ size_t location_index = |
+ GetUniformLocationIndexFromFakeLocation(fake_location); |
+ if (location_index >= uniform_infos_.size()) |
+ return false; |
+ |
+ if (!uniform_locations_[location_index].IsActive()) |
+ return false; |
+ |
+ UniformInfo* info = uniform_locations_[location_index].uniform(); |
+ |
+ size_t element_index = GetArrayElementIndexFromFakeLocation(fake_location); |
+ if (static_cast<GLsizei>(element_index) >= info->size) |
+ return true; |
+ count = std::min(info->size - static_cast<GLsizei>(element_index), count); |
+ if (info->IsSampler() && count > 0) { |
+ for (GLsizei ii = 0; ii < count; ++ii) { |
+ if (value[ii] < 0 || value[ii] >= num_texture_units) { |
+ return false; |
} |
} |
+ std::copy(value, value + count, |
+ info->texture_units.begin() + element_index); |
+ return true; |
} |
return true; |
} |
@@ -1230,7 +1187,7 @@ void Program::GetProgramiv(GLenum pname, GLint* params) { |
*params = max_attrib_name_length_ + 1; |
break; |
case GL_ACTIVE_UNIFORMS: |
- *params = num_uniforms_; |
+ *params = uniform_infos_.size(); |
break; |
case GL_ACTIVE_UNIFORM_MAX_LENGTH: |
// Notice +1 to accomodate NULL terminator. |
@@ -1592,15 +1549,12 @@ void Program::GetProgramInfo( |
total_string_size += info.name.size(); |
} |
- for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) { |
- const UniformInfo& info = uniform_infos_[ii]; |
- if (info.IsValid()) { |
- num_locations += info.element_locations.size(); |
- total_string_size += info.name.size(); |
- } |
+ for (const UniformInfo& info : uniform_infos_) { |
+ num_locations += info.element_locations.size(); |
+ total_string_size += info.name.size(); |
} |
- uint32 num_inputs = attrib_infos_.size() + num_uniforms_; |
+ uint32 num_inputs = attrib_infos_.size() + uniform_infos_.size(); |
uint32 input_size = num_inputs * sizeof(ProgramInput); |
uint32 location_size = num_locations * sizeof(int32); |
uint32 size = sizeof(ProgramInfoHeader) + |
@@ -1622,7 +1576,7 @@ void Program::GetProgramInfo( |
header->link_status = link_status_; |
header->num_attribs = attrib_infos_.size(); |
- header->num_uniforms = num_uniforms_; |
+ header->num_uniforms = uniform_infos_.size(); |
for (size_t ii = 0; ii < attrib_infos_.size(); ++ii) { |
const VertexAttrib& info = attrib_infos_[ii]; |
@@ -1637,26 +1591,26 @@ void Program::GetProgramInfo( |
++inputs; |
} |
- for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) { |
- const UniformInfo& info = uniform_infos_[ii]; |
- if (info.IsValid()) { |
- inputs->size = info.size; |
- inputs->type = info.type; |
- inputs->location_offset = ComputeOffset(header, locations); |
- inputs->name_offset = ComputeOffset(header, strings); |
- inputs->name_length = info.name.size(); |
- DCHECK(static_cast<size_t>(info.size) == info.element_locations.size()); |
- for (size_t jj = 0; jj < info.element_locations.size(); ++jj) { |
- if (info.element_locations[jj] == -1) |
- *locations++ = -1; |
- else |
- *locations++ = ProgramManager::MakeFakeLocation(ii, jj); |
- } |
- memcpy(strings, info.name.c_str(), info.name.size()); |
- strings += info.name.size(); |
- ++inputs; |
+ for (const UniformInfo& info : uniform_infos_) { |
+ inputs->size = info.size; |
+ inputs->type = info.type; |
+ inputs->location_offset = ComputeOffset(header, locations); |
+ inputs->name_offset = ComputeOffset(header, strings); |
+ inputs->name_length = info.name.size(); |
+ DCHECK(static_cast<size_t>(info.size) == info.element_locations.size()); |
+ for (size_t jj = 0; jj < info.element_locations.size(); ++jj) { |
+ if (info.element_locations[jj] == -1) |
+ *locations++ = -1; |
+ else |
+ *locations++ = |
+ ProgramManager::MakeFakeLocation(info.fake_location_base, jj); |
} |
+ memcpy(strings, info.name.c_str(), info.name.size()); |
+ strings += info.name.size(); |
+ ++inputs; |
} |
+ // NOTE: currently we do not pass inactive uniform binding locations |
+ // through the program info call. |
// NOTE: currently we do not pass fragment input infos through the program |
// info call, because they are not exposed through any getter function. |