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.
7 #include "gpu/command_buffer/service/shader_translator.h"
8 #include "testing/gtest/include/gtest/gtest.h"
9 #include "ui/gl/gl_version_info.h"
14 class ShaderTranslatorTest
: public testing::Test
{
16 ShaderTranslatorTest() {
17 shader_output_language_
=
18 ShaderTranslator::GetShaderOutputLanguageForContext(
19 gfx::GLVersionInfo("2.0", "", ""));
22 ~ShaderTranslatorTest() override
{}
25 void SetUp() override
{
26 ShBuiltInResources resources
;
27 ShInitBuiltInResources(&resources
);
28 resources
.MaxExpressionComplexity
= 32;
29 resources
.MaxCallStackDepth
= 32;
31 vertex_translator_
= new ShaderTranslator();
32 fragment_translator_
= new ShaderTranslator();
34 ASSERT_TRUE(vertex_translator_
->Init(GL_VERTEX_SHADER
, SH_GLES2_SPEC
,
35 &resources
, shader_output_language_
,
36 SH_EMULATE_BUILT_IN_FUNCTIONS
));
37 ASSERT_TRUE(fragment_translator_
->Init(GL_FRAGMENT_SHADER
, SH_GLES2_SPEC
,
38 &resources
, shader_output_language_
,
39 static_cast<ShCompileOptions
>(0)));
41 void TearDown() override
{
42 vertex_translator_
= NULL
;
43 fragment_translator_
= NULL
;
46 scoped_refptr
<ShaderTranslator
> vertex_translator_
;
47 scoped_refptr
<ShaderTranslator
> fragment_translator_
;
48 ShShaderOutput shader_output_language_
;
51 TEST_F(ShaderTranslatorTest
, ValidVertexShader
) {
54 " gl_Position = vec4(1.0);\n"
57 // A valid shader should be successfully translated.
58 std::string info_log
, translated_source
;
60 AttributeMap attrib_map
;
61 UniformMap uniform_map
;
62 VaryingMap varying_map
;
64 EXPECT_TRUE(vertex_translator_
->Translate(shader
,
72 // Info log must be NULL.
73 EXPECT_TRUE(info_log
.empty());
74 // Translated shader must be valid and non-empty.
75 ASSERT_FALSE(translated_source
.empty());
76 // There should be no attributes, uniforms, and only one built-in
77 // varying: gl_Position.
78 EXPECT_TRUE(attrib_map
.empty());
79 EXPECT_TRUE(uniform_map
.empty());
80 EXPECT_EQ(1u, varying_map
.size());
81 // There should be no name mapping.
82 EXPECT_TRUE(name_map
.empty());
85 TEST_F(ShaderTranslatorTest
, InvalidVertexShader
) {
86 const char* bad_shader
= "foo-bar";
87 const char* good_shader
=
89 " gl_Position = vec4(1.0);\n"
92 // An invalid shader should fail.
93 std::string info_log
, translated_source
;
95 AttributeMap attrib_map
;
96 UniformMap uniform_map
;
97 VaryingMap varying_map
;
99 EXPECT_FALSE(vertex_translator_
->Translate(bad_shader
,
107 // Info log must be valid and non-empty.
108 ASSERT_FALSE(info_log
.empty());
109 // Translated shader must be NULL.
110 EXPECT_TRUE(translated_source
.empty());
111 // There should be no attributes, uniforms, varyings, or name mapping.
112 EXPECT_TRUE(attrib_map
.empty());
113 EXPECT_TRUE(uniform_map
.empty());
114 EXPECT_TRUE(varying_map
.empty());
115 EXPECT_TRUE(name_map
.empty());
117 // Try a good shader after bad.
119 EXPECT_TRUE(vertex_translator_
->Translate(good_shader
,
127 EXPECT_TRUE(info_log
.empty());
128 EXPECT_FALSE(translated_source
.empty());
131 TEST_F(ShaderTranslatorTest
, ValidFragmentShader
) {
134 " gl_FragColor = vec4(1.0);\n"
137 // A valid shader should be successfully translated.
138 std::string info_log
, translated_source
;
140 AttributeMap attrib_map
;
141 UniformMap uniform_map
;
142 VaryingMap varying_map
;
144 EXPECT_TRUE(fragment_translator_
->Translate(shader
,
152 // Info log must be NULL.
153 EXPECT_TRUE(info_log
.empty());
154 // Translated shader must be valid and non-empty.
155 ASSERT_FALSE(translated_source
.empty());
156 // There should be no attributes, uniforms, varyings, or name mapping.
157 EXPECT_TRUE(attrib_map
.empty());
158 EXPECT_TRUE(uniform_map
.empty());
159 EXPECT_TRUE(varying_map
.empty());
160 EXPECT_TRUE(name_map
.empty());
163 TEST_F(ShaderTranslatorTest
, InvalidFragmentShader
) {
164 const char* shader
= "foo-bar";
166 std::string info_log
, translated_source
;
168 AttributeMap attrib_map
;
169 UniformMap uniform_map
;
170 VaryingMap varying_map
;
172 // An invalid shader should fail.
173 EXPECT_FALSE(fragment_translator_
->Translate(shader
,
181 // Info log must be valid and non-empty.
182 EXPECT_FALSE(info_log
.empty());
183 // Translated shader must be NULL.
184 EXPECT_TRUE(translated_source
.empty());
185 // There should be no attributes or uniforms.
186 EXPECT_TRUE(attrib_map
.empty());
187 EXPECT_TRUE(uniform_map
.empty());
188 EXPECT_TRUE(varying_map
.empty());
189 EXPECT_TRUE(name_map
.empty());
192 TEST_F(ShaderTranslatorTest
, GetAttributes
) {
194 "attribute vec4 vPosition;\n"
196 " gl_Position = vPosition;\n"
199 std::string info_log
, translated_source
;
201 AttributeMap attrib_map
;
202 UniformMap uniform_map
;
203 VaryingMap varying_map
;
205 EXPECT_TRUE(vertex_translator_
->Translate(shader
,
213 // Info log must be NULL.
214 EXPECT_TRUE(info_log
.empty());
215 // Translated shader must be valid and non-empty.
216 EXPECT_FALSE(translated_source
.empty());
217 // There should be no uniforms.
218 EXPECT_TRUE(uniform_map
.empty());
219 // There should be one attribute with following characteristics:
220 // name:vPosition type:GL_FLOAT_VEC4 size:0.
221 EXPECT_EQ(1u, attrib_map
.size());
222 AttributeMap::const_iterator iter
= attrib_map
.find("vPosition");
223 EXPECT_TRUE(iter
!= attrib_map
.end());
224 EXPECT_EQ(static_cast<GLenum
>(GL_FLOAT_VEC4
), iter
->second
.type
);
225 EXPECT_EQ(0u, iter
->second
.arraySize
);
226 EXPECT_EQ("vPosition", iter
->second
.name
);
229 TEST_F(ShaderTranslatorTest
, GetUniforms
) {
231 "precision mediump float;\n"
238 "uniform Bar bar[2];\n"
240 " gl_FragColor = bar[0].foo.color[0] + bar[1].foo.color[0];\n"
243 std::string info_log
, translated_source
;
245 AttributeMap attrib_map
;
246 UniformMap uniform_map
;
247 VaryingMap varying_map
;
249 EXPECT_TRUE(fragment_translator_
->Translate(shader
,
257 // Info log must be NULL.
258 EXPECT_TRUE(info_log
.empty());
259 // Translated shader must be valid and non-empty.
260 EXPECT_FALSE(translated_source
.empty());
261 // There should be no attributes.
262 EXPECT_TRUE(attrib_map
.empty());
263 // There should be two uniforms with following characteristics:
264 // 1. name:bar[0].foo.color[0] type:GL_FLOAT_VEC4 size:1
265 // 2. name:bar[1].foo.color[0] type:GL_FLOAT_VEC4 size:1
266 // However, there will be only one entry "bar" in the map.
267 EXPECT_EQ(1u, uniform_map
.size());
268 UniformMap::const_iterator iter
= uniform_map
.find("bar");
269 EXPECT_TRUE(iter
!= uniform_map
.end());
271 const sh::ShaderVariable
* info
;
272 std::string original_name
;
273 EXPECT_TRUE(iter
->second
.findInfoByMappedName(
274 "bar[0].foo.color[0]", &info
, &original_name
));
275 EXPECT_EQ(static_cast<GLenum
>(GL_FLOAT_VEC4
), info
->type
);
276 EXPECT_EQ(1u, info
->arraySize
);
277 EXPECT_STREQ("color", info
->name
.c_str());
278 EXPECT_STREQ("bar[0].foo.color[0]", original_name
.c_str());
280 EXPECT_TRUE(iter
->second
.findInfoByMappedName(
281 "bar[1].foo.color[0]", &info
, &original_name
));
282 EXPECT_EQ(static_cast<GLenum
>(GL_FLOAT_VEC4
), info
->type
);
283 EXPECT_EQ(1u, info
->arraySize
);
284 EXPECT_STREQ("color", info
->name
.c_str());
285 EXPECT_STREQ("bar[1].foo.color[0]", original_name
.c_str());
288 TEST_F(ShaderTranslatorTest
, OptionsString
) {
289 scoped_refptr
<ShaderTranslator
> translator_1
= new ShaderTranslator();
290 scoped_refptr
<ShaderTranslator
> translator_2
= new ShaderTranslator();
291 scoped_refptr
<ShaderTranslator
> translator_3
= new ShaderTranslator();
293 ShBuiltInResources resources
;
294 ShInitBuiltInResources(&resources
);
296 ASSERT_TRUE(translator_1
->Init(GL_VERTEX_SHADER
, SH_GLES2_SPEC
, &resources
,
297 SH_GLSL_150_CORE_OUTPUT
,
298 SH_EMULATE_BUILT_IN_FUNCTIONS
));
299 ASSERT_TRUE(translator_2
->Init(GL_FRAGMENT_SHADER
, SH_GLES2_SPEC
, &resources
,
300 SH_GLSL_150_CORE_OUTPUT
,
301 static_cast<ShCompileOptions
>(0)));
302 resources
.EXT_draw_buffers
= 1;
303 ASSERT_TRUE(translator_3
->Init(GL_VERTEX_SHADER
, SH_GLES2_SPEC
, &resources
,
304 SH_GLSL_150_CORE_OUTPUT
,
305 SH_EMULATE_BUILT_IN_FUNCTIONS
));
307 std::string
options_1(
308 translator_1
->GetStringForOptionsThatWouldAffectCompilation());
309 std::string
options_2(
310 translator_1
->GetStringForOptionsThatWouldAffectCompilation());
311 std::string
options_3(
312 translator_2
->GetStringForOptionsThatWouldAffectCompilation());
313 std::string
options_4(
314 translator_3
->GetStringForOptionsThatWouldAffectCompilation());
316 EXPECT_EQ(options_1
, options_2
);
317 EXPECT_NE(options_1
, options_3
);
318 EXPECT_NE(options_1
, options_4
);
319 EXPECT_NE(options_3
, options_4
);
322 class ShaderTranslatorOutputVersionTest
323 : public testing::TestWithParam
<testing::tuple
<const char*, const char*>> {
326 TEST_P(ShaderTranslatorOutputVersionTest
, HasCorrectOutputGLSLVersion
) {
327 // Test that translating to a shader targeting certain OpenGL context version
328 // (version string in test param tuple index 0) produces a GLSL shader that
329 // contains correct version string for that context (version directive
330 // in test param tuple index 1).
332 const char* kShader
=
333 "attribute vec4 vPosition;\n"
335 " gl_Position = vPosition;\n"
338 gfx::GLVersionInfo
output_context_version(testing::get
<0>(GetParam()), "",
341 scoped_refptr
<ShaderTranslator
> translator
= new ShaderTranslator();
342 ShBuiltInResources resources
;
343 ShInitBuiltInResources(&resources
);
344 ShCompileOptions compile_options
= SH_OBJECT_CODE
;
345 ShShaderOutput shader_output_language
=
346 ShaderTranslator::GetShaderOutputLanguageForContext(
347 output_context_version
);
348 ASSERT_TRUE(translator
->Init(GL_VERTEX_SHADER
, SH_GLES2_SPEC
, &resources
,
349 shader_output_language
, compile_options
));
351 std::string translated_source
;
353 EXPECT_TRUE(translator
->Translate(kShader
, nullptr, &translated_source
,
354 &shader_version
, nullptr, nullptr, nullptr,
357 std::string expected_version_directive
= testing::get
<1>(GetParam());
358 if (expected_version_directive
.empty()) {
359 EXPECT_TRUE(translated_source
.find("#version") == std::string::npos
)
360 << "Translation was:\n" << translated_source
;
362 EXPECT_TRUE(translated_source
.find(expected_version_directive
) !=
364 << "Translation was:\n" << translated_source
;
368 // For some compilers, using make_tuple("a", "bb") would end up
369 // instantiating make_tuple<char[1], char[2]>. This does not work.
371 testing::tuple
<const char*, const char*> make_gl_glsl_tuple(
372 const char* gl_version
,
373 const char* glsl_version_directive
) {
374 return testing::make_tuple(gl_version
, glsl_version_directive
);
378 // Test data for the above test. OpenGL specifications specify a
379 // certain version of GLSL to be guaranteed to be supported. Test
380 // that ShaderTranslator produces a GLSL shader with the exact
381 // specified GLSL version for each known OpenGL version.
382 INSTANTIATE_TEST_CASE_P(
384 ShaderTranslatorOutputVersionTest
,
385 testing::Values(make_gl_glsl_tuple("4.5", "#version 450\n"),
386 make_gl_glsl_tuple("4.4", "#version 440\n"),
387 make_gl_glsl_tuple("4.3", "#version 430\n"),
388 make_gl_glsl_tuple("4.2", "#version 420\n"),
389 make_gl_glsl_tuple("4.1", "#version 410\n"),
390 make_gl_glsl_tuple("4.0", "#version 400\n"),
391 make_gl_glsl_tuple("3.3", "#version 330\n"),
392 make_gl_glsl_tuple("3.2", "#version 150\n"),
393 make_gl_glsl_tuple("3.1", "#version 140\n"),
394 make_gl_glsl_tuple("3.0", "#version 130\n")));
396 // Test data for the above test. Check that early OpenGL contexts get
397 // GLSL compatibility profile shader, e.g. shader has no #version
398 // directive. Also check that future version 3.3+ OpenGL contexts get
399 // similar shader. We do not expect that future 3.3+ specs contain
400 // the "all eariler GLSL versions" clause, since 3.3 did not contain
402 INSTANTIATE_TEST_CASE_P(OldOrUnknownOpenGLContexts
,
403 ShaderTranslatorOutputVersionTest
,
404 testing::Values(make_gl_glsl_tuple("3.4", ""),
405 make_gl_glsl_tuple("2.0", "")));
407 // Test data for the above test. Cases for the future OpenGL versions. The
408 // code assumes that the future OpenGL specs specify the clause that all
409 // earlier GLSL versions are supported. We select the highest GLSL
410 // version known at the time of writing.
411 INSTANTIATE_TEST_CASE_P(
412 BackwardsCompatibleFutureOpenGLContexts
,
413 ShaderTranslatorOutputVersionTest
,
414 testing::Values(make_gl_glsl_tuple("5.0", "#version 450\n"),
415 make_gl_glsl_tuple("4.6", "#version 450\n")));
417 // Test data for the above test. Check that for the OpenGL ES output
418 // contexts, the shader is such that GLSL 1.0 is used. The translator
419 // selects GLSL 1.0 by not output any version at the moment, though we
420 // do not know if that would be correct for the future OpenGL ES specs.
421 INSTANTIATE_TEST_CASE_P(OpenGLESContexts
,
422 ShaderTranslatorOutputVersionTest
,
423 testing::Values(make_gl_glsl_tuple("opengl es 2.0", ""),
424 make_gl_glsl_tuple("opengl es 3.0", ""),
425 make_gl_glsl_tuple("opengl es 3.1", ""),
426 make_gl_glsl_tuple("opengl es 3.2",