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/shader_manager.h" 6 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" 13 14 using ::testing::Return; 15 using ::testing::ReturnRef; 16 17 namespace gpu { 18 namespace gles2 { 19 20 class ShaderManagerTest : public GpuServiceTest { 21 public: 22 ShaderManagerTest() { 23 } 24 25 virtual ~ShaderManagerTest() { 26 manager_.Destroy(false); 27 } 28 29 protected: 30 ShaderManager manager_; 31 }; 32 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); 50 } 51 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)) 62 .Times(1) 63 .RetiresOnSaturation(); 64 manager_.Destroy(true); 65 // Check that resources got freed. 66 shader1 = manager_.GetShader(kClient1Id); 67 ASSERT_TRUE(shader1 == NULL); 68 } 69 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())); 88 } 89 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"; 119 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()); 137 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()); 142 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"; 147 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); 166 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()); 175 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()); 188 } 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()); 201 } 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()); 214 } 215 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()); 226 } 227 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); 252 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); 269 } 270 271 } // namespace gles2 272 } // namespace gpu 273