Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 1
/*
2
 * Copyright © 2012 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 link_varyings.cpp
26
 *
27
 * Linker functions related specifically to linking varyings between shader
28
 * stages.
29
 */
30
 
31
 
32
#include "main/mtypes.h"
33
#include "glsl_symbol_table.h"
34
#include "glsl_parser_extras.h"
35
#include "ir_optimization.h"
36
#include "linker.h"
37
#include "link_varyings.h"
38
#include "main/macros.h"
39
#include "program/hash_table.h"
40
#include "program.h"
41
 
42
 
43
/**
44
 * Validate that outputs from one stage match inputs of another
45
 */
46
bool
47
cross_validate_outputs_to_inputs(struct gl_shader_program *prog,
48
				 gl_shader *producer, gl_shader *consumer)
49
{
50
   glsl_symbol_table parameters;
51
   const char *const producer_stage =
52
      _mesa_glsl_shader_target_name(producer->Type);
53
   const char *const consumer_stage =
54
      _mesa_glsl_shader_target_name(consumer->Type);
55
 
56
   /* Find all shader outputs in the "producer" stage.
57
    */
58
   foreach_list(node, producer->ir) {
59
      ir_variable *const var = ((ir_instruction *) node)->as_variable();
60
 
61
      if ((var == NULL) || (var->mode != ir_var_shader_out))
62
	 continue;
63
 
64
      parameters.add_variable(var);
65
   }
66
 
67
 
68
   /* Find all shader inputs in the "consumer" stage.  Any variables that have
69
    * matching outputs already in the symbol table must have the same type and
70
    * qualifiers.
71
    */
72
   foreach_list(node, consumer->ir) {
73
      ir_variable *const input = ((ir_instruction *) node)->as_variable();
74
 
75
      if ((input == NULL) || (input->mode != ir_var_shader_in))
76
	 continue;
77
 
78
      ir_variable *const output = parameters.get_variable(input->name);
79
      if (output != NULL) {
80
	 /* Check that the types match between stages.
81
	  */
82
	 if (input->type != output->type) {
83
	    /* There is a bit of a special case for gl_TexCoord.  This
84
	     * built-in is unsized by default.  Applications that variable
85
	     * access it must redeclare it with a size.  There is some
86
	     * language in the GLSL spec that implies the fragment shader
87
	     * and vertex shader do not have to agree on this size.  Other
88
	     * driver behave this way, and one or two applications seem to
89
	     * rely on it.
90
	     *
91
	     * Neither declaration needs to be modified here because the array
92
	     * sizes are fixed later when update_array_sizes is called.
93
	     *
94
	     * From page 48 (page 54 of the PDF) of the GLSL 1.10 spec:
95
	     *
96
	     *     "Unlike user-defined varying variables, the built-in
97
	     *     varying variables don't have a strict one-to-one
98
	     *     correspondence between the vertex language and the
99
	     *     fragment language."
100
	     */
101
	    if (!output->type->is_array()
102
		|| (strncmp("gl_", output->name, 3) != 0)) {
103
	       linker_error(prog,
104
			    "%s shader output `%s' declared as type `%s', "
105
			    "but %s shader input declared as type `%s'\n",
106
			    producer_stage, output->name,
107
			    output->type->name,
108
			    consumer_stage, input->type->name);
109
	       return false;
110
	    }
111
	 }
112
 
113
	 /* Check that all of the qualifiers match between stages.
114
	  */
115
	 if (input->centroid != output->centroid) {
116
	    linker_error(prog,
117
			 "%s shader output `%s' %s centroid qualifier, "
118
			 "but %s shader input %s centroid qualifier\n",
119
			 producer_stage,
120
			 output->name,
121
			 (output->centroid) ? "has" : "lacks",
122
			 consumer_stage,
123
			 (input->centroid) ? "has" : "lacks");
124
	    return false;
125
	 }
126
 
127
	 if (input->invariant != output->invariant) {
128
	    linker_error(prog,
129
			 "%s shader output `%s' %s invariant qualifier, "
130
			 "but %s shader input %s invariant qualifier\n",
131
			 producer_stage,
132
			 output->name,
133
			 (output->invariant) ? "has" : "lacks",
134
			 consumer_stage,
135
			 (input->invariant) ? "has" : "lacks");
136
	    return false;
137
	 }
138
 
139
	 if (input->interpolation != output->interpolation) {
140
	    linker_error(prog,
141
			 "%s shader output `%s' specifies %s "
142
			 "interpolation qualifier, "
143
			 "but %s shader input specifies %s "
144
			 "interpolation qualifier\n",
145
			 producer_stage,
146
			 output->name,
147
			 output->interpolation_string(),
148
			 consumer_stage,
149
			 input->interpolation_string());
150
	    return false;
151
	 }
152
      }
153
   }
154
 
155
   return true;
156
}
157
 
158
 
159
/**
160
 * Initialize this object based on a string that was passed to
161
 * glTransformFeedbackVaryings.
162
 *
163
 * If the input is mal-formed, this call still succeeds, but it sets
164
 * this->var_name to a mal-formed input, so tfeedback_decl::find_output_var()
165
 * will fail to find any matching variable.
166
 */
167
void
168
tfeedback_decl::init(struct gl_context *ctx, struct gl_shader_program *prog,
169
                     const void *mem_ctx, const char *input)
170
{
171
   /* We don't have to be pedantic about what is a valid GLSL variable name,
172
    * because any variable with an invalid name can't exist in the IR anyway.
173
    */
174
 
175
   this->location = -1;
176
   this->orig_name = input;
177
   this->is_clip_distance_mesa = false;
178
   this->skip_components = 0;
179
   this->next_buffer_separator = false;
180
   this->matched_candidate = NULL;
181
 
182
   if (ctx->Extensions.ARB_transform_feedback3) {
183
      /* Parse gl_NextBuffer. */
184
      if (strcmp(input, "gl_NextBuffer") == 0) {
185
         this->next_buffer_separator = true;
186
         return;
187
      }
188
 
189
      /* Parse gl_SkipComponents. */
190
      if (strcmp(input, "gl_SkipComponents1") == 0)
191
         this->skip_components = 1;
192
      else if (strcmp(input, "gl_SkipComponents2") == 0)
193
         this->skip_components = 2;
194
      else if (strcmp(input, "gl_SkipComponents3") == 0)
195
         this->skip_components = 3;
196
      else if (strcmp(input, "gl_SkipComponents4") == 0)
197
         this->skip_components = 4;
198
 
199
      if (this->skip_components)
200
         return;
201
   }
202
 
203
   /* Parse a declaration. */
204
   const char *base_name_end;
205
   long subscript = parse_program_resource_name(input, &base_name_end);
206
   this->var_name = ralloc_strndup(mem_ctx, input, base_name_end - input);
207
   if (subscript >= 0) {
208
      this->array_subscript = subscript;
209
      this->is_subscripted = true;
210
   } else {
211
      this->is_subscripted = false;
212
   }
213
 
214
   /* For drivers that lower gl_ClipDistance to gl_ClipDistanceMESA, this
215
    * class must behave specially to account for the fact that gl_ClipDistance
216
    * is converted from a float[8] to a vec4[2].
217
    */
218
   if (ctx->ShaderCompilerOptions[MESA_SHADER_VERTEX].LowerClipDistance &&
219
       strcmp(this->var_name, "gl_ClipDistance") == 0) {
220
      this->is_clip_distance_mesa = true;
221
   }
222
}
223
 
224
 
225
/**
226
 * Determine whether two tfeedback_decl objects refer to the same variable and
227
 * array index (if applicable).
228
 */
229
bool
230
tfeedback_decl::is_same(const tfeedback_decl &x, const tfeedback_decl &y)
231
{
232
   assert(x.is_varying() && y.is_varying());
233
 
234
   if (strcmp(x.var_name, y.var_name) != 0)
235
      return false;
236
   if (x.is_subscripted != y.is_subscripted)
237
      return false;
238
   if (x.is_subscripted && x.array_subscript != y.array_subscript)
239
      return false;
240
   return true;
241
}
242
 
243
 
244
/**
245
 * Assign a location for this tfeedback_decl object based on the transform
246
 * feedback candidate found by find_candidate.
247
 *
248
 * If an error occurs, the error is reported through linker_error() and false
249
 * is returned.
250
 */
251
bool
252
tfeedback_decl::assign_location(struct gl_context *ctx,
253
                                struct gl_shader_program *prog)
254
{
255
   assert(this->is_varying());
256
 
257
   unsigned fine_location
258
      = this->matched_candidate->toplevel_var->location * 4
259
      + this->matched_candidate->toplevel_var->location_frac
260
      + this->matched_candidate->offset;
261
 
262
   if (this->matched_candidate->type->is_array()) {
263
      /* Array variable */
264
      const unsigned matrix_cols =
265
         this->matched_candidate->type->fields.array->matrix_columns;
266
      const unsigned vector_elements =
267
         this->matched_candidate->type->fields.array->vector_elements;
268
      unsigned actual_array_size = this->is_clip_distance_mesa ?
269
         prog->Vert.ClipDistanceArraySize :
270
         this->matched_candidate->type->array_size();
271
 
272
      if (this->is_subscripted) {
273
         /* Check array bounds. */
274
         if (this->array_subscript >= actual_array_size) {
275
            linker_error(prog, "Transform feedback varying %s has index "
276
                         "%i, but the array size is %u.",
277
                         this->orig_name, this->array_subscript,
278
                         actual_array_size);
279
            return false;
280
         }
281
         unsigned array_elem_size = this->is_clip_distance_mesa ?
282
            1 : vector_elements * matrix_cols;
283
         fine_location += array_elem_size * this->array_subscript;
284
         this->size = 1;
285
      } else {
286
         this->size = actual_array_size;
287
      }
288
      this->vector_elements = vector_elements;
289
      this->matrix_columns = matrix_cols;
290
      if (this->is_clip_distance_mesa)
291
         this->type = GL_FLOAT;
292
      else
293
         this->type = this->matched_candidate->type->fields.array->gl_type;
294
   } else {
295
      /* Regular variable (scalar, vector, or matrix) */
296
      if (this->is_subscripted) {
297
         linker_error(prog, "Transform feedback varying %s requested, "
298
                      "but %s is not an array.",
299
                      this->orig_name, this->var_name);
300
         return false;
301
      }
302
      this->size = 1;
303
      this->vector_elements = this->matched_candidate->type->vector_elements;
304
      this->matrix_columns = this->matched_candidate->type->matrix_columns;
305
      this->type = this->matched_candidate->type->gl_type;
306
   }
307
   this->location = fine_location / 4;
308
   this->location_frac = fine_location % 4;
309
 
310
   /* From GL_EXT_transform_feedback:
311
    *   A program will fail to link if:
312
    *
313
    *   * the total number of components to capture in any varying
314
    *     variable in  is greater than the constant
315
    *     MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT and the
316
    *     buffer mode is SEPARATE_ATTRIBS_EXT;
317
    */
318
   if (prog->TransformFeedback.BufferMode == GL_SEPARATE_ATTRIBS &&
319
       this->num_components() >
320
       ctx->Const.MaxTransformFeedbackSeparateComponents) {
321
      linker_error(prog, "Transform feedback varying %s exceeds "
322
                   "MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS.",
323
                   this->orig_name);
324
      return false;
325
   }
326
 
327
   return true;
328
}
329
 
330
 
331
unsigned
332
tfeedback_decl::get_num_outputs() const
333
{
334
   if (!this->is_varying()) {
335
      return 0;
336
   }
337
 
338
   return (this->num_components() + this->location_frac + 3)/4;
339
}
340
 
341
 
342
/**
343
 * Update gl_transform_feedback_info to reflect this tfeedback_decl.
344
 *
345
 * If an error occurs, the error is reported through linker_error() and false
346
 * is returned.
347
 */
348
bool
349
tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog,
350
                      struct gl_transform_feedback_info *info,
351
                      unsigned buffer, const unsigned max_outputs) const
352
{
353
   assert(!this->next_buffer_separator);
354
 
355
   /* Handle gl_SkipComponents. */
356
   if (this->skip_components) {
357
      info->BufferStride[buffer] += this->skip_components;
358
      return true;
359
   }
360
 
361
   /* From GL_EXT_transform_feedback:
362
    *   A program will fail to link if:
363
    *
364
    *     * the total number of components to capture is greater than
365
    *       the constant MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT
366
    *       and the buffer mode is INTERLEAVED_ATTRIBS_EXT.
367
    */
368
   if (prog->TransformFeedback.BufferMode == GL_INTERLEAVED_ATTRIBS &&
369
       info->BufferStride[buffer] + this->num_components() >
370
       ctx->Const.MaxTransformFeedbackInterleavedComponents) {
371
      linker_error(prog, "The MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS "
372
                   "limit has been exceeded.");
373
      return false;
374
   }
375
 
376
   unsigned location = this->location;
377
   unsigned location_frac = this->location_frac;
378
   unsigned num_components = this->num_components();
379
   while (num_components > 0) {
380
      unsigned output_size = MIN2(num_components, 4 - location_frac);
381
      assert(info->NumOutputs < max_outputs);
382
      info->Outputs[info->NumOutputs].ComponentOffset = location_frac;
383
      info->Outputs[info->NumOutputs].OutputRegister = location;
384
      info->Outputs[info->NumOutputs].NumComponents = output_size;
385
      info->Outputs[info->NumOutputs].OutputBuffer = buffer;
386
      info->Outputs[info->NumOutputs].DstOffset = info->BufferStride[buffer];
387
      ++info->NumOutputs;
388
      info->BufferStride[buffer] += output_size;
389
      num_components -= output_size;
390
      location++;
391
      location_frac = 0;
392
   }
393
 
394
   info->Varyings[info->NumVarying].Name = ralloc_strdup(prog, this->orig_name);
395
   info->Varyings[info->NumVarying].Type = this->type;
396
   info->Varyings[info->NumVarying].Size = this->size;
397
   info->NumVarying++;
398
 
399
   return true;
400
}
401
 
402
 
403
const tfeedback_candidate *
404
tfeedback_decl::find_candidate(gl_shader_program *prog,
405
                               hash_table *tfeedback_candidates)
406
{
407
   const char *name = this->is_clip_distance_mesa
408
      ? "gl_ClipDistanceMESA" : this->var_name;
409
   this->matched_candidate = (const tfeedback_candidate *)
410
      hash_table_find(tfeedback_candidates, name);
411
   if (!this->matched_candidate) {
412
      /* From GL_EXT_transform_feedback:
413
       *   A program will fail to link if:
414
       *
415
       *   * any variable name specified in the  array is not
416
       *     declared as an output in the geometry shader (if present) or
417
       *     the vertex shader (if no geometry shader is present);
418
       */
419
      linker_error(prog, "Transform feedback varying %s undeclared.",
420
                   this->orig_name);
421
   }
422
   return this->matched_candidate;
423
}
424
 
425
 
426
/**
427
 * Parse all the transform feedback declarations that were passed to
428
 * glTransformFeedbackVaryings() and store them in tfeedback_decl objects.
429
 *
430
 * If an error occurs, the error is reported through linker_error() and false
431
 * is returned.
432
 */
433
bool
434
parse_tfeedback_decls(struct gl_context *ctx, struct gl_shader_program *prog,
435
                      const void *mem_ctx, unsigned num_names,
436
                      char **varying_names, tfeedback_decl *decls)
437
{
438
   for (unsigned i = 0; i < num_names; ++i) {
439
      decls[i].init(ctx, prog, mem_ctx, varying_names[i]);
440
 
441
      if (!decls[i].is_varying())
442
         continue;
443
 
444
      /* From GL_EXT_transform_feedback:
445
       *   A program will fail to link if:
446
       *
447
       *   * any two entries in the  array specify the same varying
448
       *     variable;
449
       *
450
       * We interpret this to mean "any two entries in the  array
451
       * specify the same varying variable and array index", since transform
452
       * feedback of arrays would be useless otherwise.
453
       */
454
      for (unsigned j = 0; j < i; ++j) {
455
         if (!decls[j].is_varying())
456
            continue;
457
 
458
         if (tfeedback_decl::is_same(decls[i], decls[j])) {
459
            linker_error(prog, "Transform feedback varying %s specified "
460
                         "more than once.", varying_names[i]);
461
            return false;
462
         }
463
      }
464
   }
465
   return true;
466
}
467
 
468
 
469
/**
470
 * Store transform feedback location assignments into
471
 * prog->LinkedTransformFeedback based on the data stored in tfeedback_decls.
472
 *
473
 * If an error occurs, the error is reported through linker_error() and false
474
 * is returned.
475
 */
476
bool
477
store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog,
478
                     unsigned num_tfeedback_decls,
479
                     tfeedback_decl *tfeedback_decls)
480
{
481
   bool separate_attribs_mode =
482
      prog->TransformFeedback.BufferMode == GL_SEPARATE_ATTRIBS;
483
 
484
   ralloc_free(prog->LinkedTransformFeedback.Varyings);
485
   ralloc_free(prog->LinkedTransformFeedback.Outputs);
486
 
487
   memset(&prog->LinkedTransformFeedback, 0,
488
          sizeof(prog->LinkedTransformFeedback));
489
 
490
   prog->LinkedTransformFeedback.Varyings =
491
      rzalloc_array(prog,
492
		    struct gl_transform_feedback_varying_info,
493
		    num_tfeedback_decls);
494
 
495
   unsigned num_outputs = 0;
496
   for (unsigned i = 0; i < num_tfeedback_decls; ++i)
497
      num_outputs += tfeedback_decls[i].get_num_outputs();
498
 
499
   prog->LinkedTransformFeedback.Outputs =
500
      rzalloc_array(prog,
501
                    struct gl_transform_feedback_output,
502
                    num_outputs);
503
 
504
   unsigned num_buffers = 0;
505
 
506
   if (separate_attribs_mode) {
507
      /* GL_SEPARATE_ATTRIBS */
508
      for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
509
         if (!tfeedback_decls[i].store(ctx, prog, &prog->LinkedTransformFeedback,
510
                                       num_buffers, num_outputs))
511
            return false;
512
 
513
         num_buffers++;
514
      }
515
   }
516
   else {
517
      /* GL_INVERLEAVED_ATTRIBS */
518
      for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
519
         if (tfeedback_decls[i].is_next_buffer_separator()) {
520
            num_buffers++;
521
            continue;
522
         }
523
 
524
         if (!tfeedback_decls[i].store(ctx, prog,
525
                                       &prog->LinkedTransformFeedback,
526
                                       num_buffers, num_outputs))
527
            return false;
528
      }
529
      num_buffers++;
530
   }
531
 
532
   assert(prog->LinkedTransformFeedback.NumOutputs == num_outputs);
533
 
534
   prog->LinkedTransformFeedback.NumBuffers = num_buffers;
535
   return true;
536
}
537
 
538
 
539
/**
540
 * Data structure recording the relationship between outputs of one shader
541
 * stage (the "producer") and inputs of another (the "consumer").
542
 */
543
class varying_matches
544
{
545
public:
546
   varying_matches(bool disable_varying_packing, bool consumer_is_fs);
547
   ~varying_matches();
548
   void record(ir_variable *producer_var, ir_variable *consumer_var);
549
   unsigned assign_locations();
550
   void store_locations(unsigned producer_base, unsigned consumer_base) const;
551
 
552
private:
553
   /**
554
    * If true, this driver disables varying packing, so all varyings need to
555
    * be aligned on slot boundaries, and take up a number of slots equal to
556
    * their number of matrix columns times their array size.
557
    */
558
   const bool disable_varying_packing;
559
 
560
   /**
561
    * Enum representing the order in which varyings are packed within a
562
    * packing class.
563
    *
564
    * Currently we pack vec4's first, then vec2's, then scalar values, then
565
    * vec3's.  This order ensures that the only vectors that are at risk of
566
    * having to be "double parked" (split between two adjacent varying slots)
567
    * are the vec3's.
568
    */
569
   enum packing_order_enum {
570
      PACKING_ORDER_VEC4,
571
      PACKING_ORDER_VEC2,
572
      PACKING_ORDER_SCALAR,
573
      PACKING_ORDER_VEC3,
574
   };
575
 
576
   static unsigned compute_packing_class(ir_variable *var);
577
   static packing_order_enum compute_packing_order(ir_variable *var);
578
   static int match_comparator(const void *x_generic, const void *y_generic);
579
 
580
   /**
581
    * Structure recording the relationship between a single producer output
582
    * and a single consumer input.
583
    */
584
   struct match {
585
      /**
586
       * Packing class for this varying, computed by compute_packing_class().
587
       */
588
      unsigned packing_class;
589
 
590
      /**
591
       * Packing order for this varying, computed by compute_packing_order().
592
       */
593
      packing_order_enum packing_order;
594
      unsigned num_components;
595
 
596
      /**
597
       * The output variable in the producer stage.
598
       */
599
      ir_variable *producer_var;
600
 
601
      /**
602
       * The input variable in the consumer stage.
603
       */
604
      ir_variable *consumer_var;
605
 
606
      /**
607
       * The location which has been assigned for this varying.  This is
608
       * expressed in multiples of a float, with the first generic varying
609
       * (i.e. the one referred to by VARYING_SLOT_VAR0) represented by the
610
       * value 0.
611
       */
612
      unsigned generic_location;
613
   } *matches;
614
 
615
   /**
616
    * The number of elements in the \c matches array that are currently in
617
    * use.
618
    */
619
   unsigned num_matches;
620
 
621
   /**
622
    * The number of elements that were set aside for the \c matches array when
623
    * it was allocated.
624
    */
625
   unsigned matches_capacity;
626
 
627
   const bool consumer_is_fs;
628
};
629
 
630
 
631
varying_matches::varying_matches(bool disable_varying_packing,
632
                                 bool consumer_is_fs)
633
   : disable_varying_packing(disable_varying_packing),
634
     consumer_is_fs(consumer_is_fs)
635
{
636
   /* Note: this initial capacity is rather arbitrarily chosen to be large
637
    * enough for many cases without wasting an unreasonable amount of space.
638
    * varying_matches::record() will resize the array if there are more than
639
    * this number of varyings.
640
    */
641
   this->matches_capacity = 8;
642
   this->matches = (match *)
643
      malloc(sizeof(*this->matches) * this->matches_capacity);
644
   this->num_matches = 0;
645
}
646
 
647
 
648
varying_matches::~varying_matches()
649
{
650
   free(this->matches);
651
}
652
 
653
 
654
/**
655
 * Record the given producer/consumer variable pair in the list of variables
656
 * that should later be assigned locations.
657
 *
658
 * It is permissible for \c consumer_var to be NULL (this happens if a
659
 * variable is output by the producer and consumed by transform feedback, but
660
 * not consumed by the consumer).
661
 *
662
 * If \c producer_var has already been paired up with a consumer_var, or
663
 * producer_var is part of fixed pipeline functionality (and hence already has
664
 * a location assigned), this function has no effect.
665
 *
666
 * Note: as a side effect this function may change the interpolation type of
667
 * \c producer_var, but only when the change couldn't possibly affect
668
 * rendering.
669
 */
670
void
671
varying_matches::record(ir_variable *producer_var, ir_variable *consumer_var)
672
{
673
   if (!producer_var->is_unmatched_generic_inout) {
674
      /* Either a location already exists for this variable (since it is part
675
       * of fixed functionality), or it has already been recorded as part of a
676
       * previous match.
677
       */
678
      return;
679
   }
680
 
681
   if ((consumer_var == NULL && producer_var->type->contains_integer()) ||
682
       !consumer_is_fs) {
683
      /* Since this varying is not being consumed by the fragment shader, its
684
       * interpolation type varying cannot possibly affect rendering.  Also,
685
       * this variable is non-flat and is (or contains) an integer.
686
       *
687
       * lower_packed_varyings requires all integer varyings to flat,
688
       * regardless of where they appear.  We can trivially satisfy that
689
       * requirement by changing the interpolation type to flat here.
690
       */
691
      producer_var->centroid = false;
692
      producer_var->interpolation = INTERP_QUALIFIER_FLAT;
693
 
694
      if (consumer_var) {
695
         consumer_var->centroid = false;
696
         consumer_var->interpolation = INTERP_QUALIFIER_FLAT;
697
      }
698
   }
699
 
700
   if (this->num_matches == this->matches_capacity) {
701
      this->matches_capacity *= 2;
702
      this->matches = (match *)
703
         realloc(this->matches,
704
                 sizeof(*this->matches) * this->matches_capacity);
705
   }
706
   this->matches[this->num_matches].packing_class
707
      = this->compute_packing_class(producer_var);
708
   this->matches[this->num_matches].packing_order
709
      = this->compute_packing_order(producer_var);
710
   if (this->disable_varying_packing) {
711
      unsigned slots = producer_var->type->is_array()
712
         ? (producer_var->type->length
713
            * producer_var->type->fields.array->matrix_columns)
714
         : producer_var->type->matrix_columns;
715
      this->matches[this->num_matches].num_components = 4 * slots;
716
   } else {
717
      this->matches[this->num_matches].num_components
718
         = producer_var->type->component_slots();
719
   }
720
   this->matches[this->num_matches].producer_var = producer_var;
721
   this->matches[this->num_matches].consumer_var = consumer_var;
722
   this->num_matches++;
723
   producer_var->is_unmatched_generic_inout = 0;
724
   if (consumer_var)
725
      consumer_var->is_unmatched_generic_inout = 0;
726
}
727
 
728
 
729
/**
730
 * Choose locations for all of the variable matches that were previously
731
 * passed to varying_matches::record().
732
 */
733
unsigned
734
varying_matches::assign_locations()
735
{
736
   /* Sort varying matches into an order that makes them easy to pack. */
737
   qsort(this->matches, this->num_matches, sizeof(*this->matches),
738
         &varying_matches::match_comparator);
739
 
740
   unsigned generic_location = 0;
741
 
742
   for (unsigned i = 0; i < this->num_matches; i++) {
743
      /* Advance to the next slot if this varying has a different packing
744
       * class than the previous one, and we're not already on a slot
745
       * boundary.
746
       */
747
      if (i > 0 &&
748
          this->matches[i - 1].packing_class
749
          != this->matches[i].packing_class) {
750
         generic_location = ALIGN(generic_location, 4);
751
      }
752
 
753
      this->matches[i].generic_location = generic_location;
754
 
755
      generic_location += this->matches[i].num_components;
756
   }
757
 
758
   return (generic_location + 3) / 4;
759
}
760
 
761
 
762
/**
763
 * Update the producer and consumer shaders to reflect the locations
764
 * assignments that were made by varying_matches::assign_locations().
765
 */
766
void
767
varying_matches::store_locations(unsigned producer_base,
768
                                 unsigned consumer_base) const
769
{
770
   for (unsigned i = 0; i < this->num_matches; i++) {
771
      ir_variable *producer_var = this->matches[i].producer_var;
772
      ir_variable *consumer_var = this->matches[i].consumer_var;
773
      unsigned generic_location = this->matches[i].generic_location;
774
      unsigned slot = generic_location / 4;
775
      unsigned offset = generic_location % 4;
776
 
777
      producer_var->location = producer_base + slot;
778
      producer_var->location_frac = offset;
779
      if (consumer_var) {
780
         assert(consumer_var->location == -1);
781
         consumer_var->location = consumer_base + slot;
782
         consumer_var->location_frac = offset;
783
      }
784
   }
785
}
786
 
787
 
788
/**
789
 * Compute the "packing class" of the given varying.  This is an unsigned
790
 * integer with the property that two variables in the same packing class can
791
 * be safely backed into the same vec4.
792
 */
793
unsigned
794
varying_matches::compute_packing_class(ir_variable *var)
795
{
796
   /* Without help from the back-end, there is no way to pack together
797
    * variables with different interpolation types, because
798
    * lower_packed_varyings must choose exactly one interpolation type for
799
    * each packed varying it creates.
800
    *
801
    * However, we can safely pack together floats, ints, and uints, because:
802
    *
803
    * - varyings of base type "int" and "uint" must use the "flat"
804
    *   interpolation type, which can only occur in GLSL 1.30 and above.
805
    *
806
    * - On platforms that support GLSL 1.30 and above, lower_packed_varyings
807
    *   can store flat floats as ints without losing any information (using
808
    *   the ir_unop_bitcast_* opcodes).
809
    *
810
    * Therefore, the packing class depends only on the interpolation type.
811
    */
812
   unsigned packing_class = var->centroid ? 1 : 0;
813
   packing_class *= 4;
814
   packing_class += var->interpolation;
815
   return packing_class;
816
}
817
 
818
 
819
/**
820
 * Compute the "packing order" of the given varying.  This is a sort key we
821
 * use to determine when to attempt to pack the given varying relative to
822
 * other varyings in the same packing class.
823
 */
824
varying_matches::packing_order_enum
825
varying_matches::compute_packing_order(ir_variable *var)
826
{
827
   const glsl_type *element_type = var->type;
828
 
829
   while (element_type->base_type == GLSL_TYPE_ARRAY) {
830
      element_type = element_type->fields.array;
831
   }
832
 
833
   switch (element_type->component_slots() % 4) {
834
   case 1: return PACKING_ORDER_SCALAR;
835
   case 2: return PACKING_ORDER_VEC2;
836
   case 3: return PACKING_ORDER_VEC3;
837
   case 0: return PACKING_ORDER_VEC4;
838
   default:
839
      assert(!"Unexpected value of vector_elements");
840
      return PACKING_ORDER_VEC4;
841
   }
842
}
843
 
844
 
845
/**
846
 * Comparison function passed to qsort() to sort varyings by packing_class and
847
 * then by packing_order.
848
 */
849
int
850
varying_matches::match_comparator(const void *x_generic, const void *y_generic)
851
{
852
   const match *x = (const match *) x_generic;
853
   const match *y = (const match *) y_generic;
854
 
855
   if (x->packing_class != y->packing_class)
856
      return x->packing_class - y->packing_class;
857
   return x->packing_order - y->packing_order;
858
}
859
 
860
 
861
/**
862
 * Is the given variable a varying variable to be counted against the
863
 * limit in ctx->Const.MaxVarying?
864
 * This includes variables such as texcoords, colors and generic
865
 * varyings, but excludes variables such as gl_FrontFacing and gl_FragCoord.
866
 */
867
static bool
868
is_varying_var(GLenum shaderType, const ir_variable *var)
869
{
870
   /* Only fragment shaders will take a varying variable as an input */
871
   if (shaderType == GL_FRAGMENT_SHADER &&
872
       var->mode == ir_var_shader_in) {
873
      switch (var->location) {
874
      case VARYING_SLOT_POS:
875
      case VARYING_SLOT_FACE:
876
      case VARYING_SLOT_PNTC:
877
         return false;
878
      default:
879
         return true;
880
      }
881
   }
882
   return false;
883
}
884
 
885
 
886
/**
887
 * Visitor class that generates tfeedback_candidate structs describing all
888
 * possible targets of transform feedback.
889
 *
890
 * tfeedback_candidate structs are stored in the hash table
891
 * tfeedback_candidates, which is passed to the constructor.  This hash table
892
 * maps varying names to instances of the tfeedback_candidate struct.
893
 */
894
class tfeedback_candidate_generator : public program_resource_visitor
895
{
896
public:
897
   tfeedback_candidate_generator(void *mem_ctx,
898
                                 hash_table *tfeedback_candidates)
899
      : mem_ctx(mem_ctx),
900
        tfeedback_candidates(tfeedback_candidates),
901
        toplevel_var(NULL),
902
        varying_floats(0)
903
   {
904
   }
905
 
906
   void process(ir_variable *var)
907
   {
908
      this->toplevel_var = var;
909
      this->varying_floats = 0;
910
      if (var->is_interface_instance())
911
         program_resource_visitor::process(var->interface_type,
912
                                           var->interface_type->name);
913
      else
914
         program_resource_visitor::process(var);
915
   }
916
 
917
private:
918
   virtual void visit_field(const glsl_type *type, const char *name,
919
                            bool row_major)
920
   {
921
      assert(!type->is_record());
922
      assert(!(type->is_array() && type->fields.array->is_record()));
923
      assert(!type->is_interface());
924
      assert(!(type->is_array() && type->fields.array->is_interface()));
925
 
926
      (void) row_major;
927
 
928
      tfeedback_candidate *candidate
929
         = rzalloc(this->mem_ctx, tfeedback_candidate);
930
      candidate->toplevel_var = this->toplevel_var;
931
      candidate->type = type;
932
      candidate->offset = this->varying_floats;
933
      hash_table_insert(this->tfeedback_candidates, candidate,
934
                        ralloc_strdup(this->mem_ctx, name));
935
      this->varying_floats += type->component_slots();
936
   }
937
 
938
   /**
939
    * Memory context used to allocate hash table keys and values.
940
    */
941
   void * const mem_ctx;
942
 
943
   /**
944
    * Hash table in which tfeedback_candidate objects should be stored.
945
    */
946
   hash_table * const tfeedback_candidates;
947
 
948
   /**
949
    * Pointer to the toplevel variable that is being traversed.
950
    */
951
   ir_variable *toplevel_var;
952
 
953
   /**
954
    * Total number of varying floats that have been visited so far.  This is
955
    * used to determine the offset to each varying within the toplevel
956
    * variable.
957
    */
958
   unsigned varying_floats;
959
};
960
 
961
 
962
/**
963
 * Assign locations for all variables that are produced in one pipeline stage
964
 * (the "producer") and consumed in the next stage (the "consumer").
965
 *
966
 * Variables produced by the producer may also be consumed by transform
967
 * feedback.
968
 *
969
 * \param num_tfeedback_decls is the number of declarations indicating
970
 *        variables that may be consumed by transform feedback.
971
 *
972
 * \param tfeedback_decls is a pointer to an array of tfeedback_decl objects
973
 *        representing the result of parsing the strings passed to
974
 *        glTransformFeedbackVaryings().  assign_location() will be called for
975
 *        each of these objects that matches one of the outputs of the
976
 *        producer.
977
 *
978
 * When num_tfeedback_decls is nonzero, it is permissible for the consumer to
979
 * be NULL.  In this case, varying locations are assigned solely based on the
980
 * requirements of transform feedback.
981
 */
982
bool
983
assign_varying_locations(struct gl_context *ctx,
984
			 void *mem_ctx,
985
			 struct gl_shader_program *prog,
986
			 gl_shader *producer, gl_shader *consumer,
987
                         unsigned num_tfeedback_decls,
988
                         tfeedback_decl *tfeedback_decls)
989
{
990
   const unsigned producer_base = VARYING_SLOT_VAR0;
991
   const unsigned consumer_base = VARYING_SLOT_VAR0;
992
   varying_matches matches(ctx->Const.DisableVaryingPacking,
993
                           consumer && consumer->Type == GL_FRAGMENT_SHADER);
994
   hash_table *tfeedback_candidates
995
      = hash_table_ctor(0, hash_table_string_hash, hash_table_string_compare);
996
   hash_table *consumer_inputs
997
      = hash_table_ctor(0, hash_table_string_hash, hash_table_string_compare);
998
   hash_table *consumer_interface_inputs
999
      = hash_table_ctor(0, hash_table_string_hash, hash_table_string_compare);
1000
 
1001
   /* Operate in a total of three passes.
1002
    *
1003
    * 1. Assign locations for any matching inputs and outputs.
1004
    *
1005
    * 2. Mark output variables in the producer that do not have locations as
1006
    *    not being outputs.  This lets the optimizer eliminate them.
1007
    *
1008
    * 3. Mark input variables in the consumer that do not have locations as
1009
    *    not being inputs.  This lets the optimizer eliminate them.
1010
    */
1011
 
1012
   if (consumer) {
1013
      foreach_list(node, consumer->ir) {
1014
         ir_variable *const input_var =
1015
            ((ir_instruction *) node)->as_variable();
1016
 
1017
         if ((input_var != NULL) && (input_var->mode == ir_var_shader_in)) {
1018
            if (input_var->interface_type != NULL) {
1019
               char *const iface_field_name =
1020
                  ralloc_asprintf(mem_ctx, "%s.%s",
1021
                                  input_var->interface_type->name,
1022
                                  input_var->name);
1023
               hash_table_insert(consumer_interface_inputs, input_var,
1024
                                 iface_field_name);
1025
            } else {
1026
               hash_table_insert(consumer_inputs, input_var,
1027
                                 ralloc_strdup(mem_ctx, input_var->name));
1028
            }
1029
         }
1030
      }
1031
   }
1032
 
1033
   foreach_list(node, producer->ir) {
1034
      ir_variable *const output_var = ((ir_instruction *) node)->as_variable();
1035
 
1036
      if ((output_var == NULL) || (output_var->mode != ir_var_shader_out))
1037
	 continue;
1038
 
1039
      tfeedback_candidate_generator g(mem_ctx, tfeedback_candidates);
1040
      g.process(output_var);
1041
 
1042
      ir_variable *input_var;
1043
      if (output_var->interface_type != NULL) {
1044
         char *const iface_field_name =
1045
            ralloc_asprintf(mem_ctx, "%s.%s",
1046
                            output_var->interface_type->name,
1047
                            output_var->name);
1048
         input_var =
1049
            (ir_variable *) hash_table_find(consumer_interface_inputs,
1050
                                            iface_field_name);
1051
      } else {
1052
         input_var =
1053
            (ir_variable *) hash_table_find(consumer_inputs, output_var->name);
1054
      }
1055
 
1056
      if (input_var && input_var->mode != ir_var_shader_in)
1057
         input_var = NULL;
1058
 
1059
      if (input_var) {
1060
         matches.record(output_var, input_var);
1061
      }
1062
   }
1063
 
1064
   for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
1065
      if (!tfeedback_decls[i].is_varying())
1066
         continue;
1067
 
1068
      const tfeedback_candidate *matched_candidate
1069
         = tfeedback_decls[i].find_candidate(prog, tfeedback_candidates);
1070
 
1071
      if (matched_candidate == NULL) {
1072
         hash_table_dtor(tfeedback_candidates);
1073
         hash_table_dtor(consumer_inputs);
1074
         hash_table_dtor(consumer_interface_inputs);
1075
         return false;
1076
      }
1077
 
1078
      if (matched_candidate->toplevel_var->is_unmatched_generic_inout)
1079
         matches.record(matched_candidate->toplevel_var, NULL);
1080
   }
1081
 
1082
   const unsigned slots_used = matches.assign_locations();
1083
   matches.store_locations(producer_base, consumer_base);
1084
 
1085
   for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
1086
      if (!tfeedback_decls[i].is_varying())
1087
         continue;
1088
 
1089
      if (!tfeedback_decls[i].assign_location(ctx, prog)) {
1090
         hash_table_dtor(tfeedback_candidates);
1091
         hash_table_dtor(consumer_inputs);
1092
         hash_table_dtor(consumer_interface_inputs);
1093
         return false;
1094
      }
1095
   }
1096
 
1097
   hash_table_dtor(tfeedback_candidates);
1098
   hash_table_dtor(consumer_inputs);
1099
   hash_table_dtor(consumer_interface_inputs);
1100
 
1101
   if (ctx->Const.DisableVaryingPacking) {
1102
      /* Transform feedback code assumes varyings are packed, so if the driver
1103
       * has disabled varying packing, make sure it does not support transform
1104
       * feedback.
1105
       */
1106
      assert(!ctx->Extensions.EXT_transform_feedback);
1107
   } else {
1108
      lower_packed_varyings(mem_ctx, producer_base, slots_used,
1109
                            ir_var_shader_out, producer);
1110
      if (consumer) {
1111
         lower_packed_varyings(mem_ctx, consumer_base, slots_used,
1112
                               ir_var_shader_in, consumer);
1113
      }
1114
   }
1115
 
1116
   if (consumer) {
1117
      foreach_list(node, consumer->ir) {
1118
         ir_variable *const var = ((ir_instruction *) node)->as_variable();
1119
 
1120
         if (var && var->mode == ir_var_shader_in &&
1121
             var->is_unmatched_generic_inout) {
1122
            if (prog->Version <= 120) {
1123
               /* On page 25 (page 31 of the PDF) of the GLSL 1.20 spec:
1124
                *
1125
                *     Only those varying variables used (i.e. read) in
1126
                *     the fragment shader executable must be written to
1127
                *     by the vertex shader executable; declaring
1128
                *     superfluous varying variables in a vertex shader is
1129
                *     permissible.
1130
                *
1131
                * We interpret this text as meaning that the VS must
1132
                * write the variable for the FS to read it.  See
1133
                * "glsl1-varying read but not written" in piglit.
1134
                */
1135
 
1136
               linker_error(prog, "%s shader varying %s not written "
1137
                            "by %s shader\n.",
1138
                            _mesa_glsl_shader_target_name(consumer->Type),
1139
			    var->name,
1140
                            _mesa_glsl_shader_target_name(producer->Type));
1141
            }
1142
 
1143
            /* An 'in' variable is only really a shader input if its
1144
             * value is written by the previous stage.
1145
             */
1146
            var->mode = ir_var_auto;
1147
         }
1148
      }
1149
   }
1150
 
1151
   return true;
1152
}
1153
 
1154
bool
1155
check_against_varying_limit(struct gl_context *ctx,
1156
                            struct gl_shader_program *prog,
1157
                            gl_shader *consumer)
1158
{
1159
   unsigned varying_vectors = 0;
1160
 
1161
   foreach_list(node, consumer->ir) {
1162
      ir_variable *const var = ((ir_instruction *) node)->as_variable();
1163
 
1164
      if (var && var->mode == ir_var_shader_in &&
1165
          is_varying_var(consumer->Type, var)) {
1166
         /* The packing rules used for vertex shader inputs are also
1167
          * used for fragment shader inputs.
1168
          */
1169
         varying_vectors += count_attribute_slots(var->type);
1170
      }
1171
   }
1172
 
1173
   if (ctx->API == API_OPENGLES2 || prog->IsES) {
1174
      if (varying_vectors > ctx->Const.MaxVarying) {
1175
         linker_error(prog, "shader uses too many varying vectors "
1176
                      "(%u > %u)\n",
1177
                      varying_vectors, ctx->Const.MaxVarying);
1178
         return false;
1179
      }
1180
   } else {
1181
      const unsigned float_components = varying_vectors * 4;
1182
      if (float_components > ctx->Const.MaxVarying * 4) {
1183
         linker_error(prog, "shader uses too many varying components "
1184
                      "(%u > %u)\n",
1185
                      float_components, ctx->Const.MaxVarying * 4);
1186
         return false;
1187
      }
1188
   }
1189
 
1190
   return true;
1191
}