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 manager_.MarkAsDeleted(shader1);
47 EXPECT_TRUE(manager_.GetShader(kClient1Id) == NULL);
50 TEST_F(ShaderManagerTest, Destroy) {
51 const GLuint kClient1Id = 1;
52 const GLuint kService1Id = 11;
53 const GLenum kShader1Type = GL_VERTEX_SHADER;
54 // Check we can create shader.
55 Shader* shader1 = manager_.CreateShader(
56 kClient1Id, kService1Id, kShader1Type);
57 // Check shader got created.
58 ASSERT_TRUE(shader1 != NULL);
59 EXPECT_CALL(*gl_, DeleteShader(kService1Id))
61 .RetiresOnSaturation();
62 manager_.Destroy(true);
63 // Check that resources got freed.
64 shader1 = manager_.GetShader(kClient1Id);
65 ASSERT_TRUE(shader1 == NULL);
68 TEST_F(ShaderManagerTest, DeleteBug) {
69 const GLuint kClient1Id = 1;
70 const GLuint kClient2Id = 2;
71 const GLuint kService1Id = 11;
72 const GLuint kService2Id = 12;
73 const GLenum kShaderType = GL_VERTEX_SHADER;
74 // Check we can create shader.
75 scoped_refptr<Shader> shader1(
76 manager_.CreateShader(kClient1Id, kService1Id, kShaderType));
77 scoped_refptr<Shader> shader2(
78 manager_.CreateShader(kClient2Id, kService2Id, kShaderType));
79 ASSERT_TRUE(shader1.get());
80 ASSERT_TRUE(shader2.get());
81 manager_.UseShader(shader1.get());
82 manager_.MarkAsDeleted(shader1.get());
83 manager_.MarkAsDeleted(shader2.get());
84 EXPECT_TRUE(manager_.IsOwned(shader1.get()));
85 EXPECT_FALSE(manager_.IsOwned(shader2.get()));
88 TEST_F(ShaderManagerTest, DoCompile) {
89 const GLuint kClient1Id = 1;
90 const GLuint kService1Id = 11;
91 const GLenum kShader1Type = GL_VERTEX_SHADER;
92 const char* kClient1Source = "hello world";
93 const GLenum kAttrib1Type = GL_FLOAT_VEC2;
94 const GLint kAttrib1Size = 2;
95 const GLenum kAttrib1Precision = GL_MEDIUM_FLOAT;
96 const char* kAttrib1Name = "attr1";
97 const GLenum kAttrib2Type = GL_FLOAT_VEC3;
98 const GLint kAttrib2Size = 4;
99 const GLenum kAttrib2Precision = GL_HIGH_FLOAT;
100 const char* kAttrib2Name = "attr2";
101 const bool kAttribStaticUse = false;
102 const GLenum kUniform1Type = GL_FLOAT_MAT2;
103 const GLint kUniform1Size = 3;
104 const GLenum kUniform1Precision = GL_LOW_FLOAT;
105 const bool kUniform1StaticUse = true;
106 const char* kUniform1Name = "uni1";
107 const GLenum kUniform2Type = GL_FLOAT_MAT3;
108 const GLint kUniform2Size = 5;
109 const GLenum kUniform2Precision = GL_MEDIUM_FLOAT;
110 const bool kUniform2StaticUse = false;
111 const char* kUniform2Name = "uni2";
112 const GLenum kVarying1Type = GL_FLOAT_VEC4;
113 const GLint kVarying1Size = 1;
114 const GLenum kVarying1Precision = GL_HIGH_FLOAT;
115 const bool kVarying1StaticUse = false;
116 const char* kVarying1Name = "varying1";
118 // Check we can create shader.
119 Shader* shader1 = manager_.CreateShader(
120 kClient1Id, kService1Id, kShader1Type);
121 // Check shader got created.
122 ASSERT_TRUE(shader1 != NULL);
123 EXPECT_EQ(kService1Id, shader1->service_id());
124 // Check if the shader has correct type.
125 EXPECT_EQ(kShader1Type, shader1->shader_type());
126 EXPECT_FALSE(shader1->valid());
127 EXPECT_FALSE(shader1->InUse());
128 EXPECT_TRUE(shader1->source().empty());
129 EXPECT_TRUE(shader1->log_info().empty());
130 EXPECT_TRUE(shader1->signature_source().empty());
131 EXPECT_TRUE(shader1->translated_source().empty());
132 EXPECT_EQ(0u, shader1->attrib_map().size());
133 EXPECT_EQ(0u, shader1->uniform_map().size());
134 EXPECT_EQ(0u, shader1->varying_map().size());
136 // Check we can set its source.
137 shader1->set_source(kClient1Source);
138 EXPECT_STREQ(kClient1Source, shader1->source().c_str());
139 EXPECT_TRUE(shader1->signature_source().empty());
141 // Check DoCompile() will set compilation states, log, translated source,
142 // shader variables, and name mapping.
143 const std::string kLog = "foo";
144 const std::string kTranslatedSource = "poo";
146 AttributeMap attrib_map;
147 attrib_map[kAttrib1Name] = TestHelper::ConstructAttribute(
148 kAttrib1Type, kAttrib1Size, kAttrib1Precision,
149 kAttribStaticUse, kAttrib1Name);
150 attrib_map[kAttrib2Name] = TestHelper::ConstructAttribute(
151 kAttrib2Type, kAttrib2Size, kAttrib2Precision,
152 kAttribStaticUse, kAttrib2Name);
153 UniformMap uniform_map;
154 uniform_map[kUniform1Name] = TestHelper::ConstructUniform(
155 kUniform1Type, kUniform1Size, kUniform1Precision,
156 kUniform1StaticUse, kUniform1Name);
157 uniform_map[kUniform2Name] = TestHelper::ConstructUniform(
158 kUniform2Type, kUniform2Size, kUniform2Precision,
159 kUniform2StaticUse, kUniform2Name);
160 VaryingMap varying_map;
161 varying_map[kVarying1Name] = TestHelper::ConstructVarying(
162 kVarying1Type, kVarying1Size, kVarying1Precision,
163 kVarying1StaticUse, kVarying1Name);
165 TestHelper::SetShaderStates(
166 gl_.get(), shader1, true, &kLog, &kTranslatedSource,
167 &attrib_map, &uniform_map, &varying_map, NULL);
168 EXPECT_TRUE(shader1->valid());
169 // When compilation succeeds, no log is recorded.
170 EXPECT_STREQ("", shader1->log_info().c_str());
171 EXPECT_STREQ(kClient1Source, shader1->signature_source().c_str());
172 EXPECT_STREQ(kTranslatedSource.c_str(), shader1->translated_source().c_str());
174 // Check varying infos got copied.
175 EXPECT_EQ(attrib_map.size(), shader1->attrib_map().size());
176 for (AttributeMap::const_iterator it = attrib_map.begin();
177 it != attrib_map.end(); ++it) {
178 const sh::Attribute* variable_info = shader1->GetAttribInfo(it->first);
179 ASSERT_TRUE(variable_info != NULL);
180 EXPECT_EQ(it->second.type, variable_info->type);
181 EXPECT_EQ(it->second.arraySize, variable_info->arraySize);
182 EXPECT_EQ(it->second.precision, variable_info->precision);
183 EXPECT_EQ(it->second.staticUse, variable_info->staticUse);
184 EXPECT_STREQ(it->second.name.c_str(), variable_info->name.c_str());
186 // Check uniform infos got copied.
187 EXPECT_EQ(uniform_map.size(), shader1->uniform_map().size());
188 for (UniformMap::const_iterator it = uniform_map.begin();
189 it != uniform_map.end(); ++it) {
190 const sh::Uniform* variable_info = shader1->GetUniformInfo(it->first);
191 ASSERT_TRUE(variable_info != NULL);
192 EXPECT_EQ(it->second.type, variable_info->type);
193 EXPECT_EQ(it->second.arraySize, variable_info->arraySize);
194 EXPECT_EQ(it->second.precision, variable_info->precision);
195 EXPECT_EQ(it->second.staticUse, variable_info->staticUse);
196 EXPECT_STREQ(it->second.name.c_str(), variable_info->name.c_str());
198 // Check varying infos got copied.
199 EXPECT_EQ(varying_map.size(), shader1->varying_map().size());
200 for (VaryingMap::const_iterator it = varying_map.begin();
201 it != varying_map.end(); ++it) {
202 const sh::Varying* variable_info = shader1->GetVaryingInfo(it->first);
203 ASSERT_TRUE(variable_info != NULL);
204 EXPECT_EQ(it->second.type, variable_info->type);
205 EXPECT_EQ(it->second.arraySize, variable_info->arraySize);
206 EXPECT_EQ(it->second.precision, variable_info->precision);
207 EXPECT_EQ(it->second.staticUse, variable_info->staticUse);
208 EXPECT_STREQ(it->second.name.c_str(), variable_info->name.c_str());
211 // Compile failure case.
212 TestHelper::SetShaderStates(
213 gl_.get(), shader1, false, &kLog, &kTranslatedSource,
214 &attrib_map, &uniform_map, &varying_map, NULL);
215 EXPECT_FALSE(shader1->valid());
216 EXPECT_STREQ(kLog.c_str(), shader1->log_info().c_str());
217 EXPECT_STREQ("", shader1->translated_source().c_str());
218 EXPECT_TRUE(shader1->attrib_map().empty());
219 EXPECT_TRUE(shader1->uniform_map().empty());
220 EXPECT_TRUE(shader1->varying_map().empty());
223 TEST_F(ShaderManagerTest, ShaderInfoUseCount) {
224 const GLuint kClient1Id = 1;
225 const GLuint kService1Id = 11;
226 const GLenum kShader1Type = GL_VERTEX_SHADER;
227 // Check we can create shader.
228 Shader* shader1 = manager_.CreateShader(
229 kClient1Id, kService1Id, kShader1Type);
230 // Check shader got created.
231 ASSERT_TRUE(shader1 != NULL);
232 EXPECT_FALSE(shader1->InUse());
233 EXPECT_FALSE(shader1->IsDeleted());
234 manager_.UseShader(shader1);
235 EXPECT_TRUE(shader1->InUse());
236 manager_.UseShader(shader1);
237 EXPECT_TRUE(shader1->InUse());
238 manager_.MarkAsDeleted(shader1);
239 EXPECT_TRUE(shader1->IsDeleted());
240 Shader* shader2 = manager_.GetShader(kClient1Id);
241 EXPECT_EQ(shader1, shader2);
242 manager_.UnuseShader(shader1);
243 EXPECT_TRUE(shader1->InUse());
244 manager_.UnuseShader(shader1); // this should delete the info.
245 shader2 = manager_.GetShader(kClient1Id);
246 EXPECT_TRUE(shader2 == NULL);
248 shader1 = manager_.CreateShader(kClient1Id, kService1Id, kShader1Type);
249 ASSERT_TRUE(shader1 != NULL);
250 EXPECT_FALSE(shader1->InUse());
251 manager_.UseShader(shader1);
252 EXPECT_TRUE(shader1->InUse());
253 manager_.UseShader(shader1);
254 EXPECT_TRUE(shader1->InUse());
255 manager_.UnuseShader(shader1);
256 EXPECT_TRUE(shader1->InUse());
257 manager_.UnuseShader(shader1);
258 EXPECT_FALSE(shader1->InUse());
259 shader2 = manager_.GetShader(kClient1Id);
260 EXPECT_EQ(shader1, shader2);
261 manager_.MarkAsDeleted(shader1); // this should delete the shader.
262 shader2 = manager_.GetShader(kClient1Id);
263 EXPECT_TRUE(shader2 == NULL);