nir: move to compiler/
[mesa.git] / src / glsl / tests / builtin_variable_test.cpp
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 }