Home | History | Annotate | Download | only in tests
      1 /*
      2  * Copyright  2013 Intel Corporation
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a
      5  * copy of this software and associated documentation files (the "Software"),
      6  * to deal in the Software without restriction, including without limitation
      7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8  * and/or sell copies of the Software, and to permit persons to whom the
      9  * Software is furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice (including the next
     12  * paragraph) shall be included in all copies or substantial portions of the
     13  * Software.
     14  *
     15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     21  * DEALINGS IN THE SOFTWARE.
     22  */
     23 #include <gtest/gtest.h>
     24 #include "standalone_scaffolding.h"
     25 #include "main/compiler.h"
     26 #include "main/mtypes.h"
     27 #include "main/macros.h"
     28 #include "ir.h"
     29 #include "glsl_parser_extras.h"
     30 #include "glsl_symbol_table.h"
     31 
     32 class common_builtin : public ::testing::Test {
     33 public:
     34    common_builtin(GLenum shader_type)
     35       : shader_type(shader_type)
     36    {
     37       /* empty */
     38    }
     39 
     40    virtual void SetUp();
     41    virtual void TearDown();
     42 
     43    void string_starts_with_prefix(const char *str, const char *prefix);
     44    void names_start_with_gl();
     45    void uniforms_and_system_values_dont_have_explicit_location();
     46    void constants_are_constant();
     47    void no_invalid_variable_modes();
     48 
     49    GLenum shader_type;
     50    struct _mesa_glsl_parse_state *state;
     51    struct gl_shader *shader;
     52    void *mem_ctx;
     53    gl_context ctx;
     54    exec_list ir;
     55 };
     56 
     57 void
     58 common_builtin::SetUp()
     59 {
     60    this->mem_ctx = ralloc_context(NULL);
     61    this->ir.make_empty();
     62 
     63    initialize_context_to_defaults(&this->ctx, API_OPENGL_COMPAT);
     64 
     65    this->shader = rzalloc(this->mem_ctx, gl_shader);
     66    this->shader->Type = this->shader_type;
     67    this->shader->Stage = _mesa_shader_enum_to_shader_stage(this->shader_type);
     68 
     69    this->state =
     70       new(mem_ctx) _mesa_glsl_parse_state(&this->ctx, this->shader->Stage,
     71                                           this->shader);
     72 
     73    _mesa_glsl_initialize_types(this->state);
     74    _mesa_glsl_initialize_variables(&this->ir, this->state);
     75 }
     76 
     77 void
     78 common_builtin::TearDown()
     79 {
     80    ralloc_free(this->mem_ctx);
     81    this->mem_ctx = NULL;
     82 }
     83 
     84 void
     85 common_builtin::string_starts_with_prefix(const char *str, const char *prefix)
     86 {
     87    const size_t len = strlen(prefix);
     88    char *const name_prefix = new char[len + 1];
     89 
     90    strncpy(name_prefix, str, len);
     91    name_prefix[len] = '\0';
     92    EXPECT_STREQ(prefix, name_prefix) << "Bad name " << str;
     93 
     94    delete [] name_prefix;
     95 }
     96 
     97 void
     98 common_builtin::names_start_with_gl()
     99 {
    100    foreach_in_list(ir_instruction, node, &this->ir) {
    101       ir_variable *const var = node->as_variable();
    102 
    103       string_starts_with_prefix(var->name, "gl_");
    104    }
    105 }
    106 
    107 void
    108 common_builtin::uniforms_and_system_values_dont_have_explicit_location()
    109 {
    110    foreach_in_list(ir_instruction, node, &this->ir) {
    111       ir_variable *const var = node->as_variable();
    112 
    113       if (var->data.mode != ir_var_uniform && var->data.mode != ir_var_system_value)
    114          continue;
    115 
    116       EXPECT_FALSE(var->data.explicit_location);
    117       EXPECT_EQ(-1, var->data.location);
    118    }
    119 }
    120 
    121 void
    122 common_builtin::constants_are_constant()
    123 {
    124    foreach_in_list(ir_instruction, node, &this->ir) {
    125       ir_variable *const var = node->as_variable();
    126 
    127       if (var->data.mode != ir_var_auto)
    128          continue;
    129 
    130       EXPECT_FALSE(var->data.explicit_location);
    131       EXPECT_EQ(-1, var->data.location);
    132       EXPECT_TRUE(var->data.read_only);
    133    }
    134 }
    135 
    136 void
    137 common_builtin::no_invalid_variable_modes()
    138 {
    139    foreach_in_list(ir_instruction, node, &this->ir) {
    140       ir_variable *const var = node->as_variable();
    141 
    142       switch (var->data.mode) {
    143       case ir_var_auto:
    144       case ir_var_uniform:
    145       case ir_var_shader_in:
    146       case ir_var_shader_out:
    147       case ir_var_system_value:
    148          break;
    149 
    150       default:
    151          ADD_FAILURE() << "Built-in variable " << var->name
    152                        << " has an invalid mode " << int(var->data.mode);
    153          break;
    154       }
    155    }
    156 }
    157 
    158 /************************************************************/
    159 
    160 class vertex_builtin : public common_builtin {
    161 public:
    162    vertex_builtin()
    163       : common_builtin(GL_VERTEX_SHADER)
    164    {
    165       /* empty */
    166    }
    167 };
    168 
    169 TEST_F(vertex_builtin, names_start_with_gl)
    170 {
    171    common_builtin::names_start_with_gl();
    172 }
    173 
    174 TEST_F(vertex_builtin, inputs_have_explicit_location)
    175 {
    176    foreach_in_list(ir_instruction, node, &this->ir) {
    177       ir_variable *const var = node->as_variable();
    178 
    179       if (var->data.mode != ir_var_shader_in)
    180          continue;
    181 
    182       EXPECT_TRUE(var->data.explicit_location);
    183       EXPECT_NE(-1, var->data.location);
    184       EXPECT_GT(VERT_ATTRIB_GENERIC0, var->data.location);
    185       EXPECT_EQ(0u, var->data.location_frac);
    186    }
    187 }
    188 
    189 TEST_F(vertex_builtin, outputs_have_explicit_location)
    190 {
    191    foreach_in_list(ir_instruction, node, &this->ir) {
    192       ir_variable *const var = node->as_variable();
    193 
    194       if (var->data.mode != ir_var_shader_out)
    195          continue;
    196 
    197       EXPECT_TRUE(var->data.explicit_location);
    198       EXPECT_NE(-1, var->data.location);
    199       EXPECT_GT(VARYING_SLOT_VAR0, var->data.location);
    200       EXPECT_EQ(0u, var->data.location_frac);
    201 
    202       /* Several varyings only exist in the fragment shader.  Be sure that no
    203        * outputs with these locations exist.
    204        */
    205       EXPECT_NE(VARYING_SLOT_PNTC, var->data.location);
    206       EXPECT_NE(VARYING_SLOT_FACE, var->data.location);
    207       EXPECT_NE(VARYING_SLOT_PRIMITIVE_ID, var->data.location);
    208    }
    209 }
    210 
    211 TEST_F(vertex_builtin, uniforms_and_system_values_dont_have_explicit_location)
    212 {
    213    common_builtin::uniforms_and_system_values_dont_have_explicit_location();
    214 }
    215 
    216 TEST_F(vertex_builtin, constants_are_constant)
    217 {
    218    common_builtin::constants_are_constant();
    219 }
    220 
    221 TEST_F(vertex_builtin, no_invalid_variable_modes)
    222 {
    223    common_builtin::no_invalid_variable_modes();
    224 }
    225 
    226 /********************************************************************/
    227 
    228 class fragment_builtin : public common_builtin {
    229 public:
    230    fragment_builtin()
    231       : common_builtin(GL_FRAGMENT_SHADER)
    232    {
    233       /* empty */
    234    }
    235 };
    236 
    237 TEST_F(fragment_builtin, names_start_with_gl)
    238 {
    239    common_builtin::names_start_with_gl();
    240 }
    241 
    242 TEST_F(fragment_builtin, inputs_have_explicit_location)
    243 {
    244    foreach_in_list(ir_instruction, node, &this->ir) {
    245       ir_variable *const var = node->as_variable();
    246 
    247       if (var->data.mode != ir_var_shader_in)
    248 	 continue;
    249 
    250       EXPECT_TRUE(var->data.explicit_location);
    251       EXPECT_NE(-1, var->data.location);
    252       EXPECT_GT(VARYING_SLOT_VAR0, var->data.location);
    253       EXPECT_EQ(0u, var->data.location_frac);
    254 
    255       /* Several varyings only exist in the vertex / geometry shader.  Be sure
    256        * that no inputs with these locations exist.
    257        */
    258       EXPECT_TRUE(_mesa_varying_slot_in_fs((gl_varying_slot) var->data.location));
    259    }
    260 }
    261 
    262 TEST_F(fragment_builtin, outputs_have_explicit_location)
    263 {
    264    foreach_in_list(ir_instruction, node, &this->ir) {
    265       ir_variable *const var = node->as_variable();
    266 
    267       if (var->data.mode != ir_var_shader_out)
    268 	 continue;
    269 
    270       EXPECT_TRUE(var->data.explicit_location);
    271       EXPECT_NE(-1, var->data.location);
    272 
    273       /* gl_FragData[] has location FRAG_RESULT_DATA0.  Locations beyond that
    274        * are invalid.
    275        */
    276       EXPECT_GE(FRAG_RESULT_DATA0, var->data.location);
    277 
    278       EXPECT_EQ(0u, var->data.location_frac);
    279    }
    280 }
    281 
    282 TEST_F(fragment_builtin, uniforms_and_system_values_dont_have_explicit_location)
    283 {
    284    common_builtin::uniforms_and_system_values_dont_have_explicit_location();
    285 }
    286 
    287 TEST_F(fragment_builtin, constants_are_constant)
    288 {
    289    common_builtin::constants_are_constant();
    290 }
    291 
    292 TEST_F(fragment_builtin, no_invalid_variable_modes)
    293 {
    294    common_builtin::no_invalid_variable_modes();
    295 }
    296 
    297 /********************************************************************/
    298 
    299 class geometry_builtin : public common_builtin {
    300 public:
    301    geometry_builtin()
    302       : common_builtin(GL_GEOMETRY_SHADER)
    303    {
    304       /* empty */
    305    }
    306 };
    307 
    308 TEST_F(geometry_builtin, names_start_with_gl)
    309 {
    310    common_builtin::names_start_with_gl();
    311 }
    312 
    313 TEST_F(geometry_builtin, inputs_have_explicit_location)
    314 {
    315    foreach_in_list(ir_instruction, node, &this->ir) {
    316       ir_variable *const var = node->as_variable();
    317 
    318       if (var->data.mode != ir_var_shader_in)
    319 	 continue;
    320 
    321       if (var->is_interface_instance()) {
    322          EXPECT_STREQ("gl_in", var->name);
    323          EXPECT_FALSE(var->data.explicit_location);
    324          EXPECT_EQ(-1, var->data.location);
    325 
    326          ASSERT_TRUE(var->type->is_array());
    327 
    328          const glsl_type *const instance_type = var->type->fields.array;
    329 
    330          for (unsigned i = 0; i < instance_type->length; i++) {
    331             const glsl_struct_field *const input =
    332                &instance_type->fields.structure[i];
    333 
    334             string_starts_with_prefix(input->name, "gl_");
    335             EXPECT_NE(-1, input->location);
    336             EXPECT_GT(VARYING_SLOT_VAR0, input->location);
    337 
    338             /* Several varyings only exist in the fragment shader.  Be sure
    339              * that no inputs with these locations exist.
    340              */
    341             EXPECT_NE(VARYING_SLOT_PNTC, input->location);
    342             EXPECT_NE(VARYING_SLOT_FACE, input->location);
    343          }
    344       } else {
    345          EXPECT_TRUE(var->data.explicit_location);
    346          EXPECT_NE(-1, var->data.location);
    347          EXPECT_GT(VARYING_SLOT_VAR0, var->data.location);
    348          EXPECT_EQ(0u, var->data.location_frac);
    349       }
    350 
    351       /* Several varyings only exist in the fragment shader.  Be sure that no
    352        * inputs with these locations exist.
    353        */
    354       EXPECT_NE(VARYING_SLOT_PNTC, var->data.location);
    355       EXPECT_NE(VARYING_SLOT_FACE, var->data.location);
    356    }
    357 }
    358 
    359 TEST_F(geometry_builtin, outputs_have_explicit_location)
    360 {
    361    foreach_in_list(ir_instruction, node, &this->ir) {
    362       ir_variable *const var = node->as_variable();
    363 
    364       if (var->data.mode != ir_var_shader_out)
    365 	 continue;
    366 
    367       EXPECT_TRUE(var->data.explicit_location);
    368       EXPECT_NE(-1, var->data.location);
    369       EXPECT_GT(VARYING_SLOT_VAR0, var->data.location);
    370       EXPECT_EQ(0u, var->data.location_frac);
    371 
    372       /* Several varyings only exist in the fragment shader.  Be sure that no
    373        * outputs with these locations exist.
    374        */
    375       EXPECT_NE(VARYING_SLOT_PNTC, var->data.location);
    376       EXPECT_NE(VARYING_SLOT_FACE, var->data.location);
    377    }
    378 }
    379 
    380 TEST_F(geometry_builtin, uniforms_and_system_values_dont_have_explicit_location)
    381 {
    382    common_builtin::uniforms_and_system_values_dont_have_explicit_location();
    383 }
    384 
    385 TEST_F(geometry_builtin, constants_are_constant)
    386 {
    387    common_builtin::constants_are_constant();
    388 }
    389 
    390 TEST_F(geometry_builtin, no_invalid_variable_modes)
    391 {
    392    common_builtin::no_invalid_variable_modes();
    393 }
    394