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 virtual ~ShaderManagerTest() {
26 manager_
.Destroy(false);
30 ShaderManager manager_
;
33 TEST_F(ShaderManagerTest
, Basic
) {
34 const GLuint kClient1Id
= 1;
35 const GLuint kService1Id
= 11;
36 const GLenum kShader1Type
= GL_VERTEX_SHADER
;
37 const GLuint kClient2Id
= 2;
38 // Check we can create shader.
39 Shader
* info0
= manager_
.CreateShader(
40 kClient1Id
, kService1Id
, kShader1Type
);
41 // Check shader got created.
42 ASSERT_TRUE(info0
!= NULL
);
43 Shader
* shader1
= manager_
.GetShader(kClient1Id
);
44 ASSERT_EQ(info0
, shader1
);
45 // Check we get nothing for a non-existent shader.
46 EXPECT_TRUE(manager_
.GetShader(kClient2Id
) == NULL
);
47 // Check we can't get the shader after we remove it.
48 manager_
.MarkAsDeleted(shader1
);
49 EXPECT_TRUE(manager_
.GetShader(kClient1Id
) == NULL
);
52 TEST_F(ShaderManagerTest
, Destroy
) {
53 const GLuint kClient1Id
= 1;
54 const GLuint kService1Id
= 11;
55 const GLenum kShader1Type
= GL_VERTEX_SHADER
;
56 // Check we can create shader.
57 Shader
* shader1
= manager_
.CreateShader(
58 kClient1Id
, kService1Id
, kShader1Type
);
59 // Check shader got created.
60 ASSERT_TRUE(shader1
!= NULL
);
61 EXPECT_CALL(*gl_
, DeleteShader(kService1Id
))
63 .RetiresOnSaturation();
64 manager_
.Destroy(true);
65 // Check that resources got freed.
66 shader1
= manager_
.GetShader(kClient1Id
);
67 ASSERT_TRUE(shader1
== NULL
);
70 TEST_F(ShaderManagerTest
, DeleteBug
) {
71 const GLuint kClient1Id
= 1;
72 const GLuint kClient2Id
= 2;
73 const GLuint kService1Id
= 11;
74 const GLuint kService2Id
= 12;
75 const GLenum kShaderType
= GL_VERTEX_SHADER
;
76 // Check we can create shader.
77 scoped_refptr
<Shader
> shader1(
78 manager_
.CreateShader(kClient1Id
, kService1Id
, kShaderType
));
79 scoped_refptr
<Shader
> shader2(
80 manager_
.CreateShader(kClient2Id
, kService2Id
, kShaderType
));
81 ASSERT_TRUE(shader1
.get());
82 ASSERT_TRUE(shader2
.get());
83 manager_
.UseShader(shader1
.get());
84 manager_
.MarkAsDeleted(shader1
.get());
85 manager_
.MarkAsDeleted(shader2
.get());
86 EXPECT_TRUE(manager_
.IsOwned(shader1
.get()));
87 EXPECT_FALSE(manager_
.IsOwned(shader2
.get()));
90 TEST_F(ShaderManagerTest
, DoCompile
) {
91 const GLuint kClient1Id
= 1;
92 const GLuint kService1Id
= 11;
93 const GLenum kShader1Type
= GL_VERTEX_SHADER
;
94 const char* kClient1Source
= "hello world";
95 const GLenum kAttrib1Type
= GL_FLOAT_VEC2
;
96 const GLsizei kAttrib1Size
= 2;
97 const int kAttrib1Precision
= SH_PRECISION_MEDIUMP
;
98 const char* kAttrib1Name
= "attr1";
99 const GLenum kAttrib2Type
= GL_FLOAT_VEC3
;
100 const GLsizei kAttrib2Size
= 4;
101 const int kAttrib2Precision
= SH_PRECISION_HIGHP
;
102 const char* kAttrib2Name
= "attr2";
103 const int kAttribStaticUse
= 0;
104 const GLenum kUniform1Type
= GL_FLOAT_MAT2
;
105 const GLsizei kUniform1Size
= 3;
106 const int kUniform1Precision
= SH_PRECISION_LOWP
;
107 const int kUniform1StaticUse
= 1;
108 const char* kUniform1Name
= "uni1";
109 const GLenum kUniform2Type
= GL_FLOAT_MAT3
;
110 const GLsizei kUniform2Size
= 5;
111 const int kUniform2Precision
= SH_PRECISION_MEDIUMP
;
112 const int kUniform2StaticUse
= 0;
113 const char* kUniform2Name
= "uni2";
114 const GLenum kVarying1Type
= GL_FLOAT_VEC4
;
115 const GLsizei kVarying1Size
= 1;
116 const int kVarying1Precision
= SH_PRECISION_HIGHP
;
117 const int kVarying1StaticUse
= 0;
118 const char* kVarying1Name
= "varying1";
120 // Check we can create shader.
121 Shader
* shader1
= manager_
.CreateShader(
122 kClient1Id
, kService1Id
, kShader1Type
);
123 // Check shader got created.
124 ASSERT_TRUE(shader1
!= NULL
);
125 EXPECT_EQ(kService1Id
, shader1
->service_id());
126 // Check if the shader has correct type.
127 EXPECT_EQ(kShader1Type
, shader1
->shader_type());
128 EXPECT_FALSE(shader1
->valid());
129 EXPECT_FALSE(shader1
->InUse());
130 EXPECT_TRUE(shader1
->source().empty());
131 EXPECT_TRUE(shader1
->log_info().empty());
132 EXPECT_TRUE(shader1
->signature_source().empty());
133 EXPECT_TRUE(shader1
->translated_source().empty());
134 EXPECT_EQ(0u, shader1
->attrib_map().size());
135 EXPECT_EQ(0u, shader1
->uniform_map().size());
136 EXPECT_EQ(0u, shader1
->varying_map().size());
138 // Check we can set its source.
139 shader1
->set_source(kClient1Source
);
140 EXPECT_STREQ(kClient1Source
, shader1
->source().c_str());
141 EXPECT_TRUE(shader1
->signature_source().empty());
143 // Check DoCompile() will set compilation states, log, translated source,
144 // shader variables, and name mapping.
145 const std::string kLog
= "foo";
146 const std::string kTranslatedSource
= "poo";
148 ShaderTranslator::VariableMap attrib_map
;
149 attrib_map
[kAttrib1Name
] = ShaderTranslatorInterface::VariableInfo(
150 kAttrib1Type
, kAttrib1Size
, kAttrib1Precision
,
151 kAttribStaticUse
, kAttrib1Name
);
152 attrib_map
[kAttrib2Name
] = ShaderTranslatorInterface::VariableInfo(
153 kAttrib2Type
, kAttrib2Size
, kAttrib2Precision
,
154 kAttribStaticUse
, kAttrib2Name
);
155 ShaderTranslator::VariableMap uniform_map
;
156 uniform_map
[kUniform1Name
] = ShaderTranslatorInterface::VariableInfo(
157 kUniform1Type
, kUniform1Size
, kUniform1Precision
,
158 kUniform1StaticUse
, kUniform1Name
);
159 uniform_map
[kUniform2Name
] = ShaderTranslatorInterface::VariableInfo(
160 kUniform2Type
, kUniform2Size
, kUniform2Precision
,
161 kUniform2StaticUse
, kUniform2Name
);
162 ShaderTranslator::VariableMap varying_map
;
163 varying_map
[kVarying1Name
] = ShaderTranslatorInterface::VariableInfo(
164 kVarying1Type
, kVarying1Size
, kVarying1Precision
,
165 kVarying1StaticUse
, kVarying1Name
);
167 TestHelper::SetShaderStates(
168 gl_
.get(), shader1
, true, &kLog
, &kTranslatedSource
,
169 &attrib_map
, &uniform_map
, &varying_map
, NULL
);
170 EXPECT_TRUE(shader1
->valid());
171 // When compilation succeeds, no log is recorded.
172 EXPECT_STREQ("", shader1
->log_info().c_str());
173 EXPECT_STREQ(kClient1Source
, shader1
->signature_source().c_str());
174 EXPECT_STREQ(kTranslatedSource
.c_str(), shader1
->translated_source().c_str());
176 // Check varying infos got copied.
177 EXPECT_EQ(attrib_map
.size(), shader1
->attrib_map().size());
178 for (ShaderTranslator::VariableMap::const_iterator it
= attrib_map
.begin();
179 it
!= attrib_map
.end(); ++it
) {
180 const Shader::VariableInfo
* variable_info
=
181 shader1
->GetAttribInfo(it
->first
);
182 ASSERT_TRUE(variable_info
!= NULL
);
183 EXPECT_EQ(it
->second
.type
, variable_info
->type
);
184 EXPECT_EQ(it
->second
.size
, variable_info
->size
);
185 EXPECT_EQ(it
->second
.precision
, variable_info
->precision
);
186 EXPECT_EQ(it
->second
.static_use
, variable_info
->static_use
);
187 EXPECT_STREQ(it
->second
.name
.c_str(), variable_info
->name
.c_str());
189 // Check uniform infos got copied.
190 EXPECT_EQ(uniform_map
.size(), shader1
->uniform_map().size());
191 for (ShaderTranslator::VariableMap::const_iterator it
= uniform_map
.begin();
192 it
!= uniform_map
.end(); ++it
) {
193 const Shader::VariableInfo
* variable_info
=
194 shader1
->GetUniformInfo(it
->first
);
195 ASSERT_TRUE(variable_info
!= NULL
);
196 EXPECT_EQ(it
->second
.type
, variable_info
->type
);
197 EXPECT_EQ(it
->second
.size
, variable_info
->size
);
198 EXPECT_EQ(it
->second
.precision
, variable_info
->precision
);
199 EXPECT_EQ(it
->second
.static_use
, variable_info
->static_use
);
200 EXPECT_STREQ(it
->second
.name
.c_str(), variable_info
->name
.c_str());
202 // Check varying infos got copied.
203 EXPECT_EQ(varying_map
.size(), shader1
->varying_map().size());
204 for (ShaderTranslator::VariableMap::const_iterator it
= varying_map
.begin();
205 it
!= varying_map
.end(); ++it
) {
206 const Shader::VariableInfo
* variable_info
=
207 shader1
->GetVaryingInfo(it
->first
);
208 ASSERT_TRUE(variable_info
!= NULL
);
209 EXPECT_EQ(it
->second
.type
, variable_info
->type
);
210 EXPECT_EQ(it
->second
.size
, variable_info
->size
);
211 EXPECT_EQ(it
->second
.precision
, variable_info
->precision
);
212 EXPECT_EQ(it
->second
.static_use
, variable_info
->static_use
);
213 EXPECT_STREQ(it
->second
.name
.c_str(), variable_info
->name
.c_str());
216 // Compile failure case.
217 TestHelper::SetShaderStates(
218 gl_
.get(), shader1
, false, &kLog
, &kTranslatedSource
,
219 &attrib_map
, &uniform_map
, &varying_map
, NULL
);
220 EXPECT_FALSE(shader1
->valid());
221 EXPECT_STREQ(kLog
.c_str(), shader1
->log_info().c_str());
222 EXPECT_STREQ("", shader1
->translated_source().c_str());
223 EXPECT_TRUE(shader1
->attrib_map().empty());
224 EXPECT_TRUE(shader1
->uniform_map().empty());
225 EXPECT_TRUE(shader1
->varying_map().empty());
228 TEST_F(ShaderManagerTest
, ShaderInfoUseCount
) {
229 const GLuint kClient1Id
= 1;
230 const GLuint kService1Id
= 11;
231 const GLenum kShader1Type
= GL_VERTEX_SHADER
;
232 // Check we can create shader.
233 Shader
* shader1
= manager_
.CreateShader(
234 kClient1Id
, kService1Id
, kShader1Type
);
235 // Check shader got created.
236 ASSERT_TRUE(shader1
!= NULL
);
237 EXPECT_FALSE(shader1
->InUse());
238 EXPECT_FALSE(shader1
->IsDeleted());
239 manager_
.UseShader(shader1
);
240 EXPECT_TRUE(shader1
->InUse());
241 manager_
.UseShader(shader1
);
242 EXPECT_TRUE(shader1
->InUse());
243 manager_
.MarkAsDeleted(shader1
);
244 EXPECT_TRUE(shader1
->IsDeleted());
245 Shader
* shader2
= manager_
.GetShader(kClient1Id
);
246 EXPECT_EQ(shader1
, shader2
);
247 manager_
.UnuseShader(shader1
);
248 EXPECT_TRUE(shader1
->InUse());
249 manager_
.UnuseShader(shader1
); // this should delete the info.
250 shader2
= manager_
.GetShader(kClient1Id
);
251 EXPECT_TRUE(shader2
== NULL
);
253 shader1
= manager_
.CreateShader(kClient1Id
, kService1Id
, kShader1Type
);
254 ASSERT_TRUE(shader1
!= NULL
);
255 EXPECT_FALSE(shader1
->InUse());
256 manager_
.UseShader(shader1
);
257 EXPECT_TRUE(shader1
->InUse());
258 manager_
.UseShader(shader1
);
259 EXPECT_TRUE(shader1
->InUse());
260 manager_
.UnuseShader(shader1
);
261 EXPECT_TRUE(shader1
->InUse());
262 manager_
.UnuseShader(shader1
);
263 EXPECT_FALSE(shader1
->InUse());
264 shader2
= manager_
.GetShader(kClient1Id
);
265 EXPECT_EQ(shader1
, shader2
);
266 manager_
.MarkAsDeleted(shader1
); // this should delete the shader.
267 shader2
= manager_
.GetShader(kClient1Id
);
268 EXPECT_TRUE(shader2
== NULL
);