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

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

Issue 10534173: GPU Program Caching (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Style fixes, thorough tests 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
Index: gpu/command_buffer/service/memory_program_cache_unittest.cc
diff --git a/gpu/command_buffer/service/memory_program_cache_unittest.cc b/gpu/command_buffer/service/memory_program_cache_unittest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..4ded9712f598c5f936c94b7cc57ab8fccaa0f7e6
--- /dev/null
+++ b/gpu/command_buffer/service/memory_program_cache_unittest.cc
@@ -0,0 +1,267 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "gpu/command_buffer/service/memory_program_cache.h"
+
+#include "gpu/command_buffer/common/gl_mock.h"
+#include "gpu/command_buffer/common/gles2_cmd_format.h"
+#include "gpu/command_buffer/service/gl_utils.h"
+#include "gpu/command_buffer/service/shader_translator.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gl/gl_bindings.h"
+
+using ::testing::_;
+using ::testing::SetArgPointee;
+using ::testing::SetArrayArgument;
+using ::testing::ElementsAreArray;
+
+namespace gpu {
+namespace gles2 {
+
+// custom mock interface due to limitations of gmock with void*
greggman 2012/07/10 21:43:30 What is the limitation of gmock with void*? You c
dmurph 2012/07/11 23:32:52 Awesome, I was digging around forever to figure ou
+class GLMockWithProgramBinary : public ::gfx::MockGLInterface {
+ public:
+ virtual void GetProgramBinary(GLuint program,
+ GLsizei bufSize,
greggman 2012/07/10 21:43:30 style: arguments are under_score
dmurph 2012/07/11 23:32:52 Done.
+ GLsizei* length,
+ GLenum* binaryFormat,
greggman 2012/07/10 21:43:30 style: arguments are under_score
dmurph 2012/07/11 23:32:52 Done.
+ GLvoid* binary) OVERRIDE {
+ EXPECT_EQ(program_, program);
+ EXPECT_EQ(length_, bufSize);
+ *length = length_;
+ *binaryFormat = format_;
+ memcpy(binary, binary_, length_);
+ get_called_ = true;
+ }
+
+ virtual void ProgramBinary(GLuint program,
+ GLenum format,
+ const GLvoid* binary,
+ GLsizei length) OVERRIDE {
+ const char* charBinary = static_cast<const char*>(binary);
+ EXPECT_EQ(program_, program);
+ EXPECT_EQ(format_, format);
+ EXPECT_EQ(length_, length);
+ for (int i = 0; i < length; i++) {
+ char expected = binary_[i];
+ EXPECT_EQ(expected, charBinary[i]);
+ }
+ binary_called_ = true;
+ }
+
+ void ExpectAndPopulateProgramBinaryCalls(GLuint program,
+ GLsizei length,
+ GLenum format,
+ char* binary) {
+ program_ = program;
+ length_ = length;
+ format_ = format;
+ binary_ = binary;
+ get_called_ = binary_called_ = false;
+ }
+
+ bool get_called() const {
+ return get_called_;
+ }
+
+ bool binary_called() const {
+ return binary_called_;
+ }
+
+ private:
+ bool get_called_;
+ bool binary_called_;
+ GLuint program_;
+ GLsizei length_;
+ GLenum format_;
+ char* binary_;
+};
+
+class MemoryProgramCacheTest : public testing::Test {
+ public:
+ static const size_t kCacheSizeBytes = 1024;
+ static const GLuint kVertexShaderClientId = 90;
+ static const GLuint kVertexShaderServiceId = 100;
+ static const GLuint kFragmentShaderClientId = 91;
+ static const GLuint kFragmentShaderServiceId = 100;
+
+ MemoryProgramCacheTest()
+ : cache_(new MemoryProgramCache(kCacheSizeBytes)),
+ vertex_shader_(NULL),
+ fragment_shader_(NULL) { }
+ ~MemoryProgramCacheTest() {
+ shader_manager_.Destroy(false);
+ }
+
+ protected:
+ virtual void SetUp() {
+ gl_.reset(new ::testing::StrictMock<GLMockWithProgramBinary>());
+ ::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);
+ typedef ShaderTranslatorInterface::VariableInfo VariableInfo;
+ typedef ShaderTranslator::VariableMap VariableMap;
+ VariableMap vertex_attrib_map;
+ VariableMap vertex_uniform_map;
+ VariableMap fragment_attrib_map;
+ VariableMap fragment_uniform_map;
+
+ vertex_attrib_map["a"] = VariableInfo(1, 34, "a");
+ vertex_uniform_map["a"] = VariableInfo(0, 10, "a");
+ vertex_uniform_map["b"] = VariableInfo(2, 3114, "b");
+ fragment_attrib_map["jjjbb"] = VariableInfo(463, 1114, "jjjbb");
+ fragment_uniform_map["k"] = VariableInfo(10, 34413, "k");
+
+ vertex_shader_->SetAttribMap(vertex_attrib_map);
+ vertex_shader_->SetUniformMap(vertex_uniform_map);
+ fragment_shader_->SetAttribMap(vertex_attrib_map);
+ fragment_shader_->SetUniformMap(vertex_uniform_map);
+
+ vertex_shader_->UpdateSource("bbbalsldkdkdkd");
+ fragment_shader_->UpdateSource("bbbal sldkdkdkas 134 ad");
+
+ vertex_shader_->SetStatus(true, NULL, NULL);
+ fragment_shader_->SetStatus(true, NULL, NULL);
+ }
+
+ virtual void TearDown() {
+ ::gfx::GLInterface::SetGLInterface(NULL);
+ gl_.reset();
+ }
+ // Use StrictMock to make 100% sure we know how GL will be called.
+ scoped_ptr< ::testing::StrictMock<GLMockWithProgramBinary> > gl_;
+ scoped_ptr<MemoryProgramCache> cache_;
+ ShaderManager shader_manager_;
+ ShaderManager::ShaderInfo* vertex_shader_;
+ ShaderManager::ShaderInfo* fragment_shader_;
+};
+
+TEST_F(MemoryProgramCacheTest, MemoryProgramCacheSave) {
+ const GLenum kFormat = 1;
+ const int kProgramId = 10;
+ const int kBinaryLength = 20;
+ char testBinary[kBinaryLength];
+ for (int i = 0; i < kBinaryLength; ++i) {
+ testBinary[i] = i;
+ }
+ EXPECT_CALL(*gl_.get(),
+ GetProgramiv(kProgramId, GL_PROGRAM_BINARY_LENGTH_OES, _))
+ .WillOnce(SetArgPointee<2>(kBinaryLength));
+ gl_->ExpectAndPopulateProgramBinaryCalls(kProgramId,
greggman 2012/07/10 21:43:30 Is seems better to use gmock for all this?
dmurph 2012/07/11 23:32:52 Definitely. Thanks for the tip above.
+ kBinaryLength,
+ kFormat,
+ testBinary);
+
+ cache_->SaveLinkedProgram(kProgramId, vertex_shader_, fragment_shader_, NULL);
+ EXPECT_TRUE(gl_->get_called());
+
+ EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
+ *vertex_shader_->source(),
+ *fragment_shader_->source(),
+ NULL));
+}
+
+TEST_F(MemoryProgramCacheTest, MemoryProgramCacheLoad) {
+ typedef ShaderTranslator::VariableMap VariableMap;
+ const GLenum kFormat = 1;
+ const int kProgramId = 10;
+ const int kBinaryLength = 20;
+ char testBinary[kBinaryLength];
+ for (int i = 0; i < kBinaryLength; ++i) {
+ testBinary[i] = i;
+ }
+ EXPECT_CALL(*gl_.get(),
+ GetProgramiv(kProgramId, GL_PROGRAM_BINARY_LENGTH_OES, _))
+ .WillOnce(SetArgPointee<2>(kBinaryLength));
+ gl_->ExpectAndPopulateProgramBinaryCalls(kProgramId,
+ kBinaryLength,
+ kFormat,
+ testBinary);
+
+ cache_->SaveLinkedProgram(kProgramId, vertex_shader_, fragment_shader_, NULL);
+
+ VariableMap vertex_attrib_map = vertex_shader_->attrib_map();
+ VariableMap vertex_uniform_map = vertex_shader_->uniform_map();
+ VariableMap fragment_attrib_map = fragment_shader_->attrib_map();
+ VariableMap fragment_uniform_map = fragment_shader_->uniform_map();
+
+ vertex_shader_->SetAttribMap(VariableMap());
+ vertex_shader_->SetUniformMap(VariableMap());
+ fragment_shader_->SetAttribMap(VariableMap());
+ fragment_shader_->SetUniformMap(VariableMap());
+
+ ProgramCache::ProgramLoadResult result = cache_->LoadLinkedProgram(
+ kProgramId,
+ vertex_shader_,
+ fragment_shader_,
+ NULL);
+
+ EXPECT_EQ(ProgramCache::PROGRAM_LOAD_SUCCESS, result);
+ EXPECT_EQ(vertex_attrib_map, vertex_shader_->attrib_map());
+
+ EXPECT_TRUE(gl_->binary_called());
+}
greggman 2012/07/10 21:43:30 Should there be a checks that *) The binary saved
dmurph 2012/07/11 23:32:52 Implemented. Also, I list all of my tests in the
+
+TEST_F(MemoryProgramCacheTest, MemoryProgramCacheEviction) {
+ typedef ShaderTranslator::VariableMap VariableMap;
+ const GLenum kFormat = 1;
+ const int kProgramId = 10;
+ const int kBinaryLength = 20;
+ char testBinary[kBinaryLength];
+ for (int i = 0; i < kBinaryLength; ++i) {
+ testBinary[i] = i;
+ }
+ EXPECT_CALL(*gl_.get(),
+ GetProgramiv(kProgramId, GL_PROGRAM_BINARY_LENGTH_OES, _))
+ .WillOnce(SetArgPointee<2>(kBinaryLength));
+ gl_->ExpectAndPopulateProgramBinaryCalls(kProgramId,
+ kBinaryLength,
+ kFormat,
+ testBinary);
+
+ cache_->SaveLinkedProgram(kProgramId, vertex_shader_, fragment_shader_, NULL);
+
+ const int kEvictingProgramId = 11;
+ const size_t kEvictingBinaryLength = kCacheSizeBytes - kBinaryLength + 1;
+
+ // save old source and modify for new program
+ std::string old_source(*vertex_shader_->source());
+ vertex_shader_->UpdateSource("alkjdk");
+
+ scoped_array<char> bigTestBinary =
+ scoped_array<char>(new char[kEvictingBinaryLength]);
+ for (size_t i = 0; i < kEvictingBinaryLength; ++i) {
+ bigTestBinary[i] = i % 250;
+ }
+ EXPECT_CALL(*gl_.get(),
+ GetProgramiv(kEvictingProgramId, GL_PROGRAM_BINARY_LENGTH_OES, _))
+ .WillOnce(SetArgPointee<2>(kEvictingBinaryLength));
+ gl_->ExpectAndPopulateProgramBinaryCalls(kEvictingProgramId,
+ kEvictingBinaryLength,
+ kFormat,
+ bigTestBinary.get());
+ cache_->SaveLinkedProgram(kEvictingProgramId,
+ vertex_shader_,
+ fragment_shader_,
+ NULL);
+ EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, cache_->GetLinkedProgramStatus(
+ *vertex_shader_->source(),
+ *fragment_shader_->source(),
+ NULL));
+ EXPECT_EQ(ProgramCache::LINK_UNKNOWN, cache_->GetLinkedProgramStatus(
+ old_source,
+ *fragment_shader_->source(),
+ NULL));
+}
+
+} // namespace gles2
+} // namespace gpu

Powered by Google App Engine
This is Rietveld 408576698