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 32class common_builtin : public ::testing::Test { 33public: 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 57void 58common_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 79void 80common_builtin::TearDown() 81{ 82 ralloc_free(this->mem_ctx); 83 this->mem_ctx = NULL; 84 85 glsl_type_singleton_decref(); 86} 87 88void 89common_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 101void 102common_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 111void 112common_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 125void 126common_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 140void 141common_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 164class vertex_builtin : public common_builtin { 165public: 166 vertex_builtin() 167 : common_builtin(GL_VERTEX_SHADER) 168 { 169 /* empty */ 170 } 171}; 172 173TEST_F(vertex_builtin, names_start_with_gl) 174{ 175 common_builtin::names_start_with_gl(); 176} 177 178TEST_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 193TEST_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 215TEST_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 220TEST_F(vertex_builtin, constants_are_constant) 221{ 222 common_builtin::constants_are_constant(); 223} 224 225TEST_F(vertex_builtin, no_invalid_variable_modes) 226{ 227 common_builtin::no_invalid_variable_modes(); 228} 229 230/********************************************************************/ 231 232class fragment_builtin : public common_builtin { 233public: 234 fragment_builtin() 235 : common_builtin(GL_FRAGMENT_SHADER) 236 { 237 /* empty */ 238 } 239}; 240 241TEST_F(fragment_builtin, names_start_with_gl) 242{ 243 common_builtin::names_start_with_gl(); 244} 245 246TEST_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 266TEST_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 286TEST_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 291TEST_F(fragment_builtin, constants_are_constant) 292{ 293 common_builtin::constants_are_constant(); 294} 295 296TEST_F(fragment_builtin, no_invalid_variable_modes) 297{ 298 common_builtin::no_invalid_variable_modes(); 299} 300 301/********************************************************************/ 302 303class geometry_builtin : public common_builtin { 304public: 305 geometry_builtin() 306 : common_builtin(GL_GEOMETRY_SHADER) 307 { 308 /* empty */ 309 } 310}; 311 312TEST_F(geometry_builtin, names_start_with_gl) 313{ 314 common_builtin::names_start_with_gl(); 315} 316 317TEST_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 363TEST_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 384TEST_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 389TEST_F(geometry_builtin, constants_are_constant) 390{ 391 common_builtin::constants_are_constant(); 392} 393 394TEST_F(geometry_builtin, no_invalid_variable_modes) 395{ 396 common_builtin::no_invalid_variable_modes(); 397} 398