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:
LoadLinkedProgram(GLuint,Shader *,const ShaderTranslatorInterface *,Shader *,const ShaderTranslatorInterface *,const LocationMap *,const ShaderCacheCallback &)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 }
SaveLinkedProgram(GLuint,const Shader *,const ShaderTranslatorInterface *,const Shader *,const ShaderTranslatorInterface *,const LocationMap *,const ShaderCacheCallback &)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
LoadProgram(const std::string &)37 virtual void LoadProgram(const std::string& /* program */) OVERRIDE {}
38
ClearBackend()39 virtual void ClearBackend() OVERRIDE {}
40
SaySuccessfullyCached(const std::string & shader1,const ShaderTranslatorInterface * translator_1,const std::string & shader2,const ShaderTranslatorInterface * translator_2,std::map<std::string,GLint> * attrib_map)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
ComputeShaderHash(const std::string & shader,const ShaderTranslatorInterface * translator,char * result) const61 void ComputeShaderHash(const std::string& shader,
62 const ShaderTranslatorInterface* translator,
63 char* result) const {
64 ProgramCache::ComputeShaderHash(shader, translator, result);
65 }
66
ComputeProgramHash(const char * hashed_shader_0,const char * hashed_shader_1,const LocationMap * bind_attrib_location_map,char * result) const67 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
Evict(const std::string & program_hash)77 void Evict(const std::string& program_hash) {
78 ProgramCache::Evict(program_hash);
79 }
80 };
81
82 class ProgramCacheTest : public testing::Test {
83 public:
ProgramCacheTest()84 ProgramCacheTest() :
85 cache_(new NoBackendProgramCache()) { }
86
87 protected:
88 scoped_ptr<NoBackendProgramCache> cache_;
89 };
90
TEST_F(ProgramCacheTest,LinkStatusSave)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
TEST_F(ProgramCacheTest,LinkUnknownOnFragmentSourceChange)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
TEST_F(ProgramCacheTest,LinkUnknownOnVertexSourceChange)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
TEST_F(ProgramCacheTest,StatusEviction)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
TEST_F(ProgramCacheTest,EvictionWithReusedShader)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
TEST_F(ProgramCacheTest,StatusClear)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