Index: gpu/command_buffer/service/program_manager_unittest.cc |
diff --git a/gpu/command_buffer/service/program_manager_unittest.cc b/gpu/command_buffer/service/program_manager_unittest.cc |
index 8dca84db7e752ad89fe0be4f2dd26c43b82b36b1..e1cc44158d65e1a6cfc2bb7af0554f2da5d1b5bb 100644 |
--- a/gpu/command_buffer/service/program_manager_unittest.cc |
+++ b/gpu/command_buffer/service/program_manager_unittest.cc |
@@ -13,6 +13,7 @@ |
#include "gpu/command_buffer/common/gles2_cmd_format.h" |
#include "gpu/command_buffer/common/gles2_cmd_utils.h" |
#include "gpu/command_buffer/service/common_decoder.h" |
+#include "gpu/command_buffer/service/feature_info.h" |
#include "gpu/command_buffer/service/mocks.h" |
#include "gpu/command_buffer/service/test_helper.h" |
#include "testing/gtest/include/gtest/gtest.h" |
@@ -35,7 +36,7 @@ namespace gles2 { |
class ProgramManagerTest : public testing::Test { |
public: |
- ProgramManagerTest() { } |
+ ProgramManagerTest() : manager_(NULL) { } |
~ProgramManagerTest() { |
manager_.Destroy(false); |
} |
@@ -134,7 +135,7 @@ TEST_F(ProgramManagerTest, ProgramInfo) { |
class ProgramManagerWithShaderTest : public testing::Test { |
public: |
ProgramManagerWithShaderTest() |
- : program_info_(NULL) { |
+ : manager_(NULL), program_info_(NULL) { |
} |
~ProgramManagerWithShaderTest() { |
@@ -218,7 +219,7 @@ class ProgramManagerWithShaderTest : public testing::Test { |
program_info_->AttachShader(&shader_manager_, vertex_shader); |
program_info_->AttachShader(&shader_manager_, fragment_shader); |
- program_info_->Link(); |
+ program_info_->Link(NULL, NULL, NULL, NULL); |
} |
void SetupShader(AttribInfo* attribs, size_t num_attribs, |
@@ -251,7 +252,7 @@ class ProgramManagerWithShaderTest : public testing::Test { |
SetupShader(kAttribs, kNumAttribs, kUniforms, kNumUniforms, |
service_id); |
} |
- program_info->Link(); |
+ program_info->Link(NULL, NULL, NULL, NULL); |
GLint link_status; |
program_info->GetProgramiv(GL_LINK_STATUS, &link_status); |
return (static_cast<bool>(link_status) == expected_link_status); |
@@ -584,7 +585,7 @@ TEST_F(ProgramManagerWithShaderTest, GLDriverReturnsGLUnderscoreUniform) { |
ASSERT_TRUE(program_info != NULL); |
EXPECT_TRUE(program_info->AttachShader(&shader_manager_, vshader)); |
EXPECT_TRUE(program_info->AttachShader(&shader_manager_, fshader)); |
- program_info->Link(); |
+ program_info->Link(NULL, NULL, NULL, NULL); |
GLint value = 0; |
program_info->GetProgramiv(GL_ACTIVE_ATTRIBUTES, &value); |
EXPECT_EQ(3, value); |
@@ -678,7 +679,7 @@ TEST_F(ProgramManagerWithShaderTest, GLDriverReturnsWrongTypeInfo) { |
ASSERT_TRUE(program_info != NULL); |
EXPECT_TRUE(program_info->AttachShader(&shader_manager_, vshader)); |
EXPECT_TRUE(program_info->AttachShader(&shader_manager_, fshader)); |
- program_info->Link(); |
+ program_info->Link(NULL, NULL, NULL, NULL); |
// Check that we got the good type, not the bad. |
// Check Attribs |
for (unsigned index = 0; index < kNumAttribs; ++index) { |
@@ -997,7 +998,7 @@ TEST_F(ProgramManagerWithShaderTest, ClearWithSamplerTypes) { |
const size_t kNumUniforms = arraysize(kUniforms); |
SetupShader(kAttribs, kNumAttribs, kUniforms, kNumUniforms, |
kServiceProgramId); |
- program_info->Link(); |
+ program_info->Link(NULL, NULL, NULL, NULL); |
SetupExpectationsForClearingUniforms(kUniforms, kNumUniforms); |
manager_.ClearUniforms(program_info); |
} |
@@ -1069,7 +1070,7 @@ TEST_F(ProgramManagerWithShaderTest, BindUniformLocation) { |
const size_t kNumUniforms = arraysize(kUniforms); |
SetupShader(kAttribs, kNumAttribs, kUniforms, kNumUniforms, |
kServiceProgramId); |
- program_info->Link(); |
+ program_info->Link(NULL, NULL, NULL, NULL); |
EXPECT_EQ(kUniform1DesiredLocation, |
program_info->GetUniformFakeLocation(kUniform1Name)); |
@@ -1079,7 +1080,380 @@ TEST_F(ProgramManagerWithShaderTest, BindUniformLocation) { |
program_info->GetUniformFakeLocation(kUniform3GoodName)); |
} |
-} // namespace gles2 |
-} // namespace gpu |
+class ProgramManagerWithCacheTest : public testing::Test { |
+ public: |
+ static const GLuint kClientProgramId = 1; |
+ static const GLuint kServiceProgramId = 10; |
+ static const GLuint kVertexShaderClientId = 2; |
+ static const GLuint kFragmentShaderClientId = 20; |
+ static const GLuint kVertexShaderServiceId = 3; |
+ static const GLuint kFragmentShaderServiceId = 30; |
+ |
+ ProgramManagerWithCacheTest() |
+ : cache_(new MockProgramCache()), |
+ manager_(cache_.get()), |
+ vertex_shader_(NULL), |
+ fragment_shader_(NULL), |
+ program_info_(NULL) { |
+ } |
+ ~ProgramManagerWithCacheTest() { |
+ manager_.Destroy(false); |
+ shader_manager_.Destroy(false); |
+ } |
+ |
+ protected: |
+ virtual void SetUp() { |
+ gl_.reset(new StrictMock<gfx::MockGLInterface>()); |
+ ::gfx::GLInterface::SetGLInterface(gl_.get()); |
+ |
+ vertex_shader_ = shader_manager_.CreateShaderInfo( |
+ kVertexShaderClientId, kVertexShaderServiceId, GL_VERTEX_SHADER); |
+ fragment_shader_ = shader_manager_.CreateShaderInfo( |
+ kFragmentShaderClientId, kFragmentShaderServiceId, GL_FRAGMENT_SHADER); |
+ ASSERT_TRUE(vertex_shader_ != NULL); |
+ ASSERT_TRUE(fragment_shader_ != NULL); |
+ vertex_shader_->UpdateSource("lka asjf bjajsdfj"); |
+ fragment_shader_->UpdateSource("lka asjf a fasgag 3rdsf3 bjajsdfj"); |
+ |
+ program_info_ = manager_.CreateProgramInfo( |
+ kClientProgramId, kServiceProgramId); |
+ ASSERT_TRUE(program_info_ != NULL); |
+ |
+ program_info_->AttachShader(&shader_manager_, vertex_shader_); |
+ program_info_->AttachShader(&shader_manager_, fragment_shader_); |
+ } |
+ |
+ virtual void TearDown() { |
+ ::gfx::GLInterface::SetGLInterface(NULL); |
+ } |
+ |
+ void SetShadersCompiled() { |
+ cache_->ShaderCompilationSucceeded(*vertex_shader_->source()); |
+ cache_->ShaderCompilationSucceeded(*fragment_shader_->source()); |
+ vertex_shader_->SetStatus(true, NULL, NULL); |
+ fragment_shader_->SetStatus(true, NULL, NULL); |
+ vertex_shader_->FlagSourceAsCompiled(true); |
+ fragment_shader_->FlagSourceAsCompiled(true); |
+ } |
+ |
+ void SetShadersNotCompiledButCached() { |
+ SetShadersCompiled(); |
+ vertex_shader_->FlagSourceAsCompiled(false); |
+ fragment_shader_->FlagSourceAsCompiled(false); |
+ } |
+ |
+ void SetProgramCached() { |
+ cache_->LinkedProgramCacheSuccess( |
+ vertex_shader_->source()->c_str(), |
+ fragment_shader_->source()->c_str(), |
+ &program_info_->bind_attrib_location_map()); |
+ } |
+ |
+ void SetExpectationsForProgramCached() { |
+ SetExpectationsForProgramCached(program_info_, |
+ vertex_shader_, |
+ fragment_shader_); |
+ } |
+ |
+ void SetExpectationsForProgramCached( |
+ ProgramManager::ProgramInfo* program_info, |
+ ShaderManager::ShaderInfo* vertex_shader, |
+ ShaderManager::ShaderInfo* fragment_shader) { |
+ EXPECT_CALL(*cache_.get(), SaveLinkedProgram( |
+ program_info->service_id(), |
+ vertex_shader, |
+ fragment_shader, |
+ &program_info->bind_attrib_location_map())).Times(1); |
+ } |
+ |
+ void SetExpectationsForNotCachingProgram() { |
+ SetExpectationsForNotCachingProgram(program_info_, |
+ vertex_shader_, |
+ fragment_shader_); |
+ } |
+ |
+ void SetExpectationsForNotCachingProgram( |
+ ProgramManager::ProgramInfo* program_info, |
+ ShaderManager::ShaderInfo* vertex_shader, |
+ ShaderManager::ShaderInfo* fragment_shader) { |
+ EXPECT_CALL(*cache_.get(), SaveLinkedProgram( |
+ program_info->service_id(), |
+ vertex_shader, |
+ fragment_shader, |
+ &program_info->bind_attrib_location_map())).Times(0); |
+ } |
+ |
+ void SetExpectationsForProgramLoad(ProgramCache::ProgramLoadResult result) { |
+ SetExpectationsForProgramLoad(kServiceProgramId, |
+ program_info_, |
+ vertex_shader_, |
+ fragment_shader_, |
+ result); |
+ } |
+ |
+ void SetExpectationsForProgramLoad( |
+ GLuint service_program_id, |
+ ProgramManager::ProgramInfo* program_info, |
+ ShaderManager::ShaderInfo* vertex_shader, |
+ ShaderManager::ShaderInfo* fragment_shader, |
+ ProgramCache::ProgramLoadResult result) { |
+ EXPECT_CALL(*cache_.get(), |
+ LoadLinkedProgram(service_program_id, |
+ vertex_shader, |
+ fragment_shader, |
+ &program_info->bind_attrib_location_map())) |
+ .WillOnce(Return(result)); |
+ } |
+ |
+ void SetExpectationsForProgramLoadSuccess() { |
+ SetExpectationsForProgramLoadSuccess(kServiceProgramId); |
+ } |
+ |
+ void SetExpectationsForProgramLoadSuccess(GLuint service_program_id) { |
+ TestHelper::SetupProgramSuccessExpectations(gl_.get(), |
+ NULL, |
+ 0, |
+ NULL, |
+ 0, |
+ service_program_id); |
+ } |
+ |
+ void SetExpectationsForProgramLink() { |
+ SetExpectationsForProgramLink(kServiceProgramId); |
+ } |
+ |
+ void SetExpectationsForProgramLink(GLuint service_program_id) { |
+ TestHelper::SetupShader(gl_.get(), NULL, 0, NULL, 0, service_program_id); |
+ if (gfx::g_GL_ARB_get_program_binary) { |
+ EXPECT_CALL(*gl_.get(), |
+ ProgramParameteri(service_program_id, |
+ PROGRAM_BINARY_RETRIEVABLE_HINT, |
+ GL_TRUE)).Times(1); |
+ } |
+ } |
+ |
+ void SetExpectationsForSuccessCompile( |
+ const ShaderManager::ShaderInfo* shader) { |
+ const GLuint shader_id = shader->service_id(); |
+ const char* src = shader->source()->c_str(); |
+ EXPECT_CALL(*gl_.get(), |
+ ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(1); |
+ EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(1); |
+ EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _)) |
+ .WillOnce(SetArgumentPointee<2>(GL_TRUE)); |
+ } |
+ |
+ void SetExpectationsForNoCompile(const ShaderManager::ShaderInfo* shader) { |
+ const GLuint shader_id = shader->service_id(); |
+ const char* src = shader->source()->c_str(); |
+ EXPECT_CALL(*gl_.get(), |
+ ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(0); |
+ EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(0); |
+ EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _)) |
+ .Times(0); |
+ } |
+ |
+ void SetExpectationsForErrorCompile(const ShaderManager::ShaderInfo* shader) { |
+ const GLuint shader_id = shader->service_id(); |
+ const char* src = shader->source()->c_str(); |
+ EXPECT_CALL(*gl_.get(), |
+ ShaderSource(shader_id, 1, Pointee(src), NULL)).Times(1); |
+ EXPECT_CALL(*gl_.get(), CompileShader(shader_id)).Times(1); |
+ EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_COMPILE_STATUS, _)) |
+ .WillOnce(SetArgumentPointee<2>(GL_FALSE)); |
+ EXPECT_CALL(*gl_.get(), GetShaderiv(shader_id, GL_INFO_LOG_LENGTH, _)) |
+ .WillOnce(SetArgumentPointee<2>(0)); |
+ EXPECT_CALL(*gl_.get(), GetShaderInfoLog(shader_id, 0, _, _)) |
+ .Times(1); |
+ } |
+ |
+ scoped_ptr<StrictMock<gfx::MockGLInterface> > gl_; |
+ |
+ scoped_ptr<MockProgramCache> cache_; |
+ ProgramManager manager_; |
+ |
+ ShaderManager::ShaderInfo* vertex_shader_; |
+ ShaderManager::ShaderInfo* fragment_shader_; |
+ ProgramManager::ProgramInfo* program_info_; |
+ ShaderManager shader_manager_; |
+}; |
+ |
+// GCC requires these declarations, but MSVC requires they not be present |
+#ifndef COMPILER_MSVC |
+const GLuint ProgramManagerWithCacheTest::kClientProgramId; |
+const GLuint ProgramManagerWithCacheTest::kServiceProgramId; |
+const GLuint ProgramManagerWithCacheTest::kVertexShaderClientId; |
+const GLuint ProgramManagerWithCacheTest::kFragmentShaderClientId; |
+const GLuint ProgramManagerWithCacheTest::kVertexShaderServiceId; |
+const GLuint ProgramManagerWithCacheTest::kFragmentShaderServiceId; |
+#endif |
+ |
+TEST_F(ProgramManagerWithCacheTest, CacheSuccessAfterShaderCompile) { |
+ SetExpectationsForSuccessCompile(vertex_shader_); |
+ FeatureInfo::Ref info(new FeatureInfo()); |
+ manager_.DoCompileShader(vertex_shader_, NULL, info.get()); |
+ EXPECT_EQ(ProgramCache::COMPILATION_SUCCEEDED, |
+ cache_->GetShaderCompilationStatus(*vertex_shader_->source())); |
+} |
+ |
+TEST_F(ProgramManagerWithCacheTest, CacheUnknownAfterShaderError) { |
+ SetExpectationsForErrorCompile(vertex_shader_); |
+ FeatureInfo::Ref info(new FeatureInfo()); |
+ manager_.DoCompileShader(vertex_shader_, NULL, info.get()); |
+ EXPECT_EQ(ProgramCache::COMPILATION_UNKNOWN, |
+ cache_->GetShaderCompilationStatus(*vertex_shader_->source())); |
+} |
+ |
+TEST_F(ProgramManagerWithCacheTest, NoCompileWhenShaderCached) { |
+ cache_->ShaderCompilationSucceeded(vertex_shader_->source()->c_str()); |
+ SetExpectationsForNoCompile(vertex_shader_); |
+ FeatureInfo::Ref info(new FeatureInfo()); |
+ manager_.DoCompileShader(vertex_shader_, NULL, info.get()); |
+} |
+ |
+TEST_F(ProgramManagerWithCacheTest, CacheProgramOnSuccessfulLink) { |
+ SetShadersCompiled(); |
+ SetExpectationsForProgramLink(); |
+ SetExpectationsForProgramCached(); |
+ EXPECT_TRUE(program_info_->Link(NULL, NULL, NULL, NULL)); |
+} |
+ |
+TEST_F(ProgramManagerWithCacheTest, CompileShaderOnLinkCacheMiss) { |
+ SetShadersCompiled(); |
+ vertex_shader_->FlagSourceAsCompiled(false); |
+ |
+ FeatureInfo::Ref info(new FeatureInfo()); |
+ |
+ SetExpectationsForSuccessCompile(vertex_shader_); |
+ SetExpectationsForProgramLink(); |
+ SetExpectationsForProgramCached(); |
+ EXPECT_TRUE(program_info_->Link(&shader_manager_, NULL, NULL, info.get())); |
+} |
+ |
+TEST_F(ProgramManagerWithCacheTest, LoadProgramOnProgramCacheHit) { |
+ SetShadersNotCompiledButCached(); |
+ SetProgramCached(); |
+ |
+ SetExpectationsForNoCompile(vertex_shader_); |
+ SetExpectationsForNoCompile(fragment_shader_); |
+ SetExpectationsForProgramLoad(ProgramCache::PROGRAM_LOAD_SUCCESS); |
+ SetExpectationsForNotCachingProgram(); |
+ SetExpectationsForProgramLoadSuccess(); |
+ |
+ EXPECT_TRUE(program_info_->Link(NULL, NULL, NULL, NULL)); |
+} |
+ |
+TEST_F(ProgramManagerWithCacheTest, CompileAndLinkOnProgramCacheError) { |
+ SetShadersNotCompiledButCached(); |
+ SetProgramCached(); |
+ |
+ SetExpectationsForSuccessCompile(vertex_shader_); |
+ SetExpectationsForSuccessCompile(fragment_shader_); |
+ SetExpectationsForProgramLoad(ProgramCache::PROGRAM_LOAD_FAILURE); |
+ SetExpectationsForProgramLink(); |
+ SetExpectationsForProgramCached(); |
+ |
+ FeatureInfo::Ref info(new FeatureInfo()); |
+ EXPECT_TRUE(program_info_->Link(&shader_manager_, NULL, NULL, info.get())); |
+} |
+ |
+TEST_F(ProgramManagerWithCacheTest, CorrectCompileOnSourceChangeNoCompile) { |
+ SetShadersNotCompiledButCached(); |
+ SetProgramCached(); |
+ const GLuint kNewShaderClientId = 4; |
+ const GLuint kNewShaderServiceId = 40; |
+ const GLuint kNewProgramClientId = 5; |
+ const GLuint kNewProgramServiceId = 50; |
+ ShaderManager::ShaderInfo* new_vertex_shader = |
+ shader_manager_.CreateShaderInfo(kNewShaderClientId, |
+ kNewShaderServiceId, |
+ GL_VERTEX_SHADER); |
+ |
+ const std::string original_source = *vertex_shader_->source(); |
+ new_vertex_shader->UpdateSource(original_source.c_str()); |
+ |
+ ProgramManager::ProgramInfo* program_info = manager_.CreateProgramInfo( |
+ kNewProgramClientId, kNewProgramServiceId); |
+ ASSERT_TRUE(program_info != NULL); |
+ program_info->AttachShader(&shader_manager_, new_vertex_shader); |
+ program_info->AttachShader(&shader_manager_, fragment_shader_); |
+ |
+ SetExpectationsForNoCompile(new_vertex_shader); |
+ |
+ manager_.DoCompileShader(new_vertex_shader, NULL, NULL); |
+ |
+ new_vertex_shader->UpdateSource("different!"); |
+ EXPECT_EQ(original_source, |
+ *new_vertex_shader->deferred_compilation_source()); |
+ |
+ EXPECT_FALSE(new_vertex_shader->source_compiled()); |
+ EXPECT_FALSE(fragment_shader_->source_compiled()); |
+ |
+ SetExpectationsForNoCompile(fragment_shader_); |
+ SetExpectationsForNotCachingProgram(program_info, |
+ new_vertex_shader, |
+ fragment_shader_); |
+ SetExpectationsForProgramLoad(kNewProgramServiceId, |
+ program_info, |
+ new_vertex_shader, |
+ fragment_shader_, |
+ ProgramCache::PROGRAM_LOAD_SUCCESS); |
+ SetExpectationsForProgramLoadSuccess(kNewProgramServiceId); |
+ |
+ FeatureInfo::Ref info(new FeatureInfo()); |
+ EXPECT_TRUE(program_info->Link(&shader_manager_, NULL, NULL, info.get())); |
+} |
+ |
+TEST_F(ProgramManagerWithCacheTest, CorrectCompileOnSourceChangeWithCompile) { |
+ SetShadersNotCompiledButCached(); |
+ SetProgramCached(); |
+ |
+ const GLuint kNewShaderClientId = 4; |
+ const GLuint kNewShaderServiceId = 40; |
+ const GLuint kNewProgramClientId = 5; |
+ const GLuint kNewProgramServiceId = 50; |
+ |
+ ShaderManager::ShaderInfo* new_vertex_shader = |
+ shader_manager_.CreateShaderInfo(kNewShaderClientId, |
+ kNewShaderServiceId, |
+ GL_VERTEX_SHADER); |
+ |
+ new_vertex_shader->UpdateSource(vertex_shader_->source()->c_str()); |
+ |
+ ProgramManager::ProgramInfo* program_info = manager_.CreateProgramInfo( |
+ kNewProgramClientId, kNewProgramServiceId); |
+ ASSERT_TRUE(program_info != NULL); |
+ program_info->AttachShader(&shader_manager_, new_vertex_shader); |
+ program_info->AttachShader(&shader_manager_, fragment_shader_); |
+ |
+ SetExpectationsForNoCompile(new_vertex_shader); |
+ |
+ manager_.DoCompileShader(new_vertex_shader, NULL, NULL); |
+ |
+ const std::string differentSource = "different!"; |
+ new_vertex_shader->UpdateSource(differentSource.c_str()); |
+ SetExpectationsForSuccessCompile(new_vertex_shader); |
+ |
+ FeatureInfo::Ref info(new FeatureInfo()); |
+ manager_.DoCompileShader(new_vertex_shader, NULL, info.get()); |
+ EXPECT_EQ(differentSource, |
+ *new_vertex_shader->deferred_compilation_source()); |
+ |
+ EXPECT_TRUE(new_vertex_shader->source_compiled()); |
+ EXPECT_FALSE(fragment_shader_->source_compiled()); |
+ |
+ // so we don't recompile because we were pending originally |
+ SetExpectationsForNoCompile(new_vertex_shader); |
+ SetExpectationsForSuccessCompile(fragment_shader_); |
+ SetExpectationsForProgramCached(program_info, |
+ new_vertex_shader, |
+ fragment_shader_); |
+ SetExpectationsForProgramLink(kNewProgramServiceId); |
+ |
+ EXPECT_TRUE(program_info->Link(&shader_manager_, NULL, NULL, info.get())); |
+} |
+ |
+} // namespace gles2 |
+} // namespace gpu |