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 } 394