Home | History | Annotate | Download | only in service
      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