• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "util/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:
common_builtin(GLenum shader_type)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
SetUp()58 common_builtin::SetUp()
59 {
60    glsl_type_singleton_init_or_ref();
61 
62    this->mem_ctx = ralloc_context(NULL);
63    this->ir.make_empty();
64 
65    initialize_context_to_defaults(&this->ctx, API_OPENGL_COMPAT);
66 
67    this->shader = rzalloc(this->mem_ctx, gl_shader);
68    this->shader->Type = this->shader_type;
69    this->shader->Stage = _mesa_shader_enum_to_shader_stage(this->shader_type);
70 
71    this->state =
72       new(mem_ctx) _mesa_glsl_parse_state(&this->ctx, this->shader->Stage,
73                                           this->shader);
74 
75    _mesa_glsl_initialize_types(this->state);
76    _mesa_glsl_initialize_variables(&this->ir, this->state);
77 }
78 
79 void
TearDown()80 common_builtin::TearDown()
81 {
82    ralloc_free(this->mem_ctx);
83    this->mem_ctx = NULL;
84 
85    glsl_type_singleton_decref();
86 }
87 
88 void
string_starts_with_prefix(const char * str,const char * prefix)89 common_builtin::string_starts_with_prefix(const char *str, const char *prefix)
90 {
91    const size_t len = strlen(prefix);
92    char *const name_prefix = new char[len + 1];
93 
94    strncpy(name_prefix, str, len);
95    name_prefix[len] = '\0';
96    EXPECT_STREQ(prefix, name_prefix) << "Bad name " << str;
97 
98    delete [] name_prefix;
99 }
100 
101 void
names_start_with_gl()102 common_builtin::names_start_with_gl()
103 {
104    foreach_in_list(ir_instruction, node, &this->ir) {
105       ir_variable *const var = node->as_variable();
106 
107       string_starts_with_prefix(var->name, "gl_");
108    }
109 }
110 
111 void
uniforms_and_system_values_dont_have_explicit_location()112 common_builtin::uniforms_and_system_values_dont_have_explicit_location()
113 {
114    foreach_in_list(ir_instruction, node, &this->ir) {
115       ir_variable *const var = node->as_variable();
116 
117       if (var->data.mode != ir_var_uniform && var->data.mode != ir_var_system_value)
118          continue;
119 
120       EXPECT_FALSE(var->data.explicit_location);
121       EXPECT_EQ(-1, var->data.location);
122    }
123 }
124 
125 void
constants_are_constant()126 common_builtin::constants_are_constant()
127 {
128    foreach_in_list(ir_instruction, node, &this->ir) {
129       ir_variable *const var = node->as_variable();
130 
131       if (var->data.mode != ir_var_auto)
132          continue;
133 
134       EXPECT_FALSE(var->data.explicit_location);
135       EXPECT_EQ(-1, var->data.location);
136       EXPECT_TRUE(var->data.read_only);
137    }
138 }
139 
140 void
no_invalid_variable_modes()141 common_builtin::no_invalid_variable_modes()
142 {
143    foreach_in_list(ir_instruction, node, &this->ir) {
144       ir_variable *const var = node->as_variable();
145 
146       switch (var->data.mode) {
147       case ir_var_auto:
148       case ir_var_uniform:
149       case ir_var_shader_in:
150       case ir_var_shader_out:
151       case ir_var_system_value:
152          break;
153 
154       default:
155          ADD_FAILURE() << "Built-in variable " << var->name
156                        << " has an invalid mode " << int(var->data.mode);
157          break;
158       }
159    }
160 }
161 
162 /************************************************************/
163 
164 class vertex_builtin : public common_builtin {
165 public:
vertex_builtin()166    vertex_builtin()
167       : common_builtin(GL_VERTEX_SHADER)
168    {
169       /* empty */
170    }
171 };
172 
TEST_F(vertex_builtin,names_start_with_gl)173 TEST_F(vertex_builtin, names_start_with_gl)
174 {
175    common_builtin::names_start_with_gl();
176 }
177 
TEST_F(vertex_builtin,inputs_have_explicit_location)178 TEST_F(vertex_builtin, inputs_have_explicit_location)
179 {
180    foreach_in_list(ir_instruction, node, &this->ir) {
181       ir_variable *const var = node->as_variable();
182 
183       if (var->data.mode != ir_var_shader_in)
184          continue;
185 
186       EXPECT_TRUE(var->data.explicit_location);
187       EXPECT_NE(-1, var->data.location);
188       EXPECT_GT(VERT_ATTRIB_GENERIC0, var->data.location);
189       EXPECT_EQ(0u, var->data.location_frac);
190    }
191 }
192 
TEST_F(vertex_builtin,outputs_have_explicit_location)193 TEST_F(vertex_builtin, outputs_have_explicit_location)
194 {
195    foreach_in_list(ir_instruction, node, &this->ir) {
196       ir_variable *const var = node->as_variable();
197 
198       if (var->data.mode != ir_var_shader_out)
199          continue;
200 
201       EXPECT_TRUE(var->data.explicit_location);
202       EXPECT_NE(-1, var->data.location);
203       EXPECT_GT(VARYING_SLOT_VAR0, var->data.location);
204       EXPECT_EQ(0u, var->data.location_frac);
205 
206       /* Several varyings only exist in the fragment shader.  Be sure that no
207        * outputs with these locations exist.
208        */
209       EXPECT_NE(VARYING_SLOT_PNTC, var->data.location);
210       EXPECT_NE(VARYING_SLOT_FACE, var->data.location);
211       EXPECT_NE(VARYING_SLOT_PRIMITIVE_ID, var->data.location);
212    }
213 }
214 
TEST_F(vertex_builtin,uniforms_and_system_values_dont_have_explicit_location)215 TEST_F(vertex_builtin, uniforms_and_system_values_dont_have_explicit_location)
216 {
217    common_builtin::uniforms_and_system_values_dont_have_explicit_location();
218 }
219 
TEST_F(vertex_builtin,constants_are_constant)220 TEST_F(vertex_builtin, constants_are_constant)
221 {
222    common_builtin::constants_are_constant();
223 }
224 
TEST_F(vertex_builtin,no_invalid_variable_modes)225 TEST_F(vertex_builtin, no_invalid_variable_modes)
226 {
227    common_builtin::no_invalid_variable_modes();
228 }
229 
230 /********************************************************************/
231 
232 class fragment_builtin : public common_builtin {
233 public:
fragment_builtin()234    fragment_builtin()
235       : common_builtin(GL_FRAGMENT_SHADER)
236    {
237       /* empty */
238    }
239 };
240 
TEST_F(fragment_builtin,names_start_with_gl)241 TEST_F(fragment_builtin, names_start_with_gl)
242 {
243    common_builtin::names_start_with_gl();
244 }
245 
TEST_F(fragment_builtin,inputs_have_explicit_location)246 TEST_F(fragment_builtin, inputs_have_explicit_location)
247 {
248    foreach_in_list(ir_instruction, node, &this->ir) {
249       ir_variable *const var = node->as_variable();
250 
251       if (var->data.mode != ir_var_shader_in)
252 	 continue;
253 
254       EXPECT_TRUE(var->data.explicit_location);
255       EXPECT_NE(-1, var->data.location);
256       EXPECT_GT(VARYING_SLOT_VAR0, var->data.location);
257       EXPECT_EQ(0u, var->data.location_frac);
258 
259       /* Several varyings only exist in the vertex / geometry shader.  Be sure
260        * that no inputs with these locations exist.
261        */
262       EXPECT_TRUE(_mesa_varying_slot_in_fs((gl_varying_slot) var->data.location));
263    }
264 }
265 
TEST_F(fragment_builtin,outputs_have_explicit_location)266 TEST_F(fragment_builtin, outputs_have_explicit_location)
267 {
268    foreach_in_list(ir_instruction, node, &this->ir) {
269       ir_variable *const var = node->as_variable();
270 
271       if (var->data.mode != ir_var_shader_out)
272 	 continue;
273 
274       EXPECT_TRUE(var->data.explicit_location);
275       EXPECT_NE(-1, var->data.location);
276 
277       /* gl_FragData[] has location FRAG_RESULT_DATA0.  Locations beyond that
278        * are invalid.
279        */
280       EXPECT_GE(FRAG_RESULT_DATA0, var->data.location);
281 
282       EXPECT_EQ(0u, var->data.location_frac);
283    }
284 }
285 
TEST_F(fragment_builtin,uniforms_and_system_values_dont_have_explicit_location)286 TEST_F(fragment_builtin, uniforms_and_system_values_dont_have_explicit_location)
287 {
288    common_builtin::uniforms_and_system_values_dont_have_explicit_location();
289 }
290 
TEST_F(fragment_builtin,constants_are_constant)291 TEST_F(fragment_builtin, constants_are_constant)
292 {
293    common_builtin::constants_are_constant();
294 }
295 
TEST_F(fragment_builtin,no_invalid_variable_modes)296 TEST_F(fragment_builtin, no_invalid_variable_modes)
297 {
298    common_builtin::no_invalid_variable_modes();
299 }
300 
301 /********************************************************************/
302 
303 class geometry_builtin : public common_builtin {
304 public:
geometry_builtin()305    geometry_builtin()
306       : common_builtin(GL_GEOMETRY_SHADER)
307    {
308       /* empty */
309    }
310 };
311 
TEST_F(geometry_builtin,names_start_with_gl)312 TEST_F(geometry_builtin, names_start_with_gl)
313 {
314    common_builtin::names_start_with_gl();
315 }
316 
TEST_F(geometry_builtin,inputs_have_explicit_location)317 TEST_F(geometry_builtin, inputs_have_explicit_location)
318 {
319    foreach_in_list(ir_instruction, node, &this->ir) {
320       ir_variable *const var = node->as_variable();
321 
322       if (var->data.mode != ir_var_shader_in)
323 	 continue;
324 
325       if (var->is_interface_instance()) {
326          EXPECT_STREQ("gl_in", var->name);
327          EXPECT_FALSE(var->data.explicit_location);
328          EXPECT_EQ(-1, var->data.location);
329 
330          ASSERT_TRUE(var->type->is_array());
331 
332          const glsl_type *const instance_type = var->type->fields.array;
333 
334          for (unsigned i = 0; i < instance_type->length; i++) {
335             const glsl_struct_field *const input =
336                &instance_type->fields.structure[i];
337 
338             string_starts_with_prefix(input->name, "gl_");
339             EXPECT_NE(-1, input->location);
340             EXPECT_GT(VARYING_SLOT_VAR0, input->location);
341 
342             /* Several varyings only exist in the fragment shader.  Be sure
343              * that no inputs with these locations exist.
344              */
345             EXPECT_NE(VARYING_SLOT_PNTC, input->location);
346             EXPECT_NE(VARYING_SLOT_FACE, input->location);
347          }
348       } else {
349          EXPECT_TRUE(var->data.explicit_location);
350          EXPECT_NE(-1, var->data.location);
351          EXPECT_GT(VARYING_SLOT_VAR0, var->data.location);
352          EXPECT_EQ(0u, var->data.location_frac);
353       }
354 
355       /* Several varyings only exist in the fragment shader.  Be sure that no
356        * inputs with these locations exist.
357        */
358       EXPECT_NE(VARYING_SLOT_PNTC, var->data.location);
359       EXPECT_NE(VARYING_SLOT_FACE, var->data.location);
360    }
361 }
362 
TEST_F(geometry_builtin,outputs_have_explicit_location)363 TEST_F(geometry_builtin, outputs_have_explicit_location)
364 {
365    foreach_in_list(ir_instruction, node, &this->ir) {
366       ir_variable *const var = node->as_variable();
367 
368       if (var->data.mode != ir_var_shader_out)
369 	 continue;
370 
371       EXPECT_TRUE(var->data.explicit_location);
372       EXPECT_NE(-1, var->data.location);
373       EXPECT_GT(VARYING_SLOT_VAR0, var->data.location);
374       EXPECT_EQ(0u, var->data.location_frac);
375 
376       /* Several varyings only exist in the fragment shader.  Be sure that no
377        * outputs with these locations exist.
378        */
379       EXPECT_NE(VARYING_SLOT_PNTC, var->data.location);
380       EXPECT_NE(VARYING_SLOT_FACE, var->data.location);
381    }
382 }
383 
TEST_F(geometry_builtin,uniforms_and_system_values_dont_have_explicit_location)384 TEST_F(geometry_builtin, uniforms_and_system_values_dont_have_explicit_location)
385 {
386    common_builtin::uniforms_and_system_values_dont_have_explicit_location();
387 }
388 
TEST_F(geometry_builtin,constants_are_constant)389 TEST_F(geometry_builtin, constants_are_constant)
390 {
391    common_builtin::constants_are_constant();
392 }
393 
TEST_F(geometry_builtin,no_invalid_variable_modes)394 TEST_F(geometry_builtin, no_invalid_variable_modes)
395 {
396    common_builtin::no_invalid_variable_modes();
397 }
398