1 /* 2 * Copyright 2010 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 24 /** 25 * \file ir_set_program_inouts.cpp 26 * 27 * Sets the inputs_read and outputs_written of Mesa programs. 28 * 29 * Mesa programs (gl_program, not gl_shader_program) have a set of 30 * flags indicating which varyings are read and written. Computing 31 * which are actually read from some sort of backend code can be 32 * tricky when variable array indexing involved. So this pass 33 * provides support for setting inputs_read and outputs_written right 34 * from the GLSL IR. 35 */ 36 37 #include "main/core.h" /* for struct gl_program */ 38 #include "ir.h" 39 #include "ir_visitor.h" 40 #include "compiler/glsl_types.h" 41 42 namespace { 43 44 class ir_set_program_inouts_visitor : public ir_hierarchical_visitor { 45 public: 46 ir_set_program_inouts_visitor(struct gl_program *prog, 47 gl_shader_stage shader_stage) 48 { 49 this->prog = prog; 50 this->shader_stage = shader_stage; 51 } 52 ~ir_set_program_inouts_visitor() 53 { 54 } 55 56 virtual ir_visitor_status visit_enter(ir_dereference_array *); 57 virtual ir_visitor_status visit_enter(ir_function_signature *); 58 virtual ir_visitor_status visit_enter(ir_discard *); 59 virtual ir_visitor_status visit_enter(ir_texture *); 60 virtual ir_visitor_status visit(ir_dereference_variable *); 61 62 private: 63 void mark_whole_variable(ir_variable *var); 64 bool try_mark_partial_variable(ir_variable *var, ir_rvalue *index); 65 66 struct gl_program *prog; 67 gl_shader_stage shader_stage; 68 }; 69 70 } /* anonymous namespace */ 71 72 static inline bool 73 is_shader_inout(ir_variable *var) 74 { 75 return var->data.mode == ir_var_shader_in || 76 var->data.mode == ir_var_shader_out || 77 var->data.mode == ir_var_system_value; 78 } 79 80 static void 81 mark(struct gl_program *prog, ir_variable *var, int offset, int len, 82 gl_shader_stage stage) 83 { 84 /* As of GLSL 1.20, varyings can only be floats, floating-point 85 * vectors or matrices, or arrays of them. For Mesa programs using 86 * inputs_read/outputs_written, everything but matrices uses one 87 * slot, while matrices use a slot per column. Presumably 88 * something doing a more clever packing would use something other 89 * than inputs_read/outputs_written. 90 */ 91 92 for (int i = 0; i < len; i++) { 93 assert(var->data.location != -1); 94 95 int idx = var->data.location + offset + i; 96 bool is_patch_generic = var->data.patch && 97 idx != VARYING_SLOT_TESS_LEVEL_INNER && 98 idx != VARYING_SLOT_TESS_LEVEL_OUTER && 99 idx != VARYING_SLOT_BOUNDING_BOX0 && 100 idx != VARYING_SLOT_BOUNDING_BOX1; 101 GLbitfield64 bitfield; 102 103 if (is_patch_generic) { 104 assert(idx >= VARYING_SLOT_PATCH0 && idx < VARYING_SLOT_TESS_MAX); 105 bitfield = BITFIELD64_BIT(idx - VARYING_SLOT_PATCH0); 106 } 107 else { 108 assert(idx < VARYING_SLOT_MAX); 109 bitfield = BITFIELD64_BIT(idx); 110 } 111 112 if (var->data.mode == ir_var_shader_in) { 113 if (is_patch_generic) 114 prog->info.patch_inputs_read |= bitfield; 115 else 116 prog->info.inputs_read |= bitfield; 117 118 /* double inputs read is only for vertex inputs */ 119 if (stage == MESA_SHADER_VERTEX && 120 var->type->without_array()->is_dual_slot()) 121 prog->info.double_inputs_read |= bitfield; 122 123 if (stage == MESA_SHADER_FRAGMENT) { 124 prog->info.fs.uses_sample_qualifier |= var->data.sample; 125 } 126 } else if (var->data.mode == ir_var_system_value) { 127 prog->info.system_values_read |= bitfield; 128 } else { 129 assert(var->data.mode == ir_var_shader_out); 130 if (is_patch_generic) { 131 prog->info.patch_outputs_written |= bitfield; 132 } else if (!var->data.read_only) { 133 prog->info.outputs_written |= bitfield; 134 if (var->data.index > 0) 135 prog->SecondaryOutputsWritten |= bitfield; 136 } 137 138 if (var->data.fb_fetch_output) 139 prog->info.outputs_read |= bitfield; 140 } 141 } 142 } 143 144 /** 145 * Mark an entire variable as used. Caller must ensure that the variable 146 * represents a shader input or output. 147 */ 148 void 149 ir_set_program_inouts_visitor::mark_whole_variable(ir_variable *var) 150 { 151 const glsl_type *type = var->type; 152 bool is_vertex_input = false; 153 if (this->shader_stage == MESA_SHADER_GEOMETRY && 154 var->data.mode == ir_var_shader_in && type->is_array()) { 155 type = type->fields.array; 156 } 157 158 if (this->shader_stage == MESA_SHADER_TESS_CTRL && 159 var->data.mode == ir_var_shader_in) { 160 assert(type->is_array()); 161 type = type->fields.array; 162 } 163 164 if (this->shader_stage == MESA_SHADER_TESS_CTRL && 165 var->data.mode == ir_var_shader_out && !var->data.patch) { 166 assert(type->is_array()); 167 type = type->fields.array; 168 } 169 170 if (this->shader_stage == MESA_SHADER_TESS_EVAL && 171 var->data.mode == ir_var_shader_in && !var->data.patch) { 172 assert(type->is_array()); 173 type = type->fields.array; 174 } 175 176 if (this->shader_stage == MESA_SHADER_VERTEX && 177 var->data.mode == ir_var_shader_in) 178 is_vertex_input = true; 179 180 mark(this->prog, var, 0, type->count_attribute_slots(is_vertex_input), 181 this->shader_stage); 182 } 183 184 /* Default handler: Mark all the locations in the variable as used. */ 185 ir_visitor_status 186 ir_set_program_inouts_visitor::visit(ir_dereference_variable *ir) 187 { 188 if (!is_shader_inout(ir->var)) 189 return visit_continue; 190 191 mark_whole_variable(ir->var); 192 193 return visit_continue; 194 } 195 196 /** 197 * Try to mark a portion of the given variable as used. Caller must ensure 198 * that the variable represents a shader input or output which can be indexed 199 * into in array fashion (an array or matrix). For the purpose of geometry 200 * shader inputs (which are always arrays*), this means that the array element 201 * must be something that can be indexed into in array fashion. 202 * 203 * *Except gl_PrimitiveIDIn, as noted below. 204 * 205 * For tessellation control shaders all inputs and non-patch outputs are 206 * arrays. For tessellation evaluation shaders non-patch inputs are arrays. 207 * 208 * If the index can't be interpreted as a constant, or some other problem 209 * occurs, then nothing will be marked and false will be returned. 210 */ 211 bool 212 ir_set_program_inouts_visitor::try_mark_partial_variable(ir_variable *var, 213 ir_rvalue *index) 214 { 215 const glsl_type *type = var->type; 216 217 if (this->shader_stage == MESA_SHADER_GEOMETRY && 218 var->data.mode == ir_var_shader_in) { 219 /* The only geometry shader input that is not an array is 220 * gl_PrimitiveIDIn, and in that case, this code will never be reached, 221 * because gl_PrimitiveIDIn can't be indexed into in array fashion. 222 */ 223 assert(type->is_array()); 224 type = type->fields.array; 225 } 226 227 if (this->shader_stage == MESA_SHADER_TESS_CTRL && 228 var->data.mode == ir_var_shader_in) { 229 assert(type->is_array()); 230 type = type->fields.array; 231 } 232 233 if (this->shader_stage == MESA_SHADER_TESS_CTRL && 234 var->data.mode == ir_var_shader_out && !var->data.patch) { 235 assert(type->is_array()); 236 type = type->fields.array; 237 } 238 239 if (this->shader_stage == MESA_SHADER_TESS_EVAL && 240 var->data.mode == ir_var_shader_in && !var->data.patch) { 241 assert(type->is_array()); 242 type = type->fields.array; 243 } 244 245 /* TODO: implement proper arrays of arrays support 246 * for now let the caller mark whole variable as used. 247 */ 248 if (type->is_array() && type->fields.array->is_array()) 249 return false; 250 251 /* The code below only handles: 252 * 253 * - Indexing into matrices 254 * - Indexing into arrays of (matrices, vectors, or scalars) 255 * 256 * All other possibilities are either prohibited by GLSL (vertex inputs and 257 * fragment outputs can't be structs) or should have been eliminated by 258 * lowering passes (do_vec_index_to_swizzle() gets rid of indexing into 259 * vectors, and lower_packed_varyings() gets rid of structs that occur in 260 * varyings). 261 * 262 * However, we don't use varying packing in all cases - tessellation 263 * shaders bypass it. This means we'll see varying structs and arrays 264 * of structs here. For now, we just give up so the caller marks the 265 * entire variable as used. 266 */ 267 if (!(type->is_matrix() || 268 (type->is_array() && 269 (type->fields.array->is_numeric() || 270 type->fields.array->is_boolean())))) { 271 272 /* If we don't know how to handle this case, give up and let the 273 * caller mark the whole variable as used. 274 */ 275 return false; 276 } 277 278 ir_constant *index_as_constant = index->as_constant(); 279 if (!index_as_constant) 280 return false; 281 282 unsigned elem_width; 283 unsigned num_elems; 284 if (type->is_array()) { 285 num_elems = type->length; 286 if (type->fields.array->is_matrix()) 287 elem_width = type->fields.array->matrix_columns; 288 else 289 elem_width = 1; 290 } else { 291 num_elems = type->matrix_columns; 292 elem_width = 1; 293 } 294 295 if (index_as_constant->value.u[0] >= num_elems) { 296 /* Constant index outside the bounds of the matrix/array. This could 297 * arise as a result of constant folding of a legal GLSL program. 298 * 299 * Even though the spec says that indexing outside the bounds of a 300 * matrix/array results in undefined behaviour, we don't want to pass 301 * out-of-range values to mark() (since this could result in slots that 302 * don't exist being marked as used), so just let the caller mark the 303 * whole variable as used. 304 */ 305 return false; 306 } 307 308 /* double element width for double types that takes two slots */ 309 if (this->shader_stage != MESA_SHADER_VERTEX || 310 var->data.mode != ir_var_shader_in) { 311 if (type->without_array()->is_dual_slot()) 312 elem_width *= 2; 313 } 314 315 mark(this->prog, var, index_as_constant->value.u[0] * elem_width, 316 elem_width, this->shader_stage); 317 return true; 318 } 319 320 static bool 321 is_multiple_vertices(gl_shader_stage stage, ir_variable *var) 322 { 323 if (var->data.patch) 324 return false; 325 326 if (var->data.mode == ir_var_shader_in) 327 return stage == MESA_SHADER_GEOMETRY || 328 stage == MESA_SHADER_TESS_CTRL || 329 stage == MESA_SHADER_TESS_EVAL; 330 if (var->data.mode == ir_var_shader_out) 331 return stage == MESA_SHADER_TESS_CTRL; 332 333 return false; 334 } 335 336 ir_visitor_status 337 ir_set_program_inouts_visitor::visit_enter(ir_dereference_array *ir) 338 { 339 /* Note: for geometry shader inputs, lower_named_interface_blocks may 340 * create 2D arrays, so we need to be able to handle those. 2D arrays 341 * shouldn't be able to crop up for any other reason. 342 */ 343 if (ir_dereference_array * const inner_array = 344 ir->array->as_dereference_array()) { 345 /* ir => foo[i][j] 346 * inner_array => foo[i] 347 */ 348 if (ir_dereference_variable * const deref_var = 349 inner_array->array->as_dereference_variable()) { 350 if (is_multiple_vertices(this->shader_stage, deref_var->var)) { 351 /* foo is a geometry or tessellation shader input, so i is 352 * the vertex, and j the part of the input we're accessing. 353 */ 354 if (try_mark_partial_variable(deref_var->var, ir->array_index)) 355 { 356 /* We've now taken care of foo and j, but i might contain a 357 * subexpression that accesses shader inputs. So manually 358 * visit i and then continue with the parent. 359 */ 360 inner_array->array_index->accept(this); 361 return visit_continue_with_parent; 362 } 363 } 364 } 365 } else if (ir_dereference_variable * const deref_var = 366 ir->array->as_dereference_variable()) { 367 /* ir => foo[i], where foo is a variable. */ 368 if (is_multiple_vertices(this->shader_stage, deref_var->var)) { 369 /* foo is a geometry or tessellation shader input, so i is 370 * the vertex, and we're accessing the entire input. 371 */ 372 mark_whole_variable(deref_var->var); 373 /* We've now taken care of foo, but i might contain a subexpression 374 * that accesses shader inputs. So manually visit i and then 375 * continue with the parent. 376 */ 377 ir->array_index->accept(this); 378 return visit_continue_with_parent; 379 } else if (is_shader_inout(deref_var->var)) { 380 /* foo is a shader input/output, but not a geometry shader input, 381 * so i is the part of the input we're accessing. 382 */ 383 if (try_mark_partial_variable(deref_var->var, ir->array_index)) 384 return visit_continue_with_parent; 385 } 386 } 387 388 /* The expression is something we don't recognize. Just visit its 389 * subexpressions. 390 */ 391 return visit_continue; 392 } 393 394 ir_visitor_status 395 ir_set_program_inouts_visitor::visit_enter(ir_function_signature *ir) 396 { 397 /* We don't want to descend into the function parameters and 398 * consider them as shader inputs or outputs. 399 */ 400 visit_list_elements(this, &ir->body); 401 return visit_continue_with_parent; 402 } 403 404 ir_visitor_status 405 ir_set_program_inouts_visitor::visit_enter(ir_discard *) 406 { 407 /* discards are only allowed in fragment shaders. */ 408 assert(this->shader_stage == MESA_SHADER_FRAGMENT); 409 410 prog->info.fs.uses_discard = true; 411 412 return visit_continue; 413 } 414 415 ir_visitor_status 416 ir_set_program_inouts_visitor::visit_enter(ir_texture *ir) 417 { 418 if (ir->op == ir_tg4) 419 prog->info.uses_texture_gather = true; 420 return visit_continue; 421 } 422 423 void 424 do_set_program_inouts(exec_list *instructions, struct gl_program *prog, 425 gl_shader_stage shader_stage) 426 { 427 ir_set_program_inouts_visitor v(prog, shader_stage); 428 429 prog->info.inputs_read = 0; 430 prog->info.outputs_written = 0; 431 prog->SecondaryOutputsWritten = 0; 432 prog->info.outputs_read = 0; 433 prog->info.patch_inputs_read = 0; 434 prog->info.patch_outputs_written = 0; 435 prog->info.system_values_read = 0; 436 if (shader_stage == MESA_SHADER_FRAGMENT) { 437 prog->info.fs.uses_sample_qualifier = false; 438 prog->info.fs.uses_discard = false; 439 } 440 visit_list_elements(&v, instructions); 441 } 442