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.
5 #include "gpu/command_buffer/service/shader_manager.h"
7 #include "base/memory/scoped_ptr.h"
8 #include "gpu/command_buffer/service/gpu_service_test.h"
9 #include "gpu/command_buffer/service/mocks.h"
10 #include "gpu/command_buffer/service/test_helper.h"
11 #include "testing/gtest/include/gtest/gtest.h"
12 #include "ui/gl/gl_mock.h"
14 using ::testing::Return
;
15 using ::testing::ReturnRef
;
20 class ShaderManagerTest
: public GpuServiceTest
{
25 ~ShaderManagerTest() override
{ manager_
.Destroy(false); }
28 ShaderManager manager_
;
31 TEST_F(ShaderManagerTest
, Basic
) {
32 const GLuint kClient1Id
= 1;
33 const GLuint kService1Id
= 11;
34 const GLenum kShader1Type
= GL_VERTEX_SHADER
;
35 const GLuint kClient2Id
= 2;
36 // Check we can create shader.
37 Shader
* info0
= manager_
.CreateShader(
38 kClient1Id
, kService1Id
, kShader1Type
);
39 // Check shader got created.
40 ASSERT_TRUE(info0
!= NULL
);
41 Shader
* shader1
= manager_
.GetShader(kClient1Id
);
42 ASSERT_EQ(info0
, shader1
);
43 // Check we get nothing for a non-existent shader.
44 EXPECT_TRUE(manager_
.GetShader(kClient2Id
) == NULL
);
45 // Check we can't get the shader after we remove it.
46 EXPECT_CALL(*gl_
, DeleteShader(kService1Id
))
48 .RetiresOnSaturation();
49 manager_
.Delete(shader1
);
50 EXPECT_TRUE(manager_
.GetShader(kClient1Id
) == NULL
);
53 TEST_F(ShaderManagerTest
, Destroy
) {
54 const GLuint kClient1Id
= 1;
55 const GLuint kService1Id
= 11;
56 const GLenum kShader1Type
= GL_VERTEX_SHADER
;
57 // Check we can create shader.
58 Shader
* shader1
= manager_
.CreateShader(
59 kClient1Id
, kService1Id
, kShader1Type
);
60 // Check shader got created.
61 ASSERT_TRUE(shader1
!= NULL
);
62 EXPECT_CALL(*gl_
, DeleteShader(kService1Id
))
64 .RetiresOnSaturation();
65 manager_
.Destroy(true);
66 // Check that resources got freed.
67 shader1
= manager_
.GetShader(kClient1Id
);
68 ASSERT_TRUE(shader1
== NULL
);
71 TEST_F(ShaderManagerTest
, DeleteBug
) {
72 const GLuint kClient1Id
= 1;
73 const GLuint kClient2Id
= 2;
74 const GLuint kService1Id
= 11;
75 const GLuint kService2Id
= 12;
76 const GLenum kShaderType
= GL_VERTEX_SHADER
;
77 // Check we can create shader.
78 scoped_refptr
<Shader
> shader1(
79 manager_
.CreateShader(kClient1Id
, kService1Id
, kShaderType
));
80 scoped_refptr
<Shader
> shader2(
81 manager_
.CreateShader(kClient2Id
, kService2Id
, kShaderType
));
82 ASSERT_TRUE(shader1
.get());
83 ASSERT_TRUE(shader2
.get());
84 manager_
.UseShader(shader1
.get());
85 manager_
.Delete(shader1
.get());
87 EXPECT_CALL(*gl_
, DeleteShader(kService2Id
))
89 .RetiresOnSaturation();
90 manager_
.Delete(shader2
.get());
91 EXPECT_TRUE(manager_
.IsOwned(shader1
.get()));
92 EXPECT_FALSE(manager_
.IsOwned(shader2
.get()));
94 EXPECT_CALL(*gl_
, DeleteShader(kService1Id
))
96 .RetiresOnSaturation();
97 manager_
.UnuseShader(shader1
.get());
100 TEST_F(ShaderManagerTest
, DoCompile
) {
101 const GLuint kClient1Id
= 1;
102 const GLuint kService1Id
= 11;
103 const GLenum kShader1Type
= GL_VERTEX_SHADER
;
104 const char* kClient1Source
= "hello world";
105 const GLenum kAttrib1Type
= GL_FLOAT_VEC2
;
106 const GLint kAttrib1Size
= 2;
107 const GLenum kAttrib1Precision
= GL_MEDIUM_FLOAT
;
108 const char* kAttrib1Name
= "attr1";
109 const GLenum kAttrib2Type
= GL_FLOAT_VEC3
;
110 const GLint kAttrib2Size
= 4;
111 const GLenum kAttrib2Precision
= GL_HIGH_FLOAT
;
112 const char* kAttrib2Name
= "attr2";
113 const bool kAttribStaticUse
= false;
114 const GLenum kUniform1Type
= GL_FLOAT_MAT2
;
115 const GLint kUniform1Size
= 3;
116 const GLenum kUniform1Precision
= GL_LOW_FLOAT
;
117 const bool kUniform1StaticUse
= true;
118 const char* kUniform1Name
= "uni1";
119 const GLenum kUniform2Type
= GL_FLOAT_MAT3
;
120 const GLint kUniform2Size
= 5;
121 const GLenum kUniform2Precision
= GL_MEDIUM_FLOAT
;
122 const bool kUniform2StaticUse
= false;
123 const char* kUniform2Name
= "uni2";
124 const GLenum kVarying1Type
= GL_FLOAT_VEC4
;
125 const GLint kVarying1Size
= 1;
126 const GLenum kVarying1Precision
= GL_HIGH_FLOAT
;
127 const bool kVarying1StaticUse
= false;
128 const char* kVarying1Name
= "varying1";
130 // Check we can create shader.
131 Shader
* shader1
= manager_
.CreateShader(
132 kClient1Id
, kService1Id
, kShader1Type
);
133 // Check shader got created.
134 ASSERT_TRUE(shader1
!= NULL
);
135 EXPECT_EQ(kService1Id
, shader1
->service_id());
136 // Check if the shader has correct type.
137 EXPECT_EQ(kShader1Type
, shader1
->shader_type());
138 EXPECT_FALSE(shader1
->valid());
139 EXPECT_FALSE(shader1
->InUse());
140 EXPECT_TRUE(shader1
->source().empty());
141 EXPECT_TRUE(shader1
->log_info().empty());
142 EXPECT_TRUE(shader1
->last_compiled_source().empty());
143 EXPECT_TRUE(shader1
->translated_source().empty());
144 EXPECT_EQ(0u, shader1
->attrib_map().size());
145 EXPECT_EQ(0u, shader1
->uniform_map().size());
146 EXPECT_EQ(0u, shader1
->varying_map().size());
147 EXPECT_EQ(Shader::kShaderStateWaiting
, shader1
->shader_state());
149 // Check we can set its source.
150 shader1
->set_source(kClient1Source
);
151 EXPECT_STREQ(kClient1Source
, shader1
->source().c_str());
152 EXPECT_TRUE(shader1
->last_compiled_source().empty());
154 // Check that DoCompile() will not work if RequestCompile() was not called.
155 shader1
->DoCompile();
156 EXPECT_EQ(Shader::kShaderStateWaiting
, shader1
->shader_state());
157 EXPECT_FALSE(shader1
->valid());
159 // Check RequestCompile() will update the state and last compiled source, but
160 // still keep the actual compile state invalid.
161 scoped_refptr
<ShaderTranslatorInterface
> translator(new MockShaderTranslator
);
162 shader1
->RequestCompile(translator
, Shader::kANGLE
);
163 EXPECT_EQ(Shader::kShaderStateCompileRequested
, shader1
->shader_state());
164 EXPECT_STREQ(kClient1Source
, shader1
->last_compiled_source().c_str());
165 EXPECT_FALSE(shader1
->valid());
167 // Check DoCompile() will set compilation states, log, translated source,
168 // shader variables, and name mapping.
169 const std::string kLog
= "foo";
170 const std::string kTranslatedSource
= "poo";
172 AttributeMap attrib_map
;
173 attrib_map
[kAttrib1Name
] = TestHelper::ConstructAttribute(
174 kAttrib1Type
, kAttrib1Size
, kAttrib1Precision
,
175 kAttribStaticUse
, kAttrib1Name
);
176 attrib_map
[kAttrib2Name
] = TestHelper::ConstructAttribute(
177 kAttrib2Type
, kAttrib2Size
, kAttrib2Precision
,
178 kAttribStaticUse
, kAttrib2Name
);
179 UniformMap uniform_map
;
180 uniform_map
[kUniform1Name
] = TestHelper::ConstructUniform(
181 kUniform1Type
, kUniform1Size
, kUniform1Precision
,
182 kUniform1StaticUse
, kUniform1Name
);
183 uniform_map
[kUniform2Name
] = TestHelper::ConstructUniform(
184 kUniform2Type
, kUniform2Size
, kUniform2Precision
,
185 kUniform2StaticUse
, kUniform2Name
);
186 VaryingMap varying_map
;
187 varying_map
[kVarying1Name
] = TestHelper::ConstructVarying(
188 kVarying1Type
, kVarying1Size
, kVarying1Precision
,
189 kVarying1StaticUse
, kVarying1Name
);
191 TestHelper::SetShaderStates(
192 gl_
.get(), shader1
, true, &kLog
, &kTranslatedSource
, NULL
,
193 &attrib_map
, &uniform_map
, &varying_map
, NULL
);
194 EXPECT_TRUE(shader1
->valid());
195 // When compilation succeeds, no log is recorded.
196 EXPECT_STREQ("", shader1
->log_info().c_str());
197 EXPECT_STREQ(kClient1Source
, shader1
->last_compiled_source().c_str());
198 EXPECT_STREQ(kTranslatedSource
.c_str(), shader1
->translated_source().c_str());
200 // Check varying infos got copied.
201 EXPECT_EQ(attrib_map
.size(), shader1
->attrib_map().size());
202 for (AttributeMap::const_iterator it
= attrib_map
.begin();
203 it
!= attrib_map
.end(); ++it
) {
204 const sh::Attribute
* variable_info
= shader1
->GetAttribInfo(it
->first
);
205 ASSERT_TRUE(variable_info
!= NULL
);
206 EXPECT_EQ(it
->second
.type
, variable_info
->type
);
207 EXPECT_EQ(it
->second
.arraySize
, variable_info
->arraySize
);
208 EXPECT_EQ(it
->second
.precision
, variable_info
->precision
);
209 EXPECT_EQ(it
->second
.staticUse
, variable_info
->staticUse
);
210 EXPECT_STREQ(it
->second
.name
.c_str(), variable_info
->name
.c_str());
212 // Check uniform infos got copied.
213 EXPECT_EQ(uniform_map
.size(), shader1
->uniform_map().size());
214 for (UniformMap::const_iterator it
= uniform_map
.begin();
215 it
!= uniform_map
.end(); ++it
) {
216 const sh::Uniform
* variable_info
= shader1
->GetUniformInfo(it
->first
);
217 ASSERT_TRUE(variable_info
!= NULL
);
218 EXPECT_EQ(it
->second
.type
, variable_info
->type
);
219 EXPECT_EQ(it
->second
.arraySize
, variable_info
->arraySize
);
220 EXPECT_EQ(it
->second
.precision
, variable_info
->precision
);
221 EXPECT_EQ(it
->second
.staticUse
, variable_info
->staticUse
);
222 EXPECT_STREQ(it
->second
.name
.c_str(), variable_info
->name
.c_str());
224 // Check varying infos got copied.
225 EXPECT_EQ(varying_map
.size(), shader1
->varying_map().size());
226 for (VaryingMap::const_iterator it
= varying_map
.begin();
227 it
!= varying_map
.end(); ++it
) {
228 const sh::Varying
* variable_info
= shader1
->GetVaryingInfo(it
->first
);
229 ASSERT_TRUE(variable_info
!= NULL
);
230 EXPECT_EQ(it
->second
.type
, variable_info
->type
);
231 EXPECT_EQ(it
->second
.arraySize
, variable_info
->arraySize
);
232 EXPECT_EQ(it
->second
.precision
, variable_info
->precision
);
233 EXPECT_EQ(it
->second
.staticUse
, variable_info
->staticUse
);
234 EXPECT_STREQ(it
->second
.name
.c_str(), variable_info
->name
.c_str());
237 // Compile failure case.
238 TestHelper::SetShaderStates(
239 gl_
.get(), shader1
, false, &kLog
, &kTranslatedSource
, NULL
,
240 &attrib_map
, &uniform_map
, &varying_map
, NULL
);
241 EXPECT_FALSE(shader1
->valid());
242 EXPECT_STREQ(kLog
.c_str(), shader1
->log_info().c_str());
243 EXPECT_STREQ("", shader1
->translated_source().c_str());
244 EXPECT_TRUE(shader1
->attrib_map().empty());
245 EXPECT_TRUE(shader1
->uniform_map().empty());
246 EXPECT_TRUE(shader1
->varying_map().empty());
249 TEST_F(ShaderManagerTest
, ShaderInfoUseCount
) {
250 const GLuint kClient1Id
= 1;
251 const GLuint kService1Id
= 11;
252 const GLenum kShader1Type
= GL_VERTEX_SHADER
;
253 // Check we can create shader.
254 Shader
* shader1
= manager_
.CreateShader(
255 kClient1Id
, kService1Id
, kShader1Type
);
256 // Check shader got created.
257 ASSERT_TRUE(shader1
!= NULL
);
258 EXPECT_FALSE(shader1
->InUse());
259 EXPECT_FALSE(shader1
->IsDeleted());
260 manager_
.UseShader(shader1
);
261 EXPECT_TRUE(shader1
->InUse());
262 manager_
.UseShader(shader1
);
263 EXPECT_TRUE(shader1
->InUse());
264 EXPECT_CALL(*gl_
, DeleteShader(kService1Id
))
266 .RetiresOnSaturation();
267 manager_
.Delete(shader1
);
268 EXPECT_TRUE(shader1
->IsDeleted());
269 Shader
* shader2
= manager_
.GetShader(kClient1Id
);
270 EXPECT_EQ(shader1
, shader2
);
271 manager_
.UnuseShader(shader1
);
272 EXPECT_TRUE(shader1
->InUse());
273 manager_
.UnuseShader(shader1
); // this should delete the info.
274 shader2
= manager_
.GetShader(kClient1Id
);
275 EXPECT_TRUE(shader2
== NULL
);
277 shader1
= manager_
.CreateShader(kClient1Id
, kService1Id
, kShader1Type
);
278 ASSERT_TRUE(shader1
!= NULL
);
279 EXPECT_FALSE(shader1
->InUse());
280 manager_
.UseShader(shader1
);
281 EXPECT_TRUE(shader1
->InUse());
282 manager_
.UseShader(shader1
);
283 EXPECT_TRUE(shader1
->InUse());
284 manager_
.UnuseShader(shader1
);
285 EXPECT_TRUE(shader1
->InUse());
286 manager_
.UnuseShader(shader1
);
287 EXPECT_FALSE(shader1
->InUse());
288 shader2
= manager_
.GetShader(kClient1Id
);
289 EXPECT_EQ(shader1
, shader2
);
290 EXPECT_CALL(*gl_
, DeleteShader(kService1Id
))
292 .RetiresOnSaturation();
293 manager_
.Delete(shader1
); // this should delete the shader.
294 shader2
= manager_
.GetShader(kClient1Id
);
295 EXPECT_TRUE(shader2
== NULL
);