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