diff options
author | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-28 01:09:54 +0000 |
---|---|---|
committer | gman@chromium.org <gman@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2012-04-28 01:09:54 +0000 |
commit | 2df73893433f075f59c1090b1fc3eb3de876d2ad (patch) | |
tree | df5d59eebea0742eb5f161d72ac83afd1093bfad /gpu | |
parent | 93bb08dd51c803739d5e964bc69299bf2b8a3f85 (diff) | |
download | chromium_src-2df73893433f075f59c1090b1fc3eb3de876d2ad.zip chromium_src-2df73893433f075f59c1090b1fc3eb3de876d2ad.tar.gz chromium_src-2df73893433f075f59c1090b1fc3eb3de876d2ad.tar.bz2 |
Clear uniforms
TEST=unit tests
BUG=124764
R=zmo@chromium.org
Review URL: http://codereview.chromium.org/10246004
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@134418 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'gpu')
5 files changed, 186 insertions, 8 deletions
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 4a8e752..cc864ab 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -4462,7 +4462,11 @@ void GLES2DecoderImpl::DoLinkProgram(GLuint program) { return; } - info->Link(); + if (info->Link()) { + if (info == current_program_.get()) { + program_manager()->ClearUniforms(info); + } + } }; void GLES2DecoderImpl::DoTexParameterf( @@ -4776,10 +4780,10 @@ void GLES2DecoderImpl::DoUseProgram(GLuint program) { program_manager()->UnuseProgram(shader_manager(), current_program_); } current_program_ = info; + glUseProgram(service_id); if (current_program_) { program_manager()->UseProgram(current_program_); } - glUseProgram(service_id); } GLenum GLES2DecoderImpl::GetGLError() { diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc index c0b1e8c..40e98d4 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc @@ -1255,6 +1255,86 @@ void GLES2DecoderTestBase::SetupShader( link_cmd.Init(program_client_id); EXPECT_EQ(error::kNoError, ExecuteCmd(link_cmd)); + + // Assume the next command will be UseProgram. + SetupExpectationsForClearingUniforms(uniforms, num_uniforms); +} + +void GLES2DecoderTestBase::SetupExpectationsForClearingUniforms( + UniformInfo* uniforms, size_t num_uniforms) { + for (size_t ii = 0; ii < num_uniforms; ++ii) { + const UniformInfo& info = uniforms[ii]; + switch (info.type) { + case GL_FLOAT: + EXPECT_CALL(*gl_, Uniform1fv(info.real_location, info.size, _)) + .Times(1) + .RetiresOnSaturation(); + break; + case GL_FLOAT_VEC2: + EXPECT_CALL(*gl_, Uniform2fv(info.real_location, info.size, _)) + .Times(1) + .RetiresOnSaturation(); + break; + case GL_FLOAT_VEC3: + EXPECT_CALL(*gl_, Uniform3fv(info.real_location, info.size, _)) + .Times(1) + .RetiresOnSaturation(); + break; + case GL_FLOAT_VEC4: + EXPECT_CALL(*gl_, Uniform4fv(info.real_location, info.size, _)) + .Times(1) + .RetiresOnSaturation(); + break; + case GL_INT: + case GL_BOOL: + case GL_SAMPLER_2D: + case GL_SAMPLER_CUBE: + case GL_SAMPLER_EXTERNAL_OES: + EXPECT_CALL(*gl_, Uniform1iv(info.real_location, info.size, _)) + .Times(1) + .RetiresOnSaturation(); + break; + case GL_INT_VEC2: + case GL_BOOL_VEC2: + EXPECT_CALL(*gl_, Uniform2iv(info.real_location, info.size, _)) + .Times(1) + .RetiresOnSaturation(); + break; + case GL_INT_VEC3: + case GL_BOOL_VEC3: + EXPECT_CALL(*gl_, Uniform3iv(info.real_location, info.size, _)) + .Times(1) + .RetiresOnSaturation(); + break; + case GL_INT_VEC4: + case GL_BOOL_VEC4: + EXPECT_CALL(*gl_, Uniform4iv(info.real_location, info.size, _)) + .Times(1) + .RetiresOnSaturation(); + break; + case GL_FLOAT_MAT2: + EXPECT_CALL(*gl_, UniformMatrix2fv( + info.real_location, info.size, false, _)) + .Times(1) + .RetiresOnSaturation(); + break; + case GL_FLOAT_MAT3: + EXPECT_CALL(*gl_, UniformMatrix3fv( + info.real_location, info.size, false, _)) + .Times(1) + .RetiresOnSaturation(); + break; + case GL_FLOAT_MAT4: + EXPECT_CALL(*gl_, UniformMatrix4fv( + info.real_location, info.size, false, _)) + .Times(1) + .RetiresOnSaturation(); + break; + default: + NOTREACHED(); + break; + } + } } void GLES2DecoderTestBase::DoEnableVertexAttribArray(GLint index) { diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h index 85bfe1d..64d47f6 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.h @@ -176,6 +176,9 @@ class GLES2DecoderTestBase : public testing::Test { GLuint vertex_shader_client_id, GLuint vertex_shader_service_id, GLuint fragment_shader_client_id, GLuint fragment_shader_service_id); + void SetupExpectationsForClearingUniforms( + UniformInfo* uniforms, size_t num_uniforms); + // Setups up a shader for testing glUniform. void SetupShaderForUniform(); void SetupDefaultProgram(); diff --git a/gpu/command_buffer/service/program_manager.cc b/gpu/command_buffer/service/program_manager.cc index e40d23a..1669173 100644 --- a/gpu/command_buffer/service/program_manager.cc +++ b/gpu/command_buffer/service/program_manager.cc @@ -12,6 +12,7 @@ #include "base/memory/scoped_ptr.h" #include "base/string_number_conversions.h" #include "gpu/command_buffer/common/gles2_cmd_format.h" +#include "gpu/command_buffer/common/gles2_cmd_utils.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" namespace gpu { @@ -58,7 +59,8 @@ ProgramManager::ProgramInfo::ProgramInfo( service_id_(service_id), deleted_(false), valid_(false), - link_status_(false) { + link_status_(false), + uniforms_cleared_(false) { manager_->StartTracking(this); } @@ -88,10 +90,80 @@ void ProgramManager::ProgramInfo::UpdateLogInfo() { set_log_info(std::string(temp.get(), len).c_str()); } +void ProgramManager::ProgramInfo::ClearUniforms( + std::vector<uint8>* zero_buffer) { + DCHECK(zero_buffer); + if (uniforms_cleared_) { + return; + } + uniforms_cleared_ = true; + for (size_t ii = 0; ii < uniform_infos_.size(); ++ii) { + const UniformInfo& uniform_info = uniform_infos_[ii]; + GLint location = uniform_info.element_locations[0]; + GLsizei size = uniform_info.size; + uint32 unit_size = GLES2Util::GetGLDataTypeSizeForUniforms( + uniform_info.type); + uint32 size_needed = size * unit_size; + if (size_needed > zero_buffer->size()) { + zero_buffer->resize(size_needed, 0u); + } + const void* zero = &(*zero_buffer)[0]; + switch (uniform_info.type) { + case GL_FLOAT: + glUniform1fv(location, size, reinterpret_cast<const GLfloat*>(zero)); + break; + case GL_FLOAT_VEC2: + glUniform2fv(location, size, reinterpret_cast<const GLfloat*>(zero)); + break; + case GL_FLOAT_VEC3: + glUniform3fv(location, size, reinterpret_cast<const GLfloat*>(zero)); + break; + case GL_FLOAT_VEC4: + glUniform4fv(location, size, reinterpret_cast<const GLfloat*>(zero)); + break; + case GL_INT: + case GL_BOOL: + case GL_SAMPLER_2D: + case GL_SAMPLER_CUBE: + case GL_SAMPLER_EXTERNAL_OES: + glUniform1iv(location, size, reinterpret_cast<const GLint*>(zero)); + break; + case GL_INT_VEC2: + case GL_BOOL_VEC2: + glUniform2iv(location, size, reinterpret_cast<const GLint*>(zero)); + break; + case GL_INT_VEC3: + case GL_BOOL_VEC3: + glUniform3iv(location, size, reinterpret_cast<const GLint*>(zero)); + break; + case GL_INT_VEC4: + case GL_BOOL_VEC4: + glUniform4iv(location, size, reinterpret_cast<const GLint*>(zero)); + break; + case GL_FLOAT_MAT2: + glUniformMatrix2fv( + location, size, false, reinterpret_cast<const GLfloat*>(zero)); + break; + case GL_FLOAT_MAT3: + glUniformMatrix3fv( + location, size, false, reinterpret_cast<const GLfloat*>(zero)); + break; + case GL_FLOAT_MAT4: + glUniformMatrix4fv( + location, size, false, reinterpret_cast<const GLfloat*>(zero)); + break; + default: + NOTREACHED(); + break; + } + } +} + void ProgramManager::ProgramInfo::Update() { Reset(); UpdateLogInfo(); link_status_ = true; + uniforms_cleared_ = false; GLint num_attribs = 0; GLint max_len = 0; GLint max_location = -1; @@ -177,25 +249,26 @@ void ProgramManager::ProgramInfo::ExecuteBindAttribLocationCalls() { } } -void ProgramManager::ProgramInfo::Link() { +bool ProgramManager::ProgramInfo::Link() { ClearLinkStatus(); if (!CanLink()) { set_log_info("missing shaders"); - return; + return false; } if (DetectAttribLocationBindingConflicts()) { set_log_info("glBindAttribLocation() conflicts"); - return; + return false; } ExecuteBindAttribLocationCalls(); glLinkProgram(service_id()); GLint success = 0; glGetProgramiv(service_id(), GL_LINK_STATUS, &success); - if (success) { + if (success == GL_TRUE) { Update(); } else { UpdateLogInfo(); } + return success == GL_TRUE; } void ProgramManager::ProgramInfo::Validate() { @@ -692,6 +765,7 @@ void ProgramManager::UseProgram(ProgramManager::ProgramInfo* info) { DCHECK(info); DCHECK(IsOwned(info)); info->IncUseCount(); + ClearUniforms(info); } void ProgramManager::UnuseProgram( @@ -704,6 +778,11 @@ void ProgramManager::UnuseProgram( RemoveProgramInfoIfUnused(shader_manager, info); } +void ProgramManager::ClearUniforms(ProgramManager::ProgramInfo* info) { + DCHECK(info); + info->ClearUniforms(&zero_); +} + // Swizzles the locations to prevent developers from assuming they // can do math on uniforms. According to the OpenGL ES 2.0 spec // the location of "someuniform[1]" is not 'n' more than "someuniform[0]". diff --git a/gpu/command_buffer/service/program_manager.h b/gpu/command_buffer/service/program_manager.h index 232db91..43433f8 100644 --- a/gpu/command_buffer/service/program_manager.h +++ b/gpu/command_buffer/service/program_manager.h @@ -144,7 +144,7 @@ class GPU_EXPORT ProgramManager { bool CanLink() const; // Performs glLinkProgram and related activities. - void Link(); + bool Link(); // Performs glValidateProgram and related activities. void Validate(); @@ -211,6 +211,9 @@ class GPU_EXPORT ProgramManager { // Updates the program log info from GL void UpdateLogInfo(); + // Clears all the uniforms. + void ClearUniforms(std::vector<uint8>* zero_buffer); + // If long attribate names are mapped during shader translation, call // glBindAttribLocation() again with the mapped names. // This is called right before the glLink() call, but after shaders are @@ -272,6 +275,9 @@ class GPU_EXPORT ProgramManager { // This is true if glLinkProgram was successful last time it was called. bool link_status_; + // True if the uniforms have been cleared. + bool uniforms_cleared_; + // Log info scoped_ptr<std::string> log_info_; @@ -303,6 +309,9 @@ class GPU_EXPORT ProgramManager { // Makes a program as unused. If deleted the program info will be removed. void UnuseProgram(ShaderManager* shader_manager, ProgramInfo* info); + // Clears the uniforms for this program. + void ClearUniforms(ProgramInfo* info); + // Returns true if prefix is invalid for gl. static bool IsInvalidPrefix(const char* name, size_t length); @@ -329,6 +338,9 @@ class GPU_EXPORT ProgramManager { bool have_context_; + // Used to clear uniforms. + std::vector<uint8> zero_; + void RemoveProgramInfoIfUnused( ShaderManager* shader_manager, ProgramInfo* info); |