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