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