1f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/*
2f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Copyright © 2010 Intel Corporation
3f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
4f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Permission is hereby granted, free of charge, to any person obtaining a
5f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * copy of this software and associated documentation files (the "Software"),
6f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * to deal in the Software without restriction, including without limitation
7f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * and/or sell copies of the Software, and to permit persons to whom the
9f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Software is furnished to do so, subject to the following conditions:
10f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
11f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The above copyright notice and this permission notice (including the next
12f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * paragraph) shall be included in all copies or substantial portions of the
13f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Software.
14f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
15f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * DEALINGS IN THE SOFTWARE.
22f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
23f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
24f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
25f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \file linker.cpp
26f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * GLSL linker implementation
27f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
28f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Given a set of shaders that are to be linked to generate a final program,
29f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * there are three distinct stages.
30f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
31f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * In the first stage shaders are partitioned into groups based on the shader
32f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * type.  All shaders of a particular type (e.g., vertex shaders) are linked
33f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * together.
34f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
35f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *   - Undefined references in each shader are resolve to definitions in
36f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *     another shader.
37f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *   - Types and qualifiers of uniforms, outputs, and global variables defined
38f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *     in multiple shaders with the same name are verified to be the same.
39f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *   - Initializers for uniforms and global variables defined
40f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *     in multiple shaders with the same name are verified to be the same.
41f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
42f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The result, in the terminology of the GLSL spec, is a set of shader
43f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * executables for each processing unit.
44f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
45f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * After the first stage is complete, a series of semantic checks are performed
46f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * on each of the shader executables.
47f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
48f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *   - Each shader executable must define a \c main function.
49f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *   - Each vertex shader executable must write to \c gl_Position.
50f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *   - Each fragment shader executable must write to either \c gl_FragData or
51f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *     \c gl_FragColor.
52f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
53f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * In the final stage individual shader executables are linked to create a
54f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * complete exectuable.
55f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
56f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *   - Types of uniforms defined in multiple shader stages with the same name
57f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *     are verified to be the same.
58f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *   - Initializers for uniforms defined in multiple shader stages with the
59f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *     same name are verified to be the same.
60f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *   - Types and qualifiers of outputs defined in one stage are verified to
61f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *     be the same as the types and qualifiers of inputs defined with the same
62f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *     name in a later stage.
63f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
64f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \author Ian Romanick <ian.d.romanick@intel.com>
65f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
66f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
67f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "main/core.h"
68f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "glsl_symbol_table.h"
69f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "ir.h"
70f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "program.h"
71f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "program/hash_table.h"
72f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "linker.h"
73f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "ir_optimization.h"
74f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
75f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgextern "C" {
76f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#include "main/shaderobj.h"
77f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
78f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
79f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
80f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Visitor that determines whether or not a variable is ever written.
81f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
82f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass find_assignment_visitor : public ir_hierarchical_visitor {
83f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpublic:
84f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   find_assignment_visitor(const char *name)
85f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      : name(name), found(false)
86f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   {
87f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* empty */
88f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
89f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
90f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_enter(ir_assignment *ir)
91f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   {
92f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_variable *const var = ir->lhs->variable_referenced();
93f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
94f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (strcmp(name, var->name) == 0) {
95f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 found = true;
96f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return visit_stop;
97f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
98f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
99f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return visit_continue_with_parent;
100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit_enter(ir_call *ir)
103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   {
104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      exec_list_iterator sig_iter = ir->callee->parameters.iterator();
105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      foreach_iter(exec_list_iterator, iter, *ir) {
106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_rvalue *param_rval = (ir_rvalue *)iter.get();
107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_variable *sig_param = (ir_variable *)sig_iter.get();
108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (sig_param->mode == ir_var_out ||
110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     sig_param->mode == ir_var_inout) {
111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    ir_variable *var = param_rval->variable_referenced();
112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    if (var && strcmp(name, var->name) == 0) {
113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       found = true;
114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       return visit_stop;
115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    }
116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 }
117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 sig_iter.next();
118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (ir->return_deref != NULL) {
121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_variable *const var = ir->return_deref->variable_referenced();
122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (strcmp(name, var->name) == 0) {
124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    found = true;
125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    return visit_stop;
126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 }
127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return visit_continue_with_parent;
130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bool variable_found()
133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   {
134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return found;
135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgprivate:
138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const char *name;       /**< Find writes to a variable with this name. */
139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bool found;             /**< Was a write to the variable found? */
140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Visitor that determines whether or not a variable is ever read.
145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass find_deref_visitor : public ir_hierarchical_visitor {
147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpublic:
148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   find_deref_visitor(const char *name)
149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      : name(name), found(false)
150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   {
151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* empty */
152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit(ir_dereference_variable *ir)
155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   {
156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (strcmp(this->name, ir->var->name) == 0) {
157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 this->found = true;
158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return visit_stop;
159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return visit_continue;
162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bool variable_found() const
165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   {
166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return this->found;
167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgprivate:
170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const char *name;       /**< Find writes to a variable with this name. */
171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bool found;             /**< Was a write to the variable found? */
172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orglinker_error(gl_shader_program *prog, const char *fmt, ...)
177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   va_list ap;
179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ralloc_strcat(&prog->InfoLog, "error: ");
181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   va_start(ap, fmt);
182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ralloc_vasprintf_append(&prog->InfoLog, fmt, ap);
183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   va_end(ap);
184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   prog->LinkStatus = false;
186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orglinker_warning(gl_shader_program *prog, const char *fmt, ...)
191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   va_list ap;
193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ralloc_strcat(&prog->InfoLog, "error: ");
195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   va_start(ap, fmt);
196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ralloc_vasprintf_append(&prog->InfoLog, fmt, ap);
197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   va_end(ap);
198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orglink_invalidate_variable_locations(gl_shader *sh, enum ir_variable_mode mode,
204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				   int generic_base)
205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   foreach_list(node, sh->ir) {
207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_variable *const var = ((ir_instruction *) node)->as_variable();
208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if ((var == NULL) || (var->mode != (unsigned) mode))
210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 continue;
211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* Only assign locations for generic attributes / varyings / etc.
213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       */
214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if ((var->location >= generic_base) && !var->explicit_location)
215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	  var->location = -1;
216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Determine the number of attribute slots required for a particular type
222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * This code is here because it implements the language rules of a specific
224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * GLSL version.  Since it's a property of the language and not a property of
225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * types in general, it doesn't really belong in glsl_type.
226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgunsigned
228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgcount_attribute_slots(const glsl_type *t)
229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* From page 31 (page 37 of the PDF) of the GLSL 1.50 spec:
231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *
232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *     "A scalar input counts the same amount against this limit as a vec4,
233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *     so applications may want to consider packing groups of four
234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *     unrelated float inputs together into a vector to better utilize the
235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *     capabilities of the underlying hardware. A matrix input will use up
236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *     multiple locations.  The number of locations used will equal the
237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *     number of columns in the matrix."
238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *
239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * The spec does not explicitly say how arrays are counted.  However, it
240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * should be safe to assume the total number of slots consumed by an array
241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * is the number of entries in the array multiplied by the number of slots
242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * consumed by a single element of the array.
243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (t->is_array())
246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return t->array_size() * count_attribute_slots(t->element_type());
247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (t->is_matrix())
249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return t->matrix_columns;
250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return 1;
252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Verify that a vertex shader executable meets all semantic requirements.
257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Also sets prog->Vert.UsesClipDistance and prog->Vert.ClipDistanceArraySize
259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * as a side effect.
260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param shader  Vertex shader executable to be verified
262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool
264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvalidate_vertex_shader_executable(struct gl_shader_program *prog,
265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				  struct gl_shader *shader)
266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (shader == NULL)
268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return true;
269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* From the GLSL 1.10 spec, page 48:
271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *
272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *     "The variable gl_Position is available only in the vertex
273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *      language and is intended for writing the homogeneous vertex
274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *      position. All executions of a well-formed vertex shader
275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *      executable must write a value into this variable. [...] The
276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *      variable gl_Position is available only in the vertex
277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *      language and is intended for writing the homogeneous vertex
278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *      position. All executions of a well-formed vertex shader
279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *      executable must write a value into this variable."
280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *
281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * while in GLSL 1.40 this text is changed to:
282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *
283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *     "The variable gl_Position is available only in the vertex
284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *      language and is intended for writing the homogeneous vertex
285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *      position. It can be written at any time during shader
286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *      execution. It may also be read back by a vertex shader
287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *      after being written. This value will be used by primitive
288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *      assembly, clipping, culling, and other fixed functionality
289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *      operations, if present, that operate on primitives after
290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *      vertex processing has occurred. Its value is undefined if
291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *      the vertex shader executable does not write gl_Position."
292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (prog->Version < 140) {
294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      find_assignment_visitor find("gl_Position");
295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      find.run(shader->ir);
296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!find.variable_found()) {
297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 linker_error(prog, "vertex shader does not write to `gl_Position'\n");
298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return false;
299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   prog->Vert.ClipDistanceArraySize = 0;
303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (prog->Version >= 130) {
305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* From section 7.1 (Vertex Shader Special Variables) of the
306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * GLSL 1.30 spec:
307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       *
308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       *   "It is an error for a shader to statically write both
309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       *   gl_ClipVertex and gl_ClipDistance."
310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       */
311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      find_assignment_visitor clip_vertex("gl_ClipVertex");
312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      find_assignment_visitor clip_distance("gl_ClipDistance");
313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      clip_vertex.run(shader->ir);
315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      clip_distance.run(shader->ir);
316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (clip_vertex.variable_found() && clip_distance.variable_found()) {
317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         linker_error(prog, "vertex shader writes to both `gl_ClipVertex' "
318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                      "and `gl_ClipDistance'\n");
319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return false;
320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      prog->Vert.UsesClipDistance = clip_distance.variable_found();
322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_variable *clip_distance_var =
323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         shader->symbols->get_variable("gl_ClipDistance");
324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (clip_distance_var)
325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         prog->Vert.ClipDistanceArraySize = clip_distance_var->type->length;
326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return true;
329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Verify that a fragment shader executable meets all semantic requirements
334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param shader  Fragment shader executable to be verified
336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool
338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvalidate_fragment_shader_executable(struct gl_shader_program *prog,
339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				    struct gl_shader *shader)
340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (shader == NULL)
342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return true;
343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   find_assignment_visitor frag_color("gl_FragColor");
345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   find_assignment_visitor frag_data("gl_FragData");
346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   frag_color.run(shader->ir);
348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   frag_data.run(shader->ir);
349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (frag_color.variable_found() && frag_data.variable_found()) {
351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      linker_error(prog,  "fragment shader writes to both "
352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		   "`gl_FragColor' and `gl_FragData'\n");
353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return false;
354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return true;
357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Generate a string describing the mode of a variable
362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic const char *
364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgmode_string(const ir_variable *var)
365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   switch (var->mode) {
367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case ir_var_auto:
368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return (var->read_only) ? "global constant" : "global variable";
369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case ir_var_uniform: return "uniform";
371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case ir_var_in:      return "shader input";
372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case ir_var_out:     return "shader output";
373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case ir_var_inout:   return "shader inout";
374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case ir_var_const_in:
376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   case ir_var_temporary:
377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   default:
378f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      assert(!"Should not get here.");
379f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return "invalid variable";
380f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
381f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
382f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
383f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
384f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
385f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Perform validation of global variables used across multiple shaders
386f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
387f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool
388f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgcross_validate_globals(struct gl_shader_program *prog,
389f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		       struct gl_shader **shader_list,
390f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		       unsigned num_shaders,
391f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		       bool uniforms_only)
392f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
393f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Examine all of the uniforms in all of the shaders and cross validate
394f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * them.
395f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
396f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   glsl_symbol_table variables;
397f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (unsigned i = 0; i < num_shaders; i++) {
398f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (shader_list[i] == NULL)
399f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 continue;
400f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
401f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      foreach_list(node, shader_list[i]->ir) {
402f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_variable *const var = ((ir_instruction *) node)->as_variable();
403f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
404f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (var == NULL)
405f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    continue;
406f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
407f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (uniforms_only && (var->mode != ir_var_uniform))
408f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    continue;
409f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
410f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 /* Don't cross validate temporaries that are at global scope.  These
411f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	  * will eventually get pulled into the shaders 'main'.
412f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	  */
413f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (var->mode == ir_var_temporary)
414f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    continue;
415f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
416f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 /* If a global with this name has already been seen, verify that the
417f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	  * new instance has the same type.  In addition, if the globals have
418f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	  * initializers, the values of the initializers must be the same.
419f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	  */
420f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_variable *const existing = variables.get_variable(var->name);
421f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (existing != NULL) {
422f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    if (var->type != existing->type) {
423f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       /* Consider the types to be "the same" if both types are arrays
424f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		* of the same type and one of the arrays is implicitly sized.
425f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		* In addition, set the type of the linked variable to the
426f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		* explicitly sized array.
427f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		*/
428f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       if (var->type->is_array()
429f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		   && existing->type->is_array()
430f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		   && (var->type->fields.array == existing->type->fields.array)
431f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		   && ((var->type->length == 0)
432f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		       || (existing->type->length == 0))) {
433f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		  if (var->type->length != 0) {
434f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		     existing->type = var->type;
435f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		  }
436f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       } else {
437f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		  linker_error(prog, "%s `%s' declared as type "
438f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       "`%s' and type `%s'\n",
439f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       mode_string(var),
440f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       var->name, var->type->name,
441f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       existing->type->name);
442f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		  return false;
443f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       }
444f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    }
445f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
446f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    if (var->explicit_location) {
447f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       if (existing->explicit_location
448f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		   && (var->location != existing->location)) {
449f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		     linker_error(prog, "explicit locations for %s "
450f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				  "`%s' have differing values\n",
451f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				  mode_string(var), var->name);
452f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		     return false;
453f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       }
454f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
455f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       existing->location = var->location;
456f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       existing->explicit_location = true;
457f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    }
458f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
459f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    /* Validate layout qualifiers for gl_FragDepth.
460f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *
461f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * From the AMD/ARB_conservative_depth specs:
462f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *
463f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *    "If gl_FragDepth is redeclared in any fragment shader in a
464f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *    program, it must be redeclared in all fragment shaders in
465f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *    that program that have static assignments to
466f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *    gl_FragDepth. All redeclarations of gl_FragDepth in all
467f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *    fragment shaders in a single program must have the same set
468f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *    of qualifiers."
469f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     */
470f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    if (strcmp(var->name, "gl_FragDepth") == 0) {
471f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       bool layout_declared = var->depth_layout != ir_depth_layout_none;
472f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       bool layout_differs =
473f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		  var->depth_layout != existing->depth_layout;
474f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
475f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       if (layout_declared && layout_differs) {
476f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		  linker_error(prog,
477f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       "All redeclarations of gl_FragDepth in all "
478f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       "fragment shaders in a single program must have "
479f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       "the same set of qualifiers.");
480f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       }
481f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
482f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       if (var->used && layout_differs) {
483f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		  linker_error(prog,
484f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       "If gl_FragDepth is redeclared with a layout "
485f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       "qualifier in any fragment shader, it must be "
486f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       "redeclared with the same layout qualifier in "
487f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       "all fragment shaders that have assignments to "
488f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       "gl_FragDepth");
489f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       }
490f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    }
491f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
492f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    /* Page 35 (page 41 of the PDF) of the GLSL 4.20 spec says:
493f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *
494f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *     "If a shared global has multiple initializers, the
495f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *     initializers must all be constant expressions, and they
496f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *     must all have the same value. Otherwise, a link error will
497f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *     result. (A shared global having only one initializer does
498f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *     not require that initializer to be a constant expression.)"
499f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *
500f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * Previous to 4.20 the GLSL spec simply said that initializers
501f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * must have the same value.  In this case of non-constant
502f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * initializers, this was impossible to determine.  As a result,
503f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * no vendor actually implemented that behavior.  The 4.20
504f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * behavior matches the implemented behavior of at least one other
505f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * vendor, so we'll implement that for all GLSL versions.
506f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     */
507f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    if (var->constant_initializer != NULL) {
508f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       if (existing->constant_initializer != NULL) {
509f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		  if (!var->constant_initializer->has_value(existing->constant_initializer)) {
510f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		     linker_error(prog, "initializers for %s "
511f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				  "`%s' have differing values\n",
512f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				  mode_string(var), var->name);
513f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		     return false;
514f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		  }
515f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       } else {
516f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		  /* If the first-seen instance of a particular uniform did not
517f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		   * have an initializer but a later instance does, copy the
518f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		   * initializer to the version stored in the symbol table.
519f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		   */
520f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		  /* FINISHME: This is wrong.  The constant_value field should
521f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		   * FINISHME: not be modified!  Imagine a case where a shader
522f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		   * FINISHME: without an initializer is linked in two different
523f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		   * FINISHME: programs with shaders that have differing
524f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		   * FINISHME: initializers.  Linking with the first will
525f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		   * FINISHME: modify the shader, and linking with the second
526f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		   * FINISHME: will fail.
527f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		   */
528f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		  existing->constant_initializer =
529f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		     var->constant_initializer->clone(ralloc_parent(existing),
530f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						      NULL);
531f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       }
532f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    }
533f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
534f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    if (var->has_initializer) {
535f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       if (existing->has_initializer
536f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		   && (var->constant_initializer == NULL
537f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		       || existing->constant_initializer == NULL)) {
538f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		  linker_error(prog,
539f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       "shared global variable `%s' has multiple "
540f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       "non-constant initializers.\n",
541f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       var->name);
542f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		  return false;
543f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       }
544f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
545f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       /* Some instance had an initializer, so keep track of that.  In
546f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		* this location, all sorts of initializers (constant or
547f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		* otherwise) will propagate the existence to the variable
548f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		* stored in the symbol table.
549f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		*/
550f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       existing->has_initializer = true;
551f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    }
552f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
553f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    if (existing->invariant != var->invariant) {
554f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       linker_error(prog, "declarations for %s `%s' have "
555f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			    "mismatching invariant qualifiers\n",
556f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			    mode_string(var), var->name);
557f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       return false;
558f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    }
559f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            if (existing->centroid != var->centroid) {
560f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               linker_error(prog, "declarations for %s `%s' have "
561f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			    "mismatching centroid qualifiers\n",
562f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			    mode_string(var), var->name);
563f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               return false;
564f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            }
565f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 } else
566f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    variables.add_variable(var);
567f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
568f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
569f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
570f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return true;
571f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
572f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
573f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
574f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
575f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Perform validation of uniforms used across multiple shader stages
576f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
577f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool
578f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgcross_validate_uniforms(struct gl_shader_program *prog)
579f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
580f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return cross_validate_globals(prog, prog->_LinkedShaders,
581f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 MESA_SHADER_TYPES, true);
582f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
583f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
584f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
585f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Accumulates the array of prog->UniformBlocks and checks that all
586f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * definitons of blocks agree on their contents.
587f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
588f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic bool
589f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orginterstage_cross_validate_uniform_blocks(struct gl_shader_program *prog)
590f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
591f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned max_num_uniform_blocks = 0;
592f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
593f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (prog->_LinkedShaders[i])
594f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 max_num_uniform_blocks += prog->_LinkedShaders[i]->NumUniformBlocks;
595f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
596f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
597f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
598f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      struct gl_shader *sh = prog->_LinkedShaders[i];
599f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
600f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      prog->UniformBlockStageIndex[i] = ralloc_array(prog, int,
601f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						     max_num_uniform_blocks);
602f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (unsigned int j = 0; j < max_num_uniform_blocks; j++)
603f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 prog->UniformBlockStageIndex[i][j] = -1;
604f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
605f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (sh == NULL)
606f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 continue;
607f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
608f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (unsigned int j = 0; j < sh->NumUniformBlocks; j++) {
609f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 int index = link_cross_validate_uniform_block(prog,
610f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						       &prog->UniformBlocks,
611f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						       &prog->NumUniformBlocks,
612f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						       &sh->UniformBlocks[j]);
613f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
614f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (index == -1) {
615f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    linker_error(prog, "uniform block `%s' has mismatching definitions",
616f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 sh->UniformBlocks[j].Name);
617f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    return false;
618f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 }
619f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
620f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 prog->UniformBlockStageIndex[i][index] = j;
621f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
622f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
623f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
624f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return true;
625f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
626f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
627f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
628f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Validate that outputs from one stage match inputs of another
629f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
630f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool
631f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgcross_validate_outputs_to_inputs(struct gl_shader_program *prog,
632f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 gl_shader *producer, gl_shader *consumer)
633f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
634f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   glsl_symbol_table parameters;
635f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* FINISHME: Figure these out dynamically. */
636f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const char *const producer_stage = "vertex";
637f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const char *const consumer_stage = "fragment";
638f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
639f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Find all shader outputs in the "producer" stage.
640f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
641f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   foreach_list(node, producer->ir) {
642f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_variable *const var = ((ir_instruction *) node)->as_variable();
643f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
644f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* FINISHME: For geometry shaders, this should also look for inout
645f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * FINISHME: variables.
646f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       */
647f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if ((var == NULL) || (var->mode != ir_var_out))
648f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 continue;
649f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
650f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      parameters.add_variable(var);
651f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
652f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
653f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
654f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Find all shader inputs in the "consumer" stage.  Any variables that have
655f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * matching outputs already in the symbol table must have the same type and
656f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * qualifiers.
657f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
658f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   foreach_list(node, consumer->ir) {
659f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_variable *const input = ((ir_instruction *) node)->as_variable();
660f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
661f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* FINISHME: For geometry shaders, this should also look for inout
662f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * FINISHME: variables.
663f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       */
664f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if ((input == NULL) || (input->mode != ir_var_in))
665f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 continue;
666f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
667f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_variable *const output = parameters.get_variable(input->name);
668f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (output != NULL) {
669f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 /* Check that the types match between stages.
670f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	  */
671f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (input->type != output->type) {
672f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    /* There is a bit of a special case for gl_TexCoord.  This
673f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * built-in is unsized by default.  Applications that variable
674f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * access it must redeclare it with a size.  There is some
675f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * language in the GLSL spec that implies the fragment shader
676f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * and vertex shader do not have to agree on this size.  Other
677f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * driver behave this way, and one or two applications seem to
678f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * rely on it.
679f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *
680f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * Neither declaration needs to be modified here because the array
681f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * sizes are fixed later when update_array_sizes is called.
682f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *
683f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * From page 48 (page 54 of the PDF) of the GLSL 1.10 spec:
684f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *
685f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *     "Unlike user-defined varying variables, the built-in
686f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *     varying variables don't have a strict one-to-one
687f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *     correspondence between the vertex language and the
688f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *     fragment language."
689f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     */
690f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    if (!output->type->is_array()
691f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		|| (strncmp("gl_", output->name, 3) != 0)) {
692f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       linker_error(prog,
693f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			    "%s shader output `%s' declared as type `%s', "
694f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			    "but %s shader input declared as type `%s'\n",
695f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			    producer_stage, output->name,
696f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			    output->type->name,
697f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			    consumer_stage, input->type->name);
698f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       return false;
699f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    }
700f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 }
701f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
702f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 /* Check that all of the qualifiers match between stages.
703f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	  */
704f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (input->centroid != output->centroid) {
705f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    linker_error(prog,
706f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 "%s shader output `%s' %s centroid qualifier, "
707f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 "but %s shader input %s centroid qualifier\n",
708f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 producer_stage,
709f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 output->name,
710f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 (output->centroid) ? "has" : "lacks",
711f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 consumer_stage,
712f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 (input->centroid) ? "has" : "lacks");
713f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    return false;
714f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 }
715f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
716f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (input->invariant != output->invariant) {
717f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    linker_error(prog,
718f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 "%s shader output `%s' %s invariant qualifier, "
719f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 "but %s shader input %s invariant qualifier\n",
720f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 producer_stage,
721f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 output->name,
722f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 (output->invariant) ? "has" : "lacks",
723f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 consumer_stage,
724f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 (input->invariant) ? "has" : "lacks");
725f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    return false;
726f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 }
727f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
728f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (input->interpolation != output->interpolation) {
729f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    linker_error(prog,
730f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 "%s shader output `%s' specifies %s "
731f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 "interpolation qualifier, "
732f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 "but %s shader input specifies %s "
733f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 "interpolation qualifier\n",
734f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 producer_stage,
735f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 output->name,
736f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 output->interpolation_string(),
737f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 consumer_stage,
738f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 input->interpolation_string());
739f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    return false;
740f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 }
741f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
742f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
743f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
744f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return true;
745f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
746f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
747f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
748f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
749f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Populates a shaders symbol table with all global declarations
750f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
751f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
752f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpopulate_symbol_table(gl_shader *sh)
753f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
754f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   sh->symbols = new(sh) glsl_symbol_table;
755f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
756f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   foreach_list(node, sh->ir) {
757f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_instruction *const inst = (ir_instruction *) node;
758f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_variable *var;
759f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_function *func;
760f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
761f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if ((func = inst->as_function()) != NULL) {
762f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 sh->symbols->add_function(func);
763f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else if ((var = inst->as_variable()) != NULL) {
764f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 sh->symbols->add_variable(var);
765f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
766f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
767f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
768f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
769f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
770f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
771f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Remap variables referenced in an instruction tree
772f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
773f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * This is used when instruction trees are cloned from one shader and placed in
774f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * another.  These trees will contain references to \c ir_variable nodes that
775f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * do not exist in the target shader.  This function finds these \c ir_variable
776f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * references and replaces the references with matching variables in the target
777f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * shader.
778f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
779f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * If there is no matching variable in the target shader, a clone of the
780f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \c ir_variable is made and added to the target shader.  The new variable is
781f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * added to \b both the instruction stream and the symbol table.
782f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
783f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param inst         IR tree that is to be processed.
784f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param symbols      Symbol table containing global scope symbols in the
785f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *                     linked shader.
786f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param instructions Instruction stream where new variable declarations
787f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *                     should be added.
788f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
789f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
790f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgremap_variables(ir_instruction *inst, struct gl_shader *target,
791f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		hash_table *temps)
792f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
793f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   class remap_visitor : public ir_hierarchical_visitor {
794f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   public:
795f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 remap_visitor(struct gl_shader *target,
796f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		    hash_table *temps)
797f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      {
798f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 this->target = target;
799f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 this->symbols = target->symbols;
800f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 this->instructions = target->ir;
801f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 this->temps = temps;
802f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
803f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
804f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      virtual ir_visitor_status visit(ir_dereference_variable *ir)
805f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      {
806f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (ir->var->mode == ir_var_temporary) {
807f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    ir_variable *var = (ir_variable *) hash_table_find(temps, ir->var);
808f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
809f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    assert(var != NULL);
810f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    ir->var = var;
811f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    return visit_continue;
812f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 }
813f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
814f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_variable *const existing =
815f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    this->symbols->get_variable(ir->var->name);
816f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (existing != NULL)
817f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    ir->var = existing;
818f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 else {
819f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    ir_variable *copy = ir->var->clone(this->target, NULL);
820f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
821f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    this->symbols->add_variable(copy);
822f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    this->instructions->push_head(copy);
823f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    ir->var = copy;
824f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 }
825f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
826f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return visit_continue;
827f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
828f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
829f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   private:
830f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      struct gl_shader *target;
831f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      glsl_symbol_table *symbols;
832f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      exec_list *instructions;
833f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      hash_table *temps;
834f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   };
835f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
836f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   remap_visitor v(target, temps);
837f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
838f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   inst->accept(&v);
839f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
840f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
841f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
842f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
843f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Move non-declarations from one instruction stream to another
844f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
845f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The intended usage pattern of this function is to pass the pointer to the
846f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * head sentinel of a list (i.e., a pointer to the list cast to an \c exec_node
847f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * pointer) for \c last and \c false for \c make_copies on the first
848f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * call.  Successive calls pass the return value of the previous call for
849f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \c last and \c true for \c make_copies.
850f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
851f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param instructions Source instruction stream
852f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param last         Instruction after which new instructions should be
853f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *                     inserted in the target instruction stream
854f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param make_copies  Flag selecting whether instructions in \c instructions
855f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *                     should be copied (via \c ir_instruction::clone) into the
856f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *                     target list or moved.
857f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
858f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \return
859f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * The new "last" instruction in the target instruction stream.  This pointer
860f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * is suitable for use as the \c last parameter of a later call to this
861f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * function.
862f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
863f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgexec_node *
864f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgmove_non_declarations(exec_list *instructions, exec_node *last,
865f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		      bool make_copies, gl_shader *target)
866f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
867f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   hash_table *temps = NULL;
868f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
869f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (make_copies)
870f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      temps = hash_table_ctor(0, hash_table_pointer_hash,
871f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			      hash_table_pointer_compare);
872f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
873f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   foreach_list_safe(node, instructions) {
874f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_instruction *inst = (ir_instruction *) node;
875f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
876f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (inst->as_function())
877f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 continue;
878f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
879f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_variable *var = inst->as_variable();
880f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if ((var != NULL) && (var->mode != ir_var_temporary))
881f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 continue;
882f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
883f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      assert(inst->as_assignment()
884f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             || inst->as_call()
885f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             || inst->as_if() /* for initializers with the ?: operator */
886f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     || ((var != NULL) && (var->mode == ir_var_temporary)));
887f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
888f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (make_copies) {
889f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 inst = inst->clone(target, NULL);
890f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
891f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (var != NULL)
892f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    hash_table_insert(temps, inst, var);
893f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 else
894f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    remap_variables(inst, target, temps);
895f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else {
896f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 inst->remove();
897f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
898f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
899f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      last->insert_after(inst);
900f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      last = inst;
901f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
902f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
903f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (make_copies)
904f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      hash_table_dtor(temps);
905f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
906f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return last;
907f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
908f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
909f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
910f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Get the function signature for main from a shader
911f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
912f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic ir_function_signature *
913f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgget_main_function_signature(gl_shader *sh)
914f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
915f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_function *const f = sh->symbols->get_function("main");
916f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (f != NULL) {
917f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      exec_list void_parameters;
918f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
919f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* Look for the 'void main()' signature and ensure that it's defined.
920f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * This keeps the linker from accidentally pick a shader that just
921f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * contains a prototype for main.
922f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       *
923f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * We don't have to check for multiple definitions of main (in multiple
924f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * shaders) because that would have already been caught above.
925f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       */
926f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_function_signature *sig = f->matching_signature(&void_parameters);
927f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if ((sig != NULL) && sig->is_defined) {
928f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return sig;
929f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
930f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
931f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
932f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return NULL;
933f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
934f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
935f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
936f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
937f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * This class is only used in link_intrastage_shaders() below but declaring
938f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * it inside that function leads to compiler warnings with some versions of
939f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * gcc.
940f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
941f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass array_sizing_visitor : public ir_hierarchical_visitor {
942f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpublic:
943f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   virtual ir_visitor_status visit(ir_variable *var)
944f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   {
945f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (var->type->is_array() && (var->type->length == 0)) {
946f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         const glsl_type *type =
947f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            glsl_type::get_array_instance(var->type->fields.array,
948f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                          var->max_array_access + 1);
949f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         assert(type != NULL);
950f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         var->type = type;
951f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
952f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return visit_continue;
953f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
954f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
955f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
956f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
957f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Combine a group of shaders for a single stage to generate a linked shader
958f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
959f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \note
960f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * If this function is supplied a single shader, it is cloned, and the new
961f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * shader is returned.
962f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
963f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic struct gl_shader *
964f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orglink_intrastage_shaders(void *mem_ctx,
965f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			struct gl_context *ctx,
966f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			struct gl_shader_program *prog,
967f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			struct gl_shader **shader_list,
968f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			unsigned num_shaders)
969f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
970f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_uniform_block *uniform_blocks = NULL;
971f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned num_uniform_blocks = 0;
972f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
973f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Check that global variables defined in multiple shaders are consistent.
974f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
975f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!cross_validate_globals(prog, shader_list, num_shaders, false))
976f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
977f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
978f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Check that uniform blocks between shaders for a stage agree. */
979f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (unsigned i = 0; i < num_shaders; i++) {
980f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      struct gl_shader *sh = shader_list[i];
981f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
982f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (unsigned j = 0; j < shader_list[i]->NumUniformBlocks; j++) {
983f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 link_assign_uniform_block_offsets(shader_list[i]);
984f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
985f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 int index = link_cross_validate_uniform_block(mem_ctx,
986f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						       &uniform_blocks,
987f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						       &num_uniform_blocks,
988f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						       &sh->UniformBlocks[j]);
989f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (index == -1) {
990f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    linker_error(prog, "uniform block `%s' has mismatching definitions",
991f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 sh->UniformBlocks[j].Name);
992f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    return NULL;
993f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 }
994f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
995f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
996f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
997f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Check that there is only a single definition of each function signature
998f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * across all shaders.
999f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
1000f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (unsigned i = 0; i < (num_shaders - 1); i++) {
1001f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      foreach_list(node, shader_list[i]->ir) {
1002f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_function *const f = ((ir_instruction *) node)->as_function();
1003f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1004f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (f == NULL)
1005f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    continue;
1006f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1007f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 for (unsigned j = i + 1; j < num_shaders; j++) {
1008f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    ir_function *const other =
1009f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       shader_list[j]->symbols->get_function(f->name);
1010f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1011f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    /* If the other shader has no function (and therefore no function
1012f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * signatures) with the same name, skip to the next shader.
1013f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     */
1014f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    if (other == NULL)
1015f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       continue;
1016f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1017f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    foreach_iter (exec_list_iterator, iter, *f) {
1018f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       ir_function_signature *sig =
1019f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		  (ir_function_signature *) iter.get();
1020f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1021f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       if (!sig->is_defined || sig->is_builtin)
1022f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		  continue;
1023f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1024f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       ir_function_signature *other_sig =
1025f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		  other->exact_matching_signature(& sig->parameters);
1026f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1027f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       if ((other_sig != NULL) && other_sig->is_defined
1028f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		   && !other_sig->is_builtin) {
1029f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		  linker_error(prog, "function `%s' is multiply defined",
1030f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       f->name);
1031f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		  return NULL;
1032f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       }
1033f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    }
1034f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 }
1035f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1036f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1037f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1038f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Find the shader that defines main, and make a clone of it.
1039f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *
1040f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * Starting with the clone, search for undefined references.  If one is
1041f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * found, find the shader that defines it.  Clone the reference and add
1042f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * it to the shader.  Repeat until there are no undefined references or
1043f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * until a reference cannot be resolved.
1044f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
1045f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   gl_shader *main = NULL;
1046f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (unsigned i = 0; i < num_shaders; i++) {
1047f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (get_main_function_signature(shader_list[i]) != NULL) {
1048f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 main = shader_list[i];
1049f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 break;
1050f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1051f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1052f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1053f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (main == NULL) {
1054f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      linker_error(prog, "%s shader lacks `main'\n",
1055f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		   (shader_list[0]->Type == GL_VERTEX_SHADER)
1056f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		   ? "vertex" : "fragment");
1057f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return NULL;
1058f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1059f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1060f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   gl_shader *linked = ctx->Driver.NewShader(NULL, 0, main->Type);
1061f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   linked->ir = new(linked) exec_list;
1062f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   clone_ir_list(mem_ctx, linked->ir, main->ir);
1063f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1064f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   linked->UniformBlocks = uniform_blocks;
1065f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   linked->NumUniformBlocks = num_uniform_blocks;
1066f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ralloc_steal(linked, linked->UniformBlocks);
1067f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1068f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   populate_symbol_table(linked);
1069f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1070f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* The a pointer to the main function in the final linked shader (i.e., the
1071f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * copy of the original shader that contained the main function).
1072f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
1073f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ir_function_signature *const main_sig = get_main_function_signature(linked);
1074f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1075f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Move any instructions other than variable declarations or function
1076f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * declarations into main.
1077f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
1078f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   exec_node *insertion_point =
1079f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      move_non_declarations(linked->ir, (exec_node *) &main_sig->body, false,
1080f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			    linked);
1081f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1082f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (unsigned i = 0; i < num_shaders; i++) {
1083f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (shader_list[i] == main)
1084f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 continue;
1085f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1086f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      insertion_point = move_non_declarations(shader_list[i]->ir,
1087f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					      insertion_point, true, linked);
1088f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1089f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1090f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Resolve initializers for global variables in the linked shader.
1091f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
1092f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned num_linking_shaders = num_shaders;
1093f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (unsigned i = 0; i < num_shaders; i++)
1094f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      num_linking_shaders += shader_list[i]->num_builtins_to_link;
1095f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1096f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   gl_shader **linking_shaders =
1097f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      (gl_shader **) calloc(num_linking_shaders, sizeof(gl_shader *));
1098f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1099f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   memcpy(linking_shaders, shader_list,
1100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	  sizeof(linking_shaders[0]) * num_shaders);
1101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned idx = num_shaders;
1103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (unsigned i = 0; i < num_shaders; i++) {
1104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      memcpy(&linking_shaders[idx], shader_list[i]->builtins_to_link,
1105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     sizeof(linking_shaders[0]) * shader_list[i]->num_builtins_to_link);
1106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      idx += shader_list[i]->num_builtins_to_link;
1107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert(idx == num_linking_shaders);
1110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!link_function_calls(prog, linked, linking_shaders,
1112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			    num_linking_shaders)) {
1113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ctx->Driver.DeleteShader(ctx, linked);
1114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      linked = NULL;
1115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   free(linking_shaders);
1118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#ifdef DEBUG
1120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* At this point linked should contain all of the linked IR, so
1121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * validate it to make sure nothing went wrong.
1122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
1123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (linked)
1124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      validate_ir_tree(linked->ir);
1125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org#endif
1126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Make a pass over all variable declarations to ensure that arrays with
1128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * unspecified sizes have a size specified.  The size is inferred from the
1129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * max_array_access field.
1130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
1131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (linked != NULL) {
1132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      array_sizing_visitor v;
1133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      v.run(linked->ir);
1135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return linked;
1138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
1141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Update the sizes of linked shader uniform arrays to the maximum
1142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * array index used.
1143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
1144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * From page 81 (page 95 of the PDF) of the OpenGL 2.1 spec:
1145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
1146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *     If one or more elements of an array are active,
1147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *     GetActiveUniform will return the name of the array in name,
1148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *     subject to the restrictions listed above. The type of the array
1149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *     is returned in type. The size parameter contains the highest
1150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *     array element index used, plus one. The compiler or linker
1151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *     determines the highest index used.  There will be only one
1152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *     active uniform reported by the GL per uniform array.
1153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
1155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
1156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgupdate_array_sizes(struct gl_shader_program *prog)
1157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
1159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (prog->_LinkedShaders[i] == NULL)
1160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    continue;
1161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      foreach_list(node, prog->_LinkedShaders[i]->ir) {
1163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ir_variable *const var = ((ir_instruction *) node)->as_variable();
1164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if ((var == NULL) || (var->mode != ir_var_uniform &&
1166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       var->mode != ir_var_in &&
1167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			       var->mode != ir_var_out) ||
1168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     !var->type->is_array())
1169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    continue;
1170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 /* GL_ARB_uniform_buffer_object says that std140 uniforms
1172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	  * will not be eliminated.  Since we always do std140, just
1173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	  * don't resize arrays in UBOs.
1174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	  */
1175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (var->uniform_block != -1)
1176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    continue;
1177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 unsigned int size = var->max_array_access;
1179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 for (unsigned j = 0; j < MESA_SHADER_TYPES; j++) {
1180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       if (prog->_LinkedShaders[j] == NULL)
1181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		  continue;
1182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    foreach_list(node2, prog->_LinkedShaders[j]->ir) {
1184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       ir_variable *other_var = ((ir_instruction *) node2)->as_variable();
1185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       if (!other_var)
1186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		  continue;
1187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       if (strcmp(var->name, other_var->name) == 0 &&
1189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		   other_var->max_array_access > size) {
1190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		  size = other_var->max_array_access;
1191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       }
1192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    }
1193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 }
1194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (size + 1 != var->type->fields.array->length) {
1196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    /* If this is a built-in uniform (i.e., it's backed by some
1197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * fixed-function state), adjust the number of state slots to
1198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * match the new array size.  The number of slots per array entry
1199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * is not known.  It seems safe to assume that the total number of
1200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * slots is an integer multiple of the number of array elements.
1201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * Determine the number of slots per array element by dividing by
1202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * the old (total) size.
1203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     */
1204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    if (var->num_state_slots > 0) {
1205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       var->num_state_slots = (size + 1)
1206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		  * (var->num_state_slots / var->type->length);
1207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    }
1208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    var->type = glsl_type::get_array_instance(var->type->fields.array,
1210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org						      size + 1);
1211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    /* FINISHME: We should update the types of array
1212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * dereferences of this variable now.
1213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     */
1214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 }
1215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
1220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Find a contiguous set of available bits in a bitmask.
1221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
1222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param used_mask     Bits representing used (1) and unused (0) locations
1223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param needed_count  Number of contiguous bits needed.
1224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
1225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \return
1226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Base location of the available bits on success or -1 on failure.
1227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
1228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgint
1229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgfind_available_slots(unsigned used_mask, unsigned needed_count)
1230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned needed_mask = (1 << needed_count) - 1;
1232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const int max_bit_to_test = (8 * sizeof(used_mask)) - needed_count;
1233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* The comparison to 32 is redundant, but without it GCC emits "warning:
1235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * cannot optimize possibly infinite loops" for the loop below.
1236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
1237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if ((needed_count == 0) || (max_bit_to_test < 0) || (max_bit_to_test > 32))
1238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return -1;
1239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (int i = 0; i <= max_bit_to_test; i++) {
1241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if ((needed_mask & ~used_mask) == needed_mask)
1242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return i;
1243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      needed_mask <<= 1;
1245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return -1;
1248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
1252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Assign locations for either VS inputs for FS outputs
1253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
1254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param prog          Shader program whose variables need locations assigned
1255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param target_index  Selector for the program target to receive location
1256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *                      assignmnets.  Must be either \c MESA_SHADER_VERTEX or
1257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *                      \c MESA_SHADER_FRAGMENT.
1258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param max_index     Maximum number of generic locations.  This corresponds
1259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *                      to either the maximum number of draw buffers or the
1260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *                      maximum number of generic attributes.
1261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
1262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \return
1263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * If locations are successfully assigned, true is returned.  Otherwise an
1264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * error is emitted to the shader link log and false is returned.
1265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
1266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool
1267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgassign_attribute_or_color_locations(gl_shader_program *prog,
1268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				    unsigned target_index,
1269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				    unsigned max_index)
1270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Mark invalid locations as being used.
1272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
1273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned used_locations = (max_index >= 32)
1274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ? ~0 : ~((1 << max_index) - 1);
1275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert((target_index == MESA_SHADER_VERTEX)
1277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	  || (target_index == MESA_SHADER_FRAGMENT));
1278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   gl_shader *const sh = prog->_LinkedShaders[target_index];
1280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (sh == NULL)
1281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return true;
1282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Operate in a total of four passes.
1284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *
1285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * 1. Invalidate the location assignments for all vertex shader inputs.
1286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *
1287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * 2. Assign locations for inputs that have user-defined (via
1288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *    glBindVertexAttribLocation) locations and outputs that have
1289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *    user-defined locations (via glBindFragDataLocation).
1290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *
1291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * 3. Sort the attributes without assigned locations by number of slots
1292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *    required in decreasing order.  Fragmentation caused by attribute
1293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *    locations assigned by the application may prevent large attributes
1294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *    from having enough contiguous space.
1295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *
1296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * 4. Assign locations to any inputs without assigned locations.
1297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
1298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const int generic_base = (target_index == MESA_SHADER_VERTEX)
1300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ? (int) VERT_ATTRIB_GENERIC0 : (int) FRAG_RESULT_DATA0;
1301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const enum ir_variable_mode direction =
1303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      (target_index == MESA_SHADER_VERTEX) ? ir_var_in : ir_var_out;
1304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   link_invalidate_variable_locations(sh, direction, generic_base);
1307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Temporary storage for the set of attributes that need locations assigned.
1309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
1310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct temp_attr {
1311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      unsigned slots;
1312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_variable *var;
1313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* Used below in the call to qsort. */
1315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      static int compare(const void *a, const void *b)
1316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      {
1317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 const temp_attr *const l = (const temp_attr *) a;
1318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 const temp_attr *const r = (const temp_attr *) b;
1319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 /* Reversed because we want a descending order sort below. */
1321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return r->slots - l->slots;
1322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   } to_assign[16];
1324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned num_attr = 0;
1326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   foreach_list(node, sh->ir) {
1328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_variable *const var = ((ir_instruction *) node)->as_variable();
1329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if ((var == NULL) || (var->mode != (unsigned) direction))
1331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 continue;
1332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (var->explicit_location) {
1334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if ((var->location >= (int)(max_index + generic_base))
1335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     || (var->location < 0)) {
1336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    linker_error(prog,
1337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 "invalid explicit location %d specified for `%s'\n",
1338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 (var->location < 0)
1339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 ? var->location : var->location - generic_base,
1340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 var->name);
1341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    return false;
1342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 }
1343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else if (target_index == MESA_SHADER_VERTEX) {
1344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 unsigned binding;
1345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (prog->AttributeBindings->get(binding, var->name)) {
1347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    assert(binding >= VERT_ATTRIB_GENERIC0);
1348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    var->location = binding;
1349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 }
1350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else if (target_index == MESA_SHADER_FRAGMENT) {
1351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 unsigned binding;
1352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 unsigned index;
1353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (prog->FragDataBindings->get(binding, var->name)) {
1355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    assert(binding >= FRAG_RESULT_DATA0);
1356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    var->location = binding;
1357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    if (prog->FragDataIndexBindings->get(index, var->name)) {
1359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       var->index = index;
1360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    }
1361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 }
1362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* If the variable is not a built-in and has a location statically
1365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * assigned in the shader (presumably via a layout qualifier), make sure
1366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * that it doesn't collide with other assigned locations.  Otherwise,
1367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * add it to the list of variables that need linker-assigned locations.
1368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       */
1369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      const unsigned slots = count_attribute_slots(var->type);
1370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (var->location != -1) {
1371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (var->location >= generic_base && var->index < 1) {
1372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    /* From page 61 of the OpenGL 4.0 spec:
1373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *
1374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *     "LinkProgram will fail if the attribute bindings assigned
1375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *     by BindAttribLocation do not leave not enough space to
1376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *     assign a location for an active matrix attribute or an
1377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *     active attribute array, both of which require multiple
1378f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *     contiguous generic attributes."
1379f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *
1380f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * Previous versions of the spec contain similar language but omit
1381f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * the bit about attribute arrays.
1382f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *
1383f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * Page 61 of the OpenGL 4.0 spec also says:
1384f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *
1385f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *     "It is possible for an application to bind more than one
1386f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *     attribute name to the same location. This is referred to as
1387f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *     aliasing. This will only work if only one of the aliased
1388f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *     attributes is active in the executable program, or if no
1389f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *     path through the shader consumes more than one attribute of
1390f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *     a set of attributes aliased to the same location. A link
1391f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *     error can occur if the linker determines that every path
1392f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *     through the shader consumes multiple aliased attributes,
1393f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *     but implementations are not required to generate an error
1394f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *     in this case."
1395f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     *
1396f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * These two paragraphs are either somewhat contradictory, or I
1397f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * don't fully understand one or both of them.
1398f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     */
1399f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    /* FINISHME: The code as currently written does not support
1400f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * FINISHME: attribute location aliasing (see comment above).
1401f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     */
1402f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    /* Mask representing the contiguous slots that will be used by
1403f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * this attribute.
1404f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     */
1405f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    const unsigned attr = var->location - generic_base;
1406f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    const unsigned use_mask = (1 << slots) - 1;
1407f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1408f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    /* Generate a link error if the set of bits requested for this
1409f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     * attribute overlaps any previously allocated bits.
1410f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	     */
1411f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    if ((~(use_mask << attr) & used_locations) != used_locations) {
1412f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       const char *const string = (target_index == MESA_SHADER_VERTEX)
1413f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		  ? "vertex shader input" : "fragment shader output";
1414f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       linker_error(prog,
1415f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			    "insufficient contiguous locations "
1416f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			    "available for %s `%s' %d %d %d", string,
1417f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			    var->name, used_locations, use_mask, attr);
1418f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       return false;
1419f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    }
1420f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1421f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    used_locations |= (use_mask << attr);
1422f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 }
1423f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1424f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 continue;
1425f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1426f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1427f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      to_assign[num_attr].slots = slots;
1428f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      to_assign[num_attr].var = var;
1429f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      num_attr++;
1430f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1431f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1432f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* If all of the attributes were assigned locations by the application (or
1433f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * are built-in attributes with fixed locations), return early.  This should
1434f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * be the common case.
1435f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
1436f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (num_attr == 0)
1437f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return true;
1438f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1439f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   qsort(to_assign, num_attr, sizeof(to_assign[0]), temp_attr::compare);
1440f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1441f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (target_index == MESA_SHADER_VERTEX) {
1442f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* VERT_ATTRIB_GENERIC0 is a pseudo-alias for VERT_ATTRIB_POS.  It can
1443f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * only be explicitly assigned by via glBindAttribLocation.  Mark it as
1444f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * reserved to prevent it from being automatically allocated below.
1445f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       */
1446f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      find_deref_visitor find("gl_Vertex");
1447f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      find.run(sh->ir);
1448f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (find.variable_found())
1449f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 used_locations |= (1 << 0);
1450f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1451f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1452f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (unsigned i = 0; i < num_attr; i++) {
1453f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* Mask representing the contiguous slots that will be used by this
1454f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * attribute.
1455f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       */
1456f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      const unsigned use_mask = (1 << to_assign[i].slots) - 1;
1457f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1458f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      int location = find_available_slots(used_locations, to_assign[i].slots);
1459f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1460f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (location < 0) {
1461f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 const char *const string = (target_index == MESA_SHADER_VERTEX)
1462f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    ? "vertex shader input" : "fragment shader output";
1463f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1464f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 linker_error(prog,
1465f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		      "insufficient contiguous locations "
1466f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		      "available for %s `%s'",
1467f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		      string, to_assign[i].var->name);
1468f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 return false;
1469f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1470f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1471f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      to_assign[i].var->location = generic_base + location;
1472f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      used_locations |= (use_mask << location);
1473f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1474f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1475f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return true;
1476f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1477f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1478f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1479f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
1480f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Demote shader inputs and outputs that are not used in other stages
1481f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
1482f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
1483f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdemote_shader_inputs_and_outputs(gl_shader *sh, enum ir_variable_mode mode)
1484f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1485f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   foreach_list(node, sh->ir) {
1486f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_variable *const var = ((ir_instruction *) node)->as_variable();
1487f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1488f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if ((var == NULL) || (var->mode != int(mode)))
1489f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 continue;
1490f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1491f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* A shader 'in' or 'out' variable is only really an input or output if
1492f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * its value is used by other shader stages.  This will cause the variable
1493f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * to have a location assigned.
1494f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       */
1495f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (var->location == -1) {
1496f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 var->mode = ir_var_auto;
1497f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1498f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1499f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1500f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1501f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1502f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
1503f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Data structure tracking information about a transform feedback declaration
1504f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * during linking.
1505f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
1506f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgclass tfeedback_decl
1507f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1508f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgpublic:
1509f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bool init(struct gl_context *ctx, struct gl_shader_program *prog,
1510f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             const void *mem_ctx, const char *input);
1511f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   static bool is_same(const tfeedback_decl &x, const tfeedback_decl &y);
1512f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bool assign_location(struct gl_context *ctx, struct gl_shader_program *prog,
1513f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                        ir_variable *output_var);
1514f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bool accumulate_num_outputs(struct gl_shader_program *prog, unsigned *count);
1515f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bool store(struct gl_context *ctx, struct gl_shader_program *prog,
1516f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org              struct gl_transform_feedback_info *info, unsigned buffer,
1517f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org              const unsigned max_outputs) const;
1518f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1519f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /**
1520f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * True if assign_location() has been called for this object.
1521f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
1522f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bool is_assigned() const
1523f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   {
1524f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return this->location != -1;
1525f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1526f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1527f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bool is_next_buffer_separator() const
1528f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   {
1529f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return this->next_buffer_separator;
1530f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1531f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1532f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bool is_varying() const
1533f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   {
1534f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return !this->next_buffer_separator && !this->skip_components;
1535f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1536f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1537f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /**
1538f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * Determine whether this object refers to the variable var.
1539f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
1540f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bool matches_var(ir_variable *var) const
1541f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   {
1542f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (this->is_clip_distance_mesa)
1543f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return strcmp(var->name, "gl_ClipDistanceMESA") == 0;
1544f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else
1545f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return strcmp(var->name, this->var_name) == 0;
1546f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1547f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1548f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /**
1549f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * The total number of varying components taken up by this variable.  Only
1550f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * valid if is_assigned() is true.
1551f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
1552f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned num_components() const
1553f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   {
1554f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (this->is_clip_distance_mesa)
1555f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return this->size;
1556f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else
1557f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return this->vector_elements * this->matrix_columns * this->size;
1558f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1559f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1560f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgprivate:
1561f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /**
1562f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * The name that was supplied to glTransformFeedbackVaryings.  Used for
1563f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * error reporting and glGetTransformFeedbackVarying().
1564f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
1565f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const char *orig_name;
1566f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1567f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /**
1568f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * The name of the variable, parsed from orig_name.
1569f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
1570f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const char *var_name;
1571f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1572f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /**
1573f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * True if the declaration in orig_name represents an array.
1574f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
1575f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bool is_subscripted;
1576f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1577f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /**
1578f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * If is_subscripted is true, the subscript that was specified in orig_name.
1579f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
1580f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned array_subscript;
1581f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1582f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /**
1583f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * True if the variable is gl_ClipDistance and the driver lowers
1584f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * gl_ClipDistance to gl_ClipDistanceMESA.
1585f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
1586f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bool is_clip_distance_mesa;
1587f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1588f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /**
1589f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * The vertex shader output location that the linker assigned for this
1590f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * variable.  -1 if a location hasn't been assigned yet.
1591f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
1592f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   int location;
1593f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1594f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /**
1595f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * If location != -1, the number of vector elements in this variable, or 1
1596f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * if this variable is a scalar.
1597f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
1598f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned vector_elements;
1599f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1600f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /**
1601f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * If location != -1, the number of matrix columns in this variable, or 1
1602f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * if this variable is not a matrix.
1603f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
1604f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned matrix_columns;
1605f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1606f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /** Type of the varying returned by glGetTransformFeedbackVarying() */
1607f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   GLenum type;
1608f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1609f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /**
1610f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * If location != -1, the size that should be returned by
1611f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * glGetTransformFeedbackVarying().
1612f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
1613f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned size;
1614f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1615f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /**
1616f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * How many components to skip. If non-zero, this is
1617f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * gl_SkipComponents{1,2,3,4} from ARB_transform_feedback3.
1618f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
1619f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned skip_components;
1620f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1621f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /**
1622f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * Whether this is gl_NextBuffer from ARB_transform_feedback3.
1623f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
1624f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bool next_buffer_separator;
1625f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org};
1626f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1627f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1628f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
1629f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Initialize this object based on a string that was passed to
1630f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * glTransformFeedbackVaryings.  If there is a parse error, the error is
1631f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * reported using linker_error(), and false is returned.
1632f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
1633f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool
1634f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgtfeedback_decl::init(struct gl_context *ctx, struct gl_shader_program *prog,
1635f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     const void *mem_ctx, const char *input)
1636f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1637f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* We don't have to be pedantic about what is a valid GLSL variable name,
1638f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * because any variable with an invalid name can't exist in the IR anyway.
1639f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
1640f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1641f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   this->location = -1;
1642f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   this->orig_name = input;
1643f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   this->is_clip_distance_mesa = false;
1644f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   this->skip_components = 0;
1645f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   this->next_buffer_separator = false;
1646f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1647f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (ctx->Extensions.ARB_transform_feedback3) {
1648f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* Parse gl_NextBuffer. */
1649f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (strcmp(input, "gl_NextBuffer") == 0) {
1650f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         this->next_buffer_separator = true;
1651f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return true;
1652f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1653f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1654f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* Parse gl_SkipComponents. */
1655f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (strcmp(input, "gl_SkipComponents1") == 0)
1656f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         this->skip_components = 1;
1657f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else if (strcmp(input, "gl_SkipComponents2") == 0)
1658f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         this->skip_components = 2;
1659f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else if (strcmp(input, "gl_SkipComponents3") == 0)
1660f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         this->skip_components = 3;
1661f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else if (strcmp(input, "gl_SkipComponents4") == 0)
1662f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         this->skip_components = 4;
1663f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1664f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (this->skip_components)
1665f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return true;
1666f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1667f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1668f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Parse a declaration. */
1669f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const char *bracket = strrchr(input, '[');
1670f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1671f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (bracket) {
1672f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      this->var_name = ralloc_strndup(mem_ctx, input, bracket - input);
1673f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (sscanf(bracket, "[%u]", &this->array_subscript) != 1) {
1674f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         linker_error(prog, "Cannot parse transform feedback varying %s", input);
1675f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return false;
1676f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1677f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      this->is_subscripted = true;
1678f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   } else {
1679f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      this->var_name = ralloc_strdup(mem_ctx, input);
1680f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      this->is_subscripted = false;
1681f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1682f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1683f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* For drivers that lower gl_ClipDistance to gl_ClipDistanceMESA, this
1684f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * class must behave specially to account for the fact that gl_ClipDistance
1685f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * is converted from a float[8] to a vec4[2].
1686f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
1687f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (ctx->ShaderCompilerOptions[MESA_SHADER_VERTEX].LowerClipDistance &&
1688f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       strcmp(this->var_name, "gl_ClipDistance") == 0) {
1689f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      this->is_clip_distance_mesa = true;
1690f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1691f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1692f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return true;
1693f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1694f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1695f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1696f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
1697f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Determine whether two tfeedback_decl objects refer to the same variable and
1698f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * array index (if applicable).
1699f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
1700f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool
1701f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgtfeedback_decl::is_same(const tfeedback_decl &x, const tfeedback_decl &y)
1702f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1703f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert(x.is_varying() && y.is_varying());
1704f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1705f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (strcmp(x.var_name, y.var_name) != 0)
1706f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return false;
1707f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (x.is_subscripted != y.is_subscripted)
1708f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return false;
1709f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (x.is_subscripted && x.array_subscript != y.array_subscript)
1710f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return false;
1711f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return true;
1712f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1713f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1714f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1715f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
1716f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Assign a location for this tfeedback_decl object based on the location
1717f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * assignment in output_var.
1718f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
1719f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * If an error occurs, the error is reported through linker_error() and false
1720f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * is returned.
1721f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
1722f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool
1723f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgtfeedback_decl::assign_location(struct gl_context *ctx,
1724f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                struct gl_shader_program *prog,
1725f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                ir_variable *output_var)
1726f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1727f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert(this->is_varying());
1728f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1729f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (output_var->type->is_array()) {
1730f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* Array variable */
1731f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      const unsigned matrix_cols =
1732f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         output_var->type->fields.array->matrix_columns;
1733f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      unsigned actual_array_size = this->is_clip_distance_mesa ?
1734f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         prog->Vert.ClipDistanceArraySize : output_var->type->array_size();
1735f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1736f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (this->is_subscripted) {
1737f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         /* Check array bounds. */
1738f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (this->array_subscript >= actual_array_size) {
1739f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            linker_error(prog, "Transform feedback varying %s has index "
1740f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                         "%i, but the array size is %u.",
1741f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                         this->orig_name, this->array_subscript,
1742f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                         actual_array_size);
1743f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            return false;
1744f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
1745f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (this->is_clip_distance_mesa) {
1746f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            this->location =
1747f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               output_var->location + this->array_subscript / 4;
1748f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         } else {
1749f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            this->location =
1750f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               output_var->location + this->array_subscript * matrix_cols;
1751f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
1752f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         this->size = 1;
1753f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else {
1754f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         this->location = output_var->location;
1755f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         this->size = actual_array_size;
1756f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1757f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      this->vector_elements = output_var->type->fields.array->vector_elements;
1758f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      this->matrix_columns = matrix_cols;
1759f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (this->is_clip_distance_mesa)
1760f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         this->type = GL_FLOAT;
1761f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      else
1762f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         this->type = output_var->type->fields.array->gl_type;
1763f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   } else {
1764f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* Regular variable (scalar, vector, or matrix) */
1765f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (this->is_subscripted) {
1766f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         linker_error(prog, "Transform feedback varying %s requested, "
1767f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                      "but %s is not an array.",
1768f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                      this->orig_name, this->var_name);
1769f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return false;
1770f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1771f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      this->location = output_var->location;
1772f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      this->size = 1;
1773f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      this->vector_elements = output_var->type->vector_elements;
1774f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      this->matrix_columns = output_var->type->matrix_columns;
1775f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      this->type = output_var->type->gl_type;
1776f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1777f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1778f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* From GL_EXT_transform_feedback:
1779f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *   A program will fail to link if:
1780f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *
1781f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *   * the total number of components to capture in any varying
1782f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *     variable in <varyings> is greater than the constant
1783f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *     MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT and the
1784f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *     buffer mode is SEPARATE_ATTRIBS_EXT;
1785f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
1786f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (prog->TransformFeedback.BufferMode == GL_SEPARATE_ATTRIBS &&
1787f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       this->num_components() >
1788f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       ctx->Const.MaxTransformFeedbackSeparateComponents) {
1789f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      linker_error(prog, "Transform feedback varying %s exceeds "
1790f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                   "MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS.",
1791f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                   this->orig_name);
1792f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return false;
1793f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1794f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1795f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return true;
1796f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1797f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1798f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1799f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool
1800f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgtfeedback_decl::accumulate_num_outputs(struct gl_shader_program *prog,
1801f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                       unsigned *count)
1802f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1803f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!this->is_varying()) {
1804f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return true;
1805f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1806f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1807f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!this->is_assigned()) {
1808f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* From GL_EXT_transform_feedback:
1809f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       *   A program will fail to link if:
1810f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       *
1811f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       *   * any variable name specified in the <varyings> array is not
1812f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       *     declared as an output in the geometry shader (if present) or
1813f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       *     the vertex shader (if no geometry shader is present);
1814f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       */
1815f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      linker_error(prog, "Transform feedback varying %s undeclared.",
1816f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                   this->orig_name);
1817f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return false;
1818f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1819f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1820f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned translated_size = this->size;
1821f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (this->is_clip_distance_mesa)
1822f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      translated_size = (translated_size + 3) / 4;
1823f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1824f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   *count += translated_size * this->matrix_columns;
1825f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1826f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return true;
1827f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1828f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1829f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1830f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
1831f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Update gl_transform_feedback_info to reflect this tfeedback_decl.
1832f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
1833f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * If an error occurs, the error is reported through linker_error() and false
1834f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * is returned.
1835f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
1836f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool
1837f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgtfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog,
1838f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                      struct gl_transform_feedback_info *info,
1839f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                      unsigned buffer, const unsigned max_outputs) const
1840f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1841f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert(!this->next_buffer_separator);
1842f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1843f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Handle gl_SkipComponents. */
1844f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (this->skip_components) {
1845f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      info->BufferStride[buffer] += this->skip_components;
1846f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return true;
1847f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1848f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1849f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* From GL_EXT_transform_feedback:
1850f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *   A program will fail to link if:
1851f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *
1852f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *     * the total number of components to capture is greater than
1853f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *       the constant MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT
1854f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *       and the buffer mode is INTERLEAVED_ATTRIBS_EXT.
1855f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
1856f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (prog->TransformFeedback.BufferMode == GL_INTERLEAVED_ATTRIBS &&
1857f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       info->BufferStride[buffer] + this->num_components() >
1858f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       ctx->Const.MaxTransformFeedbackInterleavedComponents) {
1859f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      linker_error(prog, "The MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS "
1860f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                   "limit has been exceeded.");
1861f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return false;
1862f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1863f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1864f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned translated_size = this->size;
1865f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (this->is_clip_distance_mesa)
1866f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      translated_size = (translated_size + 3) / 4;
1867f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned components_so_far = 0;
1868f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (unsigned index = 0; index < translated_size; ++index) {
1869f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (unsigned v = 0; v < this->matrix_columns; ++v) {
1870f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         unsigned num_components = this->vector_elements;
1871f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         assert(info->NumOutputs < max_outputs);
1872f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         info->Outputs[info->NumOutputs].ComponentOffset = 0;
1873f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (this->is_clip_distance_mesa) {
1874f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            if (this->is_subscripted) {
1875f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               num_components = 1;
1876f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               info->Outputs[info->NumOutputs].ComponentOffset =
1877f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                  this->array_subscript % 4;
1878f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            } else {
1879f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               num_components = MIN2(4, this->size - components_so_far);
1880f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            }
1881f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
1882f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         info->Outputs[info->NumOutputs].OutputRegister =
1883f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            this->location + v + index * this->matrix_columns;
1884f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         info->Outputs[info->NumOutputs].NumComponents = num_components;
1885f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         info->Outputs[info->NumOutputs].OutputBuffer = buffer;
1886f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         info->Outputs[info->NumOutputs].DstOffset = info->BufferStride[buffer];
1887f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         ++info->NumOutputs;
1888f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         info->BufferStride[buffer] += num_components;
1889f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         components_so_far += num_components;
1890f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1891f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1892f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert(components_so_far == this->num_components());
1893f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1894f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   info->Varyings[info->NumVarying].Name = ralloc_strdup(prog, this->orig_name);
1895f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   info->Varyings[info->NumVarying].Type = this->type;
1896f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   info->Varyings[info->NumVarying].Size = this->size;
1897f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   info->NumVarying++;
1898f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1899f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return true;
1900f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1901f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1902f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1903f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
1904f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Parse all the transform feedback declarations that were passed to
1905f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * glTransformFeedbackVaryings() and store them in tfeedback_decl objects.
1906f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
1907f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * If an error occurs, the error is reported through linker_error() and false
1908f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * is returned.
1909f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
1910f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic bool
1911f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgparse_tfeedback_decls(struct gl_context *ctx, struct gl_shader_program *prog,
1912f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                      const void *mem_ctx, unsigned num_names,
1913f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                      char **varying_names, tfeedback_decl *decls)
1914f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1915f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (unsigned i = 0; i < num_names; ++i) {
1916f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!decls[i].init(ctx, prog, mem_ctx, varying_names[i]))
1917f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return false;
1918f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1919f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!decls[i].is_varying())
1920f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         continue;
1921f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1922f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* From GL_EXT_transform_feedback:
1923f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       *   A program will fail to link if:
1924f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       *
1925f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       *   * any two entries in the <varyings> array specify the same varying
1926f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       *     variable;
1927f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       *
1928f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * We interpret this to mean "any two entries in the <varyings> array
1929f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * specify the same varying variable and array index", since transform
1930f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * feedback of arrays would be useless otherwise.
1931f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       */
1932f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (unsigned j = 0; j < i; ++j) {
1933f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (!decls[j].is_varying())
1934f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            continue;
1935f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1936f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (tfeedback_decl::is_same(decls[i], decls[j])) {
1937f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            linker_error(prog, "Transform feedback varying %s specified "
1938f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                         "more than once.", varying_names[i]);
1939f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            return false;
1940f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
1941f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
1942f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1943f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return true;
1944f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
1945f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1946f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1947f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
1948f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Assign a location for a variable that is produced in one pipeline stage
1949f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * (the "producer") and consumed in the next stage (the "consumer").
1950f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
1951f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param input_var is the input variable declaration in the consumer.
1952f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
1953f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param output_var is the output variable declaration in the producer.
1954f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
1955f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param input_index is the counter that keeps track of assigned input
1956f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *        locations in the consumer.
1957f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
1958f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param output_index is the counter that keeps track of assigned output
1959f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *        locations in the producer.
1960f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
1961f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * It is permissible for \c input_var to be NULL (this happens if a variable
1962f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * is output by the producer and consumed by transform feedback, but not
1963f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * consumed by the consumer).
1964f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
1965f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * If the variable has already been assigned a location, this function has no
1966f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * effect.
1967f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
1968f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
1969f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgassign_varying_location(ir_variable *input_var, ir_variable *output_var,
1970f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                        unsigned *input_index, unsigned *output_index)
1971f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
1972f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (output_var->location != -1) {
1973f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* Location already assigned. */
1974f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return;
1975f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1976f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1977f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (input_var) {
1978f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      assert(input_var->location == -1);
1979f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      input_var->location = *input_index;
1980f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1981f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1982f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   output_var->location = *output_index;
1983f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1984f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* FINISHME: Support for "varying" records in GLSL 1.50. */
1985f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert(!output_var->type->is_record());
1986f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1987f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (output_var->type->is_array()) {
1988f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      const unsigned slots = output_var->type->length
1989f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         * output_var->type->fields.array->matrix_columns;
1990f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1991f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      *output_index += slots;
1992f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      *input_index += slots;
1993f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   } else {
1994f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      const unsigned slots = output_var->type->matrix_columns;
1995f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
1996f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      *output_index += slots;
1997f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      *input_index += slots;
1998f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
1999f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
2000f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2001f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2002f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
2003f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Is the given variable a varying variable to be counted against the
2004f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * limit in ctx->Const.MaxVarying?
2005f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * This includes variables such as texcoords, colors and generic
2006f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * varyings, but excludes variables such as gl_FrontFacing and gl_FragCoord.
2007f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
2008f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic bool
2009f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgis_varying_var(GLenum shaderType, const ir_variable *var)
2010f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
2011f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Only fragment shaders will take a varying variable as an input */
2012f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (shaderType == GL_FRAGMENT_SHADER &&
2013f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       var->mode == ir_var_in &&
2014f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       var->explicit_location) {
2015f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      switch (var->location) {
2016f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case FRAG_ATTRIB_WPOS:
2017f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case FRAG_ATTRIB_FACE:
2018f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case FRAG_ATTRIB_PNTC:
2019f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return false;
2020f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      default:
2021f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return true;
2022f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
2023f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
2024f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return false;
2025f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
2026f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2027f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2028f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
2029f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Assign locations for all variables that are produced in one pipeline stage
2030f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * (the "producer") and consumed in the next stage (the "consumer").
2031f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
2032f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Variables produced by the producer may also be consumed by transform
2033f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * feedback.
2034f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
2035f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param num_tfeedback_decls is the number of declarations indicating
2036f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *        variables that may be consumed by transform feedback.
2037f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
2038f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * \param tfeedback_decls is a pointer to an array of tfeedback_decl objects
2039f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *        representing the result of parsing the strings passed to
2040f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *        glTransformFeedbackVaryings().  assign_location() will be called for
2041f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *        each of these objects that matches one of the outputs of the
2042f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *        producer.
2043f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
2044f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * When num_tfeedback_decls is nonzero, it is permissible for the consumer to
2045f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * be NULL.  In this case, varying locations are assigned solely based on the
2046f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * requirements of transform feedback.
2047f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
2048f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgbool
2049f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgassign_varying_locations(struct gl_context *ctx,
2050f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 struct gl_shader_program *prog,
2051f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			 gl_shader *producer, gl_shader *consumer,
2052f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                         unsigned num_tfeedback_decls,
2053f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                         tfeedback_decl *tfeedback_decls)
2054f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
2055f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* FINISHME: Set dynamically when geometry shader support is added. */
2056f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned output_index = VERT_RESULT_VAR0;
2057f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned input_index = FRAG_ATTRIB_VAR0;
2058f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2059f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Operate in a total of three passes.
2060f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *
2061f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * 1. Assign locations for any matching inputs and outputs.
2062f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *
2063f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * 2. Mark output variables in the producer that do not have locations as
2064f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *    not being outputs.  This lets the optimizer eliminate them.
2065f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *
2066f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * 3. Mark input variables in the consumer that do not have locations as
2067f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *    not being inputs.  This lets the optimizer eliminate them.
2068f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
2069f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2070f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   link_invalidate_variable_locations(producer, ir_var_out, VERT_RESULT_VAR0);
2071f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (consumer)
2072f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      link_invalidate_variable_locations(consumer, ir_var_in, FRAG_ATTRIB_VAR0);
2073f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2074f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   foreach_list(node, producer->ir) {
2075f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_variable *const output_var = ((ir_instruction *) node)->as_variable();
2076f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2077f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if ((output_var == NULL) || (output_var->mode != ir_var_out))
2078f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 continue;
2079f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2080f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_variable *input_var =
2081f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 consumer ? consumer->symbols->get_variable(output_var->name) : NULL;
2082f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2083f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (input_var && input_var->mode != ir_var_in)
2084f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         input_var = NULL;
2085f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2086f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (input_var) {
2087f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         assign_varying_location(input_var, output_var, &input_index,
2088f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                 &output_index);
2089f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
2090f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2091f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
2092f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (!tfeedback_decls[i].is_varying())
2093f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            continue;
2094f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2095f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (!tfeedback_decls[i].is_assigned() &&
2096f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             tfeedback_decls[i].matches_var(output_var)) {
2097f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            if (output_var->location == -1) {
2098f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               assign_varying_location(input_var, output_var, &input_index,
2099f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                       &output_index);
2100f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            }
2101f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            if (!tfeedback_decls[i].assign_location(ctx, prog, output_var))
2102f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               return false;
2103f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
2104f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
2105f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
2106f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2107f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned varying_vectors = 0;
2108f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2109f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (consumer) {
2110f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      foreach_list(node, consumer->ir) {
2111f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         ir_variable *const var = ((ir_instruction *) node)->as_variable();
2112f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2113f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if ((var == NULL) || (var->mode != ir_var_in))
2114f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            continue;
2115f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2116f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (var->location == -1) {
2117f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            if (prog->Version <= 120) {
2118f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               /* On page 25 (page 31 of the PDF) of the GLSL 1.20 spec:
2119f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                *
2120f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                *     Only those varying variables used (i.e. read) in
2121f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                *     the fragment shader executable must be written to
2122f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                *     by the vertex shader executable; declaring
2123f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                *     superfluous varying variables in a vertex shader is
2124f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                *     permissible.
2125f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                *
2126f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                * We interpret this text as meaning that the VS must
2127f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                * write the variable for the FS to read it.  See
2128f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                * "glsl1-varying read but not written" in piglit.
2129f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                */
2130f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2131f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org               linker_error(prog, "fragment shader varying %s not written "
2132f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                            "by vertex shader\n.", var->name);
2133f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            }
2134f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2135f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            /* An 'in' variable is only really a shader input if its
2136f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             * value is written by the previous stage.
2137f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             */
2138f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            var->mode = ir_var_auto;
2139f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         } else if (is_varying_var(consumer->Type, var)) {
2140f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            /* The packing rules are used for vertex shader inputs are also
2141f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             * used for fragment shader inputs.
2142f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             */
2143f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            varying_vectors += count_attribute_slots(var->type);
2144f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
2145f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
2146f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
2147f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2148f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (ctx->API == API_OPENGLES2 || prog->Version == 100) {
2149f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (varying_vectors > ctx->Const.MaxVarying) {
2150f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (ctx->Const.GLSLSkipStrictMaxVaryingLimitCheck) {
2151f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            linker_warning(prog, "shader uses too many varying vectors "
2152f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           "(%u > %u), but the driver will try to optimize "
2153f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           "them out; this is non-portable out-of-spec "
2154f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           "behavior\n",
2155f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           varying_vectors, ctx->Const.MaxVarying);
2156f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         } else {
2157f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            linker_error(prog, "shader uses too many varying vectors "
2158f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                         "(%u > %u)\n",
2159f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                         varying_vectors, ctx->Const.MaxVarying);
2160f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            return false;
2161f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
2162f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
2163f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   } else {
2164f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      const unsigned float_components = varying_vectors * 4;
2165f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (float_components > ctx->Const.MaxVarying * 4) {
2166f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (ctx->Const.GLSLSkipStrictMaxVaryingLimitCheck) {
2167f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            linker_warning(prog, "shader uses too many varying components "
2168f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           "(%u > %u), but the driver will try to optimize "
2169f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           "them out; this is non-portable out-of-spec "
2170f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           "behavior\n",
2171f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           float_components, ctx->Const.MaxVarying * 4);
2172f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         } else {
2173f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            linker_error(prog, "shader uses too many varying components "
2174f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                         "(%u > %u)\n",
2175f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                         float_components, ctx->Const.MaxVarying * 4);
2176f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            return false;
2177f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
2178f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
2179f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
2180f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2181f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return true;
2182f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
2183f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2184f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2185f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
2186f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Store transform feedback location assignments into
2187f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * prog->LinkedTransformFeedback based on the data stored in tfeedback_decls.
2188f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org *
2189f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * If an error occurs, the error is reported through linker_error() and false
2190f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * is returned.
2191f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
2192f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic bool
2193f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstore_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog,
2194f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     unsigned num_tfeedback_decls,
2195f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                     tfeedback_decl *tfeedback_decls)
2196f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
2197f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   bool separate_attribs_mode =
2198f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      prog->TransformFeedback.BufferMode == GL_SEPARATE_ATTRIBS;
2199f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2200f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ralloc_free(prog->LinkedTransformFeedback.Varyings);
2201f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ralloc_free(prog->LinkedTransformFeedback.Outputs);
2202f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2203f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   memset(&prog->LinkedTransformFeedback, 0,
2204f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org          sizeof(prog->LinkedTransformFeedback));
2205f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2206f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   prog->LinkedTransformFeedback.Varyings =
2207f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      rzalloc_array(prog,
2208f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		    struct gl_transform_feedback_varying_info,
2209f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		    num_tfeedback_decls);
2210f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2211f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned num_outputs = 0;
2212f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (unsigned i = 0; i < num_tfeedback_decls; ++i)
2213f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!tfeedback_decls[i].accumulate_num_outputs(prog, &num_outputs))
2214f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         return false;
2215f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2216f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   prog->LinkedTransformFeedback.Outputs =
2217f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      rzalloc_array(prog,
2218f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    struct gl_transform_feedback_output,
2219f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                    num_outputs);
2220f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2221f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned num_buffers = 0;
2222f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2223f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (separate_attribs_mode) {
2224f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* GL_SEPARATE_ATTRIBS */
2225f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
2226f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (!tfeedback_decls[i].store(ctx, prog, &prog->LinkedTransformFeedback,
2227f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                       num_buffers, num_outputs))
2228f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            return false;
2229f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2230f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         num_buffers++;
2231f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
2232f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
2233f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   else {
2234f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* GL_INVERLEAVED_ATTRIBS */
2235f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
2236f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (tfeedback_decls[i].is_next_buffer_separator()) {
2237f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            num_buffers++;
2238f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            continue;
2239f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
2240f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2241f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (!tfeedback_decls[i].store(ctx, prog,
2242f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                       &prog->LinkedTransformFeedback,
2243f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                       num_buffers, num_outputs))
2244f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            return false;
2245f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
2246f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      num_buffers++;
2247f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
2248f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2249f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert(prog->LinkedTransformFeedback.NumOutputs == num_outputs);
2250f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2251f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   prog->LinkedTransformFeedback.NumBuffers = num_buffers;
2252f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return true;
2253f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
2254f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2255f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
2256f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Store the gl_FragDepth layout in the gl_shader_program struct.
2257f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
2258f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic void
2259f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstore_fragdepth_layout(struct gl_shader_program *prog)
2260f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
2261f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL) {
2262f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      return;
2263f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
2264f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2265f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct exec_list *ir = prog->_LinkedShaders[MESA_SHADER_FRAGMENT]->ir;
2266f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2267f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* We don't look up the gl_FragDepth symbol directly because if
2268f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * gl_FragDepth is not used in the shader, it's removed from the IR.
2269f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * However, the symbol won't be removed from the symbol table.
2270f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    *
2271f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * We're only interested in the cases where the variable is NOT removed
2272f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * from the IR.
2273f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
2274f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   foreach_list(node, ir) {
2275f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ir_variable *const var = ((ir_instruction *) node)->as_variable();
2276f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2277f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (var == NULL || var->mode != ir_var_out) {
2278f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         continue;
2279f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
2280f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2281f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (strcmp(var->name, "gl_FragDepth") == 0) {
2282f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         switch (var->depth_layout) {
2283f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         case ir_depth_layout_none:
2284f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            prog->FragDepthLayout = FRAG_DEPTH_LAYOUT_NONE;
2285f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            return;
2286f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         case ir_depth_layout_any:
2287f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            prog->FragDepthLayout = FRAG_DEPTH_LAYOUT_ANY;
2288f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            return;
2289f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         case ir_depth_layout_greater:
2290f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            prog->FragDepthLayout = FRAG_DEPTH_LAYOUT_GREATER;
2291f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            return;
2292f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         case ir_depth_layout_less:
2293f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            prog->FragDepthLayout = FRAG_DEPTH_LAYOUT_LESS;
2294f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            return;
2295f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         case ir_depth_layout_unchanged:
2296f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            prog->FragDepthLayout = FRAG_DEPTH_LAYOUT_UNCHANGED;
2297f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            return;
2298f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         default:
2299f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            assert(0);
2300f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            return;
2301f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
2302f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
2303f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
2304f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
2305f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2306f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org/**
2307f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org * Validate the resources used by a program versus the implementation limits
2308f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org */
2309f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgstatic bool
2310f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgcheck_resources(struct gl_context *ctx, struct gl_shader_program *prog)
2311f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
2312f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   static const char *const shader_names[MESA_SHADER_TYPES] = {
2313f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      "vertex", "fragment", "geometry"
2314f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   };
2315f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2316f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const unsigned max_samplers[MESA_SHADER_TYPES] = {
2317f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ctx->Const.MaxVertexTextureImageUnits,
2318f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ctx->Const.MaxTextureImageUnits,
2319f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ctx->Const.MaxGeometryTextureImageUnits
2320f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   };
2321f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2322f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const unsigned max_uniform_components[MESA_SHADER_TYPES] = {
2323f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ctx->Const.VertexProgram.MaxUniformComponents,
2324f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ctx->Const.FragmentProgram.MaxUniformComponents,
2325f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      0          /* FINISHME: Geometry shaders. */
2326f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   };
2327f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2328f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   const unsigned max_uniform_blocks[MESA_SHADER_TYPES] = {
2329f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ctx->Const.VertexProgram.MaxUniformBlocks,
2330f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ctx->Const.FragmentProgram.MaxUniformBlocks,
2331f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ctx->Const.GeometryProgram.MaxUniformBlocks,
2332f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   };
2333f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2334f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
2335f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      struct gl_shader *sh = prog->_LinkedShaders[i];
2336f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2337f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (sh == NULL)
2338f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 continue;
2339f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2340f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (sh->num_samplers > max_samplers[i]) {
2341f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 linker_error(prog, "Too many %s shader texture samplers",
2342f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		      shader_names[i]);
2343f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
2344f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2345f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (sh->num_uniform_components > max_uniform_components[i]) {
2346f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         if (ctx->Const.GLSLSkipStrictMaxUniformLimitCheck) {
2347f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            linker_warning(prog, "Too many %s shader uniform components, "
2348f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           "but the driver will try to optimize them out; "
2349f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           "this is non-portable out-of-spec behavior\n",
2350f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                           shader_names[i]);
2351f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         } else {
2352f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org            linker_error(prog, "Too many %s shader uniform components",
2353f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                         shader_names[i]);
2354f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         }
2355f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
2356f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
2357f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2358f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned blocks[MESA_SHADER_TYPES] = {0};
2359f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned total_uniform_blocks = 0;
2360f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2361f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (unsigned i = 0; i < prog->NumUniformBlocks; i++) {
2362f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (unsigned j = 0; j < MESA_SHADER_TYPES; j++) {
2363f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (prog->UniformBlockStageIndex[j][i] != -1) {
2364f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    blocks[j]++;
2365f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    total_uniform_blocks++;
2366f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 }
2367f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
2368f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2369f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (total_uniform_blocks > ctx->Const.MaxCombinedUniformBlocks) {
2370f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 linker_error(prog, "Too many combined uniform blocks (%d/%d)",
2371f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		      prog->NumUniformBlocks,
2372f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		      ctx->Const.MaxCombinedUniformBlocks);
2373f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else {
2374f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
2375f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    if (blocks[i] > max_uniform_blocks[i]) {
2376f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       linker_error(prog, "Too many %s uniform blocks (%d/%d)",
2377f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			    shader_names[i],
2378f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			    blocks[i],
2379f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			    max_uniform_blocks[i]);
2380f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	       break;
2381f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    }
2382f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 }
2383f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
2384f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
2385f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2386f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   return prog->LinkStatus;
2387f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
2388f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2389f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgvoid
2390f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orglink_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
2391f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org{
2392f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   tfeedback_decl *tfeedback_decls = NULL;
2393f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned num_tfeedback_decls = prog->TransformFeedback.NumVarying;
2394f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2395f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   void *mem_ctx = ralloc_context(NULL); // temporary linker context
2396f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2397f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   prog->LinkStatus = false;
2398f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   prog->Validated = false;
2399f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   prog->_Used = false;
2400f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2401f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ralloc_free(prog->InfoLog);
2402f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   prog->InfoLog = ralloc_strdup(NULL, "");
2403f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2404f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ralloc_free(prog->UniformBlocks);
2405f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   prog->UniformBlocks = NULL;
2406f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   prog->NumUniformBlocks = 0;
2407f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (int i = 0; i < MESA_SHADER_TYPES; i++) {
2408f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      ralloc_free(prog->UniformBlockStageIndex[i]);
2409f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      prog->UniformBlockStageIndex[i] = NULL;
2410f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
2411f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2412f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Separate the shaders into groups based on their type.
2413f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
2414f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_shader **vert_shader_list;
2415f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned num_vert_shaders = 0;
2416f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   struct gl_shader **frag_shader_list;
2417f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned num_frag_shaders = 0;
2418f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2419f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   vert_shader_list = (struct gl_shader **)
2420f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      calloc(2 * prog->NumShaders, sizeof(struct gl_shader *));
2421f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   frag_shader_list =  &vert_shader_list[prog->NumShaders];
2422f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2423f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned min_version = UINT_MAX;
2424f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned max_version = 0;
2425f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (unsigned i = 0; i < prog->NumShaders; i++) {
2426f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      min_version = MIN2(min_version, prog->Shaders[i]->Version);
2427f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      max_version = MAX2(max_version, prog->Shaders[i]->Version);
2428f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2429f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      switch (prog->Shaders[i]->Type) {
2430f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case GL_VERTEX_SHADER:
2431f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 vert_shader_list[num_vert_shaders] = prog->Shaders[i];
2432f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 num_vert_shaders++;
2433f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 break;
2434f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case GL_FRAGMENT_SHADER:
2435f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 frag_shader_list[num_frag_shaders] = prog->Shaders[i];
2436f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 num_frag_shaders++;
2437f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 break;
2438f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      case GL_GEOMETRY_SHADER:
2439f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 /* FINISHME: Support geometry shaders. */
2440f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 assert(prog->Shaders[i]->Type != GL_GEOMETRY_SHADER);
2441f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 break;
2442f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
2443f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
2444f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2445f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Previous to GLSL version 1.30, different compilation units could mix and
2446f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * match shading language versions.  With GLSL 1.30 and later, the versions
2447f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * of all shaders must match.
2448f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
2449f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert(min_version >= 100);
2450f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   assert(max_version <= 140);
2451f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if ((max_version >= 130 || min_version == 100)
2452f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       && min_version != max_version) {
2453f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      linker_error(prog, "all shaders must use same shading "
2454f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org		   "language version\n");
2455f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      goto done;
2456f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
2457f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2458f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   prog->Version = max_version;
2459f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2460f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (unsigned int i = 0; i < MESA_SHADER_TYPES; i++) {
2461f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (prog->_LinkedShaders[i] != NULL)
2462f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ctx->Driver.DeleteShader(ctx, prog->_LinkedShaders[i]);
2463f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2464f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      prog->_LinkedShaders[i] = NULL;
2465f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
2466f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2467f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Link all shaders for a particular stage and validate the result.
2468f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
2469f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (num_vert_shaders > 0) {
2470f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      gl_shader *const sh =
2471f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 link_intrastage_shaders(mem_ctx, ctx, prog, vert_shader_list,
2472f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 num_vert_shaders);
2473f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2474f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (sh == NULL)
2475f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 goto done;
2476f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2477f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!validate_vertex_shader_executable(prog, sh))
2478f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 goto done;
2479f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2480f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _mesa_reference_shader(ctx, &prog->_LinkedShaders[MESA_SHADER_VERTEX],
2481f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			     sh);
2482f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
2483f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2484f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (num_frag_shaders > 0) {
2485f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      gl_shader *const sh =
2486f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 link_intrastage_shaders(mem_ctx, ctx, prog, frag_shader_list,
2487f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				 num_frag_shaders);
2488f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2489f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (sh == NULL)
2490f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 goto done;
2491f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2492f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!validate_fragment_shader_executable(prog, sh))
2493f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 goto done;
2494f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2495f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      _mesa_reference_shader(ctx, &prog->_LinkedShaders[MESA_SHADER_FRAGMENT],
2496f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org			     sh);
2497f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
2498f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2499f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Here begins the inter-stage linking phase.  Some initial validation is
2500f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * performed, then locations are assigned for uniforms, attributes, and
2501f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * varyings.
2502f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
2503f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (cross_validate_uniforms(prog)) {
2504f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      unsigned prev;
2505f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2506f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (prev = 0; prev < MESA_SHADER_TYPES; prev++) {
2507f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (prog->_LinkedShaders[prev] != NULL)
2508f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    break;
2509f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
2510f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2511f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* Validate the inputs of each stage with the output of the preceding
2512f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * stage.
2513f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       */
2514f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      for (unsigned i = prev + 1; i < MESA_SHADER_TYPES; i++) {
2515f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (prog->_LinkedShaders[i] == NULL)
2516f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    continue;
2517f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2518f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 if (!cross_validate_outputs_to_inputs(prog,
2519f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					       prog->_LinkedShaders[prev],
2520f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org					       prog->_LinkedShaders[i]))
2521f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	    goto done;
2522f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2523f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 prev = i;
2524f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
2525f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2526f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      prog->LinkStatus = true;
2527f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
2528f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2529f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Implement the GLSL 1.30+ rule for discard vs infinite loops Do
2530f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * it before optimization because we want most of the checks to get
2531f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * dropped thanks to constant propagation.
2532f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
2533f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (max_version >= 130) {
2534f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      struct gl_shader *sh = prog->_LinkedShaders[MESA_SHADER_FRAGMENT];
2535f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (sh) {
2536f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 lower_discard_flow(sh->ir);
2537f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
2538f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
2539f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2540f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!interstage_cross_validate_uniform_blocks(prog))
2541f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      goto done;
2542f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2543f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* Do common optimization before assigning storage for attributes,
2544f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * uniforms, and varyings.  Later optimization could possibly make
2545f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * some of that unused.
2546f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
2547f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
2548f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (prog->_LinkedShaders[i] == NULL)
2549f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 continue;
2550f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2551f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      detect_recursion_linked(prog, prog->_LinkedShaders[i]->ir);
2552f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!prog->LinkStatus)
2553f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 goto done;
2554f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2555f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (ctx->ShaderCompilerOptions[i].LowerClipDistance)
2556f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         lower_clip_distance(prog->_LinkedShaders[i]->ir);
2557f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2558f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      unsigned max_unroll = ctx->ShaderCompilerOptions[i].MaxUnrollIterations;
2559f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2560f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      while (do_common_optimization(prog->_LinkedShaders[i]->ir, true, false, max_unroll))
2561f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ;
2562f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
2563f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2564f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* FINISHME: The value of the max_attribute_index parameter is
2565f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * FINISHME: implementation dependent based on the value of
2566f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * FINISHME: GL_MAX_VERTEX_ATTRIBS.  GL_MAX_VERTEX_ATTRIBS must be
2567f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * FINISHME: at least 16, so hardcode 16 for now.
2568f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
2569f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!assign_attribute_or_color_locations(prog, MESA_SHADER_VERTEX, 16)) {
2570f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      goto done;
2571f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
2572f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2573f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!assign_attribute_or_color_locations(prog, MESA_SHADER_FRAGMENT, MAX2(ctx->Const.MaxDrawBuffers, ctx->Const.MaxDualSourceDrawBuffers))) {
2574f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      goto done;
2575f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
2576f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2577f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   unsigned prev;
2578f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (prev = 0; prev < MESA_SHADER_TYPES; prev++) {
2579f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (prog->_LinkedShaders[prev] != NULL)
2580f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 break;
2581f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
2582f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2583f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (num_tfeedback_decls != 0) {
2584f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* From GL_EXT_transform_feedback:
2585f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       *   A program will fail to link if:
2586f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       *
2587f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       *   * the <count> specified by TransformFeedbackVaryingsEXT is
2588f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       *     non-zero, but the program object has no vertex or geometry
2589f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       *     shader;
2590f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       */
2591f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (prev >= MESA_SHADER_FRAGMENT) {
2592f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         linker_error(prog, "Transform feedback varyings specified, but "
2593f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                      "no vertex or geometry shader is present.");
2594f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         goto done;
2595f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
2596f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2597f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      tfeedback_decls = ralloc_array(mem_ctx, tfeedback_decl,
2598f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                     prog->TransformFeedback.NumVarying);
2599f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!parse_tfeedback_decls(ctx, prog, mem_ctx, num_tfeedback_decls,
2600f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                 prog->TransformFeedback.VaryingNames,
2601f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org                                 tfeedback_decls))
2602f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         goto done;
2603f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
2604f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2605f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (unsigned i = prev + 1; i < MESA_SHADER_TYPES; i++) {
2606f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (prog->_LinkedShaders[i] == NULL)
2607f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 continue;
2608f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2609f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!assign_varying_locations(
2610f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             ctx, prog, prog->_LinkedShaders[prev], prog->_LinkedShaders[i],
2611f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             i == MESA_SHADER_FRAGMENT ? num_tfeedback_decls : 0,
2612f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             tfeedback_decls))
2613f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 goto done;
2614f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2615f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      prev = i;
2616f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
2617f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2618f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (prev != MESA_SHADER_FRAGMENT && num_tfeedback_decls != 0) {
2619f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* There was no fragment shader, but we still have to assign varying
2620f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * locations for use by transform feedback.
2621f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       */
2622f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (!assign_varying_locations(
2623f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             ctx, prog, prog->_LinkedShaders[prev], NULL, num_tfeedback_decls,
2624f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org             tfeedback_decls))
2625f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org         goto done;
2626f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
2627f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2628f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!store_tfeedback_info(ctx, prog, num_tfeedback_decls, tfeedback_decls))
2629f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      goto done;
2630f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2631f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (prog->_LinkedShaders[MESA_SHADER_VERTEX] != NULL) {
2632f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      demote_shader_inputs_and_outputs(prog->_LinkedShaders[MESA_SHADER_VERTEX],
2633f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org				       ir_var_out);
2634f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2635f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* Eliminate code that is now dead due to unused vertex outputs being
2636f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * demoted.
2637f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       */
2638f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      while (do_dead_code(prog->_LinkedShaders[MESA_SHADER_VERTEX]->ir, false))
2639f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ;
2640f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
2641f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2642f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (prog->_LinkedShaders[MESA_SHADER_GEOMETRY] != NULL) {
2643f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      gl_shader *const sh = prog->_LinkedShaders[MESA_SHADER_GEOMETRY];
2644f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2645f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      demote_shader_inputs_and_outputs(sh, ir_var_in);
2646f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      demote_shader_inputs_and_outputs(sh, ir_var_inout);
2647f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      demote_shader_inputs_and_outputs(sh, ir_var_out);
2648f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2649f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* Eliminate code that is now dead due to unused geometry outputs being
2650f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * demoted.
2651f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       */
2652f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      while (do_dead_code(prog->_LinkedShaders[MESA_SHADER_GEOMETRY]->ir, false))
2653f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ;
2654f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
2655f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2656f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] != NULL) {
2657f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      gl_shader *const sh = prog->_LinkedShaders[MESA_SHADER_FRAGMENT];
2658f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2659f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      demote_shader_inputs_and_outputs(sh, ir_var_in);
2660f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2661f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* Eliminate code that is now dead due to unused fragment inputs being
2662f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * demoted.  This shouldn't actually do anything other than remove
2663f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * declarations of the (now unused) global variables.
2664f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       */
2665f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      while (do_dead_code(prog->_LinkedShaders[MESA_SHADER_FRAGMENT]->ir, false))
2666f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 ;
2667f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
2668f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2669f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   update_array_sizes(prog);
2670f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   link_assign_uniform_locations(prog);
2671f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   store_fragdepth_layout(prog);
2672f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2673f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!check_resources(ctx, prog))
2674f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      goto done;
2675f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2676f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* OpenGL ES requires that a vertex shader and a fragment shader both be
2677f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * present in a linked program.  By checking for use of shading language
2678f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    * version 1.00, we also catch the GL_ARB_ES2_compatibility case.
2679f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org    */
2680f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   if (!prog->InternalSeparateShader &&
2681f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       (ctx->API == API_OPENGLES2 || prog->Version == 100)) {
2682f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (prog->_LinkedShaders[MESA_SHADER_VERTEX] == NULL) {
2683f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 linker_error(prog, "program lacks a vertex shader\n");
2684f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      } else if (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL) {
2685f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 linker_error(prog, "program lacks a fragment shader\n");
2686f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      }
2687f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
2688f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2689f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   /* FINISHME: Assign fragment shader output locations. */
2690f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2691f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.orgdone:
2692f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   free(vert_shader_list);
2693f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2694f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
2695f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      if (prog->_LinkedShaders[i] == NULL)
2696f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org	 continue;
2697f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2698f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* Retain any live IR, but trash the rest. */
2699f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      reparent_ir(prog->_LinkedShaders[i]->ir, prog->_LinkedShaders[i]->ir);
2700f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2701f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      /* The symbol table in the linked shaders may contain references to
2702f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * variables that were removed (e.g., unused uniforms).  Since it may
2703f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * contain junk, there is no possible valid use.  Delete it and set the
2704f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       * pointer to NULL.
2705f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org       */
2706f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      delete prog->_LinkedShaders[i]->symbols;
2707f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org      prog->_LinkedShaders[i]->symbols = NULL;
2708f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   }
2709f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org
2710f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org   ralloc_free(mem_ctx);
2711f2ba7591b1407a7ee9209f842c50696914dc2dedkbr@chromium.org}
2712