2 * Copyright © 2013 Intel Corporation
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:
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
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.
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"
29 #include "glsl_parser_extras.h"
30 #include "glsl_symbol_table.h"
32 class common_builtin
: public ::testing::Test
{
34 common_builtin(GLenum shader_type
)
35 : shader_type(shader_type
)
41 virtual void TearDown();
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();
50 struct _mesa_glsl_parse_state
*state
;
51 struct gl_shader
*shader
;
58 common_builtin::SetUp()
60 this->mem_ctx
= ralloc_context(NULL
);
61 this->ir
.make_empty();
63 initialize_context_to_defaults(&this->ctx
, API_OPENGL_COMPAT
);
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
);
70 new(mem_ctx
) _mesa_glsl_parse_state(&this->ctx
, this->shader
->Stage
,
73 _mesa_glsl_initialize_types(this->state
);
74 _mesa_glsl_initialize_variables(&this->ir
, this->state
);
78 common_builtin::TearDown()
80 ralloc_free(this->mem_ctx
);
85 common_builtin::string_starts_with_prefix(const char *str
, const char *prefix
)
87 const size_t len
= strlen(prefix
);
88 char *const name_prefix
= new char[len
+ 1];
90 strncpy(name_prefix
, str
, len
);
91 name_prefix
[len
] = '\0';
92 EXPECT_STREQ(prefix
, name_prefix
) << "Bad name " << str
;
94 delete [] name_prefix
;
98 common_builtin::names_start_with_gl()
100 foreach_in_list(ir_instruction
, node
, &this->ir
) {
101 ir_variable
*const var
= node
->as_variable();
103 string_starts_with_prefix(var
->name
, "gl_");
108 common_builtin::uniforms_and_system_values_dont_have_explicit_location()
110 foreach_in_list(ir_instruction
, node
, &this->ir
) {
111 ir_variable
*const var
= node
->as_variable();
113 if (var
->data
.mode
!= ir_var_uniform
&& var
->data
.mode
!= ir_var_system_value
)
116 EXPECT_FALSE(var
->data
.explicit_location
);
117 EXPECT_EQ(-1, var
->data
.location
);
122 common_builtin::constants_are_constant()
124 foreach_in_list(ir_instruction
, node
, &this->ir
) {
125 ir_variable
*const var
= node
->as_variable();
127 if (var
->data
.mode
!= ir_var_auto
)
130 EXPECT_FALSE(var
->data
.explicit_location
);
131 EXPECT_EQ(-1, var
->data
.location
);
132 EXPECT_TRUE(var
->data
.read_only
);
137 common_builtin::no_invalid_variable_modes()
139 foreach_in_list(ir_instruction
, node
, &this->ir
) {
140 ir_variable
*const var
= node
->as_variable();
142 switch (var
->data
.mode
) {
145 case ir_var_shader_in
:
146 case ir_var_shader_out
:
147 case ir_var_system_value
:
151 ADD_FAILURE() << "Built-in variable " << var
->name
152 << " has an invalid mode " << int(var
->data
.mode
);
158 /************************************************************/
160 class vertex_builtin
: public common_builtin
{
163 : common_builtin(GL_VERTEX_SHADER
)
169 TEST_F(vertex_builtin
, names_start_with_gl
)
171 common_builtin::names_start_with_gl();
174 TEST_F(vertex_builtin
, inputs_have_explicit_location
)
176 foreach_in_list(ir_instruction
, node
, &this->ir
) {
177 ir_variable
*const var
= node
->as_variable();
179 if (var
->data
.mode
!= ir_var_shader_in
)
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
);
189 TEST_F(vertex_builtin
, outputs_have_explicit_location
)
191 foreach_in_list(ir_instruction
, node
, &this->ir
) {
192 ir_variable
*const var
= node
->as_variable();
194 if (var
->data
.mode
!= ir_var_shader_out
)
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
);
202 /* Several varyings only exist in the fragment shader. Be sure that no
203 * outputs with these locations exist.
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
);
211 TEST_F(vertex_builtin
, uniforms_and_system_values_dont_have_explicit_location
)
213 common_builtin::uniforms_and_system_values_dont_have_explicit_location();
216 TEST_F(vertex_builtin
, constants_are_constant
)
218 common_builtin::constants_are_constant();
221 TEST_F(vertex_builtin
, no_invalid_variable_modes
)
223 common_builtin::no_invalid_variable_modes();
226 /********************************************************************/
228 class fragment_builtin
: public common_builtin
{
231 : common_builtin(GL_FRAGMENT_SHADER
)
237 TEST_F(fragment_builtin
, names_start_with_gl
)
239 common_builtin::names_start_with_gl();
242 TEST_F(fragment_builtin
, inputs_have_explicit_location
)
244 foreach_in_list(ir_instruction
, node
, &this->ir
) {
245 ir_variable
*const var
= node
->as_variable();
247 if (var
->data
.mode
!= ir_var_shader_in
)
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
);
255 /* Several varyings only exist in the vertex / geometry shader. Be sure
256 * that no inputs with these locations exist.
258 EXPECT_TRUE(_mesa_varying_slot_in_fs((gl_varying_slot
) var
->data
.location
));
262 TEST_F(fragment_builtin
, outputs_have_explicit_location
)
264 foreach_in_list(ir_instruction
, node
, &this->ir
) {
265 ir_variable
*const var
= node
->as_variable();
267 if (var
->data
.mode
!= ir_var_shader_out
)
270 EXPECT_TRUE(var
->data
.explicit_location
);
271 EXPECT_NE(-1, var
->data
.location
);
273 /* gl_FragData[] has location FRAG_RESULT_DATA0. Locations beyond that
276 EXPECT_GE(FRAG_RESULT_DATA0
, var
->data
.location
);
278 EXPECT_EQ(0u, var
->data
.location_frac
);
282 TEST_F(fragment_builtin
, uniforms_and_system_values_dont_have_explicit_location
)
284 common_builtin::uniforms_and_system_values_dont_have_explicit_location();
287 TEST_F(fragment_builtin
, constants_are_constant
)
289 common_builtin::constants_are_constant();
292 TEST_F(fragment_builtin
, no_invalid_variable_modes
)
294 common_builtin::no_invalid_variable_modes();
297 /********************************************************************/
299 class geometry_builtin
: public common_builtin
{
302 : common_builtin(GL_GEOMETRY_SHADER
)
308 TEST_F(geometry_builtin
, names_start_with_gl
)
310 common_builtin::names_start_with_gl();
313 TEST_F(geometry_builtin
, inputs_have_explicit_location
)
315 foreach_in_list(ir_instruction
, node
, &this->ir
) {
316 ir_variable
*const var
= node
->as_variable();
318 if (var
->data
.mode
!= ir_var_shader_in
)
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
);
326 ASSERT_TRUE(var
->type
->is_array());
328 const glsl_type
*const instance_type
= var
->type
->fields
.array
;
330 for (unsigned i
= 0; i
< instance_type
->length
; i
++) {
331 const glsl_struct_field
*const input
=
332 &instance_type
->fields
.structure
[i
];
334 string_starts_with_prefix(input
->name
, "gl_");
335 EXPECT_NE(-1, input
->location
);
336 EXPECT_GT(VARYING_SLOT_VAR0
, input
->location
);
338 /* Several varyings only exist in the fragment shader. Be sure
339 * that no inputs with these locations exist.
341 EXPECT_NE(VARYING_SLOT_PNTC
, input
->location
);
342 EXPECT_NE(VARYING_SLOT_FACE
, input
->location
);
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
);
351 /* Several varyings only exist in the fragment shader. Be sure that no
352 * inputs with these locations exist.
354 EXPECT_NE(VARYING_SLOT_PNTC
, var
->data
.location
);
355 EXPECT_NE(VARYING_SLOT_FACE
, var
->data
.location
);
359 TEST_F(geometry_builtin
, outputs_have_explicit_location
)
361 foreach_in_list(ir_instruction
, node
, &this->ir
) {
362 ir_variable
*const var
= node
->as_variable();
364 if (var
->data
.mode
!= ir_var_shader_out
)
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
);
372 /* Several varyings only exist in the fragment shader. Be sure that no
373 * outputs with these locations exist.
375 EXPECT_NE(VARYING_SLOT_PNTC
, var
->data
.location
);
376 EXPECT_NE(VARYING_SLOT_FACE
, var
->data
.location
);
380 TEST_F(geometry_builtin
, uniforms_and_system_values_dont_have_explicit_location
)
382 common_builtin::uniforms_and_system_values_dont_have_explicit_location();
385 TEST_F(geometry_builtin
, constants_are_constant
)
387 common_builtin::constants_are_constant();
390 TEST_F(geometry_builtin
, no_invalid_variable_modes
)
392 common_builtin::no_invalid_variable_modes();