OSDN Git Service

linker: Limit attribute allocation to MAX_VERTEX_ATTRIBS
[android-x86/external-mesa.git] / linker.cpp
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 linker.cpp
26  * GLSL linker implementation
27  *
28  * Given a set of shaders that are to be linked to generate a final program,
29  * there are three distinct stages.
30  *
31  * In the first stage shaders are partitioned into groups based on the shader
32  * type.  All shaders of a particular type (e.g., vertex shaders) are linked
33  * together.
34  *
35  *   - Undefined references in each shader are resolve to definitions in
36  *     another shader.
37  *   - Types and qualifiers of uniforms, outputs, and global variables defined
38  *     in multiple shaders with the same name are verified to be the same.
39  *   - Initializers for uniforms and global variables defined
40  *     in multiple shaders with the same name are verified to be the same.
41  *
42  * The result, in the terminology of the GLSL spec, is a set of shader
43  * executables for each processing unit.
44  *
45  * After the first stage is complete, a series of semantic checks are performed
46  * on each of the shader executables.
47  *
48  *   - Each shader executable must define a \c main function.
49  *   - Each vertex shader executable must write to \c gl_Position.
50  *   - Each fragment shader executable must write to either \c gl_FragData or
51  *     \c gl_FragColor.
52  *
53  * In the final stage individual shader executables are linked to create a
54  * complete exectuable.
55  *
56  *   - Types of uniforms defined in multiple shader stages with the same name
57  *     are verified to be the same.
58  *   - Initializers for uniforms defined in multiple shader stages with the
59  *     same name are verified to be the same.
60  *   - Types and qualifiers of outputs defined in one stage are verified to
61  *     be the same as the types and qualifiers of inputs defined with the same
62  *     name in a later stage.
63  *
64  * \author Ian Romanick <ian.d.romanick@intel.com>
65  */
66 #include <cstdlib>
67 #include <cstdio>
68
69 #include "main/mtypes.h"
70 #include "glsl_symbol_table.h"
71 #include "glsl_parser_extras.h"
72 #include "ir.h"
73 #include "ir_optimization.h"
74 #include "program.h"
75 #include "hash_table.h"
76
77 /**
78  * Visitor that determines whether or not a variable is ever written.
79  */
80 class find_assignment_visitor : public ir_hierarchical_visitor {
81 public:
82    find_assignment_visitor(const char *name)
83       : name(name), found(false)
84    {
85       /* empty */
86    }
87
88    virtual ir_visitor_status visit_enter(ir_assignment *ir)
89    {
90       ir_variable *const var = ir->lhs->variable_referenced();
91
92       if (strcmp(name, var->name) == 0) {
93          found = true;
94          return visit_stop;
95       }
96
97       return visit_continue_with_parent;
98    }
99
100    bool variable_found()
101    {
102       return found;
103    }
104
105 private:
106    const char *name;       /**< Find writes to a variable with this name. */
107    bool found;             /**< Was a write to the variable found? */
108 };
109
110
111 void
112 invalidate_variable_locations(glsl_shader *sh, enum ir_variable_mode mode,
113                               int generic_base)
114 {
115    foreach_list(node, &sh->ir) {
116       ir_variable *const var = ((ir_instruction *) node)->as_variable();
117
118       if ((var == NULL) || (var->mode != (unsigned) mode))
119          continue;
120
121       /* Only assign locations for generic attributes / varyings / etc.
122        */
123       if (var->location >= generic_base)
124           var->location = -1;
125    }
126 }
127
128
129 /**
130  * Determine the number of attribute slots required for a particular type
131  *
132  * This code is here because it implements the language rules of a specific
133  * GLSL version.  Since it's a property of the language and not a property of
134  * types in general, it doesn't really belong in glsl_type.
135  */
136 unsigned
137 count_attribute_slots(const glsl_type *t)
138 {
139    /* From page 31 (page 37 of the PDF) of the GLSL 1.50 spec:
140     *
141     *     "A scalar input counts the same amount against this limit as a vec4,
142     *     so applications may want to consider packing groups of four
143     *     unrelated float inputs together into a vector to better utilize the
144     *     capabilities of the underlying hardware. A matrix input will use up
145     *     multiple locations.  The number of locations used will equal the
146     *     number of columns in the matrix."
147     *
148     * The spec does not explicitly say how arrays are counted.  However, it
149     * should be safe to assume the total number of slots consumed by an array
150     * is the number of entries in the array multiplied by the number of slots
151     * consumed by a single element of the array.
152     */
153
154    if (t->is_array())
155       return t->array_size() * count_attribute_slots(t->element_type());
156
157    if (t->is_matrix())
158       return t->matrix_columns;
159
160    return 1;
161 }
162
163
164 /**
165  * Verify that a vertex shader executable meets all semantic requirements
166  *
167  * \param shader  Vertex shader executable to be verified
168  */
169 bool
170 validate_vertex_shader_executable(struct glsl_shader *shader)
171 {
172    if (shader == NULL)
173       return true;
174
175    if (!shader->symbols->get_function("main")) {
176       printf("error: vertex shader lacks `main'\n");
177       return false;
178    }
179
180    find_assignment_visitor find("gl_Position");
181    find.run(&shader->ir);
182    if (!find.variable_found()) {
183       printf("error: vertex shader does not write to `gl_Position'\n");
184       return false;
185    }
186
187    return true;
188 }
189
190
191 /**
192  * Verify that a fragment shader executable meets all semantic requirements
193  *
194  * \param shader  Fragment shader executable to be verified
195  */
196 bool
197 validate_fragment_shader_executable(struct glsl_shader *shader)
198 {
199    if (shader == NULL)
200       return true;
201
202    if (!shader->symbols->get_function("main")) {
203       printf("error: fragment shader lacks `main'\n");
204       return false;
205    }
206
207    find_assignment_visitor frag_color("gl_FragColor");
208    find_assignment_visitor frag_data("gl_FragData");
209
210    frag_color.run(&shader->ir);
211    frag_data.run(&shader->ir);
212
213    if (!frag_color.variable_found() && !frag_data.variable_found()) {
214       printf("error: fragment shader does not write to `gl_FragColor' or "
215              "`gl_FragData'\n");
216       return false;
217    }
218
219    if (frag_color.variable_found() && frag_data.variable_found()) {
220       printf("error: fragment shader write to both `gl_FragColor' and "
221              "`gl_FragData'\n");
222       return false;
223    }
224
225    return true;
226 }
227
228
229 /**
230  * Perform validation of uniforms used across multiple shader stages
231  */
232 bool
233 cross_validate_uniforms(struct glsl_shader **shaders, unsigned num_shaders)
234 {
235    /* Examine all of the uniforms in all of the shaders and cross validate
236     * them.
237     */
238    glsl_symbol_table uniforms;
239    for (unsigned i = 0; i < num_shaders; i++) {
240       foreach_list(node, &shaders[i]->ir) {
241          ir_variable *const var = ((ir_instruction *) node)->as_variable();
242
243          if ((var == NULL) || (var->mode != ir_var_uniform))
244             continue;
245
246          /* If a uniform with this name has already been seen, verify that the
247           * new instance has the same type.  In addition, if the uniforms have
248           * initializers, the values of the initializers must be the same.
249           */
250          ir_variable *const existing = uniforms.get_variable(var->name);
251          if (existing != NULL) {
252             if (var->type != existing->type) {
253                printf("error: uniform `%s' declared as type `%s' and "
254                       "type `%s'\n",
255                       var->name, var->type->name, existing->type->name);
256                return false;
257             }
258
259             if (var->constant_value != NULL) {
260                if (existing->constant_value != NULL) {
261                   if (!var->constant_value->has_value(existing->constant_value)) {
262                      printf("error: initializers for uniform `%s' have "
263                             "differing values\n",
264                             var->name);
265                      return false;
266                   }
267                } else
268                   /* If the first-seen instance of a particular uniform did not
269                    * have an initializer but a later instance does, copy the
270                    * initializer to the version stored in the symbol table.
271                    */
272                   existing->constant_value = var->constant_value->clone();
273             }
274          } else
275             uniforms.add_variable(var->name, var);
276       }
277    }
278
279    return true;
280 }
281
282
283 /**
284  * Validate that outputs from one stage match inputs of another
285  */
286 bool
287 cross_validate_outputs_to_inputs(glsl_shader *producer, glsl_shader *consumer)
288 {
289    glsl_symbol_table parameters;
290    /* FINISHME: Figure these out dynamically. */
291    const char *const producer_stage = "vertex";
292    const char *const consumer_stage = "fragment";
293
294    /* Find all shader outputs in the "producer" stage.
295     */
296    foreach_list(node, &producer->ir) {
297       ir_variable *const var = ((ir_instruction *) node)->as_variable();
298
299       /* FINISHME: For geometry shaders, this should also look for inout
300        * FINISHME: variables.
301        */
302       if ((var == NULL) || (var->mode != ir_var_out))
303          continue;
304
305       parameters.add_variable(var->name, var);
306    }
307
308
309    /* Find all shader inputs in the "consumer" stage.  Any variables that have
310     * matching outputs already in the symbol table must have the same type and
311     * qualifiers.
312     */
313    foreach_list(node, &consumer->ir) {
314       ir_variable *const input = ((ir_instruction *) node)->as_variable();
315
316       /* FINISHME: For geometry shaders, this should also look for inout
317        * FINISHME: variables.
318        */
319       if ((input == NULL) || (input->mode != ir_var_in))
320          continue;
321
322       ir_variable *const output = parameters.get_variable(input->name);
323       if (output != NULL) {
324          /* Check that the types match between stages.
325           */
326          if (input->type != output->type) {
327             printf("error: %s shader output `%s' delcared as type `%s', but "
328                    "%s shader input declared as type `%s'\n",
329                    producer_stage, output->name, output->type->name,
330                    consumer_stage, input->type->name);
331             return false;
332          }
333
334          /* Check that all of the qualifiers match between stages.
335           */
336          if (input->centroid != output->centroid) {
337             printf("error: %s shader output `%s' %s centroid qualifier, but "
338                    "%s shader input %s centroid qualifier\n",
339                    producer_stage,
340                    output->name,
341                    (output->centroid) ? "has" : "lacks",
342                    consumer_stage,
343                    (input->centroid) ? "has" : "lacks");
344             return false;
345          }
346
347          if (input->invariant != output->invariant) {
348             printf("error: %s shader output `%s' %s invariant qualifier, but "
349                    "%s shader input %s invariant qualifier\n",
350                    producer_stage,
351                    output->name,
352                    (output->invariant) ? "has" : "lacks",
353                    consumer_stage,
354                    (input->invariant) ? "has" : "lacks");
355             return false;
356          }
357
358          if (input->interpolation != output->interpolation) {
359             printf("error: %s shader output `%s' specifies %s interpolation "
360                    "qualifier, "
361                    "but %s shader input specifies %s interpolation "
362                    "qualifier\n",
363                    producer_stage,
364                    output->name,
365                    output->interpolation_string(),
366                    consumer_stage,
367                    input->interpolation_string());
368             return false;
369          }
370       }
371    }
372
373    return true;
374 }
375
376
377 struct uniform_node {
378    exec_node link;
379    struct gl_uniform *u;
380    unsigned slots;
381 };
382
383 void
384 assign_uniform_locations(struct glsl_program *prog)
385 {
386    /* */
387    exec_list uniforms;
388    unsigned total_uniforms = 0;
389    hash_table *ht = hash_table_ctor(32, hash_table_string_hash,
390                                     hash_table_string_compare);
391
392    for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
393       unsigned next_position = 0;
394
395       foreach_list(node, &prog->_LinkedShaders[i]->ir) {
396          ir_variable *const var = ((ir_instruction *) node)->as_variable();
397
398          if ((var == NULL) || (var->mode != ir_var_uniform))
399             continue;
400
401          const unsigned vec4_slots = (var->component_slots() + 3) / 4;
402          assert(vec4_slots != 0);
403
404          uniform_node *n = (uniform_node *) hash_table_find(ht, var->name);
405          if (n == NULL) {
406             n = (uniform_node *) calloc(1, sizeof(struct uniform_node));
407             n->u = (gl_uniform *) calloc(vec4_slots, sizeof(struct gl_uniform));
408             n->slots = vec4_slots;
409
410             n->u[0].Name = strdup(var->name);
411             for (unsigned j = 1; j < vec4_slots; j++)
412                n->u[j].Name = n->u[0].Name;
413
414             hash_table_insert(ht, n, n->u[0].Name);
415             uniforms.push_tail(& n->link);
416             total_uniforms += vec4_slots;
417          }
418
419          if (var->constant_value != NULL)
420             for (unsigned j = 0; j < vec4_slots; j++)
421                n->u[j].Initialized = true;
422
423          var->location = next_position;
424
425          for (unsigned j = 0; j < vec4_slots; j++) {
426             switch (prog->_LinkedShaders[i]->Type) {
427             case GL_VERTEX_SHADER:
428                n->u[j].VertPos = next_position;
429                break;
430             case GL_FRAGMENT_SHADER:
431                n->u[j].FragPos = next_position;
432                break;
433             case GL_GEOMETRY_SHADER:
434                /* FINISHME: Support geometry shaders. */
435                assert(prog->_LinkedShaders[i]->Type != GL_GEOMETRY_SHADER);
436                break;
437             }
438
439             next_position++;
440          }
441       }
442    }
443
444    gl_uniform_list *ul = (gl_uniform_list *)
445       calloc(1, sizeof(gl_uniform_list));
446
447    ul->Size = total_uniforms;
448    ul->NumUniforms = total_uniforms;
449    ul->Uniforms = (gl_uniform *) calloc(total_uniforms, sizeof(gl_uniform));
450
451    unsigned idx = 0;
452    uniform_node *next;
453    for (uniform_node *node = (uniform_node *) uniforms.head
454            ; node->link.next != NULL
455            ; node = next) {
456       next = (uniform_node *) node->link.next;
457
458       node->link.remove();
459       memcpy(&ul->Uniforms[idx], node->u, sizeof(gl_uniform) * node->slots);
460       idx += node->slots;
461
462       free(node->u);
463       free(node);
464    }
465
466    hash_table_dtor(ht);
467
468    prog->Uniforms = ul;
469 }
470
471
472 /**
473  * Find a contiguous set of available bits in a bitmask
474  *
475  * \param used_mask     Bits representing used (1) and unused (0) locations
476  * \param needed_count  Number of contiguous bits needed.
477  *
478  * \return
479  * Base location of the available bits on success or -1 on failure.
480  */
481 int
482 find_available_slots(unsigned used_mask, unsigned needed_count)
483 {
484    unsigned needed_mask = (1 << needed_count) - 1;
485    const int max_bit_to_test = (8 * sizeof(used_mask)) - needed_count;
486
487    /* The comparison to 32 is redundant, but without it GCC emits "warning:
488     * cannot optimize possibly infinite loops" for the loop below.
489     */
490    if ((needed_count == 0) || (max_bit_to_test < 0) || (max_bit_to_test > 32))
491       return -1;
492
493    for (int i = 0; i <= max_bit_to_test; i++) {
494       if ((needed_mask & ~used_mask) == needed_mask)
495          return i;
496
497       needed_mask <<= 1;
498    }
499
500    return -1;
501 }
502
503
504 bool
505 assign_attribute_locations(glsl_shader *sh,
506                            struct gl_program_parameter_list *attrib,
507                            unsigned max_attribute_index)
508 {
509    /* Mark invalid attribute locations as being used.
510     */
511    unsigned used_locations = (max_attribute_index >= 32)
512       ? ~0 : ~((1 << max_attribute_index) - 1);
513
514    assert(sh->Type == GL_VERTEX_SHADER);
515
516    /* Operate in a total of four passes.
517     *
518     * 1. Invalidate the location assignments for all vertex shader inputs.
519     *
520     * 2. Assign locations for inputs that have user-defined (via
521     *    glBindVertexAttribLocation) locatoins.
522     *
523     * 3. Sort the attributes without assigned locations by number of slots
524     *    required in decreasing order.  Fragmentation caused by attribute
525     *    locations assigned by the application may prevent large attributes
526     *    from having enough contiguous space.
527     *
528     * 4. Assign locations to any inputs without assigned locations.
529     */
530
531    invalidate_variable_locations(sh, ir_var_in, VERT_ATTRIB_GENERIC0);
532
533    if (attrib != NULL) {
534       for (unsigned i = 0; i < attrib->NumParameters; i++) {
535          ir_variable *const var =
536             sh->symbols->get_variable(attrib->Parameters[i].Name);
537
538          /* Note: attributes that occupy multiple slots, such as arrays or
539           * matrices, may appear in the attrib array multiple times.
540           */
541          if ((var == NULL) || (var->location != -1))
542             continue;
543
544          /* From page 61 of the OpenGL 4.0 spec:
545           *
546           *     "LinkProgram will fail if the attribute bindings assigned by
547           *     BindAttribLocation do not leave not enough space to assign a
548           *     location for an active matrix attribute or an active attribute
549           *     array, both of which require multiple contiguous generic
550           *     attributes."
551           *
552           * Previous versions of the spec contain similar language but omit the
553           * bit about attribute arrays.
554           *
555           * Page 61 of the OpenGL 4.0 spec also says:
556           *
557           *     "It is possible for an application to bind more than one
558           *     attribute name to the same location. This is referred to as
559           *     aliasing. This will only work if only one of the aliased
560           *     attributes is active in the executable program, or if no path
561           *     through the shader consumes more than one attribute of a set
562           *     of attributes aliased to the same location. A link error can
563           *     occur if the linker determines that every path through the
564           *     shader consumes multiple aliased attributes, but
565           *     implementations are not required to generate an error in this
566           *     case."
567           *
568           * These two paragraphs are either somewhat contradictory, or I don't
569           * fully understand one or both of them.
570           */
571          /* FINISHME: The code as currently written does not support attribute
572           * FINISHME: location aliasing (see comment above).
573           */
574          const int attr = attrib->Parameters[i].StateIndexes[0];
575          const unsigned slots = count_attribute_slots(var->type);
576
577          /* Mask representing the contiguous slots that will be used by this
578           * attribute.
579           */
580          const unsigned use_mask = (1 << slots) - 1;
581
582          /* Generate a link error if the set of bits requested for this
583           * attribute overlaps any previously allocated bits.
584           */
585          if ((~(use_mask << attr) & used_locations) != used_locations) {
586             printf("error: insufficient contiguous attribute locations "
587                    "available for vertex shader input `%s'",
588                    var->name);
589             return false;
590          }
591
592          var->location = VERT_ATTRIB_GENERIC0 + attr;
593          used_locations |= (use_mask << attr);
594       }
595    }
596
597    /* Temporary storage for the set of attributes that need locations assigned.
598     */
599    struct temp_attr {
600       unsigned slots;
601       ir_variable *var;
602
603       /* Used below in the call to qsort. */
604       static int compare(const void *a, const void *b)
605       {
606          const temp_attr *const l = (const temp_attr *) a;
607          const temp_attr *const r = (const temp_attr *) b;
608
609          /* Reversed because we want a descending order sort below. */
610          return r->slots - l->slots;
611       }
612    } to_assign[16];
613
614    unsigned num_attr = 0;
615
616    foreach_list(node, &sh->ir) {
617       ir_variable *const var = ((ir_instruction *) node)->as_variable();
618
619       if ((var == NULL) || (var->mode != ir_var_in))
620          continue;
621
622       /* The location was explicitly assigned, nothing to do here.
623        */
624       if (var->location != -1)
625          continue;
626
627       to_assign[num_attr].slots = count_attribute_slots(var->type);
628       to_assign[num_attr].var = var;
629       num_attr++;
630    }
631
632    /* If all of the attributes were assigned locations by the application (or
633     * are built-in attributes with fixed locations), return early.  This should
634     * be the common case.
635     */
636    if (num_attr == 0)
637       return true;
638
639    qsort(to_assign, num_attr, sizeof(to_assign[0]), temp_attr::compare);
640
641    for (unsigned i = 0; i < num_attr; i++) {
642       /* Mask representing the contiguous slots that will be used by this
643        * attribute.
644        */
645       const unsigned use_mask = (1 << to_assign[i].slots) - 1;
646
647       int location = find_available_slots(used_locations, to_assign[i].slots);
648
649       if (location < 0) {
650          printf("error: insufficient contiguous attribute locations "
651                 "available for vertex shader input `%s'",
652                 to_assign[i].var->name);
653          return false;
654       }
655
656       to_assign[i].var->location = VERT_ATTRIB_GENERIC0 + location;
657       used_locations |= (use_mask << location);
658    }
659
660    return true;
661 }
662
663
664 void
665 link_shaders(struct glsl_program *prog)
666 {
667    prog->LinkStatus = false;
668    prog->Validated = false;
669    prog->_Used = false;
670
671    /* Separate the shaders into groups based on their type.
672     */
673    struct glsl_shader **vert_shader_list;
674    unsigned num_vert_shaders = 0;
675    struct glsl_shader **frag_shader_list;
676    unsigned num_frag_shaders = 0;
677
678    vert_shader_list = (struct glsl_shader **)
679       calloc(2 * prog->NumShaders, sizeof(struct glsl_shader *));
680    frag_shader_list =  &vert_shader_list[prog->NumShaders];
681
682    for (unsigned i = 0; i < prog->NumShaders; i++) {
683       switch (prog->Shaders[i]->Type) {
684       case GL_VERTEX_SHADER:
685          vert_shader_list[num_vert_shaders] = prog->Shaders[i];
686          num_vert_shaders++;
687          break;
688       case GL_FRAGMENT_SHADER:
689          frag_shader_list[num_frag_shaders] = prog->Shaders[i];
690          num_frag_shaders++;
691          break;
692       case GL_GEOMETRY_SHADER:
693          /* FINISHME: Support geometry shaders. */
694          assert(prog->Shaders[i]->Type != GL_GEOMETRY_SHADER);
695          break;
696       }
697    }
698
699    /* FINISHME: Implement intra-stage linking. */
700    assert(num_vert_shaders <= 1);
701    assert(num_frag_shaders <= 1);
702
703    /* Verify that each of the per-target executables is valid.
704     */
705    if (!validate_vertex_shader_executable(vert_shader_list[0])
706        || !validate_fragment_shader_executable(frag_shader_list[0]))
707       goto done;
708
709
710    /* FINISHME: Perform inter-stage linking. */
711    prog->_LinkedShaders = (struct glsl_shader **)
712       calloc(2, sizeof(struct glsl_shader *));
713    prog->_NumLinkedShaders = 0;
714
715    if (num_vert_shaders > 0) {
716       prog->_LinkedShaders[prog->_NumLinkedShaders] = vert_shader_list[0];
717       prog->_NumLinkedShaders++;
718    }
719
720    if (num_frag_shaders > 0) {
721       prog->_LinkedShaders[prog->_NumLinkedShaders] = frag_shader_list[0];
722       prog->_NumLinkedShaders++;
723    }
724
725    if (cross_validate_uniforms(prog->_LinkedShaders, prog->_NumLinkedShaders)) {
726       /* Validate the inputs of each stage with the output of the preceeding
727        * stage.
728        */
729       for (unsigned i = 1; i < prog->_NumLinkedShaders; i++) {
730          if (!cross_validate_outputs_to_inputs(prog->_LinkedShaders[i - 1],
731                                                prog->_LinkedShaders[i]))
732             goto done;
733       }
734
735       prog->LinkStatus = true;
736    }
737
738    /* FINISHME: Perform whole-program optimization here. */
739
740    assign_uniform_locations(prog);
741
742    if (prog->_LinkedShaders[0]->Type == GL_VERTEX_SHADER)
743       /* FINISHME: The value of the max_attribute_index parameter is
744        * FINISHME: implementation dependent based on the value of
745        * FINISHME: GL_MAX_VERTEX_ATTRIBS.  GL_MAX_VERTEX_ATTRIBS must be
746        * FINISHME: at least 16, so hardcode 16 for now.
747        */
748       if (!assign_attribute_locations(prog->_LinkedShaders[0],
749                                       prog->Attributes,
750                                       16))
751          goto done;
752
753    /* FINISHME: Assign vertex shader output / fragment shader input
754     * FINISHME: locations.
755     */
756
757    /* FINISHME: Assign fragment shader output locations. */
758
759    /* FINISHME: Generate code here. */
760
761 done:
762    free(vert_shader_list);
763 }