1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #include "gpu/command_buffer/service/program_cache.h" 6 7 #include "base/memory/scoped_ptr.h" 8 #include "gpu/command_buffer/service/mocks.h" 9 #include "testing/gtest/include/gtest/gtest.h" 10 11 using ::testing::Return; 12 13 namespace gpu { 14 namespace gles2 { 15 16 class NoBackendProgramCache : public ProgramCache { 17 public: 18 virtual ProgramLoadResult LoadLinkedProgram( 19 GLuint /* program */, 20 Shader* /* shader_a */, 21 const ShaderTranslatorInterface* /* translator_a */, 22 Shader* /* shader_b */, 23 const ShaderTranslatorInterface* /* translator_b */, 24 const LocationMap* /* bind_attrib_location_map */, 25 const ShaderCacheCallback& /* callback */) OVERRIDE { 26 return PROGRAM_LOAD_SUCCESS; 27 } 28 virtual void SaveLinkedProgram( 29 GLuint /* program */, 30 const Shader* /* shader_a */, 31 const ShaderTranslatorInterface* /* translator_b */, 32 const Shader* /* shader_b */, 33 const ShaderTranslatorInterface* /* translator_b */, 34 const LocationMap* /* bind_attrib_location_map */, 35 const ShaderCacheCallback& /* callback */) OVERRIDE { } 36 37 virtual void LoadProgram(const std::string& /* program */) OVERRIDE {} 38 39 virtual void ClearBackend() OVERRIDE {} 40 41 void SaySuccessfullyCached(const std::string& shader1, 42 const ShaderTranslatorInterface* translator_1, 43 const std::string& shader2, 44 const ShaderTranslatorInterface* translator_2, 45 std::map<std::string, GLint>* attrib_map) { 46 char a_sha[kHashLength]; 47 char b_sha[kHashLength]; 48 ComputeShaderHash(shader1, translator_1, a_sha); 49 ComputeShaderHash(shader2, translator_2, b_sha); 50 51 char sha[kHashLength]; 52 ComputeProgramHash(a_sha, 53 b_sha, 54 attrib_map, 55 sha); 56 const std::string shaString(sha, kHashLength); 57 58 LinkedProgramCacheSuccess(shaString); 59 } 60 61 void ComputeShaderHash(const std::string& shader, 62 const ShaderTranslatorInterface* translator, 63 char* result) const { 64 ProgramCache::ComputeShaderHash(shader, translator, result); 65 } 66 67 void ComputeProgramHash(const char* hashed_shader_0, 68 const char* hashed_shader_1, 69 const LocationMap* bind_attrib_location_map, 70 char* result) const { 71 ProgramCache::ComputeProgramHash(hashed_shader_0, 72 hashed_shader_1, 73 bind_attrib_location_map, 74 result); 75 } 76 77 void Evict(const std::string& program_hash) { 78 ProgramCache::Evict(program_hash); 79 } 80 }; 81 82 class ProgramCacheTest : public testing::Test { 83 public: 84 ProgramCacheTest() : 85 cache_(new NoBackendProgramCache()) { } 86 87 protected: 88 scoped_ptr<NoBackendProgramCache> cache_; 89 }; 90 91 TEST_F(ProgramCacheTest, LinkStatusSave) { 92 const std::string shader1 = "abcd1234"; 93 const std::string shader2 = "abcda sda b1~#4 bbbbb1234"; 94 { 95 std::string shader_a = shader1; 96 std::string shader_b = shader2; 97 EXPECT_EQ(ProgramCache::LINK_UNKNOWN, 98 cache_->GetLinkedProgramStatus( 99 shader_a, NULL, shader_b, NULL, NULL)); 100 cache_->SaySuccessfullyCached(shader_a, NULL, shader_b, NULL, NULL); 101 102 shader_a.clear(); 103 shader_b.clear(); 104 } 105 // make sure it was copied 106 EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, 107 cache_->GetLinkedProgramStatus( 108 shader1, NULL, shader2, NULL, NULL)); 109 } 110 111 TEST_F(ProgramCacheTest, LinkUnknownOnFragmentSourceChange) { 112 const std::string shader1 = "abcd1234"; 113 std::string shader2 = "abcda sda b1~#4 bbbbb1234"; 114 cache_->SaySuccessfullyCached(shader1, NULL, shader2, NULL, NULL); 115 116 shader2 = "different!"; 117 EXPECT_EQ(ProgramCache::LINK_UNKNOWN, 118 cache_->GetLinkedProgramStatus(shader1, NULL, shader2, NULL, NULL)); 119 } 120 121 TEST_F(ProgramCacheTest, LinkUnknownOnVertexSourceChange) { 122 std::string shader1 = "abcd1234"; 123 const std::string shader2 = "abcda sda b1~#4 bbbbb1234"; 124 cache_->SaySuccessfullyCached(shader1, NULL, shader2, NULL, NULL); 125 126 shader1 = "different!"; 127 EXPECT_EQ(ProgramCache::LINK_UNKNOWN, 128 cache_->GetLinkedProgramStatus(shader1, NULL, shader2, NULL, NULL)); 129 } 130 131 TEST_F(ProgramCacheTest, StatusEviction) { 132 const std::string shader1 = "abcd1234"; 133 const std::string shader2 = "abcda sda b1~#4 bbbbb1234"; 134 cache_->SaySuccessfullyCached(shader1, NULL, shader2, NULL, NULL); 135 char a_sha[ProgramCache::kHashLength]; 136 char b_sha[ProgramCache::kHashLength]; 137 cache_->ComputeShaderHash(shader1, NULL, a_sha); 138 cache_->ComputeShaderHash(shader2, NULL, b_sha); 139 140 char sha[ProgramCache::kHashLength]; 141 cache_->ComputeProgramHash(a_sha, 142 b_sha, 143 NULL, 144 sha); 145 cache_->Evict(std::string(sha, ProgramCache::kHashLength)); 146 EXPECT_EQ(ProgramCache::LINK_UNKNOWN, 147 cache_->GetLinkedProgramStatus(shader1, NULL, shader2, NULL, NULL)); 148 } 149 150 TEST_F(ProgramCacheTest, EvictionWithReusedShader) { 151 const std::string shader1 = "abcd1234"; 152 const std::string shader2 = "abcda sda b1~#4 bbbbb1234"; 153 const std::string shader3 = "asbjbbjj239a"; 154 cache_->SaySuccessfullyCached(shader1, NULL, shader2, NULL, NULL); 155 cache_->SaySuccessfullyCached(shader1, NULL, shader3, NULL, NULL); 156 157 char a_sha[ProgramCache::kHashLength]; 158 char b_sha[ProgramCache::kHashLength]; 159 char c_sha[ProgramCache::kHashLength]; 160 cache_->ComputeShaderHash(shader1, NULL, a_sha); 161 cache_->ComputeShaderHash(shader2, NULL, b_sha); 162 cache_->ComputeShaderHash(shader3, NULL, c_sha); 163 164 char sha[ProgramCache::kHashLength]; 165 cache_->ComputeProgramHash(a_sha, 166 b_sha, 167 NULL, 168 sha); 169 cache_->Evict(std::string(sha, ProgramCache::kHashLength)); 170 EXPECT_EQ(ProgramCache::LINK_UNKNOWN, 171 cache_->GetLinkedProgramStatus(shader1, NULL, shader2, NULL, NULL)); 172 EXPECT_EQ(ProgramCache::LINK_SUCCEEDED, 173 cache_->GetLinkedProgramStatus(shader1, NULL, shader3, NULL, NULL)); 174 175 176 cache_->ComputeProgramHash(a_sha, 177 c_sha, 178 NULL, 179 sha); 180 cache_->Evict(std::string(sha, ProgramCache::kHashLength)); 181 EXPECT_EQ(ProgramCache::LINK_UNKNOWN, 182 cache_->GetLinkedProgramStatus(shader1, NULL, shader2, NULL, NULL)); 183 EXPECT_EQ(ProgramCache::LINK_UNKNOWN, 184 cache_->GetLinkedProgramStatus(shader1, NULL, shader3, NULL, NULL)); 185 } 186 187 TEST_F(ProgramCacheTest, StatusClear) { 188 const std::string shader1 = "abcd1234"; 189 const std::string shader2 = "abcda sda b1~#4 bbbbb1234"; 190 const std::string shader3 = "asbjbbjj239a"; 191 cache_->SaySuccessfullyCached(shader1, NULL, shader2, NULL, NULL); 192 cache_->SaySuccessfullyCached(shader1, NULL, shader3, NULL, NULL); 193 cache_->Clear(); 194 EXPECT_EQ(ProgramCache::LINK_UNKNOWN, 195 cache_->GetLinkedProgramStatus(shader1, NULL, shader2, NULL, NULL)); 196 EXPECT_EQ(ProgramCache::LINK_UNKNOWN, 197 cache_->GetLinkedProgramStatus(shader1, NULL, shader3, NULL, NULL)); 198 } 199 200 } // namespace gles2 201 } // namespace gpu 202