Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(230)

Unified Diff: gpu/command_buffer/service/program_manager_unittest.cc

Issue 10797055: gpu in-memory program cache implementation with a memory limit + lru eviction. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: nit fixes Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « gpu/command_buffer/service/program_manager.cc ('k') | gpu/command_buffer/service/shader_manager.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
« no previous file with comments | « gpu/command_buffer/service/program_manager.cc ('k') | gpu/command_buffer/service/shader_manager.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698