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 EXPECT_CALL(*gl_
, DeleteShader(kService1Id
))
87 .RetiresOnSaturation();
88 manager_
.Delete(shader1
.get());
89 EXPECT_CALL(*gl_
, DeleteShader(kService2Id
))
91 .RetiresOnSaturation();
92 manager_
.Delete(shader2
.get());
93 EXPECT_TRUE(manager_
.IsOwned(shader1
.get()));
94 EXPECT_FALSE(manager_
.IsOwned(shader2
.get()));
97 TEST_F(ShaderManagerTest
, DoCompile
) {
98 const GLuint kClient1Id
= 1;
99 const GLuint kService1Id
= 11;
100 const GLenum kShader1Type
= GL_VERTEX_SHADER
;
101 const char* kClient1Source
= "hello world";
102 const GLenum kAttrib1Type
= GL_FLOAT_VEC2
;
103 const GLint kAttrib1Size
= 2;
104 const GLenum kAttrib1Precision
= GL_MEDIUM_FLOAT
;
105 const char* kAttrib1Name
= "attr1";
106 const GLenum kAttrib2Type
= GL_FLOAT_VEC3
;
107 const GLint kAttrib2Size
= 4;
108 const GLenum kAttrib2Precision
= GL_HIGH_FLOAT
;
109 const char* kAttrib2Name
= "attr2";
110 const bool kAttribStaticUse
= false;
111 const GLenum kUniform1Type
= GL_FLOAT_MAT2
;
112 const GLint kUniform1Size
= 3;
113 const GLenum kUniform1Precision
= GL_LOW_FLOAT
;
114 const bool kUniform1StaticUse
= true;
115 const char* kUniform1Name
= "uni1";
116 const GLenum kUniform2Type
= GL_FLOAT_MAT3
;
117 const GLint kUniform2Size
= 5;
118 const GLenum kUniform2Precision
= GL_MEDIUM_FLOAT
;
119 const bool kUniform2StaticUse
= false;
120 const char* kUniform2Name
= "uni2";
121 const GLenum kVarying1Type
= GL_FLOAT_VEC4
;
122 const GLint kVarying1Size
= 1;
123 const GLenum kVarying1Precision
= GL_HIGH_FLOAT
;
124 const bool kVarying1StaticUse
= false;
125 const char* kVarying1Name
= "varying1";
127 // Check we can create shader.
128 Shader
* shader1
= manager_
.CreateShader(
129 kClient1Id
, kService1Id
, kShader1Type
);
130 // Check shader got created.
131 ASSERT_TRUE(shader1
!= NULL
);
132 EXPECT_EQ(kService1Id
, shader1
->service_id());
133 // Check if the shader has correct type.
134 EXPECT_EQ(kShader1Type
, shader1
->shader_type());
135 EXPECT_FALSE(shader1
->valid());
136 EXPECT_FALSE(shader1
->InUse());
137 EXPECT_TRUE(shader1
->source().empty());
138 EXPECT_TRUE(shader1
->log_info().empty());
139 EXPECT_TRUE(shader1
->last_compiled_source().empty());
140 EXPECT_TRUE(shader1
->translated_source().empty());
141 EXPECT_EQ(0u, shader1
->attrib_map().size());
142 EXPECT_EQ(0u, shader1
->uniform_map().size());
143 EXPECT_EQ(0u, shader1
->varying_map().size());
144 EXPECT_EQ(Shader::kShaderStateWaiting
, shader1
->shader_state());
146 // Check we can set its source.
147 shader1
->set_source(kClient1Source
);
148 EXPECT_STREQ(kClient1Source
, shader1
->source().c_str());
149 EXPECT_TRUE(shader1
->last_compiled_source().empty());
151 // Check that DoCompile() will not work if RequestCompile() was not called.
152 shader1
->DoCompile();
153 EXPECT_EQ(Shader::kShaderStateWaiting
, shader1
->shader_state());
154 EXPECT_FALSE(shader1
->valid());
156 // Check RequestCompile() will update the state and last compiled source, but
157 // still keep the actual compile state invalid.
158 scoped_refptr
<ShaderTranslatorInterface
> translator(new MockShaderTranslator
);
159 shader1
->RequestCompile(translator
, Shader::kANGLE
);
160 EXPECT_EQ(Shader::kShaderStateCompileRequested
, shader1
->shader_state());
161 EXPECT_STREQ(kClient1Source
, shader1
->last_compiled_source().c_str());
162 EXPECT_FALSE(shader1
->valid());
164 // Check DoCompile() will set compilation states, log, translated source,
165 // shader variables, and name mapping.
166 const std::string kLog
= "foo";
167 const std::string kTranslatedSource
= "poo";
169 AttributeMap attrib_map
;
170 attrib_map
[kAttrib1Name
] = TestHelper::ConstructAttribute(
171 kAttrib1Type
, kAttrib1Size
, kAttrib1Precision
,
172 kAttribStaticUse
, kAttrib1Name
);
173 attrib_map
[kAttrib2Name
] = TestHelper::ConstructAttribute(
174 kAttrib2Type
, kAttrib2Size
, kAttrib2Precision
,
175 kAttribStaticUse
, kAttrib2Name
);
176 UniformMap uniform_map
;
177 uniform_map
[kUniform1Name
] = TestHelper::ConstructUniform(
178 kUniform1Type
, kUniform1Size
, kUniform1Precision
,
179 kUniform1StaticUse
, kUniform1Name
);
180 uniform_map
[kUniform2Name
] = TestHelper::ConstructUniform(
181 kUniform2Type
, kUniform2Size
, kUniform2Precision
,
182 kUniform2StaticUse
, kUniform2Name
);
183 VaryingMap varying_map
;
184 varying_map
[kVarying1Name
] = TestHelper::ConstructVarying(
185 kVarying1Type
, kVarying1Size
, kVarying1Precision
,
186 kVarying1StaticUse
, kVarying1Name
);
188 TestHelper::SetShaderStates(
189 gl_
.get(), shader1
, true, &kLog
, &kTranslatedSource
,
190 &attrib_map
, &uniform_map
, &varying_map
, NULL
);
191 EXPECT_TRUE(shader1
->valid());
192 // When compilation succeeds, no log is recorded.
193 EXPECT_STREQ("", shader1
->log_info().c_str());
194 EXPECT_STREQ(kClient1Source
, shader1
->last_compiled_source().c_str());
195 EXPECT_STREQ(kTranslatedSource
.c_str(), shader1
->translated_source().c_str());
197 // Check varying infos got copied.
198 EXPECT_EQ(attrib_map
.size(), shader1
->attrib_map().size());
199 for (AttributeMap::const_iterator it
= attrib_map
.begin();
200 it
!= attrib_map
.end(); ++it
) {
201 const sh::Attribute
* variable_info
= shader1
->GetAttribInfo(it
->first
);
202 ASSERT_TRUE(variable_info
!= NULL
);
203 EXPECT_EQ(it
->second
.type
, variable_info
->type
);
204 EXPECT_EQ(it
->second
.arraySize
, variable_info
->arraySize
);
205 EXPECT_EQ(it
->second
.precision
, variable_info
->precision
);
206 EXPECT_EQ(it
->second
.staticUse
, variable_info
->staticUse
);
207 EXPECT_STREQ(it
->second
.name
.c_str(), variable_info
->name
.c_str());
209 // Check uniform infos got copied.
210 EXPECT_EQ(uniform_map
.size(), shader1
->uniform_map().size());
211 for (UniformMap::const_iterator it
= uniform_map
.begin();
212 it
!= uniform_map
.end(); ++it
) {
213 const sh::Uniform
* variable_info
= shader1
->GetUniformInfo(it
->first
);
214 ASSERT_TRUE(variable_info
!= NULL
);
215 EXPECT_EQ(it
->second
.type
, variable_info
->type
);
216 EXPECT_EQ(it
->second
.arraySize
, variable_info
->arraySize
);
217 EXPECT_EQ(it
->second
.precision
, variable_info
->precision
);
218 EXPECT_EQ(it
->second
.staticUse
, variable_info
->staticUse
);
219 EXPECT_STREQ(it
->second
.name
.c_str(), variable_info
->name
.c_str());
221 // Check varying infos got copied.
222 EXPECT_EQ(varying_map
.size(), shader1
->varying_map().size());
223 for (VaryingMap::const_iterator it
= varying_map
.begin();
224 it
!= varying_map
.end(); ++it
) {
225 const sh::Varying
* variable_info
= shader1
->GetVaryingInfo(it
->first
);
226 ASSERT_TRUE(variable_info
!= NULL
);
227 EXPECT_EQ(it
->second
.type
, variable_info
->type
);
228 EXPECT_EQ(it
->second
.arraySize
, variable_info
->arraySize
);
229 EXPECT_EQ(it
->second
.precision
, variable_info
->precision
);
230 EXPECT_EQ(it
->second
.staticUse
, variable_info
->staticUse
);
231 EXPECT_STREQ(it
->second
.name
.c_str(), variable_info
->name
.c_str());
234 // Compile failure case.
235 TestHelper::SetShaderStates(
236 gl_
.get(), shader1
, false, &kLog
, &kTranslatedSource
,
237 &attrib_map
, &uniform_map
, &varying_map
, NULL
);
238 EXPECT_FALSE(shader1
->valid());
239 EXPECT_STREQ(kLog
.c_str(), shader1
->log_info().c_str());
240 EXPECT_STREQ("", shader1
->translated_source().c_str());
241 EXPECT_TRUE(shader1
->attrib_map().empty());
242 EXPECT_TRUE(shader1
->uniform_map().empty());
243 EXPECT_TRUE(shader1
->varying_map().empty());
246 TEST_F(ShaderManagerTest
, ShaderInfoUseCount
) {
247 const GLuint kClient1Id
= 1;
248 const GLuint kService1Id
= 11;
249 const GLenum kShader1Type
= GL_VERTEX_SHADER
;
250 // Check we can create shader.
251 Shader
* shader1
= manager_
.CreateShader(
252 kClient1Id
, kService1Id
, kShader1Type
);
253 // Check shader got created.
254 ASSERT_TRUE(shader1
!= NULL
);
255 EXPECT_FALSE(shader1
->InUse());
256 EXPECT_FALSE(shader1
->IsDeleted());
257 manager_
.UseShader(shader1
);
258 EXPECT_TRUE(shader1
->InUse());
259 manager_
.UseShader(shader1
);
260 EXPECT_TRUE(shader1
->InUse());
261 EXPECT_CALL(*gl_
, DeleteShader(kService1Id
))
263 .RetiresOnSaturation();
264 manager_
.Delete(shader1
);
265 EXPECT_TRUE(shader1
->IsDeleted());
266 Shader
* shader2
= manager_
.GetShader(kClient1Id
);
267 EXPECT_EQ(shader1
, shader2
);
268 manager_
.UnuseShader(shader1
);
269 EXPECT_TRUE(shader1
->InUse());
270 manager_
.UnuseShader(shader1
); // this should delete the info.
271 shader2
= manager_
.GetShader(kClient1Id
);
272 EXPECT_TRUE(shader2
== NULL
);
274 shader1
= manager_
.CreateShader(kClient1Id
, kService1Id
, kShader1Type
);
275 ASSERT_TRUE(shader1
!= NULL
);
276 EXPECT_FALSE(shader1
->InUse());
277 manager_
.UseShader(shader1
);
278 EXPECT_TRUE(shader1
->InUse());
279 manager_
.UseShader(shader1
);
280 EXPECT_TRUE(shader1
->InUse());
281 manager_
.UnuseShader(shader1
);
282 EXPECT_TRUE(shader1
->InUse());
283 manager_
.UnuseShader(shader1
);
284 EXPECT_FALSE(shader1
->InUse());
285 shader2
= manager_
.GetShader(kClient1Id
);
286 EXPECT_EQ(shader1
, shader2
);
287 EXPECT_CALL(*gl_
, DeleteShader(kService1Id
))
289 .RetiresOnSaturation();
290 manager_
.Delete(shader1
); // this should delete the shader.
291 shader2
= manager_
.GetShader(kClient1Id
);
292 EXPECT_TRUE(shader2
== NULL
);