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_translator.h" 6 #include "testing/gtest/include/gtest/gtest.h" 7 8 namespace gpu { 9 namespace gles2 { 10 11 class ShaderTranslatorTest : public testing::Test { 12 public: 13 ShaderTranslatorTest() { 14 } 15 16 virtual ~ShaderTranslatorTest() { 17 } 18 19 protected: 20 virtual void SetUp() { 21 ShBuiltInResources resources; 22 resources.MaxExpressionComplexity = 32; 23 resources.MaxCallStackDepth = 32; 24 ShInitBuiltInResources(&resources); 25 vertex_translator_ = new ShaderTranslator(); 26 fragment_translator_ = new ShaderTranslator(); 27 28 ASSERT_TRUE(vertex_translator_->Init( 29 SH_VERTEX_SHADER, SH_GLES2_SPEC, &resources, 30 ShaderTranslatorInterface::kGlsl, 31 SH_EMULATE_BUILT_IN_FUNCTIONS)); 32 ASSERT_TRUE(fragment_translator_->Init( 33 SH_FRAGMENT_SHADER, SH_GLES2_SPEC, &resources, 34 ShaderTranslatorInterface::kGlsl, 35 static_cast<ShCompileOptions>(0))); 36 // Post-init the results must be empty. 37 // Vertex translator results. 38 EXPECT_TRUE(vertex_translator_->translated_shader() == NULL); 39 EXPECT_TRUE(vertex_translator_->info_log() == NULL); 40 EXPECT_TRUE(vertex_translator_->attrib_map().empty()); 41 EXPECT_TRUE(vertex_translator_->uniform_map().empty()); 42 // Fragment translator results. 43 EXPECT_TRUE(fragment_translator_->translated_shader() == NULL); 44 EXPECT_TRUE(fragment_translator_->info_log() == NULL); 45 EXPECT_TRUE(fragment_translator_->attrib_map().empty()); 46 EXPECT_TRUE(fragment_translator_->uniform_map().empty()); 47 } 48 virtual void TearDown() { 49 vertex_translator_ = NULL; 50 fragment_translator_ = NULL; 51 } 52 53 scoped_refptr<ShaderTranslator> vertex_translator_; 54 scoped_refptr<ShaderTranslator> fragment_translator_; 55 }; 56 57 TEST_F(ShaderTranslatorTest, ValidVertexShader) { 58 const char* shader = 59 "void main() {\n" 60 " gl_Position = vec4(1.0);\n" 61 "}"; 62 63 // A valid shader should be successfully translated. 64 EXPECT_TRUE(vertex_translator_->Translate(shader)); 65 // Info log must be NULL. 66 EXPECT_TRUE(vertex_translator_->info_log() == NULL); 67 // Translated shader must be valid and non-empty. 68 ASSERT_TRUE(vertex_translator_->translated_shader() != NULL); 69 EXPECT_GT(strlen(vertex_translator_->translated_shader()), 0u); 70 // There should be no attributes or uniforms. 71 EXPECT_TRUE(vertex_translator_->attrib_map().empty()); 72 EXPECT_TRUE(vertex_translator_->uniform_map().empty()); 73 } 74 75 TEST_F(ShaderTranslatorTest, InvalidVertexShader) { 76 const char* bad_shader = "foo-bar"; 77 const char* good_shader = 78 "void main() {\n" 79 " gl_Position = vec4(1.0);\n" 80 "}"; 81 82 // An invalid shader should fail. 83 EXPECT_FALSE(vertex_translator_->Translate(bad_shader)); 84 // Info log must be valid and non-empty. 85 ASSERT_TRUE(vertex_translator_->info_log() != NULL); 86 EXPECT_GT(strlen(vertex_translator_->info_log()), 0u); 87 // Translated shader must be NULL. 88 EXPECT_TRUE(vertex_translator_->translated_shader() == NULL); 89 // There should be no attributes or uniforms. 90 EXPECT_TRUE(vertex_translator_->attrib_map().empty()); 91 EXPECT_TRUE(vertex_translator_->uniform_map().empty()); 92 93 // Try a good shader after bad. 94 EXPECT_TRUE(vertex_translator_->Translate(good_shader)); 95 EXPECT_TRUE(vertex_translator_->info_log() == NULL); 96 ASSERT_TRUE(vertex_translator_->translated_shader() != NULL); 97 EXPECT_GT(strlen(vertex_translator_->translated_shader()), 0u); 98 } 99 100 TEST_F(ShaderTranslatorTest, ValidFragmentShader) { 101 const char* shader = 102 "void main() {\n" 103 " gl_FragColor = vec4(1.0);\n" 104 "}"; 105 106 // A valid shader should be successfully translated. 107 EXPECT_TRUE(fragment_translator_->Translate(shader)); 108 // Info log must be NULL. 109 EXPECT_TRUE(fragment_translator_->info_log() == NULL); 110 // Translated shader must be valid and non-empty. 111 ASSERT_TRUE(fragment_translator_->translated_shader() != NULL); 112 EXPECT_GT(strlen(fragment_translator_->translated_shader()), 0u); 113 // There should be no attributes or uniforms. 114 EXPECT_TRUE(fragment_translator_->attrib_map().empty()); 115 EXPECT_TRUE(fragment_translator_->uniform_map().empty()); 116 } 117 118 TEST_F(ShaderTranslatorTest, InvalidFragmentShader) { 119 const char* shader = "foo-bar"; 120 121 // An invalid shader should fail. 122 EXPECT_FALSE(fragment_translator_->Translate(shader)); 123 // Info log must be valid and non-empty. 124 ASSERT_TRUE(fragment_translator_->info_log() != NULL); 125 EXPECT_GT(strlen(fragment_translator_->info_log()), 0u); 126 // Translated shader must be NULL. 127 EXPECT_TRUE(fragment_translator_->translated_shader() == NULL); 128 // There should be no attributes or uniforms. 129 EXPECT_TRUE(fragment_translator_->attrib_map().empty()); 130 EXPECT_TRUE(fragment_translator_->uniform_map().empty()); 131 } 132 133 TEST_F(ShaderTranslatorTest, GetAttributes) { 134 const char* shader = 135 "attribute vec4 vPosition;\n" 136 "void main() {\n" 137 " gl_Position = vPosition;\n" 138 "}"; 139 140 EXPECT_TRUE(vertex_translator_->Translate(shader)); 141 // Info log must be NULL. 142 EXPECT_TRUE(vertex_translator_->info_log() == NULL); 143 // Translated shader must be valid and non-empty. 144 ASSERT_TRUE(vertex_translator_->translated_shader() != NULL); 145 EXPECT_GT(strlen(vertex_translator_->translated_shader()), 0u); 146 // There should be no uniforms. 147 EXPECT_TRUE(vertex_translator_->uniform_map().empty()); 148 // There should be one attribute with following characteristics: 149 // name:vPosition type:SH_FLOAT_VEC4 size:1. 150 const ShaderTranslator::VariableMap& attrib_map = 151 vertex_translator_->attrib_map(); 152 EXPECT_EQ(1u, attrib_map.size()); 153 ShaderTranslator::VariableMap::const_iterator iter = 154 attrib_map.find("vPosition"); 155 EXPECT_TRUE(iter != attrib_map.end()); 156 EXPECT_EQ(SH_FLOAT_VEC4, iter->second.type); 157 EXPECT_EQ(1, iter->second.size); 158 EXPECT_EQ("vPosition", iter->second.name); 159 } 160 161 TEST_F(ShaderTranslatorTest, GetUniforms) { 162 const char* shader = 163 "precision mediump float;\n" 164 "struct Foo {\n" 165 " vec4 color[1];\n" 166 "};\n" 167 "struct Bar {\n" 168 " Foo foo;\n" 169 "};\n" 170 "uniform Bar bar[2];\n" 171 "void main() {\n" 172 " gl_FragColor = bar[0].foo.color[0] + bar[1].foo.color[0];\n" 173 "}"; 174 175 EXPECT_TRUE(fragment_translator_->Translate(shader)); 176 // Info log must be NULL. 177 EXPECT_TRUE(fragment_translator_->info_log() == NULL); 178 // Translated shader must be valid and non-empty. 179 ASSERT_TRUE(fragment_translator_->translated_shader() != NULL); 180 EXPECT_GT(strlen(fragment_translator_->translated_shader()), 0u); 181 // There should be no attributes. 182 EXPECT_TRUE(fragment_translator_->attrib_map().empty()); 183 // There should be two uniforms with following characteristics: 184 // 1. name:bar[0].foo.color[0] type:SH_FLOAT_VEC4 size:1 185 // 2. name:bar[1].foo.color[0] type:SH_FLOAT_VEC4 size:1 186 const ShaderTranslator::VariableMap& uniform_map = 187 fragment_translator_->uniform_map(); 188 EXPECT_EQ(2u, uniform_map.size()); 189 // First uniform. 190 ShaderTranslator::VariableMap::const_iterator iter = 191 uniform_map.find("bar[0].foo.color[0]"); 192 EXPECT_TRUE(iter != uniform_map.end()); 193 EXPECT_EQ(SH_FLOAT_VEC4, iter->second.type); 194 EXPECT_EQ(1, iter->second.size); 195 EXPECT_EQ("bar[0].foo.color[0]", iter->second.name); 196 // Second uniform. 197 iter = uniform_map.find("bar[1].foo.color[0]"); 198 EXPECT_TRUE(iter != uniform_map.end()); 199 EXPECT_EQ(SH_FLOAT_VEC4, iter->second.type); 200 EXPECT_EQ(1, iter->second.size); 201 EXPECT_EQ("bar[1].foo.color[0]", iter->second.name); 202 } 203 204 #if defined(OS_MACOSX) 205 TEST_F(ShaderTranslatorTest, BuiltInFunctionEmulation) { 206 // This test might become invalid in the future when ANGLE Translator is no 207 // longer emulate dot(float, float) in Mac, or the emulated function name is 208 // no longer webgl_dot_emu. 209 const char* shader = 210 "void main() {\n" 211 " gl_Position = vec4(dot(1.0, 1.0), 1.0, 1.0, 1.0);\n" 212 "}"; 213 214 EXPECT_TRUE(vertex_translator_->Translate(shader)); 215 // Info log must be NULL. 216 EXPECT_TRUE(vertex_translator_->info_log() == NULL); 217 // Translated shader must be valid and non-empty. 218 ASSERT_TRUE(vertex_translator_->translated_shader() != NULL); 219 EXPECT_TRUE(strstr(vertex_translator_->translated_shader(), 220 "webgl_dot_emu") != NULL); 221 } 222 #endif 223 224 TEST_F(ShaderTranslatorTest, OptionsString) { 225 scoped_refptr<ShaderTranslator> translator_1 = new ShaderTranslator(); 226 scoped_refptr<ShaderTranslator> translator_2 = new ShaderTranslator(); 227 scoped_refptr<ShaderTranslator> translator_3 = new ShaderTranslator(); 228 229 ShBuiltInResources resources; 230 ShInitBuiltInResources(&resources); 231 232 ASSERT_TRUE(translator_1->Init( 233 SH_VERTEX_SHADER, SH_GLES2_SPEC, &resources, 234 ShaderTranslatorInterface::kGlsl, 235 SH_EMULATE_BUILT_IN_FUNCTIONS)); 236 ASSERT_TRUE(translator_2->Init( 237 SH_FRAGMENT_SHADER, SH_GLES2_SPEC, &resources, 238 ShaderTranslatorInterface::kGlsl, 239 static_cast<ShCompileOptions>(0))); 240 resources.EXT_draw_buffers = 1; 241 ASSERT_TRUE(translator_3->Init( 242 SH_VERTEX_SHADER, SH_GLES2_SPEC, &resources, 243 ShaderTranslatorInterface::kGlsl, 244 SH_EMULATE_BUILT_IN_FUNCTIONS)); 245 246 std::string options_1( 247 translator_1->GetStringForOptionsThatWouldEffectCompilation()); 248 std::string options_2( 249 translator_1->GetStringForOptionsThatWouldEffectCompilation()); 250 std::string options_3( 251 translator_2->GetStringForOptionsThatWouldEffectCompilation()); 252 std::string options_4( 253 translator_3->GetStringForOptionsThatWouldEffectCompilation()); 254 255 EXPECT_EQ(options_1, options_2); 256 EXPECT_NE(options_1, options_3); 257 EXPECT_NE(options_1, options_4); 258 EXPECT_NE(options_3, options_4); 259 } 260 261 } // namespace gles2 262 } // namespace gpu 263 264